import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:logging/logging.dart'; import 'package:result_monad/result_monad.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import '../models/auth/profile.dart'; import '../models/exec_error.dart'; import '../models/timeline_entry.dart'; import 'networking/friendica_interactions_client_services.dart'; import 'networking/friendica_statuses_client_services.dart'; import 'reshared_via_services.dart'; import 'timeline_services.dart'; part 'timeline_entry_services.g.dart'; @Riverpod(keepAlive: true) Map _timelineEntries(Ref ref, Profile profile) => {}; final _logger = Logger('TimelineEntryManagerProvider'); @Riverpod(keepAlive: true) class TimelineEntryManager extends _$TimelineEntryManager { var entryId = ''; @override Result build(Profile profile, String id) { _logger.finest('Building for $id for $profile'); //ref.cacheFor(const Duration(hours: 1)); entryId = id; final entry = ref.watch(_timelineEntriesProvider(profile))[id]; if (entry == null) { _logger.finest('Entry not found for $id for $profile'); return buildErrorResult( type: ErrorType.notFound, message: '$id not found', ); } _logger.finest('For $id for $profile returning: \n$entry'); return Result.ok(entry); } Result upsert(TimelineEntry entry) { _logger.fine('Upserting entry for ${entry.id} for $profile'); if (entry.id != entryId) { return buildErrorResult( type: ErrorType.argumentError, message: 'Trying to add an entry to a provider that does not match the id: $id', ); } else { ref.read(_timelineEntriesProvider(profile))[entryId] = entry; } if (state.isFailure || entry != state.value) { state = Result.ok(entry); ref.invalidateSelf(); //Confirm I need to do this, I don't think I do } return state; } FutureResult toggleFavorited(bool newStatus) async { final result = await ref .read(changeFavoriteStatusProvider(profile, entryId, newStatus).future) .withResult((update) { _logger.fine('Updating $entryId for $profile to: \n$update'); ref.read(_timelineEntriesProvider(profile))[entryId] = update; }); if (result.isSuccess) { state = result.execErrorCast(); } return state; } FutureResult resharePost() async { final result = await ref .read(resharePostProvider(profile, entryId).future) .withResult((item) async { ref .read(resharedViaProvider(profile, entryId).notifier) .upsertResharedVia(profile.id); }).withResult((update) => ref.read(_timelineEntriesProvider(profile))[entryId] = update); state = result.execErrorCast(); return state; } FutureResult unResharePost() async { final result = await ref .read(unResharePostProvider(profile, entryId).future) .withResult((item) async { ref .read(resharedViaProvider(profile, entryId).notifier) .upsertRemovedSharer(profile.id); }).withResult((update) => ref.read(_timelineEntriesProvider(profile))[entryId] = update); state = result.execErrorCast(); return state; } void remove() { _logger.finest('Delete item $entryId'); ref.read(_timelineEntriesProvider(profile)).remove(entryId); ref.read(timelineMaintainerProvider(profile).notifier).sweep(entryId); ref.invalidateSelf(); } }