8 Commits

Author SHA1 Message Date
marco 392ec22dcd Merge pull request 'Feature: dismissible tasks' (#1) from development into main
Flutter APK Build / Build Flutter APK (push) Successful in 5m43s
Reviewed-on: #1
2026-06-19 00:36:43 +02:00
marco 064c014f8b removed unused import 2026-06-19 00:35:38 +02:00
marco 410a7eb843 made tasks dismissible 2026-06-19 00:35:20 +02:00
marco 20b017b066 added alarmkey and locationkey to allowlist 2026-06-19 00:21:34 +02:00
marco a3258b84fe added controllers to context 2026-06-19 00:02:35 +02:00
marco f088b84c54 updated imports 2026-06-18 23:20:38 +02:00
marco 5a39148577 moved controllers to folder 2026-06-18 23:19:44 +02:00
marco 2b718b5bd8 added controller for locations 2026-06-18 23:18:09 +02:00
9 changed files with 118 additions and 27 deletions
+9 -1
View File
@@ -4,7 +4,9 @@ import 'model/repositories/local_repository.dart';
import 'pages/task_edit_page.dart'; import 'pages/task_edit_page.dart';
import 'pages/task_overview_page.dart'; import 'pages/task_overview_page.dart';
import 'service/controller_scope.dart'; import 'service/controller_scope.dart';
import 'service/task_controller.dart'; import 'service/controllers/alarm_controller.dart';
import 'service/controllers/location_controller.dart';
import 'service/controllers/task_controller.dart';
void main() async { void main() async {
final repository = LocalRepository(); final repository = LocalRepository();
@@ -13,9 +15,15 @@ void main() async {
runApp( runApp(
ControllerScope( ControllerScope(
controller: LocationController(repository),
child: ControllerScope(
controller: AlarmController(repository),
child: ControllerScope(
controller: TaskController(repository), controller: TaskController(repository),
child: const MainApp(), child: const MainApp(),
), ),
),
),
); );
} }
@@ -1,4 +1,3 @@
import '../location.dart';
import '../task.dart'; import '../task.dart';
class CreateTaskRequest { class CreateTaskRequest {
+6 -1
View File
@@ -22,7 +22,12 @@ class LocalRepository
if (_prefs == null) { if (_prefs == null) {
await SharedPreferencesWithCache.create( await SharedPreferencesWithCache.create(
cacheOptions: const SharedPreferencesWithCacheOptions( cacheOptions: const SharedPreferencesWithCacheOptions(
allowList: <String>{_tasksKey, _taskOrderKey}, allowList: <String>{
_tasksKey,
_taskOrderKey,
_alarmsKey,
_locationsKey,
},
), ),
).then((value) => _prefs = value); ).then((value) => _prefs = value);
} }
+1 -1
View File
@@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
import '../model/callback_models/create_task_request.dart'; import '../model/callback_models/create_task_request.dart';
import '../model/extensions/controller_context.dart'; import '../model/extensions/controller_context.dart';
import '../model/task.dart'; import '../model/task.dart';
import '../service/task_controller.dart'; import '../service/controllers/task_controller.dart';
import '../service/tools.dart'; import '../service/tools.dart';
import '../widgets/time_selector.dart'; import '../widgets/time_selector.dart';
+7 -2
View File
@@ -3,8 +3,9 @@ import 'package:flutter/material.dart';
import '../model/callback_models/create_task_request.dart'; import '../model/callback_models/create_task_request.dart';
import '../model/extensions/controller_context.dart'; import '../model/extensions/controller_context.dart';
import '../model/task.dart'; import '../model/task.dart';
import '../service/task_controller.dart'; import '../service/controllers/task_controller.dart';
import '../service/tools.dart'; import '../service/tools.dart';
import '../widgets/task_dismissible.dart';
import 'task_edit_page.dart'; import 'task_edit_page.dart';
class TaskOverviewPage extends StatefulWidget { class TaskOverviewPage extends StatefulWidget {
@@ -37,8 +38,11 @@ class _TaskOverviewPageState extends State<TaskOverviewPage> {
Widget itemBuilder(BuildContext context, int index) { Widget itemBuilder(BuildContext context, int index) {
final task = tasks.elementAt(index); final task = tasks.elementAt(index);
return ListTile( return TaskDismissible(
key: Key(task.id), key: Key(task.id),
onDismissedRight: () =>
context.controller<TaskController>().deleteTask(task),
child: ListTile(
title: Text(task.title), title: Text(task.title),
subtitle: task.description.isNotEmpty ? Text(task.description) : null, subtitle: task.description.isNotEmpty ? Text(task.description) : null,
trailing: Checkbox( trailing: Checkbox(
@@ -55,6 +59,7 @@ class _TaskOverviewPageState extends State<TaskOverviewPage> {
); );
} }
}, },
),
); );
} }
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../model/alarm.dart'; import '../../model/alarm.dart';
import '../model/repositories/interfaces/alarm_repository.dart'; import '../../model/repositories/interfaces/alarm_repository.dart';
class AlarmController extends ChangeNotifier { class AlarmController extends ChangeNotifier {
AlarmController(AlarmRepository repository) : _repository = repository { AlarmController(AlarmRepository repository) : _repository = repository {
@@ -0,0 +1,33 @@
import 'package:flutter/material.dart';
import '../../model/location.dart';
import '../../model/repositories/interfaces/location_repository.dart';
class LocationController extends ChangeNotifier {
LocationController(LocationRepository repository) : _repository = repository {
_loadLocations();
}
final LocationRepository _repository;
final List<Location> _locations = [];
Future<void> addLocation(Location location) {
_locations.add(location);
notifyListeners();
return _repository.createLocation(location);
}
Future<void> deleteLocation(Location location) {
_locations.remove(location);
notifyListeners();
return _repository.deleteLocation(location);
}
Future<void> _loadLocations() {
_locations.clear();
return _repository.loadLocations().then(
(value) => _locations.addAll(value),
);
}
}
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart' show ChangeNotifier; import 'package:flutter/material.dart' show ChangeNotifier;
import '../model/repositories/interfaces/task_repository.dart'; import '../../model/repositories/interfaces/task_repository.dart';
import '../model/task.dart'; import '../../model/task.dart';
class TaskController extends ChangeNotifier { class TaskController extends ChangeNotifier {
TaskController(TaskRepository repository) : _repository = repository { TaskController(TaskRepository repository) : _repository = repository {
+41
View File
@@ -0,0 +1,41 @@
import 'package:flutter/material.dart';
class TaskDismissible extends StatelessWidget {
const TaskDismissible({
required super.key,
this.onDismissedRight,
required this.child,
});
final VoidCallback? onDismissedRight;
final Widget child;
@override
Widget build(BuildContext context) {
return Dismissible(
key: key!,
direction: DismissDirection.startToEnd,
background: Container(
color: Theme.of(context).colorScheme.error,
child: Align(
alignment: AlignmentGeometry.centerLeft,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Icon(
Icons.delete,
color: Theme.of(context).colorScheme.onError,
),
),
),
),
onDismissed: onDismissed,
child: child,
);
}
void onDismissed(DismissDirection direction) {
if (direction == DismissDirection.startToEnd && onDismissedRight != null) {
onDismissedRight!();
}
}
}