From 9de4d3172fadc2cad1902421b4666a910f65f3f0 Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Fri, 5 Sep 2025 21:20:42 -0500 Subject: [PATCH] refactor ui --- .../lib/screens/add_mount_screen.dart | 161 +++++++++--------- ...ton.dart => app_outlined_icon_button.dart} | 14 +- web/repertory/lib/widgets/mount_widget.dart | 6 +- 3 files changed, 93 insertions(+), 88 deletions(-) rename web/repertory/lib/widgets/{app_edit_path_button.dart => app_outlined_icon_button.dart} (78%) diff --git a/web/repertory/lib/screens/add_mount_screen.dart b/web/repertory/lib/screens/add_mount_screen.dart index f0bb1c5a..7bfa3335 100644 --- a/web/repertory/lib/screens/add_mount_screen.dart +++ b/web/repertory/lib/screens/add_mount_screen.dart @@ -11,6 +11,7 @@ import 'package:repertory/models/mount_list.dart'; import 'package:repertory/types/mount_config.dart'; import 'package:repertory/utils/safe_set_state_mixin.dart'; import 'package:repertory/widgets/app_dropdown.dart'; +import 'package:repertory/widgets/app_outlined_icon_button.dart'; import 'package:repertory/widgets/app_scaffold.dart'; import 'package:repertory/widgets/mount_settings.dart'; @@ -27,6 +28,7 @@ class _AddMountScreenState extends State Mount? _mount; final _mountNameController = TextEditingController(); String _mountType = ""; + bool _enabled = true; final Map> _settings = { "": {}, @@ -107,95 +109,78 @@ class _AddMountScreenState extends State Row( children: [ IntrinsicWidth( - child: ElevatedButton.icon( - label: const Text('Test'), - icon: const Icon(Icons.check), - style: ElevatedButton.styleFrom( - backgroundColor: scheme.primary.withValues( - alpha: constants.primaryAlpha, - ), - foregroundColor: scheme.primary, - elevation: 0, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - constants.borderRadius, - ), - side: BorderSide( - color: scheme.outlineVariant.withValues( - alpha: constants.outlineAlpha, - ), - width: 1, - ), - ), - ), + child: AppOutlinedIconButton( + enabled: _enabled, + icon: Icons.check, + text: 'Test', onPressed: _handleProviderTest, ), ), const SizedBox(width: constants.padding), IntrinsicWidth( - child: ElevatedButton.icon( - label: const Text('Add'), - icon: const Icon(Icons.add), - style: ElevatedButton.styleFrom( - backgroundColor: scheme.primary, - foregroundColor: scheme.onPrimary, - elevation: 8, - shadowColor: scheme.primary.withValues( - alpha: constants.secondaryAlpha, - ), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - constants.borderRadius, - ), - ), - ), + child: AppOutlinedIconButton( + enabled: _enabled, + icon: Icons.add, + text: 'Add', onPressed: () async { - final mountList = Provider.of( - context, - listen: false, - ); + setState(() { + _enabled = false; + }); - List failed = []; - if (!validateSettings(_settings[_mountType]!, failed)) { - for (var key in failed) { - displayErrorMessage( - context, - "Setting '$key' is not valid", - ); - } - return; - } - - if (mountList.hasConfigName(_mountNameController.text)) { - return displayErrorMessage( + try { + final mountList = Provider.of( context, - "Configuration name '${_mountNameController.text}' already exists", + listen: false, ); - } - if (_mountType == "Sia" || _mountType == "S3") { - final bucket = - _settings[_mountType]!["${_mountType}Config"]["Bucket"] - as String; - if (mountList.hasBucketName(_mountType, bucket)) { + List failed = []; + if (!validateSettings(_settings[_mountType]!, failed)) { + for (var key in failed) { + displayErrorMessage( + context, + "Setting '$key' is not valid", + ); + } + return; + } + + if (mountList.hasConfigName(_mountNameController.text)) { return displayErrorMessage( context, - "Bucket '$bucket' already exists", + "Configuration name '${_mountNameController.text}' already exists", ); } + + if (_mountType == "Sia" || _mountType == "S3") { + final bucket = + _settings[_mountType]!["${_mountType}Config"]["Bucket"] + as String; + if (mountList.hasBucketName(_mountType, bucket)) { + return displayErrorMessage( + context, + "Bucket '$bucket' already exists", + ); + } + } + + final success = await mountList.add( + _mountType, + _mountType == 'Remote' + ? '${_settings[_mountType]!['RemoteConfig']['HostNameOrIp']}_${_settings[_mountType]!['RemoteConfig']['ApiPort']}' + : _mountNameController.text, + _settings[_mountType]!, + ); + + if (!success || !context.mounted) { + return; + } + + Navigator.pop(context); + } finally { + setState(() { + _enabled = true; + }); } - - final success = await mountList.add( - _mountType, - _mountType == 'Remote' - ? '${_settings[_mountType]!['RemoteConfig']['HostNameOrIp']}_${_settings[_mountType]!['RemoteConfig']['ApiPort']}' - : _mountNameController.text, - _settings[_mountType]!, - ); - - if (!success || !context.mounted) return; - - Navigator.pop(context); }, ), ), @@ -233,14 +218,28 @@ class _AddMountScreenState extends State } Future _handleProviderTest() async { - if (_mount == null) return; + setState(() { + _enabled = false; + }); - final success = await _mount!.test(); - if (!mounted) return; + try { + if (_mount == null) { + return; + } - displayErrorMessage( - context, - success ? "Success" : "Provider settings are invalid!", - ); + final success = await _mount!.test(); + if (!mounted) { + return; + } + + displayErrorMessage( + context, + success ? "Success" : "Provider settings are invalid!", + ); + } finally { + setState(() { + _enabled = true; + }); + } } } diff --git a/web/repertory/lib/widgets/app_edit_path_button.dart b/web/repertory/lib/widgets/app_outlined_icon_button.dart similarity index 78% rename from web/repertory/lib/widgets/app_edit_path_button.dart rename to web/repertory/lib/widgets/app_outlined_icon_button.dart index 10a4e0f3..def3777c 100644 --- a/web/repertory/lib/widgets/app_edit_path_button.dart +++ b/web/repertory/lib/widgets/app_outlined_icon_button.dart @@ -1,16 +1,20 @@ -// app_edit_path_button.dart +// app_outlined_icon_button.dart import 'package:flutter/material.dart'; import 'package:repertory/constants.dart' as constants; -class AppEditPathButton extends StatelessWidget { +class AppOutlinedIconButton extends StatelessWidget { + final IconData icon; final bool enabled; + final String text; final VoidCallback onPressed; - const AppEditPathButton({ + const AppOutlinedIconButton({ super.key, + required this.icon, required this.enabled, required this.onPressed, + required this.text, }); @override @@ -21,8 +25,8 @@ class AppEditPathButton extends StatelessWidget { opacity: enabled ? 1.0 : constants.secondaryAlpha, child: OutlinedButton.icon( onPressed: enabled ? onPressed : null, - icon: const Icon(Icons.edit, size: constants.smallIconSize), - label: const Text('Edit path'), + icon: Icon(icon, size: constants.smallIconSize), + label: Text(text), style: OutlinedButton.styleFrom( foregroundColor: scheme.primary, side: BorderSide( diff --git a/web/repertory/lib/widgets/mount_widget.dart b/web/repertory/lib/widgets/mount_widget.dart index 9eef7a33..619469fa 100644 --- a/web/repertory/lib/widgets/mount_widget.dart +++ b/web/repertory/lib/widgets/mount_widget.dart @@ -7,7 +7,7 @@ import 'package:repertory/constants.dart' as constants; import 'package:repertory/helpers.dart'; import 'package:repertory/models/mount.dart'; import 'package:repertory/utils/safe_set_state_mixin.dart'; -import 'package:repertory/widgets/app_edit_path_button.dart'; +import 'package:repertory/widgets/app_outlined_icon_button.dart'; import 'package:repertory/widgets/app_icon_button_framed.dart'; import 'package:repertory/widgets/app_toggle_button_framed.dart'; @@ -93,7 +93,9 @@ class _MountWidgetState extends State const SizedBox(height: constants.padding), Row( children: [ - AppEditPathButton( + AppOutlinedIconButton( + text: 'Edit path', + icon: Icons.edit, enabled: mount.mounted == false, onPressed: () async { if (!_editEnabled) {