mirror of
https://github.com/K3vinb5/Unyo.git
synced 2026-06-13 05:49:42 +00:00
rewrite: Added a factory pattern for metadata services
This commit is contained in:
@@ -8,12 +8,12 @@ import 'package:unyo/application/cubits/effect_mixin.dart';
|
||||
import 'package:unyo/application/effects/app_effects.dart';
|
||||
import 'package:unyo/application/states/anime_advanced_search_state.dart';
|
||||
import 'package:unyo/core/di/locator.dart';
|
||||
import 'package:unyo/core/enums/service.dart';
|
||||
|
||||
import 'package:unyo/core/notification/anime_genres_notifier.dart';
|
||||
import 'package:unyo/core/notification/anime_notifier.dart';
|
||||
import 'package:unyo/core/notification/media_list_notifier.dart';
|
||||
import 'package:unyo/core/notification/user_notifier.dart';
|
||||
import 'package:unyo/data/repositories/anime_repository_anilist.dart';
|
||||
import 'package:unyo/domain/repositories/anime_repository.dart';
|
||||
import 'package:unyo/domain/entities/media/anime.dart';
|
||||
import 'package:unyo/domain/entities/list/media_list.dart';
|
||||
import 'package:unyo/domain/entities/user/user.dart';
|
||||
@@ -31,14 +31,14 @@ class AnimeAdvancedSearchCubit extends Cubit<AnimeAdvancedSearchState>
|
||||
late final StreamSubscription<String> _selectedAnimeAdvancedSearchGenresFiltersSubscription;
|
||||
|
||||
// Repositories
|
||||
final AnimeRepositoryAnilist _animeRepositoryAnilist;
|
||||
final AnimeRepository _animeRepository;
|
||||
|
||||
AnimeAdvancedSearchCubit(
|
||||
this._loggedUserNotifier,
|
||||
this._selectedMediaListNotifier,
|
||||
this._selectedAnimeNotifier,
|
||||
this._selectedAnimeAdvancedSearchGenresFilters,
|
||||
this._animeRepositoryAnilist,
|
||||
this._animeRepository,
|
||||
) : super(AnimeAdvancedSearchState(loggedUser: UserModel.empty())) {
|
||||
_init();
|
||||
}
|
||||
@@ -173,29 +173,21 @@ class AnimeAdvancedSearchCubit extends Cubit<AnimeAdvancedSearchState>
|
||||
|
||||
Future<void> _getLoggedUserServiceFilters(User loggedUser) async {
|
||||
try {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
final filters = await _animeRepositoryAnilist.getUserAnimeAdvancedSearchFilters();
|
||||
emit(
|
||||
state.copyWith(
|
||||
genresFilters: (filters['genres']?.$1 ?? false, filters['genres']?.$2 ?? []),
|
||||
seasonFilters: (filters['seasons']?.$1 ?? false, filters['seasons']?.$2 ?? []),
|
||||
formatFilters: (filters['formats']?.$1 ?? false, filters['formats']?.$2 ?? []),
|
||||
airingStatusFilters: (
|
||||
filters['airingStatuses']?.$1 ?? false,
|
||||
filters['airingStatuses']?.$2 ?? [],
|
||||
),
|
||||
yearFilters: (filters['years']?.$1 ?? false, filters['years']?.$2 ?? []),
|
||||
searchSortOptions: (filters['sortOptions']?.$1 ?? false, filters['sortOptions']?.$2 ?? []),
|
||||
searchSortOrder: (filters['sortOrders']?.$1 ?? false, filters['sortOrders']?.$2 ?? []),
|
||||
),
|
||||
);
|
||||
break;
|
||||
case Service.mal:
|
||||
case Service.shikimori:
|
||||
case Service.simkl:
|
||||
case Service.kitsu:
|
||||
}
|
||||
final filters = await _animeRepository.getUserAnimeAdvancedSearchFilters();
|
||||
emit(
|
||||
state.copyWith(
|
||||
genresFilters: (filters['genres']?.$1 ?? false, filters['genres']?.$2 ?? []),
|
||||
seasonFilters: (filters['seasons']?.$1 ?? false, filters['seasons']?.$2 ?? []),
|
||||
formatFilters: (filters['formats']?.$1 ?? false, filters['formats']?.$2 ?? []),
|
||||
airingStatusFilters: (
|
||||
filters['airingStatuses']?.$1 ?? false,
|
||||
filters['airingStatuses']?.$2 ?? [],
|
||||
),
|
||||
yearFilters: (filters['years']?.$1 ?? false, filters['years']?.$2 ?? []),
|
||||
searchSortOptions: (filters['sortOptions']?.$1 ?? false, filters['sortOptions']?.$2 ?? []),
|
||||
searchSortOrder: (filters['sortOrders']?.$1 ?? false, filters['sortOrders']?.$2 ?? []),
|
||||
),
|
||||
);
|
||||
} catch (e, stackTrace) {
|
||||
_logger.e("Error getting logged user service filters $e", stackTrace: stackTrace);
|
||||
handleError("Error getting logged user service filters", stackTrace: stackTrace);
|
||||
@@ -203,24 +195,17 @@ class AnimeAdvancedSearchCubit extends Cubit<AnimeAdvancedSearchState>
|
||||
}
|
||||
|
||||
Future<void> _performAnimeAdvancedSearch() async {
|
||||
switch (state.loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
List<Anime> searchResults = await _animeRepositoryAnilist.performAnimeAdvancedSearch(
|
||||
state.searchQuery,
|
||||
state.selectedGenres,
|
||||
state.selectedSeason,
|
||||
state.selectedFormat,
|
||||
int.tryParse(state.selectedYear ?? ''),
|
||||
state.selectedAiringStatus,
|
||||
"${state.selectedSearchSortOption.toUpperCase().replaceAll(" ", "_")}_${state.selectedSearchOrder.toUpperCase()}",
|
||||
1,
|
||||
state.loggedUser
|
||||
);
|
||||
emit(state.copyWith(searchResults: searchResults));
|
||||
case Service.mal:
|
||||
case Service.shikimori:
|
||||
case Service.simkl:
|
||||
case Service.kitsu:
|
||||
}
|
||||
List<Anime> searchResults = await _animeRepository.performAnimeAdvancedSearch(
|
||||
state.searchQuery,
|
||||
state.selectedGenres,
|
||||
state.selectedSeason,
|
||||
state.selectedFormat,
|
||||
int.tryParse(state.selectedYear ?? ''),
|
||||
state.selectedAiringStatus,
|
||||
"${state.selectedSearchSortOption.toUpperCase().replaceAll(" ", "_")}_${state.selectedSearchOrder.toUpperCase()}",
|
||||
1,
|
||||
state.loggedUser
|
||||
);
|
||||
emit(state.copyWith(searchResults: searchResults));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,14 +9,14 @@ import 'package:unyo/application/cubits/effect_mixin.dart';
|
||||
import 'package:unyo/application/effects/app_effects.dart';
|
||||
import 'package:unyo/application/states/anime_state.dart';
|
||||
import 'package:unyo/core/di/locator.dart';
|
||||
import 'package:unyo/core/enums/service.dart';
|
||||
|
||||
import 'package:unyo/core/notification/anime_genres_notifier.dart';
|
||||
import 'package:unyo/core/notification/anime_notifier.dart';
|
||||
import 'package:unyo/core/notification/media_list_notifier.dart';
|
||||
import 'package:unyo/core/notification/reload/reload_type.dart';
|
||||
import 'package:unyo/core/notification/user_notifier.dart';
|
||||
import 'package:unyo/core/services/api/http/http_exception.dart';
|
||||
import 'package:unyo/data/repositories/anime_repository_anilist.dart';
|
||||
import 'package:unyo/domain/repositories/anime_repository.dart';
|
||||
import 'package:unyo/domain/entities/media/anime.dart';
|
||||
import 'package:unyo/domain/entities/list/media_list.dart';
|
||||
import 'package:unyo/domain/entities/user/user.dart';
|
||||
@@ -24,7 +24,7 @@ import 'package:unyo/domain/entities/user/user.dart';
|
||||
import '../../core/notification/reload/reload_notifier.dart';
|
||||
|
||||
class AnimeCubit extends Cubit<AnimeState> with EffectMixin<AnimeState> {
|
||||
final AnimeRepositoryAnilist _animeRepositoryAnilist;
|
||||
final AnimeRepository _animeRepository;
|
||||
final UserNotifier _loggedUserNotifier;
|
||||
final AnimeNotifier _selectedAnimeNotifier;
|
||||
final AnimeGenresNotifier _selectedAnimeAdvancedSearchGenresFilters;
|
||||
@@ -35,7 +35,7 @@ class AnimeCubit extends Cubit<AnimeState> with EffectMixin<AnimeState> {
|
||||
final Logger _logger = sl<Logger>();
|
||||
|
||||
AnimeCubit(
|
||||
this._animeRepositoryAnilist,
|
||||
this._animeRepository,
|
||||
this._loggedUserNotifier,
|
||||
this._selectedAnimeNotifier,
|
||||
this._selectedAnimeAdvancedSearchGenresFilters,
|
||||
@@ -123,17 +123,10 @@ class AnimeCubit extends Cubit<AnimeState> with EffectMixin<AnimeState> {
|
||||
|
||||
Future<void> _fetchRecentlyReleased(int page, User loggedUser, {bool ignoreCache = false}) async {
|
||||
try {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching Anilist recently released anime");
|
||||
(bool, List<Anime>) recentlyReleased = await _animeRepositoryAnilist
|
||||
.getRecentlyReleasedAnimes(page, loggedUser, ignoreCache: ignoreCache);
|
||||
emit(state.copyWith(recentlyReleased: recentlyReleased));
|
||||
case Service.mal:
|
||||
case Service.kitsu:
|
||||
case Service.shikimori:
|
||||
case Service.simkl:
|
||||
}
|
||||
_logger.i("Fetching recently released anime");
|
||||
(bool, List<Anime>) recentlyReleased = await _animeRepository
|
||||
.getRecentlyReleasedAnimes(page, loggedUser, ignoreCache: ignoreCache);
|
||||
emit(state.copyWith(recentlyReleased: recentlyReleased));
|
||||
} on HttpServerException catch (e, stackTrace) {
|
||||
handleError(
|
||||
"Failed to fetch recently released anime:",
|
||||
@@ -150,27 +143,20 @@ class AnimeCubit extends Cubit<AnimeState> with EffectMixin<AnimeState> {
|
||||
|
||||
Future<void> _fetchTrending(int page, User loggedUser, {bool ignoreCache = false}) async {
|
||||
try {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching Anilist trending anime");
|
||||
(bool, List<Anime>) trending = await _animeRepositoryAnilist
|
||||
.getTrendingAnimes(page, loggedUser, ignoreCache: ignoreCache);
|
||||
emit(state.copyWith(trending: trending));
|
||||
if (page == 1) {
|
||||
List<Anime> banners = trending.$2.where((anime) => anime.bannerImage != "").toList();
|
||||
emit(
|
||||
state.copyWith(
|
||||
banners: banners.sublist(
|
||||
0,
|
||||
banners.length > 20 ? 20 : banners.length,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
case Service.mal:
|
||||
case Service.kitsu:
|
||||
case Service.shikimori:
|
||||
case Service.simkl:
|
||||
_logger.i("Fetching trending anime");
|
||||
(bool, List<Anime>) trending = await _animeRepository
|
||||
.getTrendingAnimes(page, loggedUser, ignoreCache: ignoreCache);
|
||||
emit(state.copyWith(trending: trending));
|
||||
if (page == 1) {
|
||||
List<Anime> banners = trending.$2.where((anime) => anime.bannerImage != "").toList();
|
||||
emit(
|
||||
state.copyWith(
|
||||
banners: banners.sublist(
|
||||
0,
|
||||
banners.length > 20 ? 20 : banners.length,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
} on HttpServerException catch (e, stackTrace) {
|
||||
handleError(
|
||||
@@ -185,17 +171,10 @@ class AnimeCubit extends Cubit<AnimeState> with EffectMixin<AnimeState> {
|
||||
|
||||
Future<void> _fetchPopular(int page, User loggedUser, {bool ignoreCache = false}) async {
|
||||
try {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching Anilist popular anime");
|
||||
(bool, List<Anime>) popular = await _animeRepositoryAnilist
|
||||
.getPopularAnimes(page, loggedUser, ignoreCache: ignoreCache);
|
||||
emit(state.copyWith(popular: popular));
|
||||
case Service.mal:
|
||||
case Service.kitsu:
|
||||
case Service.shikimori:
|
||||
case Service.simkl:
|
||||
}
|
||||
_logger.i("Fetching popular anime");
|
||||
(bool, List<Anime>) popular = await _animeRepository
|
||||
.getPopularAnimes(page, loggedUser, ignoreCache: ignoreCache);
|
||||
emit(state.copyWith(popular: popular));
|
||||
} on HttpServerException catch (e, stackTrace) {
|
||||
handleError(
|
||||
"Failed to fetch popular anime:",
|
||||
@@ -209,17 +188,10 @@ class AnimeCubit extends Cubit<AnimeState> with EffectMixin<AnimeState> {
|
||||
|
||||
Future<void> _fetchRecentlyCompleted(int page, User loggedUser, {bool ignoreCache = false}) async {
|
||||
try {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching Anilist recently completed anime");
|
||||
(bool, List<Anime>) recentlyCompleted = await _animeRepositoryAnilist
|
||||
.getRecentlyCompletedAnimes(page, loggedUser, ignoreCache: ignoreCache);
|
||||
emit(state.copyWith(recentlyCompleted: recentlyCompleted));
|
||||
case Service.mal:
|
||||
case Service.kitsu:
|
||||
case Service.shikimori:
|
||||
case Service.simkl:
|
||||
}
|
||||
_logger.i("Fetching recently completed anime");
|
||||
(bool, List<Anime>) recentlyCompleted = await _animeRepository
|
||||
.getRecentlyCompletedAnimes(page, loggedUser, ignoreCache: ignoreCache);
|
||||
emit(state.copyWith(recentlyCompleted: recentlyCompleted));
|
||||
} on HttpServerException catch (e, stackTrace) {
|
||||
handleError(
|
||||
"Failed to fetch recently completed anime:",
|
||||
@@ -236,17 +208,10 @@ class AnimeCubit extends Cubit<AnimeState> with EffectMixin<AnimeState> {
|
||||
|
||||
Future<void> _fetchUpcoming(int page, User loggedUser, {bool ignoreCache = false}) async {
|
||||
try {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching Anilist upcoming anime");
|
||||
(bool, List<Anime>) upcoming = await _animeRepositoryAnilist
|
||||
.getUpcomingAnimes(page, loggedUser, ignoreCache: ignoreCache);
|
||||
emit(state.copyWith(upcoming: upcoming));
|
||||
case Service.mal:
|
||||
case Service.kitsu:
|
||||
case Service.shikimori:
|
||||
case Service.simkl:
|
||||
}
|
||||
_logger.i("Fetching upcoming anime");
|
||||
(bool, List<Anime>) upcoming = await _animeRepository
|
||||
.getUpcomingAnimes(page, loggedUser, ignoreCache: ignoreCache);
|
||||
emit(state.copyWith(upcoming: upcoming));
|
||||
} on HttpServerException catch (e, stackTrace) {
|
||||
handleError(
|
||||
"Failed to fetch upcoming anime:",
|
||||
|
||||
@@ -30,7 +30,7 @@ import 'package:unyo/core/notification/video_info_notifier.dart';
|
||||
import 'package:unyo/core/services/api/http/http_exception.dart';
|
||||
import 'package:unyo/data/models/anilist/anilist_user_model.dart';
|
||||
import 'package:unyo/data/models/local/local_user_model.dart';
|
||||
import 'package:unyo/data/repositories/anime_repository_anilist.dart';
|
||||
import 'package:unyo/domain/repositories/anime_repository.dart';
|
||||
import 'package:unyo/data/repositories/episode_repository_anizip.dart';
|
||||
import 'package:unyo/data/repositories/extension_repository_aniyomi.dart';
|
||||
import 'package:unyo/data/repositories/repositories.dart';
|
||||
@@ -49,7 +49,7 @@ import 'package:unyo/presentation/drawers/anime_server_selection_drawer.dart';
|
||||
|
||||
class AnimeDetailsCubit extends Cubit<AnimeDetailsState> with EffectMixin<AnimeDetailsState> {
|
||||
// Repositories
|
||||
final AnimeRepositoryAnilist _animeRepositoryAnilist;
|
||||
final AnimeRepository _animeRepository;
|
||||
final EpisodeRepositoryAnizip _episodeRepositoryAnizip;
|
||||
final ExtensionRepositoryAniyomi _extensionRepositoryAniyomi;
|
||||
final UserRepositoryAnilist _userRepositoryAnilist;
|
||||
@@ -74,7 +74,7 @@ class AnimeDetailsCubit extends Cubit<AnimeDetailsState> with EffectMixin<AnimeD
|
||||
final Logger _logger = sl<Logger>();
|
||||
|
||||
AnimeDetailsCubit(
|
||||
this._animeRepositoryAnilist,
|
||||
this._animeRepository,
|
||||
this._episodeRepositoryAnizip,
|
||||
this._loggedUserNotifier,
|
||||
this._selectedAnimeNotifier,
|
||||
@@ -278,26 +278,15 @@ class AnimeDetailsCubit extends Cubit<AnimeDetailsState> with EffectMixin<AnimeD
|
||||
MediaListEntry desiredMediaListEntry = state.newMediaListEntry;
|
||||
MediaListEntry beforeUpdateMediaListEntry = state.mediaListEntry;
|
||||
try {
|
||||
switch (state.loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Updating Media List Entry to $desiredMediaListEntry on Anilist");
|
||||
await _animeRepositoryAnilist.updateMediaListEntry(
|
||||
desiredMediaListEntry,
|
||||
state.selectedAnime,
|
||||
state.loggedUser,
|
||||
);
|
||||
_reloadNotifier.emitReload(ReloadType.animeMediaListEntryUpdated);
|
||||
if (desiredMediaListEntry.status != beforeUpdateMediaListEntry.status) {
|
||||
_reloadNotifier.emitReload(ReloadType.homeMediaListEntryUpdated);
|
||||
}
|
||||
case Service.mal:
|
||||
_logger.i("Updating Media List Entry to $desiredMediaListEntry on MyAnimeList");
|
||||
case Service.shikimori:
|
||||
_logger.i("Updating Media List Entry to $desiredMediaListEntry on Shikimori");
|
||||
case Service.kitsu:
|
||||
_logger.i("Updating Media List Entry to $desiredMediaListEntry on Kitsu");
|
||||
case Service.simkl:
|
||||
_logger.i("Updating Media List Entry to $desiredMediaListEntry on Simkl");
|
||||
_logger.i("Updating Media List Entry to $desiredMediaListEntry");
|
||||
await _animeRepository.updateMediaListEntry(
|
||||
desiredMediaListEntry,
|
||||
state.selectedAnime,
|
||||
state.loggedUser,
|
||||
);
|
||||
_reloadNotifier.emitReload(ReloadType.animeMediaListEntryUpdated);
|
||||
if (desiredMediaListEntry.status != beforeUpdateMediaListEntry.status) {
|
||||
_reloadNotifier.emitReload(ReloadType.homeMediaListEntryUpdated);
|
||||
}
|
||||
} on HttpServerException catch (e, stackTrace) {
|
||||
handleError("Error updating Anime Entry:", responseBody: e.message, stackTrace: stackTrace);
|
||||
@@ -430,25 +419,14 @@ class AnimeDetailsCubit extends Cubit<AnimeDetailsState> with EffectMixin<AnimeD
|
||||
|
||||
Future<void> _getUserMediaListEntry(User loggedUser, Anime selectedAnime, {bool ignoreCache = false}) async {
|
||||
try {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching User Media List Entry from AniList for ${state.selectedAnime.title.userPreferred}");
|
||||
MediaListEntry mediaListEntry = await _animeRepositoryAnilist.getMediaListEntry(
|
||||
selectedAnime,
|
||||
loggedUser,
|
||||
ignoreCache: ignoreCache,
|
||||
);
|
||||
emit(state.copyWith(mediaListEntry: mediaListEntry, newMediaListEntry: mediaListEntry));
|
||||
_mediaListEntryNotifier.updateSelectedMediaListEntry(mediaListEntry);
|
||||
case Service.mal:
|
||||
_logger.i("Fetching User Media List Entry from MyAnimeList for ${state.selectedAnime.title.userPreferred}");
|
||||
case Service.shikimori:
|
||||
_logger.i("Fetching User Media List Entry from Shikimori for ${state.selectedAnime.title.userPreferred}");
|
||||
case Service.kitsu:
|
||||
_logger.i("Fetching User Media List Entry from Kitsu for ${state.selectedAnime.title.userPreferred}");
|
||||
case Service.simkl:
|
||||
_logger.i("Fetching User Media List Entry from Simkl for ${state.selectedAnime.title.userPreferred}");
|
||||
}
|
||||
_logger.i("Fetching User Media List Entry for ${state.selectedAnime.title.userPreferred}");
|
||||
MediaListEntry mediaListEntry = await _animeRepository.getMediaListEntry(
|
||||
selectedAnime,
|
||||
loggedUser,
|
||||
ignoreCache: ignoreCache,
|
||||
);
|
||||
emit(state.copyWith(mediaListEntry: mediaListEntry, newMediaListEntry: mediaListEntry));
|
||||
_mediaListEntryNotifier.updateSelectedMediaListEntry(mediaListEntry);
|
||||
} on HttpServerException catch (e, stackTrace) {
|
||||
handleError("Error fetching User Media List entry:", responseBody: e.message, stackTrace: stackTrace);
|
||||
} catch (e, stackTrace) {
|
||||
@@ -458,41 +436,30 @@ class AnimeDetailsCubit extends Cubit<AnimeDetailsState> with EffectMixin<AnimeD
|
||||
|
||||
Future<void> _getAnimeDetails(User loggedUser, Anime selectedAnime) async {
|
||||
try {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching Anime Details from AniList for ${state.selectedAnime.title.userPreferred}");
|
||||
(bool, AnimeDetails) animeDetails = await _animeRepositoryAnilist.getAnimeDetails(
|
||||
selectedAnime,
|
||||
loggedUser,
|
||||
);
|
||||
emit(
|
||||
state.copyWith(
|
||||
characters: (animeDetails.$2.characters.isNotEmpty, animeDetails.$2.characters),
|
||||
mediaListEntry: animeDetails.$2.mediaListEntry,
|
||||
newMediaListEntry: animeDetails.$2.mediaListEntry,
|
||||
recommendations: (
|
||||
animeDetails.$2.recommendedAnimes.isNotEmpty,
|
||||
animeDetails.$2.recommendedAnimes,
|
||||
),
|
||||
),
|
||||
);
|
||||
if (animeDetails.$2.recommendedAnimes.isEmpty) {
|
||||
(bool, List<Anime>) trendingAnimes = await _animeRepositoryAnilist.getTrendingAnimes(
|
||||
1,
|
||||
loggedUser,
|
||||
);
|
||||
emit(state.copyWith(recommendations: (trendingAnimes.$1, trendingAnimes.$2.shuffled(Random()))));
|
||||
}
|
||||
_getAlternativeImage(loggedUser, selectedAnime);
|
||||
case Service.mal:
|
||||
_logger.i("Fetching Anime Details from MyAnimeList for ${state.selectedAnime.title.userPreferred}");
|
||||
case Service.shikimori:
|
||||
_logger.i("Fetching Anime Details from Shikimori for ${state.selectedAnime.title.userPreferred}");
|
||||
case Service.kitsu:
|
||||
_logger.i("Fetching Anime Details from Kitsu for ${state.selectedAnime.title.userPreferred}");
|
||||
case Service.simkl:
|
||||
_logger.i("Fetching Anime Details from Simkl for ${state.selectedAnime.title.userPreferred}");
|
||||
_logger.i("Fetching Anime Details for ${state.selectedAnime.title.userPreferred}");
|
||||
(bool, AnimeDetails) animeDetails = await _animeRepository.getAnimeDetails(
|
||||
selectedAnime,
|
||||
loggedUser,
|
||||
);
|
||||
emit(
|
||||
state.copyWith(
|
||||
characters: (animeDetails.$2.characters.isNotEmpty, animeDetails.$2.characters),
|
||||
mediaListEntry: animeDetails.$2.mediaListEntry,
|
||||
newMediaListEntry: animeDetails.$2.mediaListEntry,
|
||||
recommendations: (
|
||||
animeDetails.$2.recommendedAnimes.isNotEmpty,
|
||||
animeDetails.$2.recommendedAnimes,
|
||||
),
|
||||
),
|
||||
);
|
||||
if (animeDetails.$2.recommendedAnimes.isEmpty) {
|
||||
(bool, List<Anime>) trendingAnimes = await _animeRepository.getTrendingAnimes(
|
||||
1,
|
||||
loggedUser,
|
||||
);
|
||||
emit(state.copyWith(recommendations: (trendingAnimes.$1, trendingAnimes.$2.shuffled(Random()))));
|
||||
}
|
||||
_getAlternativeImage(loggedUser, selectedAnime);
|
||||
} on HttpServerException catch (e, stackTrace) {
|
||||
handleError("Error fetching Anime details:", responseBody: e.message, stackTrace: stackTrace);
|
||||
} catch (e, stackTrace) {
|
||||
@@ -750,20 +717,9 @@ class AnimeDetailsCubit extends Cubit<AnimeDetailsState> with EffectMixin<AnimeD
|
||||
|
||||
Future<void> _getAnimeBanners(User loggedUser) async {
|
||||
try {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching Anime Banners from AniList for ${state.selectedAnime.title.userPreferred}");
|
||||
List<String> banners = await _animeRepositoryAnilist.getMediaCoverImages(loggedUser);
|
||||
emit(state.copyWith(banners: banners));
|
||||
case Service.mal:
|
||||
_logger.i("Fetching Anime Banners from MyAnimeList for ${state.selectedAnime.title.userPreferred}");
|
||||
case Service.shikimori:
|
||||
_logger.i("Fetching Anime Banners from Shikimori for ${state.selectedAnime.title.userPreferred}");
|
||||
case Service.kitsu:
|
||||
_logger.i("Fetching Anime Banners from Kitsu for ${state.selectedAnime.title.userPreferred}");
|
||||
case Service.simkl:
|
||||
_logger.i("Fetching Anime Banners from Simkl for ${state.selectedAnime.title.userPreferred}");
|
||||
}
|
||||
_logger.i("Fetching Anime Banners for ${state.selectedAnime.title.userPreferred}");
|
||||
List<String> banners = await _animeRepository.getMediaCoverImages(loggedUser);
|
||||
emit(state.copyWith(banners: banners));
|
||||
} on HttpServerException catch (e, stackTrace) {
|
||||
handleError("Error fetching Anime banners:", responseBody: e.message, stackTrace: stackTrace);
|
||||
} catch (e, stackTrace) {
|
||||
|
||||
@@ -10,24 +10,24 @@ import 'package:unyo/application/cubits/effect_mixin.dart';
|
||||
import 'package:unyo/application/effects/app_effects.dart';
|
||||
import 'package:unyo/application/states/calendar_state.dart';
|
||||
import 'package:unyo/core/di/locator.dart';
|
||||
import 'package:unyo/core/enums/service.dart';
|
||||
|
||||
import 'package:unyo/core/notification/anime_notifier.dart';
|
||||
import 'package:unyo/core/notification/media_list_notifier.dart';
|
||||
import 'package:unyo/core/notification/user_notifier.dart';
|
||||
import 'package:unyo/data/repositories/anime_repository_anilist.dart';
|
||||
import 'package:unyo/domain/repositories/anime_repository.dart';
|
||||
import 'package:unyo/domain/entities/media/anime.dart';
|
||||
import 'package:unyo/domain/entities/list/media_list.dart';
|
||||
import 'package:unyo/domain/entities/user/user.dart';
|
||||
|
||||
class CalendarCubit extends Cubit<CalendarState> with EffectMixin<CalendarState> {
|
||||
final Logger _logger = sl<Logger>();
|
||||
final AnimeRepositoryAnilist _animeRepositoryAnilist;
|
||||
final AnimeRepository _animeRepository;
|
||||
final UserNotifier _loggedUserNotifier;
|
||||
final AnimeNotifier _selectedAnimeNotifier;
|
||||
final MediaListNotifier _selectedMediaListNotifier;
|
||||
late StreamSubscription<User> _loggedUserSubscription;
|
||||
|
||||
CalendarCubit(this._animeRepositoryAnilist, this._loggedUserNotifier, this._selectedAnimeNotifier, this._selectedMediaListNotifier)
|
||||
CalendarCubit(this._animeRepository, this._loggedUserNotifier, this._selectedAnimeNotifier, this._selectedMediaListNotifier)
|
||||
: super(CalendarState(animeCalendarReleases: {}, loggedUser: UserModel.empty())) {
|
||||
_init();
|
||||
}
|
||||
@@ -70,20 +70,13 @@ class CalendarCubit extends Cubit<CalendarState> with EffectMixin<CalendarState>
|
||||
|
||||
Future<void> _getCalendarEvents(User loggedUser) async {
|
||||
try {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching Anilist calendar releases");
|
||||
Map<String, List<Anime>> animeCalendarReleases = await _animeRepositoryAnilist.getCalendarReleases(1, loggedUser);
|
||||
emit(
|
||||
state.copyWith(
|
||||
animeCalendarReleases: animeCalendarReleases,
|
||||
),
|
||||
);
|
||||
case Service.mal:
|
||||
case Service.shikimori:
|
||||
case Service.kitsu:
|
||||
case Service.simkl:
|
||||
}
|
||||
_logger.i("Fetching calendar releases");
|
||||
Map<String, List<Anime>> animeCalendarReleases = await _animeRepository.getCalendarReleases(1, loggedUser);
|
||||
emit(
|
||||
state.copyWith(
|
||||
animeCalendarReleases: animeCalendarReleases,
|
||||
),
|
||||
);
|
||||
} catch (e, stackTrace) {
|
||||
handleError("Error fetching user info: $e", stackTrace: stackTrace);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import 'package:unyo/application/cubits/effect_mixin.dart';
|
||||
import 'package:unyo/application/states/home_state.dart';
|
||||
import 'package:unyo/core/di/locator.dart';
|
||||
import 'package:unyo/core/enums/selected_menu_option.dart';
|
||||
import 'package:unyo/core/enums/service.dart';
|
||||
|
||||
import 'package:unyo/core/notification/anime_notifier.dart';
|
||||
import 'package:unyo/core/notification/manga_notifier.dart';
|
||||
import 'package:unyo/core/notification/media_list_notifier.dart';
|
||||
@@ -23,7 +23,7 @@ import 'package:unyo/core/notification/user_notifier.dart';
|
||||
import 'package:unyo/application/effects/app_effects.dart';
|
||||
import 'package:unyo/data/models/anilist/anilist_user_model.dart';
|
||||
import 'package:unyo/data/models/local/local_user_model.dart';
|
||||
import 'package:unyo/data/repositories/anime_repository_anilist.dart';
|
||||
import 'package:unyo/domain/repositories/anime_repository.dart';
|
||||
import 'package:unyo/data/repositories/repositories.dart';
|
||||
import 'package:unyo/domain/entities/media/anime.dart';
|
||||
import 'package:unyo/domain/entities/media/manga.dart';
|
||||
@@ -33,7 +33,7 @@ import 'package:unyo/domain/entities/user/user.dart';
|
||||
class HomeCubit extends Cubit<HomeState> with EffectMixin<HomeState> {
|
||||
// Repositories
|
||||
final UserRepositoryAnilist _userRepositoryAnilist;
|
||||
final AnimeRepositoryAnilist _animeRepositoryAnilist;
|
||||
final AnimeRepository _animeRepository;
|
||||
// Notifiers / Subscriptions
|
||||
final UserNotifier _loggedUserNotifier;
|
||||
final MenuBarNotifier _menuBarNotifier;
|
||||
@@ -51,7 +51,7 @@ class HomeCubit extends Cubit<HomeState> with EffectMixin<HomeState> {
|
||||
this._selectedMangaNotifier,
|
||||
this._selectedMediaListNotifier,
|
||||
this._userRepositoryAnilist,
|
||||
this._animeRepositoryAnilist,
|
||||
this._animeRepository,
|
||||
this._menuBarNotifier,
|
||||
this._reloadNotifier,
|
||||
) : super(
|
||||
@@ -162,20 +162,9 @@ class HomeCubit extends Cubit<HomeState> with EffectMixin<HomeState> {
|
||||
|
||||
Future<void> _getMediaCoverImages(User loggedUser, {bool ignoreCache = false}) async {
|
||||
try {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching Media Cover Images from AniList");
|
||||
List<String> mediaCoverImages = await _animeRepositoryAnilist.getMediaCoverImages(loggedUser, ignoreCache: ignoreCache);
|
||||
emit(state.copyWith(mediaCoverImages: mediaCoverImages));
|
||||
case Service.mal:
|
||||
_logger.i("Fetching Media Cover Images from MyAnimeList");
|
||||
case Service.shikimori:
|
||||
_logger.i("Fetching Media Cover Images from Shikimori");
|
||||
case Service.kitsu:
|
||||
_logger.i("Fetching Media Cover Images from Kitsu");
|
||||
case Service.simkl:
|
||||
_logger.i("Fetching Media Cover Images from Simkl");
|
||||
}
|
||||
_logger.i("Fetching Media Cover Images");
|
||||
List<String> mediaCoverImages = await _animeRepository.getMediaCoverImages(loggedUser, ignoreCache: ignoreCache);
|
||||
emit(state.copyWith(mediaCoverImages: mediaCoverImages));
|
||||
} catch (e, stackTrace) {
|
||||
handleError("Error fetching media cover images: $e", stackTrace: stackTrace);
|
||||
}
|
||||
|
||||
@@ -8,12 +8,12 @@ import 'package:unyo/application/cubits/effect_mixin.dart';
|
||||
import 'package:unyo/application/effects/app_effects.dart';
|
||||
import 'package:unyo/application/states/manga_advanced_search_state.dart';
|
||||
import 'package:unyo/core/di/locator.dart';
|
||||
import 'package:unyo/core/enums/service.dart';
|
||||
|
||||
import 'package:unyo/core/notification/manga_genres_notifier.dart';
|
||||
import 'package:unyo/core/notification/manga_notifier.dart';
|
||||
import 'package:unyo/core/notification/media_list_notifier.dart';
|
||||
import 'package:unyo/core/notification/user_notifier.dart';
|
||||
import 'package:unyo/data/repositories/manga_repository_anilist.dart';
|
||||
import 'package:unyo/domain/repositories/manga_repository.dart';
|
||||
import 'package:unyo/domain/entities/media/manga.dart';
|
||||
import 'package:unyo/domain/entities/list/media_list.dart';
|
||||
import 'package:unyo/domain/entities/user/user.dart';
|
||||
@@ -31,14 +31,14 @@ class MangaAdvancedSearchCubit extends Cubit<MangaAdvancedSearchState>
|
||||
late final StreamSubscription<String> _selectedMangaAdvancedSearchGenresFiltersSubscription;
|
||||
|
||||
// Repositories
|
||||
final MangaRepositoryAnilist _mangaRepositoryAnilist;
|
||||
final MangaRepository _mangaRepository;
|
||||
|
||||
MangaAdvancedSearchCubit(
|
||||
this._loggedUserNotifier,
|
||||
this._selectedMediaListNotifier,
|
||||
this._selectedMangaNotifier,
|
||||
this._selectedMangaAdvancedSearchGenresFilters,
|
||||
this._mangaRepositoryAnilist,
|
||||
this._mangaRepository,
|
||||
) : super(MangaAdvancedSearchState(loggedUser: UserModel.empty())) {
|
||||
_init();
|
||||
}
|
||||
@@ -162,28 +162,20 @@ class MangaAdvancedSearchCubit extends Cubit<MangaAdvancedSearchState>
|
||||
|
||||
Future<void> _getLoggedUserServiceFilters(User loggedUser) async {
|
||||
try {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
final filters = await _mangaRepositoryAnilist.getUserMangaAdvancedSearchFilters();
|
||||
emit(
|
||||
state.copyWith(
|
||||
genresFilters: (filters['genres']?.$1 ?? false, filters['genres']?.$2 ?? []),
|
||||
formatFilters: (filters['formats']?.$1 ?? false, filters['formats']?.$2 ?? []),
|
||||
countryFilters: (filters['countries']?.$1 ?? false, filters['countries']?.$2 ?? []),
|
||||
airingStatusFilters: (
|
||||
filters['airingStatuses']?.$1 ?? false,
|
||||
filters['airingStatuses']?.$2 ?? [],
|
||||
),
|
||||
searchSortOptions: (filters['sortOptions']?.$1 ?? false, filters['sortOptions']?.$2 ?? []),
|
||||
searchSortOrder: (filters['sortOrders']?.$1 ?? false, filters['sortOrders']?.$2 ?? []),
|
||||
),
|
||||
);
|
||||
break;
|
||||
case Service.mal:
|
||||
case Service.shikimori:
|
||||
case Service.simkl:
|
||||
case Service.kitsu:
|
||||
}
|
||||
final filters = await _mangaRepository.getUserMangaAdvancedSearchFilters();
|
||||
emit(
|
||||
state.copyWith(
|
||||
genresFilters: (filters['genres']?.$1 ?? false, filters['genres']?.$2 ?? []),
|
||||
formatFilters: (filters['formats']?.$1 ?? false, filters['formats']?.$2 ?? []),
|
||||
countryFilters: (filters['countries']?.$1 ?? false, filters['countries']?.$2 ?? []),
|
||||
airingStatusFilters: (
|
||||
filters['airingStatuses']?.$1 ?? false,
|
||||
filters['airingStatuses']?.$2 ?? [],
|
||||
),
|
||||
searchSortOptions: (filters['sortOptions']?.$1 ?? false, filters['sortOptions']?.$2 ?? []),
|
||||
searchSortOrder: (filters['sortOrders']?.$1 ?? false, filters['sortOrders']?.$2 ?? []),
|
||||
),
|
||||
);
|
||||
} catch (e, stackTrace) {
|
||||
_logger.e("Error getting logged user service filters $e", stackTrace: stackTrace);
|
||||
handleError("Error getting logged user service filters", stackTrace: stackTrace);
|
||||
@@ -191,23 +183,16 @@ class MangaAdvancedSearchCubit extends Cubit<MangaAdvancedSearchState>
|
||||
}
|
||||
|
||||
Future<void> _performMangaAdvancedSearch() async {
|
||||
switch (state.loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
List<Manga> searchResults = await _mangaRepositoryAnilist.performMangaAdvancedSearch(
|
||||
state.searchQuery,
|
||||
state.selectedGenres,
|
||||
state.selectedFormat,
|
||||
state.selectedCountry,
|
||||
state.selectedAiringStatus,
|
||||
"${state.selectedSearchSortOption.toUpperCase().replaceAll(" ", "_")}_${state.selectedSearchOrder.toUpperCase()}",
|
||||
1,
|
||||
state.loggedUser
|
||||
);
|
||||
emit(state.copyWith(searchResults: searchResults));
|
||||
case Service.mal:
|
||||
case Service.shikimori:
|
||||
case Service.simkl:
|
||||
case Service.kitsu:
|
||||
}
|
||||
List<Manga> searchResults = await _mangaRepository.performMangaAdvancedSearch(
|
||||
state.searchQuery,
|
||||
state.selectedGenres,
|
||||
state.selectedFormat,
|
||||
state.selectedCountry,
|
||||
state.selectedAiringStatus,
|
||||
"${state.selectedSearchSortOption.toUpperCase().replaceAll(" ", "_")}_${state.selectedSearchOrder.toUpperCase()}",
|
||||
1,
|
||||
state.loggedUser
|
||||
);
|
||||
emit(state.copyWith(searchResults: searchResults));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,21 +6,21 @@ import 'package:unyo/application/effects/app_effects.dart';
|
||||
import 'package:unyo/application/states/manga_state.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:unyo/core/di/locator.dart';
|
||||
import 'package:unyo/core/enums/service.dart';
|
||||
|
||||
import 'package:unyo/core/notification/manga_genres_notifier.dart';
|
||||
import 'package:unyo/core/notification/manga_notifier.dart';
|
||||
import 'package:unyo/core/notification/media_list_notifier.dart';
|
||||
import 'package:unyo/core/notification/reload/reload_notifier.dart';
|
||||
import 'package:unyo/core/notification/reload/reload_type.dart';
|
||||
import 'package:unyo/core/notification/user_notifier.dart';
|
||||
import 'package:unyo/data/repositories/manga_repository_anilist.dart';
|
||||
import 'package:unyo/domain/repositories/manga_repository.dart';
|
||||
import 'package:unyo/domain/entities/media/manga.dart';
|
||||
import 'package:unyo/domain/entities/list/media_list.dart';
|
||||
import 'package:unyo/domain/entities/user/user.dart';
|
||||
import 'effect_mixin.dart';
|
||||
|
||||
class MangaCubit extends Cubit<MangaState> with EffectMixin<MangaState> {
|
||||
final MangaRepositoryAnilist _mangaRepositoryAnilist;
|
||||
final MangaRepository _mangaRepository;
|
||||
final UserNotifier _loggedUserNotifier;
|
||||
final MangaNotifier _selectedMangaNotifier;
|
||||
final MangaGenresNotifier _selectedMangaAdvancedSearchGenresFilters;
|
||||
@@ -31,7 +31,7 @@ class MangaCubit extends Cubit<MangaState> with EffectMixin<MangaState> {
|
||||
final Logger _logger = sl<Logger>();
|
||||
|
||||
MangaCubit(
|
||||
this._mangaRepositoryAnilist,
|
||||
this._mangaRepository,
|
||||
this._loggedUserNotifier,
|
||||
this._selectedMangaNotifier,
|
||||
this._selectedMangaAdvancedSearchGenresFilters,
|
||||
@@ -108,26 +108,19 @@ class MangaCubit extends Cubit<MangaState> with EffectMixin<MangaState> {
|
||||
|
||||
Future<void> _fetchTrending(int page, User loggedUser, {bool ignoreCache = false}) async {
|
||||
try {
|
||||
switch (state.loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching Anilist trending manga");
|
||||
(bool, List<Manga>) trending = await _mangaRepositoryAnilist
|
||||
.getTrendingMangas(page, loggedUser, ignoreCache: ignoreCache);
|
||||
emit(state.copyWith(trending: trending));
|
||||
if (page == 1) {
|
||||
emit(
|
||||
state.copyWith(
|
||||
banners:
|
||||
trending.$2
|
||||
.where((manga) => manga.bannerImage != "")
|
||||
.toList(),
|
||||
),
|
||||
);
|
||||
}
|
||||
case Service.mal:
|
||||
case Service.kitsu:
|
||||
case Service.shikimori:
|
||||
case Service.simkl:
|
||||
_logger.i("Fetching trending manga");
|
||||
(bool, List<Manga>) trending = await _mangaRepository
|
||||
.getTrendingMangas(page, loggedUser, ignoreCache: ignoreCache);
|
||||
emit(state.copyWith(trending: trending));
|
||||
if (page == 1) {
|
||||
emit(
|
||||
state.copyWith(
|
||||
banners:
|
||||
trending.$2
|
||||
.where((manga) => manga.bannerImage != "")
|
||||
.toList(),
|
||||
),
|
||||
);
|
||||
}
|
||||
} catch (e, stackTrace) {
|
||||
handleError("Failed to fetch trending manga $e", stackTrace: stackTrace);
|
||||
@@ -136,17 +129,10 @@ class MangaCubit extends Cubit<MangaState> with EffectMixin<MangaState> {
|
||||
|
||||
Future<void> _fetchPopular(int page, User loggedUser, {bool ignoreCache = false}) async {
|
||||
try {
|
||||
switch (state.loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching Anilist popular manga");
|
||||
(bool, List<Manga>) popular = await _mangaRepositoryAnilist
|
||||
.getPopularMangas(page, loggedUser, ignoreCache: ignoreCache);
|
||||
emit(state.copyWith(popular: popular));
|
||||
case Service.mal:
|
||||
case Service.kitsu:
|
||||
case Service.shikimori:
|
||||
case Service.simkl:
|
||||
}
|
||||
_logger.i("Fetching popular manga");
|
||||
(bool, List<Manga>) popular = await _mangaRepository
|
||||
.getPopularMangas(page, loggedUser, ignoreCache: ignoreCache);
|
||||
emit(state.copyWith(popular: popular));
|
||||
} catch (e, stackTrace) {
|
||||
handleError("Failed to fetch popular manga $e", stackTrace: stackTrace);
|
||||
}
|
||||
@@ -154,17 +140,10 @@ class MangaCubit extends Cubit<MangaState> with EffectMixin<MangaState> {
|
||||
|
||||
Future<void> _fetchRecentlyCompleted(int page, User loggedUser, {bool ignoreCache = false}) async {
|
||||
try {
|
||||
switch (state.loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching Anilist recently completed manga");
|
||||
(bool, List<Manga>) recentlyCompleted = await _mangaRepositoryAnilist
|
||||
.getRecentlyCompletedMangas(page, loggedUser, ignoreCache: ignoreCache);
|
||||
emit(state.copyWith(recentlyCompleted: recentlyCompleted));
|
||||
case Service.mal:
|
||||
case Service.kitsu:
|
||||
case Service.shikimori:
|
||||
case Service.simkl:
|
||||
}
|
||||
_logger.i("Fetching recently completed manga");
|
||||
(bool, List<Manga>) recentlyCompleted = await _mangaRepository
|
||||
.getRecentlyCompletedMangas(page, loggedUser, ignoreCache: ignoreCache);
|
||||
emit(state.copyWith(recentlyCompleted: recentlyCompleted));
|
||||
} catch (e, stackTrace) {
|
||||
handleError(
|
||||
"Failed to fetch recently completed manga $e",
|
||||
@@ -175,17 +154,10 @@ class MangaCubit extends Cubit<MangaState> with EffectMixin<MangaState> {
|
||||
|
||||
Future<void> _fetchUpcoming(int page, User loggedUser, {bool ignoreCache = false}) async {
|
||||
try {
|
||||
switch (state.loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching Anilist upcoming manga");
|
||||
(bool, List<Manga>) upcoming = await _mangaRepositoryAnilist
|
||||
.getUpcomingMangas(page, loggedUser, ignoreCache: ignoreCache);
|
||||
emit(state.copyWith(upcoming: upcoming));
|
||||
case Service.mal:
|
||||
case Service.kitsu:
|
||||
case Service.shikimori:
|
||||
case Service.simkl:
|
||||
}
|
||||
_logger.i("Fetching upcoming manga");
|
||||
(bool, List<Manga>) upcoming = await _mangaRepository
|
||||
.getUpcomingMangas(page, loggedUser, ignoreCache: ignoreCache);
|
||||
emit(state.copyWith(upcoming: upcoming));
|
||||
} catch (e, stackTrace) {
|
||||
handleError("Failed to fetch upcoming manga $e", stackTrace: stackTrace);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import 'package:unyo/application/effects/app_effects.dart';
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:unyo/application/states/manga_details_state.dart';
|
||||
import 'package:unyo/core/di/locator.dart';
|
||||
import 'package:unyo/core/enums/service.dart';
|
||||
|
||||
import 'package:unyo/core/notification/manga_genres_notifier.dart';
|
||||
import 'package:unyo/core/notification/manga_notifier.dart';
|
||||
import 'package:unyo/core/notification/media_list_notifier.dart';
|
||||
@@ -20,7 +20,7 @@ import 'package:unyo/core/services/api/http/http_exception.dart';
|
||||
import 'package:unyo/data/models/anilist/anilist_user_model.dart';
|
||||
import 'package:unyo/data/models/local/local_user_model.dart';
|
||||
import 'package:unyo/data/repositories/extension_repository_aniyomi.dart';
|
||||
import 'package:unyo/data/repositories/manga_repository_anilist.dart';
|
||||
import 'package:unyo/domain/repositories/manga_repository.dart';
|
||||
import 'package:unyo/data/repositories/repositories.dart';
|
||||
import 'package:unyo/domain/entities/extension/extension.dart';
|
||||
import 'package:unyo/domain/entities/media/manga.dart';
|
||||
@@ -32,7 +32,7 @@ import 'package:unyo/domain/entities/user/user.dart';
|
||||
|
||||
class MangaDetailsCubit extends Cubit<MangaDetailsState> with EffectMixin<MangaDetailsState> {
|
||||
// Repositories
|
||||
final MangaRepositoryAnilist _mangaRepositoryAnilist;
|
||||
final MangaRepository _mangaRepository;
|
||||
final ExtensionRepositoryAniyomi _extensionRepositoryAniyomi;
|
||||
final UserRepositoryAnilist _userRepositoryAnilist;
|
||||
|
||||
@@ -49,7 +49,7 @@ class MangaDetailsCubit extends Cubit<MangaDetailsState> with EffectMixin<MangaD
|
||||
final Logger _logger = sl<Logger>();
|
||||
|
||||
MangaDetailsCubit(
|
||||
this._mangaRepositoryAnilist,
|
||||
this._mangaRepository,
|
||||
this._loggedUserNotifier,
|
||||
this._selectedMangaNotifier,
|
||||
this._selectedMangaAdvancedSearchGenresFilters,
|
||||
@@ -168,35 +168,24 @@ class MangaDetailsCubit extends Cubit<MangaDetailsState> with EffectMixin<MangaD
|
||||
|
||||
Future<void> _getMangaDetails(User loggedUser, Manga selectedManga) async {
|
||||
try {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching Manga Details from AniList for ${state.selectedManga.title.userPreferred}");
|
||||
(bool, MangaDetails) mangaDetails = await _mangaRepositoryAnilist.getMangaDetails(
|
||||
selectedManga,
|
||||
loggedUser,
|
||||
);
|
||||
emit(
|
||||
state.copyWith(
|
||||
mediaListEntry: mangaDetails.$2.mediaListEntry,
|
||||
characters: (mangaDetails.$2.characters.isNotEmpty, mangaDetails.$2.characters),
|
||||
recommendations: (
|
||||
mangaDetails.$2.recommendedMangas.isNotEmpty,
|
||||
mangaDetails.$2.recommendedMangas,
|
||||
),
|
||||
),
|
||||
);
|
||||
if (mangaDetails.$2.recommendedMangas.isEmpty) {
|
||||
(bool, List<Manga>) trendingMangas = await _mangaRepositoryAnilist.getTrendingMangas(1, loggedUser);
|
||||
emit(state.copyWith(recommendations: (trendingMangas.$1, trendingMangas.$2.shuffled(Random()))));
|
||||
}
|
||||
case Service.mal:
|
||||
_logger.i("Fetching Manga Details from MyMangaList for ${state.selectedManga.title.userPreferred}");
|
||||
case Service.shikimori:
|
||||
_logger.i("Fetching Manga Details from Shikimori for ${state.selectedManga.title.userPreferred}");
|
||||
case Service.kitsu:
|
||||
_logger.i("Fetching Manga Details from Kitsu for ${state.selectedManga.title.userPreferred}");
|
||||
case Service.simkl:
|
||||
_logger.i("Fetching Manga Details from Simkl for ${state.selectedManga.title.userPreferred}");
|
||||
_logger.i("Fetching Manga Details for ${state.selectedManga.title.userPreferred}");
|
||||
(bool, MangaDetails) mangaDetails = await _mangaRepository.getMangaDetails(
|
||||
selectedManga,
|
||||
loggedUser,
|
||||
);
|
||||
emit(
|
||||
state.copyWith(
|
||||
mediaListEntry: mangaDetails.$2.mediaListEntry,
|
||||
characters: (mangaDetails.$2.characters.isNotEmpty, mangaDetails.$2.characters),
|
||||
recommendations: (
|
||||
mangaDetails.$2.recommendedMangas.isNotEmpty,
|
||||
mangaDetails.$2.recommendedMangas,
|
||||
),
|
||||
),
|
||||
);
|
||||
if (mangaDetails.$2.recommendedMangas.isEmpty) {
|
||||
(bool, List<Manga>) trendingMangas = await _mangaRepository.getTrendingMangas(1, loggedUser);
|
||||
emit(state.copyWith(recommendations: (trendingMangas.$1, trendingMangas.$2.shuffled(Random()))));
|
||||
}
|
||||
} on HttpServerException catch (e, stackTrace) {
|
||||
handleError("Error fetching Manga details:", responseBody: e.message, stackTrace: stackTrace);
|
||||
@@ -266,20 +255,9 @@ class MangaDetailsCubit extends Cubit<MangaDetailsState> with EffectMixin<MangaD
|
||||
|
||||
Future<void> _getMangaBanners(User loggedUser) async {
|
||||
try {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching Manga Banners from AniList for ${state.selectedManga.title.userPreferred}");
|
||||
List<String> banners = await _mangaRepositoryAnilist.getMediaCoverImages(loggedUser);
|
||||
emit(state.copyWith(banners: banners));
|
||||
case Service.mal:
|
||||
_logger.i("Fetching Manga Banners from MyMangaList for ${state.selectedManga.title.userPreferred}");
|
||||
case Service.shikimori:
|
||||
_logger.i("Fetching Manga Banners from Shikimori for ${state.selectedManga.title.userPreferred}");
|
||||
case Service.kitsu:
|
||||
_logger.i("Fetching Manga Banners from Kitsu for ${state.selectedManga.title.userPreferred}");
|
||||
case Service.simkl:
|
||||
_logger.i("Fetching Manga Banners from Simkl for ${state.selectedManga.title.userPreferred}");
|
||||
}
|
||||
_logger.i("Fetching Manga Banners for ${state.selectedManga.title.userPreferred}");
|
||||
List<String> banners = await _mangaRepository.getMediaCoverImages(loggedUser);
|
||||
emit(state.copyWith(banners: banners));
|
||||
} on HttpServerException catch (e, stackTrace) {
|
||||
handleError("Error fetching Manga banners:", responseBody: e.message, stackTrace: stackTrace);
|
||||
} catch (e, stackTrace) {
|
||||
|
||||
@@ -12,7 +12,7 @@ import 'dart:async';
|
||||
import 'package:unyo/application/cubits/effect_mixin.dart';
|
||||
import 'package:unyo/application/effects/app_effects.dart';
|
||||
import 'package:unyo/application/states/video_state.dart';
|
||||
import 'package:unyo/core/enums/service.dart';
|
||||
|
||||
import 'package:unyo/core/notification/anime_notifier.dart';
|
||||
import 'package:unyo/core/notification/episode_info_notifier.dart';
|
||||
import 'package:unyo/core/notification/episodes_notifier.dart';
|
||||
@@ -27,7 +27,7 @@ import 'package:unyo/core/services/api/http/api_response.dart';
|
||||
import 'package:unyo/core/services/api/http/http_exception.dart';
|
||||
import 'package:unyo/core/services/api/http/http_service.dart';
|
||||
import 'package:unyo/core/services/video/video_service.dart';
|
||||
import 'package:unyo/data/repositories/anime_repository_anilist.dart';
|
||||
import 'package:unyo/domain/repositories/anime_repository.dart';
|
||||
import 'package:unyo/data/repositories/extension_repository_aniyomi.dart';
|
||||
import 'package:unyo/domain/entities/media/anime.dart';
|
||||
import 'package:unyo/domain/entities/media/episode_info.dart';
|
||||
@@ -44,7 +44,7 @@ class VideoCubit extends Cubit<VideoState> with EffectMixin<VideoState> {
|
||||
|
||||
// Repositories
|
||||
final ExtensionRepositoryAniyomi _extensionRepositoryAniyomi;
|
||||
final AnimeRepositoryAnilist _animeRepositoryAnilist;
|
||||
final AnimeRepository _animeRepository;
|
||||
|
||||
// Notifiers / Subscriptions
|
||||
final UserNotifier _loggedUserNotifier;
|
||||
@@ -82,7 +82,7 @@ class VideoCubit extends Cubit<VideoState> with EffectMixin<VideoState> {
|
||||
this._selectedExtensionNotifier,
|
||||
this._selectedEpisodesNotifier,
|
||||
this._extensionRepositoryAniyomi,
|
||||
this._animeRepositoryAnilist,
|
||||
this._animeRepository,
|
||||
this._reloadNotifier,
|
||||
) : super(
|
||||
VideoState(
|
||||
@@ -494,25 +494,14 @@ class VideoCubit extends Cubit<VideoState> with EffectMixin<VideoState> {
|
||||
progress: state.videoInfo.playlistIndex + 1,
|
||||
status: "Current",
|
||||
);
|
||||
switch (state.loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Updating Media List Entry to $desiredMediaListEntry on Anilist");
|
||||
MediaListEntry savedMediaListEntry = await _animeRepositoryAnilist.updateMediaListEntry(
|
||||
desiredMediaListEntry,
|
||||
state.selectedAnime,
|
||||
state.loggedUser,
|
||||
);
|
||||
emit(state.copyWith(mediaListEntry: savedMediaListEntry));
|
||||
_reloadNotifier.emitReload(ReloadType.videoMediaListEntryUpdated);
|
||||
case Service.mal:
|
||||
_logger.i("Updating Media List Entry to $desiredMediaListEntry on MyAnimeList");
|
||||
case Service.shikimori:
|
||||
_logger.i("Updating Media List Entry to $desiredMediaListEntry on Shikimori");
|
||||
case Service.kitsu:
|
||||
_logger.i("Updating Media List Entry to $desiredMediaListEntry on Kitsu");
|
||||
case Service.simkl:
|
||||
_logger.i("Updating Media List Entry to $desiredMediaListEntry on Simkl");
|
||||
}
|
||||
_logger.i("Updating Media List Entry to $desiredMediaListEntry");
|
||||
MediaListEntry savedMediaListEntry = await _animeRepository.updateMediaListEntry(
|
||||
desiredMediaListEntry,
|
||||
state.selectedAnime,
|
||||
state.loggedUser,
|
||||
);
|
||||
emit(state.copyWith(mediaListEntry: savedMediaListEntry));
|
||||
_reloadNotifier.emitReload(ReloadType.videoMediaListEntryUpdated);
|
||||
} on HttpServerException catch (e, stackTrace) {
|
||||
handleError("Error updating Anime Entry:", responseBody: e.message, stackTrace: stackTrace);
|
||||
} catch (e, stackTrace) {
|
||||
|
||||
@@ -39,6 +39,8 @@ import 'package:unyo/core/services/api/http/http_service.dart';
|
||||
import 'package:unyo/core/services/effects/app_effect_handler.dart';
|
||||
import 'package:unyo/core/services/settings/settings_service.dart';
|
||||
import 'package:unyo/core/services/torrent/torrent_service.dart';
|
||||
import 'package:unyo/core/factories/anime_repository_factory.dart';
|
||||
import 'package:unyo/core/factories/manga_repository_factory.dart';
|
||||
import 'package:unyo/core/theme/color_image_service.dart';
|
||||
import 'package:unyo/core/theme/theme_service.dart';
|
||||
import 'package:unyo/data/repositories/anime_repository_anilist.dart';
|
||||
@@ -46,6 +48,8 @@ import 'package:unyo/data/repositories/episode_repository_anizip.dart';
|
||||
import 'package:unyo/data/repositories/extension_repository_aniyomi.dart';
|
||||
import 'package:unyo/data/repositories/manga_repository_anilist.dart';
|
||||
import 'package:unyo/data/repositories/repositories.dart';
|
||||
import 'package:unyo/domain/repositories/anime_repository.dart';
|
||||
import 'package:unyo/domain/repositories/manga_repository.dart';
|
||||
import 'package:unyo/application/cubits/home_cubit.dart';
|
||||
|
||||
final sl = GetIt.instance;
|
||||
@@ -98,6 +102,8 @@ void setupLocator() async{
|
||||
));
|
||||
sl.registerLazySingleton<AnimeRepositoryAnilist>(() => AnimeRepositoryAnilist());
|
||||
sl.registerLazySingleton<MangaRepositoryAnilist>(() => MangaRepositoryAnilist());
|
||||
sl.registerLazySingleton<AnimeRepository>(() => AnimeRepositoryFactory());
|
||||
sl.registerLazySingleton<MangaRepository>(() => MangaRepositoryFactory());
|
||||
sl.registerLazySingleton<EpisodeRepositoryAnizip>(() => EpisodeRepositoryAnizip());
|
||||
// Cubits / Blocs
|
||||
sl.registerFactory<LoginCubit>(
|
||||
@@ -117,7 +123,7 @@ void setupLocator() async{
|
||||
sl<MangaNotifier>(),
|
||||
sl<MediaListNotifier>(),
|
||||
sl<UserRepositoryAnilist>(),
|
||||
sl<AnimeRepositoryAnilist>(),
|
||||
sl<AnimeRepository>(),
|
||||
sl<MenuBarNotifier>(),
|
||||
sl<ReloadNotifier>(),
|
||||
),
|
||||
@@ -127,7 +133,7 @@ void setupLocator() async{
|
||||
);
|
||||
sl.registerFactory<AnimeCubit>(
|
||||
() => AnimeCubit(
|
||||
sl<AnimeRepositoryAnilist>(),
|
||||
sl<AnimeRepository>(),
|
||||
sl<UserNotifier>(instanceName: config.loggedUserNotifier),
|
||||
sl<AnimeNotifier>(),
|
||||
sl<AnimeGenresNotifier>(),
|
||||
@@ -137,7 +143,7 @@ void setupLocator() async{
|
||||
);
|
||||
sl.registerFactory<MangaCubit>(
|
||||
() => MangaCubit(
|
||||
sl<MangaRepositoryAnilist>(),
|
||||
sl<MangaRepository>(),
|
||||
sl<UserNotifier>(instanceName: config.loggedUserNotifier),
|
||||
sl<MangaNotifier>(),
|
||||
sl<MangaGenresNotifier>(),
|
||||
@@ -162,7 +168,7 @@ void setupLocator() async{
|
||||
);
|
||||
sl.registerFactory<CalendarCubit>(
|
||||
() => CalendarCubit(
|
||||
sl<AnimeRepositoryAnilist>(),
|
||||
sl<AnimeRepository>(),
|
||||
sl<UserNotifier>(instanceName: config.loggedUserNotifier),
|
||||
sl<AnimeNotifier>(),
|
||||
sl<MediaListNotifier>(),
|
||||
@@ -170,7 +176,7 @@ void setupLocator() async{
|
||||
);
|
||||
sl.registerFactory<AnimeDetailsCubit>(
|
||||
() => AnimeDetailsCubit(
|
||||
sl<AnimeRepositoryAnilist>(),
|
||||
sl<AnimeRepository>(),
|
||||
sl<EpisodeRepositoryAnizip>(),
|
||||
sl<UserNotifier>(instanceName: config.loggedUserNotifier),
|
||||
sl<AnimeNotifier>(),
|
||||
@@ -188,7 +194,7 @@ void setupLocator() async{
|
||||
);
|
||||
sl.registerFactory<MangaDetailsCubit>(
|
||||
() => MangaDetailsCubit(
|
||||
sl<MangaRepositoryAnilist>(),
|
||||
sl<MangaRepository>(),
|
||||
sl<UserNotifier>(instanceName: config.loggedUserNotifier),
|
||||
sl<MangaNotifier>(),
|
||||
sl<MangaGenresNotifier>(),
|
||||
@@ -213,7 +219,7 @@ void setupLocator() async{
|
||||
sl<MediaListNotifier>(),
|
||||
sl<AnimeNotifier>(),
|
||||
sl<AnimeGenresNotifier>(),
|
||||
sl<AnimeRepositoryAnilist>(),
|
||||
sl<AnimeRepository>(),
|
||||
),
|
||||
);
|
||||
sl.registerFactory<MangaAdvancedSearchCubit>(
|
||||
@@ -222,7 +228,7 @@ void setupLocator() async{
|
||||
sl<MediaListNotifier>(),
|
||||
sl<MangaNotifier>(),
|
||||
sl<MangaGenresNotifier>(),
|
||||
sl<MangaRepositoryAnilist>(),
|
||||
sl<MangaRepository>(),
|
||||
),
|
||||
);
|
||||
sl.registerFactory<VideoCubit>(
|
||||
@@ -235,7 +241,7 @@ void setupLocator() async{
|
||||
sl<ExtensionNotifier>(),
|
||||
sl<EpisodesNotifier>(),
|
||||
sl<ExtensionRepositoryAniyomi>(),
|
||||
sl<AnimeRepositoryAnilist>(),
|
||||
sl<AnimeRepository>(),
|
||||
sl<ReloadNotifier>(),
|
||||
)
|
||||
);
|
||||
|
||||
288
lib/core/factories/anime_repository_factory.dart
Normal file
288
lib/core/factories/anime_repository_factory.dart
Normal file
@@ -0,0 +1,288 @@
|
||||
// External dependencies
|
||||
import 'package:logger/logger.dart';
|
||||
|
||||
// Internal dependencies
|
||||
import 'package:unyo/core/di/locator.dart';
|
||||
import 'package:unyo/core/enums/service.dart';
|
||||
import 'package:unyo/data/repositories/anime_repository_anilist.dart';
|
||||
import 'package:unyo/domain/entities/media/anime.dart';
|
||||
import 'package:unyo/domain/entities/media/anime_details.dart';
|
||||
import 'package:unyo/domain/entities/list/media_list_entry.dart';
|
||||
import 'package:unyo/domain/entities/user/user.dart';
|
||||
import 'package:unyo/domain/repositories/anime_repository.dart';
|
||||
|
||||
/// Factory that resolves the correct [AnimeRepository] implementation
|
||||
/// based on the user's selected metadata [Service].
|
||||
///
|
||||
/// Currently supports:
|
||||
/// - [Service.anilist] → delegates to [AnimeRepositoryAnilist]
|
||||
/// - All other services → returns safe empty defaults
|
||||
class AnimeRepositoryFactory implements AnimeRepository {
|
||||
final AnimeRepositoryAnilist _animeRepositoryAnilist = sl<AnimeRepositoryAnilist>();
|
||||
final Logger _logger = sl<Logger>();
|
||||
|
||||
@override
|
||||
Future<(bool, List<Anime>)> getRecentlyReleasedAnimes(
|
||||
int page,
|
||||
User loggedUser, {
|
||||
bool ignoreCache = false,
|
||||
}) async {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching Anilist recently released anime");
|
||||
return _animeRepositoryAnilist.getRecentlyReleasedAnimes(
|
||||
page,
|
||||
loggedUser,
|
||||
ignoreCache: ignoreCache,
|
||||
);
|
||||
case Service.mal:
|
||||
case Service.kitsu:
|
||||
case Service.shikimori:
|
||||
case Service.simkl:
|
||||
return (false, <Anime>[]);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<(bool, List<Anime>)> getTrendingAnimes(
|
||||
int page,
|
||||
User loggedUser, {
|
||||
bool ignoreCache = false,
|
||||
}) async {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching Anilist trending anime");
|
||||
return _animeRepositoryAnilist.getTrendingAnimes(
|
||||
page,
|
||||
loggedUser,
|
||||
ignoreCache: ignoreCache,
|
||||
);
|
||||
case Service.mal:
|
||||
case Service.kitsu:
|
||||
case Service.shikimori:
|
||||
case Service.simkl:
|
||||
return (false, <Anime>[]);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<(bool, List<Anime>)> getPopularAnimes(
|
||||
int page,
|
||||
User loggedUser, {
|
||||
bool ignoreCache = false,
|
||||
}) async {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching Anilist popular anime");
|
||||
return _animeRepositoryAnilist.getPopularAnimes(
|
||||
page,
|
||||
loggedUser,
|
||||
ignoreCache: ignoreCache,
|
||||
);
|
||||
case Service.mal:
|
||||
case Service.kitsu:
|
||||
case Service.shikimori:
|
||||
case Service.simkl:
|
||||
return (false, <Anime>[]);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<(bool, List<Anime>)> getRecentlyCompletedAnimes(
|
||||
int page,
|
||||
User loggedUser, {
|
||||
bool ignoreCache = false,
|
||||
}) async {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching Anilist recently completed anime");
|
||||
return _animeRepositoryAnilist.getRecentlyCompletedAnimes(
|
||||
page,
|
||||
loggedUser,
|
||||
ignoreCache: ignoreCache,
|
||||
);
|
||||
case Service.mal:
|
||||
case Service.kitsu:
|
||||
case Service.shikimori:
|
||||
case Service.simkl:
|
||||
return (false, <Anime>[]);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<(bool, List<Anime>)> getUpcomingAnimes(
|
||||
int page,
|
||||
User loggedUser, {
|
||||
bool ignoreCache = false,
|
||||
}) async {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching Anilist upcoming anime");
|
||||
return _animeRepositoryAnilist.getUpcomingAnimes(
|
||||
page,
|
||||
loggedUser,
|
||||
ignoreCache: ignoreCache,
|
||||
);
|
||||
case Service.mal:
|
||||
case Service.kitsu:
|
||||
case Service.shikimori:
|
||||
case Service.simkl:
|
||||
return (false, <Anime>[]);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Map<String, List<Anime>>> getCalendarReleases(int page, User loggedUser) async {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching Anilist calendar releases");
|
||||
return _animeRepositoryAnilist.getCalendarReleases(page, loggedUser);
|
||||
case Service.mal:
|
||||
case Service.kitsu:
|
||||
case Service.shikimori:
|
||||
case Service.simkl:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<(bool, AnimeDetails)> getAnimeDetails(Anime selectedAnime, User loggedUser) async {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching Anime Details from AniList for ${selectedAnime.title.userPreferred}");
|
||||
return _animeRepositoryAnilist.getAnimeDetails(selectedAnime, loggedUser);
|
||||
case Service.mal:
|
||||
_logger.i("Fetching Anime Details from MyAnimeList for ${selectedAnime.title.userPreferred}");
|
||||
return (false, AnimeDetailsModel.empty());
|
||||
case Service.shikimori:
|
||||
_logger.i("Fetching Anime Details from Shikimori for ${selectedAnime.title.userPreferred}");
|
||||
return (false, AnimeDetailsModel.empty());
|
||||
case Service.kitsu:
|
||||
_logger.i("Fetching Anime Details from Kitsu for ${selectedAnime.title.userPreferred}");
|
||||
return (false, AnimeDetailsModel.empty());
|
||||
case Service.simkl:
|
||||
_logger.i("Fetching Anime Details from Simkl for ${selectedAnime.title.userPreferred}");
|
||||
return (false, AnimeDetailsModel.empty());
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Map<String, (bool, List<String>)>> getUserAnimeAdvancedSearchFilters() async {
|
||||
return _animeRepositoryAnilist.getUserAnimeAdvancedSearchFilters();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<Anime>> performAnimeAdvancedSearch(
|
||||
String query,
|
||||
List<String> selectedGenres,
|
||||
String? selectedSeason,
|
||||
String? selectedFormat,
|
||||
int? selectedYear,
|
||||
String? selectedAiringStatus,
|
||||
String sort,
|
||||
int page,
|
||||
User loggedUser,
|
||||
) async {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
return _animeRepositoryAnilist.performAnimeAdvancedSearch(
|
||||
query,
|
||||
selectedGenres,
|
||||
selectedSeason,
|
||||
selectedFormat,
|
||||
selectedYear,
|
||||
selectedAiringStatus,
|
||||
sort,
|
||||
page,
|
||||
loggedUser,
|
||||
);
|
||||
case Service.mal:
|
||||
case Service.shikimori:
|
||||
case Service.simkl:
|
||||
case Service.kitsu:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<String>> getMediaCoverImages(User loggedUser, {bool ignoreCache = false}) async {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching Media Cover Images from AniList");
|
||||
return _animeRepositoryAnilist.getMediaCoverImages(
|
||||
loggedUser,
|
||||
ignoreCache: ignoreCache,
|
||||
);
|
||||
case Service.mal:
|
||||
_logger.i("Fetching Media Cover Images from MyAnimeList");
|
||||
return [];
|
||||
case Service.shikimori:
|
||||
_logger.i("Fetching Media Cover Images from Shikimori");
|
||||
return [];
|
||||
case Service.kitsu:
|
||||
_logger.i("Fetching Media Cover Images from Kitsu");
|
||||
return [];
|
||||
case Service.simkl:
|
||||
_logger.i("Fetching Media Cover Images from Simkl");
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<MediaListEntry> updateMediaListEntry(
|
||||
MediaListEntry newMediaListEntry,
|
||||
Anime selectedAnime,
|
||||
User loggedUser,
|
||||
) async {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Updating Media List Entry to $newMediaListEntry on Anilist");
|
||||
return _animeRepositoryAnilist.updateMediaListEntry(
|
||||
newMediaListEntry,
|
||||
selectedAnime,
|
||||
loggedUser,
|
||||
);
|
||||
case Service.mal:
|
||||
_logger.i("Updating Media List Entry to $newMediaListEntry on MyAnimeList");
|
||||
return MediaListEntryModel.empty();
|
||||
case Service.shikimori:
|
||||
_logger.i("Updating Media List Entry to $newMediaListEntry on Shikimori");
|
||||
return MediaListEntryModel.empty();
|
||||
case Service.kitsu:
|
||||
_logger.i("Updating Media List Entry to $newMediaListEntry on Kitsu");
|
||||
return MediaListEntryModel.empty();
|
||||
case Service.simkl:
|
||||
_logger.i("Updating Media List Entry to $newMediaListEntry on Simkl");
|
||||
return MediaListEntryModel.empty();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<MediaListEntry> getMediaListEntry(
|
||||
Anime selectedAnime,
|
||||
User loggedUser, {
|
||||
bool ignoreCache = false,
|
||||
}) async {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching User Media List Entry from AniList for ${selectedAnime.title.userPreferred}");
|
||||
return _animeRepositoryAnilist.getMediaListEntry(
|
||||
selectedAnime,
|
||||
loggedUser,
|
||||
ignoreCache: ignoreCache,
|
||||
);
|
||||
case Service.mal:
|
||||
_logger.i("Fetching User Media List Entry from MyAnimeList for ${selectedAnime.title.userPreferred}");
|
||||
return MediaListEntryModel.empty();
|
||||
case Service.shikimori:
|
||||
_logger.i("Fetching User Media List Entry from Shikimori for ${selectedAnime.title.userPreferred}");
|
||||
return MediaListEntryModel.empty();
|
||||
case Service.kitsu:
|
||||
_logger.i("Fetching User Media List Entry from Kitsu for ${selectedAnime.title.userPreferred}");
|
||||
return MediaListEntryModel.empty();
|
||||
case Service.simkl:
|
||||
_logger.i("Fetching User Media List Entry from Simkl for ${selectedAnime.title.userPreferred}");
|
||||
return MediaListEntryModel.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
191
lib/core/factories/manga_repository_factory.dart
Normal file
191
lib/core/factories/manga_repository_factory.dart
Normal file
@@ -0,0 +1,191 @@
|
||||
// External dependencies
|
||||
import 'package:logger/logger.dart';
|
||||
|
||||
// Internal dependencies
|
||||
import 'package:unyo/core/di/locator.dart';
|
||||
import 'package:unyo/core/enums/service.dart';
|
||||
import 'package:unyo/data/repositories/manga_repository_anilist.dart';
|
||||
import 'package:unyo/domain/entities/media/manga.dart';
|
||||
import 'package:unyo/domain/entities/media/manga_details.dart';
|
||||
import 'package:unyo/domain/entities/user/user.dart';
|
||||
import 'package:unyo/domain/repositories/manga_repository.dart';
|
||||
|
||||
/// Factory that resolves the correct [MangaRepository] implementation
|
||||
/// based on the user's selected metadata [Service].
|
||||
///
|
||||
/// Currently supports:
|
||||
/// - [Service.anilist] → delegates to [MangaRepositoryAnilist]
|
||||
/// - All other services → returns safe empty defaults
|
||||
class MangaRepositoryFactory implements MangaRepository {
|
||||
final MangaRepositoryAnilist _mangaRepositoryAnilist = sl<MangaRepositoryAnilist>();
|
||||
final Logger _logger = sl<Logger>();
|
||||
|
||||
@override
|
||||
Future<(bool, List<Manga>)> getTrendingMangas(
|
||||
int page,
|
||||
User loggedUser, {
|
||||
bool ignoreCache = false,
|
||||
}) async {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching Anilist trending manga");
|
||||
return _mangaRepositoryAnilist.getTrendingMangas(
|
||||
page,
|
||||
loggedUser,
|
||||
ignoreCache: ignoreCache,
|
||||
);
|
||||
case Service.mal:
|
||||
case Service.kitsu:
|
||||
case Service.shikimori:
|
||||
case Service.simkl:
|
||||
return (false, <Manga>[]);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<(bool, List<Manga>)> getPopularMangas(
|
||||
int page,
|
||||
User loggedUser, {
|
||||
bool ignoreCache = false,
|
||||
}) async {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching Anilist popular manga");
|
||||
return _mangaRepositoryAnilist.getPopularMangas(
|
||||
page,
|
||||
loggedUser,
|
||||
ignoreCache: ignoreCache,
|
||||
);
|
||||
case Service.mal:
|
||||
case Service.kitsu:
|
||||
case Service.shikimori:
|
||||
case Service.simkl:
|
||||
return (false, <Manga>[]);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<(bool, List<Manga>)> getRecentlyCompletedMangas(
|
||||
int page,
|
||||
User loggedUser, {
|
||||
bool ignoreCache = false,
|
||||
}) async {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching Anilist recently completed manga");
|
||||
return _mangaRepositoryAnilist.getRecentlyCompletedMangas(
|
||||
page,
|
||||
loggedUser,
|
||||
ignoreCache: ignoreCache,
|
||||
);
|
||||
case Service.mal:
|
||||
case Service.kitsu:
|
||||
case Service.shikimori:
|
||||
case Service.simkl:
|
||||
return (false, <Manga>[]);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<(bool, List<Manga>)> getUpcomingMangas(
|
||||
int page,
|
||||
User loggedUser, {
|
||||
bool ignoreCache = false,
|
||||
}) async {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching Anilist upcoming manga");
|
||||
return _mangaRepositoryAnilist.getUpcomingMangas(
|
||||
page,
|
||||
loggedUser,
|
||||
ignoreCache: ignoreCache,
|
||||
);
|
||||
case Service.mal:
|
||||
case Service.kitsu:
|
||||
case Service.shikimori:
|
||||
case Service.simkl:
|
||||
return (false, <Manga>[]);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<(bool, MangaDetails)> getMangaDetails(Manga selectedManga, User loggedUser) async {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching Manga Details from AniList for ${selectedManga.title.userPreferred}");
|
||||
return _mangaRepositoryAnilist.getMangaDetails(selectedManga, loggedUser);
|
||||
case Service.mal:
|
||||
_logger.i("Fetching Manga Details from MyMangaList for ${selectedManga.title.userPreferred}");
|
||||
return (false, MangaDetailsModel.empty());
|
||||
case Service.shikimori:
|
||||
_logger.i("Fetching Manga Details from Shikimori for ${selectedManga.title.userPreferred}");
|
||||
return (false, MangaDetailsModel.empty());
|
||||
case Service.kitsu:
|
||||
_logger.i("Fetching Manga Details from Kitsu for ${selectedManga.title.userPreferred}");
|
||||
return (false, MangaDetailsModel.empty());
|
||||
case Service.simkl:
|
||||
_logger.i("Fetching Manga Details from Simkl for ${selectedManga.title.userPreferred}");
|
||||
return (false, MangaDetailsModel.empty());
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Map<String, (bool, List<String>)>> getUserMangaAdvancedSearchFilters() async {
|
||||
return _mangaRepositoryAnilist.getUserMangaAdvancedSearchFilters();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<Manga>> performMangaAdvancedSearch(
|
||||
String query,
|
||||
List<String> selectedGenres,
|
||||
String? selectedFormat,
|
||||
String? selectedCountry,
|
||||
String? selectedAiringStatus,
|
||||
String sort,
|
||||
int page,
|
||||
User loggedUser,
|
||||
) async {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
return _mangaRepositoryAnilist.performMangaAdvancedSearch(
|
||||
query,
|
||||
selectedGenres,
|
||||
selectedFormat,
|
||||
selectedCountry,
|
||||
selectedAiringStatus,
|
||||
sort,
|
||||
page,
|
||||
loggedUser,
|
||||
);
|
||||
case Service.mal:
|
||||
case Service.shikimori:
|
||||
case Service.simkl:
|
||||
case Service.kitsu:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<String>> getMediaCoverImages(User loggedUser, {bool ignoreCache = false}) async {
|
||||
switch (loggedUser.settings.service) {
|
||||
case Service.anilist:
|
||||
_logger.i("Fetching Manga Banners from AniList for ...");
|
||||
return _mangaRepositoryAnilist.getMediaCoverImages(
|
||||
loggedUser,
|
||||
ignoreCache: ignoreCache,
|
||||
);
|
||||
case Service.mal:
|
||||
_logger.i("Fetching Manga Banners from MyMangaList for ...");
|
||||
return [];
|
||||
case Service.shikimori:
|
||||
_logger.i("Fetching Manga Banners from Shikimori for ...");
|
||||
return [];
|
||||
case Service.kitsu:
|
||||
_logger.i("Fetching Manga Banners from Kitsu for ...");
|
||||
return [];
|
||||
case Service.simkl:
|
||||
_logger.i("Fetching Manga Banners from Simkl for ...");
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -267,8 +267,8 @@ class MangaRepositoryAnilist with RepositoryMixin implements MangaRepository {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<String>> getMediaCoverImages(User loggedUser) async {
|
||||
(bool, List<Manga>) popularMangas = await getPopularMangas(1, loggedUser);
|
||||
Future<List<String>> getMediaCoverImages(User loggedUser, {bool ignoreCache = false}) async {
|
||||
(bool, List<Manga>) popularMangas = await getPopularMangas(1, loggedUser, ignoreCache: ignoreCache);
|
||||
return popularMangas.$2.map((manga) => manga.coverImage).where((coverImage) => coverImage != "").shuffled(Random()).toList();
|
||||
}
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@ import 'package:unyo/domain/entities/list/media_list_entry.dart';
|
||||
import 'package:unyo/domain/entities/user/user.dart';
|
||||
|
||||
abstract class AnimeRepository {
|
||||
Future<(bool, List<Anime>)> getRecentlyReleasedAnimes(int page, User loggedUser);
|
||||
Future<(bool, List<Anime>)> getTrendingAnimes(int page, User loggedUser);
|
||||
Future<(bool, List<Anime>)> getPopularAnimes(int page, User loggedUser);
|
||||
Future<(bool, List<Anime>)> getRecentlyCompletedAnimes(int page, User loggedUser);
|
||||
Future<(bool, List<Anime>)> getUpcomingAnimes(int page, User loggedUser);
|
||||
Future<(bool, List<Anime>)> getRecentlyReleasedAnimes(int page, User loggedUser, {bool ignoreCache = false});
|
||||
Future<(bool, List<Anime>)> getTrendingAnimes(int page, User loggedUser, {bool ignoreCache = false});
|
||||
Future<(bool, List<Anime>)> getPopularAnimes(int page, User loggedUser, {bool ignoreCache = false});
|
||||
Future<(bool, List<Anime>)> getRecentlyCompletedAnimes(int page, User loggedUser, {bool ignoreCache = false});
|
||||
Future<(bool, List<Anime>)> getUpcomingAnimes(int page, User loggedUser, {bool ignoreCache = false});
|
||||
Future<Map<String, List<Anime>>> getCalendarReleases(int page, User loggedUser);
|
||||
Future<(bool, AnimeDetails)> getAnimeDetails(Anime selectedAnime, User loggedUser);
|
||||
Future<Map<String, (bool, List<String>)>> getUserAnimeAdvancedSearchFilters();
|
||||
@@ -23,7 +23,7 @@ abstract class AnimeRepository {
|
||||
int page,
|
||||
User loggedUser
|
||||
);
|
||||
Future<List<String>> getMediaCoverImages(User loggedUser);
|
||||
Future<List<String>> getMediaCoverImages(User loggedUser, {bool ignoreCache = false});
|
||||
Future<MediaListEntry> updateMediaListEntry(MediaListEntry newMediaListEntry, Anime selectedAnime, User loggedUser);
|
||||
Future<MediaListEntry> getMediaListEntry(Anime selectedAnime, User loggedUser);
|
||||
Future<MediaListEntry> getMediaListEntry(Anime selectedAnime, User loggedUser, {bool ignoreCache = false});
|
||||
}
|
||||
|
||||
@@ -3,10 +3,10 @@ import 'package:unyo/domain/entities/media/manga_details.dart';
|
||||
import 'package:unyo/domain/entities/user/user.dart';
|
||||
|
||||
abstract class MangaRepository {
|
||||
Future<(bool, List<Manga>)> getTrendingMangas(int page, User loggedUser);
|
||||
Future<(bool, List<Manga>)> getPopularMangas(int page, User loggedUser);
|
||||
Future<(bool, List<Manga>)> getRecentlyCompletedMangas(int page, User loggedUser);
|
||||
Future<(bool, List<Manga>)> getUpcomingMangas(int page, User loggedUser);
|
||||
Future<(bool, List<Manga>)> getTrendingMangas(int page, User loggedUser, {bool ignoreCache = false});
|
||||
Future<(bool, List<Manga>)> getPopularMangas(int page, User loggedUser, {bool ignoreCache = false});
|
||||
Future<(bool, List<Manga>)> getRecentlyCompletedMangas(int page, User loggedUser, {bool ignoreCache = false});
|
||||
Future<(bool, List<Manga>)> getUpcomingMangas(int page, User loggedUser, {bool ignoreCache = false});
|
||||
Future<(bool, MangaDetails)> getMangaDetails(Manga selectedManga, User loggedUser);
|
||||
Future<Map<String, (bool, List<String>)>> getUserMangaAdvancedSearchFilters();
|
||||
Future<List<Manga>> performMangaAdvancedSearch(
|
||||
@@ -19,5 +19,5 @@ abstract class MangaRepository {
|
||||
int page,
|
||||
User loggedUser
|
||||
);
|
||||
Future<List<String>> getMediaCoverImages(User loggedUser);
|
||||
Future<List<String>> getMediaCoverImages(User loggedUser, {bool ignoreCache = false});
|
||||
}
|
||||
@@ -22,6 +22,10 @@ import 'package:unyo/data/repositories/anime_repository_anilist.dart';
|
||||
import 'package:unyo/data/repositories/episode_repository_anizip.dart';
|
||||
import 'package:unyo/data/repositories/manga_repository_anilist.dart';
|
||||
import 'package:unyo/data/repositories/repositories.dart';
|
||||
import 'package:unyo/core/factories/anime_repository_factory.dart';
|
||||
import 'package:unyo/core/factories/manga_repository_factory.dart';
|
||||
import 'package:unyo/domain/repositories/anime_repository.dart';
|
||||
import 'package:unyo/domain/repositories/manga_repository.dart';
|
||||
|
||||
// DartRX Notifiers
|
||||
class MockUserNotifier extends Mock implements UserNotifier {}
|
||||
@@ -96,6 +100,8 @@ Future<void> setupTestLocator() async{
|
||||
);
|
||||
sl.registerSingleton<AnimeRepositoryAnilist>(MockAnimeRepositoryAnilist());
|
||||
sl.registerLazySingleton<MangaRepositoryAnilist>(() => MockMangaRepositoryAnilist());
|
||||
sl.registerLazySingleton<AnimeRepository>(() => AnimeRepositoryFactory());
|
||||
sl.registerLazySingleton<MangaRepository>(() => MangaRepositoryFactory());
|
||||
sl.registerLazySingleton<EpisodeRepositoryAnizip>(() => MockEpisodeRepositoryAnizip());
|
||||
|
||||
// Cubits / Blocs - Register factories that create real cubits with mocked dependencies
|
||||
@@ -105,7 +111,7 @@ Future<void> setupTestLocator() async{
|
||||
sl<MediaListNotifier>(),
|
||||
sl<AnimeNotifier>(),
|
||||
sl<AnimeGenresNotifier>(),
|
||||
sl<AnimeRepositoryAnilist>(),
|
||||
sl<AnimeRepository>(),
|
||||
),
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user