Compare commits
17
Commits
c5f1a4e9ba
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
48a8ac93ca | ||
|
|
1900a1378a | ||
|
|
bdebda9c83 | ||
|
|
672d34fa43 | ||
|
|
0aff0208d4 | ||
|
|
097a9ea4ed | ||
|
|
f86d78a969 | ||
|
|
70c26be8e3 | ||
|
|
b177b6317e | ||
|
|
3c52239efc | ||
|
|
de4f8306d7 | ||
|
|
f77cf7bd38 | ||
|
|
716d40c694 | ||
|
|
d9f8536f26 | ||
|
|
1966f72c93 | ||
|
|
e896611bd1 | ||
|
|
2d9c93fec4 |
@@ -1 +1,12 @@
|
|||||||
include: package:flutter_lints/flutter.yaml
|
include: package:flutter_lints/flutter.yaml
|
||||||
|
analyzer:
|
||||||
|
errors:
|
||||||
|
unreachable_switch_default: ignore
|
||||||
|
exclude:
|
||||||
|
- build/**
|
||||||
|
- android/**
|
||||||
|
- ios/**
|
||||||
|
- web/**
|
||||||
|
- windows/**
|
||||||
|
- macos/**
|
||||||
|
- linux/**
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
AuthorName: 'Chad Michael "Hyperling" Greenwood'
|
||||||
|
AuthorWebSite: 'https://hyperling.com/about/'
|
||||||
|
Donate: 'https://hyperling.com/donate/'
|
||||||
|
Liberapay: 'HyperVegan'
|
||||||
|
Bitcoin: 'bc1qsfe8dkvry3d34kztz449gkq67wq8fu2nkgfkh0'
|
||||||
|
Litecoin: 'ltc1qavmpu5d6ljntxsd6jj548m4yys83zwscl0dzkx'
|
||||||
|
IssueTracker: 'https://hyperling.com/contact/'
|
||||||
|
Categories:
|
||||||
|
- fdroid
|
||||||
|
- hyperling
|
||||||
|
- utilities
|
||||||
|
Name: Expense Tracker
|
||||||
|
AuthorEmail: 'me+expense@hyperling.com'
|
||||||
|
Summary: 'Keep track of repeating expenses and view projections of their effect on your finances. First app written with Flutter.'
|
||||||
|
SourceCode: 'https://git.hyperling.com/me/flutter-expense-tracker/'
|
||||||
|
WebSite: 'https://hyperling.com/apps/#expense'
|
||||||
@@ -2,21 +2,26 @@ enum ItemType {
|
|||||||
expense(
|
expense(
|
||||||
title: "Expense",
|
title: "Expense",
|
||||||
plural: "Expenses",
|
plural: "Expenses",
|
||||||
|
description: "Items which cost revenue, or decrease asset value.",
|
||||||
),
|
),
|
||||||
income(
|
income(
|
||||||
title: "Income",
|
title: "Income",
|
||||||
plural: "Incomes",
|
plural: "Income",
|
||||||
|
description: "Items which bring in revenue, or increase asset value.",
|
||||||
),
|
),
|
||||||
asset(
|
asset(
|
||||||
title: "Asset",
|
title: "Asset",
|
||||||
plural: "Assets",
|
plural: "Assets",
|
||||||
|
description: "Value which has been earned and can be spent.",
|
||||||
);
|
);
|
||||||
|
|
||||||
const ItemType({
|
const ItemType({
|
||||||
required this.title,
|
required this.title,
|
||||||
required this.plural,
|
required this.plural,
|
||||||
|
required this.description,
|
||||||
});
|
});
|
||||||
|
|
||||||
final String title;
|
final String title;
|
||||||
final String plural;
|
final String plural;
|
||||||
|
final String description;
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-6
@@ -1,7 +1,11 @@
|
|||||||
// Flutter
|
// Flutter
|
||||||
|
import '/models/item_type.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:url_launcher/url_launcher_string.dart';
|
import 'package:url_launcher/url_launcher_string.dart';
|
||||||
|
|
||||||
|
// Local
|
||||||
|
import '/widgets/cards.dart';
|
||||||
|
|
||||||
_launchSite(String url) async {
|
_launchSite(String url) async {
|
||||||
try {
|
try {
|
||||||
if (await canLaunchUrlString(url)) {
|
if (await canLaunchUrlString(url)) {
|
||||||
@@ -38,23 +42,34 @@ class HelpPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
|
TitleCard(title: "Help"),
|
||||||
Text(
|
Text(
|
||||||
"\t\t This app is meant to be a simple budgeting tool,"
|
"\t\t This app is meant to be a simple budgeting tool,"
|
||||||
" allowing you to view your income and expenses at a high"
|
" allowing you to view your income and expenses at a high"
|
||||||
" level without micro managing specific budget items or"
|
" level without micro managing specific budget items or"
|
||||||
" adding receipts.",
|
" adding receipts."
|
||||||
|
"",
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"\n\t\t Tracked items can be swiped left to right for ,"
|
"\n\t\t ${ItemType.expense.plural} are defined as ${ItemType.expense.description.toLowerCase()}"
|
||||||
|
" ${ItemType.income.title} is defined as ${ItemType.income.description.toLowerCase()}"
|
||||||
|
" ${ItemType.asset.plural} are defined as ${ItemType.asset.description.toLowerCase()}"
|
||||||
|
"",
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"\n\t\t Tracked items can be swiped left to right for"
|
||||||
" Deletion or right to left for Editing. Items are sorted"
|
" Deletion or right to left for Editing. Items are sorted"
|
||||||
" from highest to lowest so that the biggest impacts are"
|
" from highest to lowest so that the biggest impacts are"
|
||||||
" always in view.",
|
" always in view."
|
||||||
|
"",
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"\n\t\t To subscribe to app updates, install the Obtanium"
|
"\n\t\t To subscribe to Android updates, install Obtanium,"
|
||||||
" app, then use the URL from the Source Code button below."
|
" then use the URL from the Source Code button below."
|
||||||
" Otherwise the app needs installed manually by downloading"
|
" Otherwise the app needs installed manually by downloading"
|
||||||
" APKs from the Source Code /releases/ page.",
|
" APKs from the Source Code /releases/ page. Linux users"
|
||||||
|
" currently need to install and update manually."
|
||||||
|
"",
|
||||||
),
|
),
|
||||||
//Text("Another paragraph.")
|
//Text("Another paragraph.")
|
||||||
],
|
],
|
||||||
|
|||||||
+6
-7
@@ -9,7 +9,6 @@ import '/pages/tracked_item.dart';
|
|||||||
import '/pages/report.dart';
|
import '/pages/report.dart';
|
||||||
import '/pages/settings.dart';
|
import '/pages/settings.dart';
|
||||||
import '/pages/help.dart';
|
import '/pages/help.dart';
|
||||||
import '/db.dart';
|
|
||||||
|
|
||||||
class HomePage extends StatefulWidget {
|
class HomePage extends StatefulWidget {
|
||||||
const HomePage({
|
const HomePage({
|
||||||
@@ -56,7 +55,7 @@ class _HomePageState extends State<HomePage> {
|
|||||||
switch (pageSelected) {
|
switch (pageSelected) {
|
||||||
case 0:
|
case 0:
|
||||||
page = TrackedItemPage(
|
page = TrackedItemPage(
|
||||||
assetsToLoad: DatabaseHelper.instance.getExpenses(),
|
assetType: ItemType.expense,
|
||||||
notifyParent: refresh,
|
notifyParent: refresh,
|
||||||
);
|
);
|
||||||
dialog = TrackedItemInputDialog(
|
dialog = TrackedItemInputDialog(
|
||||||
@@ -66,7 +65,7 @@ class _HomePageState extends State<HomePage> {
|
|||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
page = TrackedItemPage(
|
page = TrackedItemPage(
|
||||||
assetsToLoad: DatabaseHelper.instance.getIncomes(),
|
assetType: ItemType.income,
|
||||||
notifyParent: refresh,
|
notifyParent: refresh,
|
||||||
);
|
);
|
||||||
dialog = TrackedItemInputDialog(
|
dialog = TrackedItemInputDialog(
|
||||||
@@ -76,7 +75,7 @@ class _HomePageState extends State<HomePage> {
|
|||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
page = TrackedItemPage(
|
page = TrackedItemPage(
|
||||||
assetsToLoad: DatabaseHelper.instance.getAssets(),
|
assetType: ItemType.asset,
|
||||||
notifyParent: refresh,
|
notifyParent: refresh,
|
||||||
);
|
);
|
||||||
dialog = TrackedItemInputDialog(
|
dialog = TrackedItemInputDialog(
|
||||||
@@ -120,15 +119,15 @@ class _HomePageState extends State<HomePage> {
|
|||||||
destinations: [
|
destinations: [
|
||||||
NavigationRailDestination(
|
NavigationRailDestination(
|
||||||
icon: Icon(Icons.payment),
|
icon: Icon(Icons.payment),
|
||||||
label: Text('Expenses'),
|
label: Text(ItemType.expense.plural),
|
||||||
),
|
),
|
||||||
NavigationRailDestination(
|
NavigationRailDestination(
|
||||||
icon: Icon(Icons.account_balance),
|
icon: Icon(Icons.account_balance),
|
||||||
label: Text('Income'),
|
label: Text(ItemType.income.plural),
|
||||||
),
|
),
|
||||||
NavigationRailDestination(
|
NavigationRailDestination(
|
||||||
icon: Icon(Icons.attach_money),
|
icon: Icon(Icons.attach_money),
|
||||||
label: Text('Liquid Assets'),
|
label: Text(ItemType.asset.plural),
|
||||||
),
|
),
|
||||||
NavigationRailDestination(
|
NavigationRailDestination(
|
||||||
icon: Icon(Icons.bar_chart),
|
icon: Icon(Icons.bar_chart),
|
||||||
|
|||||||
+9
-10
@@ -1,6 +1,5 @@
|
|||||||
// Flutter
|
// Flutter
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import '/models/item_type.dart';
|
import '/models/item_type.dart';
|
||||||
|
|
||||||
@@ -12,8 +11,6 @@ import '/models/tracked_item.dart';
|
|||||||
/// TODO:
|
/// TODO:
|
||||||
/// - Projected Assets:
|
/// - Projected Assets:
|
||||||
/// - Allow customization?
|
/// - Allow customization?
|
||||||
/// - 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.
|
|
||||||
|
|
||||||
double _assetTotal = -1,
|
double _assetTotal = -1,
|
||||||
_expenseMonthly = -1,
|
_expenseMonthly = -1,
|
||||||
@@ -68,18 +65,14 @@ class _ProjectionPageState extends State<ProjectionPage> {
|
|||||||
_expenseYearly < 0) {
|
_expenseYearly < 0) {
|
||||||
_showProjections = false;
|
_showProjections = false;
|
||||||
|
|
||||||
projections = Center(
|
|
||||||
child: SizedBox(
|
|
||||||
child: CircularProgressIndicator(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
Future.delayed(Duration(seconds: 1), () {
|
Future.delayed(Duration(seconds: 1), () {
|
||||||
setState(() {
|
setState(() {
|
||||||
_showProjections = true;
|
_showProjections = true;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
if (_showProjections) {
|
||||||
double oneMonth = _assetTotal + _incomeMonthly - _expenseMonthly,
|
double oneMonth = _assetTotal + _incomeMonthly - _expenseMonthly,
|
||||||
threeMonths = _assetTotal + (3 * (_incomeMonthly - _expenseMonthly)),
|
threeMonths = _assetTotal + (3 * (_incomeMonthly - _expenseMonthly)),
|
||||||
sixMonths = _assetTotal + (6 * (_incomeMonthly - _expenseMonthly)),
|
sixMonths = _assetTotal + (6 * (_incomeMonthly - _expenseMonthly)),
|
||||||
@@ -135,6 +128,12 @@ class _ProjectionPageState extends State<ProjectionPage> {
|
|||||||
proj6,
|
proj6,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
projections = Center(
|
||||||
|
child: SizedBox(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return all of the UI elements.
|
// Return all of the UI elements.
|
||||||
|
|||||||
+12
-2
@@ -1,5 +1,9 @@
|
|||||||
|
// Flutter
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
// Local
|
||||||
|
import '/widgets/cards.dart';
|
||||||
|
|
||||||
/// TODO:
|
/// TODO:
|
||||||
/// - Export DB (JSON?)
|
/// - Export DB (JSON?)
|
||||||
/// - Import DB (JSON?)
|
/// - Import DB (JSON?)
|
||||||
@@ -14,8 +18,14 @@ class SettingsPage extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Center(
|
return Center(
|
||||||
child: Text(
|
child: Column(
|
||||||
"No settings yet. :)",
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
children: [
|
||||||
|
TitleCard(title: "Settings"),
|
||||||
|
Text(
|
||||||
|
"No settings exist yet. :)",
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+54
-12
@@ -9,14 +9,15 @@ import '/models/item_type.dart';
|
|||||||
import '/models/expense.dart';
|
import '/models/expense.dart';
|
||||||
import '/models/frequency.dart';
|
import '/models/frequency.dart';
|
||||||
import '/db.dart';
|
import '/db.dart';
|
||||||
|
import '/widgets/cards.dart';
|
||||||
|
|
||||||
class TrackedItemPage extends StatefulWidget {
|
class TrackedItemPage extends StatefulWidget {
|
||||||
final Future<List<TrackedItem>> assetsToLoad;
|
final ItemType assetType;
|
||||||
final Function() notifyParent;
|
final Function() notifyParent;
|
||||||
|
|
||||||
const TrackedItemPage({
|
const TrackedItemPage({
|
||||||
super.key,
|
super.key,
|
||||||
required this.assetsToLoad,
|
required this.assetType,
|
||||||
required this.notifyParent,
|
required this.notifyParent,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -25,12 +26,28 @@ class TrackedItemPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _TrackedItemPageState extends State<TrackedItemPage> {
|
class _TrackedItemPageState extends State<TrackedItemPage> {
|
||||||
|
late Future<List<TrackedItem>> _assetsToLoad;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
|
|
||||||
|
switch (widget.assetType) {
|
||||||
|
case ItemType.expense:
|
||||||
|
_assetsToLoad = DatabaseHelper.instance.getExpenses();
|
||||||
|
break;
|
||||||
|
case ItemType.income:
|
||||||
|
_assetsToLoad = DatabaseHelper.instance.getIncomes();
|
||||||
|
break;
|
||||||
|
case ItemType.asset:
|
||||||
|
_assetsToLoad = DatabaseHelper.instance.getAssets();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw UnimplementedError("Unsure whch asset group to load.");
|
||||||
|
}
|
||||||
|
|
||||||
return FutureBuilder<List<TrackedItem>>(
|
return FutureBuilder<List<TrackedItem>>(
|
||||||
future: widget.assetsToLoad,
|
future: _assetsToLoad,
|
||||||
builder:
|
builder:
|
||||||
(BuildContext context, AsyncSnapshot<List<TrackedItem>> snapshot) {
|
(BuildContext context, AsyncSnapshot<List<TrackedItem>> snapshot) {
|
||||||
if (!snapshot.hasData) {
|
if (!snapshot.hasData) {
|
||||||
@@ -46,7 +63,19 @@ class _TrackedItemPageState extends State<TrackedItemPage> {
|
|||||||
"Add items to get started.",
|
"Add items to get started.",
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
)
|
)
|
||||||
: ListView.builder(
|
: Column(
|
||||||
|
children: [
|
||||||
|
TitleCard(title: widget.assetType.plural),
|
||||||
|
/*Text(
|
||||||
|
"${widget.assetType.description}",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16.0,
|
||||||
|
decoration: TextDecoration.none,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),*/
|
||||||
|
Expanded(
|
||||||
|
child: ListView.builder(
|
||||||
itemCount: snapshot.data!.length,
|
itemCount: snapshot.data!.length,
|
||||||
itemBuilder: (_, index) {
|
itemBuilder: (_, index) {
|
||||||
final TrackedItem curr = snapshot.data![index];
|
final TrackedItem curr = snapshot.data![index];
|
||||||
@@ -63,7 +92,9 @@ class _TrackedItemPageState extends State<TrackedItemPage> {
|
|||||||
}
|
}
|
||||||
final String itemDescription = curr.description;
|
final String itemDescription = curr.description;
|
||||||
|
|
||||||
final double itemDayAmount, itemMonthAmount, itemYearAmount;
|
final double itemDayAmount,
|
||||||
|
itemMonthAmount,
|
||||||
|
itemYearAmount;
|
||||||
final String estimateSymbolDaily,
|
final String estimateSymbolDaily,
|
||||||
estimateSymbolMonthly,
|
estimateSymbolMonthly,
|
||||||
estimateSymbolYearly;
|
estimateSymbolYearly;
|
||||||
@@ -73,7 +104,9 @@ class _TrackedItemPageState extends State<TrackedItemPage> {
|
|||||||
estimateSymbolDaily = curr.frequency!.numDays
|
estimateSymbolDaily = curr.frequency!.numDays
|
||||||
.toStringAsFixed(2)
|
.toStringAsFixed(2)
|
||||||
.endsWith(".00") &&
|
.endsWith(".00") &&
|
||||||
itemDayAmount.toStringAsFixed(3).endsWith("0")
|
itemDayAmount
|
||||||
|
.toStringAsFixed(3)
|
||||||
|
.endsWith("0")
|
||||||
? ""
|
? ""
|
||||||
: "~";
|
: "~";
|
||||||
|
|
||||||
@@ -82,7 +115,9 @@ class _TrackedItemPageState extends State<TrackedItemPage> {
|
|||||||
estimateSymbolMonthly = curr.frequency!.timesPerYear
|
estimateSymbolMonthly = curr.frequency!.timesPerYear
|
||||||
.toStringAsFixed(2)
|
.toStringAsFixed(2)
|
||||||
.endsWith(".00") &&
|
.endsWith(".00") &&
|
||||||
itemMonthAmount.toStringAsFixed(3).endsWith("0")
|
itemMonthAmount
|
||||||
|
.toStringAsFixed(3)
|
||||||
|
.endsWith("0")
|
||||||
? ""
|
? ""
|
||||||
: "~";
|
: "~";
|
||||||
|
|
||||||
@@ -90,7 +125,9 @@ class _TrackedItemPageState extends State<TrackedItemPage> {
|
|||||||
estimateSymbolYearly = curr.frequency!.timesPerYear
|
estimateSymbolYearly = curr.frequency!.timesPerYear
|
||||||
.toStringAsFixed(2)
|
.toStringAsFixed(2)
|
||||||
.endsWith(".00") &&
|
.endsWith(".00") &&
|
||||||
itemYearAmount.toStringAsFixed(3).endsWith("0")
|
itemYearAmount
|
||||||
|
.toStringAsFixed(3)
|
||||||
|
.endsWith("0")
|
||||||
? ""
|
? ""
|
||||||
: "~";
|
: "~";
|
||||||
} else {
|
} else {
|
||||||
@@ -102,7 +139,8 @@ class _TrackedItemPageState extends State<TrackedItemPage> {
|
|||||||
estimateSymbolYearly = "";
|
estimateSymbolYearly = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
final String monthlyTitle = curr.type == ItemType.asset
|
final String monthlyTitle =
|
||||||
|
curr.type == ItemType.asset
|
||||||
? ""
|
? ""
|
||||||
: " ${Frequency.monthly.title}";
|
: " ${Frequency.monthly.title}";
|
||||||
|
|
||||||
@@ -196,7 +234,8 @@ class _TrackedItemPageState extends State<TrackedItemPage> {
|
|||||||
children: [
|
children: [
|
||||||
Column(
|
Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
itemTitle,
|
itemTitle,
|
||||||
@@ -221,7 +260,8 @@ class _TrackedItemPageState extends State<TrackedItemPage> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
itemTopText,
|
itemTopText,
|
||||||
@@ -244,6 +284,9 @@ class _TrackedItemPageState extends State<TrackedItemPage> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -352,7 +395,6 @@ class _TrackedItemInputDialogState extends State<TrackedItemInputDialog> {
|
|||||||
: Text("Edit ${_type!.title}"),
|
: Text("Edit ${_type!.title}"),
|
||||||
),
|
),
|
||||||
content: FutureBuilder<List<TrackedItem>>(
|
content: FutureBuilder<List<TrackedItem>>(
|
||||||
// TODO / TBD -- This should no longer only be Expenses.
|
|
||||||
future: items,
|
future: items,
|
||||||
builder: (BuildContext context,
|
builder: (BuildContext context,
|
||||||
AsyncSnapshot<List<TrackedItem>> snapshot) {
|
AsyncSnapshot<List<TrackedItem>> snapshot) {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// Flutter
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class TitleCard extends StatelessWidget {
|
class TitleCard extends StatelessWidget {
|
||||||
@@ -15,7 +16,11 @@ class TitleCard extends StatelessWidget {
|
|||||||
child: Center(
|
child: Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
title,
|
title,
|
||||||
style: TextStyle(fontSize: 20),
|
style: TextStyle(
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
decoration: TextDecoration.underline,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
+21
-21
@@ -21,10 +21,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: characters
|
name: characters
|
||||||
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
|
sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.4.0"
|
version: "1.4.1"
|
||||||
clock:
|
clock:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -45,10 +45,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: fake_async
|
name: fake_async
|
||||||
sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc"
|
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.2"
|
version: "1.3.3"
|
||||||
ffi:
|
ffi:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -100,26 +100,26 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: leak_tracker
|
name: leak_tracker
|
||||||
sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec
|
sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "10.0.8"
|
version: "11.0.2"
|
||||||
leak_tracker_flutter_testing:
|
leak_tracker_flutter_testing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: leak_tracker_flutter_testing
|
name: leak_tracker_flutter_testing
|
||||||
sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
|
sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.9"
|
version: "3.0.10"
|
||||||
leak_tracker_testing:
|
leak_tracker_testing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: leak_tracker_testing
|
name: leak_tracker_testing
|
||||||
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
|
sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.1"
|
version: "3.0.2"
|
||||||
lints:
|
lints:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -132,26 +132,26 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: matcher
|
name: matcher
|
||||||
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
|
sha256: "31bd099b47c10cd1aeb55146a2d46ce0277630ecef3f7dae54ad7873f36696cd"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.17"
|
version: "0.12.20"
|
||||||
material_color_utilities:
|
material_color_utilities:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: material_color_utilities
|
name: material_color_utilities
|
||||||
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
|
sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.11.1"
|
version: "0.13.0"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: meta
|
name: meta
|
||||||
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
|
sha256: "307249ce4ff29d58a18e97f6345f539382eb9c9c29ecda628900f31de0443dd9"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.16.0"
|
version: "1.19.0"
|
||||||
package_info_plus:
|
package_info_plus:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -353,10 +353,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
|
sha256: "2a122cbe059f8b610d3a5415f42e255b6c17b1f21eee1d960f31080237fb4f11"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.4"
|
version: "0.7.12"
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -433,10 +433,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vector_math
|
name: vector_math
|
||||||
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
|
sha256: "92b9910f66ed1057fd4da7b040ae7c74cafacf885bdc81be496928d5049b032d"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.4"
|
version: "2.4.3"
|
||||||
vm_service:
|
vm_service:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -470,5 +470,5 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.0"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.7.0 <4.0.0"
|
dart: ">=3.11.0-0 <4.0.0"
|
||||||
flutter: ">=3.27.0"
|
flutter: ">=3.27.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user