Plan B for the punch UI: don't just grey out file transfer — hide it
entirely when the connection is relay. The user can't try to use it,
and we save the toast explanation.
When punch succeeds (P2P, direct), the menu items reappear.
Applied to:
- Transfer file
- TCP tunneling
(Leaving View camera and Terminal in the menu regardless of mode —
they don't use server bandwidth significantly.)
Custom fork feature: surface NAT-punch result to the user so they know
whether the connection is going through their 21117 server (relay) or
directly between the two machines (P2P).
Three changes:
1. flutter/lib/common/shared_state.dart: add ConnectionType.isP2P getter
(true = direct, false = relay) and a top-level isDirectConnection(peerId)
helper that returns true when state is unknown (so UI doesn't briefly
grey out before the connection establishes).
2. flutter/lib/desktop/widgets/punch_status_banner.dart (new): a small
Positioned banner at the top of the connection page.
- P2P success: green ⚡ banner: 'P2P 直连成功 — 走的是两台机器之间的网络,可放心传文件'
- Relay fallback: orange ⚠ banner: '中继模式 — 视频/控制走服务器 21117 中转,请勿传大文件'
The banner is reactive (Obx on ConnectionType.direct Rx<String>).
3. flutter/lib/common/widgets/toolbar.dart: wrap the 'Transfer file' and
'TCP tunneling' menu items' onPressed with an isDirectConnection() guard.
On relay mode, the menu still shows but the click is intercepted with a
toast explaining why the action is blocked.
4. flutter/lib/desktop/pages/remote_page.dart: add the banner via
Positioned(top: 0, left: 0, right: 0) at the end of bodyWidget's Stack.
Why this matters: user has 4 users on 5 Mbps server (114.55.133.123).
When NAT punch fails and the session goes through relay, file transfers
would saturate the server bandwidth. Showing the relay state + blocking
the file-transfer menu protects the server without requiring the user
to remember the technical detail.