[ui] UI theme should match repertory blue #61
All checks were successful
BlockStorage/repertory/pipeline/head This commit looks good

This commit is contained in:
2025-09-05 07:53:47 -05:00
parent da0e2ddb46
commit cd28953324
10 changed files with 130 additions and 75 deletions

View File

@@ -468,13 +468,15 @@ Scaffold createCommonScaffold(
InputDecoration createCommonDecoration( InputDecoration createCommonDecoration(
ColorScheme colorScheme, ColorScheme colorScheme,
String label, { String label, {
IconData? icon,
bool filled = true, bool filled = true,
String? hintText,
IconData? icon,
}) => InputDecoration( }) => InputDecoration(
labelText: label, labelText: label,
prefixIcon: icon == null ? null : Icon(icon), prefixIcon: icon == null ? null : Icon(icon),
filled: filled, filled: filled,
fillColor: colorScheme.primary.withValues(alpha: constants.primaryAlpha), fillColor: colorScheme.primary.withValues(alpha: constants.primaryAlpha),
hintText: hintText,
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(constants.borderRadiusSmall), borderRadius: BorderRadius.circular(constants.borderRadiusSmall),
borderSide: BorderSide.none, borderSide: BorderSide.none,

View File

@@ -10,6 +10,7 @@ import 'package:repertory/models/auth.dart';
import 'package:repertory/models/mount.dart'; import 'package:repertory/models/mount.dart';
import 'package:repertory/models/mount_list.dart'; import 'package:repertory/models/mount_list.dart';
import 'package:repertory/types/mount_config.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_dropdown.dart';
import 'package:repertory/widgets/mount_settings.dart'; import 'package:repertory/widgets/mount_settings.dart';
@@ -21,7 +22,8 @@ class AddMountScreen extends StatefulWidget {
State<AddMountScreen> createState() => _AddMountScreenState(); State<AddMountScreen> createState() => _AddMountScreenState();
} }
class _AddMountScreenState extends State<AddMountScreen> { class _AddMountScreenState extends State<AddMountScreen>
with SafeSetState<AddMountScreen> {
Mount? _mount; Mount? _mount;
final _mountNameController = TextEditingController(); final _mountNameController = TextEditingController();
String _mountType = ""; String _mountType = "";
@@ -161,8 +163,9 @@ class _AddMountScreenState extends State<AddMountScreen> {
decoration: createCommonDecoration( decoration: createCommonDecoration(
scheme, scheme,
'Configuration Name', 'Configuration Name',
hintText: 'Enter a unique name',
icon: Icons.drive_file_rename_outline, icon: Icons.drive_file_rename_outline,
).copyWith(hintText: 'Enter a unique name'), ),
), ),
], ],
if (_mount != null) ...[ if (_mount != null) ...[
@@ -323,10 +326,4 @@ class _AddMountScreenState extends State<AddMountScreen> {
success ? "Success" : "Provider settings are invalid!", success ? "Success" : "Provider settings are invalid!",
); );
} }
@override
void setState(VoidCallback fn) {
if (!mounted) return;
super.setState(fn);
}
} }

View File

