[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-08-15 13:41:00 -05:00
parent 98a5c89d6b
commit f41a53c463

View File

@@ -56,7 +56,7 @@ class _AuthScreenState extends State<AuthScreen> {
} }
setState(() => _enabled = false); setState(() => _enabled = false);
var authenticated = await auth.authenticate( final authenticated = await auth.authenticate(
_userController.text.trim(), _userController.text.trim(),
_passwordController.text, _passwordController.text,
); );
@@ -81,189 +81,227 @@ class _AuthScreenState extends State<AuthScreen> {
return Scaffold( return Scaffold(
appBar: AppBar(title: Text(widget.title), scrolledUnderElevation: 0), appBar: AppBar(title: Text(widget.title), scrolledUnderElevation: 0),
body: SafeArea( body: SafeArea(
child: Container( child: Stack(
width: double.infinity, children: [
height: double.infinity, Container(
decoration: BoxDecoration( width: double.infinity,
gradient: LinearGradient( height: double.infinity,
begin: Alignment.topLeft, decoration: const BoxDecoration(
end: Alignment.bottomRight, gradient: LinearGradient(
colors: [ begin: Alignment.topLeft,
Theme.of(context).colorScheme.primary.withValues(alpha: 0.4), end: Alignment.bottomRight,
Theme.of(context).colorScheme.surface.withValues(alpha: 0.9), colors: [Color(0xFF0A0F1F), Color(0xFF1B1C1F)],
], stops: [0.0, 1.0],
stops: const [0.0, 1.0], ),
),
), ),
), Align(
child: Consumer<Auth>( alignment: const Alignment(0, 0.1),
builder: (context, auth, _) { child: IgnorePointer(
if (auth.authenticated) { child: Container(
Future.delayed(const Duration(milliseconds: 1), () { width: 740,
if (constants.navigatorKey.currentContext == null) { height: 740,
return; decoration: BoxDecoration(
} shape: BoxShape.circle,
gradient: RadialGradient(
colors: [
scheme.primary.withValues(alpha: 0.22),
Colors.transparent,
],
stops: const [0.0, 1.0],
),
),
),
),
),
Consumer<Auth>(
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( return const SizedBox.shrink();
constants.navigatorKey.currentContext!, }
).pushNamedAndRemoveUntil('/', (r) => false);
});
return const SizedBox.shrink(); return Center(
} child: AnimatedScale(
scale: 1.0,
return Center(
child: AnimatedScale(
scale: 1.0,
duration: const Duration(milliseconds: 250),
curve: Curves.easeOutCubic,
child: AnimatedOpacity(
opacity: 1.0,
duration: const Duration(milliseconds: 250), duration: const Duration(milliseconds: 250),
child: ConstrainedBox( curve: Curves.easeOutCubic,
constraints: const BoxConstraints( child: AnimatedOpacity(
maxWidth: 420, opacity: 1.0,
minWidth: 300, duration: const Duration(milliseconds: 250),
), child: ConstrainedBox(
child: Card( constraints: const BoxConstraints(
elevation: 12, maxWidth: 420,
color: scheme.surface, minWidth: 300,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18),
), ),
child: Padding( child: Card(
padding: const EdgeInsets.all(constants.padding), elevation: 12,
child: Form( color: scheme.surface,
key: _formKey, shape: RoundedRectangleBorder(
autovalidateMode: borderRadius: BorderRadius.circular(18),
AutovalidateMode.onUserInteraction, ),
child: Column( child: Padding(
mainAxisSize: MainAxisSize.min, padding: const EdgeInsets.all(constants.padding),
crossAxisAlignment: CrossAxisAlignment.stretch, child: Form(
children: [ key: _formKey,
Align( autovalidateMode:
alignment: Alignment.center, AutovalidateMode.onUserInteraction,
child: Container( child: Column(
width: 56, mainAxisSize: MainAxisSize.min,
height: 56, crossAxisAlignment: CrossAxisAlignment.stretch,
decoration: BoxDecoration( children: [
color: scheme.primary.withValues( Align(
alpha: 0.18, 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),
const SizedBox(height: 14), Text(
Text( constants.appLogonTitle,
constants.appLogonTitle, textAlign: TextAlign.center,
textAlign: TextAlign.center, style: Theme.of(context)
style: Theme.of(context) .textTheme
.textTheme .headlineSmall
.headlineSmall ?.copyWith(fontWeight: FontWeight.w600),
?.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,
), ),
validator: (v) => const SizedBox(height: 6),
(v == null || v.trim().isEmpty) Text(
? 'Enter your username' "Secure access to your mounts",
: null, textAlign: TextAlign.center,
onFieldSubmitted: (_) => style: Theme.of(context)
FocusScope.of(context).nextFocus(), .textTheme
), .bodyMedium
const SizedBox(height: constants.padding), ?.copyWith(
color: scheme.onSurface.withValues(
TextFormField( alpha: 0.7,
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) => (v == null || v.isEmpty) const SizedBox(height: 20),
? 'Enter your password'
: null,
onFieldSubmitted: (_) => doLogin(auth),
),
const SizedBox(height: constants.padding),
SizedBox( TextFormField(
height: 44, autofocus: true,
child: ElevatedButton( controller: _userController,
onPressed: _enabled textInputAction: TextInputAction.next,
? () => doLogin(auth) decoration: decoration(
: null, 'Username',
style: ElevatedButton.styleFrom( Icons.person,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
), ),
child: _enabled validator: (v) {
? const Text('Login') if (v == null || v.trim().isEmpty) {
: const SizedBox( return 'Enter your username';
height: 20, }
width: 20, return null;
child: CircularProgressIndicator( },
strokeWidth: 2.4, 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,
),
),
),
),
],
),
), ),
), ),
), ),
), ),
), ),
), ),
), );
); },
}, ),
), ],
), ),
), ),
); );