From 4ce1f510623102a20b33651c4e89e27f5327df47 Mon Sep 17 00:00:00 2001 From: fiatcode Date: Wed, 6 May 2026 08:01:12 +0700 Subject: [PATCH] refactor: extract consistent AppBar builder, remove icon from EVENT LOG title - Add buildTracPulseAppBar() helper in lib/app_bar.dart - Reads backgroundColor/elevation from ThemeData.appBarTheme - Consistent back button (#9e9e9e, size 20) via Navigator.pop - Monospace title style (14px, weight 700, letter-spacing 2) - Optional onTitleTap for tappable titles - Update all screens to use the new helper, removing redundant overrides - Remove terminal icon from status_screen title, use plain centered text - Change appBarTheme centerTitle to false (left-aligned) - Remove bottom dividers from all screens --- lib/app_bar.dart | 55 ++++++++++++++++++++++++++++++++++++++++ lib/info_screen.dart | 29 +++------------------ lib/main.dart | 2 +- lib/settings_screen.dart | 32 +++-------------------- lib/status_screen.dart | 34 +++---------------------- 5 files changed, 66 insertions(+), 86 deletions(-) create mode 100644 lib/app_bar.dart diff --git a/lib/app_bar.dart b/lib/app_bar.dart new file mode 100644 index 0000000..fe16abf --- /dev/null +++ b/lib/app_bar.dart @@ -0,0 +1,55 @@ +import 'package:flutter/material.dart'; + +/// Consistent AppBar builder for TracPulse screens. +/// +/// Reads base styles (backgroundColor, elevation) from the current +/// [ThemeData.appBarTheme], then applies TracPulse's standard back button +/// and title styling on top. +/// +/// Parameters: +/// - [title] – App bar title text (left-aligned, monospace, 14px, weight 700, letter-spacing 2) +/// - [actions] – optional list of action [IconButton]s placed on the right +/// - [onTitleTap] – optional callback when the title is tapped (e.g. Easter egg) +AppBar buildTracPulseAppBar({ + required String title, + List? actions, + VoidCallback? onTitleTap, +}) { + return AppBar( + // Inherit backgroundColor, elevation from theme (defined once in MaterialApp.appBarTheme) + automaticallyImplyLeading: true, + actions: actions, + title: onTitleTap != null + ? GestureDetector( + onTap: onTitleTap, + child: Text( + title, + style: const TextStyle( + fontFamily: 'monospace', + fontSize: 14, + fontWeight: FontWeight.w700, + letterSpacing: 2, + color: Color(0xFFe0e0e0), + ), + ), + ) + : Text( + title, + style: const TextStyle( + fontFamily: 'monospace', + fontSize: 14, + fontWeight: FontWeight.w700, + letterSpacing: 2, + color: Color(0xFFe0e0e0), + ), + ), + // Consistent back button: #9e9e9e, size 20 (distinct from title #e0e0e0) + leading: Builder( + builder: (context) => IconButton( + icon: const Icon(Icons.arrow_back, color: Color(0xFF9e9e9e), size: 20), + onPressed: () => Navigator.pop(context), + ), + ), + leadingWidth: 48, + ); +} diff --git a/lib/info_screen.dart b/lib/info_screen.dart index a980fd9..5efd1c4 100644 --- a/lib/info_screen.dart +++ b/lib/info_screen.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; +import 'app_bar.dart'; + class InfoScreen extends StatelessWidget { const InfoScreen({super.key}); @@ -7,32 +9,7 @@ class InfoScreen extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xFF0d0d0d), - appBar: AppBar( - backgroundColor: const Color(0xFF161616), - elevation: 0, - leading: IconButton( - icon: const Icon( - Icons.arrow_back, - color: Color(0xFF9e9e9e), - size: 20, - ), - onPressed: () => Navigator.pop(context), - ), - title: const Text( - 'HOW IT WORKS', - style: TextStyle( - fontFamily: 'monospace', - fontSize: 14, - fontWeight: FontWeight.w700, - letterSpacing: 2, - color: Color(0xFFe0e0e0), - ), - ), - bottom: PreferredSize( - preferredSize: const Size.fromHeight(1), - child: Container(height: 1, color: const Color(0xFF2a2a2a)), - ), - ), + appBar: buildTracPulseAppBar(title: 'HOW IT WORKS'), body: ListView( padding: const EdgeInsets.all(20), children: [ diff --git a/lib/main.dart b/lib/main.dart index 8021ef7..edada76 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -38,7 +38,7 @@ class TracPulseApp extends StatelessWidget { secondary: Color(0xFF00e676), ), appBarTheme: const AppBarTheme( - centerTitle: true, + centerTitle: false, backgroundColor: Color(0xFF161616), foregroundColor: Color(0xFFe0e0e0), elevation: 0, diff --git a/lib/settings_screen.dart b/lib/settings_screen.dart index e3be1ad..739d7a5 100644 --- a/lib/settings_screen.dart +++ b/lib/settings_screen.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:url_launcher/url_launcher.dart'; +import 'app_bar.dart'; import 'bridge/location_bridge.dart'; import 'info_screen.dart'; import 'preferences.dart'; @@ -131,34 +132,9 @@ class _SettingsScreenState extends State { Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xFF0d0d0d), - appBar: AppBar( - backgroundColor: const Color(0xFF161616), - elevation: 0, - leading: IconButton( - icon: const Icon( - Icons.arrow_back, - color: Color(0xFF9e9e9e), - size: 20, - ), - onPressed: () => Navigator.pop(context), - ), - title: GestureDetector( - onTap: _handleAppBarTap, - child: const Text( - 'SETTINGS', - style: TextStyle( - fontFamily: 'monospace', - fontSize: 14, - fontWeight: FontWeight.w700, - letterSpacing: 2, - color: Color(0xFFe0e0e0), - ), - ), - ), - bottom: PreferredSize( - preferredSize: const Size.fromHeight(1), - child: Container(height: 1, color: const Color(0xFF2a2a2a)), - ), + appBar: buildTracPulseAppBar( + title: 'SETTINGS', + onTitleTap: _handleAppBarTap, actions: [ IconButton( icon: const Icon( diff --git a/lib/status_screen.dart b/lib/status_screen.dart index cf93305..95d2ee5 100644 --- a/lib/status_screen.dart +++ b/lib/status_screen.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'app_bar.dart'; import 'bridge/location_bridge.dart'; class StatusScreen extends StatefulWidget { @@ -179,33 +180,8 @@ class _StatusScreenState extends State { Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xFF0d0d0d), - appBar: AppBar( - backgroundColor: const Color(0xFF161616), - elevation: 0, - title: Row( - children: [ - const Icon(Icons.terminal, color: Color(0xFF00bcd4), size: 18), - const SizedBox(width: 10), - const Text( - 'EVENT LOG', - style: TextStyle( - fontFamily: 'monospace', - fontSize: 14, - fontWeight: FontWeight.w700, - letterSpacing: 2, - color: Color(0xFFe0e0e0), - ), - ), - ], - ), - leading: IconButton( - icon: const Icon( - Icons.arrow_back, - color: Color(0xFF9e9e9e), - size: 20, - ), - onPressed: () => Navigator.pop(context), - ), + appBar: buildTracPulseAppBar( + title: 'EVENT LOG', actions: [ IconButton( icon: const Icon( @@ -220,10 +196,6 @@ class _StatusScreenState extends State { onPressed: _loadLogs, ), ], - bottom: PreferredSize( - preferredSize: const Size.fromHeight(1), - child: Container(height: 1, color: const Color(0xFF2a2a2a)), - ), ), body: Column( children: [