From f41a53c4639a87bf68015d5cdfab2a15810ac51f Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Fri, 15 Aug 2025 13:41:00 -0500 Subject: [PATCH] [ui] UI theme should match repertory blue #61 --- web/repertory/lib/screens/auth_screen.dart | 362 ++++++++++++--------- 1 file changed, 200 insertions(+), 162 deletions(-) diff --git a/web/repertory/lib/screens/auth_screen.dart b/web/repertory/lib/screens/auth_screen.dart index 8829a914..11325eb3 100644 --- a/web/repertory/lib/screens/auth_screen.dart +++ b/web/repertory/lib/screens/auth_screen.dart @@ -56,7 +56,7 @@ class _AuthScreenState extends State { } setState(() => _enabled = false); - var authenticated = await auth.authenticate( + final authenticated = await auth.authenticate( _userController.text.trim(), _passwordController.text, ); @@ -81,189 +81,227 @@ class _AuthScreenState extends State { return Scaffold( appBar: AppBar(title: Text(widget.title), scrolledUnderElevation: 0), body: SafeArea( - child: Container( - width: double.infinity, - height: double.infinity, - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [ - Theme.of(context).colorScheme.primary.withValues(alpha: 0.4), - Theme.of(context).colorScheme.surface.withValues(alpha: 0.9), - ], - stops: const [0.0, 1.0], + child: Stack( + children: [ + Container( + width: double.infinity, + height: double.infinity, + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [Color(0xFF0A0F1F), Color(0xFF1B1C1F)], + stops: [0.0, 1.0], + ), + ), ), - ), - child: Consumer( - builder: (context, auth, _) { - if (auth.authenticated) { - Future.delayed(const Duration(milliseconds: 1), () { - if (constants.navigatorKey.currentContext == null) { - return; - } + 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], + ), + ), + ), + ), + ), + Consumer( + builder: (context, auth, _) { + if (auth.authenticated) { + Future.delayed(const Duration(milliseconds: 1), () { + if (constants.navigatorKey.currentContext == null) { + return; + } + Navigator.of( + constants.navigatorKey.currentContext!, + ).pushNamedAndRemoveUntil('/', (r) => false); + }); - Navigator.of( - constants.navigatorKey.currentContext!, - ).pushNamedAndRemoveUntil('/', (r) => false); - }); + return const SizedBox.shrink(); + } - return const SizedBox.shrink(); - } - - return Center( - child: AnimatedScale( - scale: 1.0, - duration: const Duration(milliseconds: 250), - curve: Curves.easeOutCubic, - child: AnimatedOpacity( - opacity: 1.0, + return Center( + child: AnimatedScale( + scale: 1.0, duration: const Duration(milliseconds: 250), - child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 420, - minWidth: 300, - ), - child: Card( - elevation: 12, - color: scheme.surface, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(18), + curve: Curves.easeOutCubic, + child: AnimatedOpacity( + opacity: 1.0, + duration: const Duration(milliseconds: 250), + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 420, + minWidth: 300, ), - child: Padding( - padding: const EdgeInsets.all(constants.padding), - child: Form( - key: _formKey, - autovalidateMode: - AutovalidateMode.onUserInteraction, - 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, + child: Card( + elevation: 12, + color: scheme.surface, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(18), + ), + child: Padding( + padding: const EdgeInsets.all(constants.padding), + child: Form( + key: _formKey, + autovalidateMode: + AutovalidateMode.onUserInteraction, + 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, + ); + }, ), - 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: 20), - - TextFormField( - autofocus: true, - controller: _userController, - textInputAction: TextInputAction.next, - decoration: decoration( - 'Username', - Icons.person, + const SizedBox(height: 14), + Text( + constants.appLogonTitle, + textAlign: TextAlign.center, + style: Theme.of(context) + .textTheme + .headlineSmall + ?.copyWith(fontWeight: FontWeight.w600), ), - 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, + 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, ), ), - ), - 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, ), - child: _enabled - ? const Text('Login') - : const SizedBox( - height: 20, - width: 20, - child: CircularProgressIndicator( - strokeWidth: 2.4, + validator: (v) { + if (v == null || v.trim().isEmpty) { + return 'Enter your username'; + } + return 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; + }); + }, ), + ), + validator: (v) { + if (v == null || v.isEmpty) { + return 'Enter your password'; + } + return 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, + ), + ), + ), + ), + ], + ), ), ), ), ), ), ), - ), - ); - }, - ), + ); + }, + ), + ], ), ), );