import 'package:chopper/chopper.dart'; import 'package:fladder/models/item_base_model.dart'; import 'package:fladder/providers/service_provider.dart'; import 'package:fladder/providers/sync_provider.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart'; import 'package:fladder/models/items/episode_model.dart'; import 'package:fladder/models/items/season_model.dart'; import 'package:fladder/models/items/series_model.dart'; import 'package:fladder/providers/api_provider.dart'; import 'package:fladder/providers/related_provider.dart'; final seriesDetailsProvider = StateNotifierProvider.autoDispose.family((ref, id) { return SeriesDetailViewNotifier(ref); }); class SeriesDetailViewNotifier extends StateNotifier { SeriesDetailViewNotifier(this.ref) : super(null); final Ref ref; late final JellyService api = ref.read(jellyApiProvider); Future fetchDetails(ItemBaseModel seriesModel) async { try { if (seriesModel is SeriesModel) { state = state ?? seriesModel; } SeriesModel? newState; final response = await api.usersUserIdItemsItemIdGet(itemId: seriesModel.id); if (response.body == null) return null; newState = response.bodyOrThrow as SeriesModel; final seasons = await api.showsSeriesIdSeasonsGet(seriesId: seriesModel.id); newState = newState.copyWith(seasons: SeasonModel.seasonsFromDto(seasons.body?.items, ref)); final episodes = await api.showsSeriesIdEpisodesGet(seriesId: seriesModel.id, fields: [ ItemFields.mediastreams, ItemFields.mediasources, ItemFields.overview, ]); newState = newState.copyWith( availableEpisodes: EpisodeModel.episodesFromDto( episodes.body?.items, ref, ), ); final related = await ref.read(relatedUtilityProvider).relatedContent(seriesModel.id); state = newState.copyWith(related: related.body); return response; } catch (e) { _tryToCreateOfflineState(seriesModel); return null; } } Future _tryToCreateOfflineState(ItemBaseModel series) async { final syncNotifier = ref.read(syncProvider.notifier); final syncedItem = syncNotifier.getSyncedItem(series); if (syncedItem == null) return; final seriesModel = syncedItem.createItemModel(ref) as SeriesModel; final allChildren = syncedItem .getNestedChildren(ref) .map( (e) => e.createItemModel(ref), ) .nonNulls .toList(); state = seriesModel.copyWith( availableEpisodes: allChildren.whereType().toList(), seasons: allChildren.whereType().toList(), ); return; } void updateEpisodeInfo(EpisodeModel episode) { final index = state?.availableEpisodes?.indexOf(episode); if (index != null) { state = state?.copyWith( availableEpisodes: state?.availableEpisodes ?..remove(episode) ..insert(index, episode), ); } } }