added portal settings screen
This commit is contained in:
parent
9b5d642106
commit
e7accd1cc1
@ -63,6 +63,8 @@ private:
|
|||||||
|
|
||||||
void handle_get_mount_status(auto &&req, auto &&res) const;
|
void handle_get_mount_status(auto &&req, auto &&res) const;
|
||||||
|
|
||||||
|
void handle_get_settings(auto &&res) const;
|
||||||
|
|
||||||
void handle_post_add_mount(auto &&req, auto &&res) const;
|
void handle_post_add_mount(auto &&req, auto &&res) const;
|
||||||
|
|
||||||
void handle_post_mount(auto &&req, auto &&res) const;
|
void handle_post_mount(auto &&req, auto &&res) const;
|
||||||
|
@ -42,6 +42,8 @@ private:
|
|||||||
void save() const;
|
void save() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
[[nodiscard]] auto to_json() const -> nlohmann::json;
|
||||||
|
|
||||||
[[nodiscard]] auto get_api_password() const -> std::string {
|
[[nodiscard]] auto get_api_password() const -> std::string {
|
||||||
return api_password_;
|
return api_password_;
|
||||||
}
|
}
|
||||||
|
@ -102,6 +102,11 @@ handlers::handlers(mgmt_app_config *config, httplib::Server *server)
|
|||||||
handle_get_mount_status(req, res);
|
handle_get_mount_status(req, res);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
server->Get("/api/v1/settings",
|
||||||
|
[this](const httplib::Request & /* req */, auto &&res) {
|
||||||
|
handle_get_settings(res);
|
||||||
|
});
|
||||||
|
|
||||||
server->Post("/api/v1/add_mount", [this](auto &&req, auto &&res) {
|
server->Post("/api/v1/add_mount", [this](auto &&req, auto &&res) {
|
||||||
handle_post_add_mount(req, res);
|
handle_post_add_mount(req, res);
|
||||||
});
|
});
|
||||||
@ -307,6 +312,11 @@ void handlers::handle_get_mount_status(auto &&req, auto &&res) const {
|
|||||||
res.status = http_error_codes::ok;
|
res.status = http_error_codes::ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handlers::handle_get_settings(auto &&res) const {
|
||||||
|
res.set_content(config_->to_json().dump(), "application/json");
|
||||||
|
res.status = http_error_codes::ok;
|
||||||
|
}
|
||||||
|
|
||||||
void handlers::handle_post_add_mount(auto &&req, auto &&res) const {
|
void handlers::handle_post_add_mount(auto &&req, auto &&res) const {
|
||||||
auto name = req.get_param_value("name");
|
auto name = req.get_param_value("name");
|
||||||
auto prov = provider_type_from_string(req.get_param_value("type"));
|
auto prov = provider_type_from_string(req.get_param_value("type"));
|
||||||
|
@ -59,7 +59,7 @@ namespace {
|
|||||||
return map_of_maps;
|
return map_of_maps;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto to_json(const auto &map_of_maps) -> nlohmann::json {
|
[[nodiscard]] auto map_to_json(const auto &map_of_maps) -> nlohmann::json {
|
||||||
auto json = nlohmann::json::object();
|
auto json = nlohmann::json::object();
|
||||||
for (const auto &[prov, map] : map_of_maps) {
|
for (const auto &[prov, map] : map_of_maps) {
|
||||||
for (const auto &[key, value] : map) {
|
for (const auto &[key, value] : map) {
|
||||||
@ -134,12 +134,7 @@ void mgmt_app_config::save() const {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nlohmann::json data;
|
if (utils::file::write_json_file(config_file, to_json())) {
|
||||||
data[JSON_API_PASSWORD] = api_password_;
|
|
||||||
data[JSON_API_PORT] = api_port_;
|
|
||||||
data[JSON_API_USER] = api_user_;
|
|
||||||
data[JSON_MOUNT_LOCATIONS] = to_json(locations_);
|
|
||||||
if (utils::file::write_json_file(config_file, data)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,4 +176,13 @@ void mgmt_app_config::set_mount_location(provider_type prov,
|
|||||||
|
|
||||||
save();
|
save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto mgmt_app_config::to_json() const -> nlohmann::json {
|
||||||
|
nlohmann::json data;
|
||||||
|
data[JSON_API_PASSWORD] = api_password_;
|
||||||
|
data[JSON_API_PORT] = api_port_;
|
||||||
|
data[JSON_API_USER] = api_user_;
|
||||||
|
data[JSON_MOUNT_LOCATIONS] = map_to_json(locations_);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
} // namespace repertory::ui
|
} // namespace repertory::ui
|
||||||
|
@ -125,7 +125,7 @@ String getBaseUri() {
|
|||||||
String? getSettingDescription(String settingPath) {
|
String? getSettingDescription(String settingPath) {
|
||||||
switch (settingPath) {
|
switch (settingPath) {
|
||||||
case 'ApiPassword':
|
case 'ApiPassword':
|
||||||
return "'repertory' REST API password";
|
return "HTTP basic authentication password";
|
||||||
case 'HostConfig.ApiPassword':
|
case 'HostConfig.ApiPassword':
|
||||||
return "RENTERD_API_PASSWORD";
|
return "RENTERD_API_PASSWORD";
|
||||||
default:
|
default:
|
||||||
|
@ -6,6 +6,7 @@ import 'package:repertory/models/mount.dart';
|
|||||||
import 'package:repertory/models/mount_list.dart';
|
import 'package:repertory/models/mount_list.dart';
|
||||||
import 'package:repertory/screens/add_mount_screen.dart';
|
import 'package:repertory/screens/add_mount_screen.dart';
|
||||||
import 'package:repertory/screens/edit_mount_screen.dart';
|
import 'package:repertory/screens/edit_mount_screen.dart';
|
||||||
|
import 'package:repertory/screens/edit_settings_screen.dart';
|
||||||
import 'package:repertory/screens/home_screen.dart';
|
import 'package:repertory/screens/home_screen.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
@ -50,6 +51,8 @@ class _MyAppState extends State<MyApp> {
|
|||||||
'/': (context) => const HomeScreen(title: constants.appTitle),
|
'/': (context) => const HomeScreen(title: constants.appTitle),
|
||||||
'/add':
|
'/add':
|
||||||
(context) => const AddMountScreen(title: constants.addMountTitle),
|
(context) => const AddMountScreen(title: constants.addMountTitle),
|
||||||
|
'/settings':
|
||||||
|
(context) => const EditSettingsScreen(title: constants.appTitle),
|
||||||
},
|
},
|
||||||
onGenerateRoute: (settings) {
|
onGenerateRoute: (settings) {
|
||||||
if (settings.name != '/edit') {
|
if (settings.name != '/edit') {
|
||||||
|
68
web/repertory/lib/screens/edit_settings_screen.dart
Normal file
68
web/repertory/lib/screens/edit_settings_screen.dart
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import 'dart:convert' show jsonDecode;
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
import 'package:repertory/helpers.dart';
|
||||||
|
import 'package:repertory/widgets/ui_settings.dart';
|
||||||
|
|
||||||
|
class EditSettingsScreen extends StatefulWidget {
|
||||||
|
final String title;
|
||||||
|
const EditSettingsScreen({super.key, required this.title});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<EditSettingsScreen> createState() => _EditSettingsScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _EditSettingsScreenState extends State<EditSettingsScreen> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||||
|
title: Text(widget.title),
|
||||||
|
),
|
||||||
|
body: FutureBuilder(
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (!snapshot.hasData) {
|
||||||
|
return Center(child: CircularProgressIndicator());
|
||||||
|
}
|
||||||
|
|
||||||
|
return UISettingsWidget(
|
||||||
|
settings: snapshot.requireData,
|
||||||
|
showAdvanced: false,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
future: _grabSettings(),
|
||||||
|
initialData: <String, dynamic>{},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Map<String, dynamic>> _grabSettings() async {
|
||||||
|
try {
|
||||||
|
final response = await http.get(
|
||||||
|
Uri.parse('${getBaseUri()}/api/v1/settings'),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.statusCode != 200) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return jsonDecode(response.body);
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('$e');
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// UISettingsWidget(settings: {}, showAdvanced: false),
|
||||||
|
@override
|
||||||
|
void setState(VoidCallback fn) {
|
||||||
|
if (!mounted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
super.setState(fn);
|
||||||
|
}
|
||||||
|
}
|
@ -16,7 +16,10 @@ class _HomeScreeState extends State<HomeScreen> {
|
|||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||||
leading: const Icon(Icons.storage),
|
leading: IconButton(
|
||||||
|
onPressed: () => Navigator.pushNamed(context, '/settings'),
|
||||||
|
icon: const Icon(Icons.storage),
|
||||||
|
),
|
||||||
title: Text(widget.title),
|
title: Text(widget.title),
|
||||||
),
|
),
|
||||||
body: Padding(
|
body: Padding(
|
||||||
|
361
web/repertory/lib/settings.dart
Normal file
361
web/repertory/lib/settings.dart
Normal file
@ -0,0 +1,361 @@
|
|||||||
|
import 'package:collection/collection.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:repertory/constants.dart' as constants;
|
||||||
|
import 'package:repertory/helpers.dart' show Validator, displayErrorMessage;
|
||||||
|
import 'package:settings_ui/settings_ui.dart';
|
||||||
|
|
||||||
|
void createBooleanSetting(
|
||||||
|
context,
|
||||||
|
List<Widget> list,
|
||||||
|
Map<String, dynamic> settings,
|
||||||
|
String key,
|
||||||
|
value,
|
||||||
|
bool isAdvanced,
|
||||||
|
bool showAdvanced,
|
||||||
|
widget,
|
||||||
|
Function setState, {
|
||||||
|
String? description,
|
||||||
|
}) {
|
||||||
|
if (!isAdvanced || showAdvanced) {
|
||||||
|
list.add(
|
||||||
|
SettingsTile.switchTile(
|
||||||
|
leading: const Icon(Icons.quiz),
|
||||||
|
title: createSettingTitle(context, key, description),
|
||||||
|
initialValue: (value as bool),
|
||||||
|
onPressed:
|
||||||
|
(_) => setState(() {
|
||||||
|
settings[key] = !value;
|
||||||
|
widget.onChanged?.call(widget.settings);
|
||||||
|
}),
|
||||||
|
onToggle: (bool nextValue) {
|
||||||
|
setState(() {
|
||||||
|
settings[key] = nextValue;
|
||||||
|
widget.onChanged?.call(widget.settings);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void createIntListSetting(
|
||||||
|
context,
|
||||||
|
List<Widget> list,
|
||||||
|
Map<String, dynamic> settings,
|
||||||
|
String key,
|
||||||
|
value,
|
||||||
|
List<String> valueList,
|
||||||
|
defaultValue,
|
||||||
|
IconData icon,
|
||||||
|
bool isAdvanced,
|
||||||
|
bool showAdvanced,
|
||||||
|
widget,
|
||||||
|
Function setState, {
|
||||||
|
String? description,
|
||||||
|
}) {
|
||||||
|
if (!isAdvanced || widget.showAdvanced) {
|
||||||
|
list.add(
|
||||||
|
SettingsTile.navigation(
|
||||||
|
title: createSettingTitle(context, key, description),
|
||||||
|
leading: Icon(icon),
|
||||||
|
value: DropdownButton<String>(
|
||||||
|
value: value.toString(),
|
||||||
|
onChanged: (newValue) {
|
||||||
|
setState(() {
|
||||||
|
settings[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 createIntSetting(
|
||||||
|
context,
|
||||||
|
List<Widget> list,
|
||||||
|
Map<String, dynamic> settings,
|
||||||
|
String key,
|
||||||
|
value,
|
||||||
|
bool isAdvanced,
|
||||||
|
bool showAdvanced,
|
||||||
|
widget,
|
||||||
|
Function setState, {
|
||||||
|
String? description,
|
||||||
|
List<Validator> validators = const [],
|
||||||
|
}) {
|
||||||
|
if (!isAdvanced || widget.showAdvanced) {
|
||||||
|
list.add(
|
||||||
|
SettingsTile.navigation(
|
||||||
|
leading: const Icon(Icons.onetwothree),
|
||||||
|
title: createSettingTitle(context, key, description),
|
||||||
|
value: Text(value.toString()),
|
||||||
|
onPressed: (_) {
|
||||||
|
String updatedValue = value.toString();
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return AlertDialog(
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
child: const Text('Cancel'),
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
child: const Text('OK'),
|
||||||
|
onPressed: () {
|
||||||
|
final result = validators.firstWhereOrNull(
|
||||||
|
(validator) => !validator(updatedValue),
|
||||||
|
);
|
||||||
|
if (result != null) {
|
||||||
|
return displayErrorMessage(
|
||||||
|
context,
|
||||||
|
"Setting '$key' is not valid",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
settings[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,
|
||||||
|
),
|
||||||
|
title: createSettingTitle(context, key, description),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void createPasswordSetting(
|
||||||
|
context,
|
||||||
|
List<Widget> list,
|
||||||
|
Map<String, dynamic> settings,
|
||||||
|
String key,
|
||||||
|
value,
|
||||||
|
bool isAdvanced,
|
||||||
|
bool showAdvanced,
|
||||||
|
widget,
|
||||||
|
Function setState, {
|
||||||
|
String? description,
|
||||||
|
List<Validator> validators = const [],
|
||||||
|
}) {
|
||||||
|
if (!isAdvanced || widget.showAdvanced) {
|
||||||
|
list.add(
|
||||||
|
SettingsTile.navigation(
|
||||||
|
leading: const Icon(Icons.password),
|
||||||
|
title: createSettingTitle(context, key, description),
|
||||||
|
value: Text('*' * (value as String).length),
|
||||||
|
onPressed: (_) {
|
||||||
|
String updatedValue1 = value;
|
||||||
|
String updatedValue2 = value;
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return AlertDialog(
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
child: const Text('Cancel'),
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
child: const Text('OK'),
|
||||||
|
onPressed: () {
|
||||||
|
if (updatedValue1 != updatedValue2) {
|
||||||
|
return displayErrorMessage(
|
||||||
|
context,
|
||||||
|
"Setting '$key' does not match",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final result = validators.firstWhereOrNull(
|
||||||
|
(validator) => !validator(updatedValue1),
|
||||||
|
);
|
||||||
|
if (result != null) {
|
||||||
|
return displayErrorMessage(
|
||||||
|
context,
|
||||||
|
"Setting '$key' is not valid",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
settings[key] = updatedValue1;
|
||||||
|
widget.onChanged?.call(widget.settings);
|
||||||
|
});
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
content: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
TextField(
|
||||||
|
autofocus: true,
|
||||||
|
controller: TextEditingController(text: updatedValue1),
|
||||||
|
obscureText: true,
|
||||||
|
obscuringCharacter: '*',
|
||||||
|
onChanged: (value) => updatedValue1 = value,
|
||||||
|
),
|
||||||
|
const SizedBox(height: constants.padding),
|
||||||
|
TextField(
|
||||||
|
autofocus: false,
|
||||||
|
controller: TextEditingController(text: updatedValue2),
|
||||||
|
obscureText: true,
|
||||||
|
obscuringCharacter: '*',
|
||||||
|
onChanged: (value) => updatedValue2 = value,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
title: createSettingTitle(context, key, description),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget createSettingTitle(context, String key, String? description) {
|
||||||
|
if (description == null) {
|
||||||
|
return Text(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(key, textAlign: TextAlign.start),
|
||||||
|
Text(
|
||||||
|
description,
|
||||||
|
style: Theme.of(context).textTheme.titleSmall,
|
||||||
|
textAlign: TextAlign.start,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void createStringListSetting(
|
||||||
|
context,
|
||||||
|
List<Widget> list,
|
||||||
|
Map<String, dynamic> settings,
|
||||||
|
String key,
|
||||||
|
value,
|
||||||
|
List<String> valueList,
|
||||||
|
IconData icon,
|
||||||
|
bool isAdvanced,
|
||||||
|
bool showAdvanced,
|
||||||
|
widget,
|
||||||
|
Function setState, {
|
||||||
|
String? description,
|
||||||
|
}) {
|
||||||
|
if (!isAdvanced || widget.showAdvanced) {
|
||||||
|
list.add(
|
||||||
|
SettingsTile.navigation(
|
||||||
|
title: createSettingTitle(context, key, description),
|
||||||
|
leading: Icon(icon),
|
||||||
|
value: DropdownButton<String>(
|
||||||
|
value: value,
|
||||||
|
onChanged:
|
||||||
|
(newValue) => setState(() {
|
||||||
|
settings[key] = newValue;
|
||||||
|
widget.onChanged?.call(widget.settings);
|
||||||
|
}),
|
||||||
|
items:
|
||||||
|
valueList.map<DropdownMenuItem<String>>((item) {
|
||||||
|
return DropdownMenuItem<String>(value: item, child: Text(item));
|
||||||
|
}).toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void createStringSetting(
|
||||||
|
context,
|
||||||
|
List<Widget> list,
|
||||||
|
Map<String, dynamic> settings,
|
||||||
|
String key,
|
||||||
|
value,
|
||||||
|
IconData icon,
|
||||||
|
bool isAdvanced,
|
||||||
|
bool showAdvanced,
|
||||||
|
widget,
|
||||||
|
Function setState, {
|
||||||
|
String? description,
|
||||||
|
List<Validator> validators = const [],
|
||||||
|
}) {
|
||||||
|
if (!isAdvanced || widget.showAdvanced) {
|
||||||
|
list.add(
|
||||||
|
SettingsTile.navigation(
|
||||||
|
leading: Icon(icon),
|
||||||
|
title: createSettingTitle(context, key, description),
|
||||||
|
value: Text(value),
|
||||||
|
onPressed: (_) {
|
||||||
|
String updatedValue = value;
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return AlertDialog(
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
child: const Text('Cancel'),
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
child: const Text('OK'),
|
||||||
|
onPressed: () {
|
||||||
|
final result = validators.firstWhereOrNull(
|
||||||
|
(validator) => !validator(updatedValue),
|
||||||
|
);
|
||||||
|
if (result != null) {
|
||||||
|
return displayErrorMessage(
|
||||||
|
context,
|
||||||
|
"Setting '$key' is not valid",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
settings[key] = updatedValue;
|
||||||
|
widget.onChanged?.call(widget.settings);
|
||||||
|
});
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
content: TextField(
|
||||||
|
autofocus: true,
|
||||||
|
controller: TextEditingController(text: updatedValue),
|
||||||
|
inputFormatters: [
|
||||||
|
FilteringTextInputFormatter.deny(RegExp(r'\s')),
|
||||||
|
],
|
||||||
|
onChanged: (value) => updatedValue = value,
|
||||||
|
),
|
||||||
|
title: createSettingTitle(context, key, description),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
105
web/repertory/lib/widgets/ui_settings.dart
Normal file
105
web/repertory/lib/widgets/ui_settings.dart
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
import 'package:collection/collection.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:repertory/constants.dart' as constants;
|
||||||
|
import 'package:repertory/helpers.dart'
|
||||||
|
show getSettingDescription, getSettingValidators;
|
||||||
|
import 'package:repertory/models/mount.dart';
|
||||||
|
import 'package:repertory/models/mount_list.dart';
|
||||||
|
import 'package:repertory/settings.dart';
|
||||||
|
import 'package:settings_ui/settings_ui.dart';
|
||||||
|
|
||||||
|
class UISettingsWidget extends StatefulWidget {
|
||||||
|
final bool showAdvanced;
|
||||||
|
final Function? onChanged;
|
||||||
|
final Map<String, dynamic> settings;
|
||||||
|
const UISettingsWidget({
|
||||||
|
super.key,
|
||||||
|
this.onChanged,
|
||||||
|
required this.settings,
|
||||||
|
required this.showAdvanced,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<UISettingsWidget> createState() => _UISettingsWidgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _UISettingsWidgetState extends State<UISettingsWidget> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
List<SettingsTile> commonSettings = [];
|
||||||
|
|
||||||
|
widget.settings.forEach((key, value) {
|
||||||
|
switch (key) {
|
||||||
|
case 'ApiPassword':
|
||||||
|
{
|
||||||
|
createPasswordSetting(
|
||||||
|
context,
|
||||||
|
commonSettings,
|
||||||
|
widget.settings,
|
||||||
|
key,
|
||||||
|
value,
|
||||||
|
false,
|
||||||
|
widget.showAdvanced,
|
||||||
|
widget,
|
||||||
|
setState,
|
||||||
|
description: getSettingDescription(key),
|
||||||
|
validators: getSettingValidators(key),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'ApiPort':
|
||||||
|
{
|
||||||
|
createIntSetting(
|
||||||
|
context,
|
||||||
|
commonSettings,
|
||||||
|
widget.settings,
|
||||||
|
key,
|
||||||
|
value,
|
||||||
|
true,
|
||||||
|
widget.showAdvanced,
|
||||||
|
widget,
|
||||||
|
setState,
|
||||||
|
description: getSettingDescription(key),
|
||||||
|
validators: getSettingValidators(key),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'ApiUser':
|
||||||
|
{
|
||||||
|
createStringSetting(
|
||||||
|
context,
|
||||||
|
commonSettings,
|
||||||
|
widget.settings,
|
||||||
|
key,
|
||||||
|
value,
|
||||||
|
Icons.person,
|
||||||
|
true,
|
||||||
|
widget.showAdvanced,
|
||||||
|
widget,
|
||||||
|
setState,
|
||||||
|
description: getSettingDescription(key),
|
||||||
|
validators: getSettingValidators(key),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return SettingsList(
|
||||||
|
shrinkWrap: false,
|
||||||
|
sections: [
|
||||||
|
SettingsSection(title: const Text('Settings'), tiles: commonSettings),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void setState(VoidCallback fn) {
|
||||||
|
if (!mounted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
super.setState(fn);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user