Compare commits
	
		
			5 Commits
		
	
	
		
			0.1.2
			...
			c5f1a4e9ba
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| c5f1a4e9ba | |||
| 538a298acd | |||
| cce878ccaa | |||
| 147178e4dd | |||
| c39e09b2b6 | 
| @@ -2,6 +2,7 @@ | |||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| import '/models/item_type.dart'; | import '/models/item_type.dart'; | ||||||
| import 'dart:io'; | import 'dart:io'; | ||||||
|  | import 'package:package_info_plus/package_info_plus.dart'; | ||||||
|  |  | ||||||
| // Local | // Local | ||||||
| import '/pages/tracked_item.dart'; | import '/pages/tracked_item.dart'; | ||||||
| @@ -26,10 +27,32 @@ class _HomePageState extends State<HomePage> { | |||||||
|     setState(() {}); |     setState(() {}); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   PackageInfo _packageInfo = PackageInfo( | ||||||
|  |     appName: 'Unknown', | ||||||
|  |     packageName: 'Unknown', | ||||||
|  |     version: 'Unknown', | ||||||
|  |     buildNumber: 'Unknown', | ||||||
|  |   ); | ||||||
|  |  | ||||||
|  |   Future _initPackageInfo() async { | ||||||
|  |     final PackageInfo info = await PackageInfo.fromPlatform(); | ||||||
|  |     setState(() { | ||||||
|  |       _packageInfo = info; | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   void initState() { | ||||||
|  |     super.initState(); | ||||||
|  |     // Get package details | ||||||
|  |     _initPackageInfo(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     Widget page; |     Widget page; | ||||||
|     Widget? dialog; |     Widget? dialog; | ||||||
|  |  | ||||||
|     switch (pageSelected) { |     switch (pageSelected) { | ||||||
|       case 0: |       case 0: | ||||||
|         page = TrackedItemPage( |         page = TrackedItemPage( | ||||||
| @@ -129,6 +152,8 @@ class _HomePageState extends State<HomePage> { | |||||||
|           } |           } | ||||||
|         }); |         }); | ||||||
|       }, |       }, | ||||||
|  |       leading: Text("Menu"), | ||||||
|  |       trailing: Text("v${_packageInfo.version}"), | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     Widget main = Container( |     Widget main = Container( | ||||||
|   | |||||||
| @@ -48,15 +48,15 @@ class _ProjectionPageState extends State<ProjectionPage> { | |||||||
|     // Summaries for display as well as calculation of totals for projections. |     // Summaries for display as well as calculation of totals for projections. | ||||||
|     Widget expenseSummary = SummaryCardForTotals( |     Widget expenseSummary = SummaryCardForTotals( | ||||||
|       list: DatabaseHelper.instance.getExpenses(), |       list: DatabaseHelper.instance.getExpenses(), | ||||||
|       summaryTypeLabel: ItemType.expense.title, |       itemType: ItemType.expense, | ||||||
|     ); |     ); | ||||||
|     Widget incomeSummary = SummaryCardForTotals( |     Widget incomeSummary = SummaryCardForTotals( | ||||||
|       list: DatabaseHelper.instance.getIncomes(), |       list: DatabaseHelper.instance.getIncomes(), | ||||||
|       summaryTypeLabel: ItemType.income.title, |       itemType: ItemType.income, | ||||||
|     ); |     ); | ||||||
|     Widget assetSummary = SummaryCardForTotals( |     Widget assetSummary = SummaryCardForTotals( | ||||||
|       list: DatabaseHelper.instance.getAssets(), |       list: DatabaseHelper.instance.getAssets(), | ||||||
|       summaryTypeLabel: ItemType.asset.title, |       itemType: ItemType.asset, | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     // Calculations for the projections. |     // Calculations for the projections. | ||||||
| @@ -155,14 +155,16 @@ class SummaryCardForTotals extends StatelessWidget { | |||||||
|   const SummaryCardForTotals({ |   const SummaryCardForTotals({ | ||||||
|     super.key, |     super.key, | ||||||
|     required this.list, |     required this.list, | ||||||
|     required this.summaryTypeLabel, |     required this.itemType, | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   final Future<List<TrackedItem>> list; |   final Future<List<TrackedItem>> list; | ||||||
|   final String summaryTypeLabel; |   final ItemType itemType; | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|  |     String summaryTypeLabel = itemType.title.toString(); | ||||||
|  |  | ||||||
|     return FutureBuilder<List<TrackedItem>>( |     return FutureBuilder<List<TrackedItem>>( | ||||||
|         future: list, |         future: list, | ||||||
|         builder: ( |         builder: ( | ||||||
| @@ -175,12 +177,9 @@ class SummaryCardForTotals extends StatelessWidget { | |||||||
|  |  | ||||||
|           // Calculate the total fields based on item type. |           // Calculate the total fields based on item type. | ||||||
|           double dailyTotal = 0, monthlyTotal = 0, yearlyTotal = 0; |           double dailyTotal = 0, monthlyTotal = 0, yearlyTotal = 0; | ||||||
|           ItemType? itemType; |  | ||||||
|           for (TrackedItem e in snapshot.data!) { |           for (TrackedItem e in snapshot.data!) { | ||||||
|             if (itemType == null) { |             if (e.type != itemType) { | ||||||
|               itemType = e.type!; |               throw "List in SummaryCardForTotals has incorrect item types, abort!"; | ||||||
|             } else if (itemType != e.type) { |  | ||||||
|               throw "List in SummaryCardForTotals has multiple item types, abort!"; |  | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             if (e.type == ItemType.asset) { |             if (e.type == ItemType.asset) { | ||||||
| @@ -194,9 +193,6 @@ class SummaryCardForTotals extends StatelessWidget { | |||||||
|  |  | ||||||
|           /* Load page variables based on calculated totals. */ |           /* Load page variables based on calculated totals. */ | ||||||
|           switch (itemType) { |           switch (itemType) { | ||||||
|             case null: |  | ||||||
|               break; |  | ||||||
|  |  | ||||||
|             case ItemType.asset: |             case ItemType.asset: | ||||||
|               _assetTotal = monthlyTotal; |               _assetTotal = monthlyTotal; | ||||||
|               break; |               break; | ||||||
|   | |||||||
| @@ -297,6 +297,21 @@ class _TrackedItemInputDialogState extends State<TrackedItemInputDialog> { | |||||||
|     String amountText = |     String amountText = | ||||||
|         widget.amountText != null ? widget.amountText! : TrackedItem.amountText; |         widget.amountText != null ? widget.amountText! : TrackedItem.amountText; | ||||||
|  |  | ||||||
|  |     Future<List<TrackedItem>> items; | ||||||
|  |     switch (_type) { | ||||||
|  |       case ItemType.expense: | ||||||
|  |         items = DatabaseHelper.instance.getExpenses(); | ||||||
|  |         break; | ||||||
|  |       case ItemType.income: | ||||||
|  |         items = DatabaseHelper.instance.getIncomes(); | ||||||
|  |         break; | ||||||
|  |       case ItemType.asset: | ||||||
|  |         items = DatabaseHelper.instance.getAssets(); | ||||||
|  |         break; | ||||||
|  |       default: | ||||||
|  |         throw UnimplementedError("Cannot find unimplemented type."); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     return Column( |     return Column( | ||||||
|       // prevent AlertDialog from taking full vertical height. |       // prevent AlertDialog from taking full vertical height. | ||||||
|       mainAxisSize: MainAxisSize.min, |       mainAxisSize: MainAxisSize.min, | ||||||
| @@ -336,15 +351,15 @@ class _TrackedItemInputDialogState extends State<TrackedItemInputDialog> { | |||||||
|                 ? Text("New ${_type!.title}") |                 ? Text("New ${_type!.title}") | ||||||
|                 : Text("Edit ${_type!.title}"), |                 : Text("Edit ${_type!.title}"), | ||||||
|           ), |           ), | ||||||
|           content: FutureBuilder<List<Expense>>( |           content: FutureBuilder<List<TrackedItem>>( | ||||||
|               // TODO / TBD -- This should no longer only be Expenses. |               // TODO / TBD -- This should no longer only be Expenses. | ||||||
|               future: DatabaseHelper.instance.getExpenses(), |               future: items, | ||||||
|               builder: (BuildContext context, |               builder: (BuildContext context, | ||||||
|                   AsyncSnapshot<List<Expense>> snapshot) { |                   AsyncSnapshot<List<TrackedItem>> snapshot) { | ||||||
|                 if (!snapshot.hasData) { |                 if (!snapshot.hasData) { | ||||||
|                   return Center(child: Text('Loading...')); |                   return Center(child: Text('Loading...')); | ||||||
|                 } |                 } | ||||||
|                 List<Expense> expenses = snapshot.data!; |                 List<TrackedItem> expenses = snapshot.data!; | ||||||
|                 return Form( |                 return Form( | ||||||
|                   key: _formKey, |                   key: _formKey, | ||||||
|                   child: Column( |                   child: Column( | ||||||
| @@ -392,7 +407,16 @@ class _TrackedItemInputDialogState extends State<TrackedItemInputDialog> { | |||||||
|                             return "$amountText must be a valid number."; |                             return "$amountText must be a valid number."; | ||||||
|                           } |                           } | ||||||
|                           if (double.parse(value) < 0) { |                           if (double.parse(value) < 0) { | ||||||
|                             return "Please use the Income page rather than having negative expenses."; |                             switch (_type) { | ||||||
|  |                               case ItemType.expense: | ||||||
|  |                                 return "Please use the Income page."; | ||||||
|  |  | ||||||
|  |                               case ItemType.income: | ||||||
|  |                                 return "Please use the Expense page."; | ||||||
|  |  | ||||||
|  |                               default: | ||||||
|  |                                 break; | ||||||
|  |                             } | ||||||
|                           } |                           } | ||||||
|                           if (double.parse(value) < 0.01) { |                           if (double.parse(value) < 0.01) { | ||||||
|                             return "$amountText must be one hundreth (0.01) or higher."; |                             return "$amountText must be one hundreth (0.01) or higher."; | ||||||
|   | |||||||
| @@ -5,11 +5,13 @@ | |||||||
| import FlutterMacOS | import FlutterMacOS | ||||||
| import Foundation | import Foundation | ||||||
|  |  | ||||||
|  | import package_info_plus | ||||||
| import path_provider_foundation | import path_provider_foundation | ||||||
| import sqflite_darwin | import sqflite_darwin | ||||||
| import url_launcher_macos | import url_launcher_macos | ||||||
|  |  | ||||||
| func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { | ||||||
|  |   FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) | ||||||
|   PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) |   PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) | ||||||
|   SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) |   SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) | ||||||
|   UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) |   UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) | ||||||
|   | |||||||
							
								
								
									
										40
									
								
								pubspec.lock
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								pubspec.lock
									
									
									
									
									
								
							| @@ -80,6 +80,22 @@ packages: | |||||||
|     description: flutter |     description: flutter | ||||||
|     source: sdk |     source: sdk | ||||||
|     version: "0.0.0" |     version: "0.0.0" | ||||||
|  |   http: | ||||||
|  |     dependency: transitive | ||||||
|  |     description: | ||||||
|  |       name: http | ||||||
|  |       sha256: fe7ab022b76f3034adc518fb6ea04a82387620e19977665ea18d30a1cf43442f | ||||||
|  |       url: "https://pub.dev" | ||||||
|  |     source: hosted | ||||||
|  |     version: "1.3.0" | ||||||
|  |   http_parser: | ||||||
|  |     dependency: transitive | ||||||
|  |     description: | ||||||
|  |       name: http_parser | ||||||
|  |       sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" | ||||||
|  |       url: "https://pub.dev" | ||||||
|  |     source: hosted | ||||||
|  |     version: "4.1.2" | ||||||
|   leak_tracker: |   leak_tracker: | ||||||
|     dependency: transitive |     dependency: transitive | ||||||
|     description: |     description: | ||||||
| @@ -136,6 +152,22 @@ packages: | |||||||
|       url: "https://pub.dev" |       url: "https://pub.dev" | ||||||
|     source: hosted |     source: hosted | ||||||
|     version: "1.16.0" |     version: "1.16.0" | ||||||
|  |   package_info_plus: | ||||||
|  |     dependency: "direct main" | ||||||
|  |     description: | ||||||
|  |       name: package_info_plus | ||||||
|  |       sha256: "7976bfe4c583170d6cdc7077e3237560b364149fcd268b5f53d95a991963b191" | ||||||
|  |       url: "https://pub.dev" | ||||||
|  |     source: hosted | ||||||
|  |     version: "8.3.0" | ||||||
|  |   package_info_plus_platform_interface: | ||||||
|  |     dependency: transitive | ||||||
|  |     description: | ||||||
|  |       name: package_info_plus_platform_interface | ||||||
|  |       sha256: "6c935fb612dff8e3cc9632c2b301720c77450a126114126ffaafe28d2e87956c" | ||||||
|  |       url: "https://pub.dev" | ||||||
|  |     source: hosted | ||||||
|  |     version: "3.2.0" | ||||||
|   path: |   path: | ||||||
|     dependency: "direct main" |     dependency: "direct main" | ||||||
|     description: |     description: | ||||||
| @@ -421,6 +453,14 @@ packages: | |||||||
|       url: "https://pub.dev" |       url: "https://pub.dev" | ||||||
|     source: hosted |     source: hosted | ||||||
|     version: "1.1.1" |     version: "1.1.1" | ||||||
|  |   win32: | ||||||
|  |     dependency: transitive | ||||||
|  |     description: | ||||||
|  |       name: win32 | ||||||
|  |       sha256: dc6ecaa00a7c708e5b4d10ee7bec8c270e9276dfcab1783f57e9962d7884305f | ||||||
|  |       url: "https://pub.dev" | ||||||
|  |     source: hosted | ||||||
|  |     version: "5.12.0" | ||||||
|   xdg_directories: |   xdg_directories: | ||||||
|     dependency: transitive |     dependency: transitive | ||||||
|     description: |     description: | ||||||
|   | |||||||
| @@ -1,7 +1,8 @@ | |||||||
| name: expense_tracker | name: expense_tracker | ||||||
|  | homepage: https://git.hyperling.com/me/flutter-expense-tracker | ||||||
| description: Track recurring expenses against income and liquid assets. | description: Track recurring expenses against income and liquid assets. | ||||||
| publish_to: 'none' | publish_to: 'none' | ||||||
| version: 0.1.2 | version: 0.1.3 | ||||||
|  |  | ||||||
| environment: | environment: | ||||||
|   sdk: ^3.6.1 |   sdk: ^3.6.1 | ||||||
| @@ -9,6 +10,7 @@ environment: | |||||||
| dependencies: | dependencies: | ||||||
|   flutter: |   flutter: | ||||||
|     sdk: flutter |     sdk: flutter | ||||||
|  |   package_info_plus: ^8.3.0 | ||||||
|   path: ^1.9.0 |   path: ^1.9.0 | ||||||
|   path_provider: ^2.1.5 |   path_provider: ^2.1.5 | ||||||
|   sqflite: ^2.4.1 |   sqflite: ^2.4.1 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user