import 'package:cookie_jar/cookie_jar.dart'; import 'package:dio/dio.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../data/api/api_client.dart'; import '../data/api/auth_api.dart'; import '../data/api/chat_api.dart'; import '../data/api/journal_api.dart'; import '../data/api/knowledge_api.dart'; import '../data/api/voice_api.dart'; import '../data/api/milestones_api.dart'; import '../data/api/events_api.dart'; import '../data/api/notes_api.dart'; import '../data/api/projects_api.dart'; import '../data/api/quick_capture_api.dart'; import '../data/api/settings_api.dart'; import '../data/api/tasks_api.dart'; import '../data/local/database.dart'; import '../data/repositories/auth_repository.dart'; import '../data/repositories/chat_repository.dart'; import '../data/repositories/events_repository.dart'; import '../data/repositories/knowledge_repository.dart'; import '../data/repositories/voice_repository.dart'; import '../data/repositories/milestones_repository.dart'; import '../data/repositories/notes_repository.dart'; import '../data/repositories/projects_repository.dart'; import '../data/repositories/tasks_repository.dart'; import '../data/repositories/write_queue.dart'; import 'settings_provider.dart'; final cookieJarProvider = Provider((ref) { final cookiesPath = ref.watch(cookiesPathProvider); return buildCookieJar(cookiesPath); }); final dioProvider = Provider((ref) { final url = ref.watch(serverUrlProvider) ?? ''; final jar = ref.watch(cookieJarProvider); return buildDio(url, jar); }); final authApiProvider = Provider((ref) { return AuthApi(ref.watch(dioProvider)); }); final notesApiProvider = Provider((ref) { return NotesApi(ref.watch(dioProvider)); }); final tasksApiProvider = Provider((ref) { return TasksApi(ref.watch(dioProvider)); }); final chatApiProvider = Provider((ref) { return ChatApi(ref.watch(dioProvider)); }); final quickCaptureApiProvider = Provider((ref) { return QuickCaptureApi(ref.watch(dioProvider)); }); final projectsApiProvider = Provider((ref) { return ProjectsApi(ref.watch(dioProvider)); }); /// Local SQLite cache used by repositories for read-through caching and /// offline fallback. Backed by Drift; lives for the lifetime of the /// ProviderScope and is closed automatically when the scope disposes. final fabledDatabaseProvider = Provider((ref) { final db = FabledDatabase(); ref.onDispose(db.close); return db; }); final authRepositoryProvider = Provider((ref) { return AuthRepository(ref.watch(authApiProvider)); }); final notesRepositoryProvider = Provider((ref) { return NotesRepository( ref.watch(notesApiProvider), ref.watch(fabledDatabaseProvider), ); }); final tasksRepositoryProvider = Provider((ref) { return TasksRepository( ref.watch(tasksApiProvider), ref.watch(fabledDatabaseProvider), ); }); final chatRepositoryProvider = Provider((ref) { return ChatRepository( ref.watch(chatApiProvider), ref.watch(fabledDatabaseProvider), ); }); final projectsRepositoryProvider = Provider((ref) { return ProjectsRepository( ref.watch(projectsApiProvider), ref.watch(fabledDatabaseProvider), ); }); final milestonesApiProvider = Provider((ref) { return MilestonesApi(ref.watch(dioProvider)); }); final milestonesRepositoryProvider = Provider((ref) { return MilestonesRepository( ref.watch(milestonesApiProvider), ref.watch(fabledDatabaseProvider), ); }); final knowledgeApiProvider = Provider((ref) { return KnowledgeApi(ref.watch(dioProvider)); }); final knowledgeRepositoryProvider = Provider((ref) { return KnowledgeRepository(ref.watch(knowledgeApiProvider)); }); final journalApiProvider = Provider((ref) { return JournalApi(ref.watch(dioProvider)); }); final settingsApiProvider = Provider((ref) { return SettingsApi(ref.watch(dioProvider)); }); final voiceApiProvider = Provider((ref) { return VoiceApi(ref.watch(dioProvider)); }); final voiceRepositoryProvider = Provider((ref) { return VoiceRepository(ref.watch(voiceApiProvider)); }); final eventsApiProvider = Provider((ref) { return EventsApi(ref.watch(dioProvider)); }); final eventsRepositoryProvider = Provider((ref) { return EventsRepository( ref.watch(eventsApiProvider), ref.watch(fabledDatabaseProvider), ); }); /// Phase 3 — drains the offline write queue. Listen on /// `writeQueueFailuresProvider` to surface dropped ops to the user; /// `writeQueueDepthProvider` powers the OfflineBanner's "Retry (N)" affordance. final writeQueueProvider = Provider((ref) { final queue = WriteQueue( db: ref.watch(fabledDatabaseProvider), notesApi: ref.watch(notesApiProvider), tasksApi: ref.watch(tasksApiProvider), projectsApi: ref.watch(projectsApiProvider), milestonesApi: ref.watch(milestonesApiProvider), eventsApi: ref.watch(eventsApiProvider), ); ref.onDispose(queue.dispose); return queue; }); final writeQueueDepthProvider = StreamProvider((ref) { return ref.watch(fabledDatabaseProvider).watchQueueDepth(); }); final writeQueueFailuresProvider = StreamProvider((ref) { return ref.watch(writeQueueProvider).failures; }); /// Per-domain set of ids with a queued write (target_id ∪ temp_id). Phase 4 /// — used by `PendingSyncBadge` in list views to mark rows that are still /// in flight. final pendingNoteIdsProvider = StreamProvider>((ref) { return ref.watch(fabledDatabaseProvider).watchPendingIds(kSyncDomainNotes); }); final pendingTaskIdsProvider = StreamProvider>((ref) { return ref.watch(fabledDatabaseProvider).watchPendingIds(kSyncDomainTasks); }); final pendingProjectIdsProvider = StreamProvider>((ref) { return ref .watch(fabledDatabaseProvider) .watchPendingIds(kSyncDomainProjects); });