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:
fufesou 2024-05-17 14:19:11 +08:00 committed by GitHub
parent 3a4390e0c7
commit 8357d4675a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 707 additions and 364 deletions

View file

@ -100,8 +100,8 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
_denyLANDiscovery = denyLanDiscovery;
}
final onlyWhiteList =
(await bind.mainGetOption(key: 'whitelist')).isNotEmpty;
final onlyWhiteList = (await bind.mainGetOption(key: kOptionWhitelist)) !=
defaultOptionWhitelist;
if (onlyWhiteList != _onlyWhiteList) {
update = true;
_onlyWhiteList = onlyWhiteList;
@ -143,7 +143,7 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
}
final directAccessPort =
await bind.mainGetOption(key: 'direct-access-port');
await bind.mainGetOption(key: kOptionDirectAccessPort);
if (directAccessPort != _directAccessPort) {
update = true;
_directAccessPort = directAccessPort;
@ -257,16 +257,18 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
SettingsTile.switchTile(
title: Text(translate('Deny LAN discovery')),
initialValue: _denyLANDiscovery,
onToggle: (v) async {
await bind.mainSetOption(
key: "enable-lan-discovery",
value: bool2option("enable-lan-discovery", !v));
final newValue = !option2bool('enable-lan-discovery',
await bind.mainGetOption(key: 'enable-lan-discovery'));
setState(() {
_denyLANDiscovery = newValue;
});
},
onToggle: isOptionFixed(kOptionEnableLanDiscovery)
? null
: (v) async {
await bind.mainSetOption(
key: kOptionEnableLanDiscovery,
value: bool2option(kOptionEnableLanDiscovery, !v));
final newValue = !option2bool(kOptionEnableLanDiscovery,
await bind.mainGetOption(key: kOptionEnableLanDiscovery));
setState(() {
_denyLANDiscovery = newValue;
});
},
),
SettingsTile.switchTile(
title: Row(children: [
@ -279,42 +281,51 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
]),
initialValue: _onlyWhiteList,
onToggle: (_) async {
update() async {
final onlyWhiteList =
(await bind.mainGetOption(key: 'whitelist')).isNotEmpty;
if (onlyWhiteList != _onlyWhiteList) {
setState(() {
_onlyWhiteList = onlyWhiteList;
});
}
}
update() async {
final onlyWhiteList =
(await bind.mainGetOption(key: kOptionWhitelist)) !=
defaultOptionWhitelist;
if (onlyWhiteList != _onlyWhiteList) {
setState(() {
_onlyWhiteList = onlyWhiteList;
});
}
}
changeWhiteList(callback: update);
},
changeWhiteList(callback: update);
},
),
SettingsTile.switchTile(
title: Text('${translate('Adaptive bitrate')} (beta)'),
initialValue: _enableAbr,
onToggle: (v) async {
await bind.mainSetOption(key: "enable-abr", value: v ? "" : "N");
final newValue = await bind.mainGetOption(key: "enable-abr") != "N";
setState(() {
_enableAbr = newValue;
});
},
onToggle: isOptionFixed(kOptionEnableAbr)
? null
: (v) async {
await bind.mainSetOption(
key: kOptionEnableAbr, value: v ? defaultOptionYes : "N");
final newValue =
await bind.mainGetOption(key: kOptionEnableAbr) != "N";
setState(() {
_enableAbr = newValue;
});
},
),
SettingsTile.switchTile(
title: Text(translate('Enable recording session')),
initialValue: _enableRecordSession,
onToggle: (v) async {
await bind.mainSetOption(
key: "enable-record-session", value: v ? "" : "N");
final newValue =
await bind.mainGetOption(key: "enable-record-session") != "N";
setState(() {
_enableRecordSession = newValue;
});
},
onToggle: isOptionFixed(kOptionEnableRecordSession)
? null
: (v) async {
await bind.mainSetOption(
key: kOptionEnableRecordSession,
value: v ? defaultOptionYes : "N");
final newValue =
await bind.mainGetOption(key: kOptionEnableRecordSession) !=
"N";
setState(() {
_enableRecordSession = newValue;
});
},
),
SettingsTile.switchTile(
title: Row(
@ -341,21 +352,27 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
Icons.edit,
size: 20,
),
onPressed: () async {
final port = await changeDirectAccessPort(
_localIP, _directAccessPort);
setState(() {
_directAccessPort = port;
});
}))
onPressed: isOptionFixed(kOptionDirectAccessPort)
? null
: () async {
final port = await changeDirectAccessPort(
_localIP, _directAccessPort);
setState(() {
_directAccessPort = port;
});
}))
]),
initialValue: _enableDirectIPAccess,
onToggle: (_) async {
_enableDirectIPAccess = !_enableDirectIPAccess;
String value = bool2option('direct-server', _enableDirectIPAccess);
await bind.mainSetOption(key: 'direct-server', value: value);
setState(() {});
},
onToggle: isOptionFixed(kOptionDirectServer)
? null
: (_) async {
_enableDirectIPAccess = !_enableDirectIPAccess;
String value =
bool2option(kOptionDirectServer, _enableDirectIPAccess);
await bind.mainSetOption(
key: kOptionDirectServer, value: value);
setState(() {});
},
),
SettingsTile.switchTile(
title: Row(
@ -382,22 +399,27 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
Icons.edit,
size: 20,
),
onPressed: () async {
final timeout = await changeAutoDisconnectTimeout(
_autoDisconnectTimeout);
setState(() {
_autoDisconnectTimeout = timeout;
});
}))
onPressed: isOptionFixed(kOptionAutoDisconnectTimeout)
? null
: () async {
final timeout = await changeAutoDisconnectTimeout(
_autoDisconnectTimeout);
setState(() {
_autoDisconnectTimeout = timeout;
});
}))
]),
initialValue: _allowAutoDisconnect,
onToggle: (_) async {
_allowAutoDisconnect = !_allowAutoDisconnect;
String value =
bool2option('allow-auto-disconnect', _allowAutoDisconnect);
await bind.mainSetOption(key: 'allow-auto-disconnect', value: value);
setState(() {});
},
onToggle: isOptionFixed(kOptionAllowAutoDisconnect)
? null
: (_) async {
_allowAutoDisconnect = !_allowAutoDisconnect;
String value = bool2option(
kOptionAllowAutoDisconnect, _allowAutoDisconnect);
await bind.mainSetOption(
key: kOptionAllowAutoDisconnect, value: value);
setState(() {});
},
)
];
if (_hasIgnoreBattery) {
@ -526,15 +548,19 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
SettingsTile.switchTile(
title: Text(translate('Enable hardware codec')),
initialValue: _enableHardwareCodec,
onToggle: (v) async {
await bind.mainSetOption(
key: "enable-hwcodec", value: v ? "" : "N");
final newValue =
await bind.mainGetOption(key: "enable-hwcodec") != "N";
setState(() {
_enableHardwareCodec = newValue;
});
},
onToggle: isOptionFixed(kOptionEnableHwcodec)
? null
: (v) async {
await bind.mainSetOption(
key: kOptionEnableHwcodec,
value: v ? defaultOptionYes : "N");
final newValue =
await bind.mainGetOption(key: kOptionEnableHwcodec) !=
"N";
setState(() {
_enableHardwareCodec = newValue;
});
},
),
]),
if (isAndroid && !outgoingOnly)
@ -551,18 +577,21 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
child: Text("${translate("Directory")}: ${data.data}")),
future: bind.mainVideoSaveDirectory(root: false)),
initialValue: _autoRecordIncomingSession,
onToggle: (v) async {
await bind.mainSetOption(
key: "allow-auto-record-incoming",
value: bool2option("allow-auto-record-incoming", v));
final newValue = option2bool(
'allow-auto-record-incoming',
await bind.mainGetOption(
key: 'allow-auto-record-incoming'));
setState(() {
_autoRecordIncomingSession = newValue;
});
},
onToggle: isOptionFixed(kOptionAllowAutoRecordIncoming)
? null
: (v) async {
await bind.mainSetOption(
key: kOptionAllowAutoRecordIncoming,
value:
bool2option(kOptionAllowAutoRecordIncoming, v));
final newValue = option2bool(
kOptionAllowAutoRecordIncoming,
await bind.mainGetOption(
key: kOptionAllowAutoRecordIncoming));
setState(() {
_autoRecordIncomingSession = newValue;
});
},
),
],
),
@ -661,29 +690,32 @@ void showServerSettings(OverlayDialogManager dialogManager) async {
void showLanguageSettings(OverlayDialogManager dialogManager) async {
try {
final langs = json.decode(await bind.mainGetLangs()) as List<dynamic>;
var lang = bind.mainGetLocalOption(key: "lang");
var lang = bind.mainGetLocalOption(key: kCommConfKeyLang);
dialogManager.show((setState, close, context) {
setLang(v) async {
if (lang != v) {
setState(() {
lang = v;
});
await bind.mainSetLocalOption(key: "lang", value: v);
await bind.mainSetLocalOption(key: kCommConfKeyLang, value: v);
HomePage.homeKey.currentState?.refreshPages();
Future.delayed(Duration(milliseconds: 200), close);
}
}
final isOptFixed = isOptionFixed(kCommConfKeyLang);
return CustomAlertDialog(
content: Column(
children: [
getRadio(Text(translate('Default')), '', lang, setLang),
getRadio(Text(translate('Default')), defaultOptionLang, lang,
isOptFixed ? null : setLang),
Divider(color: MyTheme.border),
] +
langs.map((e) {
final key = e[0] as String;
final name = e[1] as String;
return getRadio(Text(translate(name)), key, lang, setLang);
return getRadio(Text(translate(name)), key, lang,
isOptFixed ? null : setLang);
}).toList(),
),
);
@ -707,13 +739,15 @@ void showThemeSettings(OverlayDialogManager dialogManager) async {
}
}
final isOptFixed = isOptionFixed(kCommConfKeyTheme);
return CustomAlertDialog(
content: Column(children: [
getRadio(
Text(translate('Light')), ThemeMode.light, themeMode, setTheme),
getRadio(Text(translate('Dark')), ThemeMode.dark, themeMode, setTheme),
getRadio(Text(translate('Light')), ThemeMode.light, themeMode,
isOptFixed ? null : setTheme),
getRadio(Text(translate('Dark')), ThemeMode.dark, themeMode,
isOptFixed ? null : setTheme),
getRadio(Text(translate('Follow System')), ThemeMode.system, themeMode,
setTheme)
isOptFixed ? null : setTheme)
]),
);
}, backDismiss: true, clickMaskDismiss: true);
@ -801,11 +835,14 @@ class __DisplayPageState extends State<_DisplayPage> {
_RadioEntry('Scale original', kRemoteViewStyleOriginal),
_RadioEntry('Scale adaptive', kRemoteViewStyleAdaptive)
],
getter: () => bind.mainGetUserDefaultOption(key: 'view_style'),
asyncSetter: (value) async {
await bind.mainSetUserDefaultOption(
key: 'view_style', value: value);
},
getter: () =>
bind.mainGetUserDefaultOption(key: kOptionViewStyle),
asyncSetter: isOptionFixed(kOptionViewStyle)
? null
: (value) async {
await bind.mainSetUserDefaultOption(
key: kOptionViewStyle, value: value);
},
),
_getPopupDialogRadioEntry(
title: 'Default Image Quality',
@ -816,16 +853,19 @@ class __DisplayPageState extends State<_DisplayPage> {
_RadioEntry('Custom', kRemoteImageQualityCustom),
],
getter: () {
final v = bind.mainGetUserDefaultOption(key: 'image_quality');
final v =
bind.mainGetUserDefaultOption(key: kOptionImageQuality);
showCustomImageQuality.value = v == kRemoteImageQualityCustom;
return v;
},
asyncSetter: (value) async {
await bind.mainSetUserDefaultOption(
key: 'image_quality', value: value);
showCustomImageQuality.value =
value == kRemoteImageQualityCustom;
},
asyncSetter: isOptionFixed(kOptionImageQuality)
? null
: (value) async {
await bind.mainSetUserDefaultOption(
key: kOptionImageQuality, value: value);
showCustomImageQuality.value =
value == kRemoteImageQualityCustom;
},
tail: customImageQualitySetting(),
showTail: showCustomImageQuality,
notCloseValue: kRemoteImageQualityCustom,
@ -834,11 +874,13 @@ class __DisplayPageState extends State<_DisplayPage> {
title: 'Default Codec',
list: codecList,
getter: () =>
bind.mainGetUserDefaultOption(key: 'codec-preference'),
asyncSetter: (value) async {
await bind.mainSetUserDefaultOption(
key: 'codec-preference', value: value);
},
bind.mainGetUserDefaultOption(key: kOptionCodecPreference),
asyncSetter: isOptionFixed(kOptionCodecPreference)
? null
: (value) async {
await bind.mainSetUserDefaultOption(
key: kOptionCodecPreference, value: value);
},
),
],
),
@ -853,13 +895,17 @@ class __DisplayPageState extends State<_DisplayPage> {
SettingsTile otherRow(String label, String key) {
final value = bind.mainGetUserDefaultOption(key: key) == 'Y';
final isOptFixed = isOptionFixed(key);
return SettingsTile.switchTile(
initialValue: value,
title: Text(translate(label)),
onToggle: (b) async {
await bind.mainSetUserDefaultOption(key: key, value: b ? 'Y' : '');
setState(() {});
},
onToggle: isOptFixed
? null
: (b) async {
await bind.mainSetUserDefaultOption(
key: key, value: b ? 'Y' : defaultOptionNo);
setState(() {});
},
);
}
}
@ -877,7 +923,7 @@ _getPopupDialogRadioEntry({
required String title,
required List<_RadioEntry> list,
required _RadioEntryGetter getter,
required _RadioEntrySetter asyncSetter,
required _RadioEntrySetter? asyncSetter,
Widget? tail,
RxBool? showTail,
String? notCloseValue,
@ -897,21 +943,23 @@ _getPopupDialogRadioEntry({
void showDialog() async {
gFFI.dialogManager.show((setState, close, context) {
onChanged(String? value) async {
if (value == null) return;
await asyncSetter(value);
init();
if (value != notCloseValue) {
close();
}
}
final onChanged = asyncSetter == null
? null
: (String? value) async {
if (value == null) return;
await asyncSetter(value);
init();
if (value != notCloseValue) {
close();
}
};
return CustomAlertDialog(
content: Obx(
() => Column(children: [
...list
.map((e) => getRadio(Text(translate(e.label)), e.value,
groupValue.value, (String? value) => onChanged(value)))
groupValue.value, onChanged))
.toList(),
Offstage(
offstage: