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 '../friendica_client/friendica_client.dart'; import '../models/auth/profile.dart'; import '../models/exec_error.dart'; import '../models/timeline_entry.dart'; import 'reshared_via_services.dart'; part 'timeline_entry_services.g.dart'; @Riverpod(keepAlive: true) Map _timelineEntries(Ref ref, Profile profile) => {}; final _logger = Logger('TimelineEntryManagerProvider'); //TODO Test using cacheFor to let it expire @Riverpod(keepAlive: true) class TimelineEntryManager extends _$TimelineEntryManager { late Profile userProfile; var entryId = ''; @override Result build(Profile profile, String id) { _logger.finest('Building for $id for $profile'); //ref.cacheFor(const Duration(hours: 1)); entryId = id; userProfile = profile; 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 $userProfile'); 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(userProfile))[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 interactionClient = InteractionsClient(userProfile); final result = await interactionClient .changeFavoriteStatus(entryId, newStatus) .withResult((update) { _logger.fine('Updating $entryId for $userProfile to: \n$update'); ref.read(_timelineEntriesProvider(userProfile))[entryId] = update; }); if (result.isSuccess) { state = result.execErrorCast(); } return state; } FutureResult resharePost() async { final client = StatusesClient(profile); final result = await client.resharePost(entryId).withResult((item) async { ref .read(resharedViaProvider(userProfile, entryId).notifier) .upsertResharedVia(profile.id); }).withResult((update) => ref.read(_timelineEntriesProvider(userProfile))[entryId] = update); state = result.execErrorCast(); return state; } FutureResult unResharePost() async { final client = StatusesClient(profile); final result = await client.unResharePost(entryId).withResult((item) async { ref .read(resharedViaProvider(userProfile, entryId).notifier) .upsertRemovedSharer(profile.id); }).withResult((update) => ref.read(_timelineEntriesProvider(userProfile))[entryId] = update); state = result.execErrorCast(); return state; } void remove() { ref.read(_timelineEntriesProvider(userProfile)).remove(entryId); ref.invalidateSelf(); } }