Create management portal in Flutter #39
This commit is contained in:
parent
5ed74aa5af
commit
1d37822451
@ -1,31 +1,28 @@
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
String formatMountName(String type, String name) {
|
||||
if (type == 'remote') {
|
||||
return name.replaceAll('_', ':');
|
||||
}
|
||||
typedef Validator = bool Function(String);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
String getBaseUri() {
|
||||
if (kDebugMode || !kIsWeb) {
|
||||
return 'http://127.0.0.1:30000';
|
||||
}
|
||||
|
||||
return Uri.base.origin;
|
||||
}
|
||||
|
||||
String initialCaps(String txt) {
|
||||
if (txt.isEmpty) {
|
||||
return txt;
|
||||
}
|
||||
|
||||
if (txt.length == 1) {
|
||||
return txt[0].toUpperCase();
|
||||
}
|
||||
|
||||
return txt[0].toUpperCase() + txt.substring(1).toLowerCase();
|
||||
bool containsRestrictedChar(String value) {
|
||||
const invalidChars = [
|
||||
'!',
|
||||
'"',
|
||||
'\$',
|
||||
'&',
|
||||
'\'',
|
||||
'(',
|
||||
')',
|
||||
'*',
|
||||
';',
|
||||
'<',
|
||||
'>',
|
||||
'?',
|
||||
'`',
|
||||
'{',
|
||||
'|',
|
||||
'}',
|
||||
];
|
||||
return invalidChars.firstWhereOrNull((char) => value.contains(char)) != null;
|
||||
}
|
||||
|
||||
Map<String, dynamic> createDefaultSettings(String mountType) {
|
||||
@ -52,7 +49,7 @@ Map<String, dynamic> createDefaultSettings(String mountType) {
|
||||
return {
|
||||
'HostConfig': {
|
||||
'ApiPassword': '',
|
||||
'ApiPort': '9980',
|
||||
'ApiPort': 9980,
|
||||
'HostNameOrIp': 'localhost',
|
||||
},
|
||||
'SiaConfig': {'Bucket': 'default'},
|
||||
@ -61,3 +58,105 @@ Map<String, dynamic> createDefaultSettings(String mountType) {
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
String formatMountName(String type, String name) {
|
||||
if (type == 'remote') {
|
||||
return name.replaceAll('_', ':');
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
String getBaseUri() {
|
||||
if (kDebugMode || !kIsWeb) {
|
||||
return 'http://127.0.0.1:30000';
|
||||
}
|
||||
|
||||
return Uri.base.origin;
|
||||
}
|
||||
|
||||
List<Validator> getSettingValidators(String settingPath) {
|
||||
switch (settingPath) {
|
||||
case 'EncryptConfig.EncryptionToken':
|
||||
return [(value) => value.isNotEmpty];
|
||||
case 'EncryptConfig.Path':
|
||||
return [
|
||||
(value) => value.trim().isNotEmpty,
|
||||
(value) => !containsRestrictedChar(value),
|
||||
];
|
||||
case 'HostConfig.ApiPassword':
|
||||
return [(value) => value.isNotEmpty];
|
||||
case 'HostConfig.ApiPort':
|
||||
return [
|
||||
(value) {
|
||||
int? intValue = int.tryParse(value);
|
||||
if (intValue == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (intValue > 0 && intValue < 65536);
|
||||
},
|
||||
(value) => Uri.tryParse('http://localhost:$value/') != null,
|
||||
];
|
||||
case 'HostConfig.HostNameOrIp':
|
||||
return [
|
||||
(value) => value.trim().isNotEmpty,
|
||||
(value) => Uri.tryParse('http://$value:9000/') != null,
|
||||
];
|
||||
case 'HostConfig.Protocol':
|
||||
return [(value) => value == "http" || value == "https"];
|
||||
case 'S3Config.AccessKey':
|
||||
return [(value) => value.isNotEmpty];
|
||||
case 'S3Config.Bucket':
|
||||
return [(value) => value.trim().isNotEmpty];
|
||||
case 'S3Config.SecretKey':
|
||||
return [(value) => value.isNotEmpty];
|
||||
case 'S3Config.URL':
|
||||
return [(value) => Uri.tryParse(value) != null];
|
||||
case 'SiaConfig.Bucket':
|
||||
return [(value) => value.trim().isNotEmpty];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
String initialCaps(String txt) {
|
||||
if (txt.isEmpty) {
|
||||
return txt;
|
||||
}
|
||||
|
||||
if (txt.length == 1) {
|
||||
return txt[0].toUpperCase();
|
||||
}
|
||||
|
||||
return txt[0].toUpperCase() + txt.substring(1).toLowerCase();
|
||||
}
|
||||
|
||||
bool validateSettings(
|
||||
Map<String, dynamic> settings,
|
||||
List<String> failed, {
|
||||
String? rootKey,
|
||||
}) {
|
||||
settings.forEach((key, value) {
|
||||
if (value is Map) {
|
||||
validateSettings(
|
||||
value as Map<String, dynamic>,
|
||||
failed,
|
||||
rootKey: rootKey == null ? key : '$rootKey.$key',
|
||||
);
|
||||
} else {
|
||||
final validators = getSettingValidators(key);
|
||||
for (var validator in validators) {
|
||||
if (!validator(value.toString())) {
|
||||
if (rootKey == null) {
|
||||
failed.add(key);
|
||||
} else {
|
||||
failed.add('$rootKey.$key');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return failed.isEmpty;
|
||||
}
|
||||
|
@ -121,11 +121,17 @@ class _AddMountScreenState extends State<AddMountScreen> {
|
||||
if (_mount != null)
|
||||
ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
List<String> failed = [];
|
||||
if (!validateSettings(_settings[_mountType]!, failed)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Provider.of<MountList>(context, listen: false).add(
|
||||
_mountType,
|
||||
_mountNameController.text,
|
||||
_settings[_mountType]!,
|
||||
);
|
||||
|
||||
Navigator.pop(context);
|
||||
},
|
||||
label: const Text('Add'),
|
||||
|
@ -2,6 +2,7 @@ import 'package:collection/collection.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:repertory/constants.dart';
|
||||
import 'package:repertory/helpers.dart' show Validator, getSettingValidators;
|
||||
import 'package:repertory/models/mount.dart';
|
||||
import 'package:settings_ui/settings_ui.dart';
|
||||
|
||||
@ -48,7 +49,14 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
}
|
||||
}
|
||||
|
||||
void _addIntSetting(list, root, key, value, isAdvanced) {
|
||||
void _addIntSetting(
|
||||
list,
|
||||
root,
|
||||
key,
|
||||
value,
|
||||
isAdvanced, {
|
||||
List<Validator> validators = const [],
|
||||
}) {
|
||||
if (!isAdvanced || widget.showAdvanced) {
|
||||
list.add(
|
||||
SettingsTile.navigation(
|
||||
@ -69,6 +77,15 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
TextButton(
|
||||
child: Text('OK'),
|
||||
onPressed: () {
|
||||
final result = validators.firstWhereOrNull(
|
||||
(func) => !func(updatedValue),
|
||||
);
|
||||
if (result != null) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('$key must be valid')),
|
||||
);
|
||||
return;
|
||||
}
|
||||
setState(() {
|
||||
root[key] = int.parse(updatedValue);
|
||||
widget.onChanged?.call(widget.settings);
|
||||
@ -176,7 +193,15 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
}
|
||||
}
|
||||
|
||||
void _addStringSetting(list, root, key, value, icon, isAdvanced) {
|
||||
void _addStringSetting(
|
||||
list,
|
||||
root,
|
||||
key,
|
||||
value,
|
||||
icon,
|
||||
isAdvanced, {
|
||||
List<Validator> validators = const [],
|
||||
}) {
|
||||
if (!isAdvanced || widget.showAdvanced) {
|
||||
list.add(
|
||||
SettingsTile.navigation(
|
||||
@ -197,6 +222,16 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
TextButton(
|
||||
child: Text('OK'),
|
||||
onPressed: () {
|
||||
final result = validators.firstWhereOrNull(
|
||||
(func) => !func(updatedValue),
|
||||
);
|
||||
if (result != null) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('$key must be valid')),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
setState(() {
|
||||
root[key] = updatedValue;
|
||||
widget.onChanged?.call(widget.settings);
|
||||
@ -234,7 +269,14 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
if (key == 'ApiAuth') {
|
||||
_addPasswordSetting(commonSettings, widget.settings, key, value, true);
|
||||
} else if (key == 'ApiPort') {
|
||||
_addIntSetting(commonSettings, widget.settings, key, value, true);
|
||||
_addIntSetting(
|
||||
commonSettings,
|
||||
widget.settings,
|
||||
key,
|
||||
value,
|
||||
true,
|
||||
validators: getSettingValidators(key),
|
||||
);
|
||||
} else if (key == 'ApiUser') {
|
||||
_addStringSetting(
|
||||
commonSettings,
|
||||
@ -243,6 +285,7 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
value,
|
||||
Icons.person,
|
||||
true,
|
||||
validators: getSettingValidators(key),
|
||||
);
|
||||
} else if (key == 'DatabaseType') {
|
||||
_addListSetting(
|
||||
@ -255,7 +298,14 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
true,
|
||||
);
|
||||
} else if (key == 'DownloadTimeoutSeconds') {
|
||||
_addIntSetting(commonSettings, widget.settings, key, value, true);
|
||||
_addIntSetting(
|
||||
commonSettings,
|
||||
widget.settings,
|
||||
key,
|
||||
value,
|
||||
true,
|
||||
validators: getSettingValidators(key),
|
||||
);
|
||||
} else if (key == 'EnableDownloadTimeout') {
|
||||
_addBooleanSetting(commonSettings, widget.settings, key, value, true);
|
||||
} else if (key == 'EnableDriveEvents') {
|
||||
@ -271,15 +321,43 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
false,
|
||||
);
|
||||
} else if (key == 'EvictionDelayMinutes') {
|
||||
_addIntSetting(commonSettings, widget.settings, key, value, true);
|
||||
_addIntSetting(
|
||||
commonSettings,
|
||||
widget.settings,
|
||||
key,
|
||||
value,
|
||||
true,
|
||||
validators: getSettingValidators(key),
|
||||
);
|
||||
} else if (key == 'EvictionUseAccessedTime') {
|
||||
_addBooleanSetting(commonSettings, widget.settings, key, value, true);
|
||||
} else if (key == 'MaxCacheSizeBytes') {
|
||||
_addIntSetting(commonSettings, widget.settings, key, value, false);
|
||||
_addIntSetting(
|
||||
commonSettings,
|
||||
widget.settings,
|
||||
key,
|
||||
value,
|
||||
false,
|
||||
validators: getSettingValidators(key),
|
||||
);
|
||||
} else if (key == 'MaxUploadCount') {
|
||||
_addIntSetting(commonSettings, widget.settings, key, value, true);
|
||||
_addIntSetting(
|
||||
commonSettings,
|
||||
widget.settings,
|
||||
key,
|
||||
value,
|
||||
true,
|
||||
validators: getSettingValidators(key),
|
||||
);
|
||||
} else if (key == 'OnlineCheckRetrySeconds') {
|
||||
_addIntSetting(commonSettings, widget.settings, key, value, true);
|
||||
_addIntSetting(
|
||||
commonSettings,
|
||||
widget.settings,
|
||||
key,
|
||||
value,
|
||||
true,
|
||||
validators: getSettingValidators(key),
|
||||
);
|
||||
} else if (key == 'PreferredDownloadType') {
|
||||
_addListSetting(
|
||||
commonSettings,
|
||||
@ -291,7 +369,14 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
false,
|
||||
);
|
||||
} else if (key == 'RetryReadCount') {
|
||||
_addIntSetting(commonSettings, widget.settings, key, value, true);
|
||||
_addIntSetting(
|
||||
commonSettings,
|
||||
widget.settings,
|
||||
key,
|
||||
value,
|
||||
true,
|
||||
validators: getSettingValidators(key),
|
||||
);
|
||||
} else if (key == 'RingBufferFileSize') {
|
||||
_addIntListSetting(
|
||||
commonSettings,
|
||||
@ -321,6 +406,7 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
subValue,
|
||||
Icons.folder,
|
||||
false,
|
||||
validators: getSettingValidators('$key.$subKey'),
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -334,6 +420,7 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
subValue,
|
||||
Icons.support_agent,
|
||||
true,
|
||||
validators: getSettingValidators('$key.$subKey'),
|
||||
);
|
||||
} else if (subKey == 'ApiPassword') {
|
||||
_addPasswordSetting(
|
||||
@ -350,6 +437,7 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
subKey,
|
||||
subValue,
|
||||
false,
|
||||
validators: getSettingValidators('$key.$subKey'),
|
||||
);
|
||||
} else if (subKey == 'ApiUser') {
|
||||
_addStringSetting(
|
||||
@ -359,6 +447,7 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
subValue,
|
||||
Icons.person,
|
||||
true,
|
||||
validators: getSettingValidators('$key.$subKey'),
|
||||
);
|
||||
} else if (subKey == 'HostNameOrIp') {
|
||||
_addStringSetting(
|
||||
@ -377,6 +466,7 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
subValue,
|
||||
Icons.route,
|
||||
true,
|
||||
validators: getSettingValidators('$key.$subKey'),
|
||||
);
|
||||
} else if (subKey == 'Protocol') {
|
||||
_addListSetting(
|
||||
@ -395,6 +485,7 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
subKey,
|
||||
subValue,
|
||||
true,
|
||||
validators: getSettingValidators('$key.$subKey'),
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -407,6 +498,7 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
subKey,
|
||||
subValue,
|
||||
false,
|
||||
validators: getSettingValidators('$key.$subKey'),
|
||||
);
|
||||
} else if (subKey == 'EncryptionToken') {
|
||||
_addPasswordSetting(
|
||||
@ -424,6 +516,7 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
subValue,
|
||||
Icons.computer,
|
||||
false,
|
||||
validators: getSettingValidators('$key.$subKey'),
|
||||
);
|
||||
} else if (subKey == 'MaxConnections') {
|
||||
_addIntSetting(
|
||||
@ -432,6 +525,7 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
subKey,
|
||||
subValue,
|
||||
true,
|
||||
validators: getSettingValidators('$key.$subKey'),
|
||||
);
|
||||
} else if (subKey == 'ReceiveTimeoutMs') {
|
||||
_addIntSetting(
|
||||
@ -440,6 +534,7 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
subKey,
|
||||
subValue,
|
||||
true,
|
||||
validators: getSettingValidators('$key.$subKey'),
|
||||
);
|
||||
} else if (subKey == 'SendTimeoutMs') {
|
||||
_addIntSetting(
|
||||
@ -448,6 +543,7 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
subKey,
|
||||
subValue,
|
||||
true,
|
||||
validators: getSettingValidators('$key.$subKey'),
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -470,6 +566,7 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
subKey,
|
||||
subValue,
|
||||
false,
|
||||
validators: getSettingValidators('$key.$subKey'),
|
||||
);
|
||||
} else if (subKey == 'ClientPoolSize') {
|
||||
_addIntSetting(
|
||||
@ -478,6 +575,7 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
subKey,
|
||||
subValue,
|
||||
true,
|
||||
validators: getSettingValidators('$key.$subKey'),
|
||||
);
|
||||
} else if (subKey == 'EncryptionToken') {
|
||||
_addPasswordSetting(
|
||||
@ -507,6 +605,7 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
subValue,
|
||||
Icons.folder,
|
||||
false,
|
||||
validators: getSettingValidators('$key.$subKey'),
|
||||
);
|
||||
} else if (subKey == 'EncryptionToken') {
|
||||
_addPasswordSetting(
|
||||
@ -524,6 +623,7 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
subValue,
|
||||
Icons.map,
|
||||
false,
|
||||
validators: getSettingValidators('$key.$subKey'),
|
||||
);
|
||||
} else if (subKey == 'SecretKey') {
|
||||
_addPasswordSetting(
|
||||
@ -540,6 +640,7 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
subKey,
|
||||
subValue,
|
||||
true,
|
||||
validators: getSettingValidators('$key.$subKey'),
|
||||
);
|
||||
} else if (subKey == 'URL') {
|
||||
_addStringSetting(
|
||||
@ -549,6 +650,7 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
subValue,
|
||||
Icons.http,
|
||||
false,
|
||||
validators: getSettingValidators('$key.$subKey'),
|
||||
);
|
||||
} else if (subKey == 'UsePathStyle') {
|
||||
_addBooleanSetting(
|
||||
@ -578,6 +680,7 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
subValue,
|
||||
Icons.folder,
|
||||
false,
|
||||
validators: getSettingValidators('$key.$subKey'),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user