From 0318489b6cd3ed1f671edc42f83e594e193d8646 Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Thu, 6 Mar 2025 08:19:30 -0600 Subject: [PATCH] Create management portal in Flutter #39 --- web/repertory/lib/constants.dart | 7 + web/repertory/lib/main.dart | 178 +------ .../lib/screens/add_mount_screen.dart | 78 +++ .../lib/screens/edit_mount_screen.dart | 50 ++ web/repertory/lib/screens/home_screen.dart | 38 ++ .../lib/widgets/add_mount_widget.dart | 125 ----- web/repertory/lib/widgets/mount_settings.dart | 467 +++++++++++------- 7 files changed, 469 insertions(+), 474 deletions(-) create mode 100644 web/repertory/lib/screens/add_mount_screen.dart create mode 100644 web/repertory/lib/screens/edit_mount_screen.dart create mode 100644 web/repertory/lib/screens/home_screen.dart delete mode 100644 web/repertory/lib/widgets/add_mount_widget.dart diff --git a/web/repertory/lib/constants.dart b/web/repertory/lib/constants.dart index 4f8af733..2d3f1c98 100644 --- a/web/repertory/lib/constants.dart +++ b/web/repertory/lib/constants.dart @@ -1 +1,8 @@ +const String addMountTitle = 'New Mount Settings'; const String appTitle = 'Repertory Management Portal'; +const databaseTypeList = ['rocksdb', 'sqlite']; +const downloadTypeList = ['default', 'direct', 'ring_buffer']; +const eventLevelList = ['critical', 'error', 'warn', 'info', 'debug', 'trace']; +const protocolTypeList = ['http', 'https']; +const providerTypeList = ['Encrypt', 'Remote', 'S3', 'Sia']; +const ringBufferSizeList = ['128', '256', '512', '1024', '2048']; diff --git a/web/repertory/lib/main.dart b/web/repertory/lib/main.dart index aff9126c..a71dc6cb 100644 --- a/web/repertory/lib/main.dart +++ b/web/repertory/lib/main.dart @@ -4,9 +4,9 @@ import 'package:repertory/constants.dart' as constants; import 'package:repertory/helpers.dart'; import 'package:repertory/models/mount.dart'; import 'package:repertory/models/mount_list.dart'; -import 'package:repertory/widgets/add_mount_widget.dart'; -import 'package:repertory/widgets/mount_list_widget.dart'; -import 'package:repertory/widgets/mount_settings.dart'; +import 'package:repertory/screens/add_mount_screen.dart'; +import 'package:repertory/screens/edit_mount_screen.dart'; +import 'package:repertory/screens/home_screen.dart'; void main() { runApp( @@ -14,9 +14,14 @@ void main() { ); } -class MyApp extends StatelessWidget { +class MyApp extends StatefulWidget { const MyApp({super.key}); + @override + State createState() => _MyAppState(); +} + +class _MyAppState extends State { @override Widget build(context) { return MaterialApp( @@ -41,7 +46,11 @@ class MyApp extends StatelessWidget { ), ), initialRoute: '/', - routes: {'/': (context) => const MyHomePage(title: constants.appTitle)}, + routes: { + '/': (context) => const HomeScreen(title: constants.appTitle), + '/add': + (context) => const AddMountScreen(title: constants.addMountTitle), + }, onGenerateRoute: (settings) { if (settings.name != '/settings') { return null; @@ -50,14 +59,10 @@ class MyApp extends StatelessWidget { final mount = settings.arguments as Mount; return MaterialPageRoute( builder: (context) { - return Scaffold( - appBar: AppBar( - backgroundColor: Theme.of(context).colorScheme.inversePrimary, - title: Text( + return EditMountScreen( + mount: mount, + title: '${initialCaps(mount.type)} [${formatMountName(mount.type, mount.name)}] Settings', - ), - ), - body: MountSettingsWidget(mount: mount), ); }, ); @@ -65,152 +70,3 @@ class MyApp extends StatelessWidget { ); } } - -class MyHomePage extends StatefulWidget { - final String title; - const MyHomePage({super.key, required this.title}); - - @override - State createState() => _MyHomePageState(); -} - -class _MyHomePageState extends State { - bool _allowAdd = true; - String? _apiPassword; - String? _apiPort; - String? _bucket; - String? _encryptionToken; - String? _hostNameOrIp; - String _mountType = 'Encrypt'; - String _mountName = ""; - String? _path; - - void _resetData() { - _apiPassword = null; - _apiPort = null; - _bucket = null; - _encryptionToken = null; - _hostNameOrIp = null; - _mountName = ""; - _mountType = 'Encrypt'; - _path = null; - } - - void _updateData(String name, String? value) { - switch (name) { - case 'ApiPassword': - _apiPassword = value ?? ''; - return; - - case 'ApiPort': - _apiPort = value ?? ''; - return; - - case 'Bucket': - _bucket = value ?? ''; - return; - - case 'EncryptionToken': - _encryptionToken = value ?? ''; - return; - - case 'HostNameOrIp': - _hostNameOrIp = value ?? ''; - return; - - case 'Name': - _mountName = value ?? ''; - return; - - case 'Provider': - _mountType = value ?? 'Encrypt'; - return; - - case 'Path': - _path = value ?? ''; - return; - } - } - - @override - Widget build(context) { - return Scaffold( - appBar: AppBar( - backgroundColor: Theme.of(context).colorScheme.inversePrimary, - leading: const Icon(Icons.storage), - title: Text(widget.title), - ), - body: MountListWidget(), - floatingActionButton: FloatingActionButton( - onPressed: - _allowAdd - ? () async => showDialog( - context: context, - builder: (context) { - return AlertDialog( - title: const Text('Add Mount'), - content: Consumer( - builder: (_, MountList mountList, __) { - return AddMountWidget( - mountType: _mountType, - onDataChanged: _updateData, - ); - }, - ), - actions: [ - TextButton( - child: const Text('Cancel'), - onPressed: () { - _resetData(); - Navigator.of(context).pop(); - }, - ), - TextButton( - child: const Text('OK'), - onPressed: () { - setState(() => _allowAdd = false); - - Provider.of(context, listen: false) - .add( - _mountType, - _mountName, - apiPassword: _apiPassword, - apiPort: _apiPort, - bucket: _bucket, - encryptionToken: _encryptionToken, - hostNameOrIp: _hostNameOrIp, - path: _path, - ) - .then((_) { - _resetData(); - setState(() { - _allowAdd = true; - }); - }) - .catchError((_) { - setState(() => _allowAdd = true); - }); - - Navigator.of(context).pop(); - }, - ), - ], - ); - }, - ) - : null, - tooltip: 'Add Mount', - child: const Icon(Icons.add), - ), - ); - } - - @override - void setState(VoidCallback fn) { - if (!mounted) { - return; - } - - super.setState(fn); - } -} diff --git a/web/repertory/lib/screens/add_mount_screen.dart b/web/repertory/lib/screens/add_mount_screen.dart new file mode 100644 index 00000000..7e357395 --- /dev/null +++ b/web/repertory/lib/screens/add_mount_screen.dart @@ -0,0 +1,78 @@ +import 'package:flutter/material.dart'; +import 'package:repertory/constants.dart'; +import 'package:repertory/models/mount.dart'; +import 'package:repertory/widgets/mount_settings.dart'; + +class AddMountScreen extends StatefulWidget { + final String title; + const AddMountScreen({super.key, required this.title}); + + @override + State createState() => _AddMountScreenState(); +} + +class _AddMountScreenState extends State { + Mount? _mount; + String _mountType = ""; + bool _showAdvanced = false; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Theme.of(context).colorScheme.inversePrimary, + title: Text(widget.title), + actions: [ + Row( + children: [ + const Text("Advanced"), + IconButton( + icon: Icon(_showAdvanced ? Icons.toggle_on : Icons.toggle_off), + onPressed: () => setState(() => _showAdvanced = !_showAdvanced), + ), + ], + ), + ], + ), + body: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Text('Provider Type'), + const SizedBox(width: 15.0), + DropdownButton( + value: _mountType, + onChanged: (newValue) { + setState(() { + _mountType = newValue ?? ""; + if (_mountType.isNotEmpty) {} + }); + }, + items: + providerTypeList.map>((item) { + return DropdownMenuItem( + value: item, + child: Text(item), + ); + }).toList(), + ), + ], + ), + if (_mount != null) + MountSettingsWidget(mount: _mount!, showAdvanced: _showAdvanced), + ], + ), + ); + } + + @override + void setState(VoidCallback fn) { + if (!mounted) { + return; + } + + super.setState(fn); + } +} diff --git a/web/repertory/lib/screens/edit_mount_screen.dart b/web/repertory/lib/screens/edit_mount_screen.dart new file mode 100644 index 00000000..c375deda --- /dev/null +++ b/web/repertory/lib/screens/edit_mount_screen.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; +import 'package:repertory/models/mount.dart'; +import 'package:repertory/widgets/mount_settings.dart'; + +class EditMountScreen extends StatefulWidget { + final Mount mount; + final String title; + const EditMountScreen({super.key, required this.mount, required this.title}); + + @override + State createState() => _EditMountScreenState(); +} + +class _EditMountScreenState extends State { + bool _showAdvanced = false; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Theme.of(context).colorScheme.inversePrimary, + title: Text(widget.title), + actions: [ + Row( + children: [ + const Text("Advanced"), + IconButton( + icon: Icon(_showAdvanced ? Icons.toggle_on : Icons.toggle_off), + onPressed: () => setState(() => _showAdvanced = !_showAdvanced), + ), + ], + ), + ], + ), + body: MountSettingsWidget( + mount: widget.mount, + showAdvanced: _showAdvanced, + ), + ); + } + + @override + void setState(VoidCallback fn) { + if (!mounted) { + return; + } + + super.setState(fn); + } +} diff --git a/web/repertory/lib/screens/home_screen.dart b/web/repertory/lib/screens/home_screen.dart new file mode 100644 index 00000000..32d84d58 --- /dev/null +++ b/web/repertory/lib/screens/home_screen.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; +import 'package:repertory/widgets/mount_list_widget.dart'; + +class HomeScreen extends StatefulWidget { + final String title; + const HomeScreen({super.key, required this.title}); + + @override + State createState() => _HomeScreeState(); +} + +class _HomeScreeState extends State { + @override + Widget build(context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Theme.of(context).colorScheme.inversePrimary, + leading: const Icon(Icons.storage), + title: Text(widget.title), + ), + body: MountListWidget(), + floatingActionButton: FloatingActionButton( + onPressed: () => Navigator.pushNamed(context, '/add'), + tooltip: 'Add Mount', + child: const Icon(Icons.add), + ), + ); + } + + @override + void setState(VoidCallback fn) { + if (!mounted) { + return; + } + + super.setState(fn); + } +} diff --git a/web/repertory/lib/widgets/add_mount_widget.dart b/web/repertory/lib/widgets/add_mount_widget.dart deleted file mode 100644 index 591543ec..00000000 --- a/web/repertory/lib/widgets/add_mount_widget.dart +++ /dev/null @@ -1,125 +0,0 @@ -import 'package:flutter/material.dart'; - -class AddMountWidget extends StatefulWidget { - final String mountType; - final void Function(String name, String? value) onDataChanged; - - const AddMountWidget({ - super.key, - required this.mountType, - required this.onDataChanged, - }); - - @override - State createState() => _AddMountWidgetState(); -} - -class _AddMountWidgetState extends State { - static const _items = ['Encrypt', 'Remote', 'S3', 'Sia']; - static const _padding = 15.0; - - late String _mountType; - - List _createTextField( - String title, - String dataName, { - String? value, - }) { - if (value != null) { - widget.onDataChanged(dataName, value); - } - - return [ - const SizedBox(height: _padding), - Text( - title, - textAlign: TextAlign.left, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface, - fontWeight: FontWeight.bold, - ), - ), - TextField( - autofocus: dataName == 'Name', - decoration: InputDecoration(), - onChanged: (value) => widget.onDataChanged(dataName, value), - controller: TextEditingController(text: value), - ), - ]; - } - - @override - Widget build(BuildContext context) { - final mountTypeLower = _mountType.toLowerCase(); - - return Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Provider Type', - textAlign: TextAlign.left, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(width: _padding), - DropdownButton( - value: _mountType, - onChanged: (value) { - widget.onDataChanged('Provider', value); - setState(() { - _mountType = value ?? ""; - }); - }, - items: - _items.map>((item) { - return DropdownMenuItem( - value: item, - child: Text(item), - ); - }).toList(), - ), - ], - ), - if (mountTypeLower != 'remote') - ..._createTextField('Configuration Name', 'Name'), - if (mountTypeLower == 'encrypt') ..._createTextField('Path', 'Path'), - if (mountTypeLower == 'sia') - ..._createTextField('ApiPassword', 'ApiPassword'), - if (mountTypeLower == 's3' || mountTypeLower == 'sia') - ..._createTextField( - 'Bucket', - 'Bucket', - value: mountTypeLower == 'sia' ? 'default' : null, - ), - if (mountTypeLower == 'remote' || mountTypeLower == 'sia') - ..._createTextField( - 'HostNameOrIp', - 'HostNameOrIp', - value: 'localhost', - ), - if (mountTypeLower == 'remote' || mountTypeLower == 'sia') - ..._createTextField( - 'ApiPort', - 'ApiPort', - value: mountTypeLower == 'sia' ? '9980' : null, - ), - if (mountTypeLower == 'encrypt' || mountTypeLower == 'remote') - ..._createTextField('EncryptionToken', 'EncryptionToken'), - ], - ); - } - - @override - void initState() { - _mountType = widget.mountType; - super.initState(); - } -} diff --git a/web/repertory/lib/widgets/mount_settings.dart b/web/repertory/lib/widgets/mount_settings.dart index d49a9371..272e4109 100644 --- a/web/repertory/lib/widgets/mount_settings.dart +++ b/web/repertory/lib/widgets/mount_settings.dart @@ -3,12 +3,18 @@ import 'dart:convert'; import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:repertory/constants.dart'; import 'package:repertory/models/mount.dart'; import 'package:settings_ui/settings_ui.dart'; class MountSettingsWidget extends StatefulWidget { + final bool showAdvanced; final Mount mount; - const MountSettingsWidget({super.key, required this.mount}); + const MountSettingsWidget({ + super.key, + required this.mount, + required this.showAdvanced, + }); @override State createState() => _MountSettingsWidgetState(); @@ -17,71 +23,75 @@ class MountSettingsWidget extends StatefulWidget { class _MountSettingsWidgetState extends State { Map _settings = {}; - void _addBooleanSetting(list, root, key, value) { - list.add( - SettingsTile.switchTile( - leading: Icon(Icons.quiz), - title: Text(key), - initialValue: (value as bool), - onPressed: (_) { - setState(() { - root[key] = !value; - }); - }, - onToggle: (bool nextValue) { - setState(() { - root[key] = nextValue; - }); - }, - ), - ); + void _addBooleanSetting(list, root, key, value, isAdvanced) { + if (!isAdvanced || widget.showAdvanced) { + list.add( + SettingsTile.switchTile( + leading: Icon(Icons.quiz), + title: Text(key), + initialValue: (value as bool), + onPressed: (_) { + setState(() { + root[key] = !value; + }); + }, + onToggle: (bool nextValue) { + setState(() { + root[key] = nextValue; + }); + }, + ), + ); + } } - void _addIntSetting(list, root, key, value) { - list.add( - SettingsTile.navigation( - leading: Icon(Icons.onetwothree), - title: Text(key), - value: Text(value.toString()), - onPressed: (_) { - String updatedValue = value.toString(); - showDialog( - context: context, - builder: (context) { - return AlertDialog( - actions: [ - TextButton( - child: Text('Cancel'), - onPressed: () { - Navigator.of(context).pop(); + void _addIntSetting(list, root, key, value, isAdvanced) { + if (!isAdvanced || widget.showAdvanced) { + list.add( + SettingsTile.navigation( + leading: Icon(Icons.onetwothree), + title: Text(key), + value: Text(value.toString()), + onPressed: (_) { + String updatedValue = value.toString(); + showDialog( + context: context, + builder: (context) { + return AlertDialog( + actions: [ + TextButton( + child: Text('Cancel'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + TextButton( + child: Text('OK'), + onPressed: () { + setState(() { + root[key] = int.parse(updatedValue); + }); + Navigator.of(context).pop(); + }, + ), + ], + content: TextField( + autofocus: true, + controller: TextEditingController(text: updatedValue), + inputFormatters: [FilteringTextInputFormatter.digitsOnly], + keyboardType: TextInputType.number, + onChanged: (nextValue) { + updatedValue = nextValue; }, ), - TextButton( - child: Text('OK'), - onPressed: () { - setState(() { - root[key] = int.parse(updatedValue); - }); - Navigator.of(context).pop(); - }, - ), - ], - content: TextField( - autofocus: true, - controller: TextEditingController(text: updatedValue), - inputFormatters: [FilteringTextInputFormatter.digitsOnly], - keyboardType: TextInputType.number, - onChanged: (nextValue) { - updatedValue = nextValue; - }, - ), - title: Text(key), - ); - }, - ); - }, - ), - ); + title: Text(key), + ); + }, + ); + }, + ), + ); + } } void _addIntListSetting( @@ -92,101 +102,124 @@ class _MountSettingsWidgetState extends State { List valueList, defaultValue, icon, + isAdvanced, ) { - list.add( - SettingsTile.navigation( - title: Text(key), - leading: Icon(icon), - value: DropdownButton( - value: value.toString(), - onChanged: (newValue) { - setState(() { - root[key] = int.parse(newValue ?? defaultValue.toString()); - }); - }, - items: - valueList.map>((item) { - return DropdownMenuItem(value: item, child: Text(item)); - }).toList(), - ), - ), - ); - } - - void _addListSetting(list, root, key, value, List valueList, icon) { - list.add( - SettingsTile.navigation( - title: Text(key), - leading: Icon(icon), - value: DropdownButton( - value: value, - onChanged: (newValue) { - setState(() { - root[key] = newValue; - }); - }, - items: - valueList.map>((item) { - return DropdownMenuItem(value: item, child: Text(item)); - }).toList(), - ), - ), - ); - } - - void _addPasswordSetting(list, root, key, value) { - list.add( - SettingsTile.navigation( - leading: Icon(Icons.password), - title: Text(key), - value: Text('*' * (value as String).length), - ), - ); - } - - void _addStringSetting(list, root, key, value, icon) { - list.add( - SettingsTile.navigation( - leading: Icon(icon), - title: Text(key), - value: Text(value), - onPressed: (_) { - String updatedValue = value; - showDialog( - context: context, - builder: (context) { - return AlertDialog( - actions: [ - TextButton( - child: Text('Cancel'), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - TextButton( - child: Text('OK'), - onPressed: () { - setState(() { - root[key] = updatedValue; - }); - Navigator.of(context).pop(); - }, - ), - ], - content: TextField( - autofocus: true, - controller: TextEditingController(text: updatedValue), - onChanged: (value) { - updatedValue = value; - }, - ), - title: Text(key), - ); + if (!isAdvanced || widget.showAdvanced) { + list.add( + SettingsTile.navigation( + title: Text(key), + leading: Icon(icon), + value: DropdownButton( + value: value.toString(), + onChanged: (newValue) { + setState(() { + root[key] = int.parse(newValue ?? defaultValue.toString()); + }); }, - ); - }, - ), - ); + items: + valueList.map>((item) { + return DropdownMenuItem( + value: item, + child: Text(item), + ); + }).toList(), + ), + ), + ); + } + } + + void _addListSetting( + list, + root, + key, + value, + List valueList, + icon, + isAdvanced, + ) { + if (!isAdvanced || widget.showAdvanced) { + list.add( + SettingsTile.navigation( + title: Text(key), + leading: Icon(icon), + value: DropdownButton( + value: value, + onChanged: (newValue) { + setState(() { + root[key] = newValue; + }); + }, + items: + valueList.map>((item) { + return DropdownMenuItem( + value: item, + child: Text(item), + ); + }).toList(), + ), + ), + ); + } + } + + void _addPasswordSetting(list, root, key, value, isAdvanced) { + if (!isAdvanced || widget.showAdvanced) { + list.add( + SettingsTile.navigation( + leading: Icon(Icons.password), + title: Text(key), + value: Text('*' * (value as String).length), + ), + ); + } + } + + void _addStringSetting(list, root, key, value, icon, isAdvanced) { + if (!isAdvanced || widget.showAdvanced) { + list.add( + SettingsTile.navigation( + leading: Icon(icon), + title: Text(key), + value: Text(value), + onPressed: (_) { + String updatedValue = value; + showDialog( + context: context, + builder: (context) { + return AlertDialog( + actions: [ + TextButton( + child: Text('Cancel'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + TextButton( + child: Text('OK'), + onPressed: () { + setState(() { + root[key] = updatedValue; + }); + Navigator.of(context).pop(); + }, + ), + ], + content: TextField( + autofocus: true, + controller: TextEditingController(text: updatedValue), + onChanged: (value) { + updatedValue = value; + }, + ), + title: Text(key), + ); + }, + ); + }, + ), + ); + } } @override @@ -201,58 +234,76 @@ class _MountSettingsWidgetState extends State { _settings.forEach((key, value) { if (key == 'ApiAuth') { - _addPasswordSetting(commonSettings, _settings, key, value); + _addPasswordSetting(commonSettings, _settings, key, value, true); } else if (key == 'ApiPort') { - _addIntSetting(commonSettings, _settings, key, value); + _addIntSetting(commonSettings, _settings, key, value, true); } else if (key == 'ApiUser') { - _addStringSetting(commonSettings, _settings, key, value, Icons.person); + _addStringSetting( + commonSettings, + _settings, + key, + value, + Icons.person, + true, + ); } else if (key == 'DatabaseType') { - _addListSetting(commonSettings, _settings, key, value, [ - 'rocksdb', - 'sqlite', - ], Icons.dataset); + _addListSetting( + commonSettings, + _settings, + key, + value, + databaseTypeList, + Icons.dataset, + true, + ); } else if (key == 'DownloadTimeoutSeconds') { - _addIntSetting(commonSettings, _settings, key, value); + _addIntSetting(commonSettings, _settings, key, value, true); } else if (key == 'EnableDownloadTimeout') { - _addBooleanSetting(commonSettings, _settings, key, value); + _addBooleanSetting(commonSettings, _settings, key, value, true); } else if (key == 'EnableDriveEvents') { - _addBooleanSetting(commonSettings, _settings, key, value); + _addBooleanSetting(commonSettings, _settings, key, value, true); } else if (key == 'EventLevel') { - _addListSetting(commonSettings, _settings, key, value, [ - 'critical', - 'error', - 'warn', - 'info', - 'debug', - 'trace', - ], Icons.event); + _addListSetting( + commonSettings, + _settings, + key, + value, + eventLevelList, + Icons.event, + false, + ); } else if (key == 'EvictionDelayMinutes') { - _addIntSetting(commonSettings, _settings, key, value); + _addIntSetting(commonSettings, _settings, key, value, true); } else if (key == 'EvictionUseAccessedTime') { - _addBooleanSetting(commonSettings, _settings, key, value); + _addBooleanSetting(commonSettings, _settings, key, value, true); } else if (key == 'MaxCacheSizeBytes') { - _addIntSetting(commonSettings, _settings, key, value); + _addIntSetting(commonSettings, _settings, key, value, false); } else if (key == 'MaxUploadCount') { - _addIntSetting(commonSettings, _settings, key, value); + _addIntSetting(commonSettings, _settings, key, value, true); } else if (key == 'OnlineCheckRetrySeconds') { - _addIntSetting(commonSettings, _settings, key, value); + _addIntSetting(commonSettings, _settings, key, value, true); } else if (key == 'PreferredDownloadType') { - _addListSetting(commonSettings, _settings, key, value, [ - 'default', - 'direct', - 'ring_buffer', - ], Icons.download); + _addListSetting( + commonSettings, + _settings, + key, + value, + downloadTypeList, + Icons.download, + false, + ); } else if (key == 'RetryReadCount') { - _addIntSetting(commonSettings, _settings, key, value); + _addIntSetting(commonSettings, _settings, key, value, true); } else if (key == 'RingBufferFileSize') { _addIntListSetting( commonSettings, _settings, key, value, - ['128', '256', '512', '1024', '2048'], + ringBufferSizeList, 512, Icons.animation, + false, ); } else if (key == 'EncryptConfig') { value.forEach((subKey, subValue) { @@ -262,6 +313,7 @@ class _MountSettingsWidgetState extends State { _settings[key], subKey, subValue, + false, ); } else if (subKey == 'Path') { _addStringSetting( @@ -270,6 +322,7 @@ class _MountSettingsWidgetState extends State { subKey, subValue, Icons.folder, + false, ); } }); @@ -282,6 +335,7 @@ class _MountSettingsWidgetState extends State { subKey, subValue, Icons.support_agent, + true, ); } else if (subKey == 'ApiPassword') { _addPasswordSetting( @@ -289,6 +343,7 @@ class _MountSettingsWidgetState extends State { _settings[key], subKey, subValue, + false, ); } else if (subKey == 'ApiPort') { _addIntSetting( @@ -296,6 +351,7 @@ class _MountSettingsWidgetState extends State { _settings[key], subKey, subValue, + false, ); } else if (subKey == 'ApiUser') { _addStringSetting( @@ -304,6 +360,7 @@ class _MountSettingsWidgetState extends State { subKey, subValue, Icons.person, + true, ); } else if (subKey == 'HostNameOrIp') { _addStringSetting( @@ -312,6 +369,7 @@ class _MountSettingsWidgetState extends State { subKey, subValue, Icons.computer, + false, ); } else if (subKey == 'Path') { _addStringSetting( @@ -320,6 +378,7 @@ class _MountSettingsWidgetState extends State { subKey, subValue, Icons.route, + true, ); } else if (subKey == 'Protocol') { _addListSetting( @@ -327,8 +386,9 @@ class _MountSettingsWidgetState extends State { _settings[key], subKey, subValue, - ['http', 'https'], + protocolTypeList, Icons.http, + true, ); } else if (subKey == 'TimeoutMs') { _addIntSetting( @@ -336,6 +396,7 @@ class _MountSettingsWidgetState extends State { _settings[key], subKey, subValue, + true, ); } }); @@ -347,6 +408,7 @@ class _MountSettingsWidgetState extends State { _settings[key], subKey, subValue, + false, ); } else if (subKey == 'EncryptionToken') { _addPasswordSetting( @@ -354,6 +416,7 @@ class _MountSettingsWidgetState extends State { _settings[key], subKey, subValue, + false, ); } else if (subKey == 'HostNameOrIp') { _addStringSetting( @@ -362,6 +425,7 @@ class _MountSettingsWidgetState extends State { subKey, subValue, Icons.computer, + false, ); } else if (subKey == 'MaxConnections') { _addIntSetting( @@ -369,6 +433,7 @@ class _MountSettingsWidgetState extends State { _settings[key], subKey, subValue, + true, ); } else if (subKey == 'ReceiveTimeoutMs') { _addIntSetting( @@ -376,6 +441,7 @@ class _MountSettingsWidgetState extends State { _settings[key], subKey, subValue, + true, ); } else if (subKey == 'SendTimeoutMs') { _addIntSetting( @@ -383,6 +449,7 @@ class _MountSettingsWidgetState extends State { _settings[key], subKey, subValue, + true, ); } }); @@ -390,7 +457,13 @@ class _MountSettingsWidgetState extends State { value.forEach((subKey, subValue) { if (subKey == 'Enable') { List tempSettings = []; - _addBooleanSetting(tempSettings, _settings[key], subKey, subValue); + _addBooleanSetting( + tempSettings, + _settings[key], + subKey, + subValue, + false, + ); remoteMountSettings.insertAll(0, tempSettings); } else if (subKey == 'ApiPort') { _addIntSetting( @@ -398,6 +471,7 @@ class _MountSettingsWidgetState extends State { _settings[key], subKey, subValue, + false, ); } else if (subKey == 'ClientPoolSize') { _addIntSetting( @@ -405,6 +479,7 @@ class _MountSettingsWidgetState extends State { _settings[key], subKey, subValue, + true, ); } else if (subKey == 'EncryptionToken') { _addPasswordSetting( @@ -412,6 +487,7 @@ class _MountSettingsWidgetState extends State { _settings[key], subKey, subValue, + false, ); } }); @@ -423,6 +499,7 @@ class _MountSettingsWidgetState extends State { _settings[key], subKey, subValue, + false, ); } else if (subKey == 'Bucket') { _addStringSetting( @@ -431,6 +508,7 @@ class _MountSettingsWidgetState extends State { subKey, subValue, Icons.folder, + false, ); } else if (subKey == 'EncryptionToken') { _addPasswordSetting( @@ -438,6 +516,7 @@ class _MountSettingsWidgetState extends State { _settings[key], subKey, subValue, + false, ); } else if (subKey == 'Region') { _addStringSetting( @@ -446,6 +525,7 @@ class _MountSettingsWidgetState extends State { subKey, subValue, Icons.map, + false, ); } else if (subKey == 'SecretKey') { _addPasswordSetting( @@ -453,9 +533,16 @@ class _MountSettingsWidgetState extends State { _settings[key], subKey, subValue, + false, ); } else if (subKey == 'TimeoutMs') { - _addIntSetting(s3ConfigSettings, _settings[key], subKey, subValue); + _addIntSetting( + s3ConfigSettings, + _settings[key], + subKey, + subValue, + true, + ); } else if (subKey == 'URL') { _addStringSetting( s3ConfigSettings, @@ -463,6 +550,7 @@ class _MountSettingsWidgetState extends State { subKey, subValue, Icons.http, + false, ); } else if (subKey == 'UsePathStyle') { _addBooleanSetting( @@ -470,6 +558,7 @@ class _MountSettingsWidgetState extends State { _settings[key], subKey, subValue, + false, ); } else if (subKey == 'UseRegionInURL') { _addBooleanSetting( @@ -477,6 +566,7 @@ class _MountSettingsWidgetState extends State { _settings[key], subKey, subValue, + false, ); } }); @@ -489,6 +579,7 @@ class _MountSettingsWidgetState extends State { subKey, subValue, Icons.folder, + false, ); } });