Compare commits
13 Commits
847bf68f85
...
94073fe1f1
Author | SHA1 | Date | |
---|---|---|---|
94073fe1f1 | |||
992a02a6ee | |||
6f45848db4 | |||
918d7172ec | |||
8da6008e29 | |||
d2065af398 | |||
b4fd093e7c | |||
5e47cdb861 | |||
eb8f66ebe9 | |||
72a2567c83 | |||
c1e5bd6b0b | |||
02157d21ea | |||
0318489b6c |
@ -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'];
|
||||
|
@ -4,6 +4,7 @@ String formatMountName(String type, String name) {
|
||||
if (type == 'remote') {
|
||||
return name.replaceAll('_', ':');
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
@ -11,6 +12,7 @@ String getBaseUri() {
|
||||
if (kDebugMode || !kIsWeb) {
|
||||
return 'http://127.0.0.1:30000';
|
||||
}
|
||||
|
||||
return Uri.base.origin;
|
||||
}
|
||||
|
||||
@ -25,3 +27,37 @@ String initialCaps(String txt) {
|
||||
|
||||
return txt[0].toUpperCase() + txt.substring(1).toLowerCase();
|
||||
}
|
||||
|
||||
Map<String, dynamic> createDefaultSettings(String mountType) {
|
||||
switch (mountType) {
|
||||
case 'Encrypt':
|
||||
return {
|
||||
'EncryptConfig': {'EncryptionToken': '', 'Path': ''},
|
||||
};
|
||||
case 'Remote':
|
||||
return {'EventLevel': 'info'};
|
||||
case 'S3':
|
||||
return {
|
||||
'S3Config': {
|
||||
'AccessKey': '',
|
||||
'Bucket': '',
|
||||
'Region': 'any',
|
||||
'SecretKey': '',
|
||||
'URL': '',
|
||||
'UsePathStyle': false,
|
||||
'UseRegionInURL': false,
|
||||
},
|
||||
};
|
||||
case 'Sia':
|
||||
return {
|
||||
'HostConfig': {
|
||||
'ApiPassword': '',
|
||||
'ApiPort': '9980',
|
||||
'HostNameOrIp': 'localhost',
|
||||
},
|
||||
'SiaConfig': {'Bucket': 'default'},
|
||||
};
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
@ -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<MyApp> createState() => _MyAppState();
|
||||
}
|
||||
|
||||
class _MyAppState extends State<MyApp> {
|
||||
@override
|
||||
Widget build(context) {
|
||||
return MaterialApp(
|
||||
@ -41,23 +46,23 @@ 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') {
|
||||
if (settings.name != '/edit') {
|
||||
return null;
|
||||
}
|
||||
|
||||
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<MyHomePage> createState() => _MyHomePageState();
|
||||
}
|
||||
|
||||
class _MyHomePageState extends State<MyHomePage> {
|
||||
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<MountList>(
|
||||
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<MountList>(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);
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,10 @@ import 'package:repertory/types/mount_config.dart';
|
||||
|
||||
class Mount with ChangeNotifier {
|
||||
final MountConfig mountConfig;
|
||||
Mount(this.mountConfig) {
|
||||
Mount(this.mountConfig, {isAdd = false}) {
|
||||
if (isAdd) {
|
||||
return;
|
||||
}
|
||||
refresh();
|
||||
}
|
||||
|
||||
@ -17,48 +20,60 @@ class Mount with ChangeNotifier {
|
||||
String get type => mountConfig.type;
|
||||
|
||||
Future<void> _fetch() async {
|
||||
final response = await http.get(
|
||||
Uri.parse(
|
||||
Uri.encodeFull('${getBaseUri()}/api/v1/mount?name=$name&type=$type'),
|
||||
),
|
||||
);
|
||||
try {
|
||||
final response = await http.get(
|
||||
Uri.parse(
|
||||
Uri.encodeFull('${getBaseUri()}/api/v1/mount?name=$name&type=$type'),
|
||||
),
|
||||
);
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
return;
|
||||
if (response.statusCode != 200) {
|
||||
return;
|
||||
}
|
||||
|
||||
mountConfig.updateSettings(jsonDecode(response.body));
|
||||
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
debugPrint('$e');
|
||||
}
|
||||
|
||||
mountConfig.updateSettings(jsonDecode(response.body));
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> _fetchStatus() async {
|
||||
final response = await http.get(
|
||||
Uri.parse(
|
||||
Uri.encodeFull(
|
||||
'${getBaseUri()}/api/v1/mount_status?name=$name&type=$type',
|
||||
try {
|
||||
final response = await http.get(
|
||||
Uri.parse(
|
||||
Uri.encodeFull(
|
||||
'${getBaseUri()}/api/v1/mount_status?name=$name&type=$type',
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
);
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
return;
|
||||
if (response.statusCode != 200) {
|
||||
return;
|
||||
}
|
||||
|
||||
mountConfig.updateStatus(jsonDecode(response.body));
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
debugPrint('$e');
|
||||
}
|
||||
|
||||
mountConfig.updateStatus(jsonDecode(response.body));
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> mount(bool unmount, {String? location}) async {
|
||||
await http.post(
|
||||
Uri.parse(
|
||||
Uri.encodeFull(
|
||||
'${getBaseUri()}/api/v1/mount?unmount=$unmount&name=$name&type=$type&location=$location',
|
||||
try {
|
||||
await http.post(
|
||||
Uri.parse(
|
||||
Uri.encodeFull(
|
||||
'${getBaseUri()}/api/v1/mount?unmount=$unmount&name=$name&type=$type&location=$location',
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
);
|
||||
|
||||
return refresh();
|
||||
return refresh();
|
||||
} catch (e) {
|
||||
debugPrint('$e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> refresh() async {
|
||||
@ -67,30 +82,40 @@ class Mount with ChangeNotifier {
|
||||
}
|
||||
|
||||
Future<void> setValue(String key, String value) async {
|
||||
await http.put(
|
||||
Uri.parse(
|
||||
Uri.encodeFull(
|
||||
'${getBaseUri()}/api/v1/set_value_by_name?name=$name&type=$type&key=$key&value=$value',
|
||||
try {
|
||||
await http.put(
|
||||
Uri.parse(
|
||||
Uri.encodeFull(
|
||||
'${getBaseUri()}/api/v1/set_value_by_name?name=$name&type=$type&key=$key&value=$value',
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
);
|
||||
|
||||
return refresh();
|
||||
return refresh();
|
||||
} catch (e) {
|
||||
debugPrint('$e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<String?> getMountLocation() async {
|
||||
final response = await http.get(
|
||||
Uri.parse(
|
||||
Uri.encodeFull(
|
||||
'${getBaseUri()}/api/v1/get_mount_location?name=$name&type=$type',
|
||||
try {
|
||||
final response = await http.get(
|
||||
Uri.parse(
|
||||
Uri.encodeFull(
|
||||
'${getBaseUri()}/api/v1/get_mount_location?name=$name&type=$type',
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
);
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
return null;
|
||||
if (response.statusCode != 200) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return jsonDecode(response.body)['Location'] as String;
|
||||
} catch (e) {
|
||||
debugPrint('$e');
|
||||
}
|
||||
|
||||
return jsonDecode(response.body)['Location'] as String;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -17,11 +17,14 @@ class MountList with ChangeNotifier {
|
||||
UnmodifiableListView<MountConfig>(_mountList);
|
||||
|
||||
Future<void> _fetch() async {
|
||||
final response = await http.get(
|
||||
Uri.parse('${getBaseUri()}/api/v1/mount_list'),
|
||||
);
|
||||
try {
|
||||
final response = await http.get(
|
||||
Uri.parse('${getBaseUri()}/api/v1/mount_list'),
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
if (response.statusCode != 200) {
|
||||
return;
|
||||
}
|
||||
List<MountConfig> nextList = [];
|
||||
|
||||
jsonDecode(response.body).forEach((key, value) {
|
||||
@ -33,7 +36,8 @@ class MountList with ChangeNotifier {
|
||||
_mountList = nextList;
|
||||
|
||||
notifyListeners();
|
||||
return;
|
||||
} catch (e) {
|
||||
debugPrint('$e');
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,25 +54,22 @@ class MountList with ChangeNotifier {
|
||||
|
||||
Future<void> add(
|
||||
String type,
|
||||
String name, {
|
||||
String? apiPassword,
|
||||
String? apiPort,
|
||||
String? bucket,
|
||||
String? encryptionToken,
|
||||
String? hostNameOrIp,
|
||||
String? path,
|
||||
}) async {
|
||||
await http.post(
|
||||
Uri.parse(
|
||||
Uri.encodeFull(
|
||||
'${getBaseUri()}/api/v1/add_mount?name=$name&type=$type&bucket=$bucket'
|
||||
'&path=$path&apiPassword=$apiPassword&apiPort=$apiPort&hostNameOrIp=$hostNameOrIp'
|
||||
'&encryptionToken=$encryptionToken',
|
||||
String name,
|
||||
Map<String, dynamic> mountConfig,
|
||||
) async {
|
||||
try {
|
||||
await http.post(
|
||||
Uri.parse(
|
||||
Uri.encodeFull(
|
||||
'${getBaseUri()}/api/v1/add_mount?name=$name&type=$type&config=${jsonEncode(mountConfig)}',
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
);
|
||||
|
||||
return _fetch();
|
||||
return _fetch();
|
||||
} catch (e) {
|
||||
debugPrint('$e');
|
||||
}
|
||||
}
|
||||
|
||||
void remove(String name) {
|
||||
|
165
web/repertory/lib/screens/add_mount_screen.dart
Normal file
165
web/repertory/lib/screens/add_mount_screen.dart
Normal file
@ -0,0 +1,165 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:repertory/constants.dart';
|
||||
import 'package:repertory/helpers.dart';
|
||||
import 'package:repertory/models/mount.dart';
|
||||
import 'package:repertory/models/mount_list.dart';
|
||||
import 'package:repertory/types/mount_config.dart';
|
||||
import 'package:repertory/widgets/mount_settings.dart';
|
||||
|
||||
class AddMountScreen extends StatefulWidget {
|
||||
final String title;
|
||||
const AddMountScreen({super.key, required this.title});
|
||||
|
||||
@override
|
||||
State<AddMountScreen> createState() => _AddMountScreenState();
|
||||
}
|
||||
|
||||
class _AddMountScreenState extends State<AddMountScreen> {
|
||||
static const _padding = 15.0;
|
||||
|
||||
Mount? _mount;
|
||||
final _mountNameController = TextEditingController();
|
||||
String _mountType = "";
|
||||
final Map<String, Map<String, dynamic>> _settings = {
|
||||
"": {},
|
||||
"Encrypt": createDefaultSettings("Encrypt"),
|
||||
"Remote": createDefaultSettings("Remote"),
|
||||
"S3": createDefaultSettings("S3"),
|
||||
"Sia": createDefaultSettings("Sia"),
|
||||
};
|
||||
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: Padding(
|
||||
padding: const EdgeInsets.all(_padding),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(_padding),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Text('Provider Type'),
|
||||
const SizedBox(width: _padding),
|
||||
DropdownButton<String>(
|
||||
value: _mountType,
|
||||
onChanged: (mountType) => _handleChange(mountType ?? ''),
|
||||
items:
|
||||
providerTypeList.map<DropdownMenuItem<String>>((
|
||||
item,
|
||||
) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: item,
|
||||
child: Text(item),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
if (_mountType.isNotEmpty) const SizedBox(height: _padding),
|
||||
if (_mountType.isNotEmpty)
|
||||
Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(_padding),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Text('Configuration Name'),
|
||||
const SizedBox(width: _padding),
|
||||
TextField(
|
||||
autofocus: true,
|
||||
controller: _mountNameController,
|
||||
keyboardType: TextInputType.text,
|
||||
onChanged: (_) => _handleChange(_mountType),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
if (_mount != null)
|
||||
Expanded(
|
||||
child: Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(_padding),
|
||||
child: MountSettingsWidget(
|
||||
isAdd: true,
|
||||
mount: _mount!,
|
||||
settings: _settings[_mountType]!,
|
||||
showAdvanced: _showAdvanced,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (_mount != null)
|
||||
ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
Provider.of<MountList>(context, listen: false).add(
|
||||
_mountType,
|
||||
_mountNameController.text,
|
||||
_settings[_mountType]!,
|
||||
);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
label: const Text('Add'),
|
||||
icon: Icon(Icons.add),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _handleChange(String mountType) {
|
||||
setState(() {
|
||||
_mountType = mountType;
|
||||
_mount =
|
||||
(_mountNameController.text.isEmpty)
|
||||
? null
|
||||
: Mount(
|
||||
MountConfig(
|
||||
name: _mountNameController.text,
|
||||
settings: _settings[mountType],
|
||||
type: mountType,
|
||||
),
|
||||
isAdd: true,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void setState(VoidCallback fn) {
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
super.setState(fn);
|
||||
}
|
||||
}
|
53
web/repertory/lib/screens/edit_mount_screen.dart
Normal file
53
web/repertory/lib/screens/edit_mount_screen.dart
Normal file
@ -0,0 +1,53 @@
|
||||
import 'dart:convert';
|
||||
|
||||
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<EditMountScreen> createState() => _EditMountScreenState();
|
||||
}
|
||||
|
||||
class _EditMountScreenState extends State<EditMountScreen> {
|
||||
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,
|
||||
settings: jsonDecode(jsonEncode(widget.mount.mountConfig.settings)),
|
||||
showAdvanced: _showAdvanced,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void setState(VoidCallback fn) {
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
super.setState(fn);
|
||||
}
|
||||
}
|
38
web/repertory/lib/screens/home_screen.dart
Normal file
38
web/repertory/lib/screens/home_screen.dart
Normal file
@ -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<HomeScreen> createState() => _HomeScreeState();
|
||||
}
|
||||
|
||||
class _HomeScreeState extends State<HomeScreen> {
|
||||
@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);
|
||||
}
|
||||
}
|
@ -7,7 +7,13 @@ class MountConfig {
|
||||
Map<String, dynamic> _settings = {};
|
||||
IconData _state = Icons.toggle_off;
|
||||
final String _type;
|
||||
MountConfig({required name, required type}) : _name = name, _type = type;
|
||||
MountConfig({required name, required type, Map<String, dynamic>? settings})
|
||||
: _name = name,
|
||||
_type = type {
|
||||
if (settings != null) {
|
||||
_settings = settings;
|
||||
}
|
||||
}
|
||||
|
||||
String get name => _name;
|
||||
String get path => _path;
|
||||
|
@ -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<AddMountWidget> createState() => _AddMountWidgetState();
|
||||
}
|
||||
|
||||
class _AddMountWidgetState extends State<AddMountWidget> {
|
||||
static const _items = <String>['Encrypt', 'Remote', 'S3', 'Sia'];
|
||||
static const _padding = 15.0;
|
||||
|
||||
late String _mountType;
|
||||
|
||||
List<Widget> _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<String>(
|
||||
value: _mountType,
|
||||
onChanged: (value) {
|
||||
widget.onDataChanged('Provider', value);
|
||||
setState(() {
|
||||
_mountType = value ?? "";
|
||||
});
|
||||
},
|
||||
items:
|
||||
_items.map<DropdownMenuItem<String>>((item) {
|
||||
return DropdownMenuItem<String>(
|
||||
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();
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@ class MountListWidget extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<MountList>(
|
||||
builder: (context, mountList, _) {
|
||||
builder: (context, MountList mountList, _) {
|
||||
return ListView.builder(
|
||||
itemBuilder: (context, idx) {
|
||||
return ChangeNotifierProvider(
|
||||
|
@ -1,87 +1,102 @@
|
||||
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 isAdd;
|
||||
final bool showAdvanced;
|
||||
final Mount mount;
|
||||
const MountSettingsWidget({super.key, required this.mount});
|
||||
final Function? onChanged;
|
||||
final Map<String, dynamic> settings;
|
||||
const MountSettingsWidget({
|
||||
super.key,
|
||||
this.isAdd = false,
|
||||
required this.mount,
|
||||
this.onChanged,
|
||||
required this.settings,
|
||||
required this.showAdvanced,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MountSettingsWidget> createState() => _MountSettingsWidgetState();
|
||||
}
|
||||
|
||||
class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
Map<String, dynamic> _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;
|
||||
widget.onChanged?.call(widget.settings);
|
||||
});
|
||||
},
|
||||
onToggle: (bool nextValue) {
|
||||
setState(() {
|
||||
root[key] = nextValue;
|
||||
widget.onChanged?.call(widget.settings);
|
||||
});
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
widget.onChanged?.call(widget.settings);
|
||||
});
|
||||
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 +107,127 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
List<String> valueList,
|
||||
defaultValue,
|
||||
icon,
|
||||
isAdvanced,
|
||||
) {
|
||||
list.add(
|
||||
SettingsTile.navigation(
|
||||
title: Text(key),
|
||||
leading: Icon(icon),
|
||||
value: DropdownButton<String>(
|
||||
value: value.toString(),
|
||||
onChanged: (newValue) {
|
||||
setState(() {
|
||||
root[key] = int.parse(newValue ?? defaultValue.toString());
|
||||
});
|
||||
},
|
||||
items:
|
||||
valueList.map<DropdownMenuItem<String>>((item) {
|
||||
return DropdownMenuItem<String>(value: item, child: Text(item));
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _addListSetting(list, root, key, value, List<String> valueList, icon) {
|
||||
list.add(
|
||||
SettingsTile.navigation(
|
||||
title: Text(key),
|
||||
leading: Icon(icon),
|
||||
value: DropdownButton<String>(
|
||||
value: value,
|
||||
onChanged: (newValue) {
|
||||
setState(() {
|
||||
root[key] = newValue;
|
||||
});
|
||||
},
|
||||
items:
|
||||
valueList.map<DropdownMenuItem<String>>((item) {
|
||||
return DropdownMenuItem<String>(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<String>(
|
||||
value: value.toString(),
|
||||
onChanged: (newValue) {
|
||||
setState(() {
|
||||
root[key] = int.parse(newValue ?? defaultValue.toString());
|
||||
widget.onChanged?.call(widget.settings);
|
||||
});
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
items:
|
||||
valueList.map<DropdownMenuItem<String>>((item) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: item,
|
||||
child: Text(item),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void _addListSetting(
|
||||
list,
|
||||
root,
|
||||
key,
|
||||
value,
|
||||
List<String> valueList,
|
||||
icon,
|
||||
isAdvanced,
|
||||
) {
|
||||
if (!isAdvanced || widget.showAdvanced) {
|
||||
list.add(
|
||||
SettingsTile.navigation(
|
||||
title: Text(key),
|
||||
leading: Icon(icon),
|
||||
value: DropdownButton<String>(
|
||||
value: value,
|
||||
onChanged: (newValue) {
|
||||
setState(() {
|
||||
root[key] = newValue;
|
||||
widget.onChanged?.call(widget.settings);
|
||||
});
|
||||
},
|
||||
items:
|
||||
valueList.map<DropdownMenuItem<String>>((item) {
|
||||
return DropdownMenuItem<String>(
|
||||
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;
|
||||
widget.onChanged?.call(widget.settings);
|
||||
});
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
content: TextField(
|
||||
autofocus: true,
|
||||
controller: TextEditingController(text: updatedValue),
|
||||
onChanged: (value) {
|
||||
updatedValue = value;
|
||||
},
|
||||
),
|
||||
title: Text(key),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@ -199,77 +240,97 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
List<SettingsTile> s3ConfigSettings = [];
|
||||
List<SettingsTile> siaConfigSettings = [];
|
||||
|
||||
_settings.forEach((key, value) {
|
||||
widget.settings.forEach((key, value) {
|
||||
if (key == 'ApiAuth') {
|
||||
_addPasswordSetting(commonSettings, _settings, key, value);
|
||||
_addPasswordSetting(commonSettings, widget.settings, key, value, true);
|
||||
} else if (key == 'ApiPort') {
|
||||
_addIntSetting(commonSettings, _settings, key, value);
|
||||
_addIntSetting(commonSettings, widget.settings, key, value, true);
|
||||
} else if (key == 'ApiUser') {
|
||||
_addStringSetting(commonSettings, _settings, key, value, Icons.person);
|
||||
_addStringSetting(
|
||||
commonSettings,
|
||||
widget.settings,
|
||||
key,
|
||||
value,
|
||||
Icons.person,
|
||||
true,
|
||||
);
|
||||
} else if (key == 'DatabaseType') {
|
||||
_addListSetting(commonSettings, _settings, key, value, [
|
||||
'rocksdb',
|
||||
'sqlite',
|
||||
], Icons.dataset);
|
||||
_addListSetting(
|
||||
commonSettings,
|
||||
widget.settings,
|
||||
key,
|
||||
value,
|
||||
databaseTypeList,
|
||||
Icons.dataset,
|
||||
true,
|
||||
);
|
||||
} else if (key == 'DownloadTimeoutSeconds') {
|
||||
_addIntSetting(commonSettings, _settings, key, value);
|
||||
_addIntSetting(commonSettings, widget.settings, key, value, true);
|
||||
} else if (key == 'EnableDownloadTimeout') {
|
||||
_addBooleanSetting(commonSettings, _settings, key, value);
|
||||
_addBooleanSetting(commonSettings, widget.settings, key, value, true);
|
||||
} else if (key == 'EnableDriveEvents') {
|
||||
_addBooleanSetting(commonSettings, _settings, key, value);
|
||||
_addBooleanSetting(commonSettings, widget.settings, key, value, true);
|
||||
} else if (key == 'EventLevel') {
|
||||
_addListSetting(commonSettings, _settings, key, value, [
|
||||
'critical',
|
||||
'error',
|
||||
'warn',
|
||||
'info',
|
||||
'debug',
|
||||
'trace',
|
||||
], Icons.event);
|
||||
_addListSetting(
|
||||
commonSettings,
|
||||
widget.settings,
|
||||
key,
|
||||
value,
|
||||
eventLevelList,
|
||||
Icons.event,
|
||||
false,
|
||||
);
|
||||
} else if (key == 'EvictionDelayMinutes') {
|
||||
_addIntSetting(commonSettings, _settings, key, value);
|
||||
_addIntSetting(commonSettings, widget.settings, key, value, true);
|
||||
} else if (key == 'EvictionUseAccessedTime') {
|
||||
_addBooleanSetting(commonSettings, _settings, key, value);
|
||||
_addBooleanSetting(commonSettings, widget.settings, key, value, true);
|
||||
} else if (key == 'MaxCacheSizeBytes') {
|
||||
_addIntSetting(commonSettings, _settings, key, value);
|
||||
_addIntSetting(commonSettings, widget.settings, key, value, false);
|
||||
} else if (key == 'MaxUploadCount') {
|
||||
_addIntSetting(commonSettings, _settings, key, value);
|
||||
_addIntSetting(commonSettings, widget.settings, key, value, true);
|
||||
} else if (key == 'OnlineCheckRetrySeconds') {
|
||||
_addIntSetting(commonSettings, _settings, key, value);
|
||||
_addIntSetting(commonSettings, widget.settings, key, value, true);
|
||||
} else if (key == 'PreferredDownloadType') {
|
||||
_addListSetting(commonSettings, _settings, key, value, [
|
||||
'default',
|
||||
'direct',
|
||||
'ring_buffer',
|
||||
], Icons.download);
|
||||
_addListSetting(
|
||||
commonSettings,
|
||||
widget.settings,
|
||||
key,
|
||||
value,
|
||||
downloadTypeList,
|
||||
Icons.download,
|
||||
false,
|
||||
);
|
||||
} else if (key == 'RetryReadCount') {
|
||||
_addIntSetting(commonSettings, _settings, key, value);
|
||||
_addIntSetting(commonSettings, widget.settings, key, value, true);
|
||||
} else if (key == 'RingBufferFileSize') {
|
||||
_addIntListSetting(
|
||||
commonSettings,
|
||||
_settings,
|
||||
widget.settings,
|
||||
key,
|
||||
value,
|
||||
['128', '256', '512', '1024', '2048'],
|
||||
ringBufferSizeList,
|
||||
512,
|
||||
Icons.animation,
|
||||
false,
|
||||
);
|
||||
} else if (key == 'EncryptConfig') {
|
||||
value.forEach((subKey, subValue) {
|
||||
if (subKey == 'EncryptionToken') {
|
||||
_addPasswordSetting(
|
||||
encryptConfigSettings,
|
||||
_settings[key],
|
||||
widget.settings[key],
|
||||
subKey,
|
||||
subValue,
|
||||
false,
|
||||
);
|
||||
} else if (subKey == 'Path') {
|
||||
_addStringSetting(
|
||||
encryptConfigSettings,
|
||||
_settings[key],
|
||||
widget.settings[key],
|
||||
subKey,
|
||||
subValue,
|
||||
Icons.folder,
|
||||
false,
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -278,64 +339,72 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
if (subKey == 'AgentString') {
|
||||
_addStringSetting(
|
||||
hostConfigSettings,
|
||||
_settings[key],
|
||||
widget.settings[key],
|
||||
subKey,
|
||||
subValue,
|
||||
Icons.support_agent,
|
||||
true,
|
||||
);
|
||||
} else if (subKey == 'ApiPassword') {
|
||||
_addPasswordSetting(
|
||||
hostConfigSettings,
|
||||
_settings[key],
|
||||
widget.settings[key],
|
||||
subKey,
|
||||
subValue,
|
||||
false,
|
||||
);
|
||||
} else if (subKey == 'ApiPort') {
|
||||
_addIntSetting(
|
||||
hostConfigSettings,
|
||||
_settings[key],
|
||||
widget.settings[key],
|
||||
subKey,
|
||||
subValue,
|
||||
false,
|
||||
);
|
||||
} else if (subKey == 'ApiUser') {
|
||||
_addStringSetting(
|
||||
hostConfigSettings,
|
||||
_settings[key],
|
||||
widget.settings[key],
|
||||
subKey,
|
||||
subValue,
|
||||
Icons.person,
|
||||
true,
|
||||
);
|
||||
} else if (subKey == 'HostNameOrIp') {
|
||||
_addStringSetting(
|
||||
hostConfigSettings,
|
||||
_settings[key],
|
||||
widget.settings[key],
|
||||
subKey,
|
||||
subValue,
|
||||
Icons.computer,
|
||||
false,
|
||||
);
|
||||
} else if (subKey == 'Path') {
|
||||
_addStringSetting(
|
||||
hostConfigSettings,
|
||||
_settings[key],
|
||||
widget.settings[key],
|
||||
subKey,
|
||||
subValue,
|
||||
Icons.route,
|
||||
true,
|
||||
);
|
||||
} else if (subKey == 'Protocol') {
|
||||
_addListSetting(
|
||||
hostConfigSettings,
|
||||
_settings[key],
|
||||
widget.settings[key],
|
||||
subKey,
|
||||
subValue,
|
||||
['http', 'https'],
|
||||
protocolTypeList,
|
||||
Icons.http,
|
||||
true,
|
||||
);
|
||||
} else if (subKey == 'TimeoutMs') {
|
||||
_addIntSetting(
|
||||
hostConfigSettings,
|
||||
_settings[key],
|
||||
widget.settings[key],
|
||||
subKey,
|
||||
subValue,
|
||||
true,
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -344,45 +413,51 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
if (subKey == 'ApiPort') {
|
||||
_addIntSetting(
|
||||
remoteConfigSettings,
|
||||
_settings[key],
|
||||
widget.settings[key],
|
||||
subKey,
|
||||
subValue,
|
||||
false,
|
||||
);
|
||||
} else if (subKey == 'EncryptionToken') {
|
||||
_addPasswordSetting(
|
||||
remoteConfigSettings,
|
||||
_settings[key],
|
||||
widget.settings[key],
|
||||
subKey,
|
||||
subValue,
|
||||
false,
|
||||
);
|
||||
} else if (subKey == 'HostNameOrIp') {
|
||||
_addStringSetting(
|
||||
remoteConfigSettings,
|
||||
_settings[key],
|
||||
widget.settings[key],
|
||||
subKey,
|
||||
subValue,
|
||||
Icons.computer,
|
||||
false,
|
||||
);
|
||||
} else if (subKey == 'MaxConnections') {
|
||||
_addIntSetting(
|
||||
remoteConfigSettings,
|
||||
_settings[key],
|
||||
widget.settings[key],
|
||||
subKey,
|
||||
subValue,
|
||||
true,
|
||||
);
|
||||
} else if (subKey == 'ReceiveTimeoutMs') {
|
||||
_addIntSetting(
|
||||
remoteConfigSettings,
|
||||
_settings[key],
|
||||
widget.settings[key],
|
||||
subKey,
|
||||
subValue,
|
||||
true,
|
||||
);
|
||||
} else if (subKey == 'SendTimeoutMs') {
|
||||
_addIntSetting(
|
||||
remoteConfigSettings,
|
||||
_settings[key],
|
||||
widget.settings[key],
|
||||
subKey,
|
||||
subValue,
|
||||
true,
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -390,28 +465,37 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
value.forEach((subKey, subValue) {
|
||||
if (subKey == 'Enable') {
|
||||
List<SettingsTile> tempSettings = [];
|
||||
_addBooleanSetting(tempSettings, _settings[key], subKey, subValue);
|
||||
_addBooleanSetting(
|
||||
tempSettings,
|
||||
widget.settings[key],
|
||||
subKey,
|
||||
subValue,
|
||||
false,
|
||||
);
|
||||
remoteMountSettings.insertAll(0, tempSettings);
|
||||
} else if (subKey == 'ApiPort') {
|
||||
_addIntSetting(
|
||||
remoteMountSettings,
|
||||
_settings[key],
|
||||
widget.settings[key],
|
||||
subKey,
|
||||
subValue,
|
||||
false,
|
||||
);
|
||||
} else if (subKey == 'ClientPoolSize') {
|
||||
_addIntSetting(
|
||||
remoteMountSettings,
|
||||
_settings[key],
|
||||
widget.settings[key],
|
||||
subKey,
|
||||
subValue,
|
||||
true,
|
||||
);
|
||||
} else if (subKey == 'EncryptionToken') {
|
||||
_addPasswordSetting(
|
||||
remoteMountSettings,
|
||||
_settings[key],
|
||||
widget.settings[key],
|
||||
subKey,
|
||||
subValue,
|
||||
false,
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -420,63 +504,77 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
if (subKey == 'AccessKey') {
|
||||
_addPasswordSetting(
|
||||
s3ConfigSettings,
|
||||
_settings[key],
|
||||
widget.settings[key],
|
||||
subKey,
|
||||
subValue,
|
||||
false,
|
||||
);
|
||||
} else if (subKey == 'Bucket') {
|
||||
_addStringSetting(
|
||||
s3ConfigSettings,
|
||||
_settings[key],
|
||||
widget.settings[key],
|
||||
subKey,
|
||||
subValue,
|
||||
Icons.folder,
|
||||
false,
|
||||
);
|
||||
} else if (subKey == 'EncryptionToken') {
|
||||
_addPasswordSetting(
|
||||
s3ConfigSettings,
|
||||
_settings[key],
|
||||
widget.settings[key],
|
||||
subKey,
|
||||
subValue,
|
||||
false,
|
||||
);
|
||||
} else if (subKey == 'Region') {
|
||||
_addStringSetting(
|
||||
s3ConfigSettings,
|
||||
_settings[key],
|
||||
widget.settings[key],
|
||||
subKey,
|
||||
subValue,
|
||||
Icons.map,
|
||||
false,
|
||||
);
|
||||
} else if (subKey == 'SecretKey') {
|
||||
_addPasswordSetting(
|
||||
s3ConfigSettings,
|
||||
_settings[key],
|
||||
widget.settings[key],
|
||||
subKey,
|
||||
subValue,
|
||||
false,
|
||||
);
|
||||
} else if (subKey == 'TimeoutMs') {
|
||||
_addIntSetting(s3ConfigSettings, _settings[key], subKey, subValue);
|
||||
_addIntSetting(
|
||||
s3ConfigSettings,
|
||||
widget.settings[key],
|
||||
subKey,
|
||||
subValue,
|
||||
true,
|
||||
);
|
||||
} else if (subKey == 'URL') {
|
||||
_addStringSetting(
|
||||
s3ConfigSettings,
|
||||
_settings[key],
|
||||
widget.settings[key],
|
||||
subKey,
|
||||
subValue,
|
||||
Icons.http,
|
||||
false,
|
||||
);
|
||||
} else if (subKey == 'UsePathStyle') {
|
||||
_addBooleanSetting(
|
||||
s3ConfigSettings,
|
||||
_settings[key],
|
||||
widget.settings[key],
|
||||
subKey,
|
||||
subValue,
|
||||
false,
|
||||
);
|
||||
} else if (subKey == 'UseRegionInURL') {
|
||||
_addBooleanSetting(
|
||||
s3ConfigSettings,
|
||||
_settings[key],
|
||||
widget.settings[key],
|
||||
subKey,
|
||||
subValue,
|
||||
false,
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -485,10 +583,11 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
if (subKey == 'Bucket') {
|
||||
_addStringSetting(
|
||||
siaConfigSettings,
|
||||
_settings[key],
|
||||
widget.settings[key],
|
||||
subKey,
|
||||
subValue,
|
||||
Icons.folder,
|
||||
false,
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -527,51 +626,40 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
|
||||
SettingsSection(
|
||||
title: const Text('Remote Mount'),
|
||||
tiles:
|
||||
_settings['RemoteMount']['Enable'] as bool
|
||||
widget.settings['RemoteMount']['Enable'] as bool
|
||||
? remoteMountSettings
|
||||
: [remoteMountSettings[0]],
|
||||
),
|
||||
SettingsSection(title: const Text('Settings'), tiles: commonSettings),
|
||||
if (commonSettings.isNotEmpty)
|
||||
SettingsSection(title: const Text('Settings'), tiles: commonSettings),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
var settings = widget.mount.mountConfig.settings;
|
||||
if (!DeepCollectionEquality().equals(_settings, settings)) {
|
||||
_settings.forEach((key, value) {
|
||||
if (!DeepCollectionEquality().equals(settings[key], value)) {
|
||||
if (value is Map<String, dynamic>) {
|
||||
value.forEach((subKey, subValue) {
|
||||
if (!DeepCollectionEquality().equals(
|
||||
settings[key][subKey],
|
||||
subValue,
|
||||
)) {
|
||||
widget.mount.setValue('$key.$subKey', subValue.toString());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
widget.mount.setValue(key, value.toString());
|
||||
if (!widget.isAdd) {
|
||||
var settings = widget.mount.mountConfig.settings;
|
||||
if (!DeepCollectionEquality().equals(widget.settings, settings)) {
|
||||
widget.settings.forEach((key, value) {
|
||||
if (!DeepCollectionEquality().equals(settings[key], value)) {
|
||||
if (value is Map<String, dynamic>) {
|
||||
value.forEach((subKey, subValue) {
|
||||
if (!DeepCollectionEquality().equals(
|
||||
settings[key][subKey],
|
||||
subValue,
|
||||
)) {
|
||||
widget.mount.setValue('$key.$subKey', subValue.toString());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
widget.mount.setValue(key, value.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_settings = jsonDecode(jsonEncode(widget.mount.mountConfig.settings));
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void setState(VoidCallback fn) {
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
super.setState(fn);
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ class _MountWidgetState extends State<MountWidget> {
|
||||
leading: IconButton(
|
||||
icon: Icon(Icons.settings, color: textColor),
|
||||
onPressed: () {
|
||||
Navigator.pushNamed(context, '/settings', arguments: mount);
|
||||
Navigator.pushNamed(context, '/edit', arguments: mount);
|
||||
},
|
||||
),
|
||||
subtitle: Column(
|
||||
|
Loading…
x
Reference in New Issue
Block a user