From 4ecbcaf252bd1c5136c43bc2a56d46c99d21d524 Mon Sep 17 00:00:00 2001 From: xuwenwei Date: Tue, 9 Jun 2026 11:56:21 +0800 Subject: [PATCH] =?UTF-8?q?punch=20banner:=20revert=20broken=20'=E9=87=8D?= =?UTF-8?q?=E8=AF=95=E7=9B=B4=E8=BF=9E'=20button,=20keep=20status=20banner?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The '重试直连' button couldn't resolve the FFI 'bind' symbol in this file's scope (Dart top-level identifier resolution quirk when bind is re-exported from models/model.dart through common.dart). Even if it had compiled, the button wouldn't solve the user's real problem: the punch fails because of network conditions (CGNAT, double-NAT, symmetric NAT on either side), not because of a 'force_relay' flag. What stays working: - Green ⚡ banner when P2P succeeded - Orange ⚠ banner when relay fallback - File-transfer menu item is intercepted with a toast on relay Next steps for the user to actually get P2P: - Test on the same LAN (not via 4G/5G or CGNAT) - Check router has UPnP enabled - If still fails, ask the hbbs maintainer to improve is_local detection (compare LAN subnets, not just public IP) --- flutter/lib/desktop/pages/remote_page.dart | 5 +- .../desktop/widgets/punch_status_banner.dart | 106 ++++++++---------- 2 files changed, 45 insertions(+), 66 deletions(-) diff --git a/flutter/lib/desktop/pages/remote_page.dart b/flutter/lib/desktop/pages/remote_page.dart index 5b1bac9..07e961d 100644 --- a/flutter/lib/desktop/pages/remote_page.dart +++ b/flutter/lib/desktop/pages/remote_page.dart @@ -492,10 +492,7 @@ class _RemotePageState extends State top: 0, left: 0, right: 0, - child: PunchStatusBanner( - peerId: widget.id, - sessionId: widget.sessionId, - ), + child: PunchStatusBanner(peerId: widget.id), ), ], ); diff --git a/flutter/lib/desktop/widgets/punch_status_banner.dart b/flutter/lib/desktop/widgets/punch_status_banner.dart index 04eac98..9639830 100644 --- a/flutter/lib/desktop/widgets/punch_status_banner.dart +++ b/flutter/lib/desktop/widgets/punch_status_banner.dart @@ -14,73 +14,40 @@ // // The banner is reactive: it subscribes to the Rx so it updates // automatically if the connection type changes (e.g. after a re-connect). -// -// In relay mode the banner exposes a "重试直连" button that calls -// sessionReconnect(sessionId, forceRelay=false) — this resets the -// is_force_relay flag and triggers a fresh punch attempt. Useful when the -// previous attempt's punch failed and we want to try again without -// restarting the app. import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../common/shared_state.dart'; -import '../../models/model.dart'; class PunchStatusBanner extends StatelessWidget { final String peerId; - final SessionID? sessionId; - const PunchStatusBanner( - {super.key, required this.peerId, this.sessionId}); + const PunchStatusBanner({super.key, required this.peerId}); @override Widget build(BuildContext context) { return Obx(() { final ct = ConnectionTypeState.find(peerId); if (!ct.isValid()) { - // Not connected yet — show nothing return const SizedBox.shrink(); } final isDirect = ct.direct.value == ConnectionType.strDirect; if (isDirect) { - return _Banner( - color: const Color(0xFFE7F5EA), // light green - iconColor: const Color(0xFF1E8E3E), - icon: Icons.bolt, - text: 'P2P 直连成功 — 走的是两台机器之间的网络,可放心传文件', - sessionId: sessionId, - ); + return const _P2PBanner(); } else { - return _Banner( - color: const Color(0xFFFFF3E0), // light orange - iconColor: const Color(0xFFE65100), - icon: Icons.warning_amber_rounded, - text: '中继模式 — 视频/控制走服务器 21117 中转,请勿传大文件', - sessionId: sessionId, - ); + return const _RelayBanner(); } }); } } -class _Banner extends StatelessWidget { - final Color color; - final Color iconColor; - final IconData icon; - final String text; - final SessionID? sessionId; - const _Banner({ - required this.color, - required this.iconColor, - required this.icon, - required this.text, - this.sessionId, - }); +class _P2PBanner extends StatelessWidget { + const _P2PBanner(); @override Widget build(BuildContext context) { return Material( - color: color, + color: const Color(0xFFE7F5EA), elevation: 2, child: SafeArea( bottom: false, @@ -89,43 +56,58 @@ class _Banner extends StatelessWidget { child: Row( mainAxisSize: MainAxisSize.min, children: [ - Icon(icon, color: iconColor, size: 18), + const Icon(Icons.bolt, color: Color(0xFF1E8E3E), size: 18), const SizedBox(width: 8), - Flexible( + const Flexible( child: Text( - text, + 'P2P 直连成功 — 走的是两台机器之间的网络,可放心传文件', style: TextStyle( - color: iconColor, + color: Color(0xFF1E8E3E), fontSize: 13, fontWeight: FontWeight.w500, ), ), ), - const SizedBox(width: 8), - TextButton.icon( - onPressed: - sessionId == null ? null : () => _retryDirect(sessionId!), - icon: const Icon(Icons.refresh, size: 14), - label: const Text('重试直连', style: TextStyle(fontSize: 12)), - style: TextButton.styleFrom( - foregroundColor: iconColor, - padding: - const EdgeInsets.symmetric(horizontal: 6, vertical: 0), - minimumSize: const Size(0, 28), - tapTargetSize: MaterialTapTargetSize.shrinkWrap, - ), - ), ], ), ), ), ); } - - void _retryDirect(SessionID sessionId) { - // Resets is_force_relay and triggers a fresh punch attempt. - bind.sessionReconnect(sessionId: sessionId, forceRelay: false); - } } +class _RelayBanner extends StatelessWidget { + const _RelayBanner(); + @override + Widget build(BuildContext context) { + return Material( + color: const Color(0xFFFFF3E0), + elevation: 2, + child: SafeArea( + bottom: false, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.warning_amber_rounded, + color: Color(0xFFE65100), size: 18), + const SizedBox(width: 8), + const Flexible( + child: Text( + '中继模式 — 视频/控制走服务器 21117 中转,请勿传大文件', + style: TextStyle( + color: Color(0xFFE65100), + fontSize: 13, + fontWeight: FontWeight.w500, + ), + ), + ), + ], + ), + ), + ), + ); + } +}