From 01bb853d22f33f334b7e3146b70d1214c1c2faec Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Fri, 15 Aug 2025 12:54:13 -0500 Subject: [PATCH] [ui] UI theme should match repertory blue #61 --- web/repertory/lib/screens/auth_screen.dart | 389 +++++++-------------- 1 file changed, 135 insertions(+), 254 deletions(-) diff --git a/web/repertory/lib/screens/auth_screen.dart b/web/repertory/lib/screens/auth_screen.dart index 61730c48..72043100 100644 --- a/web/repertory/lib/screens/auth_screen.dart +++ b/web/repertory/lib/screens/auth_screen.dart @@ -1,4 +1,3 @@ -import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:repertory/constants.dart' as constants; @@ -79,38 +78,36 @@ class _AuthScreenState extends State { ); } - void navigateHomePostFrame() { - WidgetsBinding.instance.addPostFrameCallback((_) { - final navCtx = constants.navigatorKey.currentContext; - if (navCtx == null) { - return; - } - Navigator.of(navCtx).pushNamedAndRemoveUntil('/', (r) => false); - }); - } - return Scaffold( - appBar: AppBar( - title: Text(widget.title), - scrolledUnderElevation: 0, - backgroundColor: Theme.of( - context, - ).colorScheme.surface.withValues(alpha: 0.55), - elevation: 0, - flexibleSpace: ClipRRect( - child: BackdropFilter( - filter: ImageFilter.blur(sigmaX: 14, sigmaY: 14), - child: const SizedBox.expand(), - ), - ), - ), + appBar: AppBar(title: Text(widget.title), scrolledUnderElevation: 0), body: SafeArea( - child: CoolScaffoldBg( - enableAurora: true, + child: Container( + width: double.infinity, + height: double.infinity, + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ + Theme.of(context).colorScheme.surface, + Theme.of(context).colorScheme.surface.withValues(alpha: 0.9), + ], + stops: const [0.0, 1.0], + ), + ), child: Consumer( builder: (context, auth, _) { if (auth.authenticated) { - navigateHomePostFrame(); + Future.delayed(const Duration(milliseconds: 1), () { + if (constants.navigatorKey.currentContext == null) { + return; + } + + Navigator.of( + constants.navigatorKey.currentContext!, + ).pushNamedAndRemoveUntil('/', (r) => false); + }); + return const SizedBox.shrink(); } @@ -139,134 +136,124 @@ class _AuthScreenState extends State { key: _formKey, autovalidateMode: AutovalidateMode.onUserInteraction, - child: AutofillGroup( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Align( - alignment: Alignment.center, - child: CircleAvatar( - radius: 28, - backgroundColor: scheme.primary - .withValues(alpha: 0.18), - child: ClipRRect( - borderRadius: BorderRadius.circular(28), - child: Image.asset( - 'assets/images/repertory.png', - width: 28, - height: 28, - fit: BoxFit.contain, - errorBuilder: (_, _, _) => Icon( - Icons.folder, - color: scheme.primary, - size: 28, - ), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Align( + alignment: Alignment.center, + child: Container( + width: 56, + height: 56, + decoration: BoxDecoration( + color: scheme.primary.withValues( + alpha: 0.18, + ), + borderRadius: BorderRadius.circular(8), + ), + padding: const EdgeInsets.all(8), + child: Image.asset( + 'assets/images/repertory.png', + fit: BoxFit.contain, + errorBuilder: (_, _, _) { + return Icon( + Icons.folder, + color: scheme.primary, + size: 40, + ); + }, + ), + ), + ), + const SizedBox(height: 14), + Text( + constants.appLogonTitle, + textAlign: TextAlign.center, + style: Theme.of(context) + .textTheme + .headlineSmall + ?.copyWith(fontWeight: FontWeight.w600), + ), + const SizedBox(height: 6), + Text( + "Secure access to your mounts", + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.bodyMedium + ?.copyWith( + color: scheme.onSurface.withValues( + alpha: 0.7, ), ), - ), - ), - const SizedBox(height: 14), - Text( - constants.appLogonTitle, - textAlign: TextAlign.center, - style: Theme.of(context) - .textTheme - .headlineSmall - ?.copyWith(fontWeight: FontWeight.w600), - ), - const SizedBox(height: 6), - Text( - "Secure access to your mounts", - textAlign: TextAlign.center, - style: Theme.of(context) - .textTheme - .bodyMedium - ?.copyWith( - color: scheme.onSurface.withValues( - alpha: 0.7, - ), - ), - ), - const SizedBox(height: 20), - TextFormField( - autofocus: true, - controller: _userController, - textInputAction: TextInputAction.next, - autofillHints: const [ - AutofillHints.username, - ], - decoration: decoration( - 'Username', - Icons.person, - ), - validator: (v) => - (v == null || v.trim().isEmpty) - ? 'Enter your username' - : null, - onFieldSubmitted: (_) => - FocusScope.of(context).nextFocus(), - ), - const SizedBox(height: constants.padding), - TextFormField( - controller: _passwordController, - obscureText: _obscure, - textInputAction: TextInputAction.go, - autofillHints: const [ - AutofillHints.password, - ], - decoration: - decoration( - 'Password', - Icons.lock, - ).copyWith( - suffixIcon: IconButton( - tooltip: _obscure - ? 'Show password' - : 'Hide password', - icon: Icon( - _obscure - ? Icons.visibility - : Icons.visibility_off, - ), - onPressed: () => setState( - () => _obscure = !_obscure, - ), - ), - ), - validator: (v) => (v == null || v.isEmpty) - ? 'Enter your password' - : null, - onFieldSubmitted: (_) => doLogin(auth), - ), - const SizedBox(height: constants.padding), + ), + const SizedBox(height: 20), - SizedBox( - height: 44, - child: ElevatedButton( - onPressed: _enabled - ? () => doLogin(auth) - : null, - style: ElevatedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - 12, + TextFormField( + autofocus: true, + controller: _userController, + textInputAction: TextInputAction.next, + decoration: decoration( + 'Username', + Icons.person, + ), + validator: (v) => + (v == null || v.trim().isEmpty) + ? 'Enter your username' + : null, + onFieldSubmitted: (_) => + FocusScope.of(context).nextFocus(), + ), + const SizedBox(height: constants.padding), + + TextFormField( + controller: _passwordController, + obscureText: _obscure, + textInputAction: TextInputAction.go, + decoration: decoration('Password', Icons.lock) + .copyWith( + suffixIcon: IconButton( + tooltip: _obscure + ? 'Show password' + : 'Hide password', + icon: Icon( + _obscure + ? Icons.visibility + : Icons.visibility_off, + ), + onPressed: () => setState( + () => _obscure = !_obscure, ), ), ), - child: _enabled - ? const Text('Login') - : const SizedBox( - height: 20, - width: 20, - child: CircularProgressIndicator( - strokeWidth: 2.4, - ), - ), + validator: (v) => (v == null || v.isEmpty) + ? 'Enter your password' + : null, + onFieldSubmitted: (_) => doLogin(auth), + ), + const SizedBox(height: constants.padding), + + SizedBox( + height: 44, + child: ElevatedButton( + onPressed: _enabled + ? () => doLogin(auth) + : null, + style: ElevatedButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), ), + child: _enabled + ? const Text('Login') + : const SizedBox( + height: 20, + width: 20, + child: CircularProgressIndicator( + strokeWidth: 2.4, + ), + ), ), - ], - ), + ), + ], ), ), ), @@ -282,109 +269,3 @@ class _AuthScreenState extends State { ); } } - -class CoolScaffoldBg extends StatelessWidget { - final Widget child; - final bool enableAurora; - const CoolScaffoldBg({ - super.key, - required this.child, - this.enableAurora = true, - }); - - @override - Widget build(BuildContext context) { - final scheme = Theme.of(context).colorScheme; - - return Stack( - children: [ - Builder( - builder: (context) { - return Container( - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [ - Theme.of(context).colorScheme.primary, - Theme.of(context).colorScheme.surface, - ], - ), - ), - ); - }, - ), - if (enableAurora) const AuroraSweep(), - Align( - alignment: const Alignment(0, 0.1), - child: IgnorePointer( - child: Container( - width: 740, - height: 740, - decoration: BoxDecoration( - shape: BoxShape.circle, - gradient: RadialGradient( - colors: [ - scheme.primary.withValues(alpha: 0.22), - Colors.transparent, - ], - stops: const [0.0, 1.0], - ), - ), - ), - ), - ), - child, - ], - ); - } -} - -class AuroraSweep extends StatefulWidget { - const AuroraSweep({super.key}); - - @override - State createState() => _AuroraSweepState(); -} - -class _AuroraSweepState extends State - with SingleTickerProviderStateMixin { - late final AnimationController _c = AnimationController( - vsync: this, - duration: const Duration(seconds: 18), - )..repeat(); - - @override - void dispose() { - _c.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - final scheme = Theme.of(context).colorScheme; - - return AnimatedBuilder( - animation: _c, - builder: (_, _) { - final t = _c.value; - return IgnorePointer( - child: Container( - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment(-1 + 2 * t, -0.6), - end: Alignment(0.8 - 2 * t, 0.9), - colors: [ - scheme.primary.withValues(alpha: 0.06), - Colors.transparent, - scheme.primary.withValues(alpha: 0.04), - ], - stops: const [0.0, 0.5, 1.0], - ), - ), - ), - ); - }, - ); - } -}