99 lines
2.8 KiB
Dart
99 lines
2.8 KiB
Dart
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<void> _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<void> 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<void> 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<void> 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<void> _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));
|
|
}
|
|
}
|
|
}
|