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
This commit is contained in:
parent
2123df11c9
commit
4ce1f51062
5 changed files with 66 additions and 86 deletions
55
lib/app_bar.dart
Normal file
55
lib/app_bar.dart
Normal file
|
|
@ -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<Widget>? 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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'app_bar.dart';
|
||||||
|
|
||||||
class InfoScreen extends StatelessWidget {
|
class InfoScreen extends StatelessWidget {
|
||||||
const InfoScreen({super.key});
|
const InfoScreen({super.key});
|
||||||
|
|
||||||
|
|
@ -7,32 +9,7 @@ class InfoScreen extends StatelessWidget {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: const Color(0xFF0d0d0d),
|
backgroundColor: const Color(0xFF0d0d0d),
|
||||||
appBar: AppBar(
|
appBar: buildTracPulseAppBar(title: 'HOW IT WORKS'),
|
||||||
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)),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
body: ListView(
|
body: ListView(
|
||||||
padding: const EdgeInsets.all(20),
|
padding: const EdgeInsets.all(20),
|
||||||
children: [
|
children: [
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ class TracPulseApp extends StatelessWidget {
|
||||||
secondary: Color(0xFF00e676),
|
secondary: Color(0xFF00e676),
|
||||||
),
|
),
|
||||||
appBarTheme: const AppBarTheme(
|
appBarTheme: const AppBarTheme(
|
||||||
centerTitle: true,
|
centerTitle: false,
|
||||||
backgroundColor: Color(0xFF161616),
|
backgroundColor: Color(0xFF161616),
|
||||||
foregroundColor: Color(0xFFe0e0e0),
|
foregroundColor: Color(0xFFe0e0e0),
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
|
import 'app_bar.dart';
|
||||||
import 'bridge/location_bridge.dart';
|
import 'bridge/location_bridge.dart';
|
||||||
import 'info_screen.dart';
|
import 'info_screen.dart';
|
||||||
import 'preferences.dart';
|
import 'preferences.dart';
|
||||||
|
|
@ -131,34 +132,9 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: const Color(0xFF0d0d0d),
|
backgroundColor: const Color(0xFF0d0d0d),
|
||||||
appBar: AppBar(
|
appBar: buildTracPulseAppBar(
|
||||||
backgroundColor: const Color(0xFF161616),
|
title: 'SETTINGS',
|
||||||
elevation: 0,
|
onTitleTap: _handleAppBarTap,
|
||||||
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)),
|
|
||||||
),
|
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
import 'app_bar.dart';
|
||||||
import 'bridge/location_bridge.dart';
|
import 'bridge/location_bridge.dart';
|
||||||
|
|
||||||
class StatusScreen extends StatefulWidget {
|
class StatusScreen extends StatefulWidget {
|
||||||
|
|
@ -179,33 +180,8 @@ class _StatusScreenState extends State<StatusScreen> {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: const Color(0xFF0d0d0d),
|
backgroundColor: const Color(0xFF0d0d0d),
|
||||||
appBar: AppBar(
|
appBar: buildTracPulseAppBar(
|
||||||
backgroundColor: const Color(0xFF161616),
|
title: 'EVENT LOG',
|
||||||
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),
|
|
||||||
),
|
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
|
|
@ -220,10 +196,6 @@ class _StatusScreenState extends State<StatusScreen> {
|
||||||
onPressed: _loadLogs,
|
onPressed: _loadLogs,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
bottom: PreferredSize(
|
|
||||||
preferredSize: const Size.fromHeight(1),
|
|
||||||
child: Container(height: 1, color: const Color(0xFF2a2a2a)),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
body: Column(
|
body: Column(
|
||||||
children: [
|
children: [
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue