[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-04 10:59:36 -05:00
parent 58451858fd
commit d1183c00af
9 changed files with 750 additions and 944 deletions

View File

@@ -1,11 +1,16 @@
// helpers.dart
import 'dart:ui';
import 'package:convert/convert.dart';
import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:repertory/constants.dart' as constants;
import 'package:repertory/models/auth.dart';
import 'package:repertory/models/settings.dart';
import 'package:repertory/widgets/aurora_sweep.dart';
import 'package:sodium_libs/sodium_libs.dart' show SecureKey, StringX;
Future doShowDialog(BuildContext context, Widget child) => showDialog(
@@ -426,3 +431,56 @@ Future<String?> editMountLocation(
),
);
}
Scaffold createCommonScaffold(Widget child, {Widget? floatingActionButton}) =>
Scaffold(
body: SafeArea(
child: Stack(
children: [
Container(
width: double.infinity,
height: double.infinity,
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: constants.gradientColors,
),
),
),
Consumer<Settings>(
builder: (_, settings, _) =>
AuroraSweep(enabled: settings.enableAnimations),
),
Positioned.fill(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 6, sigmaY: 6),
child: Container(color: Colors.black.withValues(alpha: 0.06)),
),
),
child,
],
),
),
floatingActionButton: floatingActionButton,
);
InputDecoration createCommonDecoration(
ColorScheme colorScheme,
String label,
IconData icon,
) => InputDecoration(
labelText: label,
prefixIcon: Icon(icon),
filled: true,
fillColor: colorScheme.primary.withValues(alpha: constants.primaryAlpha),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(constants.borderRadiusSmall),
borderSide: BorderSide.none,
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(constants.borderRadiusSmall),
borderSide: BorderSide(color: colorScheme.primary, width: 2),
),
contentPadding: const EdgeInsets.all(constants.paddingSmall),
);

View File