@@ -7,6 +7,7 @@ import 'package:repertory/constants.dart' as constants;
import 'package:repertory/helpers.dart'; import 'package:repertory/helpers.dart';
import 'package:repertory/models/auth.dart'; import 'package:repertory/models/auth.dart';
import 'package:repertory/models/settings.dart'; import 'package:repertory/models/settings.dart';
import 'package:repertory/widgets/app_text_field.dart';
import 'package:repertory/widgets/aurora_sweep.dart'; import 'package:repertory/widgets/aurora_sweep.dart';
class AuthScreen extends StatefulWidget { class AuthScreen extends StatefulWidget {
@@ -226,15 +227,12 @@ class _AuthScreenState extends State<AuthScreen> {
const SizedBox( const SizedBox(
height: constants.padding * 2.0, height: constants.padding * 2.0,
), ),
TextFormField( AppTextField(
autofocus: true, autofocus: true,
controller: _userController, controller: _userController,
textInputAction: TextInputAction.next,
decoration: createCommonDecoration(
scheme,
'Username',
icon: Icons.person, icon: Icons.person,
), labelText: 'Username',
textInputAction: TextInputAction.next,
validator: (v) { validator: (v) {
if (v == null || v.trim().isEmpty) { if (v == null || v.trim().isEmpty) {
return 'Enter your username'; return 'Enter your username';
@@ -246,17 +244,11 @@ class _AuthScreenState extends State<AuthScreen> {
}, },
), ),
const SizedBox(height: constants.padding), const SizedBox(height: constants.padding),
AppTextField(
TextFormField(
controller: _passwordController, controller: _passwordController,
obscureText: _obscure,
textInputAction: TextInputAction.go,
decoration:
createCommonDecoration(
scheme,
'Password',
icon: Icons.lock, icon: Icons.lock,
).copyWith( labelText: 'Password',
obscureText: _obscure,
suffixIcon: IconButton( suffixIcon: IconButton(
tooltip: _obscure tooltip: _obscure
? 'Show password' ? 'Show password'
@@ -272,7 +264,7 @@ class _AuthScreenState extends State<AuthScreen> {
}); });
}, },
), ),
), textInputAction: TextInputAction.go,
validator: (v) { validator: (v) {
if (v == null || v.isEmpty) { if (v == null || v.isEmpty) {
return 'Enter your password'; return 'Enter your password';

View File

@@ -8,6 +8,7 @@ import 'package:repertory/constants.dart' as constants;
import 'package:repertory/helpers.dart'; import 'package:repertory/helpers.dart';
import 'package:repertory/models/auth.dart'; import 'package:repertory/models/auth.dart';
import 'package:repertory/models/mount.dart'; import 'package:repertory/models/mount.dart';
import 'package:repertory/utils/safe_set_state_mixin.dart';
import 'package:repertory/widgets/mount_settings.dart'; import 'package:repertory/widgets/mount_settings.dart';
class EditMountScreen extends StatefulWidget { class EditMountScreen extends StatefulWidget {
@@ -19,7 +20,8 @@ class EditMountScreen extends StatefulWidget {
State<EditMountScreen> createState() => _EditMountScreenState(); State<EditMountScreen> createState() => _EditMountScreenState();
} }
class _EditMountScreenState extends State<EditMountScreen> { class _EditMountScreenState extends State<EditMountScreen>
with SafeSetState<EditMountScreen> {
bool _showAdvanced = false; bool _showAdvanced = false;
@override @override
@@ -186,10 +188,4 @@ class _EditMountScreenState extends State<EditMountScreen> {
), ),
]); ]);
} }
@override
void setState(VoidCallback fn) {
if (!mounted) return;
super.setState(fn);
}
} }

View File

@@ -9,6 +9,7 @@ import 'package:provider/provider.dart';
import 'package:repertory/constants.dart' as constants; import 'package:repertory/constants.dart' as constants;
import 'package:repertory/helpers.dart'; import 'package:repertory/helpers.dart';
import 'package:repertory/models/auth.dart'; import 'package:repertory/models/auth.dart';
import 'package:repertory/utils/safe_set_state_mixin.dart';
import 'package:repertory/widgets/ui_settings.dart'; import 'package:repertory/widgets/ui_settings.dart';
class EditSettingsScreen extends StatefulWidget { class EditSettingsScreen extends StatefulWidget {
@@ -19,7 +20,8 @@ class EditSettingsScreen extends StatefulWidget {
State<EditSettingsScreen> createState() => _EditSettingsScreenState(); State<EditSettingsScreen> createState() => _EditSettingsScreenState();
} }
class _EditSettingsScreenState extends State<EditSettingsScreen> { class _EditSettingsScreenState extends State<EditSettingsScreen>
with SafeSetState<EditSettingsScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final scheme = Theme.of(context).colorScheme; final scheme = Theme.of(context).colorScheme;
@@ -174,12 +176,4 @@ class _EditSettingsScreenState extends State<EditSettingsScreen> {
return {}; return {};
} }
@override
void setState(VoidCallback fn) {
if (!mounted) {
return;
}
super.setState(fn);
}
} }

View File

@@ -0,0 +1,14 @@
// safe_set_state_mixin.dart
import 'package:flutter/widgets.dart';
mixin SafeSetState<T extends StatefulWidget> on State<T> {
@override
void setState(VoidCallback fn) {
if (!mounted) {
return;
}
super.setState(fn);
}
}

View File

