More progress on the anime details page, displaying characters and recommended animes

This commit is contained in:
2025-10-12 18:25:16 +01:00
parent 8bb378aec3
commit c14e41150a
38 changed files with 3591 additions and 534 deletions

View File

@@ -1,3 +1,5 @@
description: This file stores settings for Dart & Flutter DevTools.
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
extensions:
- hive_ce: true
- provider: true

View File

@@ -7,33 +7,50 @@ import 'package:unyo/application/effects/app_effects.dart';
import 'package:unyo/application/states/anime_details_state.dart';
import 'package:bloc/bloc.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/models/anilist_user_model.dart';
import 'package:unyo/data/repositories/anime_repository_anilist.dart';
import 'package:unyo/domain/entities/anime.dart';
import 'package:unyo/domain/entities/anime_progress.dart';
import 'package:unyo/domain/entities/anime_details.dart';
import 'package:unyo/domain/entities/media_list.dart';
import 'package:unyo/domain/entities/user.dart';
class AnimeDetailsCubit extends Cubit<AnimeDetailsState>
with EffectMixin<AnimeDetailsState> {
// Repositories
final AnimeRepositoryAnilist _animeRepositoryAnilist;
// Notifiers / Subscriptions
final AnimeNotifier _selectedAnimeNotifier;
final UserNotifier _loggedUserNotifier;
final MediaListNotifier _selectedMediaList;
final MediaListNotifier _selectedMediaListNotifier;
late StreamSubscription<Anime> _selectedAnimeSubscription;
late StreamSubscription<User> _loggedUserSubscription;
late StreamSubscription<MediaList> _selectedMediaListSubscription;
// Logger
final Logger _logger = sl<Logger>();
// Services
final AniyomiBridge aniyomiBridge = sl<AniyomiBridge>();
AnimeDetailsCubit(this._loggedUserNotifier, this._selectedAnimeNotifier, this._selectedMediaList)
: super(
AnimeDetailsCubit(
this._animeRepositoryAnilist,
this._loggedUserNotifier,
this._selectedAnimeNotifier,
this._selectedMediaListNotifier,
) : super(
AnimeDetailsState(
loggedUser: UserModel.empty(),
selectedMediaList: MediaListModel.empty(),
selectedAnime: AnimeModel.empty(),
animeProgress: AnimeProgressModel.empty(),
progress: 0,
score: 0,
repeat: 0,
characters: (false, []),
recommendations: (false, []),
),
) {
@@ -57,24 +74,61 @@ class AnimeDetailsCubit extends Cubit<AnimeDetailsState>
}
void _init() {
_selectedAnimeSubscription = _selectedAnimeNotifier.animeStream.listen(
(anime) {
emit(state.copyWith(selectedAnime: anime));
},
);
_loggedUserSubscription = _loggedUserNotifier.userStream.listen((
user,
) {
emit(
state.copyWith(loggedUser: user),
);
_loggedUserSubscription = _loggedUserNotifier.userStream.listen((user) {
emit(state.copyWith(loggedUser: user));
});
_selectedMediaListSubscription = _selectedMediaList.mediaListStream.listen((
mediaList,
) {
emit(
state.copyWith(selectedMediaList: mediaList),
);
_selectedAnimeSubscription = _selectedAnimeNotifier.animeStream.listen((
anime,
) {
_getAnimeDetails(state.loggedUser, anime);
emit(state.copyWith(selectedAnime: anime));
});
_selectedMediaListSubscription = _selectedMediaListNotifier.mediaListStream.listen((
mediaList,
) {
emit(state.copyWith(selectedMediaList: mediaList));
});
}
void navigateToAnimeDetails(Anime anime, MediaList mediaList) {
_logger.i("Navigating to Anime Details of ${anime.title}");
_selectedAnimeNotifier.updateSelectedAnime(anime);
_selectedMediaListNotifier.updateSelectedMediaList(mediaList);
}
Future<void> _getAnimeDetails(User loggedUser, Anime selectedAnime) async {
switch (loggedUser.settings.service) {
case Service.anilist:
_logger.i(
"Fetching Anime Details from AniList for ${state.selectedAnime.title}",
);
(bool, AnimeDetails) animeDetails = await _animeRepositoryAnilist
.getAnimeDetails(selectedAnime, loggedUser);
emit(
state.copyWith(
characters: (true, animeDetails.$2.characters),
repeat: animeDetails.$2.repeat,
score: animeDetails.$2.score,
progress: animeDetails.$2.progress,
recommendations: (true, animeDetails.$2.recommendedAnimes),
),
);
case Service.mal:
_logger.i(
"Fetching Anime Details from MyAnimeList for ${state.selectedAnime.title}",
);
case Service.shikimori:
_logger.i(
"Fetching Anime Details from Shikimori for ${state.selectedAnime.title}",
);
case Service.kitsu:
_logger.i(
"Fetching Anime Details from Kitsu for ${state.selectedAnime.title}",
);
case Service.simkl:
_logger.i(
"Fetching Anime Details from Simkl for ${state.selectedAnime.title}",
);
}
}
}

View File

@@ -2,7 +2,7 @@ import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:unyo/application/cubits/effect_mixin.dart';
import 'package:unyo/application/effects/app_effects.dart';
import 'package:unyo/domain/entities/anime.dart';
import 'package:unyo/domain/entities/anime_progress.dart';
import 'package:unyo/domain/entities/media_character.dart';
import 'package:unyo/domain/entities/media_list.dart';
import 'package:unyo/domain/entities/user.dart';
@@ -14,11 +14,13 @@ abstract class AnimeDetailsState with _$AnimeDetailsState implements HasEffects{
required User loggedUser,
required MediaList selectedMediaList,
required Anime selectedAnime,
// relations
// characters
// voice actors
required int progress,
required int score,
required int repeat,
required (bool, List<MediaCharacter>) characters,
required (bool, List<Anime>) recommendations,
required AnimeProgress animeProgress,
// relations
// voice actors
@Default(<AppEffect>[]) List<AppEffect> effects,
}) = _AnimeDetailsState;

View File

@@ -14,10 +14,9 @@ T _$identity<T>(T value) => value;
/// @nodoc
mixin _$AnimeDetailsState {
User get loggedUser; MediaList get selectedMediaList; Anime get selectedAnime;// relations
// characters
User get loggedUser; MediaList get selectedMediaList; Anime get selectedAnime; int get progress; int get score; int get repeat; (bool, List<MediaCharacter>) get characters; (bool, List<Anime>) get recommendations;// relations
// voice actors
(bool, List<Anime>) get recommendations; AnimeProgress get animeProgress; List<AppEffect> get effects;
List<AppEffect> get effects;
/// Create a copy of AnimeDetailsState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@@ -28,16 +27,16 @@ $AnimeDetailsStateCopyWith<AnimeDetailsState> get copyWith => _$AnimeDetailsStat
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is AnimeDetailsState&&(identical(other.loggedUser, loggedUser) || other.loggedUser == loggedUser)&&(identical(other.selectedMediaList, selectedMediaList) || other.selectedMediaList == selectedMediaList)&&(identical(other.selectedAnime, selectedAnime) || other.selectedAnime == selectedAnime)&&(identical(other.recommendations, recommendations) || other.recommendations == recommendations)&&(identical(other.animeProgress, animeProgress) || other.animeProgress == animeProgress)&&const DeepCollectionEquality().equals(other.effects, effects));
return identical(this, other) || (other.runtimeType == runtimeType&&other is AnimeDetailsState&&(identical(other.loggedUser, loggedUser) || other.loggedUser == loggedUser)&&(identical(other.selectedMediaList, selectedMediaList) || other.selectedMediaList == selectedMediaList)&&(identical(other.selectedAnime, selectedAnime) || other.selectedAnime == selectedAnime)&&(identical(other.progress, progress) || other.progress == progress)&&(identical(other.score, score) || other.score == score)&&(identical(other.repeat, repeat) || other.repeat == repeat)&&(identical(other.characters, characters) || other.characters == characters)&&(identical(other.recommendations, recommendations) || other.recommendations == recommendations)&&const DeepCollectionEquality().equals(other.effects, effects));
}
@override
int get hashCode => Object.hash(runtimeType,loggedUser,selectedMediaList,selectedAnime,recommendations,animeProgress,const DeepCollectionEquality().hash(effects));
int get hashCode => Object.hash(runtimeType,loggedUser,selectedMediaList,selectedAnime,progress,score,repeat,characters,recommendations,const DeepCollectionEquality().hash(effects));
@override
String toString() {
return 'AnimeDetailsState(loggedUser: $loggedUser, selectedMediaList: $selectedMediaList, selectedAnime: $selectedAnime, recommendations: $recommendations, animeProgress: $animeProgress, effects: $effects)';
return 'AnimeDetailsState(loggedUser: $loggedUser, selectedMediaList: $selectedMediaList, selectedAnime: $selectedAnime, progress: $progress, score: $score, repeat: $repeat, characters: $characters, recommendations: $recommendations, effects: $effects)';
}
@@ -48,7 +47,7 @@ abstract mixin class $AnimeDetailsStateCopyWith<$Res> {
factory $AnimeDetailsStateCopyWith(AnimeDetailsState value, $Res Function(AnimeDetailsState) _then) = _$AnimeDetailsStateCopyWithImpl;
@useResult
$Res call({
User loggedUser, MediaList selectedMediaList, Anime selectedAnime, (bool, List<Anime>) recommendations, AnimeProgress animeProgress, List<AppEffect> effects
User loggedUser, MediaList selectedMediaList, Anime selectedAnime, int progress, int score, int repeat, (bool, List<MediaCharacter>) characters, (bool, List<Anime>) recommendations, List<AppEffect> effects
});
@@ -65,14 +64,17 @@ class _$AnimeDetailsStateCopyWithImpl<$Res>
/// Create a copy of AnimeDetailsState
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? loggedUser = null,Object? selectedMediaList = null,Object? selectedAnime = null,Object? recommendations = null,Object? animeProgress = null,Object? effects = null,}) {
@pragma('vm:prefer-inline') @override $Res call({Object? loggedUser = null,Object? selectedMediaList = null,Object? selectedAnime = null,Object? progress = null,Object? score = null,Object? repeat = null,Object? characters = null,Object? recommendations = null,Object? effects = null,}) {
return _then(_self.copyWith(
loggedUser: null == loggedUser ? _self.loggedUser : loggedUser // ignore: cast_nullable_to_non_nullable
as User,selectedMediaList: null == selectedMediaList ? _self.selectedMediaList : selectedMediaList // ignore: cast_nullable_to_non_nullable
as MediaList,selectedAnime: null == selectedAnime ? _self.selectedAnime : selectedAnime // ignore: cast_nullable_to_non_nullable
as Anime,recommendations: null == recommendations ? _self.recommendations : recommendations // ignore: cast_nullable_to_non_nullable
as (bool, List<Anime>),animeProgress: null == animeProgress ? _self.animeProgress : animeProgress // ignore: cast_nullable_to_non_nullable
as AnimeProgress,effects: null == effects ? _self.effects : effects // ignore: cast_nullable_to_non_nullable
as Anime,progress: null == progress ? _self.progress : progress // ignore: cast_nullable_to_non_nullable
as int,score: null == score ? _self.score : score // ignore: cast_nullable_to_non_nullable
as int,repeat: null == repeat ? _self.repeat : repeat // ignore: cast_nullable_to_non_nullable
as int,characters: null == characters ? _self.characters : characters // ignore: cast_nullable_to_non_nullable
as (bool, List<MediaCharacter>),recommendations: null == recommendations ? _self.recommendations : recommendations // ignore: cast_nullable_to_non_nullable
as (bool, List<Anime>),effects: null == effects ? _self.effects : effects // ignore: cast_nullable_to_non_nullable
as List<AppEffect>,
));
}
@@ -158,10 +160,10 @@ return $default(_that);case _:
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( User loggedUser, MediaList selectedMediaList, Anime selectedAnime, (bool, List<Anime>) recommendations, AnimeProgress animeProgress, List<AppEffect> effects)? $default,{required TResult orElse(),}) {final _that = this;
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( User loggedUser, MediaList selectedMediaList, Anime selectedAnime, int progress, int score, int repeat, (bool, List<MediaCharacter>) characters, (bool, List<Anime>) recommendations, List<AppEffect> effects)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _AnimeDetailsState() when $default != null:
return $default(_that.loggedUser,_that.selectedMediaList,_that.selectedAnime,_that.recommendations,_that.animeProgress,_that.effects);case _:
return $default(_that.loggedUser,_that.selectedMediaList,_that.selectedAnime,_that.progress,_that.score,_that.repeat,_that.characters,_that.recommendations,_that.effects);case _:
return orElse();
}
@@ -179,10 +181,10 @@ return $default(_that.loggedUser,_that.selectedMediaList,_that.selectedAnime,_th
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( User loggedUser, MediaList selectedMediaList, Anime selectedAnime, (bool, List<Anime>) recommendations, AnimeProgress animeProgress, List<AppEffect> effects) $default,) {final _that = this;
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( User loggedUser, MediaList selectedMediaList, Anime selectedAnime, int progress, int score, int repeat, (bool, List<MediaCharacter>) characters, (bool, List<Anime>) recommendations, List<AppEffect> effects) $default,) {final _that = this;
switch (_that) {
case _AnimeDetailsState():
return $default(_that.loggedUser,_that.selectedMediaList,_that.selectedAnime,_that.recommendations,_that.animeProgress,_that.effects);case _:
return $default(_that.loggedUser,_that.selectedMediaList,_that.selectedAnime,_that.progress,_that.score,_that.repeat,_that.characters,_that.recommendations,_that.effects);case _:
throw StateError('Unexpected subclass');
}
@@ -199,10 +201,10 @@ return $default(_that.loggedUser,_that.selectedMediaList,_that.selectedAnime,_th
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( User loggedUser, MediaList selectedMediaList, Anime selectedAnime, (bool, List<Anime>) recommendations, AnimeProgress animeProgress, List<AppEffect> effects)? $default,) {final _that = this;
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( User loggedUser, MediaList selectedMediaList, Anime selectedAnime, int progress, int score, int repeat, (bool, List<MediaCharacter>) characters, (bool, List<Anime>) recommendations, List<AppEffect> effects)? $default,) {final _that = this;
switch (_that) {
case _AnimeDetailsState() when $default != null:
return $default(_that.loggedUser,_that.selectedMediaList,_that.selectedAnime,_that.recommendations,_that.animeProgress,_that.effects);case _:
return $default(_that.loggedUser,_that.selectedMediaList,_that.selectedAnime,_that.progress,_that.score,_that.repeat,_that.characters,_that.recommendations,_that.effects);case _:
return null;
}
@@ -214,18 +216,22 @@ return $default(_that.loggedUser,_that.selectedMediaList,_that.selectedAnime,_th
class _AnimeDetailsState extends AnimeDetailsState {
const _AnimeDetailsState({required this.loggedUser, required this.selectedMediaList, required this.selectedAnime, required this.recommendations, required this.animeProgress, final List<AppEffect> effects = const <AppEffect>[]}): _effects = effects,super._();
const _AnimeDetailsState({required this.loggedUser, required this.selectedMediaList, required this.selectedAnime, required this.progress, required this.score, required this.repeat, required this.characters, required this.recommendations, final List<AppEffect> effects = const <AppEffect>[]}): _effects = effects,super._();
@override final User loggedUser;
@override final MediaList selectedMediaList;
@override final Anime selectedAnime;
// relations
// characters
// voice actors
@override final int progress;
@override final int score;
@override final int repeat;
@override final (bool, List<MediaCharacter>) characters;
@override final (bool, List<Anime>) recommendations;
@override final AnimeProgress animeProgress;
// relations
// voice actors
final List<AppEffect> _effects;
// relations
// voice actors
@override@JsonKey() List<AppEffect> get effects {
if (_effects is EqualUnmodifiableListView) return _effects;
// ignore: implicit_dynamic_type
@@ -243,16 +249,16 @@ _$AnimeDetailsStateCopyWith<_AnimeDetailsState> get copyWith => __$AnimeDetailsS
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AnimeDetailsState&&(identical(other.loggedUser, loggedUser) || other.loggedUser == loggedUser)&&(identical(other.selectedMediaList, selectedMediaList) || other.selectedMediaList == selectedMediaList)&&(identical(other.selectedAnime, selectedAnime) || other.selectedAnime == selectedAnime)&&(identical(other.recommendations, recommendations) || other.recommendations == recommendations)&&(identical(other.animeProgress, animeProgress) || other.animeProgress == animeProgress)&&const DeepCollectionEquality().equals(other._effects, _effects));
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AnimeDetailsState&&(identical(other.loggedUser, loggedUser) || other.loggedUser == loggedUser)&&(identical(other.selectedMediaList, selectedMediaList) || other.selectedMediaList == selectedMediaList)&&(identical(other.selectedAnime, selectedAnime) || other.selectedAnime == selectedAnime)&&(identical(other.progress, progress) || other.progress == progress)&&(identical(other.score, score) || other.score == score)&&(identical(other.repeat, repeat) || other.repeat == repeat)&&(identical(other.characters, characters) || other.characters == characters)&&(identical(other.recommendations, recommendations) || other.recommendations == recommendations)&&const DeepCollectionEquality().equals(other._effects, _effects));
}
@override
int get hashCode => Object.hash(runtimeType,loggedUser,selectedMediaList,selectedAnime,recommendations,animeProgress,const DeepCollectionEquality().hash(_effects));
int get hashCode => Object.hash(runtimeType,loggedUser,selectedMediaList,selectedAnime,progress,score,repeat,characters,recommendations,const DeepCollectionEquality().hash(_effects));
@override
String toString() {
return 'AnimeDetailsState(loggedUser: $loggedUser, selectedMediaList: $selectedMediaList, selectedAnime: $selectedAnime, recommendations: $recommendations, animeProgress: $animeProgress, effects: $effects)';
return 'AnimeDetailsState(loggedUser: $loggedUser, selectedMediaList: $selectedMediaList, selectedAnime: $selectedAnime, progress: $progress, score: $score, repeat: $repeat, characters: $characters, recommendations: $recommendations, effects: $effects)';
}
@@ -263,7 +269,7 @@ abstract mixin class _$AnimeDetailsStateCopyWith<$Res> implements $AnimeDetailsS
factory _$AnimeDetailsStateCopyWith(_AnimeDetailsState value, $Res Function(_AnimeDetailsState) _then) = __$AnimeDetailsStateCopyWithImpl;
@override @useResult
$Res call({
User loggedUser, MediaList selectedMediaList, Anime selectedAnime, (bool, List<Anime>) recommendations, AnimeProgress animeProgress, List<AppEffect> effects
User loggedUser, MediaList selectedMediaList, Anime selectedAnime, int progress, int score, int repeat, (bool, List<MediaCharacter>) characters, (bool, List<Anime>) recommendations, List<AppEffect> effects
});
@@ -280,14 +286,17 @@ class __$AnimeDetailsStateCopyWithImpl<$Res>
/// Create a copy of AnimeDetailsState
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? loggedUser = null,Object? selectedMediaList = null,Object? selectedAnime = null,Object? recommendations = null,Object? animeProgress = null,Object? effects = null,}) {
@override @pragma('vm:prefer-inline') $Res call({Object? loggedUser = null,Object? selectedMediaList = null,Object? selectedAnime = null,Object? progress = null,Object? score = null,Object? repeat = null,Object? characters = null,Object? recommendations = null,Object? effects = null,}) {
return _then(_AnimeDetailsState(
loggedUser: null == loggedUser ? _self.loggedUser : loggedUser // ignore: cast_nullable_to_non_nullable
as User,selectedMediaList: null == selectedMediaList ? _self.selectedMediaList : selectedMediaList // ignore: cast_nullable_to_non_nullable
as MediaList,selectedAnime: null == selectedAnime ? _self.selectedAnime : selectedAnime // ignore: cast_nullable_to_non_nullable
as Anime,recommendations: null == recommendations ? _self.recommendations : recommendations // ignore: cast_nullable_to_non_nullable
as (bool, List<Anime>),animeProgress: null == animeProgress ? _self.animeProgress : animeProgress // ignore: cast_nullable_to_non_nullable
as AnimeProgress,effects: null == effects ? _self._effects : effects // ignore: cast_nullable_to_non_nullable
as Anime,progress: null == progress ? _self.progress : progress // ignore: cast_nullable_to_non_nullable
as int,score: null == score ? _self.score : score // ignore: cast_nullable_to_non_nullable
as int,repeat: null == repeat ? _self.repeat : repeat // ignore: cast_nullable_to_non_nullable
as int,characters: null == characters ? _self.characters : characters // ignore: cast_nullable_to_non_nullable
as (bool, List<MediaCharacter>),recommendations: null == recommendations ? _self.recommendations : recommendations // ignore: cast_nullable_to_non_nullable
as (bool, List<Anime>),effects: null == effects ? _self._effects : effects // ignore: cast_nullable_to_non_nullable
as List<AppEffect>,
));
}

View File

@@ -137,6 +137,7 @@ void setupLocator() {
sl.registerFactory<AnimeDetailsCubit>(
() => AnimeDetailsCubit(
sl<AnimeRepositoryAnilist>(),
sl<UserNotifier>(instanceName: config.loggedUserNotifier),
sl<AnimeNotifier>(),
sl<MediaListNotifier>()

View File

@@ -0,0 +1,298 @@
import 'package:unyo/generated/json/base/json_field.dart';
import 'package:unyo/generated/json/anime_details_graphql_dto_entity.g.dart';
import 'dart:convert';
export 'package:unyo/generated/json/anime_details_graphql_dto_entity.g.dart';
@JsonSerializable()
class AnimeDetailsGraphqlDtoEntity {
late AnimeDetailsGraphqlDtoData data;
AnimeDetailsGraphqlDtoEntity();
factory AnimeDetailsGraphqlDtoEntity.fromJson(Map<String, dynamic> json) => $AnimeDetailsGraphqlDtoEntityFromJson(json);
Map<String, dynamic> toJson() => $AnimeDetailsGraphqlDtoEntityToJson(this);
@override
String toString() {
return jsonEncode(this);
}
}
@JsonSerializable()
class AnimeDetailsGraphqlDtoData {
@JSONField(name: "MediaList")
late AnimeDetailsGraphqlDtoDataMediaList mediaList;
AnimeDetailsGraphqlDtoData();
factory AnimeDetailsGraphqlDtoData.fromJson(Map<String, dynamic> json) => $AnimeDetailsGraphqlDtoDataFromJson(json);
Map<String, dynamic> toJson() => $AnimeDetailsGraphqlDtoDataToJson(this);
@override
String toString() {
return jsonEncode(this);
}
}
@JsonSerializable()
class AnimeDetailsGraphqlDtoDataMediaList {
late int progress = 0;
late int score = 0;
late int repeat = 0;
late AnimeDetailsGraphqlDtoDataMediaListMedia media;
AnimeDetailsGraphqlDtoDataMediaList();
factory AnimeDetailsGraphqlDtoDataMediaList.fromJson(Map<String, dynamic> json) => $AnimeDetailsGraphqlDtoDataMediaListFromJson(json);
Map<String, dynamic> toJson() => $AnimeDetailsGraphqlDtoDataMediaListToJson(this);
@override
String toString() {
return jsonEncode(this);
}
}
@JsonSerializable()
class AnimeDetailsGraphqlDtoDataMediaListMedia {
late AnimeDetailsGraphqlDtoDataMediaListMediaRecommendations recommendations;
late AnimeDetailsGraphqlDtoDataMediaListMediaCharacters characters;
AnimeDetailsGraphqlDtoDataMediaListMedia();
factory AnimeDetailsGraphqlDtoDataMediaListMedia.fromJson(Map<String, dynamic> json) => $AnimeDetailsGraphqlDtoDataMediaListMediaFromJson(json);
Map<String, dynamic> toJson() => $AnimeDetailsGraphqlDtoDataMediaListMediaToJson(this);
@override
String toString() {
return jsonEncode(this);
}
}
@JsonSerializable()
class AnimeDetailsGraphqlDtoDataMediaListMediaRecommendations {
late List<AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodes> nodes = [];
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendations();
factory AnimeDetailsGraphqlDtoDataMediaListMediaRecommendations.fromJson(Map<String, dynamic> json) => $AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsFromJson(json);
Map<String, dynamic> toJson() => $AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsToJson(this);
@override
String toString() {
return jsonEncode(this);
}
}
@JsonSerializable()
class AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodes {
late AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation mediaRecommendation;
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodes();
factory AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodes.fromJson(Map<String, dynamic> json) => $AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesFromJson(json);
Map<String, dynamic> toJson() => $AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesToJson(this);
@override
String toString() {
return jsonEncode(this);
}
}
@JsonSerializable()
class AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation {
late int id = 0;
late int idMal = 0;
late AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationStartDate startDate;
late AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationEndDate endDate;
late String season = '';
late String status = '';
late bool isFavourite = false;
late bool isAdult = false;
late int episodes = 0;
late AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationTitle title;
late String bannerImage = '';
late AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationCoverImage coverImage;
late int averageScore = 0;
late int duration = 0;
late String format = '';
late List<String> genres = [];
late String description = '';
late int meanScore = 0;
dynamic nextAiringEpisode;
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation();
factory AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation.fromJson(Map<String, dynamic> json) => $AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationFromJson(json);
Map<String, dynamic> toJson() => $AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationToJson(this);
@override
String toString() {
return jsonEncode(this);
}
}
@JsonSerializable()
class AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationStartDate {
late int day = 0;
late int month = 0;
late int year = 0;
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationStartDate();
factory AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationStartDate.fromJson(Map<String, dynamic> json) => $AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationStartDateFromJson(json);
Map<String, dynamic> toJson() => $AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationStartDateToJson(this);
@override
String toString() {
return jsonEncode(this);
}
}
@JsonSerializable()
class AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationEndDate {
late int day = 0;
late int month = 0;
late int year = 0;
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationEndDate();
factory AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationEndDate.fromJson(Map<String, dynamic> json) => $AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationEndDateFromJson(json);
Map<String, dynamic> toJson() => $AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationEndDateToJson(this);
@override
String toString() {
return jsonEncode(this);
}
}
@JsonSerializable()
class AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationTitle {
late String english = '';
late String native = '';
late String romaji = '';
late String userPreferred = '';
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationTitle();
factory AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationTitle.fromJson(Map<String, dynamic> json) => $AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationTitleFromJson(json);
Map<String, dynamic> toJson() => $AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationTitleToJson(this);
@override
String toString() {
return jsonEncode(this);
}
}
@JsonSerializable()
class AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationCoverImage {
late String large = '';
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationCoverImage();
factory AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationCoverImage.fromJson(Map<String, dynamic> json) => $AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationCoverImageFromJson(json);
Map<String, dynamic> toJson() => $AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationCoverImageToJson(this);
@override
String toString() {
return jsonEncode(this);
}
}
@JsonSerializable()
class AnimeDetailsGraphqlDtoDataMediaListMediaCharacters {
late List<AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodes> nodes = [];
AnimeDetailsGraphqlDtoDataMediaListMediaCharacters();
factory AnimeDetailsGraphqlDtoDataMediaListMediaCharacters.fromJson(Map<String, dynamic> json) => $AnimeDetailsGraphqlDtoDataMediaListMediaCharactersFromJson(json);
Map<String, dynamic> toJson() => $AnimeDetailsGraphqlDtoDataMediaListMediaCharactersToJson(this);
@override
String toString() {
return jsonEncode(this);
}
}
@JsonSerializable()
class AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodes {
late int id = 0;
late AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesImage image;
late AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesName name;
late String gender = '';
late String description = '';
late AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesDateOfBirth dateOfBirth;
late String age = '';
AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodes();
factory AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodes.fromJson(Map<String, dynamic> json) => $AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesFromJson(json);
Map<String, dynamic> toJson() => $AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesToJson(this);
@override
String toString() {
return jsonEncode(this);
}
}
@JsonSerializable()
class AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesImage {
late String large = '';
AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesImage();
factory AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesImage.fromJson(Map<String, dynamic> json) => $AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesImageFromJson(json);
Map<String, dynamic> toJson() => $AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesImageToJson(this);
@override
String toString() {
return jsonEncode(this);
}
}
@JsonSerializable()
class AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesName {
late String userPreferred = '';
AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesName();
factory AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesName.fromJson(Map<String, dynamic> json) => $AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesNameFromJson(json);
Map<String, dynamic> toJson() => $AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesNameToJson(this);
@override
String toString() {
return jsonEncode(this);
}
}
@JsonSerializable()
class AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesDateOfBirth {
dynamic day;
dynamic month;
dynamic year;
AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesDateOfBirth();
factory AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesDateOfBirth.fromJson(Map<String, dynamic> json) => $AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesDateOfBirthFromJson(json);
Map<String, dynamic> toJson() => $AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesDateOfBirthToJson(this);
@override
String toString() {
return jsonEncode(this);
}
}

View File

@@ -362,4 +362,86 @@ query Page(\$sort: [AiringSort], \$page: Int, \$perPage: Int, \$airingAtGreater:
}
}
}
''';
// {
// "userId": 859862,
// "type": "ANIME",
// "mediaId": 1735,
// "page" : 1,
// "perPage": 20,
// "sort": "RELEVANCE"
// }
const animeDetailsQuery = '''
query Page(\$userId: Int, \$type: MediaType, \$mediaId: Int, \$page: Int, \$perPage: Int) {
MediaList(userId: \$userId, type: \$type, mediaId: \$mediaId) {
progress
score
repeat
media {
recommendations(page: \$page, perPage: \$perPage) {
nodes {
mediaRecommendation {
id
idMal
startDate {
day
month
year
}
endDate {
day
month
year
}
season
status
isFavourite
isAdult
episodes
title {
english
native
romaji
userPreferred
}
bannerImage
coverImage {
large
}
averageScore
duration
format
genres
description
meanScore
nextAiringEpisode {
episode
airingAt
}
}
}
}
characters {
nodes {
id
image {
large
}
name {
userPreferred
}
gender
description
dateOfBirth {
day
month
year
}
age
}
}
}
}
}
''';

View File

@@ -2,5 +2,5 @@ const localUserModelAdapterName = 'LocalUserModelAdapter';
const anilistUserModelAdapterName = 'AnilistUserModelAdapter';
const settingsModelAdapterName = 'SettingsModelAdapter';
const serviceEnumAdapterName = 'ServiceEnumAdapter';
const animeProgressModelAdapterName = 'AnimeProgressModelAdapter';
const anilistAnimeDetailsModelAdapterName = 'AnimeProgressModelAdapter';
const mediaListModelAdapterName = 'MediaListModelAdapter';

View File

@@ -2,5 +2,5 @@ const anilistUserAdapterType = 0;
const localUserAdapterType = 1;
const settingsAdapterType = 2;
const serviceAdapterType = 3;
const animeProgressAdapterType = 4;
const anilistAnimeDetailsAdapterType = 4;
const mediaListAdapterType = 5;

View File

@@ -0,0 +1,76 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:hive_ce/hive.dart';
import 'package:unyo/core/services/api/dto/anime_details_graphql_dto_entity.dart';
import 'package:unyo/data/adapters/adapters_names.dart' as names;
import 'package:unyo/data/adapters/adapters_types.dart' as types;
import 'package:unyo/data/models/anilist_anime_model.dart';
import 'package:unyo/data/models/anilist_media_character.dart';
import 'package:unyo/domain/entities/anime.dart';
import 'package:unyo/domain/entities/anime_details.dart';
import 'package:unyo/domain/entities/media_character.dart';
part 'anilist_anime_details.freezed.dart';
part 'anilist_anime_details.g.dart';
@freezed
@HiveType(
typeId: types.anilistAnimeDetailsAdapterType,
adapterName: names.anilistAnimeDetailsModelAdapterName,
)
abstract class AnilistAnimeDetailsModel
with _$AnilistAnimeDetailsModel
implements AnimeDetails {
const factory AnilistAnimeDetailsModel({
@HiveField(0) required int progress,
@HiveField(1) required int score,
@HiveField(2) required int repeat,
@HiveField(3) @AnimeConverter() required List<Anime> recommendedAnimes,
@HiveField(4)
@MediaCharacterConverter()
required List<MediaCharacter> characters,
}) = _AnilistAnimeDetailsModel;
factory AnilistAnimeDetailsModel.empty() => const AnilistAnimeDetailsModel(
progress: 0,
score: 0,
repeat: 0,
recommendedAnimes: [],
characters: [],
);
factory AnilistAnimeDetailsModel.fromJson(Map<String, dynamic> json) =>
_$AnilistAnimeDetailsModelFromJson(json);
@override
Map<String, dynamic> toJson() =>
_$AnilistAnimeDetailsModelToJson(this as _AnilistAnimeDetailsModel);
factory AnilistAnimeDetailsModel.fromAnimeDetailsMediaList(
AnimeDetailsGraphqlDtoDataMediaList animeDetailsMediaList,
) {
return AnilistAnimeDetailsModel(
progress: animeDetailsMediaList.progress,
score: animeDetailsMediaList.score,
repeat: animeDetailsMediaList.repeat,
recommendedAnimes:
animeDetailsMediaList.media.recommendations.nodes
.map(
(recommendationNode) =>
AnilistAnimeModel.fromMediaRecommendationNode(
recommendationNode.mediaRecommendation,
)
as Anime,
)
.toList(),
characters:
animeDetailsMediaList.media.characters.nodes
.map(
(characterNode) =>
AnilistMediaCharacterModel.fromCharacterNode(characterNode)
as MediaCharacter,
)
.toList(),
);
}
}

View File

@@ -0,0 +1,301 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// coverage:ignore-file
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'anilist_anime_details.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$AnilistAnimeDetailsModel {
@HiveField(0) int get progress;@HiveField(1) int get score;@HiveField(2) int get repeat;@HiveField(3)@AnimeConverter() List<Anime> get recommendedAnimes;@HiveField(4)@MediaCharacterConverter() List<MediaCharacter> get characters;
/// Create a copy of AnilistAnimeDetailsModel
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$AnilistAnimeDetailsModelCopyWith<AnilistAnimeDetailsModel> get copyWith => _$AnilistAnimeDetailsModelCopyWithImpl<AnilistAnimeDetailsModel>(this as AnilistAnimeDetailsModel, _$identity);
/// Serializes this AnilistAnimeDetailsModel to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is AnilistAnimeDetailsModel&&(identical(other.progress, progress) || other.progress == progress)&&(identical(other.score, score) || other.score == score)&&(identical(other.repeat, repeat) || other.repeat == repeat)&&const DeepCollectionEquality().equals(other.recommendedAnimes, recommendedAnimes)&&const DeepCollectionEquality().equals(other.characters, characters));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,progress,score,repeat,const DeepCollectionEquality().hash(recommendedAnimes),const DeepCollectionEquality().hash(characters));
@override
String toString() {
return 'AnilistAnimeDetailsModel(progress: $progress, score: $score, repeat: $repeat, recommendedAnimes: $recommendedAnimes, characters: $characters)';
}
}
/// @nodoc
abstract mixin class $AnilistAnimeDetailsModelCopyWith<$Res> {
factory $AnilistAnimeDetailsModelCopyWith(AnilistAnimeDetailsModel value, $Res Function(AnilistAnimeDetailsModel) _then) = _$AnilistAnimeDetailsModelCopyWithImpl;
@useResult
$Res call({
@HiveField(0) int progress,@HiveField(1) int score,@HiveField(2) int repeat,@HiveField(3)@AnimeConverter() List<Anime> recommendedAnimes,@HiveField(4)@MediaCharacterConverter() List<MediaCharacter> characters
});
}
/// @nodoc
class _$AnilistAnimeDetailsModelCopyWithImpl<$Res>
implements $AnilistAnimeDetailsModelCopyWith<$Res> {
_$AnilistAnimeDetailsModelCopyWithImpl(this._self, this._then);
final AnilistAnimeDetailsModel _self;
final $Res Function(AnilistAnimeDetailsModel) _then;
/// Create a copy of AnilistAnimeDetailsModel
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? progress = null,Object? score = null,Object? repeat = null,Object? recommendedAnimes = null,Object? characters = null,}) {
return _then(_self.copyWith(
progress: null == progress ? _self.progress : progress // ignore: cast_nullable_to_non_nullable
as int,score: null == score ? _self.score : score // ignore: cast_nullable_to_non_nullable
as int,repeat: null == repeat ? _self.repeat : repeat // ignore: cast_nullable_to_non_nullable
as int,recommendedAnimes: null == recommendedAnimes ? _self.recommendedAnimes : recommendedAnimes // ignore: cast_nullable_to_non_nullable
as List<Anime>,characters: null == characters ? _self.characters : characters // ignore: cast_nullable_to_non_nullable
as List<MediaCharacter>,
));
}
}
/// Adds pattern-matching-related methods to [AnilistAnimeDetailsModel].
extension AnilistAnimeDetailsModelPatterns on AnilistAnimeDetailsModel {
/// A variant of `map` that fallback to returning `orElse`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _AnilistAnimeDetailsModel value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _AnilistAnimeDetailsModel() when $default != null:
return $default(_that);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case final Subclass2 value:
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _AnilistAnimeDetailsModel value) $default,){
final _that = this;
switch (_that) {
case _AnilistAnimeDetailsModel():
return $default(_that);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _AnilistAnimeDetailsModel value)? $default,){
final _that = this;
switch (_that) {
case _AnilistAnimeDetailsModel() when $default != null:
return $default(_that);case _:
return null;
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function(@HiveField(0) int progress, @HiveField(1) int score, @HiveField(2) int repeat, @HiveField(3)@AnimeConverter() List<Anime> recommendedAnimes, @HiveField(4)@MediaCharacterConverter() List<MediaCharacter> characters)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _AnilistAnimeDetailsModel() when $default != null:
return $default(_that.progress,_that.score,_that.repeat,_that.recommendedAnimes,_that.characters);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case Subclass2(:final field2):
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function(@HiveField(0) int progress, @HiveField(1) int score, @HiveField(2) int repeat, @HiveField(3)@AnimeConverter() List<Anime> recommendedAnimes, @HiveField(4)@MediaCharacterConverter() List<MediaCharacter> characters) $default,) {final _that = this;
switch (_that) {
case _AnilistAnimeDetailsModel():
return $default(_that.progress,_that.score,_that.repeat,_that.recommendedAnimes,_that.characters);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function(@HiveField(0) int progress, @HiveField(1) int score, @HiveField(2) int repeat, @HiveField(3)@AnimeConverter() List<Anime> recommendedAnimes, @HiveField(4)@MediaCharacterConverter() List<MediaCharacter> characters)? $default,) {final _that = this;
switch (_that) {
case _AnilistAnimeDetailsModel() when $default != null:
return $default(_that.progress,_that.score,_that.repeat,_that.recommendedAnimes,_that.characters);case _:
return null;
}
}
}
/// @nodoc
@JsonSerializable()
class _AnilistAnimeDetailsModel implements AnilistAnimeDetailsModel {
const _AnilistAnimeDetailsModel({@HiveField(0) required this.progress, @HiveField(1) required this.score, @HiveField(2) required this.repeat, @HiveField(3)@AnimeConverter() required final List<Anime> recommendedAnimes, @HiveField(4)@MediaCharacterConverter() required final List<MediaCharacter> characters}): _recommendedAnimes = recommendedAnimes,_characters = characters;
factory _AnilistAnimeDetailsModel.fromJson(Map<String, dynamic> json) => _$AnilistAnimeDetailsModelFromJson(json);
@override@HiveField(0) final int progress;
@override@HiveField(1) final int score;
@override@HiveField(2) final int repeat;
final List<Anime> _recommendedAnimes;
@override@HiveField(3)@AnimeConverter() List<Anime> get recommendedAnimes {
if (_recommendedAnimes is EqualUnmodifiableListView) return _recommendedAnimes;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_recommendedAnimes);
}
final List<MediaCharacter> _characters;
@override@HiveField(4)@MediaCharacterConverter() List<MediaCharacter> get characters {
if (_characters is EqualUnmodifiableListView) return _characters;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_characters);
}
/// Create a copy of AnilistAnimeDetailsModel
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$AnilistAnimeDetailsModelCopyWith<_AnilistAnimeDetailsModel> get copyWith => __$AnilistAnimeDetailsModelCopyWithImpl<_AnilistAnimeDetailsModel>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$AnilistAnimeDetailsModelToJson(this, );
}
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AnilistAnimeDetailsModel&&(identical(other.progress, progress) || other.progress == progress)&&(identical(other.score, score) || other.score == score)&&(identical(other.repeat, repeat) || other.repeat == repeat)&&const DeepCollectionEquality().equals(other._recommendedAnimes, _recommendedAnimes)&&const DeepCollectionEquality().equals(other._characters, _characters));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,progress,score,repeat,const DeepCollectionEquality().hash(_recommendedAnimes),const DeepCollectionEquality().hash(_characters));
@override
String toString() {
return 'AnilistAnimeDetailsModel(progress: $progress, score: $score, repeat: $repeat, recommendedAnimes: $recommendedAnimes, characters: $characters)';
}
}
/// @nodoc
abstract mixin class _$AnilistAnimeDetailsModelCopyWith<$Res> implements $AnilistAnimeDetailsModelCopyWith<$Res> {
factory _$AnilistAnimeDetailsModelCopyWith(_AnilistAnimeDetailsModel value, $Res Function(_AnilistAnimeDetailsModel) _then) = __$AnilistAnimeDetailsModelCopyWithImpl;
@override @useResult
$Res call({
@HiveField(0) int progress,@HiveField(1) int score,@HiveField(2) int repeat,@HiveField(3)@AnimeConverter() List<Anime> recommendedAnimes,@HiveField(4)@MediaCharacterConverter() List<MediaCharacter> characters
});
}
/// @nodoc
class __$AnilistAnimeDetailsModelCopyWithImpl<$Res>
implements _$AnilistAnimeDetailsModelCopyWith<$Res> {
__$AnilistAnimeDetailsModelCopyWithImpl(this._self, this._then);
final _AnilistAnimeDetailsModel _self;
final $Res Function(_AnilistAnimeDetailsModel) _then;
/// Create a copy of AnilistAnimeDetailsModel
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? progress = null,Object? score = null,Object? repeat = null,Object? recommendedAnimes = null,Object? characters = null,}) {
return _then(_AnilistAnimeDetailsModel(
progress: null == progress ? _self.progress : progress // ignore: cast_nullable_to_non_nullable
as int,score: null == score ? _self.score : score // ignore: cast_nullable_to_non_nullable
as int,repeat: null == repeat ? _self.repeat : repeat // ignore: cast_nullable_to_non_nullable
as int,recommendedAnimes: null == recommendedAnimes ? _self._recommendedAnimes : recommendedAnimes // ignore: cast_nullable_to_non_nullable
as List<Anime>,characters: null == characters ? _self._characters : characters // ignore: cast_nullable_to_non_nullable
as List<MediaCharacter>,
));
}
}
// dart format on

View File

@@ -0,0 +1,91 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'anilist_anime_details.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class AnimeProgressModelAdapter extends TypeAdapter<AnilistAnimeDetailsModel> {
@override
final typeId = 4;
@override
AnilistAnimeDetailsModel read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return AnilistAnimeDetailsModel(
progress: (fields[0] as num).toInt(),
score: (fields[1] as num).toInt(),
repeat: (fields[2] as num).toInt(),
recommendedAnimes: (fields[3] as List).cast<Anime>(),
characters: (fields[4] as List).cast<MediaCharacter>(),
);
}
@override
void write(BinaryWriter writer, AnilistAnimeDetailsModel obj) {
writer
..writeByte(5)
..writeByte(0)
..write(obj.progress)
..writeByte(1)
..write(obj.score)
..writeByte(2)
..write(obj.repeat)
..writeByte(3)
..write(obj.recommendedAnimes)
..writeByte(4)
..write(obj.characters);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is AnimeProgressModelAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_AnilistAnimeDetailsModel _$AnilistAnimeDetailsModelFromJson(
Map<String, dynamic> json,
) => _AnilistAnimeDetailsModel(
progress: (json['progress'] as num).toInt(),
score: (json['score'] as num).toInt(),
repeat: (json['repeat'] as num).toInt(),
recommendedAnimes:
(json['recommendedAnimes'] as List<dynamic>)
.map(
(e) => const AnimeConverter().fromJson(e as Map<String, dynamic>),
)
.toList(),
characters:
(json['characters'] as List<dynamic>)
.map(
(e) => const MediaCharacterConverter().fromJson(
e as Map<String, dynamic>,
),
)
.toList(),
);
Map<String, dynamic> _$AnilistAnimeDetailsModelToJson(
_AnilistAnimeDetailsModel instance,
) => <String, dynamic>{
'progress': instance.progress,
'score': instance.score,
'repeat': instance.repeat,
'recommendedAnimes':
instance.recommendedAnimes.map(const AnimeConverter().toJson).toList(),
'characters':
instance.characters.map(const MediaCharacterConverter().toJson).toList(),
};

View File

@@ -1,6 +1,7 @@
// External dependencies
import 'package:freezed_annotation/freezed_annotation.dart';
// Internal dependencies
import 'package:unyo/core/services/api/dto/anime_details_graphql_dto_entity.dart';
import 'package:unyo/core/services/api/dto/media_collection_graphql_dto_entity.dart';
import 'package:unyo/core/services/api/dto/media_collection_recently_completed_graphql_dto_entity.dart';
import 'package:unyo/core/services/api/dto/media_collection_recently_released_graphql_dto_entity.dart';
@@ -45,9 +46,8 @@ abstract class AnilistAnimeModel with _$AnilistAnimeModel implements Anime {
_$AnilistAnimeModelFromJson(json);
factory AnilistAnimeModel.fromUserMediaEntry(
MediaCollectionGraphqlDtoDataMediaListCollectionListsEntriesMedia
mediaEntry,
) {
MediaCollectionGraphqlDtoDataMediaListCollectionListsEntriesMedia
mediaEntry,) {
return AnilistAnimeModel(
id: mediaEntry.id,
idMal: mediaEntry.idMal,
@@ -64,9 +64,11 @@ abstract class AnilistAnimeModel with _$AnilistAnimeModel implements Anime {
description: mediaEntry.description,
duration: mediaEntry.duration,
endDate:
"${mediaEntry.endDate.day}/${mediaEntry.endDate.month}/${mediaEntry.endDate.year}",
"${mediaEntry.endDate.day}/${mediaEntry.endDate.month}/${mediaEntry
.endDate.year}",
startDate:
"${mediaEntry.startDate.day}/${mediaEntry.startDate.month}/${mediaEntry.startDate.year}",
"${mediaEntry.startDate.day}/${mediaEntry.startDate.month}/${mediaEntry
.startDate.year}",
episodes: mediaEntry.episodes,
genres: mediaEntry.genres,
format: mediaEntry.format,
@@ -85,8 +87,7 @@ abstract class AnilistAnimeModel with _$AnilistAnimeModel implements Anime {
factory AnilistAnimeModel.fromScheduleEntry(
MediaCollectionRecentlyReleasedGraphqlDtoPageAiringSchedules
schedule,
) {
schedule,) {
return AnilistAnimeModel(
id: schedule.media.id,
idMal: schedule.media.idMal,
@@ -103,9 +104,11 @@ abstract class AnilistAnimeModel with _$AnilistAnimeModel implements Anime {
description: schedule.media.description,
duration: schedule.media.duration,
endDate:
"${schedule.media.endDate.day}/${schedule.media.endDate.month}/${schedule.media.endDate.year}",
"${schedule.media.endDate.day}/${schedule.media.endDate.month}/${schedule
.media.endDate.year}",
startDate:
"${schedule.media.startDate.day}/${schedule.media.startDate.month}/${schedule.media.startDate.year}",
"${schedule.media.startDate.day}/${schedule.media.startDate
.month}/${schedule.media.startDate.year}",
episodes: schedule.media.episodes,
genres: schedule.media.genres,
format: schedule.media.format,
@@ -124,8 +127,7 @@ abstract class AnilistAnimeModel with _$AnilistAnimeModel implements Anime {
factory AnilistAnimeModel.fromPopularOrTrendingMediaEntry(
MediaCollectionTrendingOrPopularGraphqlDtoPageMedia
mediaEntry,
) {
mediaEntry,) {
return AnilistAnimeModel(
id: mediaEntry.id,
idMal: mediaEntry.idMal,
@@ -142,9 +144,11 @@ abstract class AnilistAnimeModel with _$AnilistAnimeModel implements Anime {
description: mediaEntry.description,
duration: mediaEntry.duration,
endDate:
"${mediaEntry.endDate.day}/${mediaEntry.endDate.month}/${mediaEntry.endDate.year}",
"${mediaEntry.endDate.day}/${mediaEntry.endDate.month}/${mediaEntry
.endDate.year}",
startDate:
"${mediaEntry.startDate.day}/${mediaEntry.startDate.month}/${mediaEntry.startDate.year}",
"${mediaEntry.startDate.day}/${mediaEntry.startDate.month}/${mediaEntry
.startDate.year}",
episodes: mediaEntry.episodes,
genres: mediaEntry.genres,
format: mediaEntry.format,
@@ -163,8 +167,7 @@ abstract class AnilistAnimeModel with _$AnilistAnimeModel implements Anime {
factory AnilistAnimeModel.fromRecentlyCompletedMediaEntry(
MediaCollectionRecentlyCompletedGraphqlDtoPageMedia
mediaEntry,
) {
mediaEntry,) {
return AnilistAnimeModel(
id: mediaEntry.id,
idMal: mediaEntry.idMal,
@@ -181,9 +184,11 @@ abstract class AnilistAnimeModel with _$AnilistAnimeModel implements Anime {
description: mediaEntry.description,
duration: mediaEntry.duration,
endDate:
"${mediaEntry.endDate.day}/${mediaEntry.endDate.month}/${mediaEntry.endDate.year}",
"${mediaEntry.endDate.day}/${mediaEntry.endDate.month}/${mediaEntry
.endDate.year}",
startDate:
"${mediaEntry.startDate.day}/${mediaEntry.startDate.month}/${mediaEntry.startDate.year}",
"${mediaEntry.startDate.day}/${mediaEntry.startDate.month}/${mediaEntry
.startDate.year}",
episodes: mediaEntry.episodes,
genres: mediaEntry.genres,
format: mediaEntry.format,
@@ -202,8 +207,7 @@ abstract class AnilistAnimeModel with _$AnilistAnimeModel implements Anime {
factory AnilistAnimeModel.fromUpcomingMediaEntry(
MediaCollectionUpcomingGraphqlDtoPageMedia
mediaEntry,
) {
mediaEntry,) {
return AnilistAnimeModel(
id: mediaEntry.id,
idMal: mediaEntry.idMal,
@@ -220,9 +224,11 @@ abstract class AnilistAnimeModel with _$AnilistAnimeModel implements Anime {
description: mediaEntry.description,
duration: mediaEntry.duration,
endDate:
"${mediaEntry.endDate.day}/${mediaEntry.endDate.month}/${mediaEntry.endDate.year}",
"${mediaEntry.endDate.day}/${mediaEntry.endDate.month}/${mediaEntry
.endDate.year}",
startDate:
"${mediaEntry.startDate.day}/${mediaEntry.startDate.month}/${mediaEntry.startDate.year}",
"${mediaEntry.startDate.day}/${mediaEntry.startDate.month}/${mediaEntry
.startDate.year}",
episodes: mediaEntry.episodes,
genres: mediaEntry.genres,
format: mediaEntry.format,
@@ -239,6 +245,39 @@ abstract class AnilistAnimeModel with _$AnilistAnimeModel implements Anime {
);
}
factory AnilistAnimeModel.fromMediaRecommendationNode(
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation mediaRecommendation) {
return AnilistAnimeModel(
id: mediaRecommendation.id,
idMal: mediaRecommendation.idMal,
title: TitleModel(romaji: mediaRecommendation.title.romaji,
english: mediaRecommendation.title.english,
nativeTitle: mediaRecommendation.title.native,
userPreferred: mediaRecommendation.title.userPreferred),
averageScore: mediaRecommendation.averageScore,
bannerImage: mediaRecommendation.bannerImage,
countryOfOrigin: "Unimplemented",
coverImage: mediaRecommendation.coverImage.large,
description: mediaRecommendation.description,
duration: mediaRecommendation.duration,
endDate: "${mediaRecommendation.endDate.day}/${mediaRecommendation.endDate.month}/${mediaRecommendation.endDate.year}",
startDate: "${mediaRecommendation.startDate.day}/${mediaRecommendation.startDate.month}/${mediaRecommendation.startDate.year}",
episodes: mediaRecommendation.episodes,
genres: mediaRecommendation.genres,
format: mediaRecommendation.format,
isAdult: mediaRecommendation.isAdult,
popularity: -1,
meanScore: mediaRecommendation.meanScore,
season: mediaRecommendation.season,
status: mediaRecommendation.status,
isFavourite: mediaRecommendation.isFavourite,
nextAiringEpisode: AiringEpisodeModel(
episode: mediaRecommendation.nextAiringEpisode?['episode'] ?? 0,
airingAt: mediaRecommendation.nextAiringEpisode?['airingAt'].toString() ?? "",
),
);
}
@override
Map<String, dynamic> toJson() =>
_$AnilistAnimeModelToJson(this as _AnilistAnimeModel);

View File

@@ -0,0 +1,53 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:unyo/core/services/api/dto/anime_details_graphql_dto_entity.dart' show AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodes;
import 'package:unyo/domain/entities/media_character.dart';
part 'anilist_media_character.freezed.dart';
part 'anilist_media_character.g.dart';
@freezed
abstract class AnilistMediaCharacterModel
with _$AnilistMediaCharacterModel
implements MediaCharacter {
const factory AnilistMediaCharacterModel({
required int id,
required String image,
required String name,
required String gender,
required String description,
required String dateOfBirth,
required int age
}) = _AnilistMediaCharacterModel;
factory AnilistMediaCharacterModel.empty() =>
const AnilistMediaCharacterModel(
id: -1,
image: '',
name: '',
gender: '',
description: '',
dateOfBirth: '',
age: 0
);
factory AnilistMediaCharacterModel.fromJson(Map<String, dynamic> json) =>
_$AnilistMediaCharacterModelFromJson(json);
@override
Map<String, dynamic> toJson() =>
_$AnilistMediaCharacterModelToJson(this as _AnilistMediaCharacterModel);
factory AnilistMediaCharacterModel.fromCharacterNode(
AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodes characterNode) {
return AnilistMediaCharacterModel(
id: characterNode.id,
image: characterNode.image.large,
name: characterNode.name.userPreferred,
gender: characterNode.gender,
description: characterNode.description,
dateOfBirth: "${characterNode.dateOfBirth.day}/${characterNode.dateOfBirth.month}/${characterNode.dateOfBirth.year}",
age: int.tryParse(characterNode.age) ?? -1
);
}
}

View File

@@ -0,0 +1,287 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// coverage:ignore-file
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'anilist_media_character.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$AnilistMediaCharacterModel {
int get id; String get image; String get name; String get gender; String get description; String get dateOfBirth; int get age;
/// Create a copy of AnilistMediaCharacterModel
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$AnilistMediaCharacterModelCopyWith<AnilistMediaCharacterModel> get copyWith => _$AnilistMediaCharacterModelCopyWithImpl<AnilistMediaCharacterModel>(this as AnilistMediaCharacterModel, _$identity);
/// Serializes this AnilistMediaCharacterModel to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is AnilistMediaCharacterModel&&(identical(other.id, id) || other.id == id)&&(identical(other.image, image) || other.image == image)&&(identical(other.name, name) || other.name == name)&&(identical(other.gender, gender) || other.gender == gender)&&(identical(other.description, description) || other.description == description)&&(identical(other.dateOfBirth, dateOfBirth) || other.dateOfBirth == dateOfBirth)&&(identical(other.age, age) || other.age == age));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,id,image,name,gender,description,dateOfBirth,age);
}
/// @nodoc
abstract mixin class $AnilistMediaCharacterModelCopyWith<$Res> {
factory $AnilistMediaCharacterModelCopyWith(AnilistMediaCharacterModel value, $Res Function(AnilistMediaCharacterModel) _then) = _$AnilistMediaCharacterModelCopyWithImpl;
@useResult
$Res call({
int id, String image, String name, String gender, String description, String dateOfBirth, int age
});
}
/// @nodoc
class _$AnilistMediaCharacterModelCopyWithImpl<$Res>
implements $AnilistMediaCharacterModelCopyWith<$Res> {
_$AnilistMediaCharacterModelCopyWithImpl(this._self, this._then);
final AnilistMediaCharacterModel _self;
final $Res Function(AnilistMediaCharacterModel) _then;
/// Create a copy of AnilistMediaCharacterModel
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? image = null,Object? name = null,Object? gender = null,Object? description = null,Object? dateOfBirth = null,Object? age = null,}) {
return _then(_self.copyWith(
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
as int,image: null == image ? _self.image : image // ignore: cast_nullable_to_non_nullable
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
as String,gender: null == gender ? _self.gender : gender // ignore: cast_nullable_to_non_nullable
as String,description: null == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
as String,dateOfBirth: null == dateOfBirth ? _self.dateOfBirth : dateOfBirth // ignore: cast_nullable_to_non_nullable
as String,age: null == age ? _self.age : age // ignore: cast_nullable_to_non_nullable
as int,
));
}
}
/// Adds pattern-matching-related methods to [AnilistMediaCharacterModel].
extension AnilistMediaCharacterModelPatterns on AnilistMediaCharacterModel {
/// A variant of `map` that fallback to returning `orElse`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _AnilistMediaCharacterModel value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _AnilistMediaCharacterModel() when $default != null:
return $default(_that);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case final Subclass2 value:
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _AnilistMediaCharacterModel value) $default,){
final _that = this;
switch (_that) {
case _AnilistMediaCharacterModel():
return $default(_that);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _AnilistMediaCharacterModel value)? $default,){
final _that = this;
switch (_that) {
case _AnilistMediaCharacterModel() when $default != null:
return $default(_that);case _:
return null;
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( int id, String image, String name, String gender, String description, String dateOfBirth, int age)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _AnilistMediaCharacterModel() when $default != null:
return $default(_that.id,_that.image,_that.name,_that.gender,_that.description,_that.dateOfBirth,_that.age);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case Subclass2(:final field2):
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( int id, String image, String name, String gender, String description, String dateOfBirth, int age) $default,) {final _that = this;
switch (_that) {
case _AnilistMediaCharacterModel():
return $default(_that.id,_that.image,_that.name,_that.gender,_that.description,_that.dateOfBirth,_that.age);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( int id, String image, String name, String gender, String description, String dateOfBirth, int age)? $default,) {final _that = this;
switch (_that) {
case _AnilistMediaCharacterModel() when $default != null:
return $default(_that.id,_that.image,_that.name,_that.gender,_that.description,_that.dateOfBirth,_that.age);case _:
return null;
}
}
}
/// @nodoc
@JsonSerializable()
class _AnilistMediaCharacterModel implements AnilistMediaCharacterModel {
const _AnilistMediaCharacterModel({required this.id, required this.image, required this.name, required this.gender, required this.description, required this.dateOfBirth, required this.age});
factory _AnilistMediaCharacterModel.fromJson(Map<String, dynamic> json) => _$AnilistMediaCharacterModelFromJson(json);
@override final int id;
@override final String image;
@override final String name;
@override final String gender;
@override final String description;
@override final String dateOfBirth;
@override final int age;
/// Create a copy of AnilistMediaCharacterModel
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$AnilistMediaCharacterModelCopyWith<_AnilistMediaCharacterModel> get copyWith => __$AnilistMediaCharacterModelCopyWithImpl<_AnilistMediaCharacterModel>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$AnilistMediaCharacterModelToJson(this, );
}
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AnilistMediaCharacterModel&&(identical(other.id, id) || other.id == id)&&(identical(other.image, image) || other.image == image)&&(identical(other.name, name) || other.name == name)&&(identical(other.gender, gender) || other.gender == gender)&&(identical(other.description, description) || other.description == description)&&(identical(other.dateOfBirth, dateOfBirth) || other.dateOfBirth == dateOfBirth)&&(identical(other.age, age) || other.age == age));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,id,image,name,gender,description,dateOfBirth,age);
}
/// @nodoc
abstract mixin class _$AnilistMediaCharacterModelCopyWith<$Res> implements $AnilistMediaCharacterModelCopyWith<$Res> {
factory _$AnilistMediaCharacterModelCopyWith(_AnilistMediaCharacterModel value, $Res Function(_AnilistMediaCharacterModel) _then) = __$AnilistMediaCharacterModelCopyWithImpl;
@override @useResult
$Res call({
int id, String image, String name, String gender, String description, String dateOfBirth, int age
});
}
/// @nodoc
class __$AnilistMediaCharacterModelCopyWithImpl<$Res>
implements _$AnilistMediaCharacterModelCopyWith<$Res> {
__$AnilistMediaCharacterModelCopyWithImpl(this._self, this._then);
final _AnilistMediaCharacterModel _self;
final $Res Function(_AnilistMediaCharacterModel) _then;
/// Create a copy of AnilistMediaCharacterModel
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? image = null,Object? name = null,Object? gender = null,Object? description = null,Object? dateOfBirth = null,Object? age = null,}) {
return _then(_AnilistMediaCharacterModel(
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
as int,image: null == image ? _self.image : image // ignore: cast_nullable_to_non_nullable
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
as String,gender: null == gender ? _self.gender : gender // ignore: cast_nullable_to_non_nullable
as String,description: null == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
as String,dateOfBirth: null == dateOfBirth ? _self.dateOfBirth : dateOfBirth // ignore: cast_nullable_to_non_nullable
as String,age: null == age ? _self.age : age // ignore: cast_nullable_to_non_nullable
as int,
));
}
}
// dart format on

View File

@@ -0,0 +1,31 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'anilist_media_character.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_AnilistMediaCharacterModel _$AnilistMediaCharacterModelFromJson(
Map<String, dynamic> json,
) => _AnilistMediaCharacterModel(
id: (json['id'] as num).toInt(),
image: json['image'] as String,
name: json['name'] as String,
gender: json['gender'] as String,
description: json['description'] as String,
dateOfBirth: json['dateOfBirth'] as String,
age: (json['age'] as num).toInt(),
);
Map<String, dynamic> _$AnilistMediaCharacterModelToJson(
_AnilistMediaCharacterModel instance,
) => <String, dynamic>{
'id': instance.id,
'image': instance.image,
'name': instance.name,
'gender': instance.gender,
'description': instance.description,
'dateOfBirth': instance.dateOfBirth,
'age': instance.age,
};

View File

@@ -4,6 +4,7 @@ import 'package:logger/logger.dart';
import 'package:unyo/core/di/locator.dart';
// Internal dependencies
import 'package:unyo/config/config.dart' as config;
import 'package:unyo/core/services/api/dto/anime_details_graphql_dto_entity.dart';
import 'package:unyo/core/services/api/dto/media_collection_recently_completed_graphql_dto_entity.dart';
import 'package:unyo/core/services/api/dto/media_collection_trendingOrPopular_graphql_dto_entity.dart';
import 'package:unyo/core/services/api/dto/media_collection_upcoming_graphql_dto_entity.dart';
@@ -11,9 +12,12 @@ import 'package:unyo/core/services/api/graphql/queries/queries.dart' as queries;
import 'package:unyo/core/services/api/dto/media_collection_recently_released_graphql_dto_entity.dart';
import 'package:unyo/core/services/api/graphql/graphql_response.dart';
import 'package:unyo/core/services/api/graphql/graphql_service.dart';
import 'package:unyo/data/models/anilist_anime_details.dart';
import 'package:unyo/data/models/anilist_anime_model.dart';
import 'package:unyo/data/models/anilist_user_model.dart';
import 'package:unyo/data/repositories/repository_mixin.dart';
import 'package:unyo/domain/entities/anime.dart';
import 'package:unyo/domain/entities/anime_details.dart';
import 'package:unyo/domain/entities/user.dart';
import 'package:unyo/domain/repositories/anime_repository.dart';
@@ -148,7 +152,7 @@ class AnimeRepositoryAnilist with RepositoryMixin implements AnimeRepository {
@override
Future<Map<String, List<Anime>>> getCalendarReleases(int page, User user, {List<Anime>? calendarReleasePortion}) async {
List<Anime> calendarReleasesList = await getCalendarReleasesPage(page);
List<Anime> calendarReleasesList = await _getCalendarReleasesPage(page);
if (calendarReleasesList.length == 50){
// has next page
return await getCalendarReleases(page + 1, user, calendarReleasePortion: [...calendarReleasesList, ...(calendarReleasePortion ?? [])]);
@@ -186,7 +190,31 @@ class AnimeRepositoryAnilist with RepositoryMixin implements AnimeRepository {
return Map.fromEntries(sortedEntries);
}
Future<List<Anime>> getCalendarReleasesPage(int page) async {
@override
Future<(bool, AnimeDetails)> getAnimeDetails(Anime selectedAnime, User user) async{
Map<String, String> graphQlHeaders = {
"Authorization": "Bearer ${(user as AnilistUserModel).accessToken}",
};
ApiGraphQLResponse<AnimeDetailsGraphqlDtoData> animeDetailsData =
await _anilistGraphQLService.query<AnimeDetailsGraphqlDtoData>(
query: queries.animeDetailsQuery,
fromJson: AnimeDetailsGraphqlDtoData.fromJson,
variables: {
"userId": user.id,
"type": "ANIME",
"mediaId": selectedAnime.id,
"page" : 1,
"perPage": 20,
"sort": "RELEVANCE"
},
headers: graphQlHeaders,
);
throwIfGraphQlError(animeDetailsData);
AnimeDetails animeDetails = AnilistAnimeDetailsModel.fromAnimeDetailsMediaList(animeDetailsData.data.mediaList);
return (true, animeDetails);
}
Future<List<Anime>> _getCalendarReleasesPage(int page) async {
DateTime now = DateTime.now();
// Calculate yesterday 00:00:00
DateTime start = DateTime(now.year, now.month, now.day, 0, 0, 0, 0).subtract(Duration(days: 1));

View File

@@ -4,6 +4,7 @@ import 'airing_episode.dart';
import 'title.dart';
part 'anime.freezed.dart';
part 'anime.g.dart';
abstract class Anime {
final int id;
@@ -63,7 +64,7 @@ abstract class AnimeModel with _$AnimeModel implements Anime {
const factory AnimeModel({
required int id,
required int idMal,
required Title title,
@TitleConverter() required Title title,
required int averageScore,
required String bannerImage,
required String countryOfOrigin,
@@ -81,11 +82,11 @@ abstract class AnimeModel with _$AnimeModel implements Anime {
required String season,
required bool isFavourite,
required String status,
required AiringEpisode nextAiringEpisode,
@AiringEpisodeConverter() required AiringEpisode nextAiringEpisode,
}) = _AnimeModel;
factory AnimeModel.empty() => AnimeModel(
id: 0,
id: -1,
idMal: 0,
title: TitleModel.empty(),
averageScore: 0,
@@ -107,4 +108,21 @@ abstract class AnimeModel with _$AnimeModel implements Anime {
status: '',
nextAiringEpisode: AiringEpisodeModel.empty(),
);
factory AnimeModel.fromJson(Map<String, dynamic> json) =>
_$AnimeModelFromJson(json);
@override
Map<String, dynamic> toJson() =>
_$AnimeModelToJson(this as _AnimeModel);
}
class AnimeConverter implements JsonConverter<Anime, Map<String, dynamic>> {
const AnimeConverter();
@override
Anime fromJson(Map<String, dynamic> json) => AnimeModel.fromJson(json);
@override
Map<String, dynamic> toJson(Anime object) =>
(object as AnimeModel).toJson();
}

View File

@@ -11,16 +11,19 @@ part of 'anime.dart';
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$AnimeModel {
int get id; int get idMal; Title get title; int get averageScore; String get bannerImage; String get countryOfOrigin; String get coverImage; String get description; int get duration; String get endDate; String get startDate; int get episodes; List<String> get genres; String get format; bool get isAdult; int get popularity; int get meanScore; String get season; bool get isFavourite; String get status; AiringEpisode get nextAiringEpisode;
int get id; int get idMal;@TitleConverter() Title get title; int get averageScore; String get bannerImage; String get countryOfOrigin; String get coverImage; String get description; int get duration; String get endDate; String get startDate; int get episodes; List<String> get genres; String get format; bool get isAdult; int get popularity; int get meanScore; String get season; bool get isFavourite; String get status;@AiringEpisodeConverter() AiringEpisode get nextAiringEpisode;
/// Create a copy of AnimeModel
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$AnimeModelCopyWith<AnimeModel> get copyWith => _$AnimeModelCopyWithImpl<AnimeModel>(this as AnimeModel, _$identity);
/// Serializes this AnimeModel to a JSON map.
Map<String, dynamic> toJson();
@override
@@ -28,7 +31,7 @@ bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is AnimeModel&&(identical(other.id, id) || other.id == id)&&(identical(other.idMal, idMal) || other.idMal == idMal)&&(identical(other.title, title) || other.title == title)&&(identical(other.averageScore, averageScore) || other.averageScore == averageScore)&&(identical(other.bannerImage, bannerImage) || other.bannerImage == bannerImage)&&(identical(other.countryOfOrigin, countryOfOrigin) || other.countryOfOrigin == countryOfOrigin)&&(identical(other.coverImage, coverImage) || other.coverImage == coverImage)&&(identical(other.description, description) || other.description == description)&&(identical(other.duration, duration) || other.duration == duration)&&(identical(other.endDate, endDate) || other.endDate == endDate)&&(identical(other.startDate, startDate) || other.startDate == startDate)&&(identical(other.episodes, episodes) || other.episodes == episodes)&&const DeepCollectionEquality().equals(other.genres, genres)&&(identical(other.format, format) || other.format == format)&&(identical(other.isAdult, isAdult) || other.isAdult == isAdult)&&(identical(other.popularity, popularity) || other.popularity == popularity)&&(identical(other.meanScore, meanScore) || other.meanScore == meanScore)&&(identical(other.season, season) || other.season == season)&&(identical(other.isFavourite, isFavourite) || other.isFavourite == isFavourite)&&(identical(other.status, status) || other.status == status)&&(identical(other.nextAiringEpisode, nextAiringEpisode) || other.nextAiringEpisode == nextAiringEpisode));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hashAll([runtimeType,id,idMal,title,averageScore,bannerImage,countryOfOrigin,coverImage,description,duration,endDate,startDate,episodes,const DeepCollectionEquality().hash(genres),format,isAdult,popularity,meanScore,season,isFavourite,status,nextAiringEpisode]);
@@ -41,7 +44,7 @@ abstract mixin class $AnimeModelCopyWith<$Res> {
factory $AnimeModelCopyWith(AnimeModel value, $Res Function(AnimeModel) _then) = _$AnimeModelCopyWithImpl;
@useResult
$Res call({
int id, int idMal, Title title, int averageScore, String bannerImage, String countryOfOrigin, String coverImage, String description, int duration, String endDate, String startDate, int episodes, List<String> genres, String format, bool isAdult, int popularity, int meanScore, String season, bool isFavourite, String status, AiringEpisode nextAiringEpisode
int id, int idMal,@TitleConverter() Title title, int averageScore, String bannerImage, String countryOfOrigin, String coverImage, String description, int duration, String endDate, String startDate, int episodes, List<String> genres, String format, bool isAdult, int popularity, int meanScore, String season, bool isFavourite, String status,@AiringEpisodeConverter() AiringEpisode nextAiringEpisode
});
@@ -166,7 +169,7 @@ return $default(_that);case _:
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( int id, int idMal, Title title, int averageScore, String bannerImage, String countryOfOrigin, String coverImage, String description, int duration, String endDate, String startDate, int episodes, List<String> genres, String format, bool isAdult, int popularity, int meanScore, String season, bool isFavourite, String status, AiringEpisode nextAiringEpisode)? $default,{required TResult orElse(),}) {final _that = this;
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( int id, int idMal, @TitleConverter() Title title, int averageScore, String bannerImage, String countryOfOrigin, String coverImage, String description, int duration, String endDate, String startDate, int episodes, List<String> genres, String format, bool isAdult, int popularity, int meanScore, String season, bool isFavourite, String status, @AiringEpisodeConverter() AiringEpisode nextAiringEpisode)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _AnimeModel() when $default != null:
return $default(_that.id,_that.idMal,_that.title,_that.averageScore,_that.bannerImage,_that.countryOfOrigin,_that.coverImage,_that.description,_that.duration,_that.endDate,_that.startDate,_that.episodes,_that.genres,_that.format,_that.isAdult,_that.popularity,_that.meanScore,_that.season,_that.isFavourite,_that.status,_that.nextAiringEpisode);case _:
@@ -187,7 +190,7 @@ return $default(_that.id,_that.idMal,_that.title,_that.averageScore,_that.banner
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( int id, int idMal, Title title, int averageScore, String bannerImage, String countryOfOrigin, String coverImage, String description, int duration, String endDate, String startDate, int episodes, List<String> genres, String format, bool isAdult, int popularity, int meanScore, String season, bool isFavourite, String status, AiringEpisode nextAiringEpisode) $default,) {final _that = this;
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( int id, int idMal, @TitleConverter() Title title, int averageScore, String bannerImage, String countryOfOrigin, String coverImage, String description, int duration, String endDate, String startDate, int episodes, List<String> genres, String format, bool isAdult, int popularity, int meanScore, String season, bool isFavourite, String status, @AiringEpisodeConverter() AiringEpisode nextAiringEpisode) $default,) {final _that = this;
switch (_that) {
case _AnimeModel():
return $default(_that.id,_that.idMal,_that.title,_that.averageScore,_that.bannerImage,_that.countryOfOrigin,_that.coverImage,_that.description,_that.duration,_that.endDate,_that.startDate,_that.episodes,_that.genres,_that.format,_that.isAdult,_that.popularity,_that.meanScore,_that.season,_that.isFavourite,_that.status,_that.nextAiringEpisode);case _:
@@ -207,7 +210,7 @@ return $default(_that.id,_that.idMal,_that.title,_that.averageScore,_that.banner
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( int id, int idMal, Title title, int averageScore, String bannerImage, String countryOfOrigin, String coverImage, String description, int duration, String endDate, String startDate, int episodes, List<String> genres, String format, bool isAdult, int popularity, int meanScore, String season, bool isFavourite, String status, AiringEpisode nextAiringEpisode)? $default,) {final _that = this;
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( int id, int idMal, @TitleConverter() Title title, int averageScore, String bannerImage, String countryOfOrigin, String coverImage, String description, int duration, String endDate, String startDate, int episodes, List<String> genres, String format, bool isAdult, int popularity, int meanScore, String season, bool isFavourite, String status, @AiringEpisodeConverter() AiringEpisode nextAiringEpisode)? $default,) {final _that = this;
switch (_that) {
case _AnimeModel() when $default != null:
return $default(_that.id,_that.idMal,_that.title,_that.averageScore,_that.bannerImage,_that.countryOfOrigin,_that.coverImage,_that.description,_that.duration,_that.endDate,_that.startDate,_that.episodes,_that.genres,_that.format,_that.isAdult,_that.popularity,_that.meanScore,_that.season,_that.isFavourite,_that.status,_that.nextAiringEpisode);case _:
@@ -219,15 +222,15 @@ return $default(_that.id,_that.idMal,_that.title,_that.averageScore,_that.banner
}
/// @nodoc
@JsonSerializable()
class _AnimeModel implements AnimeModel {
const _AnimeModel({required this.id, required this.idMal, required this.title, required this.averageScore, required this.bannerImage, required this.countryOfOrigin, required this.coverImage, required this.description, required this.duration, required this.endDate, required this.startDate, required this.episodes, required final List<String> genres, required this.format, required this.isAdult, required this.popularity, required this.meanScore, required this.season, required this.isFavourite, required this.status, required this.nextAiringEpisode}): _genres = genres;
const _AnimeModel({required this.id, required this.idMal, @TitleConverter() required this.title, required this.averageScore, required this.bannerImage, required this.countryOfOrigin, required this.coverImage, required this.description, required this.duration, required this.endDate, required this.startDate, required this.episodes, required final List<String> genres, required this.format, required this.isAdult, required this.popularity, required this.meanScore, required this.season, required this.isFavourite, required this.status, @AiringEpisodeConverter() required this.nextAiringEpisode}): _genres = genres;
factory _AnimeModel.fromJson(Map<String, dynamic> json) => _$AnimeModelFromJson(json);
@override final int id;
@override final int idMal;
@override final Title title;
@override@TitleConverter() final Title title;
@override final int averageScore;
@override final String bannerImage;
@override final String countryOfOrigin;
@@ -251,7 +254,7 @@ class _AnimeModel implements AnimeModel {
@override final String season;
@override final bool isFavourite;
@override final String status;
@override final AiringEpisode nextAiringEpisode;
@override@AiringEpisodeConverter() final AiringEpisode nextAiringEpisode;
/// Create a copy of AnimeModel
/// with the given fields replaced by the non-null parameter values.
@@ -259,14 +262,17 @@ class _AnimeModel implements AnimeModel {
@pragma('vm:prefer-inline')
_$AnimeModelCopyWith<_AnimeModel> get copyWith => __$AnimeModelCopyWithImpl<_AnimeModel>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$AnimeModelToJson(this, );
}
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AnimeModel&&(identical(other.id, id) || other.id == id)&&(identical(other.idMal, idMal) || other.idMal == idMal)&&(identical(other.title, title) || other.title == title)&&(identical(other.averageScore, averageScore) || other.averageScore == averageScore)&&(identical(other.bannerImage, bannerImage) || other.bannerImage == bannerImage)&&(identical(other.countryOfOrigin, countryOfOrigin) || other.countryOfOrigin == countryOfOrigin)&&(identical(other.coverImage, coverImage) || other.coverImage == coverImage)&&(identical(other.description, description) || other.description == description)&&(identical(other.duration, duration) || other.duration == duration)&&(identical(other.endDate, endDate) || other.endDate == endDate)&&(identical(other.startDate, startDate) || other.startDate == startDate)&&(identical(other.episodes, episodes) || other.episodes == episodes)&&const DeepCollectionEquality().equals(other._genres, _genres)&&(identical(other.format, format) || other.format == format)&&(identical(other.isAdult, isAdult) || other.isAdult == isAdult)&&(identical(other.popularity, popularity) || other.popularity == popularity)&&(identical(other.meanScore, meanScore) || other.meanScore == meanScore)&&(identical(other.season, season) || other.season == season)&&(identical(other.isFavourite, isFavourite) || other.isFavourite == isFavourite)&&(identical(other.status, status) || other.status == status)&&(identical(other.nextAiringEpisode, nextAiringEpisode) || other.nextAiringEpisode == nextAiringEpisode));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hashAll([runtimeType,id,idMal,title,averageScore,bannerImage,countryOfOrigin,coverImage,description,duration,endDate,startDate,episodes,const DeepCollectionEquality().hash(_genres),format,isAdult,popularity,meanScore,season,isFavourite,status,nextAiringEpisode]);
@@ -279,7 +285,7 @@ abstract mixin class _$AnimeModelCopyWith<$Res> implements $AnimeModelCopyWith<$
factory _$AnimeModelCopyWith(_AnimeModel value, $Res Function(_AnimeModel) _then) = __$AnimeModelCopyWithImpl;
@override @useResult
$Res call({
int id, int idMal, Title title, int averageScore, String bannerImage, String countryOfOrigin, String coverImage, String description, int duration, String endDate, String startDate, int episodes, List<String> genres, String format, bool isAdult, int popularity, int meanScore, String season, bool isFavourite, String status, AiringEpisode nextAiringEpisode
int id, int idMal,@TitleConverter() Title title, int averageScore, String bannerImage, String countryOfOrigin, String coverImage, String description, int duration, String endDate, String startDate, int episodes, List<String> genres, String format, bool isAdult, int popularity, int meanScore, String season, bool isFavourite, String status,@AiringEpisodeConverter() AiringEpisode nextAiringEpisode
});

View File

@@ -0,0 +1,60 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'anime.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_AnimeModel _$AnimeModelFromJson(Map<String, dynamic> json) => _AnimeModel(
id: (json['id'] as num).toInt(),
idMal: (json['idMal'] as num).toInt(),
title: const TitleConverter().fromJson(json['title'] as Map<String, dynamic>),
averageScore: (json['averageScore'] as num).toInt(),
bannerImage: json['bannerImage'] as String,
countryOfOrigin: json['countryOfOrigin'] as String,
coverImage: json['coverImage'] as String,
description: json['description'] as String,
duration: (json['duration'] as num).toInt(),
endDate: json['endDate'] as String,
startDate: json['startDate'] as String,
episodes: (json['episodes'] as num).toInt(),
genres: (json['genres'] as List<dynamic>).map((e) => e as String).toList(),
format: json['format'] as String,
isAdult: json['isAdult'] as bool,
popularity: (json['popularity'] as num).toInt(),
meanScore: (json['meanScore'] as num).toInt(),
season: json['season'] as String,
isFavourite: json['isFavourite'] as bool,
status: json['status'] as String,
nextAiringEpisode: const AiringEpisodeConverter().fromJson(
json['nextAiringEpisode'] as Map<String, dynamic>,
),
);
Map<String, dynamic> _$AnimeModelToJson(_AnimeModel instance) =>
<String, dynamic>{
'id': instance.id,
'idMal': instance.idMal,
'title': const TitleConverter().toJson(instance.title),
'averageScore': instance.averageScore,
'bannerImage': instance.bannerImage,
'countryOfOrigin': instance.countryOfOrigin,
'coverImage': instance.coverImage,
'description': instance.description,
'duration': instance.duration,
'endDate': instance.endDate,
'startDate': instance.startDate,
'episodes': instance.episodes,
'genres': instance.genres,
'format': instance.format,
'isAdult': instance.isAdult,
'popularity': instance.popularity,
'meanScore': instance.meanScore,
'season': instance.season,
'isFavourite': instance.isFavourite,
'status': instance.status,
'nextAiringEpisode': const AiringEpisodeConverter().toJson(
instance.nextAiringEpisode,
),
};

View File

@@ -0,0 +1,53 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:unyo/domain/entities/anime.dart';
import 'package:unyo/domain/entities/media_character.dart';
part 'anime_details.freezed.dart';
part 'anime_details.g.dart';
abstract class AnimeDetails {
final int progress;
final int score;
final int repeat;
final List<Anime> recommendedAnimes;
final List<MediaCharacter> characters;
const AnimeDetails({required this.progress, required this.score, required this.repeat, required this.recommendedAnimes, required this.characters});
}
@freezed
abstract class AnimeDetailsModel with _$AnimeDetailsModel implements AnimeDetails {
const factory AnimeDetailsModel({
required int progress,
required int score,
required int repeat,
@AnimeConverter() required List<Anime> recommendedAnimes,
@MediaCharacterConverter() required List<MediaCharacter> characters,
}) = _AnimeDetailsModel;
factory AnimeDetailsModel.empty() => const AnimeDetailsModel(
progress: 0,
score: 0,
repeat: 0,
recommendedAnimes: [],
characters: []
);
factory AnimeDetailsModel.fromJson(Map<String, dynamic> json) =>
_$AnimeDetailsModelFromJson(json);
@override
Map<String, dynamic> toJson() =>
_$AnimeDetailsModelToJson(this as _AnimeDetailsModel);
}
class AnimeDetailsConverter implements JsonConverter<AnimeDetails, Map<String, dynamic>> {
const AnimeDetailsConverter();
@override
AnimeDetails fromJson(Map<String, dynamic> json) => AnimeDetailsModel.fromJson(json);
@override
Map<String, dynamic> toJson(AnimeDetails object) =>
(object as AnimeDetailsModel).toJson();
}

View File

@@ -0,0 +1,301 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// coverage:ignore-file
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'anime_details.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$AnimeDetailsModel {
int get progress; int get score; int get repeat;@AnimeConverter() List<Anime> get recommendedAnimes;@MediaCharacterConverter() List<MediaCharacter> get characters;
/// Create a copy of AnimeDetailsModel
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$AnimeDetailsModelCopyWith<AnimeDetailsModel> get copyWith => _$AnimeDetailsModelCopyWithImpl<AnimeDetailsModel>(this as AnimeDetailsModel, _$identity);
/// Serializes this AnimeDetailsModel to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is AnimeDetailsModel&&(identical(other.progress, progress) || other.progress == progress)&&(identical(other.score, score) || other.score == score)&&(identical(other.repeat, repeat) || other.repeat == repeat)&&const DeepCollectionEquality().equals(other.recommendedAnimes, recommendedAnimes)&&const DeepCollectionEquality().equals(other.characters, characters));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,progress,score,repeat,const DeepCollectionEquality().hash(recommendedAnimes),const DeepCollectionEquality().hash(characters));
@override
String toString() {
return 'AnimeDetailsModel(progress: $progress, score: $score, repeat: $repeat, recommendedAnimes: $recommendedAnimes, characters: $characters)';
}
}
/// @nodoc
abstract mixin class $AnimeDetailsModelCopyWith<$Res> {
factory $AnimeDetailsModelCopyWith(AnimeDetailsModel value, $Res Function(AnimeDetailsModel) _then) = _$AnimeDetailsModelCopyWithImpl;
@useResult
$Res call({
int progress, int score, int repeat,@AnimeConverter() List<Anime> recommendedAnimes,@MediaCharacterConverter() List<MediaCharacter> characters
});
}
/// @nodoc
class _$AnimeDetailsModelCopyWithImpl<$Res>
implements $AnimeDetailsModelCopyWith<$Res> {
_$AnimeDetailsModelCopyWithImpl(this._self, this._then);
final AnimeDetailsModel _self;
final $Res Function(AnimeDetailsModel) _then;
/// Create a copy of AnimeDetailsModel
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? progress = null,Object? score = null,Object? repeat = null,Object? recommendedAnimes = null,Object? characters = null,}) {
return _then(_self.copyWith(
progress: null == progress ? _self.progress : progress // ignore: cast_nullable_to_non_nullable
as int,score: null == score ? _self.score : score // ignore: cast_nullable_to_non_nullable
as int,repeat: null == repeat ? _self.repeat : repeat // ignore: cast_nullable_to_non_nullable
as int,recommendedAnimes: null == recommendedAnimes ? _self.recommendedAnimes : recommendedAnimes // ignore: cast_nullable_to_non_nullable
as List<Anime>,characters: null == characters ? _self.characters : characters // ignore: cast_nullable_to_non_nullable
as List<MediaCharacter>,
));
}
}
/// Adds pattern-matching-related methods to [AnimeDetailsModel].
extension AnimeDetailsModelPatterns on AnimeDetailsModel {
/// A variant of `map` that fallback to returning `orElse`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _AnimeDetailsModel value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _AnimeDetailsModel() when $default != null:
return $default(_that);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case final Subclass2 value:
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _AnimeDetailsModel value) $default,){
final _that = this;
switch (_that) {
case _AnimeDetailsModel():
return $default(_that);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _AnimeDetailsModel value)? $default,){
final _that = this;
switch (_that) {
case _AnimeDetailsModel() when $default != null:
return $default(_that);case _:
return null;
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( int progress, int score, int repeat, @AnimeConverter() List<Anime> recommendedAnimes, @MediaCharacterConverter() List<MediaCharacter> characters)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _AnimeDetailsModel() when $default != null:
return $default(_that.progress,_that.score,_that.repeat,_that.recommendedAnimes,_that.characters);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case Subclass2(:final field2):
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( int progress, int score, int repeat, @AnimeConverter() List<Anime> recommendedAnimes, @MediaCharacterConverter() List<MediaCharacter> characters) $default,) {final _that = this;
switch (_that) {
case _AnimeDetailsModel():
return $default(_that.progress,_that.score,_that.repeat,_that.recommendedAnimes,_that.characters);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( int progress, int score, int repeat, @AnimeConverter() List<Anime> recommendedAnimes, @MediaCharacterConverter() List<MediaCharacter> characters)? $default,) {final _that = this;
switch (_that) {
case _AnimeDetailsModel() when $default != null:
return $default(_that.progress,_that.score,_that.repeat,_that.recommendedAnimes,_that.characters);case _:
return null;
}
}
}
/// @nodoc
@JsonSerializable()
class _AnimeDetailsModel implements AnimeDetailsModel {
const _AnimeDetailsModel({required this.progress, required this.score, required this.repeat, @AnimeConverter() required final List<Anime> recommendedAnimes, @MediaCharacterConverter() required final List<MediaCharacter> characters}): _recommendedAnimes = recommendedAnimes,_characters = characters;
factory _AnimeDetailsModel.fromJson(Map<String, dynamic> json) => _$AnimeDetailsModelFromJson(json);
@override final int progress;
@override final int score;
@override final int repeat;
final List<Anime> _recommendedAnimes;
@override@AnimeConverter() List<Anime> get recommendedAnimes {
if (_recommendedAnimes is EqualUnmodifiableListView) return _recommendedAnimes;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_recommendedAnimes);
}
final List<MediaCharacter> _characters;
@override@MediaCharacterConverter() List<MediaCharacter> get characters {
if (_characters is EqualUnmodifiableListView) return _characters;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_characters);
}
/// Create a copy of AnimeDetailsModel
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$AnimeDetailsModelCopyWith<_AnimeDetailsModel> get copyWith => __$AnimeDetailsModelCopyWithImpl<_AnimeDetailsModel>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$AnimeDetailsModelToJson(this, );
}
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AnimeDetailsModel&&(identical(other.progress, progress) || other.progress == progress)&&(identical(other.score, score) || other.score == score)&&(identical(other.repeat, repeat) || other.repeat == repeat)&&const DeepCollectionEquality().equals(other._recommendedAnimes, _recommendedAnimes)&&const DeepCollectionEquality().equals(other._characters, _characters));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,progress,score,repeat,const DeepCollectionEquality().hash(_recommendedAnimes),const DeepCollectionEquality().hash(_characters));
@override
String toString() {
return 'AnimeDetailsModel(progress: $progress, score: $score, repeat: $repeat, recommendedAnimes: $recommendedAnimes, characters: $characters)';
}
}
/// @nodoc
abstract mixin class _$AnimeDetailsModelCopyWith<$Res> implements $AnimeDetailsModelCopyWith<$Res> {
factory _$AnimeDetailsModelCopyWith(_AnimeDetailsModel value, $Res Function(_AnimeDetailsModel) _then) = __$AnimeDetailsModelCopyWithImpl;
@override @useResult
$Res call({
int progress, int score, int repeat,@AnimeConverter() List<Anime> recommendedAnimes,@MediaCharacterConverter() List<MediaCharacter> characters
});
}
/// @nodoc
class __$AnimeDetailsModelCopyWithImpl<$Res>
implements _$AnimeDetailsModelCopyWith<$Res> {
__$AnimeDetailsModelCopyWithImpl(this._self, this._then);
final _AnimeDetailsModel _self;
final $Res Function(_AnimeDetailsModel) _then;
/// Create a copy of AnimeDetailsModel
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? progress = null,Object? score = null,Object? repeat = null,Object? recommendedAnimes = null,Object? characters = null,}) {
return _then(_AnimeDetailsModel(
progress: null == progress ? _self.progress : progress // ignore: cast_nullable_to_non_nullable
as int,score: null == score ? _self.score : score // ignore: cast_nullable_to_non_nullable
as int,repeat: null == repeat ? _self.repeat : repeat // ignore: cast_nullable_to_non_nullable
as int,recommendedAnimes: null == recommendedAnimes ? _self._recommendedAnimes : recommendedAnimes // ignore: cast_nullable_to_non_nullable
as List<Anime>,characters: null == characters ? _self._characters : characters // ignore: cast_nullable_to_non_nullable
as List<MediaCharacter>,
));
}
}
// dart format on

View File

@@ -0,0 +1,41 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'anime_details.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_AnimeDetailsModel _$AnimeDetailsModelFromJson(Map<String, dynamic> json) =>
_AnimeDetailsModel(
progress: (json['progress'] as num).toInt(),
score: (json['score'] as num).toInt(),
repeat: (json['repeat'] as num).toInt(),
recommendedAnimes:
(json['recommendedAnimes'] as List<dynamic>)
.map(
(e) =>
const AnimeConverter().fromJson(e as Map<String, dynamic>),
)
.toList(),
characters:
(json['characters'] as List<dynamic>)
.map(
(e) => const MediaCharacterConverter().fromJson(
e as Map<String, dynamic>,
),
)
.toList(),
);
Map<String, dynamic> _$AnimeDetailsModelToJson(
_AnimeDetailsModel instance,
) => <String, dynamic>{
'progress': instance.progress,
'score': instance.score,
'repeat': instance.repeat,
'recommendedAnimes':
instance.recommendedAnimes.map(const AnimeConverter().toJson).toList(),
'characters':
instance.characters.map(const MediaCharacterConverter().toJson).toList(),
};

View File

@@ -1,49 +0,0 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:hive_ce/hive.dart';
import 'package:unyo/data/adapters/adapters_names.dart' as names;
import 'package:unyo/data/adapters/adapters_types.dart' as types;
part 'anime_progress.freezed.dart';
part 'anime_progress.g.dart';
abstract class AnimeProgress {
final int progress;
final int score;
final int repeat;
const AnimeProgress({required this.progress, required this.score, required this.repeat});
}
@freezed
@HiveType(typeId: types.animeProgressAdapterType, adapterName: names.animeProgressModelAdapterName)
abstract class AnimeProgressModel with _$AnimeProgressModel implements AnimeProgress {
const factory AnimeProgressModel({
@HiveField(0) required int progress,
@HiveField(1) required int score,
@HiveField(2) required int repeat,
}) = _AnimeProgressModel;
factory AnimeProgressModel.empty() => const AnimeProgressModel(
progress: 0,
score: 0,
repeat: 0
);
factory AnimeProgressModel.fromJson(Map<String, dynamic> json) =>
_$AnimeProgressModelFromJson(json);
@override
Map<String, dynamic> toJson() =>
_$AnimeProgressModelToJson(this as _AnimeProgressModel);
}
class AnimeProgresConverter implements JsonConverter<AnimeProgress, Map<String, dynamic>> {
const AnimeProgresConverter();
@override
AnimeProgress fromJson(Map<String, dynamic> json) => AnimeProgressModel.fromJson(json);
@override
Map<String, dynamic> toJson(AnimeProgress object) =>
(object as AnimeProgressModel).toJson();
}

View File

@@ -1,283 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// coverage:ignore-file
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'anime_progress.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$AnimeProgressModel {
@HiveField(0) int get progress;@HiveField(1) int get score;@HiveField(2) int get repeat;
/// Create a copy of AnimeProgressModel
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$AnimeProgressModelCopyWith<AnimeProgressModel> get copyWith => _$AnimeProgressModelCopyWithImpl<AnimeProgressModel>(this as AnimeProgressModel, _$identity);
/// Serializes this AnimeProgressModel to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is AnimeProgressModel&&(identical(other.progress, progress) || other.progress == progress)&&(identical(other.score, score) || other.score == score)&&(identical(other.repeat, repeat) || other.repeat == repeat));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,progress,score,repeat);
@override
String toString() {
return 'AnimeProgressModel(progress: $progress, score: $score, repeat: $repeat)';
}
}
/// @nodoc
abstract mixin class $AnimeProgressModelCopyWith<$Res> {
factory $AnimeProgressModelCopyWith(AnimeProgressModel value, $Res Function(AnimeProgressModel) _then) = _$AnimeProgressModelCopyWithImpl;
@useResult
$Res call({
@HiveField(0) int progress,@HiveField(1) int score,@HiveField(2) int repeat
});
}
/// @nodoc
class _$AnimeProgressModelCopyWithImpl<$Res>
implements $AnimeProgressModelCopyWith<$Res> {
_$AnimeProgressModelCopyWithImpl(this._self, this._then);
final AnimeProgressModel _self;
final $Res Function(AnimeProgressModel) _then;
/// Create a copy of AnimeProgressModel
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? progress = null,Object? score = null,Object? repeat = null,}) {
return _then(_self.copyWith(
progress: null == progress ? _self.progress : progress // ignore: cast_nullable_to_non_nullable
as int,score: null == score ? _self.score : score // ignore: cast_nullable_to_non_nullable
as int,repeat: null == repeat ? _self.repeat : repeat // ignore: cast_nullable_to_non_nullable
as int,
));
}
}
/// Adds pattern-matching-related methods to [AnimeProgressModel].
extension AnimeProgressModelPatterns on AnimeProgressModel {
/// A variant of `map` that fallback to returning `orElse`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _AnimeProgressModel value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _AnimeProgressModel() when $default != null:
return $default(_that);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case final Subclass2 value:
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _AnimeProgressModel value) $default,){
final _that = this;
switch (_that) {
case _AnimeProgressModel():
return $default(_that);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _AnimeProgressModel value)? $default,){
final _that = this;
switch (_that) {
case _AnimeProgressModel() when $default != null:
return $default(_that);case _:
return null;
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function(@HiveField(0) int progress, @HiveField(1) int score, @HiveField(2) int repeat)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _AnimeProgressModel() when $default != null:
return $default(_that.progress,_that.score,_that.repeat);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case Subclass2(:final field2):
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function(@HiveField(0) int progress, @HiveField(1) int score, @HiveField(2) int repeat) $default,) {final _that = this;
switch (_that) {
case _AnimeProgressModel():
return $default(_that.progress,_that.score,_that.repeat);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function(@HiveField(0) int progress, @HiveField(1) int score, @HiveField(2) int repeat)? $default,) {final _that = this;
switch (_that) {
case _AnimeProgressModel() when $default != null:
return $default(_that.progress,_that.score,_that.repeat);case _:
return null;
}
}
}
/// @nodoc
@JsonSerializable()
class _AnimeProgressModel implements AnimeProgressModel {
const _AnimeProgressModel({@HiveField(0) required this.progress, @HiveField(1) required this.score, @HiveField(2) required this.repeat});
factory _AnimeProgressModel.fromJson(Map<String, dynamic> json) => _$AnimeProgressModelFromJson(json);
@override@HiveField(0) final int progress;
@override@HiveField(1) final int score;
@override@HiveField(2) final int repeat;
/// Create a copy of AnimeProgressModel
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$AnimeProgressModelCopyWith<_AnimeProgressModel> get copyWith => __$AnimeProgressModelCopyWithImpl<_AnimeProgressModel>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$AnimeProgressModelToJson(this, );
}
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AnimeProgressModel&&(identical(other.progress, progress) || other.progress == progress)&&(identical(other.score, score) || other.score == score)&&(identical(other.repeat, repeat) || other.repeat == repeat));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,progress,score,repeat);
@override
String toString() {
return 'AnimeProgressModel(progress: $progress, score: $score, repeat: $repeat)';
}
}
/// @nodoc
abstract mixin class _$AnimeProgressModelCopyWith<$Res> implements $AnimeProgressModelCopyWith<$Res> {
factory _$AnimeProgressModelCopyWith(_AnimeProgressModel value, $Res Function(_AnimeProgressModel) _then) = __$AnimeProgressModelCopyWithImpl;
@override @useResult
$Res call({
@HiveField(0) int progress,@HiveField(1) int score,@HiveField(2) int repeat
});
}
/// @nodoc
class __$AnimeProgressModelCopyWithImpl<$Res>
implements _$AnimeProgressModelCopyWith<$Res> {
__$AnimeProgressModelCopyWithImpl(this._self, this._then);
final _AnimeProgressModel _self;
final $Res Function(_AnimeProgressModel) _then;
/// Create a copy of AnimeProgressModel
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? progress = null,Object? score = null,Object? repeat = null,}) {
return _then(_AnimeProgressModel(
progress: null == progress ? _self.progress : progress // ignore: cast_nullable_to_non_nullable
as int,score: null == score ? _self.score : score // ignore: cast_nullable_to_non_nullable
as int,repeat: null == repeat ? _self.repeat : repeat // ignore: cast_nullable_to_non_nullable
as int,
));
}
}
// dart format on

View File

@@ -1,65 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'anime_progress.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class AnimeProgressModelAdapter extends TypeAdapter<AnimeProgressModel> {
@override
final typeId = 4;
@override
AnimeProgressModel read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return AnimeProgressModel(
progress: (fields[0] as num).toInt(),
score: (fields[1] as num).toInt(),
repeat: (fields[2] as num).toInt(),
);
}
@override
void write(BinaryWriter writer, AnimeProgressModel obj) {
writer
..writeByte(3)
..writeByte(0)
..write(obj.progress)
..writeByte(1)
..write(obj.score)
..writeByte(2)
..write(obj.repeat);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is AnimeProgressModelAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_AnimeProgressModel _$AnimeProgressModelFromJson(Map<String, dynamic> json) =>
_AnimeProgressModel(
progress: (json['progress'] as num).toInt(),
score: (json['score'] as num).toInt(),
repeat: (json['repeat'] as num).toInt(),
);
Map<String, dynamic> _$AnimeProgressModelToJson(_AnimeProgressModel instance) =>
<String, dynamic>{
'progress': instance.progress,
'score': instance.score,
'repeat': instance.repeat,
};

View File

@@ -0,0 +1,70 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'media_character.freezed.dart';
part 'media_character.g.dart';
abstract class MediaCharacter {
final int id;
final String image;
final String name;
final String gender;
final String description;
final String dateOfBirth;
final int age;
const MediaCharacter({
required this.id,
required this.image,
required this.name,
required this.gender,
required this.description,
required this.dateOfBirth,
required this.age
});
@override
String toString() {
return 'MediaCharacter(id: $id, image: $image, name: $name, gender: $gender, description: $description, dateOfBirth: $dateOfBirth, age: $age)';
}
}
@freezed
abstract class MediaCharacterModel with _$MediaCharacterModel implements MediaCharacter {
const factory MediaCharacterModel({
required int id,
required String image,
required String name,
required String gender,
required String description,
required String dateOfBirth,
required int age
}) = _MediaCharacterModel;
factory MediaCharacterModel.empty() => const MediaCharacterModel(
id: -1,
image: '',
name: '',
gender: '',
description: '',
dateOfBirth: '',
age: 0
);
factory MediaCharacterModel.fromJson(Map<String, dynamic> json) =>
_$MediaCharacterModelFromJson(json);
@override
Map<String, dynamic> toJson() =>
_$MediaCharacterModelToJson(this as _MediaCharacterModel);
}
class MediaCharacterConverter implements JsonConverter<MediaCharacter, Map<String, dynamic>> {
const MediaCharacterConverter();
@override
MediaCharacter fromJson(Map<String, dynamic> json) => MediaCharacterModel.fromJson(json);
@override
Map<String, dynamic> toJson(MediaCharacter object) =>
(object as MediaCharacterModel).toJson();
}

View File

@@ -0,0 +1,287 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// coverage:ignore-file
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'media_character.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$MediaCharacterModel {
int get id; String get image; String get name; String get gender; String get description; String get dateOfBirth; int get age;
/// Create a copy of MediaCharacterModel
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$MediaCharacterModelCopyWith<MediaCharacterModel> get copyWith => _$MediaCharacterModelCopyWithImpl<MediaCharacterModel>(this as MediaCharacterModel, _$identity);
/// Serializes this MediaCharacterModel to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is MediaCharacterModel&&(identical(other.id, id) || other.id == id)&&(identical(other.image, image) || other.image == image)&&(identical(other.name, name) || other.name == name)&&(identical(other.gender, gender) || other.gender == gender)&&(identical(other.description, description) || other.description == description)&&(identical(other.dateOfBirth, dateOfBirth) || other.dateOfBirth == dateOfBirth)&&(identical(other.age, age) || other.age == age));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,id,image,name,gender,description,dateOfBirth,age);
}
/// @nodoc
abstract mixin class $MediaCharacterModelCopyWith<$Res> {
factory $MediaCharacterModelCopyWith(MediaCharacterModel value, $Res Function(MediaCharacterModel) _then) = _$MediaCharacterModelCopyWithImpl;
@useResult
$Res call({
int id, String image, String name, String gender, String description, String dateOfBirth, int age
});
}
/// @nodoc
class _$MediaCharacterModelCopyWithImpl<$Res>
implements $MediaCharacterModelCopyWith<$Res> {
_$MediaCharacterModelCopyWithImpl(this._self, this._then);
final MediaCharacterModel _self;
final $Res Function(MediaCharacterModel) _then;
/// Create a copy of MediaCharacterModel
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? image = null,Object? name = null,Object? gender = null,Object? description = null,Object? dateOfBirth = null,Object? age = null,}) {
return _then(_self.copyWith(
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
as int,image: null == image ? _self.image : image // ignore: cast_nullable_to_non_nullable
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
as String,gender: null == gender ? _self.gender : gender // ignore: cast_nullable_to_non_nullable
as String,description: null == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
as String,dateOfBirth: null == dateOfBirth ? _self.dateOfBirth : dateOfBirth // ignore: cast_nullable_to_non_nullable
as String,age: null == age ? _self.age : age // ignore: cast_nullable_to_non_nullable
as int,
));
}
}
/// Adds pattern-matching-related methods to [MediaCharacterModel].
extension MediaCharacterModelPatterns on MediaCharacterModel {
/// A variant of `map` that fallback to returning `orElse`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _MediaCharacterModel value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _MediaCharacterModel() when $default != null:
return $default(_that);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case final Subclass2 value:
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _MediaCharacterModel value) $default,){
final _that = this;
switch (_that) {
case _MediaCharacterModel():
return $default(_that);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _MediaCharacterModel value)? $default,){
final _that = this;
switch (_that) {
case _MediaCharacterModel() when $default != null:
return $default(_that);case _:
return null;
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( int id, String image, String name, String gender, String description, String dateOfBirth, int age)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _MediaCharacterModel() when $default != null:
return $default(_that.id,_that.image,_that.name,_that.gender,_that.description,_that.dateOfBirth,_that.age);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case Subclass2(:final field2):
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( int id, String image, String name, String gender, String description, String dateOfBirth, int age) $default,) {final _that = this;
switch (_that) {
case _MediaCharacterModel():
return $default(_that.id,_that.image,_that.name,_that.gender,_that.description,_that.dateOfBirth,_that.age);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( int id, String image, String name, String gender, String description, String dateOfBirth, int age)? $default,) {final _that = this;
switch (_that) {
case _MediaCharacterModel() when $default != null:
return $default(_that.id,_that.image,_that.name,_that.gender,_that.description,_that.dateOfBirth,_that.age);case _:
return null;
}
}
}
/// @nodoc
@JsonSerializable()
class _MediaCharacterModel implements MediaCharacterModel {
const _MediaCharacterModel({required this.id, required this.image, required this.name, required this.gender, required this.description, required this.dateOfBirth, required this.age});
factory _MediaCharacterModel.fromJson(Map<String, dynamic> json) => _$MediaCharacterModelFromJson(json);
@override final int id;
@override final String image;
@override final String name;
@override final String gender;
@override final String description;
@override final String dateOfBirth;
@override final int age;
/// Create a copy of MediaCharacterModel
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$MediaCharacterModelCopyWith<_MediaCharacterModel> get copyWith => __$MediaCharacterModelCopyWithImpl<_MediaCharacterModel>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$MediaCharacterModelToJson(this, );
}
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _MediaCharacterModel&&(identical(other.id, id) || other.id == id)&&(identical(other.image, image) || other.image == image)&&(identical(other.name, name) || other.name == name)&&(identical(other.gender, gender) || other.gender == gender)&&(identical(other.description, description) || other.description == description)&&(identical(other.dateOfBirth, dateOfBirth) || other.dateOfBirth == dateOfBirth)&&(identical(other.age, age) || other.age == age));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,id,image,name,gender,description,dateOfBirth,age);
}
/// @nodoc
abstract mixin class _$MediaCharacterModelCopyWith<$Res> implements $MediaCharacterModelCopyWith<$Res> {
factory _$MediaCharacterModelCopyWith(_MediaCharacterModel value, $Res Function(_MediaCharacterModel) _then) = __$MediaCharacterModelCopyWithImpl;
@override @useResult
$Res call({
int id, String image, String name, String gender, String description, String dateOfBirth, int age
});
}
/// @nodoc
class __$MediaCharacterModelCopyWithImpl<$Res>
implements _$MediaCharacterModelCopyWith<$Res> {
__$MediaCharacterModelCopyWithImpl(this._self, this._then);
final _MediaCharacterModel _self;
final $Res Function(_MediaCharacterModel) _then;
/// Create a copy of MediaCharacterModel
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? image = null,Object? name = null,Object? gender = null,Object? description = null,Object? dateOfBirth = null,Object? age = null,}) {
return _then(_MediaCharacterModel(
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
as int,image: null == image ? _self.image : image // ignore: cast_nullable_to_non_nullable
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
as String,gender: null == gender ? _self.gender : gender // ignore: cast_nullable_to_non_nullable
as String,description: null == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
as String,dateOfBirth: null == dateOfBirth ? _self.dateOfBirth : dateOfBirth // ignore: cast_nullable_to_non_nullable
as String,age: null == age ? _self.age : age // ignore: cast_nullable_to_non_nullable
as int,
));
}
}
// dart format on

View File

@@ -0,0 +1,30 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'media_character.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_MediaCharacterModel _$MediaCharacterModelFromJson(Map<String, dynamic> json) =>
_MediaCharacterModel(
id: (json['id'] as num).toInt(),
image: json['image'] as String,
name: json['name'] as String,
gender: json['gender'] as String,
description: json['description'] as String,
dateOfBirth: json['dateOfBirth'] as String,
age: (json['age'] as num).toInt(),
);
Map<String, dynamic> _$MediaCharacterModelToJson(
_MediaCharacterModel instance,
) => <String, dynamic>{
'id': instance.id,
'image': instance.image,
'name': instance.name,
'gender': instance.gender,
'description': instance.description,
'dateOfBirth': instance.dateOfBirth,
'age': instance.age,
};

View File

@@ -1,4 +1,5 @@
import 'package:unyo/domain/entities/anime.dart';
import 'package:unyo/domain/entities/anime_details.dart';
import 'package:unyo/domain/entities/user.dart';
abstract class AnimeRepository {
@@ -8,4 +9,5 @@ abstract class AnimeRepository {
Future<(bool, List<Anime>)> getRecentlyCompletedAnimes(int page);
Future<(bool, List<Anime>)> getUpcomingAnimes(int page);
Future<Map<String, List<Anime>>> getCalendarReleases(int page, User user);
Future<(bool, AnimeDetails)> getAnimeDetails(Anime selectedAnime, User user);
}

View File

@@ -0,0 +1,778 @@
import 'package:unyo/generated/json/base/json_convert_content.dart';
import 'package:unyo/core/services/api/dto/anime_details_graphql_dto_entity.dart';
AnimeDetailsGraphqlDtoEntity $AnimeDetailsGraphqlDtoEntityFromJson(
Map<String, dynamic> json) {
final AnimeDetailsGraphqlDtoEntity animeDetailsGraphqlDtoEntity = AnimeDetailsGraphqlDtoEntity();
final AnimeDetailsGraphqlDtoData? data = jsonConvert.convert<
AnimeDetailsGraphqlDtoData>(json['data']);
if (data != null) {
animeDetailsGraphqlDtoEntity.data = data;
}
return animeDetailsGraphqlDtoEntity;
}
Map<String, dynamic> $AnimeDetailsGraphqlDtoEntityToJson(
AnimeDetailsGraphqlDtoEntity entity) {
final Map<String, dynamic> data = <String, dynamic>{};
data['data'] = entity.data.toJson();
return data;
}
extension AnimeDetailsGraphqlDtoEntityExtension on AnimeDetailsGraphqlDtoEntity {
AnimeDetailsGraphqlDtoEntity copyWith({
AnimeDetailsGraphqlDtoData? data,
}) {
return AnimeDetailsGraphqlDtoEntity()
..data = data ?? this.data;
}
}
AnimeDetailsGraphqlDtoData $AnimeDetailsGraphqlDtoDataFromJson(
Map<String, dynamic> json) {
final AnimeDetailsGraphqlDtoData animeDetailsGraphqlDtoData = AnimeDetailsGraphqlDtoData();
final AnimeDetailsGraphqlDtoDataMediaList? mediaList = jsonConvert.convert<
AnimeDetailsGraphqlDtoDataMediaList>(json['MediaList']);
if (mediaList != null) {
animeDetailsGraphqlDtoData.mediaList = mediaList;
}
return animeDetailsGraphqlDtoData;
}
Map<String, dynamic> $AnimeDetailsGraphqlDtoDataToJson(
AnimeDetailsGraphqlDtoData entity) {
final Map<String, dynamic> data = <String, dynamic>{};
data['MediaList'] = entity.mediaList.toJson();
return data;
}
extension AnimeDetailsGraphqlDtoDataExtension on AnimeDetailsGraphqlDtoData {
AnimeDetailsGraphqlDtoData copyWith({
AnimeDetailsGraphqlDtoDataMediaList? mediaList,
}) {
return AnimeDetailsGraphqlDtoData()
..mediaList = mediaList ?? this.mediaList;
}
}
AnimeDetailsGraphqlDtoDataMediaList $AnimeDetailsGraphqlDtoDataMediaListFromJson(
Map<String, dynamic> json) {
final AnimeDetailsGraphqlDtoDataMediaList animeDetailsGraphqlDtoDataMediaList = AnimeDetailsGraphqlDtoDataMediaList();
final int? progress = jsonConvert.convert<int>(json['progress']);
if (progress != null) {
animeDetailsGraphqlDtoDataMediaList.progress = progress;
}
final int? score = jsonConvert.convert<int>(json['score']);
if (score != null) {
animeDetailsGraphqlDtoDataMediaList.score = score;
}
final int? repeat = jsonConvert.convert<int>(json['repeat']);
if (repeat != null) {
animeDetailsGraphqlDtoDataMediaList.repeat = repeat;
}
final AnimeDetailsGraphqlDtoDataMediaListMedia? media = jsonConvert.convert<
AnimeDetailsGraphqlDtoDataMediaListMedia>(json['media']);
if (media != null) {
animeDetailsGraphqlDtoDataMediaList.media = media;
}
return animeDetailsGraphqlDtoDataMediaList;
}
Map<String, dynamic> $AnimeDetailsGraphqlDtoDataMediaListToJson(
AnimeDetailsGraphqlDtoDataMediaList entity) {
final Map<String, dynamic> data = <String, dynamic>{};
data['progress'] = entity.progress;
data['score'] = entity.score;
data['repeat'] = entity.repeat;
data['media'] = entity.media.toJson();
return data;
}
extension AnimeDetailsGraphqlDtoDataMediaListExtension on AnimeDetailsGraphqlDtoDataMediaList {
AnimeDetailsGraphqlDtoDataMediaList copyWith({
int? progress,
int? score,
int? repeat,
AnimeDetailsGraphqlDtoDataMediaListMedia? media,
}) {
return AnimeDetailsGraphqlDtoDataMediaList()
..progress = progress ?? this.progress
..score = score ?? this.score
..repeat = repeat ?? this.repeat
..media = media ?? this.media;
}
}
AnimeDetailsGraphqlDtoDataMediaListMedia $AnimeDetailsGraphqlDtoDataMediaListMediaFromJson(
Map<String, dynamic> json) {
final AnimeDetailsGraphqlDtoDataMediaListMedia animeDetailsGraphqlDtoDataMediaListMedia = AnimeDetailsGraphqlDtoDataMediaListMedia();
final AnimeDetailsGraphqlDtoDataMediaListMediaRecommendations? recommendations = jsonConvert
.convert<AnimeDetailsGraphqlDtoDataMediaListMediaRecommendations>(
json['recommendations']);
if (recommendations != null) {
animeDetailsGraphqlDtoDataMediaListMedia.recommendations = recommendations;
}
final AnimeDetailsGraphqlDtoDataMediaListMediaCharacters? characters = jsonConvert
.convert<AnimeDetailsGraphqlDtoDataMediaListMediaCharacters>(
json['characters']);
if (characters != null) {
animeDetailsGraphqlDtoDataMediaListMedia.characters = characters;
}
return animeDetailsGraphqlDtoDataMediaListMedia;
}
Map<String, dynamic> $AnimeDetailsGraphqlDtoDataMediaListMediaToJson(
AnimeDetailsGraphqlDtoDataMediaListMedia entity) {
final Map<String, dynamic> data = <String, dynamic>{};
data['recommendations'] = entity.recommendations.toJson();
data['characters'] = entity.characters.toJson();
return data;
}
extension AnimeDetailsGraphqlDtoDataMediaListMediaExtension on AnimeDetailsGraphqlDtoDataMediaListMedia {
AnimeDetailsGraphqlDtoDataMediaListMedia copyWith({
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendations? recommendations,
AnimeDetailsGraphqlDtoDataMediaListMediaCharacters? characters,
}) {
return AnimeDetailsGraphqlDtoDataMediaListMedia()
..recommendations = recommendations ?? this.recommendations
..characters = characters ?? this.characters;
}
}
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendations $AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsFromJson(
Map<String, dynamic> json) {
final AnimeDetailsGraphqlDtoDataMediaListMediaRecommendations animeDetailsGraphqlDtoDataMediaListMediaRecommendations = AnimeDetailsGraphqlDtoDataMediaListMediaRecommendations();
final List<
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodes>? nodes = (json['nodes'] as List<
dynamic>?)
?.map(
(e) =>
jsonConvert.convert<
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodes>(
e) as AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodes)
.toList();
if (nodes != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendations.nodes = nodes;
}
return animeDetailsGraphqlDtoDataMediaListMediaRecommendations;
}
Map<String,
dynamic> $AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsToJson(
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendations entity) {
final Map<String, dynamic> data = <String, dynamic>{};
data['nodes'] = entity.nodes.map((v) => v.toJson()).toList();
return data;
}
extension AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsExtension on AnimeDetailsGraphqlDtoDataMediaListMediaRecommendations {
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendations copyWith({
List<AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodes>? nodes,
}) {
return AnimeDetailsGraphqlDtoDataMediaListMediaRecommendations()
..nodes = nodes ?? this.nodes;
}
}
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodes $AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesFromJson(
Map<String, dynamic> json) {
final AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodes animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodes = AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodes();
final AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation? mediaRecommendation = jsonConvert
.convert<
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation>(
json['mediaRecommendation']);
if (mediaRecommendation != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodes
.mediaRecommendation = mediaRecommendation;
}
return animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodes;
}
Map<String,
dynamic> $AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesToJson(
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodes entity) {
final Map<String, dynamic> data = <String, dynamic>{};
data['mediaRecommendation'] = entity.mediaRecommendation.toJson();
return data;
}
extension AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesExtension on AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodes {
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodes copyWith({
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation? mediaRecommendation,
}) {
return AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodes()
..mediaRecommendation = mediaRecommendation ?? this.mediaRecommendation;
}
}
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation $AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationFromJson(
Map<String, dynamic> json) {
final AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation = AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation();
final int? id = jsonConvert.convert<int>(json['id']);
if (id != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation
.id = id;
}
final int? idMal = jsonConvert.convert<int>(json['idMal']);
if (idMal != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation
.idMal = idMal;
}
final AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationStartDate? startDate = jsonConvert
.convert<
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationStartDate>(
json['startDate']);
if (startDate != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation
.startDate = startDate;
}
final AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationEndDate? endDate = jsonConvert
.convert<
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationEndDate>(
json['endDate']);
if (endDate != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation
.endDate = endDate;
}
final String? season = jsonConvert.convert<String>(json['season']);
if (season != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation
.season = season;
}
final String? status = jsonConvert.convert<String>(json['status']);
if (status != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation
.status = status;
}
final bool? isFavourite = jsonConvert.convert<bool>(json['isFavourite']);
if (isFavourite != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation
.isFavourite = isFavourite;
}
final bool? isAdult = jsonConvert.convert<bool>(json['isAdult']);
if (isAdult != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation
.isAdult = isAdult;
}
final int? episodes = jsonConvert.convert<int>(json['episodes']);
if (episodes != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation
.episodes = episodes;
}
final AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationTitle? title = jsonConvert
.convert<
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationTitle>(
json['title']);
if (title != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation
.title = title;
}
final String? bannerImage = jsonConvert.convert<String>(json['bannerImage']);
if (bannerImage != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation
.bannerImage = bannerImage;
}
final AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationCoverImage? coverImage = jsonConvert
.convert<
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationCoverImage>(
json['coverImage']);
if (coverImage != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation
.coverImage = coverImage;
}
final int? averageScore = jsonConvert.convert<int>(json['averageScore']);
if (averageScore != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation
.averageScore = averageScore;
}
final int? duration = jsonConvert.convert<int>(json['duration']);
if (duration != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation
.duration = duration;
}
final String? format = jsonConvert.convert<String>(json['format']);
if (format != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation
.format = format;
}
final List<String>? genres = (json['genres'] as List<dynamic>?)?.map(
(e) => jsonConvert.convert<String>(e) as String).toList();
if (genres != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation
.genres = genres;
}
final String? description = jsonConvert.convert<String>(json['description']);
if (description != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation
.description = description;
}
final int? meanScore = jsonConvert.convert<int>(json['meanScore']);
if (meanScore != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation
.meanScore = meanScore;
}
final dynamic nextAiringEpisode = json['nextAiringEpisode'];
if (nextAiringEpisode != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation
.nextAiringEpisode = nextAiringEpisode;
}
return animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation;
}
Map<String,
dynamic> $AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationToJson(
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation entity) {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = entity.id;
data['idMal'] = entity.idMal;
data['startDate'] = entity.startDate.toJson();
data['endDate'] = entity.endDate.toJson();
data['season'] = entity.season;
data['status'] = entity.status;
data['isFavourite'] = entity.isFavourite;
data['isAdult'] = entity.isAdult;
data['episodes'] = entity.episodes;
data['title'] = entity.title.toJson();
data['bannerImage'] = entity.bannerImage;
data['coverImage'] = entity.coverImage.toJson();
data['averageScore'] = entity.averageScore;
data['duration'] = entity.duration;
data['format'] = entity.format;
data['genres'] = entity.genres;
data['description'] = entity.description;
data['meanScore'] = entity.meanScore;
data['nextAiringEpisode'] = entity.nextAiringEpisode;
return data;
}
extension AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationExtension on AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation {
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation copyWith(
{
int? id,
int? idMal,
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationStartDate? startDate,
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationEndDate? endDate,
String? season,
String? status,
bool? isFavourite,
bool? isAdult,
int? episodes,
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationTitle? title,
String? bannerImage,
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationCoverImage? coverImage,
int? averageScore,
int? duration,
String? format,
List<String>? genres,
String? description,
int? meanScore,
dynamic nextAiringEpisode,
}) {
return AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation()
..id = id ?? this.id
..idMal = idMal ?? this.idMal
..startDate = startDate ?? this.startDate
..endDate = endDate ?? this.endDate
..season = season ?? this.season
..status = status ?? this.status
..isFavourite = isFavourite ?? this.isFavourite
..isAdult = isAdult ?? this.isAdult
..episodes = episodes ?? this.episodes
..title = title ?? this.title
..bannerImage = bannerImage ?? this.bannerImage
..coverImage = coverImage ?? this.coverImage
..averageScore = averageScore ?? this.averageScore
..duration = duration ?? this.duration
..format = format ?? this.format
..genres = genres ?? this.genres
..description = description ?? this.description
..meanScore = meanScore ?? this.meanScore
..nextAiringEpisode = nextAiringEpisode ?? this.nextAiringEpisode;
}
}
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationStartDate $AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationStartDateFromJson(
Map<String, dynamic> json) {
final AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationStartDate animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationStartDate = AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationStartDate();
final int? day = jsonConvert.convert<int>(json['day']);
if (day != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationStartDate
.day = day;
}
final int? month = jsonConvert.convert<int>(json['month']);
if (month != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationStartDate
.month = month;
}
final int? year = jsonConvert.convert<int>(json['year']);
if (year != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationStartDate
.year = year;
}
return animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationStartDate;
}
Map<String,
dynamic> $AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationStartDateToJson(
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationStartDate entity) {
final Map<String, dynamic> data = <String, dynamic>{};
data['day'] = entity.day;
data['month'] = entity.month;
data['year'] = entity.year;
return data;
}
extension AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationStartDateExtension on AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationStartDate {
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationStartDate copyWith(
{
int? day,
int? month,
int? year,
}) {
return AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationStartDate()
..day = day ?? this.day
..month = month ?? this.month
..year = year ?? this.year;
}
}
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationEndDate $AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationEndDateFromJson(
Map<String, dynamic> json) {
final AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationEndDate animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationEndDate = AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationEndDate();
final int? day = jsonConvert.convert<int>(json['day']);
if (day != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationEndDate
.day = day;
}
final int? month = jsonConvert.convert<int>(json['month']);
if (month != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationEndDate
.month = month;
}
final int? year = jsonConvert.convert<int>(json['year']);
if (year != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationEndDate
.year = year;
}
return animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationEndDate;
}
Map<String,
dynamic> $AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationEndDateToJson(
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationEndDate entity) {
final Map<String, dynamic> data = <String, dynamic>{};
data['day'] = entity.day;
data['month'] = entity.month;
data['year'] = entity.year;
return data;
}
extension AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationEndDateExtension on AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationEndDate {
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationEndDate copyWith(
{
int? day,
int? month,
int? year,
}) {
return AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationEndDate()
..day = day ?? this.day
..month = month ?? this.month
..year = year ?? this.year;
}
}
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationTitle $AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationTitleFromJson(
Map<String, dynamic> json) {
final AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationTitle animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationTitle = AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationTitle();
final String? english = jsonConvert.convert<String>(json['english']);
if (english != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationTitle
.english = english;
}
final String? native = jsonConvert.convert<String>(json['native']);
if (native != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationTitle
.native = native;
}
final String? romaji = jsonConvert.convert<String>(json['romaji']);
if (romaji != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationTitle
.romaji = romaji;
}
final String? userPreferred = jsonConvert.convert<String>(
json['userPreferred']);
if (userPreferred != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationTitle
.userPreferred = userPreferred;
}
return animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationTitle;
}
Map<String,
dynamic> $AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationTitleToJson(
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationTitle entity) {
final Map<String, dynamic> data = <String, dynamic>{};
data['english'] = entity.english;
data['native'] = entity.native;
data['romaji'] = entity.romaji;
data['userPreferred'] = entity.userPreferred;
return data;
}
extension AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationTitleExtension on AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationTitle {
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationTitle copyWith(
{
String? english,
String? native,
String? romaji,
String? userPreferred,
}) {
return AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationTitle()
..english = english ?? this.english
..native = native ?? this.native
..romaji = romaji ?? this.romaji
..userPreferred = userPreferred ?? this.userPreferred;
}
}
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationCoverImage $AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationCoverImageFromJson(
Map<String, dynamic> json) {
final AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationCoverImage animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationCoverImage = AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationCoverImage();
final String? large = jsonConvert.convert<String>(json['large']);
if (large != null) {
animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationCoverImage
.large = large;
}
return animeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationCoverImage;
}
Map<String,
dynamic> $AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationCoverImageToJson(
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationCoverImage entity) {
final Map<String, dynamic> data = <String, dynamic>{};
data['large'] = entity.large;
return data;
}
extension AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationCoverImageExtension on AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationCoverImage {
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationCoverImage copyWith(
{
String? large,
}) {
return AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationCoverImage()
..large = large ?? this.large;
}
}
AnimeDetailsGraphqlDtoDataMediaListMediaCharacters $AnimeDetailsGraphqlDtoDataMediaListMediaCharactersFromJson(
Map<String, dynamic> json) {
final AnimeDetailsGraphqlDtoDataMediaListMediaCharacters animeDetailsGraphqlDtoDataMediaListMediaCharacters = AnimeDetailsGraphqlDtoDataMediaListMediaCharacters();
final List<
AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodes>? nodes = (json['nodes'] as List<
dynamic>?)
?.map(
(e) =>
jsonConvert.convert<
AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodes>(
e) as AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodes)
.toList();
if (nodes != null) {
animeDetailsGraphqlDtoDataMediaListMediaCharacters.nodes = nodes;
}
return animeDetailsGraphqlDtoDataMediaListMediaCharacters;
}
Map<String, dynamic> $AnimeDetailsGraphqlDtoDataMediaListMediaCharactersToJson(
AnimeDetailsGraphqlDtoDataMediaListMediaCharacters entity) {
final Map<String, dynamic> data = <String, dynamic>{};
data['nodes'] = entity.nodes.map((v) => v.toJson()).toList();
return data;
}
extension AnimeDetailsGraphqlDtoDataMediaListMediaCharactersExtension on AnimeDetailsGraphqlDtoDataMediaListMediaCharacters {
AnimeDetailsGraphqlDtoDataMediaListMediaCharacters copyWith({
List<AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodes>? nodes,
}) {
return AnimeDetailsGraphqlDtoDataMediaListMediaCharacters()
..nodes = nodes ?? this.nodes;
}
}
AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodes $AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesFromJson(
Map<String, dynamic> json) {
final AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodes animeDetailsGraphqlDtoDataMediaListMediaCharactersNodes = AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodes();
final int? id = jsonConvert.convert<int>(json['id']);
if (id != null) {
animeDetailsGraphqlDtoDataMediaListMediaCharactersNodes.id = id;
}
final AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesImage? image = jsonConvert
.convert<AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesImage>(
json['image']);
if (image != null) {
animeDetailsGraphqlDtoDataMediaListMediaCharactersNodes.image = image;
}
final AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesName? name = jsonConvert
.convert<AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesName>(
json['name']);
if (name != null) {
animeDetailsGraphqlDtoDataMediaListMediaCharactersNodes.name = name;
}
final String? gender = jsonConvert.convert<String>(json['gender']);
if (gender != null) {
animeDetailsGraphqlDtoDataMediaListMediaCharactersNodes.gender = gender;
}
final String? description = jsonConvert.convert<String>(json['description']);
if (description != null) {
animeDetailsGraphqlDtoDataMediaListMediaCharactersNodes.description =
description;
}
final AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesDateOfBirth? dateOfBirth = jsonConvert
.convert<
AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesDateOfBirth>(
json['dateOfBirth']);
if (dateOfBirth != null) {
animeDetailsGraphqlDtoDataMediaListMediaCharactersNodes.dateOfBirth =
dateOfBirth;
}
final String? age = jsonConvert.convert<String>(json['age']);
if (age != null) {
animeDetailsGraphqlDtoDataMediaListMediaCharactersNodes.age = age;
}
return animeDetailsGraphqlDtoDataMediaListMediaCharactersNodes;
}
Map<String,
dynamic> $AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesToJson(
AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodes entity) {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = entity.id;
data['image'] = entity.image.toJson();
data['name'] = entity.name.toJson();
data['gender'] = entity.gender;
data['description'] = entity.description;
data['dateOfBirth'] = entity.dateOfBirth.toJson();
data['age'] = entity.age;
return data;
}
extension AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesExtension on AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodes {
AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodes copyWith({
int? id,
AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesImage? image,
AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesName? name,
String? gender,
String? description,
AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesDateOfBirth? dateOfBirth,
String? age,
}) {
return AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodes()
..id = id ?? this.id
..image = image ?? this.image
..name = name ?? this.name
..gender = gender ?? this.gender
..description = description ?? this.description
..dateOfBirth = dateOfBirth ?? this.dateOfBirth
..age = age ?? this.age;
}
}
AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesImage $AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesImageFromJson(
Map<String, dynamic> json) {
final AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesImage animeDetailsGraphqlDtoDataMediaListMediaCharactersNodesImage = AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesImage();
final String? large = jsonConvert.convert<String>(json['large']);
if (large != null) {
animeDetailsGraphqlDtoDataMediaListMediaCharactersNodesImage.large = large;
}
return animeDetailsGraphqlDtoDataMediaListMediaCharactersNodesImage;
}
Map<String,
dynamic> $AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesImageToJson(
AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesImage entity) {
final Map<String, dynamic> data = <String, dynamic>{};
data['large'] = entity.large;
return data;
}
extension AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesImageExtension on AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesImage {
AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesImage copyWith({
String? large,
}) {
return AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesImage()
..large = large ?? this.large;
}
}
AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesName $AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesNameFromJson(
Map<String, dynamic> json) {
final AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesName animeDetailsGraphqlDtoDataMediaListMediaCharactersNodesName = AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesName();
final String? userPreferred = jsonConvert.convert<String>(
json['userPreferred']);
if (userPreferred != null) {
animeDetailsGraphqlDtoDataMediaListMediaCharactersNodesName.userPreferred =
userPreferred;
}
return animeDetailsGraphqlDtoDataMediaListMediaCharactersNodesName;
}
Map<String,
dynamic> $AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesNameToJson(
AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesName entity) {
final Map<String, dynamic> data = <String, dynamic>{};
data['userPreferred'] = entity.userPreferred;
return data;
}
extension AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesNameExtension on AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesName {
AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesName copyWith({
String? userPreferred,
}) {
return AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesName()
..userPreferred = userPreferred ?? this.userPreferred;
}
}
AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesDateOfBirth $AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesDateOfBirthFromJson(
Map<String, dynamic> json) {
final AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesDateOfBirth animeDetailsGraphqlDtoDataMediaListMediaCharactersNodesDateOfBirth = AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesDateOfBirth();
final dynamic day = json['day'];
if (day != null) {
animeDetailsGraphqlDtoDataMediaListMediaCharactersNodesDateOfBirth.day =
day;
}
final dynamic month = json['month'];
if (month != null) {
animeDetailsGraphqlDtoDataMediaListMediaCharactersNodesDateOfBirth.month =
month;
}
final dynamic year = json['year'];
if (year != null) {
animeDetailsGraphqlDtoDataMediaListMediaCharactersNodesDateOfBirth.year =
year;
}
return animeDetailsGraphqlDtoDataMediaListMediaCharactersNodesDateOfBirth;
}
Map<String,
dynamic> $AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesDateOfBirthToJson(
AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesDateOfBirth entity) {
final Map<String, dynamic> data = <String, dynamic>{};
data['day'] = entity.day;
data['month'] = entity.month;
data['year'] = entity.year;
return data;
}
extension AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesDateOfBirthExtension on AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesDateOfBirth {
AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesDateOfBirth copyWith({
dynamic day,
dynamic month,
dynamic year,
}) {
return AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesDateOfBirth()
..day = day ?? this.day
..month = month ?? this.month
..year = year ?? this.year;
}
}

View File

@@ -4,6 +4,7 @@
// This file is automatically generated. DO NOT EDIT, all your changes would be lost.
import 'package:flutter/material.dart' show debugPrint;
import 'package:unyo/core/services/api/dto/anime_details_graphql_dto_entity.dart';
import 'package:unyo/core/services/api/dto/media_collection_graphql_dto_entity.dart';
import 'package:unyo/core/services/api/dto/media_collection_recently_completed_graphql_dto_entity.dart';
import 'package:unyo/core/services/api/dto/media_collection_recently_released_graphql_dto_entity.dart';
@@ -148,6 +149,119 @@ class JsonConvert {
//list is returned by type
static M? _getListChildType<M>(List<Map<String, dynamic>> data) {
if (<AnimeDetailsGraphqlDtoEntity>[] is M) {
return data.map<AnimeDetailsGraphqlDtoEntity>((Map<String, dynamic> e) =>
AnimeDetailsGraphqlDtoEntity.fromJson(e)).toList() as M;
}
if (<AnimeDetailsGraphqlDtoData>[] is M) {
return data.map<AnimeDetailsGraphqlDtoData>((Map<String, dynamic> e) =>
AnimeDetailsGraphqlDtoData.fromJson(e)).toList() as M;
}
if (<AnimeDetailsGraphqlDtoDataMediaList>[] is M) {
return data.map<AnimeDetailsGraphqlDtoDataMediaList>((
Map<String, dynamic> e) =>
AnimeDetailsGraphqlDtoDataMediaList.fromJson(e)).toList() as M;
}
if (<AnimeDetailsGraphqlDtoDataMediaListMedia>[] is M) {
return data.map<AnimeDetailsGraphqlDtoDataMediaListMedia>((
Map<String, dynamic> e) =>
AnimeDetailsGraphqlDtoDataMediaListMedia.fromJson(e)).toList() as M;
}
if (<AnimeDetailsGraphqlDtoDataMediaListMediaRecommendations>[] is M) {
return data
.map<AnimeDetailsGraphqlDtoDataMediaListMediaRecommendations>((
Map<String, dynamic> e) =>
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendations.fromJson(e))
.toList() as M;
}
if (<AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodes>[] is M) {
return data.map<
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodes>((
Map<String, dynamic> e) =>
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodes.fromJson(
e)).toList() as M;
}
if (<
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation>[
] is M) {
return data.map<
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation>((
Map<String, dynamic> e) =>
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation
.fromJson(e)).toList() as M;
}
if (<
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationStartDate>[
] is M) {
return data.map<
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationStartDate>((
Map<String, dynamic> e) =>
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationStartDate
.fromJson(e)).toList() as M;
}
if (<
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationEndDate>[
] is M) {
return data.map<
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationEndDate>((
Map<String, dynamic> e) =>
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationEndDate
.fromJson(e)).toList() as M;
}
if (<
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationTitle>[
] is M) {
return data.map<
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationTitle>((
Map<String, dynamic> e) =>
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationTitle
.fromJson(e)).toList() as M;
}
if (<
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationCoverImage>[
] is M) {
return data.map<
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationCoverImage>((
Map<String, dynamic> e) =>
AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationCoverImage
.fromJson(e)).toList() as M;
}
if (<AnimeDetailsGraphqlDtoDataMediaListMediaCharacters>[] is M) {
return data
.map<AnimeDetailsGraphqlDtoDataMediaListMediaCharacters>((
Map<String, dynamic> e) =>
AnimeDetailsGraphqlDtoDataMediaListMediaCharacters.fromJson(e))
.toList() as M;
}
if (<AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodes>[] is M) {
return data
.map<AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodes>((
Map<String, dynamic> e) =>
AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodes.fromJson(e))
.toList() as M;
}
if (<AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesImage>[] is M) {
return data.map<
AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesImage>((
Map<String, dynamic> e) =>
AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesImage.fromJson(
e)).toList() as M;
}
if (<AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesName>[] is M) {
return data.map<
AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesName>((
Map<String, dynamic> e) =>
AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesName.fromJson(
e)).toList() as M;
}
if (<AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesDateOfBirth>[
] is M) {
return data.map<
AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesDateOfBirth>((
Map<String, dynamic> e) =>
AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesDateOfBirth
.fromJson(e)).toList() as M;
}
if (<MediaCollectionGraphqlDtoEntity>[] is M) {
return data.map<MediaCollectionGraphqlDtoEntity>((
Map<String, dynamic> e) =>
@@ -500,6 +614,50 @@ class JsonConvert {
class JsonConvertClassCollection {
Map<String, JsonConvertFunction> convertFuncMap = {
(AnimeDetailsGraphqlDtoEntity).toString(): AnimeDetailsGraphqlDtoEntity
.fromJson,
(AnimeDetailsGraphqlDtoData).toString(): AnimeDetailsGraphqlDtoData
.fromJson,
(AnimeDetailsGraphqlDtoDataMediaList)
.toString(): AnimeDetailsGraphqlDtoDataMediaList.fromJson,
(AnimeDetailsGraphqlDtoDataMediaListMedia)
.toString(): AnimeDetailsGraphqlDtoDataMediaListMedia.fromJson,
(AnimeDetailsGraphqlDtoDataMediaListMediaRecommendations)
.toString(): AnimeDetailsGraphqlDtoDataMediaListMediaRecommendations
.fromJson,
(AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodes)
.toString(): AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodes
.fromJson,
(AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation)
.toString(): AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendation
.fromJson,
(AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationStartDate)
.toString(): AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationStartDate
.fromJson,
(AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationEndDate)
.toString(): AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationEndDate
.fromJson,
(AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationTitle)
.toString(): AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationTitle
.fromJson,
(AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationCoverImage)
.toString(): AnimeDetailsGraphqlDtoDataMediaListMediaRecommendationsNodesMediaRecommendationCoverImage
.fromJson,
(AnimeDetailsGraphqlDtoDataMediaListMediaCharacters)
.toString(): AnimeDetailsGraphqlDtoDataMediaListMediaCharacters
.fromJson,
(AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodes)
.toString(): AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodes
.fromJson,
(AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesImage)
.toString(): AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesImage
.fromJson,
(AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesName)
.toString(): AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesName
.fromJson,
(AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesDateOfBirth)
.toString(): AnimeDetailsGraphqlDtoDataMediaListMediaCharactersNodesDateOfBirth
.fromJson,
(MediaCollectionGraphqlDtoEntity)
.toString(): MediaCollectionGraphqlDtoEntity.fromJson,
(MediaCollectionGraphqlDtoData).toString(): MediaCollectionGraphqlDtoData

View File

@@ -4,9 +4,9 @@
import 'package:hive_ce/hive.dart';
import 'package:unyo/core/enums/service.dart';
import 'package:unyo/data/models/anilist_anime_details.dart';
import 'package:unyo/data/models/anilist_user_model.dart';
import 'package:unyo/data/models/local_user_model.dart';
import 'package:unyo/domain/entities/anime_progress.dart';
import 'package:unyo/domain/entities/media_list.dart';
import 'package:unyo/domain/entities/settings.dart';

View File

@@ -9,8 +9,11 @@ import 'package:unyo/application/cubits/anime_details_cubit.dart';
import 'package:unyo/application/states/anime_details_state.dart';
import 'package:unyo/core/di/locator.dart';
import 'package:unyo/core/services/effects/app_effect_handler.dart';
import 'package:unyo/presentation/widgets/styled/anime_recommendations_card_list.dart';
import 'package:unyo/presentation/widgets/styled/styled.dart';
import 'package:unyo/presentation/widgets/styled/unyo_banner.dart';
import 'package:unyo/presentation/widgets/styled/unyo_character.dart';
import 'package:unyo/presentation/widgets/styled/unyo_character_list.dart';
import 'package:unyo/presentation/widgets/text/text_utils.dart';
@RoutePage()
@@ -37,7 +40,9 @@ class _AnimeDetailsListener extends StatelessWidget {
sl<AppEffectHandler>().handleEffects(
context,
state.effects,
context.read<AnimeDetailsCubit>().clearEffects,
context
.read<AnimeDetailsCubit>()
.clearEffects,
);
}
},
@@ -56,6 +61,16 @@ class _AnimeDetailsView extends StatefulWidget {
}
class _AnimeDetailsViewState extends State<_AnimeDetailsView> {
final ScrollController charactersListController = ScrollController();
final ScrollController recommendedAnimesController = ScrollController();
@override
void dispose() {
charactersListController.dispose();
recommendedAnimesController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return BlocBuilder<AnimeDetailsCubit, AnimeDetailsState>(
@@ -80,9 +95,9 @@ class _AnimeDetailsViewState extends State<_AnimeDetailsView> {
child: IconButton(
onPressed:
() =>
context
.read<AnimeDetailsCubit>()
.navigateBackToAnimePage(),
context
.read<AnimeDetailsCubit>()
.navigateBackToAnimePage(),
icon: Icon(Icons.arrow_back, color: Colors.white),
),
),
@@ -100,28 +115,41 @@ class _AnimeDetailsViewState extends State<_AnimeDetailsView> {
Expanded(
child: ListView(
children: [
Stack(
alignment: Alignment.topLeft,
children: [
UnyoBanner(
imageUrl: state.selectedAnime.bannerImage,
duration: "${state.selectedAnime.duration}min",
year: TextUtils.extractYearFromStartDate(state.selectedAnime.startDate, state.loggedUser),
score: state.selectedAnime.averageScore.toString(),
description: state.selectedAnime.description,
),
Padding(
padding: EdgeInsets.only(left: 60.w, top: 140.h),
child: ImageCard(
coverImage:
state.selectedAnime.coverImage,
title: state.selectedAnime.title.userPreferred,
status: state.selectedAnime.status,
tag: "${state.selectedMediaList.name}-${state.selectedAnime.id}",
),
),
],
UnyoBanner(
imageUrl: state.selectedAnime.bannerImage,
duration:
"${state.selectedAnime.duration}min",
year: TextUtils.extractYearFromStartDate(
state.selectedAnime.startDate,
state.loggedUser,
),
score:
state.selectedAnime.averageScore
.toString(),
description: state.selectedAnime.description,
coverImage: state.selectedAnime.coverImage,
title:
state.selectedAnime.title.userPreferred,
status: state.selectedAnime.status,
tag:
"${state.selectedMediaList.name}-${state
.selectedAnime.id}",
),
SizedBox(height: 50.h),
state.characters.$1
? UnyoCharacterList(
characters: state.characters.$2,
controller: charactersListController,
)
: const SizedBox.shrink(),
SizedBox(height: 20.h),
state.recommendations.$1 ? AnimeRecommendationCardList(
onPressed: context.read<AnimeDetailsCubit>().navigateToAnimeDetails,
listTitle: "Recommended Animes",
animeList: state.recommendations.$2,
controller: recommendedAnimesController,
loadMore: false
) : const SizedBox.shrink(),
],
),
),
@@ -149,7 +177,7 @@ class _AnimeDetailsViewState extends State<_AnimeDetailsView> {
UnyoEpisodeButton(
episodeName: "Episode 1 Name",
episodeImageUrl:
"https://s4.anilist.co/file/anilistcdn/media/anime/banner/114124-44utnIatIX16.jpg",
"https://s4.anilist.co/file/anilistcdn/media/anime/banner/114124-44utnIatIX16.jpg",
episodeNumber: 1,
progress: 1,
released: 1,
@@ -158,7 +186,7 @@ class _AnimeDetailsViewState extends State<_AnimeDetailsView> {
UnyoEpisodeButton(
episodeName: "Episode 2 Name",
episodeImageUrl:
"https://s4.anilist.co/file/anilistcdn/media/anime/banner/114124-44utnIatIX16.jpg",
"https://s4.anilist.co/file/anilistcdn/media/anime/banner/114124-44utnIatIX16.jpg",
episodeNumber: 2,
progress: 1,
released: 2,
@@ -167,7 +195,7 @@ class _AnimeDetailsViewState extends State<_AnimeDetailsView> {
UnyoEpisodeButton(
episodeName: "Episode 2 Name",
episodeImageUrl:
"https://s4.anilist.co/file/anilistcdn/media/anime/banner/114124-44utnIatIX16.jpg",
"https://s4.anilist.co/file/anilistcdn/media/anime/banner/114124-44utnIatIX16.jpg",
episodeNumber: 2,
progress: 1,
released: 2,
@@ -176,7 +204,7 @@ class _AnimeDetailsViewState extends State<_AnimeDetailsView> {
UnyoEpisodeButton(
episodeName: "Episode 2 Name",
episodeImageUrl:
"https://s4.anilist.co/file/anilistcdn/media/anime/banner/114124-44utnIatIX16.jpg",
"https://s4.anilist.co/file/anilistcdn/media/anime/banner/114124-44utnIatIX16.jpg",
episodeNumber: 2,
progress: 1,
released: 2,
@@ -185,7 +213,7 @@ class _AnimeDetailsViewState extends State<_AnimeDetailsView> {
UnyoEpisodeButton(
episodeName: "Episode 2 Name",
episodeImageUrl:
"https://s4.anilist.co/file/anilistcdn/media/anime/banner/114124-44utnIatIX16.jpg",
"https://s4.anilist.co/file/anilistcdn/media/anime/banner/114124-44utnIatIX16.jpg",
episodeNumber: 2,
progress: 1,
released: 2,
@@ -194,7 +222,7 @@ class _AnimeDetailsViewState extends State<_AnimeDetailsView> {
UnyoEpisodeButton(
episodeName: "Episode 2 Name",
episodeImageUrl:
"https://s4.anilist.co/file/anilistcdn/media/anime/banner/114124-44utnIatIX16.jpg",
"https://s4.anilist.co/file/anilistcdn/media/anime/banner/114124-44utnIatIX16.jpg",
episodeNumber: 2,
progress: 1,
released: 2,
@@ -203,7 +231,7 @@ class _AnimeDetailsViewState extends State<_AnimeDetailsView> {
UnyoEpisodeButton(
episodeName: "Episode 2 Name",
episodeImageUrl:
"https://s4.anilist.co/file/anilistcdn/media/anime/banner/114124-44utnIatIX16.jpg",
"https://s4.anilist.co/file/anilistcdn/media/anime/banner/114124-44utnIatIX16.jpg",
episodeNumber: 2,
progress: 1,
released: 2,
@@ -212,7 +240,7 @@ class _AnimeDetailsViewState extends State<_AnimeDetailsView> {
UnyoEpisodeButton(
episodeName: "Episode 2 Name",
episodeImageUrl:
"https://s4.anilist.co/file/anilistcdn/media/anime/banner/114124-44utnIatIX16.jpg",
"https://s4.anilist.co/file/anilistcdn/media/anime/banner/114124-44utnIatIX16.jpg",
episodeNumber: 2,
progress: 1,
released: 2,
@@ -221,7 +249,7 @@ class _AnimeDetailsViewState extends State<_AnimeDetailsView> {
UnyoEpisodeButton(
episodeName: "Episode 2 Name",
episodeImageUrl:
"https://s4.anilist.co/file/anilistcdn/media/anime/banner/114124-44utnIatIX16.jpg",
"https://s4.anilist.co/file/anilistcdn/media/anime/banner/114124-44utnIatIX16.jpg",
episodeNumber: 2,
progress: 1,
released: 2,

View File

@@ -0,0 +1,90 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:unyo/core/enums/media_type.dart';
import 'package:unyo/domain/entities/anime.dart';
import 'package:unyo/domain/entities/media_list.dart';
import 'package:unyo/presentation/widgets/styled/media_card.dart';
import 'package:unyo/presentation/widgets/styled/media_list_arrows.dart';
class AnimeRecommendationCardList extends StatelessWidget {
final void Function(Anime, MediaList) onPressed;
final String listTitle;
final List<Anime> animeList;
final ScrollController controller;
final bool loadMore;
const AnimeRecommendationCardList({
super.key,
required this.onPressed,
required this.listTitle,
required this.animeList,
required this.controller,
required this.loadMore,
});
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.only(left: 35.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: 0.75.sw,
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Text(
listTitle,
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
color: ColorScheme.of(context).tertiary,
),
),
Text(
" ${animeList.length.toString()} ${context.tr("entries")}",
style: const TextStyle(
fontSize: 13,
fontWeight: FontWeight.normal,
color: Colors.grey,
),
),
Spacer(),
MediaListArrows(
controller: controller,
visible: animeList.length * 144 > 0.75.sw,
),
],
),
),
SizedBox(height: 10.h,),
SizedBox(
height: 260,
width: 1.sw - 140,
child: ListView(
scrollDirection: Axis.horizontal,
controller: controller,
children: [
...animeList.map(
(anime) => MediaCard(
title: anime.title.romaji,
score: anime.averageScore,
coverImage: anime.coverImage,
onPressed: () => onPressed(anime, MediaListModel(name: listTitle, mediaType: MediaType.anime)),
status: anime.status,
year: anime.startDate,
format: anime.format,
tag: "$listTitle-${anime.id}",
),
),
// TODO loadMore Widget
],
),
),
],
),
);
}
}

View File

@@ -10,7 +10,23 @@ class UnyoBanner extends StatelessWidget {
final String year;
final String score;
final String description;
const UnyoBanner({super.key, required this.imageUrl, required this.duration, required this.year, required this.score, required this.description});
final String coverImage;
final String title;
final String status;
final String tag;
const UnyoBanner({
super.key,
required this.imageUrl,
required this.duration,
required this.year,
required this.score,
required this.description,
required this.coverImage,
required this.title,
required this.status,
required this.tag
});
@override
Widget build(BuildContext context) {
@@ -30,17 +46,26 @@ class UnyoBanner extends StatelessWidget {
) : const SizedBox.shrink(),
Container(
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.4),
color: Colors.black.withOpacity(0.5),
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Colors.transparent,
Colors.black.withOpacity(0.8),
Colors.black,
],
),
),
),
Padding(
padding: EdgeInsets.only(bottom: 16.h, left: 24.w),
child: ImageCard(
coverImage: coverImage,
title: title,
status: status,
tag: tag,
),
),
],
),
),

View File

@@ -0,0 +1,80 @@
import 'package:flutter/material.dart';
import 'package:unyo/presentation/widgets/styled/hover_animated_container.dart';
class UnyoCharacter extends StatelessWidget {
final String tag;
final String name;
final String image;
final void Function()? onPressed;
const UnyoCharacter({super.key, required this.tag, required this.onPressed, required this.image, required this.name});
@override
Widget build(BuildContext context) {
return Hero(
tag: tag,
child: SizedBox(
width: 152.5,
height: 256,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
InkWell(
onTap: onPressed,
// TODO maybe Stack over HoverAnimatedContainer
child: Stack(
alignment: Alignment.bottomRight,
children: [
HoverAnimatedContainer(
width: 140.0 /*.w.clamp(144.08, 181.7)*/,
hoverWidth: 152.5 /*.w.clamp(156.49, 199.1)*/,
height: 200.5 /*.h.clamp(200.44, 260.6)*/,
hoverHeight: 213.0 /*.h.clamp(206.03, 268.44)*/,
hoverCursor: SystemMouseCursors.click,
hoverDecoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
border: Border.all(color: Colors.white, width: 2.6),
image: DecorationImage(
image: NetworkImage(image),
fit: BoxFit.fill,
),
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
image: DecorationImage(
image: NetworkImage(image),
fit: BoxFit.fill,
),
),
child: const SizedBox.shrink(),
),
],
),
),
SizedBox(
width: 140.0 /*.w.clamp(144.08, 181.7)*/,
height: 24,
child: Center(
child: Tooltip(
message: name,
waitDuration: Duration(milliseconds: 1000),
child: Text(
name,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 14,
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
),
),
],
),
),
);
}
}

View File

@@ -0,0 +1,73 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:unyo/domain/entities/media_character.dart' show MediaCharacter;
import 'package:unyo/presentation/widgets/styled/media_list_arrows.dart';
import 'package:unyo/presentation/widgets/styled/unyo_character.dart';
class UnyoCharacterList extends StatelessWidget {
final List<MediaCharacter> characters;
final ScrollController controller;
const UnyoCharacterList({super.key, required this.characters, required this.controller});
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.only(left: 35.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: 0.75.sw,
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Text(
"Characters",
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
color: ColorScheme.of(context).tertiary,
),
),
Text(
" ${characters.length.toString()} ${context.tr("entries")}",
style: const TextStyle(
fontSize: 13,
fontWeight: FontWeight.normal,
color: Colors.grey,
),
),
Spacer(),
MediaListArrows(
controller: controller,
visible: characters.length * 144 > (0.75.sw),
),
],
),
),
SizedBox(height: 10.h),
SizedBox(
height: 260,
width: 1.sw - 140,
child: ListView(
scrollDirection: Axis.horizontal,
controller: controller,
children: [
...characters.map(
(character) => UnyoCharacter(
tag: "${character.id}",
onPressed: null,
image: character.image,
name: character.name,
),
),
],
),
),
],
),
);
}
}