@@ -9,9 +9,7 @@ import 'package:repertory/helpers.dart';
import 'package:repertory/models/auth.dart';
import 'package:repertory/models/mount.dart';
import 'package:repertory/models/mount_list.dart';
import 'package:repertory/models/settings.dart';
import 'package:repertory/types/mount_config.dart';
import 'package:repertory/widgets/aurora_sweep.dart';
import 'package:repertory/widgets/mount_settings.dart';
class AddMountScreen extends StatefulWidget {
@@ -46,15 +44,149 @@ class _AddMountScreenState extends State<AddMountScreen> {
final scheme = Theme.of(context).colorScheme;
final textTheme = Theme.of(context).textTheme;
Widget glassTile({required Widget child, EdgeInsets? padding}) {
return Container(
decoration: BoxDecoration(
color: scheme.primary.withValues(alpha: constants.primaryAlpha),
return createCommonScaffold(
Padding(
padding: const EdgeInsets.all(constants.padding),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// Header
Row(
children: [
Material(
color: Colors.transparent,
child: InkWell(
borderRadius: BorderRadius.circular(constants.borderRadius),
onTap: () => Navigator.of(context).pop(),
child: Ink(
width: 40,
height: 40,
decoration: BoxDecoration(
color: scheme.surface.withValues(alpha: 0.40),
borderRadius: BorderRadius.circular(
constants.borderRadius,
),
border: Border.all(
color: scheme.outlineVariant.withValues(alpha: 0.08),
width: 1,
),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.22),
blurRadius: constants.borderRadius,
offset: Offset(0, constants.borderRadius),
),
],
),
child: const Icon(Icons.arrow_back),
),
),
),
const SizedBox(width: constants.padding),
Expanded(
child: Text(
widget.title,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: textTheme.headlineSmall?.copyWith(
fontWeight: FontWeight.w700,
letterSpacing: 0.2,
color: scheme.onSurface.withValues(alpha: 0.96),
),
),
),
const SizedBox(width: constants.padding),
ClipRRect(
borderRadius: BorderRadius.circular(constants.borderRadius),
child: BackdropFilter(
filter: ImageFilter.blur(
sigmaX: constants.borderRadius,
sigmaY: constants.borderRadius,
),
child: Container(
height: 40,
padding: const EdgeInsets.symmetric(horizontal: 6),
decoration: BoxDecoration(
color: scheme.surface.withValues(alpha: 0.40),
borderRadius: BorderRadius.circular(
constants.borderRadius,
),
border: Border.all(
color: scheme.outlineVariant.withValues(alpha: 0.08),
width: 1,
),
),
child: Consumer<Auth>(
builder: (context, auth, _) => IconButton(
tooltip: 'Log out',
icon: const Icon(Icons.logout),
onPressed: auth.logoff,
),
),
),
),
),
],
),
const SizedBox(height: constants.padding),
DropdownButtonFormField<String>(
initialValue: _mountType.isEmpty ? null : _mountType,
decoration: createCommonDecoration(
scheme,
'Provider Type',
Icons.cloud_outlined,
),
isExpanded: true,
items: constants.providerTypeList
.map<DropdownMenuItem<String>>(
(item) => DropdownMenuItem<String>(
value: item,
child: Text(item),
),
)
.toList(),
onChanged: (mountType) => _handleChange(
Provider.of<Auth>(context, listen: false),
mountType ?? '',
),
),
// Configuration name (only when not Remote)
if (_mountType.isNotEmpty && _mountType != 'Remote') ...[
const SizedBox(height: constants.padding),
TextField(
autofocus: true,
controller: _mountNameController,
keyboardType: TextInputType.text,
inputFormatters: [
FilteringTextInputFormatter.deny(RegExp(r'\s')),
],
onChanged: (_) => _handleChange(
Provider.of<Auth>(context, listen: false),
_mountType,
),
decoration: createCommonDecoration(
scheme,
'Configuration Name',
Icons.drive_file_rename_outline,
).copyWith(hintText: 'Enter a unique name'),
),
],
// Settings + Actions
if (_mount != null) ...[
const SizedBox(height: constants.padding),
Expanded(
child: Container(
decoration: BoxDecoration(
color: scheme.primary.withValues(
alpha: constants.primaryAlpha,
),
borderRadius: BorderRadius.circular(constants.borderRadius),
border: Border.all(
color: scheme.outlineVariant.withValues(alpha: 0.06),
width: 1,
),
gradient: const LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
@@ -70,220 +202,6 @@ class _AddMountScreenState extends State<AddMountScreen> {
),
child: ClipRRect(
borderRadius: BorderRadius.circular(constants.borderRadius),
child: Padding(
padding: padding ?? const EdgeInsets.all(constants.padding),
child: child,
),
),
);
}
return Scaffold(
body: SafeArea(
child: Stack(
children: [
Container(
width: double.infinity,
height: double.infinity,
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: constants.gradientColors,
),
),
),
Consumer<Settings>(
builder: (_, settings, _) {
return AuroraSweep(enabled: settings.enableAnimations);
},
),
Positioned.fill(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 6, sigmaY: 6),
child: Container(color: Colors.black.withValues(alpha: 0.06)),
),
),
Padding(
padding: const EdgeInsets.all(constants.padding),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Row(
children: [
Material(
color: Colors.transparent,
child: InkWell(
borderRadius: BorderRadius.circular(
constants.borderRadius,
),
onTap: () {
Navigator.of(context).pop();
},
child: Ink(
width: 40,
height: 40,
decoration: BoxDecoration(
color: scheme.surface.withValues(alpha: 0.40),
borderRadius: BorderRadius.circular(
constants.borderRadius,
),
border: Border.all(
color: scheme.outlineVariant.withValues(
alpha: 0.08,
),
width: 1,
),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.22),
blurRadius: constants.borderRadius,
offset: Offset(0, constants.borderRadius),
),
],
),
child: const Icon(Icons.arrow_back),
),
),
),
const SizedBox(width: constants.padding),
Expanded(
child: Text(
widget.title,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: textTheme.headlineSmall?.copyWith(
fontWeight: FontWeight.w700,
letterSpacing: 0.2,
color: scheme.onSurface.withValues(alpha: 0.96),
),
),
),
const SizedBox(width: constants.padding),
ClipRRect(
borderRadius: BorderRadius.circular(
constants.borderRadius,
),
child: BackdropFilter(
filter: ImageFilter.blur(
sigmaX: constants.borderRadius,
sigmaY: constants.borderRadius,
),
child: Container(
height: 40,
padding: const EdgeInsets.symmetric(horizontal: 6),
decoration: BoxDecoration(
color: scheme.surface.withValues(alpha: 0.40),
borderRadius: BorderRadius.circular(
constants.borderRadius,
),
border: Border.all(
color: scheme.outlineVariant.withValues(
alpha: 0.08,
),
width: 1,
),
),
child: Consumer<Auth>(
builder: (context, auth, _) {
return IconButton(
tooltip: 'Log out',
icon: const Icon(Icons.logout),
onPressed: () {
auth.logoff();
},
);
},
),
),
),
),
],
),
const SizedBox(height: constants.padding),
glassTile(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
'Provider Type',
style: textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.w600,
),
),
const SizedBox(width: constants.padding),
DropdownButton<String>(
value: _mountType.isEmpty ? null : _mountType,
autofocus: true,
underline: const SizedBox.shrink(),
onChanged: (mountType) {
_handleChange(
Provider.of<Auth>(context, listen: false),
mountType ?? '',
);
},
items: constants.providerTypeList
.map<DropdownMenuItem<String>>((item) {
return DropdownMenuItem<String>(
value: item,
child: Text(item),
);
})
.toList(),
),
],
),
),
if (_mountType.isNotEmpty && _mountType != 'Remote') ...[
const SizedBox(height: constants.padding),
glassTile(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Configuration Name',
style: textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 8),
TextField(
autofocus: true,
controller: _mountNameController,
keyboardType: TextInputType.text,
inputFormatters: [
FilteringTextInputFormatter.deny(RegExp(r'\s')),
],
onChanged: (_) => _handleChange(
Provider.of<Auth>(context, listen: false),
_mountType,
),
decoration: InputDecoration(
hintText: 'Enter a unique name',
filled: true,
fillColor: scheme.surface.withValues(alpha: 0.30),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(
constants.borderRadius,
),
borderSide: BorderSide.none,
),
contentPadding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 12,
),
),
),
],
),
),
],
if (_mount != null) ...[
const SizedBox(height: constants.padding),
Expanded(
child: glassTile(
padding: EdgeInsets.zero,
child: Padding(
padding: const EdgeInsets.all(constants.padding),
child: MountSettingsWidget(
@@ -295,6 +213,7 @@ class _AddMountScreenState extends State<AddMountScreen> {
),
),
),
),
const SizedBox(height: constants.padding),
Row(
children: [
@@ -303,9 +222,7 @@ class _AddMountScreenState extends State<AddMountScreen> {
label: const Text('Test'),
icon: const Icon(Icons.check),
style: ElevatedButton.styleFrom(
backgroundColor: scheme.primary.withValues(
alpha: 0.18,
),
backgroundColor: scheme.primary.withValues(alpha: 0.18),
foregroundColor: scheme.primary,
elevation: 0,
shape: RoundedRectangleBorder(
@@ -332,9 +249,7 @@ class _AddMountScreenState extends State<AddMountScreen> {
backgroundColor: scheme.primary,
foregroundColor: scheme.onPrimary,
elevation: 8,
shadowColor: scheme.primary.withValues(
alpha: 0.45,
),
shadowColor: scheme.primary.withValues(alpha: 0.45),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
constants.borderRadius,
@@ -348,10 +263,7 @@ class _AddMountScreenState extends State<AddMountScreen> {
);
List<String> failed = [];
if (!validateSettings(
_settings[_mountType]!,
failed,
)) {
if (!validateSettings(_settings[_mountType]!, failed)) {
for (var key in failed) {
displayErrorMessage(
context,
@@ -374,10 +286,7 @@ class _AddMountScreenState extends State<AddMountScreen> {
final bucket =
_settings[_mountType]!["${_mountType}Config"]["Bucket"]
as String;
if (mountList.hasBucketName(
_mountType,
bucket,
)) {
if (mountList.hasBucketName(_mountType, bucket)) {
return displayErrorMessage(
context,
"Bucket '$bucket' already exists",
@@ -393,9 +302,7 @@ class _AddMountScreenState extends State<AddMountScreen> {
_settings[_mountType]!,
);
if (!success || !context.mounted) {
return;
}
if (!success || !context.mounted) return;
Navigator.pop(context);
},
@@ -407,9 +314,6 @@ class _AddMountScreenState extends State<AddMountScreen> {
],
),
),
],
),
),
);
}
@@ -440,14 +344,10 @@ class _AddMountScreenState extends State<AddMountScreen> {
}
Future<void> _handleProviderTest() async {
if (_mount == null) {
return;
}
if (_mount == null) return;
final success = await _mount!.test();
if (!mounted) {
return;
}
if (!mounted) return;
displayErrorMessage(
context,
@@ -457,9 +357,7 @@ class _AddMountScreenState extends State<AddMountScreen> {
@override
void setState(VoidCallback fn) {
if (!mounted) {
return;
}
if (!mounted) return;
super.setState(fn);
}
}

View File

@@ -4,6 +4,7 @@ import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:repertory/constants.dart' as constants;
import 'package:repertory/helpers.dart';
import 'package:repertory/models/auth.dart';
import 'package:repertory/models/settings.dart';
import 'package:repertory/widgets/aurora_sweep.dart';
@@ -35,22 +36,6 @@ class _AuthScreenState extends State<AuthScreen> {
Widget build(BuildContext context) {
final scheme = Theme.of(context).colorScheme;
InputDecoration decoration(String label, IconData icon) => InputDecoration(
labelText: label,
prefixIcon: Icon(icon),
filled: true,
fillColor: scheme.primary.withValues(alpha: constants.primaryAlpha),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(constants.borderRadiusSmall),
borderSide: BorderSide.none,
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(constants.borderRadiusSmall),
borderSide: BorderSide(color: scheme.primary, width: 2),
),
contentPadding: const EdgeInsets.all(constants.paddingSmall),
);
Future<void> doLogin(Auth auth) async {
if (!_enabled) {
return;
@@ -99,9 +84,8 @@ class _AuthScreenState extends State<AuthScreen> {
),
),
Consumer<Settings>(
builder: (_, settings, _) {
return AuroraSweep(enabled: settings.enableAnimations);
},
builder: (_, settings, _) =>
AuroraSweep(enabled: settings.enableAnimations),
),
Positioned.fill(
child: BackdropFilter(
@@ -246,7 +230,8 @@ class _AuthScreenState extends State<AuthScreen> {
autofocus: true,
controller: _userController,
textInputAction: TextInputAction.next,
decoration: decoration(
decoration: createCommonDecoration(
scheme,
'Username',
Icons.person,
),
@@ -267,7 +252,8 @@ class _AuthScreenState extends State<AuthScreen> {
obscureText: _obscure,
textInputAction: TextInputAction.go,
decoration:
decoration(
createCommonDecoration(
scheme,
'Password',
Icons.lock,
).copyWith(

View File

@@ -1,15 +1,13 @@
// edit_mount_screen.dart
import 'dart:convert';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:repertory/constants.dart' as constants;
import 'package:repertory/helpers.dart';
import 'package:repertory/models/auth.dart';
import 'package:repertory/models/mount.dart';
import 'package:repertory/models/settings.dart';
import 'package:repertory/widgets/aurora_sweep.dart';
import 'package:repertory/widgets/mount_settings.dart';
class EditMountScreen extends StatefulWidget {
@@ -29,51 +27,20 @@ class _EditMountScreenState extends State<EditMountScreen> {
final scheme = Theme.of(context).colorScheme;
final textTheme = Theme.of(context).textTheme;
return Scaffold(
body: SafeArea(
child: Stack(
children: [
Container(
width: double.infinity,
height: double.infinity,
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: constants.gradientColors,
),
),
),
Consumer<Settings>(
builder: (_, settings, _) {
return AuroraSweep(enabled: settings.enableAnimations);
},
),
Positioned.fill(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 6, sigmaY: 6),
child: Container(color: Colors.black.withValues(alpha: 0.06)),
),
),
return createCommonScaffold(
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(height: constants.padding),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: constants.padding,
),
padding: const EdgeInsets.symmetric(horizontal: constants.padding),
child: Row(
children: [
Material(
color: Colors.transparent,
child: InkWell(
borderRadius: BorderRadius.circular(
constants.borderRadius,
),
onTap: () {
Navigator.of(context).pop();
},
borderRadius: BorderRadius.circular(constants.borderRadius),
onTap: () => Navigator.of(context).pop(),
child: Ink(
width: 40,
height: 40,
@@ -83,9 +50,7 @@ class _EditMountScreenState extends State<EditMountScreen> {
constants.borderRadius,
),
border: Border.all(
color: scheme.outlineVariant.withValues(
alpha: 0.08,
),
color: scheme.outlineVariant.withValues(alpha: 0.08),
width: 1,
),
boxShadow: [
@@ -115,9 +80,7 @@ class _EditMountScreenState extends State<EditMountScreen> {
),
const SizedBox(width: constants.padding),
ClipRRect(
borderRadius: BorderRadius.circular(
constants.borderRadius,
),
borderRadius: BorderRadius.circular(constants.borderRadius),
child: BackdropFilter(
filter: ImageFilter.blur(
sigmaX: constants.borderRadius,
@@ -132,9 +95,7 @@ class _EditMountScreenState extends State<EditMountScreen> {
constants.borderRadius,
),
border: Border.all(
color: scheme.outlineVariant.withValues(
alpha: 0.08,
),
color: scheme.outlineVariant.withValues(alpha: 0.08),
width: 1,
),
),
@@ -144,9 +105,7 @@ class _EditMountScreenState extends State<EditMountScreen> {
Text(
"Advanced",
style: textTheme.labelLarge?.copyWith(
color: scheme.onSurface.withValues(
alpha: 0.90,
),
color: scheme.onSurface.withValues(alpha: 0.90),
),
),
const SizedBox(width: 6),
@@ -161,14 +120,9 @@ class _EditMountScreenState extends State<EditMountScreen> {
),
color: _showAdvanced
? scheme.primary
: scheme.onSurface.withValues(
alpha: 0.70,
),
onPressed: () {
setState(() {
_showAdvanced = !_showAdvanced;
});
},
: scheme.onSurface.withValues(alpha: 0.70),
onPressed: () =>
setState(() => _showAdvanced = !_showAdvanced),
),
],
),
@@ -177,9 +131,7 @@ class _EditMountScreenState extends State<EditMountScreen> {
),
const SizedBox(width: constants.padding),
ClipRRect(
borderRadius: BorderRadius.circular(
constants.borderRadius,
),
borderRadius: BorderRadius.circular(constants.borderRadius),
child: BackdropFilter(
filter: ImageFilter.blur(
sigmaX: constants.borderRadius,
@@ -194,22 +146,16 @@ class _EditMountScreenState extends State<EditMountScreen> {
constants.borderRadius,
),
border: Border.all(
color: scheme.outlineVariant.withValues(
alpha: 0.08,
),
color: scheme.outlineVariant.withValues(alpha: 0.08),
width: 1,
),
),
child: Consumer<Auth>(
builder: (context, auth, _) {
return IconButton(
builder: (context, auth, _) => IconButton(
tooltip: 'Log out',
icon: const Icon(Icons.logout),
onPressed: () {
auth.logoff();
},
);
},
onPressed: auth.logoff,
),
),
),
),
@@ -227,14 +173,12 @@ class _EditMountScreenState extends State<EditMountScreen> {
color: Colors.transparent,
child: Container(
decoration: BoxDecoration(
color: scheme.surface.withValues(alpha: 0.40),
borderRadius: BorderRadius.circular(
constants.borderRadius,
color: scheme.primary.withValues(
alpha: constants.primaryAlpha,
),
borderRadius: BorderRadius.circular(constants.borderRadius),
border: Border.all(
color: scheme.outlineVariant.withValues(
alpha: 0.06,
),
color: scheme.outlineVariant.withValues(alpha: 0.06),
width: 1,
),
gradient: const LinearGradient(
@@ -251,9 +195,9 @@ class _EditMountScreenState extends State<EditMountScreen> {
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(
constants.borderRadius,
),
borderRadius: BorderRadius.circular(constants.borderRadius),
child: Padding(
padding: const EdgeInsets.all(constants.padding),
child: MountSettingsWidget(
mount: widget.mount,
settings: jsonDecode(
@@ -266,21 +210,17 @@ class _EditMountScreenState extends State<EditMountScreen> {
),
),
),
),
const SizedBox(height: constants.padding),
],
),
],
),
),
);
}
@override
void setState(VoidCallback fn) {
if (!mounted) {
return;
}
if (!mounted) return;
super.setState(fn);
}
}

View File

@@ -9,8 +9,6 @@ import 'package:provider/provider.dart';
import 'package:repertory/constants.dart' as constants;
import 'package:repertory/helpers.dart';
import 'package:repertory/models/auth.dart';
import 'package:repertory/models/settings.dart';
import 'package:repertory/widgets/aurora_sweep.dart';
import 'package:repertory/widgets/ui_settings.dart';
class EditSettingsScreen extends StatefulWidget {
@@ -27,48 +25,19 @@ class _EditSettingsScreenState extends State<EditSettingsScreen> {
final scheme = Theme.of(context).colorScheme;
final textTheme = Theme.of(context).textTheme;
return Scaffold(
body: SafeArea(
child: Stack(
children: [
Container(
width: double.infinity,
height: double.infinity,
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: constants.gradientColors,
),
),
),
Consumer<Settings>(
builder: (_, settings, _) {
return AuroraSweep(enabled: settings.enableAnimations);
},
),
Positioned.fill(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 6, sigmaY: 6),
child: Container(color: Colors.black.withValues(alpha: 0.06)),
),
),
return createCommonScaffold(
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(height: constants.padding),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: constants.padding,
),
padding: const EdgeInsets.symmetric(horizontal: constants.padding),
child: Row(
children: [
Material(
color: Colors.transparent,
child: InkWell(
borderRadius: BorderRadius.circular(
constants.borderRadius,
),
borderRadius: BorderRadius.circular(constants.borderRadius),
onTap: () {
Navigator.of(context).pop();
},
@@ -81,9 +50,7 @@ class _EditSettingsScreenState extends State<EditSettingsScreen> {
constants.borderRadius,
),
border: Border.all(
color: scheme.outlineVariant.withValues(
alpha: 0.08,
),
color: scheme.outlineVariant.withValues(alpha: 0.08),
width: 1,
),
boxShadow: [
@@ -113,9 +80,7 @@ class _EditSettingsScreenState extends State<EditSettingsScreen> {
),
const SizedBox(width: constants.padding),
ClipRRect(
borderRadius: BorderRadius.circular(
constants.borderRadius,
),
borderRadius: BorderRadius.circular(constants.borderRadius),
child: BackdropFilter(
filter: ImageFilter.blur(
sigmaX: constants.borderRadius,
@@ -130,9 +95,7 @@ class _EditSettingsScreenState extends State<EditSettingsScreen> {
constants.borderRadius,
),
border: Border.all(
color: scheme.outlineVariant.withValues(
alpha: 0.08,
),
color: scheme.outlineVariant.withValues(alpha: 0.08),
width: 1,
),
),
@@ -164,13 +127,9 @@ class _EditSettingsScreenState extends State<EditSettingsScreen> {
child: Container(
decoration: BoxDecoration(
color: scheme.surface.withValues(alpha: 0.40),
borderRadius: BorderRadius.circular(
constants.borderRadius,
),
borderRadius: BorderRadius.circular(constants.borderRadius),
border: Border.all(
color: scheme.outlineVariant.withValues(
alpha: 0.06,
),
color: scheme.outlineVariant.withValues(alpha: 0.06),
width: 1,
),
gradient: const LinearGradient(
@@ -187,9 +146,7 @@ class _EditSettingsScreenState extends State<EditSettingsScreen> {
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(
constants.borderRadius,
),
borderRadius: BorderRadius.circular(constants.borderRadius),
child: FutureBuilder<Map<String, dynamic>>(
future: _grabSettings(),
initialData: const <String, dynamic>{},
@@ -217,9 +174,6 @@ class _EditSettingsScreenState extends State<EditSettingsScreen> {
const SizedBox(height: constants.padding),
],
),
],
),
),
);
}

View File

@@ -4,10 +4,10 @@ import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:repertory/constants.dart' as constants;
import 'package:repertory/helpers.dart';
import 'package:repertory/models/auth.dart';
import 'package:repertory/models/settings.dart';
import 'package:repertory/widgets/mount_list_widget.dart';
import 'package:repertory/widgets/aurora_sweep.dart';
class HomeScreen extends StatefulWidget {
final String title;
@@ -23,45 +23,18 @@ class _HomeScreeState extends State<HomeScreen> {
final scheme = Theme.of(context).colorScheme;
final textTheme = Theme.of(context).textTheme;
return Scaffold(
body: SafeArea(
child: Stack(
children: [
Container(
width: double.infinity,
height: double.infinity,
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: constants.gradientColors,
),
),
),
Consumer<Settings>(
builder: (_, settings, _) {
return AuroraSweep(enabled: settings.enableAnimations);
},
),
Positioned.fill(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 6, sigmaY: 6),
child: Container(color: Colors.black.withValues(alpha: 0.06)),
),
),
return createCommonScaffold(
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(height: constants.padding),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: constants.padding,
),
padding: const EdgeInsets.symmetric(horizontal: constants.padding),
child: Row(
children: [
SizedBox(
width: 48,
height: 48,
width: 40,
height: 40,
child: Image.asset(
'assets/images/repertory.png',
fit: BoxFit.contain,
@@ -69,7 +42,7 @@ class _HomeScreeState extends State<HomeScreen> {
return Icon(
Icons.folder,
color: scheme.primary,
size: 40,
size: 32,
);
},
),
@@ -89,9 +62,7 @@ class _HomeScreeState extends State<HomeScreen> {
),
const SizedBox(width: constants.padding),
ClipRRect(
borderRadius: BorderRadius.circular(
constants.borderRadius,
),
borderRadius: BorderRadius.circular(constants.borderRadius),
child: BackdropFilter(
filter: ImageFilter.blur(
sigmaX: constants.borderRadius,
@@ -106,9 +77,7 @@ class _HomeScreeState extends State<HomeScreen> {
constants.borderRadius,
),
border: Border.all(
color: scheme.outlineVariant.withValues(
alpha: 0.08,
),
color: scheme.outlineVariant.withValues(alpha: 0.08),
width: 1,
),
),
@@ -125,12 +94,9 @@ class _HomeScreeState extends State<HomeScreen> {
),
color: settings.autoStart
? scheme.primary
: scheme.onSurface.withValues(
alpha: 0.70,
),
onPressed: () => settings.setAutoStart(
!settings.autoStart,
),
: scheme.onSurface.withValues(alpha: 0.70),
onPressed: () =>
settings.setAutoStart(!settings.autoStart),
);
},
),
@@ -171,9 +137,6 @@ class _HomeScreeState extends State<HomeScreen> {
),
],
),
],
),
),
floatingActionButton: Padding(
padding: const EdgeInsets.all(constants.padding),
child: Hero(

View File

@@ -39,10 +39,11 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
Widget build(BuildContext context) {
final scheme = Theme.of(context).colorScheme;
// Theme SettingsList to your glass aesthetic (consistent with UISettingsWidget)
final theme = SettingsThemeData(
settingsListBackground: Colors.transparent,
settingsSectionBackground: scheme.surface.withValues(alpha: 0.30),
settingsSectionBackground: scheme.primary.withValues(
alpha: constants.primaryAlpha,
),
titleTextColor: scheme.onSurface.withValues(alpha: 0.96),
trailingTextColor: scheme.onSurface.withValues(alpha: 0.80),
tileDescriptionTextColor: scheme.onSurface.withValues(alpha: 0.68),
@@ -394,6 +395,10 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
}
});
const sectionMargin = EdgeInsetsDirectional.symmetric(
vertical: constants.padding / 2,
);
return SettingsList(
shrinkWrap: false,
platform: DevicePlatform.device,
@@ -402,38 +407,48 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
sections: [
if (encryptConfigSettings.isNotEmpty)
SettingsSection(
margin: sectionMargin,
title: const Text('Encrypt Config'),
tiles: encryptConfigSettings,
),
if (hostConfigSettings.isNotEmpty)
SettingsSection(
margin: sectionMargin,
title: const Text('Host Config'),
tiles: hostConfigSettings,
),
if (remoteConfigSettings.isNotEmpty)
SettingsSection(
margin: sectionMargin,
title: const Text('Remote Config'),
tiles: remoteConfigSettings,
),
if (s3ConfigSettings.isNotEmpty)
SettingsSection(
margin: sectionMargin,
title: const Text('S3 Config'),
tiles: s3ConfigSettings,
),
if (siaConfigSettings.isNotEmpty)
SettingsSection(
margin: sectionMargin,
title: const Text('Sia Config'),
tiles: siaConfigSettings,
),
if (remoteMountSettings.isNotEmpty)
SettingsSection(
margin: sectionMargin,
title: const Text('Remote Mount'),
tiles: (widget.settings['RemoteMount']['Enable'] as bool)
? remoteMountSettings
: [remoteMountSettings[0]],
),
if (commonSettings.isNotEmpty)
SettingsSection(title: const Text('Settings'), tiles: commonSettings),
SettingsSection(
margin: sectionMargin,
title: const Text('Settings'),
tiles: commonSettings,
),
],
);
}
@@ -1017,24 +1032,18 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
});
return;
}
mount.setValue(key, value);
});
});
}
}
super.dispose();
}
@override
void setState(VoidCallback fn) {
if (!mounted) {
return;
}
if (widget.onChanged != null) {
widget.onChanged!();
}
if (!mounted) return;
if (widget.onChanged != null) widget.onChanged!();
super.setState(fn);
}
}

View File

@@ -272,7 +272,6 @@ class _MountWidgetState extends State<MountWidget> {
return location;
}
// ignore: use_build_context_synchronously
return editMountLocation(context, await mount.getAvailableLocations());
}

View File

@@ -39,18 +39,17 @@ class _UISettingsWidgetState extends State<UISettingsWidget> {
Widget build(BuildContext context) {
final scheme = Theme.of(context).colorScheme;
// Theme the SettingsList to align with your glass look
final theme = SettingsThemeData(
settingsListBackground: Colors.transparent,
tileDescriptionTextColor: scheme.onSurface.withValues(alpha: 0.68),
settingsSectionBackground: scheme.surface.withValues(
alpha: 0.30,
), // slight glass base
tileHighlightColor: scheme.primary.withValues(alpha: 0.08),
settingsSectionBackground: scheme.primary.withValues(
alpha: constants.primaryAlpha,
),
titleTextColor: scheme.onSurface.withValues(alpha: 0.96),
trailingTextColor: scheme.onSurface.withValues(alpha: 0.80),
tileDescriptionTextColor: scheme.onSurface.withValues(alpha: 0.68),
leadingIconsColor: scheme.onSurface.withValues(alpha: 0.90),
dividerColor: scheme.outlineVariant.withValues(alpha: 0.10),
tileHighlightColor: scheme.primary.withValues(alpha: 0.08),
);
List<SettingsTile> commonSettings = [];