Compare commits
7 Commits
f5b22c6c1c
...
0.1.2
Author | SHA1 | Date | |
---|---|---|---|
fa852faadc | |||
6f9d0d8afb | |||
75cc72678b | |||
2970431b91 | |||
4d0dc03c69 | |||
bdb3fc5c7a | |||
da2ae6206a |
3
.gitignore
vendored
3
.gitignore
vendored
@ -44,3 +44,6 @@ app.*.map.json
|
|||||||
/android/app/release
|
/android/app/release
|
||||||
|
|
||||||
/android/app/.*
|
/android/app/.*
|
||||||
|
|
||||||
|
# Ignore the releases folder.
|
||||||
|
releases/*
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Recurring Expense Tracker
|
# Recurring Expense Tracker
|
||||||
|
|
||||||
Recurring expense tracker app for Android.
|
Recurring expense tracker app for Linux and Android.
|
||||||
|
|
||||||
Add a debit as daily, weekly, monthly, etc, then see how it affects your liquid
|
Add an expense as daily, weekly, monthly, etc, then see how it affects your
|
||||||
assets based on your reported income over different time projections.
|
liquid assets based on your reported income over different time projections.
|
||||||
|
46
create_release_files.sh
Executable file
46
create_release_files.sh
Executable file
@ -0,0 +1,46 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
DIR="$(dirname -- "${BASH_SOURCE[0]}")"
|
||||||
|
RELEASE_DIR=$DIR/releases
|
||||||
|
|
||||||
|
|
||||||
|
echo "*** Prepare for Builds ***"
|
||||||
|
cd $DIR
|
||||||
|
pwd
|
||||||
|
mkdir -pv $RELEASE_DIR
|
||||||
|
|
||||||
|
echo "*** Get Version ***"
|
||||||
|
grep 'version:' pubspec.yaml | while read v_text v_number; do
|
||||||
|
# Skip any newlines found while grepping.
|
||||||
|
if [[ -z $v_number ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Creating assets for version '$v_number'."
|
||||||
|
|
||||||
|
# Set Up Variables
|
||||||
|
ANDROID_APK="build/app/outputs/flutter-apk/app-release.apk"
|
||||||
|
APK_RENAME="$RELEASE_DIR/ExpenseTracker_$v_number.apk"
|
||||||
|
LINUX_BUNDLE="build/linux/x64/release/bundle"
|
||||||
|
BUNDLE_RENAME="LinuxBundle_$v_number"
|
||||||
|
|
||||||
|
# Build Android App
|
||||||
|
echo -e "\n*** Android APK ***"
|
||||||
|
rm -v "$APK_RENAME"
|
||||||
|
flutter build apk
|
||||||
|
mv -v $ANDROID_APK "$APK_RENAME"
|
||||||
|
ls -sh "$APK_RENAME"
|
||||||
|
|
||||||
|
# Build Linux Project
|
||||||
|
echo -e "\n*** Linux Bundle ***"
|
||||||
|
rm -rv "$RELEASE_DIR/$BUNDLE_RENAME"*
|
||||||
|
flutter build linux
|
||||||
|
mv -v $LINUX_BUNDLE "$RELEASE_DIR/$BUNDLE_RENAME"
|
||||||
|
cd $RELEASE_DIR
|
||||||
|
zip -r $BUNDLE_RENAME.zip $BUNDLE_RENAME
|
||||||
|
rm -rv $BUNDLE_RENAME
|
||||||
|
ls -sh $BUNDLE_RENAME.zip
|
||||||
|
|
||||||
|
# Only one version should be found, but just in case, only use the top one!
|
||||||
|
break
|
||||||
|
done
|
@ -38,9 +38,24 @@ class HelpPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Text("This app is meant to be a simple budgeting tool,"
|
Text(
|
||||||
" allowing you to view your income and expenses at a high level"
|
"\t\t This app is meant to be a simple budgeting tool,"
|
||||||
" without micro managing specific budget items or adding receipts."),
|
" allowing you to view your income and expenses at a high"
|
||||||
|
" level without micro managing specific budget items or"
|
||||||
|
" adding receipts.",
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"\n\t\t Tracked items can be swiped left to right for ,"
|
||||||
|
" Deletion or right to left for Editing. Items are sorted"
|
||||||
|
" from highest to lowest so that the biggest impacts are"
|
||||||
|
" always in view.",
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"\n\t\t To subscribe to app updates, install the Obtanium"
|
||||||
|
" app, then use the URL from the Source Code button below."
|
||||||
|
" Otherwise the app needs installed manually by downloading"
|
||||||
|
" APKs from the Source Code /releases/ page.",
|
||||||
|
),
|
||||||
//Text("Another paragraph.")
|
//Text("Another paragraph.")
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -59,10 +74,12 @@ class HelpPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
child: TextButton.icon(
|
child: TextButton.icon(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_launchSite("https://git.hyperling.com/me");
|
_launchSite(
|
||||||
|
"https://git.hyperling.com/me/flutter-expense-tracker",
|
||||||
|
);
|
||||||
},
|
},
|
||||||
icon: Icon(Icons.code),
|
icon: Icon(Icons.code),
|
||||||
label: Text("Code Repository"),
|
label: Text("Source Code"),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -77,7 +94,9 @@ class HelpPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
child: TextButton.icon(
|
child: TextButton.icon(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_launchSite("https://hyperling.com");
|
_launchSite(
|
||||||
|
"https://hyperling.com",
|
||||||
|
);
|
||||||
},
|
},
|
||||||
icon: Icon(Icons.web_asset),
|
icon: Icon(Icons.web_asset),
|
||||||
label: Text("Personal Website"),
|
label: Text("Personal Website"),
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
// Flutter
|
// Flutter
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import '/models/item_type.dart';
|
import '/models/item_type.dart';
|
||||||
|
|
||||||
@ -13,11 +15,11 @@ import '/models/tracked_item.dart';
|
|||||||
/// - Fix bug where editing an item does not reflect immediately when returning to Reports page.
|
/// - Fix bug where editing an item does not reflect immediately when returning to Reports page.
|
||||||
/// - Currently reflects after going back to Reports the 2nd time.
|
/// - Currently reflects after going back to Reports the 2nd time.
|
||||||
|
|
||||||
double _assetTotal = 0,
|
double _assetTotal = -1,
|
||||||
_expenseMonthly = 0,
|
_expenseMonthly = -1,
|
||||||
_expenseYearly = 0,
|
_expenseYearly = -1,
|
||||||
_incomeMonthly = 0,
|
_incomeMonthly = -1,
|
||||||
_incomeYearly = 0;
|
_incomeYearly = -1;
|
||||||
|
|
||||||
class ProjectionPage extends StatefulWidget {
|
class ProjectionPage extends StatefulWidget {
|
||||||
const ProjectionPage({
|
const ProjectionPage({
|
||||||
@ -29,6 +31,18 @@ class ProjectionPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _ProjectionPageState extends State<ProjectionPage> {
|
class _ProjectionPageState extends State<ProjectionPage> {
|
||||||
|
bool _showProjections = true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_assetTotal = -2;
|
||||||
|
_expenseMonthly = -2;
|
||||||
|
_expenseYearly = -2;
|
||||||
|
_incomeMonthly = -2;
|
||||||
|
_incomeYearly = -2;
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
// Summaries for display as well as calculation of totals for projections.
|
// Summaries for display as well as calculation of totals for projections.
|
||||||
@ -46,50 +60,82 @@ class _ProjectionPageState extends State<ProjectionPage> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Calculations for the projections.
|
// Calculations for the projections.
|
||||||
double oneMonth = _assetTotal + _incomeMonthly - _expenseMonthly,
|
Widget projections;
|
||||||
threeMonths = _assetTotal + (3 * (_incomeMonthly - _expenseMonthly)),
|
if (_assetTotal < 0 ||
|
||||||
sixMonths = _assetTotal + (6 * (_incomeMonthly - _expenseMonthly)),
|
_incomeMonthly < 0 ||
|
||||||
oneYear = _assetTotal + (_incomeYearly - _expenseYearly),
|
_incomeYearly < 0 ||
|
||||||
twoYears = _assetTotal + (2 * (_incomeYearly - _expenseYearly)),
|
_expenseMonthly < 0 ||
|
||||||
fiveYears = _assetTotal + (5 * (_incomeYearly - _expenseYearly));
|
_expenseYearly < 0) {
|
||||||
|
_showProjections = false;
|
||||||
|
|
||||||
// Widgets to show the projections.
|
projections = Center(
|
||||||
Widget proj1 = SummaryCard(
|
child: SizedBox(
|
||||||
name: "One month from now...",
|
child: CircularProgressIndicator(),
|
||||||
leftText: "",
|
),
|
||||||
middleText: oneMonth.toStringAsFixed(2),
|
);
|
||||||
rightText: "",
|
|
||||||
);
|
Future.delayed(Duration(seconds: 1), () {
|
||||||
Widget proj2 = SummaryCard(
|
setState(() {
|
||||||
name: "Three months from now...",
|
_showProjections = true;
|
||||||
leftText: "",
|
});
|
||||||
middleText: threeMonths.toStringAsFixed(2),
|
});
|
||||||
rightText: "",
|
} else {
|
||||||
);
|
double oneMonth = _assetTotal + _incomeMonthly - _expenseMonthly,
|
||||||
Widget proj3 = SummaryCard(
|
threeMonths = _assetTotal + (3 * (_incomeMonthly - _expenseMonthly)),
|
||||||
name: "Half a year from now...",
|
sixMonths = _assetTotal + (6 * (_incomeMonthly - _expenseMonthly)),
|
||||||
leftText: "",
|
oneYear = _assetTotal + (_incomeYearly - _expenseYearly),
|
||||||
middleText: sixMonths.toStringAsFixed(2),
|
twoYears = _assetTotal + (2 * (_incomeYearly - _expenseYearly)),
|
||||||
rightText: "",
|
fiveYears = _assetTotal + (5 * (_incomeYearly - _expenseYearly));
|
||||||
);
|
|
||||||
Widget proj4 = SummaryCard(
|
// Widgets to show the projections.
|
||||||
name: "One year from now...",
|
Widget proj1 = SummaryCard(
|
||||||
leftText: "",
|
name: "One month from now...",
|
||||||
middleText: oneYear.toStringAsFixed(2),
|
leftText: "",
|
||||||
rightText: "",
|
middleText: oneMonth.toStringAsFixed(2),
|
||||||
);
|
rightText: "",
|
||||||
Widget proj5 = SummaryCard(
|
);
|
||||||
name: "Two years from now...",
|
Widget proj2 = SummaryCard(
|
||||||
leftText: "",
|
name: "Three months from now...",
|
||||||
middleText: twoYears.toStringAsFixed(2),
|
leftText: "",
|
||||||
rightText: "",
|
middleText: threeMonths.toStringAsFixed(2),
|
||||||
);
|
rightText: "",
|
||||||
Widget proj6 = SummaryCard(
|
);
|
||||||
name: "Five years from now...",
|
Widget proj3 = SummaryCard(
|
||||||
leftText: "",
|
name: "Half a year from now...",
|
||||||
middleText: fiveYears.toStringAsFixed(2),
|
leftText: "",
|
||||||
rightText: "",
|
middleText: sixMonths.toStringAsFixed(2),
|
||||||
);
|
rightText: "",
|
||||||
|
);
|
||||||
|
Widget proj4 = SummaryCard(
|
||||||
|
name: "One year from now...",
|
||||||
|
leftText: "",
|
||||||
|
middleText: oneYear.toStringAsFixed(2),
|
||||||
|
rightText: "",
|
||||||
|
);
|
||||||
|
Widget proj5 = SummaryCard(
|
||||||
|
name: "Two years from now...",
|
||||||
|
leftText: "",
|
||||||
|
middleText: twoYears.toStringAsFixed(2),
|
||||||
|
rightText: "",
|
||||||
|
);
|
||||||
|
Widget proj6 = SummaryCard(
|
||||||
|
name: "Five years from now...",
|
||||||
|
leftText: "",
|
||||||
|
middleText: fiveYears.toStringAsFixed(2),
|
||||||
|
rightText: "",
|
||||||
|
);
|
||||||
|
|
||||||
|
projections = Column(
|
||||||
|
children: [
|
||||||
|
proj1,
|
||||||
|
proj2,
|
||||||
|
proj3,
|
||||||
|
proj4,
|
||||||
|
proj5,
|
||||||
|
proj6,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Return all of the UI elements.
|
// Return all of the UI elements.
|
||||||
return ListView(
|
return ListView(
|
||||||
@ -99,12 +145,7 @@ class _ProjectionPageState extends State<ProjectionPage> {
|
|||||||
incomeSummary,
|
incomeSummary,
|
||||||
assetSummary,
|
assetSummary,
|
||||||
TitleCard(title: "Projections"),
|
TitleCard(title: "Projections"),
|
||||||
proj1,
|
projections,
|
||||||
proj2,
|
|
||||||
proj3,
|
|
||||||
proj4,
|
|
||||||
proj5,
|
|
||||||
proj6,
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -337,6 +337,7 @@ class _TrackedItemInputDialogState extends State<TrackedItemInputDialog> {
|
|||||||
: Text("Edit ${_type!.title}"),
|
: Text("Edit ${_type!.title}"),
|
||||||
),
|
),
|
||||||
content: FutureBuilder<List<Expense>>(
|
content: FutureBuilder<List<Expense>>(
|
||||||
|
// TODO / TBD -- This should no longer only be Expenses.
|
||||||
future: DatabaseHelper.instance.getExpenses(),
|
future: DatabaseHelper.instance.getExpenses(),
|
||||||
builder: (BuildContext context,
|
builder: (BuildContext context,
|
||||||
AsyncSnapshot<List<Expense>> snapshot) {
|
AsyncSnapshot<List<Expense>> snapshot) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
name: expense_tracker
|
name: 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.1
|
version: 0.1.2
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.6.1
|
sdk: ^3.6.1
|
||||||
|
Reference in New Issue
Block a user