timeout of webrtc fallback to delay

This commit is contained in:
rustdesk
2026-09-12 13:52:11 +08:00
parent e54f21e10c
commit 3c7c13d79d
58 changed files with 215 additions and 16 deletions

View File

@@ -178,6 +178,7 @@ const String kOptionEnableIpv6Punch = "enable-ipv6-punch";
const String kOptionAllowSyncClipboardBetweenSessions =
"allow-sync-clipboard-between-sessions";
const String kOptionEnableWebrtc = "enable-webrtc";
const String kOptionRelayFallbackDelay = "relay-fallback-delay";
const String kOptionEnableTrustedDevices = "enable-trusted-devices";
const String kOptionShowVirtualMouse = "show-virtual-mouse";
const String kOptionVirtualMouseScale = "virtual-mouse-scale";

View File

@@ -591,13 +591,7 @@ class _GeneralState extends State<_General> {
isServer: false,
),
],
if (!incomingOnly)
_OptionCheckBox(
context,
'Enable WebRTC P2P connection',
kOptionEnableWebrtc,
isServer: false,
),
if (!incomingOnly) ...webrtcOptions(context),
if (!isWeb && !incomingOnly)
Tooltip(
message: translate('sync-clipboard-between-sessions-tip'),
@@ -887,6 +881,85 @@ class _GeneralState extends State<_General> {
).marginOnly(left: _kContentHMargin);
});
}
// How long an already-connected relay is held back to give the direct WebRTC
// attempt a chance to win. It only means anything while WebRTC is on, so it
// follows the checkbox as an indented sub-option and is hidden outright when
// the box is clear — the shape `directIp` uses for its port.
List<Widget> webrtcOptions(BuildContext context) {
final stored = bind.mainGetLocalOption(key: kOptionRelayFallbackDelay);
final controller = TextEditingController(text: stored);
// What the field holds against what is saved. Apply is offered only while
// the two differ, so an untouched field shows no button at all, and neither
// does one typed back to its saved value or cleared when nothing was saved
// — the state an "edited" flag alone would still call dirty.
final typed = RxString(stored);
final saved = RxString(stored);
return [
_OptionCheckBox(
context,
'Enable WebRTC P2P connection',
kOptionEnableWebrtc,
isServer: false,
update: (_) => setState(() {}),
),
() {
final enabled = mainGetLocalBoolOptionSync(kOptionEnableWebrtc);
final isOptFixed = isOptionFixed(kOptionRelayFallbackDelay);
return Offstage(
offstage: !enabled,
child: Tooltip(
message: translate('relay-fallback-delay-tip'),
child: _SubLabeledWidget(
context,
'Relay fallback delay in seconds',
Row(children: [
SizedBox(
width: 95,
child: TextField(
controller: controller,
enabled: enabled && !isOptFixed,
onChanged: (v) => typed.value = v,
inputFormatters: [
// Seconds, at most one decimal. Clearing the field is
// allowed and restores the built-in default.
FilteringTextInputFormatter.allow(
RegExp(r'^([0-9]|[1-9][0-9])(\.[0-9]?)?$')),
],
decoration: const InputDecoration(
hintText: '2.5',
contentPadding:
EdgeInsets.symmetric(vertical: 12, horizontal: 12),
),
).workaroundFreezeLinuxMint().marginOnly(right: 15),
),
Obx(() => Offstage(
offstage: typed.value.trim() == saved.value.trim(),
child: ElevatedButton(
onPressed: enabled &&
!isOptFixed &&
!typed.value.trim().endsWith('.') &&
double.tryParse(typed.value.trim()) != 0
? () async {
final v = controller.text.trim();
await bind.mainSetLocalOption(
key: kOptionRelayFallbackDelay, value: v);
if (controller.text != v) controller.text = v;
typed.value = v;
saved.value = v;
}
: null,
child: Text(translate('Apply')),
),
))
]),
enabled: enabled && !isOptFixed,
),
),
);
}(),
];
}
}
enum _AccessMode {