@@ -0,0 +1,66 @@
import 'package:flutter/material.dart';
import 'package:repertory/helpers.dart' as helpers;
class AppTextField extends StatelessWidget {
const AppTextField({
super.key,
this.autofocus = false,
this.controller,
this.enabled = true,
this.hintText,
this.icon,
this.keyboardType,
this.labelText,
this.maxLines = 1,
this.obscureText = false,
this.onChanged,
this.onFieldSubmitted,
this.suffixIcon,
this.textInputAction,
this.validator,
});
final bool autofocus;
final TextEditingController? controller;
final bool enabled;
final String? hintText;
final IconData? icon;
final TextInputType? keyboardType;
final String? labelText;
final int? maxLines;
final bool obscureText;
final ValueChanged<String>? onChanged;
final ValueChanged<String>? onFieldSubmitted;
final Widget? suffixIcon;
final TextInputAction? textInputAction;
final FormFieldValidator<String>? validator;
@override
Widget build(BuildContext context) {
final scheme = Theme.of(context).colorScheme;
final decoration = helpers
.createCommonDecoration(
scheme,
filled: true,
hintText: hintText,
icon: icon,
labelText ?? '',
)
.copyWith(suffixIcon: suffixIcon);
return TextFormField(
autofocus: autofocus,
controller: controller,
decoration: decoration,
enabled: enabled,
keyboardType: keyboardType,
maxLines: maxLines,
obscureText: obscureText,
onChanged: onChanged,
onFieldSubmitted: onFieldSubmitted,
textInputAction: textInputAction,
validator: validator,
);
}
}

View File

@@ -1042,8 +1042,14 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
@override @override
void setState(VoidCallback fn) { void setState(VoidCallback fn) {
if (!mounted) return; if (!mounted) {
if (widget.onChanged != null) widget.onChanged!(); return;
}
if (widget.onChanged != null) {
widget.onChanged!();
}
super.setState(fn); super.setState(fn);
} }
} }

View File

@@ -6,6 +6,7 @@ import 'package:provider/provider.dart';
import 'package:repertory/constants.dart' as constants; import 'package:repertory/constants.dart' as constants;
import 'package:repertory/helpers.dart'; import 'package:repertory/helpers.dart';
import 'package:repertory/models/mount.dart'; import 'package:repertory/models/mount.dart';
import 'package:repertory/utils/safe_set_state_mixin.dart';
class MountWidget extends StatefulWidget { class MountWidget extends StatefulWidget {
const MountWidget({super.key}); const MountWidget({super.key});
@@ -14,7 +15,8 @@ class MountWidget extends StatefulWidget {
State<MountWidget> createState() => _MountWidgetState(); State<MountWidget> createState() => _MountWidgetState();
} }
class _MountWidgetState extends State<MountWidget> { class _MountWidgetState extends State<MountWidget>
with SafeSetState<MountWidget> {
bool _enabled = true; bool _enabled = true;
bool _editEnabled = true; bool _editEnabled = true;
Timer? _timer; Timer? _timer;
@@ -286,14 +288,6 @@ class _MountWidgetState extends State<MountWidget> {
_timer = null; _timer = null;
super.dispose(); super.dispose();
} }
@override
void setState(VoidCallback fn) {
if (!mounted) {
return;
}
super.setState(fn);
}
} }
class _FramedBox extends StatelessWidget { class _FramedBox extends StatelessWidget {

View File

@@ -17,6 +17,7 @@ import 'package:repertory/helpers.dart'
trimNotEmptyValidator; trimNotEmptyValidator;
import 'package:repertory/models/auth.dart'; import 'package:repertory/models/auth.dart';
import 'package:repertory/settings.dart'; import 'package:repertory/settings.dart';
import 'package:repertory/utils/safe_set_state_mixin.dart';
import 'package:settings_ui/settings_ui.dart'; import 'package:settings_ui/settings_ui.dart';
class UISettingsWidget extends StatefulWidget { class UISettingsWidget extends StatefulWidget {
@@ -34,7 +35,8 @@ class UISettingsWidget extends StatefulWidget {
State<UISettingsWidget> createState() => _UISettingsWidgetState(); State<UISettingsWidget> createState() => _UISettingsWidgetState();
} }
class _UISettingsWidgetState extends State<UISettingsWidget> { class _UISettingsWidgetState extends State<UISettingsWidget>
with SafeSetState<UISettingsWidget> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final scheme = Theme.of(context).colorScheme; final scheme = Theme.of(context).colorScheme;
@@ -164,12 +166,4 @@ class _UISettingsWidgetState extends State<UISettingsWidget> {
super.dispose(); super.dispose();
} }
@override
void setState(VoidCallback fn) {
if (!mounted) {
return;
}
super.setState(fn);
}
} }