From a527ecdb17b6c1b99cebb02004ec9b3fd932cc70 Mon Sep 17 00:00:00 2001 From: petegregoryy Date: Fri, 23 Jan 2026 18:04:40 +0000 Subject: [PATCH] add logo to login page --- assets/logos/pg_logo_v2.svg | 27 +++++ lib/components/login/login.dart | 195 ++++++++++++++++++++++---------- pubspec.lock | 40 +++++++ pubspec.yaml | 3 + 4 files changed, 208 insertions(+), 57 deletions(-) create mode 100644 assets/logos/pg_logo_v2.svg diff --git a/assets/logos/pg_logo_v2.svg b/assets/logos/pg_logo_v2.svg new file mode 100644 index 0000000..33e3e95 --- /dev/null +++ b/assets/logos/pg_logo_v2.svg @@ -0,0 +1,27 @@ + + + + + + + + + + diff --git a/lib/components/login/login.dart b/lib/components/login/login.dart index 759e9b2..4cf759f 100644 --- a/lib/components/login/login.dart +++ b/lib/components/login/login.dart @@ -1,4 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_svg/flutter_svg.dart'; import 'package:go_router/go_router.dart'; import 'package:mileograph_flutter/services/authservice.dart'; import 'package:mileograph_flutter/components/pages/settings.dart'; @@ -41,71 +43,99 @@ class _LoginScreenState extends State { resizeToAvoidBottomInset: true, body: Container( color: Theme.of(context).scaffoldBackgroundColor, - child: Center( + child: SafeArea( child: Column( - mainAxisAlignment: MainAxisAlignment.center, children: [ - Text.rich( - TextSpan( - children: [ - TextSpan( - text: "Mile", - style: TextStyle( - color: Theme.of(context).textTheme.bodyLarge?.color, + Expanded( + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + LayoutBuilder( + builder: (context, constraints) { + return SizedBox( + width: constraints.maxWidth, + child: FittedBox( + fit: BoxFit.scaleDown, + child: Text.rich( + TextSpan( + children: [ + TextSpan( + text: "Mile", + style: TextStyle( + color: Theme.of( + context, + ).textTheme.bodyLarge?.color, + ), + ), + const TextSpan( + text: "O", + style: TextStyle(color: Colors.red), + ), + TextSpan( + text: "graph", + style: TextStyle( + color: Theme.of( + context, + ).textTheme.bodyLarge?.color, + ), + ), + ], + style: const TextStyle( + decoration: TextDecoration.none, + color: Colors.white, + fontFamily: "Tomatoes", + fontSize: 50, + ), + ), + softWrap: false, + overflow: TextOverflow.visible, + ), + ), + ); + }, ), - ), - const TextSpan( - text: "O", - style: TextStyle(color: Colors.red), - ), - TextSpan( - text: "graph", - style: TextStyle( - color: Theme.of(context).textTheme.bodyLarge?.color, + const SizedBox(height: 50), + const LoginPanel(), + const SizedBox(height: 16), + IconButton( + icon: const Icon(Icons.settings, color: Colors.grey), + tooltip: 'Settings', + onPressed: () { + Navigator.of(context).push( + MaterialPageRoute( + fullscreenDialog: true, + builder: (_) => const SettingsPage(), + ), + ); + }, ), - ), - ], - style: const TextStyle( - decoration: TextDecoration.none, - color: Colors.white, - fontFamily: "Tomatoes", - fontSize: 50, + if (_checkingSession) ...[ + const SizedBox(height: 12), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox( + height: 24, + width: 24, + child: CircularProgressIndicator(strokeWidth: 2), + ), + const SizedBox(width: 8), + Text( + 'Trying to log in', + style: Theme.of(context).textTheme.bodyMedium, + ), + ], + ), + ], + ], ), ), ), - const SizedBox(height: 50), - const LoginPanel(), - const SizedBox(height: 16), - IconButton( - icon: const Icon(Icons.settings, color: Colors.grey), - tooltip: 'Settings', - onPressed: () { - Navigator.of(context).push( - MaterialPageRoute( - fullscreenDialog: true, - builder: (_) => const SettingsPage(), - ), - ); - }, + const Padding( + padding: EdgeInsets.only(bottom: 12), + child: _LoginLogo(), ), - if (_checkingSession) ...[ - const SizedBox(height: 12), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const SizedBox( - height: 24, - width: 24, - child: CircularProgressIndicator(strokeWidth: 2), - ), - const SizedBox(width: 8), - Text( - 'Trying to log in', - style: Theme.of(context).textTheme.bodyMedium, - ), - ], - ), - ], ], ), ), @@ -114,6 +144,57 @@ class _LoginScreenState extends State { } } +class _LoginLogo extends StatefulWidget { + const _LoginLogo(); + + @override + State<_LoginLogo> createState() => _LoginLogoState(); +} + +class _LoginLogoState extends State<_LoginLogo> { + late final Future _svgFuture; + + @override + void initState() { + super.initState(); + _svgFuture = rootBundle.loadString('assets/logos/pg_logo_v2.svg'); + } + + @override + Widget build(BuildContext context) { + final accent = Theme.of(context).colorScheme.primary; + final grey = const Color(0xFF999999); + return SizedBox( + height: 42, + child: Opacity( + opacity: 0.75, + child: FutureBuilder( + future: _svgFuture, + builder: (context, snapshot) { + final svg = snapshot.data; + if (svg == null) { + return const SizedBox.shrink(); + } + final tinted = svg + .replaceAll('#00b7fd', _colorToHex(accent)) + .replaceAll('#999999', _colorToHex(grey)); + return SvgPicture.string( + tinted, + fit: BoxFit.contain, + semanticsLabel: 'Mileograph logo', + ); + }, + ), + ), + ); + } + + String _colorToHex(Color color) { + final hex = color.value.toRadixString(16).padLeft(8, '0'); + return '#${hex.substring(2)}'; + } +} + class LoginPanel extends StatefulWidget { const LoginPanel({super.key}); diff --git a/pubspec.lock b/pubspec.lock index 03a531f..ddf1f3e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -262,6 +262,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.1.0" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: "87fbd7c534435b6c5d9d98b01e1fd527812b82e68ddd8bd35fc45ed0fa8f0a95" + url: "https://pub.dev" + source: hosted + version: "2.2.3" flutter_test: dependency: "direct dev" description: flutter @@ -400,6 +408,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.1" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca" + url: "https://pub.dev" + source: hosted + version: "1.1.0" path_provider: dependency: transitive description: @@ -605,6 +621,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.0" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: a4f059dc26fc8295b5921376600a194c4ec7d55e72f2fe4c7d2831e103d461e6 + url: "https://pub.dev" + source: hosted + version: "1.1.19" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146" + url: "https://pub.dev" + source: hosted + version: "1.1.13" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: d354a7ec6931e6047785f4db12a1f61ec3d43b207fc0790f863818543f8ff0dc + url: "https://pub.dev" + source: hosted + version: "1.1.19" vector_math: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 1ca4a7c..1e2978c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -42,6 +42,7 @@ dependencies: file_selector_macos: ^0.9.4 file_selector_windows: ^0.9.3 file_selector_web: ^0.9.4 + flutter_svg: ^2.0.10 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. @@ -73,6 +74,8 @@ flutter: - family: Tomatoes fonts: - asset: lib/assets/fonts/Tomatoes-O8L8.ttf + assets: + - assets/logos/pg_logo_v2.svg # To add assets to your application, add an assets section, like this: # assets: # - images/a_dot_burr.jpeg