summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorConnor Frank <conjfrnk@gmail.com>2024-04-01 23:45:43 -0400
committerConnor Frank <conjfrnk@gmail.com>2024-04-01 23:45:43 -0400
commit79249c418d8c20d0e748be770904ddac7bbd06ed (patch)
tree541b2f49594ab71f198661029268a9efe3627325
parent7c052ab1496df403ffe6483d22e0431260476dd3 (diff)
Themes, contexts, lots of changes
-rw-r--r--README.md14
-rw-r--r--lib/main.dart35
-rw-r--r--lib/main_menu.dart136
-rw-r--r--lib/scorekeeper.dart29
4 files changed, 129 insertions, 85 deletions
diff --git a/README.md b/README.md
index 73539dd..3aa8dc0 100644
--- a/README.md
+++ b/README.md
@@ -2,15 +2,5 @@
Mini Golf Scores
-## Getting Started
-
-This project is a starting point for a Flutter application.
-
-A few resources to get you started if this is your first Flutter project:
-
-- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
-- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
-
-For help getting started with Flutter development, view the
-[online documentation](https://docs.flutter.dev/), which offers tutorials,
-samples, guidance on mobile development, and a full API reference.
+## Ideas for Improvement
+- Add course templates (automatically populate holes with par values) \ No newline at end of file
diff --git a/lib/main.dart b/lib/main.dart
index e19de54..39a7f05 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -16,9 +16,40 @@ class MiniGolfScoreApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
- return const MaterialApp(
+ return MaterialApp(
+ theme: ThemeData(
+ brightness: Brightness.light,
+ primarySwatch: Colors.blue, // Example primary color for light theme
+ scaffoldBackgroundColor: Colors.white, // Light mode background color
+ // Define other theme properties for light mode
+ elevatedButtonTheme: ElevatedButtonThemeData(
+ style: ElevatedButton.styleFrom(
+ backgroundColor: Colors.blue, // Button color for light mode
+ foregroundColor: Colors.black, // Text color for light mode
+ ),
+ ),
+ ),
+ darkTheme: ThemeData(
+ brightness: Brightness.dark,
+ primarySwatch: Colors.blueGrey, // Example primary color for dark theme
+ scaffoldBackgroundColor: Colors.black, // Dark mode background color
+ textTheme: const TextTheme(
+ bodyLarge: TextStyle(color: Colors.white),
+ bodyMedium: TextStyle(color: Colors.white),
+ bodySmall: TextStyle(color: Colors.white),
+ // Add other text styles as needed
+ ),
+ // Define other theme properties for dark mode
+ elevatedButtonTheme: ElevatedButtonThemeData(
+ style: ElevatedButton.styleFrom(
+ backgroundColor: Colors.blueGrey, // Button color for dark mode
+ foregroundColor: Colors.white, // Text color for dark mode
+ ),
+ ),
+ ),
+ themeMode: ThemeMode.system, // Use the system theme setting (light/dark)
title: 'Mini Golf Score App',
- home: MainMenu(),
+ home: const MainMenu(),
);
}
}
diff --git a/lib/main_menu.dart b/lib/main_menu.dart
index 30bd84b..7cd29c6 100644
--- a/lib/main_menu.dart
+++ b/lib/main_menu.dart
@@ -9,21 +9,21 @@ class MainMenu extends StatelessWidget {
const MainMenu({super.key});
void _showLoadGameDialog(BuildContext context) async {
+ final localContext = context;
final prefs = await SharedPreferences.getInstance();
final gameKeys = prefs.getKeys()
.where((key) => key.startsWith('game_'))
.toList();
if (gameKeys.isEmpty) {
- // No games found, show a SnackBar instead
- ScaffoldMessenger.of(context).showSnackBar(
+ ScaffoldMessenger.of(localContext).showSnackBar(
const SnackBar(content: Text('No saved games found.')),
);
return;
}
showDialog(
- context: context,
+ context: localContext,
builder: (context) {
return AlertDialog(
title: const Text('Select a Game to Load'),
@@ -34,7 +34,7 @@ class MainMenu extends StatelessWidget {
title: Text(key.substring(5).substring(0, 16).replaceAll(
"T", " ")),
onTap: () {
- _loadGame(context, key);
+ _loadGame(localContext, key);
},
);
}).toList(),
@@ -46,16 +46,16 @@ class MainMenu extends StatelessWidget {
}
Future<void> _loadGame(BuildContext context, String gameKey) async {
+ final localContext = context;
final prefs = await SharedPreferences.getInstance();
final gameDataJson = prefs.getString(gameKey);
if (gameDataJson != null) {
final gameData = jsonDecode(gameDataJson);
- // Assuming gameData structure. Convert data types as necessary.
- Navigator.of(context).pop(); // Close the selection dialog
+ Navigator.of(localContext).pop(); // Close the selection dialog
Navigator.push(
- context,
+ localContext,
MaterialPageRoute(
- builder: (context) =>
+ builder: (localContext) =>
ScoreKeeper(
isNewGame: false,
playerNames: List<String>.from(gameData['playerNames']),
@@ -70,8 +70,65 @@ class MainMenu extends StatelessWidget {
}
}
+ void showAboutDialog(BuildContext context) async {
+ final localContext = context;
+ PackageInfo packageInfo = await PackageInfo.fromPlatform();
+ String version = packageInfo.version;
+
+ showDialog(
+ context: localContext,
+ builder: (BuildContext localContext) {
+ return AlertDialog(
+ title: const Text('About'),
+ content: SingleChildScrollView(
+ child: ListBody(
+ children: <Widget>[
+ const Text('Mini Golf Scorekeeper App'),
+ const Text('Made by Connor Frank'),
+ const Text('Princeton NJ'),
+ const Text(''),
+ Text('Version: $version'), // Display app version
+ const Text(''),
+ const Text('Mini Golf Scores Copyright (C) 2024 Connor Frank'),
+ const Text('This program comes with ABSOLUTELY NO WARRANTY.'),
+ const Text('This is free software, and you are welcome to redistribute it under certain conditions.'),
+ const Text('View \'Licenses\' in main menu for details.'),
+ // Add more about info here
+ ],
+ ),
+ ),
+ actions: <Widget>[
+ TextButton(
+ child: const Text('Contact Me'),
+ onPressed: () async {
+ Uri link = Uri(scheme: 'mailto',
+ path: 'conjfrnk+minigolf@gmail.com',
+ query: 'subject=Mini Golf Scores App',
+ );
+ if (await canLaunchUrl(link)) {
+ await launchUrl(link);
+ } else {
+ ScaffoldMessenger.of(localContext).showSnackBar(
+ const SnackBar(content: Text('Could not launch email client')),
+ );
+ }
+ },
+ ),
+ TextButton(
+ child: const Text('OK'),
+ onPressed: () {
+ Navigator.of(context).pop();
+ },
+ ),
+ ],
+ );
+ },
+ );
+ }
+
@override
Widget build(BuildContext context) {
+ final localContext = context;
return Scaffold(
appBar: AppBar(
title: const Text('Mini Golf Main Menu'),
@@ -85,9 +142,9 @@ class MainMenu extends StatelessWidget {
child: const Text('Start New Game'),
onPressed: () {
Navigator.push(
- context,
+ localContext,
MaterialPageRoute(
- builder: (context) => const ScoreKeeper(isNewGame: true)),
+ builder: (localContext) => const ScoreKeeper(isNewGame: true)),
);
},
),
@@ -95,7 +152,7 @@ class MainMenu extends StatelessWidget {
// Space between the buttons
ElevatedButton(
child: const Text('Load Game'),
- onPressed: () => _showLoadGameDialog(context),
+ onPressed: () => _showLoadGameDialog(localContext),
),
const Spacer(),
// This will push the bottom content to the bottom of the screen
@@ -106,43 +163,8 @@ class MainMenu extends StatelessWidget {
children: [
// About Button
ElevatedButton(
- onPressed: () async {
- PackageInfo packageInfo = await PackageInfo.fromPlatform();
- String version = packageInfo.version;
-
- showDialog(
- context: context,
- builder: (BuildContext context) {
- return AlertDialog(
- title: const Text('About'),
- content: SingleChildScrollView(
- child: ListBody(
- children: <Widget>[
- const Text('Mini Golf Scorekeeper App'),
- const Text('Made by Connor Frank'),
- const Text('Princeton NJ'),
- const Text(''),
- Text('Version: $version'), // Display app version
- const Text(''),
- const Text('Mini Golf Scores Copyright (C) 2024 Connor Frank'),
- const Text('This program comes with ABSOLUTELY NO WARRANTY.'),
- const Text('This is free software, and you are welcome to redistribute it under certain conditions.'),
- const Text('View \'Licenses\' in main menu for details.'),
- // Add more about info here
- ],
- ),
- ),
- actions: <Widget>[
- TextButton(
- child: const Text('OK'),
- onPressed: () {
- Navigator.of(context).pop();
- },
- ),
- ],
- );
- },
- );
+ onPressed: () {
+ showAboutDialog(localContext);
},
child: const Text('About'),
),
@@ -153,7 +175,7 @@ class MainMenu extends StatelessWidget {
String version = packageInfo.version;
// Action for License button
showLicensePage(
- context: context,
+ context: localContext,
applicationName: 'Mini Golf Scores',
applicationVersion: version,
applicationLegalese: '© 2024 Connor Frank'
@@ -170,7 +192,7 @@ class MainMenu extends StatelessWidget {
if (await canLaunchUrl(link)) {
await launchUrl(link);
} else {
- ScaffoldMessenger.of(context).showSnackBar(
+ ScaffoldMessenger.of(localContext).showSnackBar(
const SnackBar(content: Text('Could not open GitHub')),
);
}
@@ -178,20 +200,6 @@ class MainMenu extends StatelessWidget {
child: const Text(
'GitHub'), // You can use an Icon instead: Icon(Icons.link)
),
- ElevatedButton(
- onPressed: () async {
- Uri link = Uri(scheme: 'mailto',
- path: 'conjfrnk+minigolf@gmail.com');
- if (await canLaunchUrl(link)) {
- await launchUrl(link);
- } else {
- ScaffoldMessenger.of(context).showSnackBar(
- const SnackBar(content: Text('Could not open GitHub')),
- );
- }
- },
- child: const Text('Contact'),
- ),
],
),
const SizedBox(height: 20),
diff --git a/lib/scorekeeper.dart b/lib/scorekeeper.dart
index b523466..ba6a068 100644
--- a/lib/scorekeeper.dart
+++ b/lib/scorekeeper.dart
@@ -94,6 +94,12 @@ class ScoreKeeperState extends State<ScoreKeeper> {
);
}
+ Future<void> _saveGameIfUnsaved() async {
+ if (!widget.isNewGame) {
+ await _saveGame();
+ }
+ }
+
Future<void> _saveGame() async {
final prefs = await SharedPreferences.getInstance();
final String timestamp = gameCreationTime.toIso8601String();
@@ -319,8 +325,8 @@ class ScoreKeeperState extends State<ScoreKeeper> {
}
return ListTile(
- title: Text('Hole $holeNumber'),
- subtitle: Text(scoreText),
+ title: Text('Hole $holeNumber', style: Theme.of(context).textTheme.bodyMedium),
+ subtitle: Text(scoreText, style: Theme.of(context).textTheme.bodySmall),
onTap: () => _showHoleDetailsDialog(holeNumber),
);
}
@@ -375,6 +381,13 @@ class ScoreKeeperState extends State<ScoreKeeper> {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
+ leading: IconButton(
+ icon: const Icon(Icons.arrow_back),
+ onPressed: () {
+ _saveGameIfUnsaved(); // Call your save game method
+ Navigator.of(context).pop(); // Navigate back after saving
+ },
+ ),
title: const Text('Mini Golf Score Keeper'),
actions: [
IconButton(
@@ -432,7 +445,7 @@ class ScoreKeeperState extends State<ScoreKeeper> {
),
),
bottomNavigationBar: Container(
- color: Colors.blueGrey[100],
+ color: Theme.of(context).brightness == Brightness.dark ? Colors.grey[850] : Colors.blueGrey[100],
height: 60.0,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
@@ -444,10 +457,12 @@ class ScoreKeeperState extends State<ScoreKeeper> {
onTap: () => _showPlayerRankings(context),
child: Container(
padding: const EdgeInsets.all(10),
- color: Colors.blueGrey[100],
child: Text(
'Total Par: ${pars.values.fold(0, (prev, par) => prev + par)}',
- style: const TextStyle(fontSize: 16),
+ style: TextStyle(
+ fontSize: 16,
+ color: Theme.of(context).brightness == Brightness.dark ? Colors.white : Colors.black, // White or black text based on theme
+ ),
),
),
),
@@ -468,8 +483,8 @@ class ScoreKeeperState extends State<ScoreKeeper> {
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
- Text(name),
- Text('Score: $totalScore'),
+ Text(name, style: Theme.of(context).textTheme.bodySmall),
+ Text('Score: $totalScore', style: Theme.of(context).textTheme.bodySmall),
],
),
);