mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-04-06 02:21:29 +03:00
Fix/custom client advanced settings (#8066)
* fix: custom client, advanced settings Signed-off-by: fufesou <shuanglongchen@yeah.net> * refact: custom client, default options Signed-off-by: fufesou <shuanglongchen@yeah.net> * fix: cargo test Signed-off-by: fufesou <shuanglongchen@yeah.net> * refact: remove prefix $ and unify option keys Signed-off-by: fufesou <shuanglongchen@yeah.net> * refact: custom client, advanced options Signed-off-by: fufesou <shuanglongchen@yeah.net> * debug custom client, advanced settings Signed-off-by: fufesou <shuanglongchen@yeah.net> * custom client, advanced settings. Add filter-transfer to display settings Signed-off-by: fufesou <shuanglongchen@yeah.net> * custom client, advanced settings Signed-off-by: fufesou <shuanglongchen@yeah.net> * fix: custom client, advanced settings, codec Signed-off-by: fufesou <shuanglongchen@yeah.net> * fix: custom client, advanced settings, whitelist Signed-off-by: fufesou <shuanglongchen@yeah.net> --------- Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
@@ -332,22 +332,23 @@ class _GeneralState extends State<_General> {
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
final isOptFixed = isOptionFixed(kCommConfKeyTheme);
|
||||
return _Card(title: 'Theme', children: [
|
||||
_Radio<String>(context,
|
||||
value: 'light',
|
||||
groupValue: current,
|
||||
label: 'Light',
|
||||
onChanged: onChanged),
|
||||
onChanged: isOptFixed ? null : onChanged),
|
||||
_Radio<String>(context,
|
||||
value: 'dark',
|
||||
groupValue: current,
|
||||
label: 'Dark',
|
||||
onChanged: onChanged),
|
||||
onChanged: isOptFixed ? null : onChanged),
|
||||
_Radio<String>(context,
|
||||
value: 'system',
|
||||
groupValue: current,
|
||||
label: 'Follow System',
|
||||
onChanged: onChanged),
|
||||
onChanged: isOptFixed ? null : onChanged),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -547,21 +548,24 @@ class _GeneralState extends State<_General> {
|
||||
)).marginOnly(left: 10),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
String? initialDirectory;
|
||||
if (await Directory.fromUri(Uri.directory(user_dir))
|
||||
.exists()) {
|
||||
initialDirectory = user_dir;
|
||||
}
|
||||
String? selectedDirectory = await FilePicker.platform
|
||||
.getDirectoryPath(initialDirectory: initialDirectory);
|
||||
if (selectedDirectory != null) {
|
||||
await bind.mainSetOption(
|
||||
key: 'video-save-directory',
|
||||
value: selectedDirectory);
|
||||
setState(() {});
|
||||
}
|
||||
},
|
||||
onPressed: isOptionFixed(kOptionVideoSaveDirectory)
|
||||
? null
|
||||
: () async {
|
||||
String? initialDirectory;
|
||||
if (await Directory.fromUri(Uri.directory(user_dir))
|
||||
.exists()) {
|
||||
initialDirectory = user_dir;
|
||||
}
|
||||
String? selectedDirectory =
|
||||
await FilePicker.platform.getDirectoryPath(
|
||||
initialDirectory: initialDirectory);
|
||||
if (selectedDirectory != null) {
|
||||
await bind.mainSetOption(
|
||||
key: kOptionVideoSaveDirectory,
|
||||
value: selectedDirectory);
|
||||
setState(() {});
|
||||
}
|
||||
},
|
||||
child: Text(translate('Change')))
|
||||
.marginOnly(left: 5),
|
||||
],
|
||||
@@ -580,12 +584,13 @@ class _GeneralState extends State<_General> {
|
||||
Map<String, String> langsMap = {for (var v in langsList) v[0]: v[1]};
|
||||
List<String> keys = langsMap.keys.toList();
|
||||
List<String> values = langsMap.values.toList();
|
||||
keys.insert(0, '');
|
||||
keys.insert(0, defaultOptionLang);
|
||||
values.insert(0, translate('Default'));
|
||||
String currentKey = bind.mainGetLocalOption(key: kCommConfKeyLang);
|
||||
if (!keys.contains(currentKey)) {
|
||||
currentKey = '';
|
||||
currentKey = defaultOptionLang;
|
||||
}
|
||||
final isOptFixed = isOptionFixed(kCommConfKeyLang);
|
||||
return ComboBox(
|
||||
keys: keys,
|
||||
values: values,
|
||||
@@ -595,6 +600,7 @@ class _GeneralState extends State<_General> {
|
||||
reloadAllWindows();
|
||||
bind.mainChangeLanguage(lang: key);
|
||||
},
|
||||
enabled: !isOptFixed,
|
||||
).marginOnly(left: _kContentHMargin);
|
||||
});
|
||||
}
|
||||
@@ -728,7 +734,7 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
||||
return _Card(title: 'Permissions', children: [
|
||||
ComboBox(
|
||||
keys: [
|
||||
'',
|
||||
defaultOptionAccessMode,
|
||||
'full',
|
||||
'view',
|
||||
],
|
||||
@@ -737,37 +743,39 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
||||
translate('Full Access'),
|
||||
translate('Screen Share'),
|
||||
],
|
||||
enabled: enabled,
|
||||
enabled: enabled && !isOptionFixed(kOptionAccessMode),
|
||||
initialKey: initialKey,
|
||||
onChanged: (mode) async {
|
||||
await bind.mainSetOption(key: 'access-mode', value: mode);
|
||||
await bind.mainSetOption(key: kOptionAccessMode, value: mode);
|
||||
setState(() {});
|
||||
}).marginOnly(left: _kContentHMargin),
|
||||
Column(
|
||||
children: [
|
||||
_OptionCheckBox(context, 'Enable keyboard/mouse', 'enable-keyboard',
|
||||
_OptionCheckBox(
|
||||
context, 'Enable keyboard/mouse', kOptionEnableKeyboard,
|
||||
enabled: enabled, fakeValue: fakeValue),
|
||||
_OptionCheckBox(context, 'Enable clipboard', 'enable-clipboard',
|
||||
_OptionCheckBox(context, 'Enable clipboard', kOptionEnableClipboard,
|
||||
enabled: enabled, fakeValue: fakeValue),
|
||||
_OptionCheckBox(
|
||||
context, 'Enable file transfer', 'enable-file-transfer',
|
||||
context, 'Enable file transfer', kOptionEnableFileTransfer,
|
||||
enabled: enabled, fakeValue: fakeValue),
|
||||
_OptionCheckBox(context, 'Enable audio', 'enable-audio',
|
||||
enabled: enabled, fakeValue: fakeValue),
|
||||
_OptionCheckBox(context, 'Enable TCP tunneling', 'enable-tunnel',
|
||||
_OptionCheckBox(context, 'Enable audio', kOptionEnableAudio,
|
||||
enabled: enabled, fakeValue: fakeValue),
|
||||
_OptionCheckBox(
|
||||
context, 'Enable remote restart', 'enable-remote-restart',
|
||||
context, 'Enable TCP tunneling', kOptionEnableTunnel,
|
||||
enabled: enabled, fakeValue: fakeValue),
|
||||
_OptionCheckBox(
|
||||
context, 'Enable recording session', 'enable-record-session',
|
||||
context, 'Enable remote restart', kOptionEnableRemoteRestart,
|
||||
enabled: enabled, fakeValue: fakeValue),
|
||||
_OptionCheckBox(
|
||||
context, 'Enable recording session', kOptionEnableRecordSession,
|
||||
enabled: enabled, fakeValue: fakeValue),
|
||||
if (isWindows)
|
||||
_OptionCheckBox(
|
||||
context, 'Enable blocking user input', 'enable-block-input',
|
||||
_OptionCheckBox(context, 'Enable blocking user input',
|
||||
kOptionEnableBlockInput,
|
||||
enabled: enabled, fakeValue: fakeValue),
|
||||
_OptionCheckBox(context, 'Enable remote configuration modification',
|
||||
'allow-remote-config-modification',
|
||||
kOptionAllowRemoteConfigModification,
|
||||
enabled: enabled, fakeValue: fakeValue),
|
||||
],
|
||||
),
|
||||
@@ -801,14 +809,15 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
||||
value: value,
|
||||
groupValue: currentValue,
|
||||
label: value,
|
||||
onChanged: ((value) {
|
||||
() async {
|
||||
await model.setVerificationMethod(
|
||||
passwordKeys[passwordValues.indexOf(value)]);
|
||||
await model.updatePasswordModel();
|
||||
}();
|
||||
}),
|
||||
enabled: !locked,
|
||||
onChanged: locked
|
||||
? null
|
||||
: ((value) {
|
||||
() async {
|
||||
await model.setVerificationMethod(
|
||||
passwordKeys[passwordValues.indexOf(value)]);
|
||||
await model.updatePasswordModel();
|
||||
}();
|
||||
}),
|
||||
))
|
||||
.toList();
|
||||
|
||||
@@ -842,7 +851,11 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
||||
))
|
||||
.toList();
|
||||
|
||||
final modeKeys = ['password', 'click', ''];
|
||||
final modeKeys = <String>[
|
||||
'password',
|
||||
'click',
|
||||
defaultOptionApproveMode
|
||||
];
|
||||
final modeValues = [
|
||||
translate('Accept sessions via password'),
|
||||
translate('Accept sessions via click'),
|
||||
@@ -852,9 +865,10 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
||||
if (!modeKeys.contains(modeInitialKey)) modeInitialKey = '';
|
||||
final usePassword = model.approveMode != 'click';
|
||||
|
||||
final isApproveModeFixed = isOptionFixed(kOptionApproveMode);
|
||||
return _Card(title: 'Password', children: [
|
||||
ComboBox(
|
||||
enabled: !locked,
|
||||
enabled: !locked && !isApproveModeFixed,
|
||||
keys: modeKeys,
|
||||
values: modeValues,
|
||||
initialKey: modeInitialKey,
|
||||
@@ -930,15 +944,17 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
||||
update() => setState(() {});
|
||||
RxBool applyEnabled = false.obs;
|
||||
return [
|
||||
_OptionCheckBox(context, 'Enable direct IP access', 'direct-server',
|
||||
_OptionCheckBox(context, 'Enable direct IP access', kOptionDirectServer,
|
||||
update: update, enabled: !locked),
|
||||
() {
|
||||
// Simple temp wrapper for PR check
|
||||
tmpWrapper() {
|
||||
bool enabled = option2bool(
|
||||
'direct-server', bind.mainGetOptionSync(key: 'direct-server'));
|
||||
bool enabled = option2bool(kOptionDirectServer,
|
||||
bind.mainGetOptionSync(key: kOptionDirectServer));
|
||||
if (!enabled) applyEnabled.value = false;
|
||||
controller.text = bind.mainGetOptionSync(key: 'direct-access-port');
|
||||
controller.text =
|
||||
bind.mainGetOptionSync(key: kOptionDirectAccessPort);
|
||||
final isOptFixed = isOptionFixed(kOptionDirectAccessPort);
|
||||
return Offstage(
|
||||
offstage: !enabled,
|
||||
child: _SubLabeledWidget(
|
||||
@@ -949,7 +965,7 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
||||
width: 95,
|
||||
child: TextField(
|
||||
controller: controller,
|
||||
enabled: enabled && !locked,
|
||||
enabled: enabled && !locked && !isOptFixed,
|
||||
onChanged: (_) => applyEnabled.value = true,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(
|
||||
@@ -963,11 +979,14 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
||||
).marginOnly(right: 15),
|
||||
),
|
||||
Obx(() => ElevatedButton(
|
||||
onPressed: applyEnabled.value && enabled && !locked
|
||||
onPressed: applyEnabled.value &&
|
||||
enabled &&
|
||||
!locked &&
|
||||
!isOptFixed
|
||||
? () async {
|
||||
applyEnabled.value = false;
|
||||
await bind.mainSetOption(
|
||||
key: 'direct-access-port',
|
||||
key: kOptionDirectAccessPort,
|
||||
value: controller.text);
|
||||
}
|
||||
: null,
|
||||
@@ -976,7 +995,7 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
||||
),
|
||||
))
|
||||
]),
|
||||
enabled: enabled && !locked,
|
||||
enabled: enabled && !locked && !isOptFixed,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -990,17 +1009,19 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
||||
bool enabled = !locked;
|
||||
// Simple temp wrapper for PR check
|
||||
tmpWrapper() {
|
||||
RxBool hasWhitelist =
|
||||
bind.mainGetOptionSync(key: 'whitelist').isNotEmpty.obs;
|
||||
RxBool hasWhitelist = (bind.mainGetOptionSync(key: kOptionWhitelist) !=
|
||||
defaultOptionWhitelist)
|
||||
.obs;
|
||||
update() async {
|
||||
hasWhitelist.value =
|
||||
bind.mainGetOptionSync(key: 'whitelist').isNotEmpty;
|
||||
hasWhitelist.value = bind.mainGetOptionSync(key: kOptionWhitelist) !=
|
||||
defaultOptionWhitelist;
|
||||
}
|
||||
|
||||
onChanged(bool? checked) async {
|
||||
changeWhiteList(callback: update);
|
||||
}
|
||||
|
||||
final isOptFixed = isOptionFixed(kOptionWhitelist);
|
||||
return GestureDetector(
|
||||
child: Tooltip(
|
||||
message: translate('whitelist_tip'),
|
||||
@@ -1008,13 +1029,16 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
||||
children: [
|
||||
Checkbox(
|
||||
value: hasWhitelist.value,
|
||||
onChanged: enabled ? onChanged : null)
|
||||
onChanged: enabled && !isOptFixed ? onChanged : null)
|
||||
.marginOnly(right: 5),
|
||||
Offstage(
|
||||
offstage: !hasWhitelist.value,
|
||||
child: const Icon(Icons.warning_amber_rounded,
|
||||
color: Color.fromARGB(255, 255, 204, 0))
|
||||
.marginOnly(right: 5),
|
||||
child: MouseRegion(
|
||||
child: const Icon(Icons.warning_amber_rounded,
|
||||
color: Color.fromARGB(255, 255, 204, 0))
|
||||
.marginOnly(right: 5),
|
||||
cursor: SystemMouseCursors.click,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
@@ -1025,9 +1049,11 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
||||
],
|
||||
)),
|
||||
),
|
||||
onTap: () {
|
||||
onChanged(!hasWhitelist.value);
|
||||
},
|
||||
onTap: enabled
|
||||
? () {
|
||||
onChanged(!hasWhitelist.value);
|
||||
}
|
||||
: null,
|
||||
).marginOnly(left: _kCheckBoxLeftMargin);
|
||||
}
|
||||
|
||||
@@ -1078,16 +1104,17 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
||||
TextEditingController controller = TextEditingController();
|
||||
update() => setState(() {});
|
||||
RxBool applyEnabled = false.obs;
|
||||
final optionKey = 'allow-auto-disconnect';
|
||||
final timeoutKey = 'auto-disconnect-timeout';
|
||||
return [
|
||||
_OptionCheckBox(context, 'auto_disconnect_option_tip', optionKey,
|
||||
_OptionCheckBox(
|
||||
context, 'auto_disconnect_option_tip', kOptionAllowAutoDisconnect,
|
||||
update: update, enabled: !locked),
|
||||
() {
|
||||
bool enabled =
|
||||
option2bool(optionKey, bind.mainGetOptionSync(key: optionKey));
|
||||
bool enabled = option2bool(kOptionAllowAutoDisconnect,
|
||||
bind.mainGetOptionSync(key: kOptionAllowAutoDisconnect));
|
||||
if (!enabled) applyEnabled.value = false;
|
||||
controller.text = bind.mainGetOptionSync(key: timeoutKey);
|
||||
controller.text =
|
||||
bind.mainGetOptionSync(key: kOptionAutoDisconnectTimeout);
|
||||
final isOptFixed = isOptionFixed(kOptionAutoDisconnectTimeout);
|
||||
return Offstage(
|
||||
offstage: !enabled,
|
||||
child: _SubLabeledWidget(
|
||||
@@ -1098,7 +1125,7 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
||||
width: 95,
|
||||
child: TextField(
|
||||
controller: controller,
|
||||
enabled: enabled && !locked,
|
||||
enabled: enabled && !locked && isOptFixed,
|
||||
onChanged: (_) => applyEnabled.value = true,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(
|
||||
@@ -1112,19 +1139,21 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
||||
).marginOnly(right: 15),
|
||||
),
|
||||
Obx(() => ElevatedButton(
|
||||
onPressed: applyEnabled.value && enabled && !locked
|
||||
? () async {
|
||||
applyEnabled.value = false;
|
||||
await bind.mainSetOption(
|
||||
key: timeoutKey, value: controller.text);
|
||||
}
|
||||
: null,
|
||||
onPressed:
|
||||
applyEnabled.value && enabled && !locked && !isOptFixed
|
||||
? () async {
|
||||
applyEnabled.value = false;
|
||||
await bind.mainSetOption(
|
||||
key: kOptionAutoDisconnectTimeout,
|
||||
value: controller.text);
|
||||
}
|
||||
: null,
|
||||
child: Text(
|
||||
translate('Apply'),
|
||||
),
|
||||
))
|
||||
]),
|
||||
enabled: enabled && !locked,
|
||||
enabled: enabled && !locked && !isOptFixed,
|
||||
),
|
||||
);
|
||||
}(),
|
||||
@@ -1273,46 +1302,47 @@ class _DisplayState extends State<_Display> {
|
||||
}
|
||||
|
||||
Widget viewStyle(BuildContext context) {
|
||||
final key = 'view_style';
|
||||
final isOptFixed = isOptionFixed(kOptionViewStyle);
|
||||
onChanged(String value) async {
|
||||
await bind.mainSetUserDefaultOption(key: key, value: value);
|
||||
await bind.mainSetUserDefaultOption(key: kOptionViewStyle, value: value);
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
final groupValue = bind.mainGetUserDefaultOption(key: key);
|
||||
final groupValue = bind.mainGetUserDefaultOption(key: kOptionViewStyle);
|
||||
return _Card(title: 'Default View Style', children: [
|
||||
_Radio(context,
|
||||
value: kRemoteViewStyleOriginal,
|
||||
groupValue: groupValue,
|
||||
label: 'Scale original',
|
||||
onChanged: onChanged),
|
||||
onChanged: isOptFixed ? null : onChanged),
|
||||
_Radio(context,
|
||||
value: kRemoteViewStyleAdaptive,
|
||||
groupValue: groupValue,
|
||||
label: 'Scale adaptive',
|
||||
onChanged: onChanged),
|
||||
onChanged: isOptFixed ? null : onChanged),
|
||||
]);
|
||||
}
|
||||
|
||||
Widget scrollStyle(BuildContext context) {
|
||||
final key = 'scroll_style';
|
||||
final isOptFixed = isOptionFixed(kOptionScrollStyle);
|
||||
onChanged(String value) async {
|
||||
await bind.mainSetUserDefaultOption(key: key, value: value);
|
||||
await bind.mainSetUserDefaultOption(
|
||||
key: kOptionScrollStyle, value: value);
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
final groupValue = bind.mainGetUserDefaultOption(key: key);
|
||||
final groupValue = bind.mainGetUserDefaultOption(key: kOptionScrollStyle);
|
||||
return _Card(title: 'Default Scroll Style', children: [
|
||||
_Radio(context,
|
||||
value: kRemoteScrollStyleAuto,
|
||||
groupValue: groupValue,
|
||||
label: 'ScrollAuto',
|
||||
onChanged: onChanged),
|
||||
onChanged: isOptFixed ? null : onChanged),
|
||||
_Radio(context,
|
||||
value: kRemoteScrollStyleBar,
|
||||
groupValue: groupValue,
|
||||
label: 'Scrollbar',
|
||||
onChanged: onChanged),
|
||||
onChanged: isOptFixed ? null : onChanged),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -1323,28 +1353,29 @@ class _DisplayState extends State<_Display> {
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
final isOptFixed = isOptionFixed(key);
|
||||
final groupValue = bind.mainGetUserDefaultOption(key: key);
|
||||
return _Card(title: 'Default Image Quality', children: [
|
||||
_Radio(context,
|
||||
value: kRemoteImageQualityBest,
|
||||
groupValue: groupValue,
|
||||
label: 'Good image quality',
|
||||
onChanged: onChanged),
|
||||
onChanged: isOptFixed ? null : onChanged),
|
||||
_Radio(context,
|
||||
value: kRemoteImageQualityBalanced,
|
||||
groupValue: groupValue,
|
||||
label: 'Balanced',
|
||||
onChanged: onChanged),
|
||||
onChanged: isOptFixed ? null : onChanged),
|
||||
_Radio(context,
|
||||
value: kRemoteImageQualityLow,
|
||||
groupValue: groupValue,
|
||||
label: 'Optimize reaction time',
|
||||
onChanged: onChanged),
|
||||
onChanged: isOptFixed ? null : onChanged),
|
||||
_Radio(context,
|
||||
value: kRemoteImageQualityCustom,
|
||||
groupValue: groupValue,
|
||||
label: 'Custom',
|
||||
onChanged: onChanged),
|
||||
onChanged: isOptFixed ? null : onChanged),
|
||||
Offstage(
|
||||
offstage: groupValue != kRemoteImageQualityCustom,
|
||||
child: customImageQualitySetting(),
|
||||
@@ -1353,14 +1384,16 @@ class _DisplayState extends State<_Display> {
|
||||
}
|
||||
|
||||
Widget codec(BuildContext context) {
|
||||
final key = 'codec-preference';
|
||||
onChanged(String value) async {
|
||||
await bind.mainSetUserDefaultOption(key: key, value: value);
|
||||
await bind.mainSetUserDefaultOption(
|
||||
key: kOptionCodecPreference, value: value);
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
final groupValue = bind.mainGetUserDefaultOption(key: key);
|
||||
final groupValue =
|
||||
bind.mainGetUserDefaultOption(key: kOptionCodecPreference);
|
||||
var hwRadios = [];
|
||||
final isOptFixed = isOptionFixed(kOptionCodecPreference);
|
||||
try {
|
||||
final Map codecsJson = jsonDecode(bind.mainSupportedHwdecodings());
|
||||
final h264 = codecsJson['h264'] ?? false;
|
||||
@@ -1370,14 +1403,14 @@ class _DisplayState extends State<_Display> {
|
||||
value: 'h264',
|
||||
groupValue: groupValue,
|
||||
label: 'H264',
|
||||
onChanged: onChanged));
|
||||
onChanged: isOptFixed ? null : onChanged));
|
||||
}
|
||||
if (h265) {
|
||||
hwRadios.add(_Radio(context,
|
||||
value: 'h265',
|
||||
groupValue: groupValue,
|
||||
label: 'H265',
|
||||
onChanged: onChanged));
|
||||
onChanged: isOptFixed ? null : onChanged));
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint("failed to parse supported hwdecodings, err=$e");
|
||||
@@ -1387,22 +1420,22 @@ class _DisplayState extends State<_Display> {
|
||||
value: 'auto',
|
||||
groupValue: groupValue,
|
||||
label: 'Auto',
|
||||
onChanged: onChanged),
|
||||
onChanged: isOptFixed ? null : onChanged),
|
||||
_Radio(context,
|
||||
value: 'vp8',
|
||||
groupValue: groupValue,
|
||||
label: 'VP8',
|
||||
onChanged: onChanged),
|
||||
onChanged: isOptFixed ? null : onChanged),
|
||||
_Radio(context,
|
||||
value: 'vp9',
|
||||
groupValue: groupValue,
|
||||
label: 'VP9',
|
||||
onChanged: onChanged),
|
||||
onChanged: isOptFixed ? null : onChanged),
|
||||
_Radio(context,
|
||||
value: 'av1',
|
||||
groupValue: groupValue,
|
||||
label: 'AV1',
|
||||
onChanged: onChanged),
|
||||
onChanged: isOptFixed ? null : onChanged),
|
||||
...hwRadios,
|
||||
]);
|
||||
}
|
||||
@@ -1445,22 +1478,29 @@ class _DisplayState extends State<_Display> {
|
||||
|
||||
Widget otherRow(String label, String key) {
|
||||
final value = bind.mainGetUserDefaultOption(key: key) == 'Y';
|
||||
final isOptFixed = isOptionFixed(key);
|
||||
onChanged(bool b) async {
|
||||
await bind.mainSetUserDefaultOption(key: key, value: b ? 'Y' : '');
|
||||
await bind.mainSetUserDefaultOption(
|
||||
key: key,
|
||||
value: b
|
||||
? 'Y'
|
||||
: (key == kOptionEnableFileTransfer ? 'N' : defaultOptionNo));
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
return GestureDetector(
|
||||
child: Row(
|
||||
children: [
|
||||
Checkbox(value: value, onChanged: (_) => onChanged(!value))
|
||||
Checkbox(
|
||||
value: value,
|
||||
onChanged: isOptFixed ? null : (_) => onChanged(!value))
|
||||
.marginOnly(right: 5),
|
||||
Expanded(
|
||||
child: Text(translate(label)),
|
||||
)
|
||||
],
|
||||
).marginOnly(left: _kCheckBoxLeftMargin),
|
||||
onTap: () => onChanged(!value));
|
||||
onTap: isOptFixed ? null : () => onChanged(!value));
|
||||
}
|
||||
|
||||
Widget other(BuildContext context) {
|
||||
@@ -1772,6 +1812,7 @@ Widget _OptionCheckBox(BuildContext context, String label, String key,
|
||||
bool isServer = true}) {
|
||||
bool value =
|
||||
isServer ? mainGetBoolOptionSync(key) : mainGetLocalBoolOptionSync(key);
|
||||
final isOptFixed = isOptionFixed(key);
|
||||
if (reverse) value = !value;
|
||||
var ref = value.obs;
|
||||
onChanged(option) async {
|
||||
@@ -1801,7 +1842,9 @@ Widget _OptionCheckBox(BuildContext context, String label, String key,
|
||||
child: Obx(
|
||||
() => Row(
|
||||
children: [
|
||||
Checkbox(value: ref.value, onChanged: enabled ? onChanged : null)
|
||||
Checkbox(
|
||||
value: ref.value,
|
||||
onChanged: enabled && !isOptFixed ? onChanged : null)
|
||||
.marginOnly(right: 5),
|
||||
Offstage(
|
||||
offstage: !ref.value || checkedIcon == null,
|
||||
@@ -1815,7 +1858,7 @@ Widget _OptionCheckBox(BuildContext context, String label, String key,
|
||||
],
|
||||
),
|
||||
).marginOnly(left: _kCheckBoxLeftMargin),
|
||||
onTap: enabled
|
||||
onTap: enabled && !isOptFixed
|
||||
? () {
|
||||
onChanged(!ref.value);
|
||||
}
|
||||
@@ -1828,10 +1871,9 @@ Widget _Radio<T>(BuildContext context,
|
||||
{required T value,
|
||||
required T groupValue,
|
||||
required String label,
|
||||
required Function(T value) onChanged,
|
||||
bool autoNewLine = true,
|
||||
bool enabled = true}) {
|
||||
var onChange = enabled
|
||||
required Function(T value)? onChanged,
|
||||
bool autoNewLine = true}) {
|
||||
final onChange2 = onChanged != null
|
||||
? (T? value) {
|
||||
if (value != null) {
|
||||
onChanged(value);
|
||||
@@ -1841,18 +1883,18 @@ Widget _Radio<T>(BuildContext context,
|
||||
return GestureDetector(
|
||||
child: Row(
|
||||
children: [
|
||||
Radio<T>(value: value, groupValue: groupValue, onChanged: onChange),
|
||||
Radio<T>(value: value, groupValue: groupValue, onChanged: onChange2),
|
||||
Expanded(
|
||||
child: Text(translate(label),
|
||||
overflow: autoNewLine ? null : TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: _kContentFontSize,
|
||||
color: disabledTextColor(context, enabled)))
|
||||
color: disabledTextColor(context, onChange2 != null)))
|
||||
.marginOnly(left: 5),
|
||||
),
|
||||
],
|
||||
).marginOnly(left: _kRadioLeftMargin),
|
||||
onTap: () => onChange?.call(value),
|
||||
onTap: () => onChange2?.call(value),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -428,7 +428,7 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
|
||||
}
|
||||
ConnectionTypeState.init(id);
|
||||
_toolbarState.setShow(
|
||||
bind.mainGetUserDefaultOption(key: 'collapse_toolbar') != 'Y');
|
||||
bind.mainGetUserDefaultOption(key: kOptionCollapseToolbar) != 'Y');
|
||||
tabController.add(TabInfo(
|
||||
key: id,
|
||||
label: id,
|
||||
|
||||
@@ -54,7 +54,7 @@ class ToolbarState {
|
||||
_initSet(bool s, bool p) {
|
||||
// Show remubar when connection is established.
|
||||
show =
|
||||
RxBool(bind.mainGetUserDefaultOption(key: 'collapse_toolbar') != 'Y');
|
||||
RxBool(bind.mainGetUserDefaultOption(key: kOptionCollapseToolbar) != 'Y');
|
||||
_pin = RxBool(p);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user