import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:timetrack/core/database/app_database.dart' as db; import 'package:timetrack/features/entries/data/drift_entries_repository.dart'; import 'package:timetrack/features/entries/domain/time_entry.dart' as domain; import 'package:timetrack/features/projects/data/project_mapper.dart'; import 'package:timetrack/features/projects/domain/project.dart'; import 'package:timetrack/features/timer/domain/timer_state.dart'; part 'timer_notifier.g.dart'; @riverpod class TimerNotifier extends _$TimerNotifier { @override TimerState build() { _restoreFromDb(); return const TimerState.idle(); } Future _restoreFromDb() async { final repo = ref.read(timeEntriesRepositoryProvider); final active = await repo.getActiveEntry(); if (active == null) return; final projectRow = await ref .read(db.appDatabaseProvider) .projectsDao .getById(active.projectId); if (projectRow == null) return; state = TimerState.running( entryId: active.id, startTime: active.startTime, project: projectRow.toDomain(), note: active.note, ); } Future start(Project project, {String? note}) async { if (state is TimerRunning) await stop(); final repo = ref.read(timeEntriesRepositoryProvider); final now = DateTime.now(); final id = await repo.create(domain.TimeEntry( id: 0, projectId: project.id, startTime: now, tags: const [], createdAt: now, note: note, )); state = TimerState.running( entryId: id, startTime: now, project: project, note: note, ); } Future stop() async { final running = state; if (running is! TimerRunning) return; final now = DateTime.now(); final repo = ref.read(timeEntriesRepositoryProvider); final current = await repo.getActiveEntry(); if (current != null) { await repo.update(current.copyWith( endTime: now, durationSeconds: now.difference(running.startTime).inSeconds, )); } state = const TimerState.idle(); } Future discard() async { final running = state; if (running is! TimerRunning) return; await ref.read(timeEntriesRepositoryProvider).delete(running.entryId); state = const TimerState.idle(); } void updateNote(String note) { final running = state; if (running is! TimerRunning) return; state = running.copyWith(note: note); _persistNote(running.entryId, note); } Future _persistNote(int entryId, String note) async { final repo = ref.read(timeEntriesRepositoryProvider); final entry = await repo.getActiveEntry(); if (entry != null) { await repo.update(entry.copyWith(note: note)); } } }