Compare commits
10
Commits
516db8edc1
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7e2d02b643 | ||
|
|
4c4a1c7f20 | ||
|
|
97c67376f5 | ||
|
|
aa7f99b3a5 | ||
|
|
78add73278 | ||
|
|
c86c2dd888 | ||
|
|
68e302c600 | ||
|
|
94a055f21f | ||
|
|
68e4481f2e | ||
|
|
1ee4458f6f |
@@ -196,3 +196,4 @@ doc/api/
|
|||||||
.flutter-plugins
|
.flutter-plugins
|
||||||
.flutter-plugins-dependencies
|
.flutter-plugins-dependencies
|
||||||
|
|
||||||
|
debug_info/
|
||||||
|
|||||||
@@ -6,7 +6,10 @@ Eine Flutter-App um den Überblick über wiederkehrende Transaktionen und den da
|
|||||||
|
|
||||||
`flutter run --web-header=Cross-Origin-Opener-Policy=same-origin --web-header=Cross-Origin-Embedder-Policy=require-corp`
|
`flutter run --web-header=Cross-Origin-Opener-Policy=same-origin --web-header=Cross-Origin-Embedder-Policy=require-corp`
|
||||||
|
|
||||||
## Release TODO:
|
## Release:
|
||||||
|
|
||||||
|
Build Android:
|
||||||
|
- `flutter build apk --obfuscate --split-debug-info=debug_info`
|
||||||
|
|
||||||
Webserver Header:
|
Webserver Header:
|
||||||
|
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ class AccountController {
|
|||||||
icon: Icons.delete_forever,
|
icon: Icons.delete_forever,
|
||||||
actions: [
|
actions: [
|
||||||
DialogAction(label: 'Abbruch', isPrimary: true),
|
DialogAction(label: 'Abbruch', isPrimary: true),
|
||||||
DialogAction(label: 'Account löschen', onPressed: _deleteAccount),
|
DialogAction(label: 'Löschen', onPressed: _deleteAccount),
|
||||||
],
|
],
|
||||||
hiddenValues: {'account': account},
|
hiddenValues: {'account': account},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import 'dart:io';
|
|||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:isolate_manager/isolate_manager.dart';
|
import 'package:isolate_manager/isolate_manager.dart';
|
||||||
|
import 'package:uuid/uuid.dart';
|
||||||
import 'package:workmanager/workmanager.dart';
|
import 'package:workmanager/workmanager.dart';
|
||||||
|
|
||||||
import '../Tasks/BackgroundHandler/workers.dart';
|
import '../Tasks/BackgroundHandler/workers.dart';
|
||||||
@@ -50,4 +51,18 @@ class BackgroundTaskController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Führt den angegebenen Task sofort aus.
|
||||||
|
static Future<void> run(final String taskName) async {
|
||||||
|
if (!kIsWeb && Platform.isAndroid) {
|
||||||
|
final String uuid = const Uuid().v4();
|
||||||
|
unawaited(Workmanager().registerOneOffTask('$taskName-$uuid', taskName));
|
||||||
|
} else {
|
||||||
|
unawaited(IsolateManager.runFunction(runTask, {
|
||||||
|
'taskName': taskName,
|
||||||
|
'initialDelayMinutes': 0,
|
||||||
|
'frequencyMinutes': 0,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import '../Pages/Dialog/dialog_type_enum.dart';
|
|||||||
import '../Pages/Dialog/dynamic_dialog.dart';
|
import '../Pages/Dialog/dynamic_dialog.dart';
|
||||||
import '../Repositories/recurring_transacation_repository.dart';
|
import '../Repositories/recurring_transacation_repository.dart';
|
||||||
import 'account_controller.dart';
|
import 'account_controller.dart';
|
||||||
|
import 'background_task_controller.dart';
|
||||||
|
|
||||||
/// Steuert die Interaktion mit den wiederkehrenden Transaktionen
|
/// Steuert die Interaktion mit den wiederkehrenden Transaktionen
|
||||||
class RecurringTransactionController {
|
class RecurringTransactionController {
|
||||||
@@ -213,7 +214,7 @@ class RecurringTransactionController {
|
|||||||
actions: [
|
actions: [
|
||||||
DialogAction(label: 'Abbruch', isPrimary: true),
|
DialogAction(label: 'Abbruch', isPrimary: true),
|
||||||
DialogAction(
|
DialogAction(
|
||||||
label: 'Wiederkehrende Transaktion löschen',
|
label: 'Löschen',
|
||||||
onPressed: _deleteRecurringTransaction,
|
onPressed: _deleteRecurringTransaction,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -258,6 +259,7 @@ class RecurringTransactionController {
|
|||||||
await _recurringTransactionCreatedDialog?.show();
|
await _recurringTransactionCreatedDialog?.show();
|
||||||
|
|
||||||
await updateRecurringTransactions();
|
await updateRecurringTransactions();
|
||||||
|
unawaited(BackgroundTaskController.run('generate_transactions'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ class TransactionController {
|
|||||||
actions: [
|
actions: [
|
||||||
DialogAction(label: 'Abbruch', isPrimary: true),
|
DialogAction(label: 'Abbruch', isPrimary: true),
|
||||||
DialogAction(
|
DialogAction(
|
||||||
label: 'Transaktion löschen',
|
label: 'Löschen',
|
||||||
onPressed: _deleteTransaction,
|
onPressed: _deleteTransaction,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_expandable_fab/flutter_expandable_fab.dart';
|
import 'package:flutter_expandable_fab/flutter_expandable_fab.dart';
|
||||||
|
|
||||||
import '../../Controller/account_controller.dart';
|
import '../../Controller/account_controller.dart';
|
||||||
import '../../Controller/recurring_transaction_controller.dart';
|
import '../../Controller/recurring_transaction_controller.dart';
|
||||||
import '../../Controller/transaction_controller.dart';
|
import '../../Controller/transaction_controller.dart';
|
||||||
|
import '../../Services/navigation_service.dart';
|
||||||
|
|
||||||
/// Ein Floating Action Button, der beim Klicken ein expandierendes Menü öffnet,
|
/// Ein Floating Action Button, der beim Klicken ein expandierendes Menü öffnet,
|
||||||
/// um neue Transaktionen oder Konten anzulegen.
|
/// um neue Transaktionen oder Konten anzulegen.
|
||||||
@@ -80,15 +83,32 @@ class _FloatingCreationButtonState extends State<FloatingCreationButton> {
|
|||||||
required final String label,
|
required final String label,
|
||||||
required final IconData icon,
|
required final IconData icon,
|
||||||
required final VoidCallback onPressed,
|
required final VoidCallback onPressed,
|
||||||
}) => GestureDetector(
|
}) {
|
||||||
|
final ThemeData theme = Theme.of(
|
||||||
|
NavigationService.getCurrentBuildContext()!,
|
||||||
|
);
|
||||||
|
|
||||||
|
return GestureDetector(
|
||||||
onTap: onPressed,
|
onTap: onPressed,
|
||||||
child: Row(
|
child: Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Container(
|
ClipRRect(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(8)),
|
child: BackdropFilter(
|
||||||
|
filter: ImageFilter.blur(sigmaX: 6, sigmaY: 6),
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 12,
|
||||||
|
vertical: 8,
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: theme.colorScheme.onPrimary.withValues(alpha: 0.15),
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
child: Text(label),
|
child: Text(label),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
const SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
FloatingActionButton.small(
|
FloatingActionButton.small(
|
||||||
heroTag: null,
|
heroTag: null,
|
||||||
@@ -106,3 +126,4 @@ class _FloatingCreationButtonState extends State<FloatingCreationButton> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,4 +16,32 @@ class DateUtils {
|
|||||||
final DateTime monthDate,
|
final DateTime monthDate,
|
||||||
final int monthsToAdd,
|
final int monthsToAdd,
|
||||||
) => DateTime(monthDate.year, monthDate.month + monthsToAdd);
|
) => DateTime(monthDate.year, monthDate.month + monthsToAdd);
|
||||||
|
|
||||||
|
/// Returns the number of days in a month, according to the proleptic
|
||||||
|
/// Gregorian calendar.
|
||||||
|
///
|
||||||
|
/// This applies the leap year logic introduced by the Gregorian reforms of
|
||||||
|
/// 1582. It will not give valid results for dates prior to that time.
|
||||||
|
static int getDaysInMonth(final int year, final int month) {
|
||||||
|
if (month == DateTime.february) {
|
||||||
|
final bool isLeapYear =
|
||||||
|
(year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0);
|
||||||
|
return isLeapYear ? 29 : 28;
|
||||||
|
}
|
||||||
|
const List<int> daysInMonth = <int>[
|
||||||
|
31,
|
||||||
|
-1,
|
||||||
|
31,
|
||||||
|
30,
|
||||||
|
31,
|
||||||
|
30,
|
||||||
|
31,
|
||||||
|
31,
|
||||||
|
30,
|
||||||
|
31,
|
||||||
|
30,
|
||||||
|
31,
|
||||||
|
];
|
||||||
|
return daysInMonth[month - 1];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,10 +18,12 @@ Future<void> runTask(final Map<String, dynamic> params) async {
|
|||||||
|
|
||||||
await executeTask(taskName, null);
|
await executeTask(taskName, null);
|
||||||
|
|
||||||
|
if (frequencyMinutes > 0) {
|
||||||
await Future.delayed(Duration(minutes: frequencyMinutes));
|
await Future.delayed(Duration(minutes: frequencyMinutes));
|
||||||
|
|
||||||
unawaited(runTask(params));
|
unawaited(runTask(params));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Funktion um Hintergrundaufgaben auszuführen
|
/// Funktion um Hintergrundaufgaben auszuführen
|
||||||
Future<bool> executeTask(
|
Future<bool> executeTask(
|
||||||
|
|||||||
@@ -67,15 +67,51 @@ class GenerateTransactionsTask extends Task {
|
|||||||
case TimeFrameEnum.weekly:
|
case TimeFrameEnum.weekly:
|
||||||
newTransactionDate = lastTransactionDate.add(const Duration(days: 7));
|
newTransactionDate = lastTransactionDate.add(const Duration(days: 7));
|
||||||
case TimeFrameEnum.monthly:
|
case TimeFrameEnum.monthly:
|
||||||
newTransactionDate = DateUtils.addMonthsToMonthDate(
|
final DateTime monthDate = DateUtils.addMonthsToMonthDate(
|
||||||
lastTransactionDate,
|
lastTransactionDate,
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final int day =
|
||||||
|
recurringTransaction.startDate!.day <
|
||||||
|
DateUtils.getDaysInMonth(
|
||||||
|
monthDate.year,
|
||||||
|
monthDate.day,
|
||||||
|
)
|
||||||
|
? recurringTransaction.startDate!.day
|
||||||
|
: DateUtils.getDaysInMonth(
|
||||||
|
monthDate.year,
|
||||||
|
monthDate.month,
|
||||||
|
);
|
||||||
|
|
||||||
|
newTransactionDate = DateTime(
|
||||||
|
monthDate.year,
|
||||||
|
monthDate.month,
|
||||||
|
day,
|
||||||
|
);
|
||||||
case TimeFrameEnum.yearly:
|
case TimeFrameEnum.yearly:
|
||||||
newTransactionDate = DateUtils.addMonthsToMonthDate(
|
final DateTime monthDate = DateUtils.addMonthsToMonthDate(
|
||||||
lastTransactionDate,
|
lastTransactionDate,
|
||||||
12,
|
12,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final int day =
|
||||||
|
recurringTransaction.startDate!.day <
|
||||||
|
DateUtils.getDaysInMonth(
|
||||||
|
monthDate.year,
|
||||||
|
monthDate.day,
|
||||||
|
)
|
||||||
|
? recurringTransaction.startDate!.day
|
||||||
|
: DateUtils.getDaysInMonth(
|
||||||
|
monthDate.year,
|
||||||
|
monthDate.month,
|
||||||
|
);
|
||||||
|
|
||||||
|
newTransactionDate = DateTime(
|
||||||
|
monthDate.year,
|
||||||
|
monthDate.month,
|
||||||
|
day,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
newTransactionDate = recurringTransaction.startDate!;
|
newTransactionDate = recurringTransaction.startDate!;
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ dependencies:
|
|||||||
package_info_plus: ^9.0.0
|
package_info_plus: ^9.0.0
|
||||||
path_provider: ^2.1.5
|
path_provider: ^2.1.5
|
||||||
routemaster: ^1.0.1
|
routemaster: ^1.0.1
|
||||||
|
uuid: ^4.5.2
|
||||||
workmanager: ^0.9.0+3
|
workmanager: ^0.9.0+3
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
|||||||
+4871
-4858
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user