From 89f068326fd201c683a5d5cf548475bbde5c1599 Mon Sep 17 00:00:00 2001 From: Jiangqn Date: Tue, 10 Oct 2023 19:33:10 +0800 Subject: [PATCH 1/4] add media external links --- .../data/media_information_repository.dart | 14 + lib/core/data/model/anime_model.dart | 5 + lib/core/data/model/anime_model.freezed.dart | 47 ++- .../data/model/media_external_link_model.dart | 32 ++ .../media_external_link_model.freezed.dart | 244 ++++++++++++++ .../model/media_external_link_model.g.dart | 34 ++ .../data/model/media_external_link_type.dart | 12 + lib/core/database/anime_dao.dart | 38 +++ lib/core/database/anime_database.dart | 13 + .../model/media_external_link_entity.dart | 38 +++ .../media_external_link_entity.freezed.dart | 304 ++++++++++++++++++ .../model/media_external_link_entity.g.dart | 31 ++ .../relations/anime_and_detail_info.dart | 3 + .../design_system/widget/trailer_preview.dart | 4 +- .../vertical_animated_scale_switcher.dart | 5 +- lib/core/network/model/detail_anime_dto.dart | 4 + .../model/detail_anime_dto.freezed.dart | 93 ++++-- .../network/model/detail_anime_dto.g.dart | 6 + .../model/media_external_links_dto.dart | 21 ++ .../media_external_links_dto.freezed.dart | 299 +++++++++++++++++ .../model/media_external_links_dto.g.dart | 31 ++ lib/feature/detail_anime/detail_anime.dart | 292 +++++++++-------- .../repository/ani_lsit_repository_test.dart | 6 +- test/core/database/anime_database_test.dart | 24 ++ 24 files changed, 1418 insertions(+), 182 deletions(-) create mode 100644 lib/core/data/model/media_external_link_model.dart create mode 100644 lib/core/data/model/media_external_link_model.freezed.dart create mode 100644 lib/core/data/model/media_external_link_model.g.dart create mode 100644 lib/core/data/model/media_external_link_type.dart create mode 100644 lib/core/database/model/media_external_link_entity.dart create mode 100644 lib/core/database/model/media_external_link_entity.freezed.dart create mode 100644 lib/core/database/model/media_external_link_entity.g.dart create mode 100644 lib/core/network/model/media_external_links_dto.dart create mode 100644 lib/core/network/model/media_external_links_dto.freezed.dart create mode 100644 lib/core/network/model/media_external_links_dto.g.dart diff --git a/lib/core/data/media_information_repository.dart b/lib/core/data/media_information_repository.dart index fd40cd31..098f270f 100644 --- a/lib/core/data/media_information_repository.dart +++ b/lib/core/data/media_information_repository.dart @@ -5,10 +5,12 @@ import 'package:anime_tracker/core/data/model/airing_schedule_model.dart'; import 'package:anime_tracker/core/database/anime_database.dart'; import 'package:anime_tracker/core/database/model/airing_schedules_entity.dart'; import 'package:anime_tracker/core/database/model/character_entity.dart'; +import 'package:anime_tracker/core/database/model/media_external_link_entity.dart'; import 'package:anime_tracker/core/database/model/staff_entity.dart'; import 'package:anime_tracker/core/network/api/airing_schedules_query_graphql.dart.dart'; import 'package:anime_tracker/core/network/model/character_edge.dart'; import 'package:anime_tracker/core/network/model/detail_anime_dto.dart'; +import 'package:anime_tracker/core/network/model/media_external_links_dto.dart'; import 'package:anime_tracker/core/network/model/staff_edge.dart'; import 'package:anime_tracker/core/common/util/time_util.dart'; import 'package:dio/dio.dart'; @@ -230,6 +232,18 @@ class MediaInformationRepositoryImpl extends MediaInformationRepository { ); } + final List externalLinks = + networkResult.externalLinks; + /// insert external links to database. + if (externalLinks.isNotEmpty) { + final linkEntities = externalLinks + .map( + (e) => MediaExternalLinkEntity.fromDto(e, id), + ) + .toList(); + await animeDao.upsertMediaExternalLinks(externalLinks: linkEntities); + } + /// notify data base has been changed an trigger the streams. animeDao.notifyAnimeDetailInfoChanged(); return LoadSuccess(data: []); diff --git a/lib/core/data/model/anime_model.dart b/lib/core/data/model/anime_model.dart index 4ee9b9f1..531099c2 100644 --- a/lib/core/data/model/anime_model.dart +++ b/lib/core/data/model/anime_model.dart @@ -5,6 +5,7 @@ import 'package:anime_tracker/core/common/model/anime_source.dart'; import 'package:anime_tracker/core/common/model/anime_status.dart'; import 'package:anime_tracker/core/data/model/staff_and_role_model.dart'; import 'package:anime_tracker/core/data/model/trailter_model.dart'; +import 'package:anime_tracker/core/data/model/media_external_link_model.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:anime_tracker/core/data/model/anime_title_modle.dart'; @@ -40,6 +41,7 @@ class AnimeModel with _$AnimeModel { @Default(false) bool isFollowing, @Default([]) List characterAndVoiceActors, @Default([]) List staffs, + @Default([]) List externalLinks, }) = _DetailAnimeModel; static AnimeModel fromDatabaseModel(AnimeEntity model) { @@ -95,6 +97,9 @@ class AnimeModel with _$AnimeModel { staffs: model.staffs .map((e) => StaffAndRoleModel.fromDatabaseEntity(e)) .toList(), + externalLinks: model.externalLinks + .map((e) => MediaExternalLinkModel.fromEntity(e)) + .toList(), ); } } diff --git a/lib/core/data/model/anime_model.freezed.dart b/lib/core/data/model/anime_model.freezed.dart index 2e62dd0e..7ae0dafe 100644 --- a/lib/core/data/model/anime_model.freezed.dart +++ b/lib/core/data/model/anime_model.freezed.dart @@ -40,6 +40,8 @@ mixin _$AnimeModel { List get characterAndVoiceActors => throw _privateConstructorUsedError; List get staffs => throw _privateConstructorUsedError; + List get externalLinks => + throw _privateConstructorUsedError; @JsonKey(ignore: true) $AnimeModelCopyWith get copyWith => @@ -75,7 +77,8 @@ abstract class $AnimeModelCopyWith<$Res> { int? nextAiringEpisode, bool isFollowing, List characterAndVoiceActors, - List staffs}); + List staffs, + List externalLinks}); $AnimeTitleCopyWith<$Res>? get title; $TrailerModelCopyWith<$Res>? get trailerModel; @@ -117,6 +120,7 @@ class _$AnimeModelCopyWithImpl<$Res, $Val extends AnimeModel> Object? isFollowing = null, Object? characterAndVoiceActors = null, Object? staffs = null, + Object? externalLinks = null, }) { return _then(_value.copyWith( id: null == id @@ -211,6 +215,10 @@ class _$AnimeModelCopyWithImpl<$Res, $Val extends AnimeModel> ? _value.staffs : staffs // ignore: cast_nullable_to_non_nullable as List, + externalLinks: null == externalLinks + ? _value.externalLinks + : externalLinks // ignore: cast_nullable_to_non_nullable + as List, ) as $Val); } @@ -270,7 +278,8 @@ abstract class _$$_DetailAnimeModelCopyWith<$Res> int? nextAiringEpisode, bool isFollowing, List characterAndVoiceActors, - List staffs}); + List staffs, + List externalLinks}); @override $AnimeTitleCopyWith<$Res>? get title; @@ -312,6 +321,7 @@ class __$$_DetailAnimeModelCopyWithImpl<$Res> Object? isFollowing = null, Object? characterAndVoiceActors = null, Object? staffs = null, + Object? externalLinks = null, }) { return _then(_$_DetailAnimeModel( id: null == id @@ -406,6 +416,10 @@ class __$$_DetailAnimeModelCopyWithImpl<$Res> ? _value._staffs : staffs // ignore: cast_nullable_to_non_nullable as List, + externalLinks: null == externalLinks + ? _value._externalLinks + : externalLinks // ignore: cast_nullable_to_non_nullable + as List, )); } } @@ -437,11 +451,13 @@ class _$_DetailAnimeModel implements _DetailAnimeModel { this.isFollowing = false, final List characterAndVoiceActors = const [], - final List staffs = const []}) + final List staffs = const [], + final List externalLinks = const []}) : _hashtags = hashtags, _genres = genres, _characterAndVoiceActors = characterAndVoiceActors, - _staffs = staffs; + _staffs = staffs, + _externalLinks = externalLinks; @override @JsonKey() @@ -522,9 +538,18 @@ class _$_DetailAnimeModel implements _DetailAnimeModel { return EqualUnmodifiableListView(_staffs); } + final List _externalLinks; + @override + @JsonKey() + List get externalLinks { + if (_externalLinks is EqualUnmodifiableListView) return _externalLinks; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_externalLinks); + } + @override String toString() { - return 'AnimeModel(id: $id, title: $title, coverImage: $coverImage, coverImageColor: $coverImageColor, description: $description, source: $source, bannerImage: $bannerImage, averageScore: $averageScore, favourites: $favourites, trailerModel: $trailerModel, seasonYear: $seasonYear, season: $season, status: $status, ratedRank: $ratedRank, popularRank: $popularRank, hashtags: $hashtags, genres: $genres, episodes: $episodes, timeUntilAiring: $timeUntilAiring, nextAiringEpisode: $nextAiringEpisode, isFollowing: $isFollowing, characterAndVoiceActors: $characterAndVoiceActors, staffs: $staffs)'; + return 'AnimeModel(id: $id, title: $title, coverImage: $coverImage, coverImageColor: $coverImageColor, description: $description, source: $source, bannerImage: $bannerImage, averageScore: $averageScore, favourites: $favourites, trailerModel: $trailerModel, seasonYear: $seasonYear, season: $season, status: $status, ratedRank: $ratedRank, popularRank: $popularRank, hashtags: $hashtags, genres: $genres, episodes: $episodes, timeUntilAiring: $timeUntilAiring, nextAiringEpisode: $nextAiringEpisode, isFollowing: $isFollowing, characterAndVoiceActors: $characterAndVoiceActors, staffs: $staffs, externalLinks: $externalLinks)'; } @override @@ -569,7 +594,9 @@ class _$_DetailAnimeModel implements _DetailAnimeModel { other.isFollowing == isFollowing) && const DeepCollectionEquality().equals( other._characterAndVoiceActors, _characterAndVoiceActors) && - const DeepCollectionEquality().equals(other._staffs, _staffs)); + const DeepCollectionEquality().equals(other._staffs, _staffs) && + const DeepCollectionEquality() + .equals(other._externalLinks, _externalLinks)); } @override @@ -597,7 +624,8 @@ class _$_DetailAnimeModel implements _DetailAnimeModel { nextAiringEpisode, isFollowing, const DeepCollectionEquality().hash(_characterAndVoiceActors), - const DeepCollectionEquality().hash(_staffs) + const DeepCollectionEquality().hash(_staffs), + const DeepCollectionEquality().hash(_externalLinks) ]); @JsonKey(ignore: true) @@ -631,7 +659,8 @@ abstract class _DetailAnimeModel implements AnimeModel { final int? nextAiringEpisode, final bool isFollowing, final List characterAndVoiceActors, - final List staffs}) = _$_DetailAnimeModel; + final List staffs, + final List externalLinks}) = _$_DetailAnimeModel; @override String get id; @@ -680,6 +709,8 @@ abstract class _DetailAnimeModel implements AnimeModel { @override List get staffs; @override + List get externalLinks; + @override @JsonKey(ignore: true) _$$_DetailAnimeModelCopyWith<_$_DetailAnimeModel> get copyWith => throw _privateConstructorUsedError; diff --git a/lib/core/data/model/media_external_link_model.dart b/lib/core/data/model/media_external_link_model.dart new file mode 100644 index 00000000..28a47ea9 --- /dev/null +++ b/lib/core/data/model/media_external_link_model.dart @@ -0,0 +1,32 @@ +import 'package:anime_tracker/core/data/model/media_external_link_type.dart'; +import 'package:anime_tracker/core/database/model/media_external_link_entity.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'media_external_link_model.freezed.dart'; + +part 'media_external_link_model.g.dart'; + +@freezed +class MediaExternalLinkModel with _$MediaExternalLinkModel { + factory MediaExternalLinkModel({ + @Default('') String url, + @Default('') String site, + @Default(MediaExternalLinkType.info) MediaExternalLinkType type, + @Default(-1) int siteId, + @Default('') String icon, + }) = _MediaExternalLinkModel; + + factory MediaExternalLinkModel.fromJson(Map json) => + _$$_MediaExternalLinkModelFromJson(json); + + static MediaExternalLinkModel fromEntity(MediaExternalLinkEntity entity) { + return MediaExternalLinkModel( + url: entity.url ?? '', + site: entity.site ?? '', + type: $enumDecodeNullable(_$MediaExternalLinkTypeEnumMap, entity.type) ?? + MediaExternalLinkType.info, + siteId: entity.siteId ?? -1, + icon: entity.icon ?? '', + ); + } +} diff --git a/lib/core/data/model/media_external_link_model.freezed.dart b/lib/core/data/model/media_external_link_model.freezed.dart new file mode 100644 index 00000000..504154f9 --- /dev/null +++ b/lib/core/data/model/media_external_link_model.freezed.dart @@ -0,0 +1,244 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// 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_external_link_model.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); + +MediaExternalLinkModel _$MediaExternalLinkModelFromJson( + Map json) { + return _MediaExternalLinkModel.fromJson(json); +} + +/// @nodoc +mixin _$MediaExternalLinkModel { + String get url => throw _privateConstructorUsedError; + String get site => throw _privateConstructorUsedError; + MediaExternalLinkType get type => throw _privateConstructorUsedError; + int get siteId => throw _privateConstructorUsedError; + String get icon => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $MediaExternalLinkModelCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $MediaExternalLinkModelCopyWith<$Res> { + factory $MediaExternalLinkModelCopyWith(MediaExternalLinkModel value, + $Res Function(MediaExternalLinkModel) then) = + _$MediaExternalLinkModelCopyWithImpl<$Res, MediaExternalLinkModel>; + @useResult + $Res call( + {String url, + String site, + MediaExternalLinkType type, + int siteId, + String icon}); +} + +/// @nodoc +class _$MediaExternalLinkModelCopyWithImpl<$Res, + $Val extends MediaExternalLinkModel> + implements $MediaExternalLinkModelCopyWith<$Res> { + _$MediaExternalLinkModelCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? url = null, + Object? site = null, + Object? type = null, + Object? siteId = null, + Object? icon = null, + }) { + return _then(_value.copyWith( + url: null == url + ? _value.url + : url // ignore: cast_nullable_to_non_nullable + as String, + site: null == site + ? _value.site + : site // ignore: cast_nullable_to_non_nullable + as String, + type: null == type + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as MediaExternalLinkType, + siteId: null == siteId + ? _value.siteId + : siteId // ignore: cast_nullable_to_non_nullable + as int, + icon: null == icon + ? _value.icon + : icon // ignore: cast_nullable_to_non_nullable + as String, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$_MediaExternalLinkModelCopyWith<$Res> + implements $MediaExternalLinkModelCopyWith<$Res> { + factory _$$_MediaExternalLinkModelCopyWith(_$_MediaExternalLinkModel value, + $Res Function(_$_MediaExternalLinkModel) then) = + __$$_MediaExternalLinkModelCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {String url, + String site, + MediaExternalLinkType type, + int siteId, + String icon}); +} + +/// @nodoc +class __$$_MediaExternalLinkModelCopyWithImpl<$Res> + extends _$MediaExternalLinkModelCopyWithImpl<$Res, + _$_MediaExternalLinkModel> + implements _$$_MediaExternalLinkModelCopyWith<$Res> { + __$$_MediaExternalLinkModelCopyWithImpl(_$_MediaExternalLinkModel _value, + $Res Function(_$_MediaExternalLinkModel) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? url = null, + Object? site = null, + Object? type = null, + Object? siteId = null, + Object? icon = null, + }) { + return _then(_$_MediaExternalLinkModel( + url: null == url + ? _value.url + : url // ignore: cast_nullable_to_non_nullable + as String, + site: null == site + ? _value.site + : site // ignore: cast_nullable_to_non_nullable + as String, + type: null == type + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as MediaExternalLinkType, + siteId: null == siteId + ? _value.siteId + : siteId // ignore: cast_nullable_to_non_nullable + as int, + icon: null == icon + ? _value.icon + : icon // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$_MediaExternalLinkModel implements _MediaExternalLinkModel { + _$_MediaExternalLinkModel( + {this.url = '', + this.site = '', + this.type = MediaExternalLinkType.info, + this.siteId = -1, + this.icon = ''}); + + factory _$_MediaExternalLinkModel.fromJson(Map json) => + _$$_MediaExternalLinkModelFromJson(json); + + @override + @JsonKey() + final String url; + @override + @JsonKey() + final String site; + @override + @JsonKey() + final MediaExternalLinkType type; + @override + @JsonKey() + final int siteId; + @override + @JsonKey() + final String icon; + + @override + String toString() { + return 'MediaExternalLinkModel(url: $url, site: $site, type: $type, siteId: $siteId, icon: $icon)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$_MediaExternalLinkModel && + (identical(other.url, url) || other.url == url) && + (identical(other.site, site) || other.site == site) && + (identical(other.type, type) || other.type == type) && + (identical(other.siteId, siteId) || other.siteId == siteId) && + (identical(other.icon, icon) || other.icon == icon)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => Object.hash(runtimeType, url, site, type, siteId, icon); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$_MediaExternalLinkModelCopyWith<_$_MediaExternalLinkModel> get copyWith => + __$$_MediaExternalLinkModelCopyWithImpl<_$_MediaExternalLinkModel>( + this, _$identity); + + @override + Map toJson() { + return _$$_MediaExternalLinkModelToJson( + this, + ); + } +} + +abstract class _MediaExternalLinkModel implements MediaExternalLinkModel { + factory _MediaExternalLinkModel( + {final String url, + final String site, + final MediaExternalLinkType type, + final int siteId, + final String icon}) = _$_MediaExternalLinkModel; + + factory _MediaExternalLinkModel.fromJson(Map json) = + _$_MediaExternalLinkModel.fromJson; + + @override + String get url; + @override + String get site; + @override + MediaExternalLinkType get type; + @override + int get siteId; + @override + String get icon; + @override + @JsonKey(ignore: true) + _$$_MediaExternalLinkModelCopyWith<_$_MediaExternalLinkModel> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/core/data/model/media_external_link_model.g.dart b/lib/core/data/model/media_external_link_model.g.dart new file mode 100644 index 00000000..38c1c8fa --- /dev/null +++ b/lib/core/data/model/media_external_link_model.g.dart @@ -0,0 +1,34 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'media_external_link_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$_MediaExternalLinkModel _$$_MediaExternalLinkModelFromJson( + Map json) => + _$_MediaExternalLinkModel( + url: json['url'] as String? ?? '', + site: json['site'] as String? ?? '', + type: $enumDecodeNullable(_$MediaExternalLinkTypeEnumMap, json['type']) ?? + MediaExternalLinkType.info, + siteId: json['siteId'] as int? ?? -1, + icon: json['icon'] as String? ?? '', + ); + +Map _$$_MediaExternalLinkModelToJson( + _$_MediaExternalLinkModel instance) => + { + 'url': instance.url, + 'site': instance.site, + 'type': _$MediaExternalLinkTypeEnumMap[instance.type]!, + 'siteId': instance.siteId, + 'icon': instance.icon, + }; + +const _$MediaExternalLinkTypeEnumMap = { + MediaExternalLinkType.info: 'INFO', + MediaExternalLinkType.streaming: 'STREAMING', + MediaExternalLinkType.social: 'SOCIAL', +}; diff --git a/lib/core/data/model/media_external_link_type.dart b/lib/core/data/model/media_external_link_type.dart new file mode 100644 index 00000000..495451e5 --- /dev/null +++ b/lib/core/data/model/media_external_link_type.dart @@ -0,0 +1,12 @@ + +import 'package:json_annotation/json_annotation.dart'; + +@JsonEnum() +enum MediaExternalLinkType { + @JsonValue('INFO') + info, + @JsonValue('STREAMING') + streaming, + @JsonValue('SOCIAL') + social; +} diff --git a/lib/core/database/anime_dao.dart b/lib/core/database/anime_dao.dart index 81952127..d998c238 100644 --- a/lib/core/database/anime_dao.dart +++ b/lib/core/database/anime_dao.dart @@ -5,6 +5,7 @@ import 'package:anime_tracker/core/database/model/airing_schedules_entity.dart'; import 'package:anime_tracker/core/database/model/anime_entity.dart'; import 'package:anime_tracker/core/database/model/character_entity.dart'; import 'package:anime_tracker/core/database/model/relations/airing_schedule_and_anime.dart'; +import 'package:anime_tracker/core/database/model/media_external_link_entity.dart'; import 'package:anime_tracker/core/database/model/relations/anime_and_detail_info.dart'; import 'package:anime_tracker/core/database/model/staff_entity.dart'; import 'package:flutter/cupertino.dart'; @@ -130,6 +131,18 @@ class AnimeStaffCrossRef { final String staffRole; } +/// [Tables.mediaExternalLickTable] +mixin MediaExternalLinkColumnValues { + static const id = 'external_link_id'; + static const animeId = 'external_link_anime_id'; + static const url = 'external_link_url'; + static const site = 'external_link_site'; + static const type = 'external_link_type'; + static const siteId = 'external_link_siteId'; + static const color = 'external_link_color'; + static const icon = 'external_link_icon'; +} + abstract class AnimeListDao { Future clearAll(); @@ -165,6 +178,9 @@ abstract class AnimeListDao { Future clearAiringSchedule(); + Future upsertMediaExternalLinks( + {required List externalLinks}); + void notifyAnimeDetailInfoChanged(); } @@ -248,6 +264,11 @@ class AnimeDaoImpl extends AnimeListDao { 'where animeStaff.${AnimeStaffCrossRefColumns.animeId} = \'$id\' '; List staffResults = await database.animeDB.rawQuery(staffSql); + String externalLinkSql = + 'select * from ${Tables.mediaExternalLickTable} as media ' + 'where media.${MediaExternalLinkColumnValues.animeId} = \'$id\' '; + List externalLinkResults = await database.animeDB.rawQuery(externalLinkSql); + return AnimeWithDetailInfo( animeEntity: animeEntity, characterAndVoiceActors: characterResults @@ -263,6 +284,9 @@ class AnimeDaoImpl extends AnimeListDao { (e) => StaffAndRoleEntity.fromJson(e), ) .toList(), + externalLinks: externalLinkResults + .map((e) => MediaExternalLinkEntity.fromJson(e)) + .toList(), ); } @@ -356,6 +380,20 @@ class AnimeDaoImpl extends AnimeListDao { return await batch.commit(noResult: true); } + @override + Future upsertMediaExternalLinks( + {required List externalLinks}) async { + final batch = database.animeDB.batch(); + for (final externalLink in externalLinks) { + batch.insert( + Tables.mediaExternalLickTable, + externalLink.toJson(), + conflictAlgorithm: ConflictAlgorithm.replace, + ); + } + return await batch.commit(noResult: true); + } + @override Future> getAiringSchedulesByTimeRange( {required (int startMs, int endMs) timeRange}) async { diff --git a/lib/core/database/anime_database.dart b/lib/core/database/anime_database.dart index 9a94e3c2..3410620e 100644 --- a/lib/core/database/anime_database.dart +++ b/lib/core/database/anime_database.dart @@ -21,6 +21,7 @@ mixin Tables { static const String userDataTable = 'user_data_table'; static const String animeTrackListTable = 'usr_anime_list_table'; static const String airingSchedulesTable = 'airing_schedules_table'; + static const String mediaExternalLickTable = 'media_external_link_table'; } class AnimeDatabase { @@ -161,5 +162,17 @@ class AnimeDatabase { '${AiringSchedulesColumns.timeUntilAiring} integer,' '${AiringSchedulesColumns.episode} episode' ')'); + + await _animeDB! + .execute('CREATE TABLE IF NOT EXISTS ${Tables.mediaExternalLickTable} (' + '${MediaExternalLinkColumnValues.id} text primary key,' + '${MediaExternalLinkColumnValues.animeId} text,' + '${MediaExternalLinkColumnValues.url} text,' + '${MediaExternalLinkColumnValues.site} text,' + '${MediaExternalLinkColumnValues.type} text,' + '${MediaExternalLinkColumnValues.siteId} integer,' + '${MediaExternalLinkColumnValues.color} text,' + '${MediaExternalLinkColumnValues.icon} text' + ')'); } } diff --git a/lib/core/database/model/media_external_link_entity.dart b/lib/core/database/model/media_external_link_entity.dart new file mode 100644 index 00000000..238666e2 --- /dev/null +++ b/lib/core/database/model/media_external_link_entity.dart @@ -0,0 +1,38 @@ +import 'package:anime_tracker/core/database/anime_dao.dart'; +import 'package:anime_tracker/core/network/model/media_external_links_dto.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'media_external_link_entity.freezed.dart'; + +part 'media_external_link_entity.g.dart'; + +@freezed +class MediaExternalLinkEntity with _$MediaExternalLinkEntity { + factory MediaExternalLinkEntity({ + @Default('') @JsonKey(name: MediaExternalLinkColumnValues.id) String id, + @Default('') + @JsonKey(name: MediaExternalLinkColumnValues.animeId) + String animeId, + @JsonKey(name: MediaExternalLinkColumnValues.url) String? url, + @JsonKey(name: MediaExternalLinkColumnValues.site) String? site, + @JsonKey(name: MediaExternalLinkColumnValues.type) String? type, + @JsonKey(name: MediaExternalLinkColumnValues.siteId) int? siteId, + @JsonKey(name: MediaExternalLinkColumnValues.icon) String? icon, + }) = _MediaExternalLinkEntity; + + factory MediaExternalLinkEntity.fromJson(Map json) => + _$$_MediaExternalLinkEntityFromJson(json); + + static MediaExternalLinkEntity fromDto( + MediaExternalLinkDto dto, String animeId) { + return MediaExternalLinkEntity( + id: dto.id.toString(), + animeId: animeId, + url: dto.url, + site: dto.site, + type: dto.type, + siteId: dto.siteId, + icon: dto.icon, + ); + } +} diff --git a/lib/core/database/model/media_external_link_entity.freezed.dart b/lib/core/database/model/media_external_link_entity.freezed.dart new file mode 100644 index 00000000..6a75af69 --- /dev/null +++ b/lib/core/database/model/media_external_link_entity.freezed.dart @@ -0,0 +1,304 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// 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_external_link_entity.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); + +MediaExternalLinkEntity _$MediaExternalLinkEntityFromJson( + Map json) { + return _MediaExternalLinkEntity.fromJson(json); +} + +/// @nodoc +mixin _$MediaExternalLinkEntity { + @JsonKey(name: MediaExternalLinkColumnValues.id) + String get id => throw _privateConstructorUsedError; + @JsonKey(name: MediaExternalLinkColumnValues.animeId) + String get animeId => throw _privateConstructorUsedError; + @JsonKey(name: MediaExternalLinkColumnValues.url) + String? get url => throw _privateConstructorUsedError; + @JsonKey(name: MediaExternalLinkColumnValues.site) + String? get site => throw _privateConstructorUsedError; + @JsonKey(name: MediaExternalLinkColumnValues.type) + String? get type => throw _privateConstructorUsedError; + @JsonKey(name: MediaExternalLinkColumnValues.siteId) + int? get siteId => throw _privateConstructorUsedError; + @JsonKey(name: MediaExternalLinkColumnValues.icon) + String? get icon => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $MediaExternalLinkEntityCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $MediaExternalLinkEntityCopyWith<$Res> { + factory $MediaExternalLinkEntityCopyWith(MediaExternalLinkEntity value, + $Res Function(MediaExternalLinkEntity) then) = + _$MediaExternalLinkEntityCopyWithImpl<$Res, MediaExternalLinkEntity>; + @useResult + $Res call( + {@JsonKey(name: MediaExternalLinkColumnValues.id) String id, + @JsonKey(name: MediaExternalLinkColumnValues.animeId) String animeId, + @JsonKey(name: MediaExternalLinkColumnValues.url) String? url, + @JsonKey(name: MediaExternalLinkColumnValues.site) String? site, + @JsonKey(name: MediaExternalLinkColumnValues.type) String? type, + @JsonKey(name: MediaExternalLinkColumnValues.siteId) int? siteId, + @JsonKey(name: MediaExternalLinkColumnValues.icon) String? icon}); +} + +/// @nodoc +class _$MediaExternalLinkEntityCopyWithImpl<$Res, + $Val extends MediaExternalLinkEntity> + implements $MediaExternalLinkEntityCopyWith<$Res> { + _$MediaExternalLinkEntityCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? animeId = null, + Object? url = freezed, + Object? site = freezed, + Object? type = freezed, + Object? siteId = freezed, + Object? icon = freezed, + }) { + return _then(_value.copyWith( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + animeId: null == animeId + ? _value.animeId + : animeId // ignore: cast_nullable_to_non_nullable + as String, + url: freezed == url + ? _value.url + : url // ignore: cast_nullable_to_non_nullable + as String?, + site: freezed == site + ? _value.site + : site // ignore: cast_nullable_to_non_nullable + as String?, + type: freezed == type + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as String?, + siteId: freezed == siteId + ? _value.siteId + : siteId // ignore: cast_nullable_to_non_nullable + as int?, + icon: freezed == icon + ? _value.icon + : icon // ignore: cast_nullable_to_non_nullable + as String?, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$_MediaExternalLinkEntityCopyWith<$Res> + implements $MediaExternalLinkEntityCopyWith<$Res> { + factory _$$_MediaExternalLinkEntityCopyWith(_$_MediaExternalLinkEntity value, + $Res Function(_$_MediaExternalLinkEntity) then) = + __$$_MediaExternalLinkEntityCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {@JsonKey(name: MediaExternalLinkColumnValues.id) String id, + @JsonKey(name: MediaExternalLinkColumnValues.animeId) String animeId, + @JsonKey(name: MediaExternalLinkColumnValues.url) String? url, + @JsonKey(name: MediaExternalLinkColumnValues.site) String? site, + @JsonKey(name: MediaExternalLinkColumnValues.type) String? type, + @JsonKey(name: MediaExternalLinkColumnValues.siteId) int? siteId, + @JsonKey(name: MediaExternalLinkColumnValues.icon) String? icon}); +} + +/// @nodoc +class __$$_MediaExternalLinkEntityCopyWithImpl<$Res> + extends _$MediaExternalLinkEntityCopyWithImpl<$Res, + _$_MediaExternalLinkEntity> + implements _$$_MediaExternalLinkEntityCopyWith<$Res> { + __$$_MediaExternalLinkEntityCopyWithImpl(_$_MediaExternalLinkEntity _value, + $Res Function(_$_MediaExternalLinkEntity) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? animeId = null, + Object? url = freezed, + Object? site = freezed, + Object? type = freezed, + Object? siteId = freezed, + Object? icon = freezed, + }) { + return _then(_$_MediaExternalLinkEntity( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + animeId: null == animeId + ? _value.animeId + : animeId // ignore: cast_nullable_to_non_nullable + as String, + url: freezed == url + ? _value.url + : url // ignore: cast_nullable_to_non_nullable + as String?, + site: freezed == site + ? _value.site + : site // ignore: cast_nullable_to_non_nullable + as String?, + type: freezed == type + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as String?, + siteId: freezed == siteId + ? _value.siteId + : siteId // ignore: cast_nullable_to_non_nullable + as int?, + icon: freezed == icon + ? _value.icon + : icon // ignore: cast_nullable_to_non_nullable + as String?, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$_MediaExternalLinkEntity implements _MediaExternalLinkEntity { + _$_MediaExternalLinkEntity( + {@JsonKey(name: MediaExternalLinkColumnValues.id) this.id = '', + @JsonKey(name: MediaExternalLinkColumnValues.animeId) this.animeId = '', + @JsonKey(name: MediaExternalLinkColumnValues.url) this.url, + @JsonKey(name: MediaExternalLinkColumnValues.site) this.site, + @JsonKey(name: MediaExternalLinkColumnValues.type) this.type, + @JsonKey(name: MediaExternalLinkColumnValues.siteId) this.siteId, + @JsonKey(name: MediaExternalLinkColumnValues.icon) this.icon}); + + factory _$_MediaExternalLinkEntity.fromJson(Map json) => + _$$_MediaExternalLinkEntityFromJson(json); + + @override + @JsonKey(name: MediaExternalLinkColumnValues.id) + final String id; + @override + @JsonKey(name: MediaExternalLinkColumnValues.animeId) + final String animeId; + @override + @JsonKey(name: MediaExternalLinkColumnValues.url) + final String? url; + @override + @JsonKey(name: MediaExternalLinkColumnValues.site) + final String? site; + @override + @JsonKey(name: MediaExternalLinkColumnValues.type) + final String? type; + @override + @JsonKey(name: MediaExternalLinkColumnValues.siteId) + final int? siteId; + @override + @JsonKey(name: MediaExternalLinkColumnValues.icon) + final String? icon; + + @override + String toString() { + return 'MediaExternalLinkEntity(id: $id, animeId: $animeId, url: $url, site: $site, type: $type, siteId: $siteId, icon: $icon)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$_MediaExternalLinkEntity && + (identical(other.id, id) || other.id == id) && + (identical(other.animeId, animeId) || other.animeId == animeId) && + (identical(other.url, url) || other.url == url) && + (identical(other.site, site) || other.site == site) && + (identical(other.type, type) || other.type == type) && + (identical(other.siteId, siteId) || other.siteId == siteId) && + (identical(other.icon, icon) || other.icon == icon)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => + Object.hash(runtimeType, id, animeId, url, site, type, siteId, icon); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$_MediaExternalLinkEntityCopyWith<_$_MediaExternalLinkEntity> + get copyWith => + __$$_MediaExternalLinkEntityCopyWithImpl<_$_MediaExternalLinkEntity>( + this, _$identity); + + @override + Map toJson() { + return _$$_MediaExternalLinkEntityToJson( + this, + ); + } +} + +abstract class _MediaExternalLinkEntity implements MediaExternalLinkEntity { + factory _MediaExternalLinkEntity( + {@JsonKey(name: MediaExternalLinkColumnValues.id) final String id, + @JsonKey(name: MediaExternalLinkColumnValues.animeId) + final String animeId, + @JsonKey(name: MediaExternalLinkColumnValues.url) final String? url, + @JsonKey(name: MediaExternalLinkColumnValues.site) final String? site, + @JsonKey(name: MediaExternalLinkColumnValues.type) final String? type, + @JsonKey(name: MediaExternalLinkColumnValues.siteId) final int? siteId, + @JsonKey(name: MediaExternalLinkColumnValues.icon) + final String? icon}) = _$_MediaExternalLinkEntity; + + factory _MediaExternalLinkEntity.fromJson(Map json) = + _$_MediaExternalLinkEntity.fromJson; + + @override + @JsonKey(name: MediaExternalLinkColumnValues.id) + String get id; + @override + @JsonKey(name: MediaExternalLinkColumnValues.animeId) + String get animeId; + @override + @JsonKey(name: MediaExternalLinkColumnValues.url) + String? get url; + @override + @JsonKey(name: MediaExternalLinkColumnValues.site) + String? get site; + @override + @JsonKey(name: MediaExternalLinkColumnValues.type) + String? get type; + @override + @JsonKey(name: MediaExternalLinkColumnValues.siteId) + int? get siteId; + @override + @JsonKey(name: MediaExternalLinkColumnValues.icon) + String? get icon; + @override + @JsonKey(ignore: true) + _$$_MediaExternalLinkEntityCopyWith<_$_MediaExternalLinkEntity> + get copyWith => throw _privateConstructorUsedError; +} diff --git a/lib/core/database/model/media_external_link_entity.g.dart b/lib/core/database/model/media_external_link_entity.g.dart new file mode 100644 index 00000000..6689ebf5 --- /dev/null +++ b/lib/core/database/model/media_external_link_entity.g.dart @@ -0,0 +1,31 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'media_external_link_entity.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$_MediaExternalLinkEntity _$$_MediaExternalLinkEntityFromJson( + Map json) => + _$_MediaExternalLinkEntity( + id: json['external_link_id'] as String? ?? '', + animeId: json['external_link_anime_id'] as String? ?? '', + url: json['external_link_url'] as String?, + site: json['external_link_site'] as String?, + type: json['external_link_type'] as String?, + siteId: json['external_link_siteId'] as int?, + icon: json['external_link_icon'] as String?, + ); + +Map _$$_MediaExternalLinkEntityToJson( + _$_MediaExternalLinkEntity instance) => + { + 'external_link_id': instance.id, + 'external_link_anime_id': instance.animeId, + 'external_link_url': instance.url, + 'external_link_site': instance.site, + 'external_link_type': instance.type, + 'external_link_siteId': instance.siteId, + 'external_link_icon': instance.icon, + }; diff --git a/lib/core/database/model/relations/anime_and_detail_info.dart b/lib/core/database/model/relations/anime_and_detail_info.dart index 4e772eda..53be1b06 100644 --- a/lib/core/database/model/relations/anime_and_detail_info.dart +++ b/lib/core/database/model/relations/anime_and_detail_info.dart @@ -1,6 +1,7 @@ import 'package:anime_tracker/core/database/anime_dao.dart'; import 'package:anime_tracker/core/database/model/anime_entity.dart'; import 'package:anime_tracker/core/database/model/character_entity.dart'; +import 'package:anime_tracker/core/database/model/media_external_link_entity.dart'; import 'package:anime_tracker/core/database/model/staff_entity.dart'; class CharacterAndVoiceActor { @@ -27,10 +28,12 @@ class AnimeWithDetailInfo { final AnimeEntity animeEntity; final List characterAndVoiceActors; final List staffs; + final List externalLinks; AnimeWithDetailInfo({ required this.animeEntity, required this.characterAndVoiceActors, required this.staffs, + required this.externalLinks, }); } diff --git a/lib/core/design_system/widget/trailer_preview.dart b/lib/core/design_system/widget/trailer_preview.dart index 0a59a5c5..203c51b2 100644 --- a/lib/core/design_system/widget/trailer_preview.dart +++ b/lib/core/design_system/widget/trailer_preview.dart @@ -9,7 +9,7 @@ class TrailerPreview extends StatelessWidget { const TrailerPreview( {required this.model, required this.onTrailerClick, super.key}); - final TrailerModel model; + final TrailerModel? model; final VoidCallback onTrailerClick; @override @@ -28,7 +28,7 @@ class TrailerPreview extends StatelessWidget { fit: StackFit.expand, children: [ AFNetworkImage( - imageUrl: model.thumbnail ?? '', + imageUrl: model?.thumbnail ?? '', ), Center( child: SvgPicture.asset(ATIcons.icYoutube), diff --git a/lib/core/design_system/widget/vertical_animated_scale_switcher.dart b/lib/core/design_system/widget/vertical_animated_scale_switcher.dart index c01e822e..b91c70e4 100644 --- a/lib/core/design_system/widget/vertical_animated_scale_switcher.dart +++ b/lib/core/design_system/widget/vertical_animated_scale_switcher.dart @@ -2,9 +2,10 @@ import 'package:anime_tracker/core/design_system/animetion/scale_transaction_ani import 'package:flutter/material.dart'; class VerticalScaleSwitcher extends StatelessWidget { - const VerticalScaleSwitcher({required this.child, super.key}); + const VerticalScaleSwitcher({required this.child, required this.visible, super.key}); final Widget child; + final bool visible; @override Widget build(BuildContext context) { @@ -12,7 +13,7 @@ class VerticalScaleSwitcher extends StatelessWidget { duration: const Duration(milliseconds: 300), switchInCurve: Curves.ease, transitionBuilder: buildSizeTransition, - child: child, + child: visible ? child : const SizedBox(), ); } } diff --git a/lib/core/network/model/detail_anime_dto.dart b/lib/core/network/model/detail_anime_dto.dart index 3140078f..403f64f0 100644 --- a/lib/core/network/model/detail_anime_dto.dart +++ b/lib/core/network/model/detail_anime_dto.dart @@ -3,6 +3,7 @@ import 'package:anime_tracker/core/common/model/anime_source.dart'; import 'package:anime_tracker/core/common/model/anime_status.dart'; import 'package:anime_tracker/core/network/model/airing_schedule_dto.dart'; import 'package:anime_tracker/core/network/model/anime_rank.dart'; +import 'package:anime_tracker/core/network/model/media_external_links_dto.dart'; import 'package:anime_tracker/core/network/model/staff_connection.dart'; import 'package:anime_tracker/core/network/model/trailer_dto.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -37,6 +38,9 @@ class DetailAnimeDto with _$DetailAnimeDto { @Default([]) @JsonKey(name: 'rankings') List rankings, @JsonKey(name: 'characters') CharacterConnection? characters, @JsonKey(name: 'staff') StaffConnection? staff, + @Default([]) + @JsonKey(name: 'externalLinks') + List externalLinks, }) = _DetailAnimeDto; factory DetailAnimeDto.fromJson(Map json) => diff --git a/lib/core/network/model/detail_anime_dto.freezed.dart b/lib/core/network/model/detail_anime_dto.freezed.dart index 02652bcb..9e2febe8 100644 --- a/lib/core/network/model/detail_anime_dto.freezed.dart +++ b/lib/core/network/model/detail_anime_dto.freezed.dart @@ -61,6 +61,9 @@ mixin _$DetailAnimeDto { CharacterConnection? get characters => throw _privateConstructorUsedError; @JsonKey(name: 'staff') StaffConnection? get staff => throw _privateConstructorUsedError; + @JsonKey(name: 'externalLinks') + List get externalLinks => + throw _privateConstructorUsedError; Map toJson() => throw _privateConstructorUsedError; @JsonKey(ignore: true) @@ -94,7 +97,9 @@ abstract class $DetailAnimeDtoCopyWith<$Res> { @JsonKey(name: 'nextAiringEpisode') AiringScheduleDto? nextAiringEpisode, @JsonKey(name: 'rankings') List rankings, @JsonKey(name: 'characters') CharacterConnection? characters, - @JsonKey(name: 'staff') StaffConnection? staff}); + @JsonKey(name: 'staff') StaffConnection? staff, + @JsonKey(name: 'externalLinks') + List externalLinks}); $AnimeTitleCopyWith<$Res>? get title; $TrailerDtoCopyWith<$Res>? get trailer; @@ -136,6 +141,7 @@ class _$DetailAnimeDtoCopyWithImpl<$Res, $Val extends DetailAnimeDto> Object? rankings = null, Object? characters = freezed, Object? staff = freezed, + Object? externalLinks = null, }) { return _then(_value.copyWith( id: null == id @@ -218,6 +224,10 @@ class _$DetailAnimeDtoCopyWithImpl<$Res, $Val extends DetailAnimeDto> ? _value.staff : staff // ignore: cast_nullable_to_non_nullable as StaffConnection?, + externalLinks: null == externalLinks + ? _value.externalLinks + : externalLinks // ignore: cast_nullable_to_non_nullable + as List, ) as $Val); } @@ -310,7 +320,9 @@ abstract class _$$_DetailAnimeDtoCopyWith<$Res> @JsonKey(name: 'nextAiringEpisode') AiringScheduleDto? nextAiringEpisode, @JsonKey(name: 'rankings') List rankings, @JsonKey(name: 'characters') CharacterConnection? characters, - @JsonKey(name: 'staff') StaffConnection? staff}); + @JsonKey(name: 'staff') StaffConnection? staff, + @JsonKey(name: 'externalLinks') + List externalLinks}); @override $AnimeTitleCopyWith<$Res>? get title; @@ -355,6 +367,7 @@ class __$$_DetailAnimeDtoCopyWithImpl<$Res> Object? rankings = null, Object? characters = freezed, Object? staff = freezed, + Object? externalLinks = null, }) { return _then(_$_DetailAnimeDto( id: null == id @@ -437,6 +450,10 @@ class __$$_DetailAnimeDtoCopyWithImpl<$Res> ? _value.staff : staff // ignore: cast_nullable_to_non_nullable as StaffConnection?, + externalLinks: null == externalLinks + ? _value._externalLinks + : externalLinks // ignore: cast_nullable_to_non_nullable + as List, )); } } @@ -465,10 +482,13 @@ class _$_DetailAnimeDto implements _DetailAnimeDto { @JsonKey(name: 'nextAiringEpisode') this.nextAiringEpisode, @JsonKey(name: 'rankings') final List rankings = const [], @JsonKey(name: 'characters') this.characters, - @JsonKey(name: 'staff') this.staff}) + @JsonKey(name: 'staff') this.staff, + @JsonKey(name: 'externalLinks') + final List externalLinks = const []}) : _coverImage = coverImage, _genres = genres, - _rankings = rankings; + _rankings = rankings, + _externalLinks = externalLinks; factory _$_DetailAnimeDto.fromJson(Map json) => _$$_DetailAnimeDtoFromJson(json); @@ -551,10 +571,18 @@ class _$_DetailAnimeDto implements _DetailAnimeDto { @override @JsonKey(name: 'staff') final StaffConnection? staff; + final List _externalLinks; + @override + @JsonKey(name: 'externalLinks') + List get externalLinks { + if (_externalLinks is EqualUnmodifiableListView) return _externalLinks; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_externalLinks); + } @override String toString() { - return 'DetailAnimeDto(id: $id, title: $title, coverImage: $coverImage, description: $description, status: $status, source: $source, episodes: $episodes, seasonYear: $seasonYear, season: $season, hashtag: $hashtag, bannerImage: $bannerImage, averageScore: $averageScore, trending: $trending, favourites: $favourites, genres: $genres, trailer: $trailer, nextAiringEpisode: $nextAiringEpisode, rankings: $rankings, characters: $characters, staff: $staff)'; + return 'DetailAnimeDto(id: $id, title: $title, coverImage: $coverImage, description: $description, status: $status, source: $source, episodes: $episodes, seasonYear: $seasonYear, season: $season, hashtag: $hashtag, bannerImage: $bannerImage, averageScore: $averageScore, trending: $trending, favourites: $favourites, genres: $genres, trailer: $trailer, nextAiringEpisode: $nextAiringEpisode, rankings: $rankings, characters: $characters, staff: $staff, externalLinks: $externalLinks)'; } @override @@ -591,7 +619,9 @@ class _$_DetailAnimeDto implements _DetailAnimeDto { const DeepCollectionEquality().equals(other._rankings, _rankings) && (identical(other.characters, characters) || other.characters == characters) && - (identical(other.staff, staff) || other.staff == staff)); + (identical(other.staff, staff) || other.staff == staff) && + const DeepCollectionEquality() + .equals(other._externalLinks, _externalLinks)); } @JsonKey(ignore: true) @@ -617,7 +647,8 @@ class _$_DetailAnimeDto implements _DetailAnimeDto { nextAiringEpisode, const DeepCollectionEquality().hash(_rankings), characters, - staff + staff, + const DeepCollectionEquality().hash(_externalLinks) ]); @JsonKey(ignore: true) @@ -636,28 +667,29 @@ class _$_DetailAnimeDto implements _DetailAnimeDto { abstract class _DetailAnimeDto implements DetailAnimeDto { factory _DetailAnimeDto( - {@JsonKey(name: 'id') final int id, - @JsonKey(name: 'title') final AnimeTitle? title, - @JsonKey(name: 'coverImage') final Map coverImage, - @JsonKey(name: 'description') final String? description, - @JsonKey(name: 'status') final AnimeStatus? status, - @JsonKey(name: 'source') final AnimeSource? source, - @JsonKey(name: 'episodes') final int? episodes, - @JsonKey(name: 'seasonYear') final int? seasonYear, - @JsonKey(name: 'season') final AnimeSeason? season, - @JsonKey(name: 'hashtag') final String? hashtag, - @JsonKey(name: 'bannerImage') final String? bannerImage, - @JsonKey(name: 'averageScore') final int? averageScore, - @JsonKey(name: 'trending') final int? trending, - @JsonKey(name: 'favourites') final int? favourites, - @JsonKey(name: 'genres') final List genres, - @JsonKey(name: 'trailer') final TrailerDto? trailer, - @JsonKey(name: 'nextAiringEpisode') - final AiringScheduleDto? nextAiringEpisode, - @JsonKey(name: 'rankings') final List rankings, - @JsonKey(name: 'characters') final CharacterConnection? characters, - @JsonKey(name: 'staff') final StaffConnection? staff}) = - _$_DetailAnimeDto; + {@JsonKey(name: 'id') final int id, + @JsonKey(name: 'title') final AnimeTitle? title, + @JsonKey(name: 'coverImage') final Map coverImage, + @JsonKey(name: 'description') final String? description, + @JsonKey(name: 'status') final AnimeStatus? status, + @JsonKey(name: 'source') final AnimeSource? source, + @JsonKey(name: 'episodes') final int? episodes, + @JsonKey(name: 'seasonYear') final int? seasonYear, + @JsonKey(name: 'season') final AnimeSeason? season, + @JsonKey(name: 'hashtag') final String? hashtag, + @JsonKey(name: 'bannerImage') final String? bannerImage, + @JsonKey(name: 'averageScore') final int? averageScore, + @JsonKey(name: 'trending') final int? trending, + @JsonKey(name: 'favourites') final int? favourites, + @JsonKey(name: 'genres') final List genres, + @JsonKey(name: 'trailer') final TrailerDto? trailer, + @JsonKey(name: 'nextAiringEpisode') + final AiringScheduleDto? nextAiringEpisode, + @JsonKey(name: 'rankings') final List rankings, + @JsonKey(name: 'characters') final CharacterConnection? characters, + @JsonKey(name: 'staff') final StaffConnection? staff, + @JsonKey(name: 'externalLinks') + final List externalLinks}) = _$_DetailAnimeDto; factory _DetailAnimeDto.fromJson(Map json) = _$_DetailAnimeDto.fromJson; @@ -723,6 +755,9 @@ abstract class _DetailAnimeDto implements DetailAnimeDto { @JsonKey(name: 'staff') StaffConnection? get staff; @override + @JsonKey(name: 'externalLinks') + List get externalLinks; + @override @JsonKey(ignore: true) _$$_DetailAnimeDtoCopyWith<_$_DetailAnimeDto> get copyWith => throw _privateConstructorUsedError; diff --git a/lib/core/network/model/detail_anime_dto.g.dart b/lib/core/network/model/detail_anime_dto.g.dart index f0c338f1..29371548 100644 --- a/lib/core/network/model/detail_anime_dto.g.dart +++ b/lib/core/network/model/detail_anime_dto.g.dart @@ -48,6 +48,11 @@ _$_DetailAnimeDto _$$_DetailAnimeDtoFromJson(Map json) => staff: json['staff'] == null ? null : StaffConnection.fromJson(json['staff'] as Map), + externalLinks: (json['externalLinks'] as List?) + ?.map((e) => + MediaExternalLinkDto.fromJson(e as Map)) + .toList() ?? + const [], ); Map _$$_DetailAnimeDtoToJson(_$_DetailAnimeDto instance) => @@ -72,6 +77,7 @@ Map _$$_DetailAnimeDtoToJson(_$_DetailAnimeDto instance) => 'rankings': instance.rankings, 'characters': instance.characters, 'staff': instance.staff, + 'externalLinks': instance.externalLinks, }; const _$AnimeStatusEnumMap = { diff --git a/lib/core/network/model/media_external_links_dto.dart b/lib/core/network/model/media_external_links_dto.dart new file mode 100644 index 00000000..7cb3afdc --- /dev/null +++ b/lib/core/network/model/media_external_links_dto.dart @@ -0,0 +1,21 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'media_external_links_dto.freezed.dart'; + +part 'media_external_links_dto.g.dart'; + +@freezed +class MediaExternalLinkDto with _$MediaExternalLinkDto { + factory MediaExternalLinkDto({ + @JsonKey(name: 'id') int? id, + @JsonKey(name: 'url') String? url, + @JsonKey(name: 'site') String? site, + @JsonKey(name: 'type') String? type, + @JsonKey(name: 'siteId') int? siteId, + @JsonKey(name: 'color') String? color, + @JsonKey(name: 'icon') String? icon, + }) = _MediaExternalLinkDto; + + factory MediaExternalLinkDto.fromJson(Map json) => + _$$_MediaExternalLinkDtoFromJson(json); +} diff --git a/lib/core/network/model/media_external_links_dto.freezed.dart b/lib/core/network/model/media_external_links_dto.freezed.dart new file mode 100644 index 00000000..e61bdc16 --- /dev/null +++ b/lib/core/network/model/media_external_links_dto.freezed.dart @@ -0,0 +1,299 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// 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_external_links_dto.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); + +MediaExternalLinkDto _$MediaExternalLinkDtoFromJson(Map json) { + return _MediaExternalLinkDto.fromJson(json); +} + +/// @nodoc +mixin _$MediaExternalLinkDto { + @JsonKey(name: 'id') + int? get id => throw _privateConstructorUsedError; + @JsonKey(name: 'url') + String? get url => throw _privateConstructorUsedError; + @JsonKey(name: 'site') + String? get site => throw _privateConstructorUsedError; + @JsonKey(name: 'type') + String? get type => throw _privateConstructorUsedError; + @JsonKey(name: 'siteId') + int? get siteId => throw _privateConstructorUsedError; + @JsonKey(name: 'color') + String? get color => throw _privateConstructorUsedError; + @JsonKey(name: 'icon') + String? get icon => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $MediaExternalLinkDtoCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $MediaExternalLinkDtoCopyWith<$Res> { + factory $MediaExternalLinkDtoCopyWith(MediaExternalLinkDto value, + $Res Function(MediaExternalLinkDto) then) = + _$MediaExternalLinkDtoCopyWithImpl<$Res, MediaExternalLinkDto>; + @useResult + $Res call( + {@JsonKey(name: 'id') int? id, + @JsonKey(name: 'url') String? url, + @JsonKey(name: 'site') String? site, + @JsonKey(name: 'type') String? type, + @JsonKey(name: 'siteId') int? siteId, + @JsonKey(name: 'color') String? color, + @JsonKey(name: 'icon') String? icon}); +} + +/// @nodoc +class _$MediaExternalLinkDtoCopyWithImpl<$Res, + $Val extends MediaExternalLinkDto> + implements $MediaExternalLinkDtoCopyWith<$Res> { + _$MediaExternalLinkDtoCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? url = freezed, + Object? site = freezed, + Object? type = freezed, + Object? siteId = freezed, + Object? color = freezed, + Object? icon = freezed, + }) { + return _then(_value.copyWith( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as int?, + url: freezed == url + ? _value.url + : url // ignore: cast_nullable_to_non_nullable + as String?, + site: freezed == site + ? _value.site + : site // ignore: cast_nullable_to_non_nullable + as String?, + type: freezed == type + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as String?, + siteId: freezed == siteId + ? _value.siteId + : siteId // ignore: cast_nullable_to_non_nullable + as int?, + color: freezed == color + ? _value.color + : color // ignore: cast_nullable_to_non_nullable + as String?, + icon: freezed == icon + ? _value.icon + : icon // ignore: cast_nullable_to_non_nullable + as String?, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$_MediaExternalLinkDtoCopyWith<$Res> + implements $MediaExternalLinkDtoCopyWith<$Res> { + factory _$$_MediaExternalLinkDtoCopyWith(_$_MediaExternalLinkDto value, + $Res Function(_$_MediaExternalLinkDto) then) = + __$$_MediaExternalLinkDtoCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {@JsonKey(name: 'id') int? id, + @JsonKey(name: 'url') String? url, + @JsonKey(name: 'site') String? site, + @JsonKey(name: 'type') String? type, + @JsonKey(name: 'siteId') int? siteId, + @JsonKey(name: 'color') String? color, + @JsonKey(name: 'icon') String? icon}); +} + +/// @nodoc +class __$$_MediaExternalLinkDtoCopyWithImpl<$Res> + extends _$MediaExternalLinkDtoCopyWithImpl<$Res, _$_MediaExternalLinkDto> + implements _$$_MediaExternalLinkDtoCopyWith<$Res> { + __$$_MediaExternalLinkDtoCopyWithImpl(_$_MediaExternalLinkDto _value, + $Res Function(_$_MediaExternalLinkDto) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? url = freezed, + Object? site = freezed, + Object? type = freezed, + Object? siteId = freezed, + Object? color = freezed, + Object? icon = freezed, + }) { + return _then(_$_MediaExternalLinkDto( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as int?, + url: freezed == url + ? _value.url + : url // ignore: cast_nullable_to_non_nullable + as String?, + site: freezed == site + ? _value.site + : site // ignore: cast_nullable_to_non_nullable + as String?, + type: freezed == type + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as String?, + siteId: freezed == siteId + ? _value.siteId + : siteId // ignore: cast_nullable_to_non_nullable + as int?, + color: freezed == color + ? _value.color + : color // ignore: cast_nullable_to_non_nullable + as String?, + icon: freezed == icon + ? _value.icon + : icon // ignore: cast_nullable_to_non_nullable + as String?, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$_MediaExternalLinkDto implements _MediaExternalLinkDto { + _$_MediaExternalLinkDto( + {@JsonKey(name: 'id') this.id, + @JsonKey(name: 'url') this.url, + @JsonKey(name: 'site') this.site, + @JsonKey(name: 'type') this.type, + @JsonKey(name: 'siteId') this.siteId, + @JsonKey(name: 'color') this.color, + @JsonKey(name: 'icon') this.icon}); + + factory _$_MediaExternalLinkDto.fromJson(Map json) => + _$$_MediaExternalLinkDtoFromJson(json); + + @override + @JsonKey(name: 'id') + final int? id; + @override + @JsonKey(name: 'url') + final String? url; + @override + @JsonKey(name: 'site') + final String? site; + @override + @JsonKey(name: 'type') + final String? type; + @override + @JsonKey(name: 'siteId') + final int? siteId; + @override + @JsonKey(name: 'color') + final String? color; + @override + @JsonKey(name: 'icon') + final String? icon; + + @override + String toString() { + return 'MediaExternalLinkDto(id: $id, url: $url, site: $site, type: $type, siteId: $siteId, color: $color, icon: $icon)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$_MediaExternalLinkDto && + (identical(other.id, id) || other.id == id) && + (identical(other.url, url) || other.url == url) && + (identical(other.site, site) || other.site == site) && + (identical(other.type, type) || other.type == type) && + (identical(other.siteId, siteId) || other.siteId == siteId) && + (identical(other.color, color) || other.color == color) && + (identical(other.icon, icon) || other.icon == icon)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => + Object.hash(runtimeType, id, url, site, type, siteId, color, icon); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$_MediaExternalLinkDtoCopyWith<_$_MediaExternalLinkDto> get copyWith => + __$$_MediaExternalLinkDtoCopyWithImpl<_$_MediaExternalLinkDto>( + this, _$identity); + + @override + Map toJson() { + return _$$_MediaExternalLinkDtoToJson( + this, + ); + } +} + +abstract class _MediaExternalLinkDto implements MediaExternalLinkDto { + factory _MediaExternalLinkDto( + {@JsonKey(name: 'id') final int? id, + @JsonKey(name: 'url') final String? url, + @JsonKey(name: 'site') final String? site, + @JsonKey(name: 'type') final String? type, + @JsonKey(name: 'siteId') final int? siteId, + @JsonKey(name: 'color') final String? color, + @JsonKey(name: 'icon') final String? icon}) = _$_MediaExternalLinkDto; + + factory _MediaExternalLinkDto.fromJson(Map json) = + _$_MediaExternalLinkDto.fromJson; + + @override + @JsonKey(name: 'id') + int? get id; + @override + @JsonKey(name: 'url') + String? get url; + @override + @JsonKey(name: 'site') + String? get site; + @override + @JsonKey(name: 'type') + String? get type; + @override + @JsonKey(name: 'siteId') + int? get siteId; + @override + @JsonKey(name: 'color') + String? get color; + @override + @JsonKey(name: 'icon') + String? get icon; + @override + @JsonKey(ignore: true) + _$$_MediaExternalLinkDtoCopyWith<_$_MediaExternalLinkDto> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/core/network/model/media_external_links_dto.g.dart b/lib/core/network/model/media_external_links_dto.g.dart new file mode 100644 index 00000000..6aa245c1 --- /dev/null +++ b/lib/core/network/model/media_external_links_dto.g.dart @@ -0,0 +1,31 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'media_external_links_dto.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$_MediaExternalLinkDto _$$_MediaExternalLinkDtoFromJson( + Map json) => + _$_MediaExternalLinkDto( + id: json['id'] as int?, + url: json['url'] as String?, + site: json['site'] as String?, + type: json['type'] as String?, + siteId: json['siteId'] as int?, + color: json['color'] as String?, + icon: json['icon'] as String?, + ); + +Map _$$_MediaExternalLinkDtoToJson( + _$_MediaExternalLinkDto instance) => + { + 'id': instance.id, + 'url': instance.url, + 'site': instance.site, + 'type': instance.type, + 'siteId': instance.siteId, + 'color': instance.color, + 'icon': instance.icon, + }; diff --git a/lib/feature/detail_anime/detail_anime.dart b/lib/feature/detail_anime/detail_anime.dart index 86443bb7..88219930 100644 --- a/lib/feature/detail_anime/detail_anime.dart +++ b/lib/feature/detail_anime/detail_anime.dart @@ -5,6 +5,7 @@ import 'package:anime_tracker/core/common/util/global_static_constants.dart'; import 'package:anime_tracker/core/data/model/anime_title_modle.dart'; import 'package:anime_tracker/core/data/model/character_and_voice_actor_model.dart'; import 'package:anime_tracker/core/data/model/anime_model.dart'; +import 'package:anime_tracker/core/data/model/media_external_link_model.dart'; import 'package:anime_tracker/core/data/model/staff_and_role_model.dart'; import 'package:anime_tracker/core/data/model/trailter_model.dart'; import 'package:anime_tracker/core/data/media_information_repository.dart'; @@ -118,42 +119,49 @@ class _DetailAnimePageContent extends StatelessWidget { SliverToBoxAdapter( child: _buildBannerSectionSection(context, model.bannerImage), ), - const SliverToBoxAdapter(child: SizedBox(height: 16)), + const SliverPadding(padding: EdgeInsets.only(top: 16)), SliverToBoxAdapter( child: _buildAnimeBasicInfoBar( context: context, model: model, ), ), - const SliverToBoxAdapter(child: SizedBox(height: 16)), + const SliverPadding(padding: EdgeInsets.only(top: 16)), SliverToBoxAdapter( child: _buildTwitterHashTags(context, model), ), SliverToBoxAdapter( child: _buildAnimeInfoSection(context, model), ), - const SliverToBoxAdapter(child: SizedBox(height: 16)), + const SliverPadding(padding: EdgeInsets.only(top: 16)), SliverToBoxAdapter( child: _buildAnimeDescription( context: context, description: model.description, ), ), - const SliverToBoxAdapter(child: SizedBox(height: 16)), + const SliverPadding(padding: EdgeInsets.only(top: 16)), SliverToBoxAdapter( child: _buildCharacterSection( context, model.characterAndVoiceActors, ), ), - const SliverToBoxAdapter(child: SizedBox(height: 16)), + const SliverPadding(padding: EdgeInsets.only(top: 16)), SliverToBoxAdapter( child: _buildStaffsSection( context, model.staffs, ), ), - const SliverToBoxAdapter(child: SizedBox(height: 16)), + const SliverPadding(padding: EdgeInsets.only(top: 16)), + SliverToBoxAdapter( + child: _buildExternalLinkSection( + context, + model.externalLinks, + ), + ), + const SliverPadding(padding: EdgeInsets.only(top: 16)), SliverToBoxAdapter( child: _buildTrailerSection( context, @@ -163,7 +171,7 @@ class _DetailAnimePageContent extends StatelessWidget { }, ), ), - const SliverToBoxAdapter(child: SizedBox(height: 16)), + const SliverPadding(padding: EdgeInsets.only(top: 16)), ], ), ); @@ -257,58 +265,56 @@ class _DetailAnimePageContent extends StatelessWidget { Widget _buildAnimeDescription( {required BuildContext context, required String? description}) { return VerticalScaleSwitcher( - child: description != null - ? Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - AFLocalizations.of(context).animeDescription, - style: Theme.of(context).textTheme.titleMedium, - ), - Html(data: description), - ], - ), - ) - : const SizedBox(), + visible: description != null, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + AFLocalizations.of(context).animeDescription, + style: Theme.of(context).textTheme.titleMedium, + ), + description != null ? Html(data: description) : const SizedBox(), + ], + ), + ), ); } Widget _buildCharacterSection( BuildContext context, List models) { return VerticalScaleSwitcher( - child: models.isNotEmpty - ? Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - child: Text( - AFLocalizations.of(context).characters, - style: Theme.of(context).textTheme.titleMedium, - ), - ), - const SizedBox(height: 8), - SizedBox( - height: 400, - child: PageView.builder( - itemCount: (models.length / 3).ceil(), - itemBuilder: (BuildContext context, int index) { - return Column( - mainAxisSize: MainAxisSize.min, - children: _createColumItemsPage(context, - models: models, - pageCount: 3, - pageIndex: index, - onBuildWidget: _buildCharacterAndVoiceActorItem), - ); - }, - ), - ), - ], - ) - : const SizedBox(), + visible: models.isNotEmpty, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + child: Text( + AFLocalizations.of(context).characters, + style: Theme.of(context).textTheme.titleMedium, + ), + ), + const SizedBox(height: 8), + SizedBox( + height: 400, + child: PageView.builder( + itemCount: (models.length / 3).ceil(), + itemBuilder: (BuildContext context, int index) { + return Column( + mainAxisSize: MainAxisSize.min, + children: _createColumItemsPage(context, + models: models, + pageCount: 3, + pageIndex: index, + onBuildWidget: _buildCharacterAndVoiceActorItem), + ); + }, + ), + ), + ], + ), ); } @@ -329,44 +335,43 @@ class _DetailAnimePageContent extends StatelessWidget { Widget _buildStaffsSection( BuildContext context, List staffs) { return VerticalScaleSwitcher( - child: staffs.isNotEmpty - ? Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - child: Text( - AFLocalizations.of(context).staff, - style: Theme.of(context).textTheme.titleMedium, - ), - ), - const SizedBox(height: 8), - SizedBox( - height: 266, - child: PageView.builder( - itemCount: (staffs.length).ceil(), - itemBuilder: (BuildContext context, int index) { - return PageView.builder( - itemCount: (staffs.length / 2).ceil(), - itemBuilder: (BuildContext context, int index) { - return Column( - mainAxisSize: MainAxisSize.min, - children: _createColumItemsPage( - context, - models: staffs, - pageCount: 2, - pageIndex: index, - onBuildWidget: _buildStaffItem, - ), - ); - }, - ); - }, - ), - ), - ], - ) - : const SizedBox(), + visible: staffs.isNotEmpty, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + child: Text( + AFLocalizations.of(context).staff, + style: Theme.of(context).textTheme.titleMedium, + ), + ), + const SizedBox(height: 8), + SizedBox( + height: 266, + child: PageView.builder( + itemCount: (staffs.length).ceil(), + itemBuilder: (BuildContext context, int index) { + return PageView.builder( + itemCount: (staffs.length / 2).ceil(), + itemBuilder: (BuildContext context, int index) { + return Column( + mainAxisSize: MainAxisSize.min, + children: _createColumItemsPage( + context, + models: staffs, + pageCount: 2, + pageIndex: index, + onBuildWidget: _buildStaffItem, + ), + ); + }, + ); + }, + ), + ), + ], + ), ); } @@ -397,68 +402,78 @@ class _DetailAnimePageContent extends StatelessWidget { ); } + Widget _buildExternalLinkSection( + BuildContext context, List externalLinks) { + return VerticalScaleSwitcher( + visible: externalLinks.isNotEmpty, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Wrap( + children: externalLinks.map((e) => Text(e.site)).toList(), + ), + ), + ); + } + Widget _buildTrailerSection(BuildContext context, {required VoidCallback onTrailerClick, TrailerModel? trailerModel}) { return VerticalScaleSwitcher( - child: trailerModel != null - ? Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - mainAxisSize: MainAxisSize.max, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - AFLocalizations.of(context).trailer, - style: Theme.of(context).textTheme.titleMedium, - ), - const SizedBox(height: 8), - TrailerPreview( - model: trailerModel, - onTrailerClick: onTrailerClick, - ), - ], - ), - ) - : const SizedBox(), + visible: trailerModel != null, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + AFLocalizations.of(context).trailer, + style: Theme.of(context).textTheme.titleMedium, + ), + const SizedBox(height: 8), + TrailerPreview( + model: trailerModel, + onTrailerClick: onTrailerClick, + ), + ], + ), + ), ); } Widget _buildTwitterHashTags(BuildContext context, AnimeModel model) { final hashTags = model.hashtags; return VerticalScaleSwitcher( - child: hashTags.isNotEmpty - ? Padding( - padding: const EdgeInsets.all(8.0), - child: Wrap( - spacing: 10, - children: hashTags - .map((hashtag) => TwitterHashtagWidget(hashtag: hashtag)) - .toList(), - ), - ) - : const SizedBox(), + visible: hashTags.isNotEmpty, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Wrap( + spacing: 10, + children: hashTags + .map((hashtag) => TwitterHashtagWidget(hashtag: hashtag)) + .toList(), + ), + ), ); } Widget _buildAnimeInfoSection(BuildContext context, AnimeModel model) { final infoString = model.getAnimeInfoString(context); return VerticalScaleSwitcher( - child: infoString.isNotEmpty - ? Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - model.getAnimeInfoString(context), - style: Theme.of(context).textTheme.titleMedium, - ), - const SizedBox(height: 8), - _buildAiringInfo(context, model) - ], - ), - ) - : const SizedBox(), + visible: infoString.isNotEmpty, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + model.getAnimeInfoString(context), + style: Theme.of(context).textTheme.titleMedium, + ), + const SizedBox(height: 8), + _buildAiringInfo(context, model) + ], + ), + ), ); } @@ -470,6 +485,7 @@ class _DetailAnimePageContent extends StatelessWidget { } const stringRes = 'Next airing schedule is EP.%s in %s'; return VerticalScaleSwitcher( + visible: true, child: Padding( padding: const EdgeInsets.all(8.0), child: Text( diff --git a/test/core/data/repository/ani_lsit_repository_test.dart b/test/core/data/repository/ani_lsit_repository_test.dart index 642b5ef2..dd7072ab 100644 --- a/test/core/data/repository/ani_lsit_repository_test.dart +++ b/test/core/data/repository/ani_lsit_repository_test.dart @@ -95,11 +95,11 @@ void main() { }); test('ani_list_fetch_anime_detail_data_and_get_result', () async { - await aniListRepository.startFetchDetailAnimeInfo('789'); + await aniListRepository.startFetchDetailAnimeInfo('161964'); final res = await aniListRepository - .getDetailAnimeInfoStream('789') + .getDetailAnimeInfoStream('161964') .first; - expect(res.id, equals('789')); + expect(res.id, equals('161964')); }); test('ani_list_refresh_airing_schedule', () async { diff --git a/test/core/database/anime_database_test.dart b/test/core/database/anime_database_test.dart index 2d3a73ce..7e7291fe 100644 --- a/test/core/database/anime_database_test.dart +++ b/test/core/database/anime_database_test.dart @@ -4,6 +4,7 @@ import 'package:anime_tracker/core/database/anime_database.dart'; import 'package:anime_tracker/core/database/model/airing_schedules_entity.dart'; import 'package:anime_tracker/core/database/model/anime_entity.dart'; import 'package:anime_tracker/core/database/model/character_entity.dart'; +import 'package:anime_tracker/core/database/model/media_external_link_entity.dart'; import 'package:anime_tracker/core/database/model/user_data_entity.dart'; import 'package:anime_tracker/core/database/model/staff_entity.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -94,6 +95,18 @@ void main() { AiringSchedulesEntity(id: '132', mediaId: '8917', airingAt: 3), AiringSchedulesEntity(id: '142', mediaId: '4353', airingAt: 2), AiringSchedulesEntity(id: '152', mediaId: '9523', airingAt: 4), + ]; + final dummyExternalLinks = [ + MediaExternalLinkEntity( + id: '212', + animeId: '5784', + site: 'youtube', + ), + MediaExternalLinkEntity( + id: '124', + animeId: '9523', + site: 'bilibili', + ), ]; setUp(() async { @@ -111,6 +124,7 @@ void main() { await animeDatabase.animeDB.delete(Tables.animeCharacterCrossRefTable); await animeDatabase.animeDB.delete(Tables.characterTable); await animeDatabase.animeDB.delete(Tables.airingSchedulesTable); + await animeDatabase.animeDB.delete(Tables.mediaExternalLickTable); }); test('anime_dao_clear_all', () async { @@ -264,5 +278,15 @@ void main() { .sublist(0, 3) ..sort((a, b) => a.airingAt!.compareTo(b.airingAt!)))); }); + + test('upsert_media_external_links_test', () async { + final animeDao = animeDatabase.getAnimeDao(); + + await animeDao.upsertAnimeInformation(dummyAnimeData); + await animeDao.upsertMediaExternalLinks(externalLinks: dummyExternalLinks); + + final result = await animeDao.getDetailAnimeInfo('5784'); + expect(result.externalLinks, equals([dummyExternalLinks[0]])); + }); }); } From 0e7ed71aa2f570e1aef9cdf64a32e16dba5c96e2 Mon Sep 17 00:00:00 2001 From: andannn Date: Sat, 14 Oct 2023 22:25:10 +0800 Subject: [PATCH 2/4] external link item widget --- lib/core/common/util/color_util.dart | 16 ++++ .../data/model/media_external_link_model.dart | 2 + .../media_external_link_model.freezed.dart | 36 +++++++-- .../model/media_external_link_model.g.dart | 2 + .../model/media_external_link_entity.dart | 2 + .../media_external_link_entity.freezed.dart | 29 ++++++- .../model/media_external_link_entity.g.dart | 2 + lib/feature/detail_anime/detail_anime.dart | 75 ++++++++++++++++--- test/core/common/common_test.dart | 11 +++ 9 files changed, 153 insertions(+), 22 deletions(-) create mode 100644 lib/core/common/util/color_util.dart diff --git a/lib/core/common/util/color_util.dart b/lib/core/common/util/color_util.dart new file mode 100644 index 00000000..6d064844 --- /dev/null +++ b/lib/core/common/util/color_util.dart @@ -0,0 +1,16 @@ +import 'dart:ui'; + +mixin ColorUtil { + /// parse color with format #001100. + static Color? parseColor(String source) { + final colorRegex = RegExp('#\\w{6}'); + if (!colorRegex.hasMatch(source)) { + return null; + } + + final r = int.parse(source.substring(1, 3), radix: 16); + final g = int.parse(source.substring(3, 5), radix: 16); + final b = int.parse(source.substring(5, 7), radix: 16); + return Color.fromARGB(255, r, g, b); + } +} \ No newline at end of file diff --git a/lib/core/data/model/media_external_link_model.dart b/lib/core/data/model/media_external_link_model.dart index 28a47ea9..db29cd6c 100644 --- a/lib/core/data/model/media_external_link_model.dart +++ b/lib/core/data/model/media_external_link_model.dart @@ -14,6 +14,7 @@ class MediaExternalLinkModel with _$MediaExternalLinkModel { @Default(MediaExternalLinkType.info) MediaExternalLinkType type, @Default(-1) int siteId, @Default('') String icon, + @Default('') String color, }) = _MediaExternalLinkModel; factory MediaExternalLinkModel.fromJson(Map json) => @@ -27,6 +28,7 @@ class MediaExternalLinkModel with _$MediaExternalLinkModel { MediaExternalLinkType.info, siteId: entity.siteId ?? -1, icon: entity.icon ?? '', + color: entity.color ?? '', ); } } diff --git a/lib/core/data/model/media_external_link_model.freezed.dart b/lib/core/data/model/media_external_link_model.freezed.dart index 504154f9..cff4a3dc 100644 --- a/lib/core/data/model/media_external_link_model.freezed.dart +++ b/lib/core/data/model/media_external_link_model.freezed.dart @@ -26,6 +26,7 @@ mixin _$MediaExternalLinkModel { MediaExternalLinkType get type => throw _privateConstructorUsedError; int get siteId => throw _privateConstructorUsedError; String get icon => throw _privateConstructorUsedError; + String get color => throw _privateConstructorUsedError; Map toJson() => throw _privateConstructorUsedError; @JsonKey(ignore: true) @@ -44,7 +45,8 @@ abstract class $MediaExternalLinkModelCopyWith<$Res> { String site, MediaExternalLinkType type, int siteId, - String icon}); + String icon, + String color}); } /// @nodoc @@ -66,6 +68,7 @@ class _$MediaExternalLinkModelCopyWithImpl<$Res, Object? type = null, Object? siteId = null, Object? icon = null, + Object? color = null, }) { return _then(_value.copyWith( url: null == url @@ -88,6 +91,10 @@ class _$MediaExternalLinkModelCopyWithImpl<$Res, ? _value.icon : icon // ignore: cast_nullable_to_non_nullable as String, + color: null == color + ? _value.color + : color // ignore: cast_nullable_to_non_nullable + as String, ) as $Val); } } @@ -105,7 +112,8 @@ abstract class _$$_MediaExternalLinkModelCopyWith<$Res> String site, MediaExternalLinkType type, int siteId, - String icon}); + String icon, + String color}); } /// @nodoc @@ -125,6 +133,7 @@ class __$$_MediaExternalLinkModelCopyWithImpl<$Res> Object? type = null, Object? siteId = null, Object? icon = null, + Object? color = null, }) { return _then(_$_MediaExternalLinkModel( url: null == url @@ -147,6 +156,10 @@ class __$$_MediaExternalLinkModelCopyWithImpl<$Res> ? _value.icon : icon // ignore: cast_nullable_to_non_nullable as String, + color: null == color + ? _value.color + : color // ignore: cast_nullable_to_non_nullable + as String, )); } } @@ -159,7 +172,8 @@ class _$_MediaExternalLinkModel implements _MediaExternalLinkModel { this.site = '', this.type = MediaExternalLinkType.info, this.siteId = -1, - this.icon = ''}); + this.icon = '', + this.color = ''}); factory _$_MediaExternalLinkModel.fromJson(Map json) => _$$_MediaExternalLinkModelFromJson(json); @@ -179,10 +193,13 @@ class _$_MediaExternalLinkModel implements _MediaExternalLinkModel { @override @JsonKey() final String icon; + @override + @JsonKey() + final String color; @override String toString() { - return 'MediaExternalLinkModel(url: $url, site: $site, type: $type, siteId: $siteId, icon: $icon)'; + return 'MediaExternalLinkModel(url: $url, site: $site, type: $type, siteId: $siteId, icon: $icon, color: $color)'; } @override @@ -194,12 +211,14 @@ class _$_MediaExternalLinkModel implements _MediaExternalLinkModel { (identical(other.site, site) || other.site == site) && (identical(other.type, type) || other.type == type) && (identical(other.siteId, siteId) || other.siteId == siteId) && - (identical(other.icon, icon) || other.icon == icon)); + (identical(other.icon, icon) || other.icon == icon) && + (identical(other.color, color) || other.color == color)); } @JsonKey(ignore: true) @override - int get hashCode => Object.hash(runtimeType, url, site, type, siteId, icon); + int get hashCode => + Object.hash(runtimeType, url, site, type, siteId, icon, color); @JsonKey(ignore: true) @override @@ -222,7 +241,8 @@ abstract class _MediaExternalLinkModel implements MediaExternalLinkModel { final String site, final MediaExternalLinkType type, final int siteId, - final String icon}) = _$_MediaExternalLinkModel; + final String icon, + final String color}) = _$_MediaExternalLinkModel; factory _MediaExternalLinkModel.fromJson(Map json) = _$_MediaExternalLinkModel.fromJson; @@ -238,6 +258,8 @@ abstract class _MediaExternalLinkModel implements MediaExternalLinkModel { @override String get icon; @override + String get color; + @override @JsonKey(ignore: true) _$$_MediaExternalLinkModelCopyWith<_$_MediaExternalLinkModel> get copyWith => throw _privateConstructorUsedError; diff --git a/lib/core/data/model/media_external_link_model.g.dart b/lib/core/data/model/media_external_link_model.g.dart index 38c1c8fa..4b3a857b 100644 --- a/lib/core/data/model/media_external_link_model.g.dart +++ b/lib/core/data/model/media_external_link_model.g.dart @@ -15,6 +15,7 @@ _$_MediaExternalLinkModel _$$_MediaExternalLinkModelFromJson( MediaExternalLinkType.info, siteId: json['siteId'] as int? ?? -1, icon: json['icon'] as String? ?? '', + color: json['color'] as String? ?? '', ); Map _$$_MediaExternalLinkModelToJson( @@ -25,6 +26,7 @@ Map _$$_MediaExternalLinkModelToJson( 'type': _$MediaExternalLinkTypeEnumMap[instance.type]!, 'siteId': instance.siteId, 'icon': instance.icon, + 'color': instance.color, }; const _$MediaExternalLinkTypeEnumMap = { diff --git a/lib/core/database/model/media_external_link_entity.dart b/lib/core/database/model/media_external_link_entity.dart index 238666e2..dc5c3e78 100644 --- a/lib/core/database/model/media_external_link_entity.dart +++ b/lib/core/database/model/media_external_link_entity.dart @@ -17,6 +17,7 @@ class MediaExternalLinkEntity with _$MediaExternalLinkEntity { @JsonKey(name: MediaExternalLinkColumnValues.site) String? site, @JsonKey(name: MediaExternalLinkColumnValues.type) String? type, @JsonKey(name: MediaExternalLinkColumnValues.siteId) int? siteId, + @JsonKey(name: MediaExternalLinkColumnValues.color) String? color, @JsonKey(name: MediaExternalLinkColumnValues.icon) String? icon, }) = _MediaExternalLinkEntity; @@ -33,6 +34,7 @@ class MediaExternalLinkEntity with _$MediaExternalLinkEntity { type: dto.type, siteId: dto.siteId, icon: dto.icon, + color: dto.color ); } } diff --git a/lib/core/database/model/media_external_link_entity.freezed.dart b/lib/core/database/model/media_external_link_entity.freezed.dart index 6a75af69..8933f9be 100644 --- a/lib/core/database/model/media_external_link_entity.freezed.dart +++ b/lib/core/database/model/media_external_link_entity.freezed.dart @@ -33,6 +33,8 @@ mixin _$MediaExternalLinkEntity { String? get type => throw _privateConstructorUsedError; @JsonKey(name: MediaExternalLinkColumnValues.siteId) int? get siteId => throw _privateConstructorUsedError; + @JsonKey(name: MediaExternalLinkColumnValues.color) + String? get color => throw _privateConstructorUsedError; @JsonKey(name: MediaExternalLinkColumnValues.icon) String? get icon => throw _privateConstructorUsedError; @@ -55,6 +57,7 @@ abstract class $MediaExternalLinkEntityCopyWith<$Res> { @JsonKey(name: MediaExternalLinkColumnValues.site) String? site, @JsonKey(name: MediaExternalLinkColumnValues.type) String? type, @JsonKey(name: MediaExternalLinkColumnValues.siteId) int? siteId, + @JsonKey(name: MediaExternalLinkColumnValues.color) String? color, @JsonKey(name: MediaExternalLinkColumnValues.icon) String? icon}); } @@ -78,6 +81,7 @@ class _$MediaExternalLinkEntityCopyWithImpl<$Res, Object? site = freezed, Object? type = freezed, Object? siteId = freezed, + Object? color = freezed, Object? icon = freezed, }) { return _then(_value.copyWith( @@ -105,6 +109,10 @@ class _$MediaExternalLinkEntityCopyWithImpl<$Res, ? _value.siteId : siteId // ignore: cast_nullable_to_non_nullable as int?, + color: freezed == color + ? _value.color + : color // ignore: cast_nullable_to_non_nullable + as String?, icon: freezed == icon ? _value.icon : icon // ignore: cast_nullable_to_non_nullable @@ -128,6 +136,7 @@ abstract class _$$_MediaExternalLinkEntityCopyWith<$Res> @JsonKey(name: MediaExternalLinkColumnValues.site) String? site, @JsonKey(name: MediaExternalLinkColumnValues.type) String? type, @JsonKey(name: MediaExternalLinkColumnValues.siteId) int? siteId, + @JsonKey(name: MediaExternalLinkColumnValues.color) String? color, @JsonKey(name: MediaExternalLinkColumnValues.icon) String? icon}); } @@ -149,6 +158,7 @@ class __$$_MediaExternalLinkEntityCopyWithImpl<$Res> Object? site = freezed, Object? type = freezed, Object? siteId = freezed, + Object? color = freezed, Object? icon = freezed, }) { return _then(_$_MediaExternalLinkEntity( @@ -176,6 +186,10 @@ class __$$_MediaExternalLinkEntityCopyWithImpl<$Res> ? _value.siteId : siteId // ignore: cast_nullable_to_non_nullable as int?, + color: freezed == color + ? _value.color + : color // ignore: cast_nullable_to_non_nullable + as String?, icon: freezed == icon ? _value.icon : icon // ignore: cast_nullable_to_non_nullable @@ -194,6 +208,7 @@ class _$_MediaExternalLinkEntity implements _MediaExternalLinkEntity { @JsonKey(name: MediaExternalLinkColumnValues.site) this.site, @JsonKey(name: MediaExternalLinkColumnValues.type) this.type, @JsonKey(name: MediaExternalLinkColumnValues.siteId) this.siteId, + @JsonKey(name: MediaExternalLinkColumnValues.color) this.color, @JsonKey(name: MediaExternalLinkColumnValues.icon) this.icon}); factory _$_MediaExternalLinkEntity.fromJson(Map json) => @@ -218,12 +233,15 @@ class _$_MediaExternalLinkEntity implements _MediaExternalLinkEntity { @JsonKey(name: MediaExternalLinkColumnValues.siteId) final int? siteId; @override + @JsonKey(name: MediaExternalLinkColumnValues.color) + final String? color; + @override @JsonKey(name: MediaExternalLinkColumnValues.icon) final String? icon; @override String toString() { - return 'MediaExternalLinkEntity(id: $id, animeId: $animeId, url: $url, site: $site, type: $type, siteId: $siteId, icon: $icon)'; + return 'MediaExternalLinkEntity(id: $id, animeId: $animeId, url: $url, site: $site, type: $type, siteId: $siteId, color: $color, icon: $icon)'; } @override @@ -237,13 +255,14 @@ class _$_MediaExternalLinkEntity implements _MediaExternalLinkEntity { (identical(other.site, site) || other.site == site) && (identical(other.type, type) || other.type == type) && (identical(other.siteId, siteId) || other.siteId == siteId) && + (identical(other.color, color) || other.color == color) && (identical(other.icon, icon) || other.icon == icon)); } @JsonKey(ignore: true) @override - int get hashCode => - Object.hash(runtimeType, id, animeId, url, site, type, siteId, icon); + int get hashCode => Object.hash( + runtimeType, id, animeId, url, site, type, siteId, color, icon); @JsonKey(ignore: true) @override @@ -270,6 +289,7 @@ abstract class _MediaExternalLinkEntity implements MediaExternalLinkEntity { @JsonKey(name: MediaExternalLinkColumnValues.site) final String? site, @JsonKey(name: MediaExternalLinkColumnValues.type) final String? type, @JsonKey(name: MediaExternalLinkColumnValues.siteId) final int? siteId, + @JsonKey(name: MediaExternalLinkColumnValues.color) final String? color, @JsonKey(name: MediaExternalLinkColumnValues.icon) final String? icon}) = _$_MediaExternalLinkEntity; @@ -295,6 +315,9 @@ abstract class _MediaExternalLinkEntity implements MediaExternalLinkEntity { @JsonKey(name: MediaExternalLinkColumnValues.siteId) int? get siteId; @override + @JsonKey(name: MediaExternalLinkColumnValues.color) + String? get color; + @override @JsonKey(name: MediaExternalLinkColumnValues.icon) String? get icon; @override diff --git a/lib/core/database/model/media_external_link_entity.g.dart b/lib/core/database/model/media_external_link_entity.g.dart index 6689ebf5..b55a59d3 100644 --- a/lib/core/database/model/media_external_link_entity.g.dart +++ b/lib/core/database/model/media_external_link_entity.g.dart @@ -15,6 +15,7 @@ _$_MediaExternalLinkEntity _$$_MediaExternalLinkEntityFromJson( site: json['external_link_site'] as String?, type: json['external_link_type'] as String?, siteId: json['external_link_siteId'] as int?, + color: json['external_link_color'] as String?, icon: json['external_link_icon'] as String?, ); @@ -27,5 +28,6 @@ Map _$$_MediaExternalLinkEntityToJson( 'external_link_site': instance.site, 'external_link_type': instance.type, 'external_link_siteId': instance.siteId, + 'external_link_color': instance.color, 'external_link_icon': instance.icon, }; diff --git a/lib/feature/detail_anime/detail_anime.dart b/lib/feature/detail_anime/detail_anime.dart index 88219930..a2c423b4 100644 --- a/lib/feature/detail_anime/detail_anime.dart +++ b/lib/feature/detail_anime/detail_anime.dart @@ -1,6 +1,7 @@ import 'dart:math'; import 'package:anime_tracker/app/local/ani_flow_localizations.dart'; +import 'package:anime_tracker/core/common/util/color_util.dart'; import 'package:anime_tracker/core/common/util/global_static_constants.dart'; import 'package:anime_tracker/core/data/model/anime_title_modle.dart'; import 'package:anime_tracker/core/data/model/character_and_voice_actor_model.dart'; @@ -155,13 +156,6 @@ class _DetailAnimePageContent extends StatelessWidget { ), ), const SliverPadding(padding: EdgeInsets.only(top: 16)), - SliverToBoxAdapter( - child: _buildExternalLinkSection( - context, - model.externalLinks, - ), - ), - const SliverPadding(padding: EdgeInsets.only(top: 16)), SliverToBoxAdapter( child: _buildTrailerSection( context, @@ -172,6 +166,13 @@ class _DetailAnimePageContent extends StatelessWidget { ), ), const SliverPadding(padding: EdgeInsets.only(top: 16)), + SliverToBoxAdapter( + child: _buildExternalLinkSection( + context, + model.externalLinks, + ), + ), + const SliverPadding(padding: EdgeInsets.only(top: 16)), ], ), ); @@ -406,11 +407,26 @@ class _DetailAnimePageContent extends StatelessWidget { BuildContext context, List externalLinks) { return VerticalScaleSwitcher( visible: externalLinks.isNotEmpty, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Wrap( - children: externalLinks.map((e) => Text(e.site)).toList(), - ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + child: Text( + 'External & Streaming links', + style: Theme.of(context).textTheme.titleMedium, + ), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Wrap( + spacing: 6, + children: externalLinks + .map((e) => _ExternalLinkItem(externalLink: e)) + .toList(), + ), + ), + ], ), ); } @@ -578,3 +594,38 @@ class _InfoItem extends StatelessWidget { ); } } + +class _ExternalLinkItem extends StatelessWidget { + const _ExternalLinkItem({required this.externalLink}); + + final MediaExternalLinkModel externalLink; + + @override + Widget build(BuildContext context) { + return OutlinedButton.icon( + onPressed: () async { + final url = Uri.parse(externalLink.url); + if (await canLaunchUrl(url)) { + await launchUrl(url); + } + }, + icon: externalLink.icon.isNotEmpty + ? Container( + width: 24, + height: 24, + decoration: ShapeDecoration( + color: ColorUtil.parseColor(externalLink.color), + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(5)), + ), + ), + child: Padding( + padding: const EdgeInsets.all(4.0), + child: AFNetworkImage(imageUrl: externalLink.icon), + ), + ) + : const SizedBox(), + label: Text(externalLink.site), + ); + } +} diff --git a/test/core/common/common_test.dart b/test/core/common/common_test.dart index 3da2b307..7159c4fb 100644 --- a/test/core/common/common_test.dart +++ b/test/core/common/common_test.dart @@ -1,3 +1,4 @@ +import 'package:anime_tracker/core/common/util/color_util.dart'; import 'package:anime_tracker/core/common/util/time_util.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -14,5 +15,15 @@ void main() { test('today', () async { TimeUtil.getTimeRange(DateTime.now(), daysAfter: 0, daysAgo: 0); }); + test('parse_color', () async { + final res1 = ColorUtil.parseColor(''); + expect(res1 != null, equals(false)); + + final res2 = ColorUtil.parseColor('#1234'); + expect(res2 != null, equals(false)); + + final res = ColorUtil.parseColor('#123456'); + expect(res != null, equals(true)); + }); }); } From b496d157c532c16fd82117cd74d0eb783e9976fa Mon Sep 17 00:00:00 2001 From: andannn Date: Sat, 14 Oct 2023 22:54:54 +0800 Subject: [PATCH 3/4] jump to detail page when tap time line item. --- lib/feature/airing_schedule/airing_schedule.dart | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/feature/airing_schedule/airing_schedule.dart b/lib/feature/airing_schedule/airing_schedule.dart index b5a814bb..1e59c343 100644 --- a/lib/feature/airing_schedule/airing_schedule.dart +++ b/lib/feature/airing_schedule/airing_schedule.dart @@ -1,3 +1,4 @@ +import 'package:anime_tracker/app/navigation/ani_flow_router.dart'; import 'package:anime_tracker/core/common/util/logger.dart'; import 'package:anime_tracker/core/data/media_information_repository.dart'; import 'package:anime_tracker/core/design_system/widget/airing_anime_item.dart'; @@ -51,7 +52,7 @@ class AiringScheduleRoute extends PageRoute with MaterialRouteTransitionMixin { } @override - bool get maintainState => false; + bool get maintainState => true; } class _AiringScheduleContent extends StatefulWidget { @@ -240,7 +241,13 @@ class _TimeLineItemState extends State<_TimeLineItem> { top: 2.0, bottom: 2.0, left: 16.0, right: 8.0), child: SizedBox( height: 120, - child: AiringAnimeItem(model: schedule, onClick: () {}), + child: AiringAnimeItem( + model: schedule, + onClick: () { + AnimeTrackerRouterDelegate.of(context) + .navigateToDetailAnime(schedule.animeModel.id); + }, + ), ), ); }, From 4f92fdd8030dd82bb0ae5a93db8615195f889cb6 Mon Sep 17 00:00:00 2001 From: andannn Date: Sat, 14 Oct 2023 23:12:22 +0800 Subject: [PATCH 4/4] remove short anime dto --- lib/core/data/ani_list_repository.dart | 2 +- .../data/media_information_repository.dart | 12 +- lib/core/database/model/anime_entity.dart | 15 +- lib/core/network/ani_list_data_source.dart | 13 +- .../airing_schedules_query_graphql.dart.dart | 3 + .../network/model/airing_schedule_dto.dart | 4 +- .../model/airing_schedule_dto.freezed.dart | 35 ++- .../network/model/airing_schedule_dto.g.dart | 2 +- .../{detail_anime_dto.dart => anime_dto.dart} | 14 +- ...to.freezed.dart => anime_dto.freezed.dart} | 73 +++--- ...tail_anime_dto.g.dart => anime_dto.g.dart} | 7 +- lib/core/network/model/media_list_dto.dart | 4 +- .../network/model/media_list_dto.freezed.dart | 24 +- lib/core/network/model/media_list_dto.g.dart | 2 +- lib/core/network/model/short_anime_dto.dart | 19 -- .../model/short_anime_dto.freezed.dart | 231 ------------------ lib/core/network/model/short_anime_dto.g.dart | 26 -- .../detail_network_anime_model_test.dart | 4 +- .../model/short_network_anime_model_test.dart | 6 +- 19 files changed, 103 insertions(+), 393 deletions(-) rename lib/core/network/model/{detail_anime_dto.dart => anime_dto.dart} (88%) rename lib/core/network/model/{detail_anime_dto.freezed.dart => anime_dto.freezed.dart} (91%) rename lib/core/network/model/{detail_anime_dto.g.dart => anime_dto.g.dart} (94%) delete mode 100644 lib/core/network/model/short_anime_dto.dart delete mode 100644 lib/core/network/model/short_anime_dto.freezed.dart delete mode 100644 lib/core/network/model/short_anime_dto.g.dart diff --git a/lib/core/data/ani_list_repository.dart b/lib/core/data/ani_list_repository.dart index 05c0194c..08dc49f6 100644 --- a/lib/core/data/ani_list_repository.dart +++ b/lib/core/data/ani_list_repository.dart @@ -104,7 +104,7 @@ class AnimeTrackListRepositoryImpl extends AniListRepository { final animeEntities = networkAnimeList .map( (e) => e.media != null - ? AnimeEntity.fromDetailNetworkModel(e.media!) + ? AnimeEntity.fromNetworkModel(e.media!) : null, ) .whereType() diff --git a/lib/core/data/media_information_repository.dart b/lib/core/data/media_information_repository.dart index 098f270f..5c7f77be 100644 --- a/lib/core/data/media_information_repository.dart +++ b/lib/core/data/media_information_repository.dart @@ -9,7 +9,7 @@ import 'package:anime_tracker/core/database/model/media_external_link_entity.dar import 'package:anime_tracker/core/database/model/staff_entity.dart'; import 'package:anime_tracker/core/network/api/airing_schedules_query_graphql.dart.dart'; import 'package:anime_tracker/core/network/model/character_edge.dart'; -import 'package:anime_tracker/core/network/model/detail_anime_dto.dart'; +import 'package:anime_tracker/core/network/model/anime_dto.dart'; import 'package:anime_tracker/core/network/model/media_external_links_dto.dart'; import 'package:anime_tracker/core/network/model/staff_edge.dart'; import 'package:anime_tracker/core/common/util/time_util.dart'; @@ -107,7 +107,7 @@ class MediaInformationRepositoryImpl extends MediaInformationRepository { /// insert the anime to db. final dbAnimeList = networkRes - .map((e) => AnimeEntity.fromShortNetworkModel(e)) + .map((e) => AnimeEntity.fromNetworkModel(e)) .toList(); /// clear and re-insert data when refresh. @@ -130,7 +130,7 @@ class MediaInformationRepositoryImpl extends MediaInformationRepository { /// insert the network data to db. final dbAnimeList = networkRes - .map((e) => AnimeEntity.fromShortNetworkModel(e)) + .map((e) => AnimeEntity.fromNetworkModel(e)) .toList(); await animeDao.insertOrIgnoreAnimeByAnimeCategory(category, animeList: dbAnimeList); @@ -166,13 +166,13 @@ class MediaInformationRepositoryImpl extends MediaInformationRepository { Future> startFetchDetailAnimeInfo(String id) async { try { /// fetch anime info from network. - DetailAnimeDto networkResult = await aniListDataSource.getNetworkAnime( + AnimeDto networkResult = await aniListDataSource.getNetworkAnime( id: int.parse(id), ); /// insert anime info to db. await animeDao.upsertAnimeInformation( - [AnimeEntity.fromDetailNetworkModel(networkResult)], + [AnimeEntity.fromNetworkModel(networkResult)], conflictAlgorithm: ConflictAlgorithm.replace); final List characters = @@ -289,7 +289,7 @@ class MediaInformationRepositoryImpl extends MediaInformationRepository { /// insert anime data to db if not exist. final animeEntities = networkResults - .map((e) => AnimeEntity.fromShortNetworkModel(e.media!)) + .map((e) => AnimeEntity.fromNetworkModel(e.media!)) .toList(); await animeDao.upsertAnimeInformation(animeEntities, conflictAlgorithm: ConflictAlgorithm.ignore); diff --git a/lib/core/database/model/anime_entity.dart b/lib/core/database/model/anime_entity.dart index 31570bd6..dbb53e4e 100644 --- a/lib/core/database/model/anime_entity.dart +++ b/lib/core/database/model/anime_entity.dart @@ -4,8 +4,7 @@ import 'package:anime_tracker/core/common/model/anime_season.dart'; import 'package:anime_tracker/core/common/model/anime_source.dart'; import 'package:anime_tracker/core/common/model/anime_status.dart'; import 'package:anime_tracker/core/database/anime_dao.dart'; -import 'package:anime_tracker/core/network/model/detail_anime_dto.dart'; -import 'package:anime_tracker/core/network/model/short_anime_dto.dart'; +import 'package:anime_tracker/core/network/model/anime_dto.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; part 'anime_entity.freezed.dart'; @@ -53,17 +52,7 @@ class AnimeEntity with _$AnimeEntity { factory AnimeEntity.fromJson(Map json) => _$$_AnimeEntityFromJson(json); - static AnimeEntity fromShortNetworkModel(ShortcutAnimeDto model) => - AnimeEntity( - id: model.id.toString(), - englishTitle: model.title?.english ?? '', - romajiTitle: model.title?.romaji ?? '', - nativeTitle: model.title?.native ?? '', - coverImage: model.coverImage['extraLarge'] ?? '', - coverImageColor: model.coverImage['color'] ?? '', - ); - - static AnimeEntity fromDetailNetworkModel(DetailAnimeDto model) => + static AnimeEntity fromNetworkModel(AnimeDto model) => AnimeEntity( id: model.id.toString(), englishTitle: model.title?.english ?? '', diff --git a/lib/core/network/ani_list_data_source.dart b/lib/core/network/ani_list_data_source.dart index 2ffea851..5618db98 100644 --- a/lib/core/network/ani_list_data_source.dart +++ b/lib/core/network/ani_list_data_source.dart @@ -3,11 +3,10 @@ import 'package:anime_tracker/core/network/api/ani_detail_query_graphql.dart'; import 'package:anime_tracker/core/network/api/user_anime_list_query_graphql.dart'; import 'package:anime_tracker/core/network/client/ani_list_dio.dart'; import 'package:anime_tracker/core/network/model/airing_schedule_dto.dart'; -import 'package:anime_tracker/core/network/model/detail_anime_dto.dart'; +import 'package:anime_tracker/core/network/model/anime_dto.dart'; import 'package:anime_tracker/core/network/api/ani_list_query_graphql.dart'; import 'package:anime_tracker/core/network/model/media_list_dto.dart'; -import 'package:anime_tracker/core/network/model/short_anime_dto.dart'; /// Anime list data source get from AniList. class AniListDataSource { @@ -17,7 +16,7 @@ class AniListDataSource { AniListDataSource._(); - Future getNetworkAnime({required int id}) async { + Future getNetworkAnime({required int id}) async { final queryGraphQL = detailAnimeQueryGraphQLString; final variablesMap = { 'id': id, @@ -26,12 +25,12 @@ class AniListDataSource { data: {'query': queryGraphQL, 'variables': variablesMap}); final resultJson = response.data['data']['Media']; - final DetailAnimeDto detailAnimeDto = DetailAnimeDto.fromJson(resultJson); + final AnimeDto detailAnimeDto = AnimeDto.fromJson(resultJson); return detailAnimeDto; } - Future> getNetworkAnimePage({ + Future> getNetworkAnimePage({ required AnimePageQueryParam param, }) async { final queryGraphQL = animeListQueryGraphQLString; @@ -67,8 +66,8 @@ class AniListDataSource { data: {'query': queryGraphQL, 'variables': variablesMap}); final List resultJson = response.data['data']['Page']['media']; - final List animeList = - resultJson.map((e) => ShortcutAnimeDto.fromJson(e)).toList(); + final List animeList = + resultJson.map((e) => AnimeDto.fromJson(e)).toList(); return animeList; } diff --git a/lib/core/network/api/airing_schedules_query_graphql.dart.dart b/lib/core/network/api/airing_schedules_query_graphql.dart.dart index b78d6ed7..9cba606f 100644 --- a/lib/core/network/api/airing_schedules_query_graphql.dart.dart +++ b/lib/core/network/api/airing_schedules_query_graphql.dart.dart @@ -20,7 +20,10 @@ query(\$airingAt_greater: Int, \$airingAt_lesser: Int){ type format status + seasonYear season + source + episodes coverImage { extraLarge large diff --git a/lib/core/network/model/airing_schedule_dto.dart b/lib/core/network/model/airing_schedule_dto.dart index 55d55ed0..44f0e2de 100644 --- a/lib/core/network/model/airing_schedule_dto.dart +++ b/lib/core/network/model/airing_schedule_dto.dart @@ -1,5 +1,5 @@ -import 'package:anime_tracker/core/network/model/short_anime_dto.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:anime_tracker/core/network/model/anime_dto.dart'; part 'airing_schedule_dto.freezed.dart'; @@ -13,7 +13,7 @@ class AiringScheduleDto with _$AiringScheduleDto { @JsonKey(name: 'airingAt') int? airingAt, @JsonKey(name: 'timeUntilAiring') int? timeUntilAiring, @JsonKey(name: 'episode') int? episode, - @JsonKey(name: 'media') ShortcutAnimeDto? media, + @JsonKey(name: 'media') AnimeDto? media, }) = _AiringScheduleDto; factory AiringScheduleDto.fromJson(Map json) => diff --git a/lib/core/network/model/airing_schedule_dto.freezed.dart b/lib/core/network/model/airing_schedule_dto.freezed.dart index efab4efd..ba346002 100644 --- a/lib/core/network/model/airing_schedule_dto.freezed.dart +++ b/lib/core/network/model/airing_schedule_dto.freezed.dart @@ -31,7 +31,7 @@ mixin _$AiringScheduleDto { @JsonKey(name: 'episode') int? get episode => throw _privateConstructorUsedError; @JsonKey(name: 'media') - ShortcutAnimeDto? get media => throw _privateConstructorUsedError; + AnimeDto? get media => throw _privateConstructorUsedError; Map toJson() => throw _privateConstructorUsedError; @JsonKey(ignore: true) @@ -51,9 +51,9 @@ abstract class $AiringScheduleDtoCopyWith<$Res> { @JsonKey(name: 'airingAt') int? airingAt, @JsonKey(name: 'timeUntilAiring') int? timeUntilAiring, @JsonKey(name: 'episode') int? episode, - @JsonKey(name: 'media') ShortcutAnimeDto? media}); + @JsonKey(name: 'media') AnimeDto? media}); - $ShortcutAnimeDtoCopyWith<$Res>? get media; + $AnimeDtoCopyWith<$Res>? get media; } /// @nodoc @@ -100,18 +100,18 @@ class _$AiringScheduleDtoCopyWithImpl<$Res, $Val extends AiringScheduleDto> media: freezed == media ? _value.media : media // ignore: cast_nullable_to_non_nullable - as ShortcutAnimeDto?, + as AnimeDto?, ) as $Val); } @override @pragma('vm:prefer-inline') - $ShortcutAnimeDtoCopyWith<$Res>? get media { + $AnimeDtoCopyWith<$Res>? get media { if (_value.media == null) { return null; } - return $ShortcutAnimeDtoCopyWith<$Res>(_value.media!, (value) { + return $AnimeDtoCopyWith<$Res>(_value.media!, (value) { return _then(_value.copyWith(media: value) as $Val); }); } @@ -131,10 +131,10 @@ abstract class _$$_AiringScheduleDtoCopyWith<$Res> @JsonKey(name: 'airingAt') int? airingAt, @JsonKey(name: 'timeUntilAiring') int? timeUntilAiring, @JsonKey(name: 'episode') int? episode, - @JsonKey(name: 'media') ShortcutAnimeDto? media}); + @JsonKey(name: 'media') AnimeDto? media}); @override - $ShortcutAnimeDtoCopyWith<$Res>? get media; + $AnimeDtoCopyWith<$Res>? get media; } /// @nodoc @@ -179,7 +179,7 @@ class __$$_AiringScheduleDtoCopyWithImpl<$Res> media: freezed == media ? _value.media : media // ignore: cast_nullable_to_non_nullable - as ShortcutAnimeDto?, + as AnimeDto?, )); } } @@ -215,7 +215,7 @@ class _$_AiringScheduleDto implements _AiringScheduleDto { final int? episode; @override @JsonKey(name: 'media') - final ShortcutAnimeDto? media; + final AnimeDto? media; @override String toString() { @@ -259,13 +259,12 @@ class _$_AiringScheduleDto implements _AiringScheduleDto { abstract class _AiringScheduleDto implements AiringScheduleDto { factory _AiringScheduleDto( - {@JsonKey(name: 'id') final int id, - @JsonKey(name: 'mediaId') final int? mediaId, - @JsonKey(name: 'airingAt') final int? airingAt, - @JsonKey(name: 'timeUntilAiring') final int? timeUntilAiring, - @JsonKey(name: 'episode') final int? episode, - @JsonKey(name: 'media') final ShortcutAnimeDto? media}) = - _$_AiringScheduleDto; + {@JsonKey(name: 'id') final int id, + @JsonKey(name: 'mediaId') final int? mediaId, + @JsonKey(name: 'airingAt') final int? airingAt, + @JsonKey(name: 'timeUntilAiring') final int? timeUntilAiring, + @JsonKey(name: 'episode') final int? episode, + @JsonKey(name: 'media') final AnimeDto? media}) = _$_AiringScheduleDto; factory _AiringScheduleDto.fromJson(Map json) = _$_AiringScheduleDto.fromJson; @@ -287,7 +286,7 @@ abstract class _AiringScheduleDto implements AiringScheduleDto { int? get episode; @override @JsonKey(name: 'media') - ShortcutAnimeDto? get media; + AnimeDto? get media; @override @JsonKey(ignore: true) _$$_AiringScheduleDtoCopyWith<_$_AiringScheduleDto> get copyWith => diff --git a/lib/core/network/model/airing_schedule_dto.g.dart b/lib/core/network/model/airing_schedule_dto.g.dart index fd886ebc..1bd1144b 100644 --- a/lib/core/network/model/airing_schedule_dto.g.dart +++ b/lib/core/network/model/airing_schedule_dto.g.dart @@ -15,7 +15,7 @@ _$_AiringScheduleDto _$$_AiringScheduleDtoFromJson(Map json) => episode: json['episode'] as int?, media: json['media'] == null ? null - : ShortcutAnimeDto.fromJson(json['media'] as Map), + : AnimeDto.fromJson(json['media'] as Map), ); Map _$$_AiringScheduleDtoToJson( diff --git a/lib/core/network/model/detail_anime_dto.dart b/lib/core/network/model/anime_dto.dart similarity index 88% rename from lib/core/network/model/detail_anime_dto.dart rename to lib/core/network/model/anime_dto.dart index 403f64f0..22c74474 100644 --- a/lib/core/network/model/detail_anime_dto.dart +++ b/lib/core/network/model/anime_dto.dart @@ -11,13 +11,13 @@ import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:anime_tracker/core/data/model/anime_title_modle.dart'; import 'package:anime_tracker/core/network/model/character_connection.dart'; -part 'detail_anime_dto.freezed.dart'; +part 'anime_dto.freezed.dart'; -part 'detail_anime_dto.g.dart'; +part 'anime_dto.g.dart'; @freezed -class DetailAnimeDto with _$DetailAnimeDto { - factory DetailAnimeDto({ +class AnimeDto with _$AnimeDto { + factory AnimeDto({ @Default(-1) @JsonKey(name: 'id') int id, @JsonKey(name: 'title') AnimeTitle? title, @Default({}) @JsonKey(name: 'coverImage') Map coverImage, @@ -41,8 +41,8 @@ class DetailAnimeDto with _$DetailAnimeDto { @Default([]) @JsonKey(name: 'externalLinks') List externalLinks, - }) = _DetailAnimeDto; + }) = _AnimeDto; - factory DetailAnimeDto.fromJson(Map json) => - _$$_DetailAnimeDtoFromJson(json); + factory AnimeDto.fromJson(Map json) => + _$$_AnimeDtoFromJson(json); } diff --git a/lib/core/network/model/detail_anime_dto.freezed.dart b/lib/core/network/model/anime_dto.freezed.dart similarity index 91% rename from lib/core/network/model/detail_anime_dto.freezed.dart rename to lib/core/network/model/anime_dto.freezed.dart index 9e2febe8..935c434d 100644 --- a/lib/core/network/model/detail_anime_dto.freezed.dart +++ b/lib/core/network/model/anime_dto.freezed.dart @@ -3,7 +3,7 @@ // 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 'detail_anime_dto.dart'; +part of 'anime_dto.dart'; // ************************************************************************** // FreezedGenerator @@ -14,12 +14,12 @@ T _$identity(T value) => value; final _privateConstructorUsedError = UnsupportedError( 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); -DetailAnimeDto _$DetailAnimeDtoFromJson(Map json) { - return _DetailAnimeDto.fromJson(json); +AnimeDto _$AnimeDtoFromJson(Map json) { + return _AnimeDto.fromJson(json); } /// @nodoc -mixin _$DetailAnimeDto { +mixin _$AnimeDto { @JsonKey(name: 'id') int get id => throw _privateConstructorUsedError; @JsonKey(name: 'title') @@ -67,15 +67,14 @@ mixin _$DetailAnimeDto { Map toJson() => throw _privateConstructorUsedError; @JsonKey(ignore: true) - $DetailAnimeDtoCopyWith get copyWith => + $AnimeDtoCopyWith get copyWith => throw _privateConstructorUsedError; } /// @nodoc -abstract class $DetailAnimeDtoCopyWith<$Res> { - factory $DetailAnimeDtoCopyWith( - DetailAnimeDto value, $Res Function(DetailAnimeDto) then) = - _$DetailAnimeDtoCopyWithImpl<$Res, DetailAnimeDto>; +abstract class $AnimeDtoCopyWith<$Res> { + factory $AnimeDtoCopyWith(AnimeDto value, $Res Function(AnimeDto) then) = + _$AnimeDtoCopyWithImpl<$Res, AnimeDto>; @useResult $Res call( {@JsonKey(name: 'id') int id, @@ -109,9 +108,9 @@ abstract class $DetailAnimeDtoCopyWith<$Res> { } /// @nodoc -class _$DetailAnimeDtoCopyWithImpl<$Res, $Val extends DetailAnimeDto> - implements $DetailAnimeDtoCopyWith<$Res> { - _$DetailAnimeDtoCopyWithImpl(this._value, this._then); +class _$AnimeDtoCopyWithImpl<$Res, $Val extends AnimeDto> + implements $AnimeDtoCopyWith<$Res> { + _$AnimeDtoCopyWithImpl(this._value, this._then); // ignore: unused_field final $Val _value; @@ -293,11 +292,10 @@ class _$DetailAnimeDtoCopyWithImpl<$Res, $Val extends DetailAnimeDto> } /// @nodoc -abstract class _$$_DetailAnimeDtoCopyWith<$Res> - implements $DetailAnimeDtoCopyWith<$Res> { - factory _$$_DetailAnimeDtoCopyWith( - _$_DetailAnimeDto value, $Res Function(_$_DetailAnimeDto) then) = - __$$_DetailAnimeDtoCopyWithImpl<$Res>; +abstract class _$$_AnimeDtoCopyWith<$Res> implements $AnimeDtoCopyWith<$Res> { + factory _$$_AnimeDtoCopyWith( + _$_AnimeDto value, $Res Function(_$_AnimeDto) then) = + __$$_AnimeDtoCopyWithImpl<$Res>; @override @useResult $Res call( @@ -337,11 +335,11 @@ abstract class _$$_DetailAnimeDtoCopyWith<$Res> } /// @nodoc -class __$$_DetailAnimeDtoCopyWithImpl<$Res> - extends _$DetailAnimeDtoCopyWithImpl<$Res, _$_DetailAnimeDto> - implements _$$_DetailAnimeDtoCopyWith<$Res> { - __$$_DetailAnimeDtoCopyWithImpl( - _$_DetailAnimeDto _value, $Res Function(_$_DetailAnimeDto) _then) +class __$$_AnimeDtoCopyWithImpl<$Res> + extends _$AnimeDtoCopyWithImpl<$Res, _$_AnimeDto> + implements _$$_AnimeDtoCopyWith<$Res> { + __$$_AnimeDtoCopyWithImpl( + _$_AnimeDto _value, $Res Function(_$_AnimeDto) _then) : super(_value, _then); @pragma('vm:prefer-inline') @@ -369,7 +367,7 @@ class __$$_DetailAnimeDtoCopyWithImpl<$Res> Object? staff = freezed, Object? externalLinks = null, }) { - return _then(_$_DetailAnimeDto( + return _then(_$_AnimeDto( id: null == id ? _value.id : id // ignore: cast_nullable_to_non_nullable @@ -460,8 +458,8 @@ class __$$_DetailAnimeDtoCopyWithImpl<$Res> /// @nodoc @JsonSerializable() -class _$_DetailAnimeDto implements _DetailAnimeDto { - _$_DetailAnimeDto( +class _$_AnimeDto implements _AnimeDto { + _$_AnimeDto( {@JsonKey(name: 'id') this.id = -1, @JsonKey(name: 'title') this.title, @JsonKey(name: 'coverImage') @@ -490,8 +488,8 @@ class _$_DetailAnimeDto implements _DetailAnimeDto { _rankings = rankings, _externalLinks = externalLinks; - factory _$_DetailAnimeDto.fromJson(Map json) => - _$$_DetailAnimeDtoFromJson(json); + factory _$_AnimeDto.fromJson(Map json) => + _$$_AnimeDtoFromJson(json); @override @JsonKey(name: 'id') @@ -582,14 +580,14 @@ class _$_DetailAnimeDto implements _DetailAnimeDto { @override String toString() { - return 'DetailAnimeDto(id: $id, title: $title, coverImage: $coverImage, description: $description, status: $status, source: $source, episodes: $episodes, seasonYear: $seasonYear, season: $season, hashtag: $hashtag, bannerImage: $bannerImage, averageScore: $averageScore, trending: $trending, favourites: $favourites, genres: $genres, trailer: $trailer, nextAiringEpisode: $nextAiringEpisode, rankings: $rankings, characters: $characters, staff: $staff, externalLinks: $externalLinks)'; + return 'AnimeDto(id: $id, title: $title, coverImage: $coverImage, description: $description, status: $status, source: $source, episodes: $episodes, seasonYear: $seasonYear, season: $season, hashtag: $hashtag, bannerImage: $bannerImage, averageScore: $averageScore, trending: $trending, favourites: $favourites, genres: $genres, trailer: $trailer, nextAiringEpisode: $nextAiringEpisode, rankings: $rankings, characters: $characters, staff: $staff, externalLinks: $externalLinks)'; } @override bool operator ==(dynamic other) { return identical(this, other) || (other.runtimeType == runtimeType && - other is _$_DetailAnimeDto && + other is _$_AnimeDto && (identical(other.id, id) || other.id == id) && (identical(other.title, title) || other.title == title) && const DeepCollectionEquality() @@ -654,19 +652,19 @@ class _$_DetailAnimeDto implements _DetailAnimeDto { @JsonKey(ignore: true) @override @pragma('vm:prefer-inline') - _$$_DetailAnimeDtoCopyWith<_$_DetailAnimeDto> get copyWith => - __$$_DetailAnimeDtoCopyWithImpl<_$_DetailAnimeDto>(this, _$identity); + _$$_AnimeDtoCopyWith<_$_AnimeDto> get copyWith => + __$$_AnimeDtoCopyWithImpl<_$_AnimeDto>(this, _$identity); @override Map toJson() { - return _$$_DetailAnimeDtoToJson( + return _$$_AnimeDtoToJson( this, ); } } -abstract class _DetailAnimeDto implements DetailAnimeDto { - factory _DetailAnimeDto( +abstract class _AnimeDto implements AnimeDto { + factory _AnimeDto( {@JsonKey(name: 'id') final int id, @JsonKey(name: 'title') final AnimeTitle? title, @JsonKey(name: 'coverImage') final Map coverImage, @@ -689,10 +687,9 @@ abstract class _DetailAnimeDto implements DetailAnimeDto { @JsonKey(name: 'characters') final CharacterConnection? characters, @JsonKey(name: 'staff') final StaffConnection? staff, @JsonKey(name: 'externalLinks') - final List externalLinks}) = _$_DetailAnimeDto; + final List externalLinks}) = _$_AnimeDto; - factory _DetailAnimeDto.fromJson(Map json) = - _$_DetailAnimeDto.fromJson; + factory _AnimeDto.fromJson(Map json) = _$_AnimeDto.fromJson; @override @JsonKey(name: 'id') @@ -759,6 +756,6 @@ abstract class _DetailAnimeDto implements DetailAnimeDto { List get externalLinks; @override @JsonKey(ignore: true) - _$$_DetailAnimeDtoCopyWith<_$_DetailAnimeDto> get copyWith => + _$$_AnimeDtoCopyWith<_$_AnimeDto> get copyWith => throw _privateConstructorUsedError; } diff --git a/lib/core/network/model/detail_anime_dto.g.dart b/lib/core/network/model/anime_dto.g.dart similarity index 94% rename from lib/core/network/model/detail_anime_dto.g.dart rename to lib/core/network/model/anime_dto.g.dart index 29371548..0177b90d 100644 --- a/lib/core/network/model/detail_anime_dto.g.dart +++ b/lib/core/network/model/anime_dto.g.dart @@ -1,13 +1,12 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of 'detail_anime_dto.dart'; +part of 'anime_dto.dart'; // ************************************************************************** // JsonSerializableGenerator // ************************************************************************** -_$_DetailAnimeDto _$$_DetailAnimeDtoFromJson(Map json) => - _$_DetailAnimeDto( +_$_AnimeDto _$$_AnimeDtoFromJson(Map json) => _$_AnimeDto( id: json['id'] as int? ?? -1, title: json['title'] == null ? null @@ -55,7 +54,7 @@ _$_DetailAnimeDto _$$_DetailAnimeDtoFromJson(Map json) => const [], ); -Map _$$_DetailAnimeDtoToJson(_$_DetailAnimeDto instance) => +Map _$$_AnimeDtoToJson(_$_AnimeDto instance) => { 'id': instance.id, 'title': instance.title, diff --git a/lib/core/network/model/media_list_dto.dart b/lib/core/network/model/media_list_dto.dart index a2bffc0d..88b5e5b2 100644 --- a/lib/core/network/model/media_list_dto.dart +++ b/lib/core/network/model/media_list_dto.dart @@ -1,6 +1,6 @@ import 'package:anime_tracker/core/data/ani_list_repository.dart'; -import 'package:anime_tracker/core/network/model/detail_anime_dto.dart'; +import 'package:anime_tracker/core/network/model/anime_dto.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; part 'media_list_dto.freezed.dart'; @@ -15,7 +15,7 @@ class MediaListDto with _$MediaListDto { @JsonKey(name: 'status') AnimeListStatus? status, @Default(-1) @JsonKey(name: 'progress') int progress, @Default(-1) @JsonKey(name: 'updatedAt') int updatedAt, - @JsonKey(name: 'media') DetailAnimeDto? media, + @JsonKey(name: 'media') AnimeDto? media, }) = _MediaListDto; factory MediaListDto.fromJson(Map json) => diff --git a/lib/core/network/model/media_list_dto.freezed.dart b/lib/core/network/model/media_list_dto.freezed.dart index 12308af1..6f34decf 100644 --- a/lib/core/network/model/media_list_dto.freezed.dart +++ b/lib/core/network/model/media_list_dto.freezed.dart @@ -33,7 +33,7 @@ mixin _$MediaListDto { @JsonKey(name: 'updatedAt') int get updatedAt => throw _privateConstructorUsedError; @JsonKey(name: 'media') - DetailAnimeDto? get media => throw _privateConstructorUsedError; + AnimeDto? get media => throw _privateConstructorUsedError; Map toJson() => throw _privateConstructorUsedError; @JsonKey(ignore: true) @@ -54,9 +54,9 @@ abstract class $MediaListDtoCopyWith<$Res> { @JsonKey(name: 'status') AnimeListStatus? status, @JsonKey(name: 'progress') int progress, @JsonKey(name: 'updatedAt') int updatedAt, - @JsonKey(name: 'media') DetailAnimeDto? media}); + @JsonKey(name: 'media') AnimeDto? media}); - $DetailAnimeDtoCopyWith<$Res>? get media; + $AnimeDtoCopyWith<$Res>? get media; } /// @nodoc @@ -108,18 +108,18 @@ class _$MediaListDtoCopyWithImpl<$Res, $Val extends MediaListDto> media: freezed == media ? _value.media : media // ignore: cast_nullable_to_non_nullable - as DetailAnimeDto?, + as AnimeDto?, ) as $Val); } @override @pragma('vm:prefer-inline') - $DetailAnimeDtoCopyWith<$Res>? get media { + $AnimeDtoCopyWith<$Res>? get media { if (_value.media == null) { return null; } - return $DetailAnimeDtoCopyWith<$Res>(_value.media!, (value) { + return $AnimeDtoCopyWith<$Res>(_value.media!, (value) { return _then(_value.copyWith(media: value) as $Val); }); } @@ -140,10 +140,10 @@ abstract class _$$_MediaListDtoCopyWith<$Res> @JsonKey(name: 'status') AnimeListStatus? status, @JsonKey(name: 'progress') int progress, @JsonKey(name: 'updatedAt') int updatedAt, - @JsonKey(name: 'media') DetailAnimeDto? media}); + @JsonKey(name: 'media') AnimeDto? media}); @override - $DetailAnimeDtoCopyWith<$Res>? get media; + $AnimeDtoCopyWith<$Res>? get media; } /// @nodoc @@ -193,7 +193,7 @@ class __$$_MediaListDtoCopyWithImpl<$Res> media: freezed == media ? _value.media : media // ignore: cast_nullable_to_non_nullable - as DetailAnimeDto?, + as AnimeDto?, )); } } @@ -233,7 +233,7 @@ class _$_MediaListDto implements _MediaListDto { final int updatedAt; @override @JsonKey(name: 'media') - final DetailAnimeDto? media; + final AnimeDto? media; @override String toString() { @@ -283,7 +283,7 @@ abstract class _MediaListDto implements MediaListDto { @JsonKey(name: 'status') final AnimeListStatus? status, @JsonKey(name: 'progress') final int progress, @JsonKey(name: 'updatedAt') final int updatedAt, - @JsonKey(name: 'media') final DetailAnimeDto? media}) = _$_MediaListDto; + @JsonKey(name: 'media') final AnimeDto? media}) = _$_MediaListDto; factory _MediaListDto.fromJson(Map json) = _$_MediaListDto.fromJson; @@ -308,7 +308,7 @@ abstract class _MediaListDto implements MediaListDto { int get updatedAt; @override @JsonKey(name: 'media') - DetailAnimeDto? get media; + AnimeDto? get media; @override @JsonKey(ignore: true) _$$_MediaListDtoCopyWith<_$_MediaListDto> get copyWith => diff --git a/lib/core/network/model/media_list_dto.g.dart b/lib/core/network/model/media_list_dto.g.dart index 7a855414..776c1cee 100644 --- a/lib/core/network/model/media_list_dto.g.dart +++ b/lib/core/network/model/media_list_dto.g.dart @@ -16,7 +16,7 @@ _$_MediaListDto _$$_MediaListDtoFromJson(Map json) => updatedAt: json['updatedAt'] as int? ?? -1, media: json['media'] == null ? null - : DetailAnimeDto.fromJson(json['media'] as Map), + : AnimeDto.fromJson(json['media'] as Map), ); Map _$$_MediaListDtoToJson(_$_MediaListDto instance) => diff --git a/lib/core/network/model/short_anime_dto.dart b/lib/core/network/model/short_anime_dto.dart deleted file mode 100644 index 459f73d8..00000000 --- a/lib/core/network/model/short_anime_dto.dart +++ /dev/null @@ -1,19 +0,0 @@ -import 'package:freezed_annotation/freezed_annotation.dart'; - -import 'package:anime_tracker/core/data/model/anime_title_modle.dart'; - -part 'short_anime_dto.freezed.dart'; - -part 'short_anime_dto.g.dart'; - -@freezed -class ShortcutAnimeDto with _$ShortcutAnimeDto { - factory ShortcutAnimeDto({ - @Default(-1) @JsonKey(name: 'id') int id, - @JsonKey(name: 'title') AnimeTitle? title, - @Default({}) @JsonKey(name: 'coverImage') Map coverImage, - }) = _ShortcutAnimeDto; - - factory ShortcutAnimeDto.fromJson(Map json) => - _$$_ShortcutAnimeDtoFromJson(json); -} diff --git a/lib/core/network/model/short_anime_dto.freezed.dart b/lib/core/network/model/short_anime_dto.freezed.dart deleted file mode 100644 index c8c9504f..00000000 --- a/lib/core/network/model/short_anime_dto.freezed.dart +++ /dev/null @@ -1,231 +0,0 @@ -// coverage:ignore-file -// GENERATED CODE - DO NOT MODIFY BY HAND -// 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 'short_anime_dto.dart'; - -// ************************************************************************** -// FreezedGenerator -// ************************************************************************** - -T _$identity(T value) => value; - -final _privateConstructorUsedError = UnsupportedError( - 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); - -ShortcutAnimeDto _$ShortcutAnimeDtoFromJson(Map json) { - return _ShortcutAnimeDto.fromJson(json); -} - -/// @nodoc -mixin _$ShortcutAnimeDto { - @JsonKey(name: 'id') - int get id => throw _privateConstructorUsedError; - @JsonKey(name: 'title') - AnimeTitle? get title => throw _privateConstructorUsedError; - @JsonKey(name: 'coverImage') - Map get coverImage => throw _privateConstructorUsedError; - - Map toJson() => throw _privateConstructorUsedError; - @JsonKey(ignore: true) - $ShortcutAnimeDtoCopyWith get copyWith => - throw _privateConstructorUsedError; -} - -/// @nodoc -abstract class $ShortcutAnimeDtoCopyWith<$Res> { - factory $ShortcutAnimeDtoCopyWith( - ShortcutAnimeDto value, $Res Function(ShortcutAnimeDto) then) = - _$ShortcutAnimeDtoCopyWithImpl<$Res, ShortcutAnimeDto>; - @useResult - $Res call( - {@JsonKey(name: 'id') int id, - @JsonKey(name: 'title') AnimeTitle? title, - @JsonKey(name: 'coverImage') Map coverImage}); - - $AnimeTitleCopyWith<$Res>? get title; -} - -/// @nodoc -class _$ShortcutAnimeDtoCopyWithImpl<$Res, $Val extends ShortcutAnimeDto> - implements $ShortcutAnimeDtoCopyWith<$Res> { - _$ShortcutAnimeDtoCopyWithImpl(this._value, this._then); - - // ignore: unused_field - final $Val _value; - // ignore: unused_field - final $Res Function($Val) _then; - - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? id = null, - Object? title = freezed, - Object? coverImage = null, - }) { - return _then(_value.copyWith( - id: null == id - ? _value.id - : id // ignore: cast_nullable_to_non_nullable - as int, - title: freezed == title - ? _value.title - : title // ignore: cast_nullable_to_non_nullable - as AnimeTitle?, - coverImage: null == coverImage - ? _value.coverImage - : coverImage // ignore: cast_nullable_to_non_nullable - as Map, - ) as $Val); - } - - @override - @pragma('vm:prefer-inline') - $AnimeTitleCopyWith<$Res>? get title { - if (_value.title == null) { - return null; - } - - return $AnimeTitleCopyWith<$Res>(_value.title!, (value) { - return _then(_value.copyWith(title: value) as $Val); - }); - } -} - -/// @nodoc -abstract class _$$_ShortcutAnimeDtoCopyWith<$Res> - implements $ShortcutAnimeDtoCopyWith<$Res> { - factory _$$_ShortcutAnimeDtoCopyWith( - _$_ShortcutAnimeDto value, $Res Function(_$_ShortcutAnimeDto) then) = - __$$_ShortcutAnimeDtoCopyWithImpl<$Res>; - @override - @useResult - $Res call( - {@JsonKey(name: 'id') int id, - @JsonKey(name: 'title') AnimeTitle? title, - @JsonKey(name: 'coverImage') Map coverImage}); - - @override - $AnimeTitleCopyWith<$Res>? get title; -} - -/// @nodoc -class __$$_ShortcutAnimeDtoCopyWithImpl<$Res> - extends _$ShortcutAnimeDtoCopyWithImpl<$Res, _$_ShortcutAnimeDto> - implements _$$_ShortcutAnimeDtoCopyWith<$Res> { - __$$_ShortcutAnimeDtoCopyWithImpl( - _$_ShortcutAnimeDto _value, $Res Function(_$_ShortcutAnimeDto) _then) - : super(_value, _then); - - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? id = null, - Object? title = freezed, - Object? coverImage = null, - }) { - return _then(_$_ShortcutAnimeDto( - id: null == id - ? _value.id - : id // ignore: cast_nullable_to_non_nullable - as int, - title: freezed == title - ? _value.title - : title // ignore: cast_nullable_to_non_nullable - as AnimeTitle?, - coverImage: null == coverImage - ? _value._coverImage - : coverImage // ignore: cast_nullable_to_non_nullable - as Map, - )); - } -} - -/// @nodoc -@JsonSerializable() -class _$_ShortcutAnimeDto implements _ShortcutAnimeDto { - _$_ShortcutAnimeDto( - {@JsonKey(name: 'id') this.id = -1, - @JsonKey(name: 'title') this.title, - @JsonKey(name: 'coverImage') - final Map coverImage = const {}}) - : _coverImage = coverImage; - - factory _$_ShortcutAnimeDto.fromJson(Map json) => - _$$_ShortcutAnimeDtoFromJson(json); - - @override - @JsonKey(name: 'id') - final int id; - @override - @JsonKey(name: 'title') - final AnimeTitle? title; - final Map _coverImage; - @override - @JsonKey(name: 'coverImage') - Map get coverImage { - if (_coverImage is EqualUnmodifiableMapView) return _coverImage; - // ignore: implicit_dynamic_type - return EqualUnmodifiableMapView(_coverImage); - } - - @override - String toString() { - return 'ShortcutAnimeDto(id: $id, title: $title, coverImage: $coverImage)'; - } - - @override - bool operator ==(dynamic other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is _$_ShortcutAnimeDto && - (identical(other.id, id) || other.id == id) && - (identical(other.title, title) || other.title == title) && - const DeepCollectionEquality() - .equals(other._coverImage, _coverImage)); - } - - @JsonKey(ignore: true) - @override - int get hashCode => Object.hash( - runtimeType, id, title, const DeepCollectionEquality().hash(_coverImage)); - - @JsonKey(ignore: true) - @override - @pragma('vm:prefer-inline') - _$$_ShortcutAnimeDtoCopyWith<_$_ShortcutAnimeDto> get copyWith => - __$$_ShortcutAnimeDtoCopyWithImpl<_$_ShortcutAnimeDto>(this, _$identity); - - @override - Map toJson() { - return _$$_ShortcutAnimeDtoToJson( - this, - ); - } -} - -abstract class _ShortcutAnimeDto implements ShortcutAnimeDto { - factory _ShortcutAnimeDto( - {@JsonKey(name: 'id') final int id, - @JsonKey(name: 'title') final AnimeTitle? title, - @JsonKey(name: 'coverImage') final Map coverImage}) = - _$_ShortcutAnimeDto; - - factory _ShortcutAnimeDto.fromJson(Map json) = - _$_ShortcutAnimeDto.fromJson; - - @override - @JsonKey(name: 'id') - int get id; - @override - @JsonKey(name: 'title') - AnimeTitle? get title; - @override - @JsonKey(name: 'coverImage') - Map get coverImage; - @override - @JsonKey(ignore: true) - _$$_ShortcutAnimeDtoCopyWith<_$_ShortcutAnimeDto> get copyWith => - throw _privateConstructorUsedError; -} diff --git a/lib/core/network/model/short_anime_dto.g.dart b/lib/core/network/model/short_anime_dto.g.dart deleted file mode 100644 index 6c882d89..00000000 --- a/lib/core/network/model/short_anime_dto.g.dart +++ /dev/null @@ -1,26 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'short_anime_dto.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -_$_ShortcutAnimeDto _$$_ShortcutAnimeDtoFromJson(Map json) => - _$_ShortcutAnimeDto( - id: json['id'] as int? ?? -1, - title: json['title'] == null - ? null - : AnimeTitle.fromJson(json['title'] as Map), - coverImage: (json['coverImage'] as Map?)?.map( - (k, e) => MapEntry(k, e as String?), - ) ?? - const {}, - ); - -Map _$$_ShortcutAnimeDtoToJson(_$_ShortcutAnimeDto instance) => - { - 'id': instance.id, - 'title': instance.title, - 'coverImage': instance.coverImage, - }; diff --git a/test/core/network/model/detail_network_anime_model_test.dart b/test/core/network/model/detail_network_anime_model_test.dart index 7b15a0f8..2d00f612 100644 --- a/test/core/network/model/detail_network_anime_model_test.dart +++ b/test/core/network/model/detail_network_anime_model_test.dart @@ -1,4 +1,4 @@ -import 'package:anime_tracker/core/network/model/detail_anime_dto.dart'; +import 'package:anime_tracker/core/network/model/anime_dto.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { @@ -173,7 +173,7 @@ void main() { } }; test('detail_anime', () async { - DetailAnimeDto.fromJson(dummyData); + AnimeDto.fromJson(dummyData); }); }); } diff --git a/test/core/network/model/short_network_anime_model_test.dart b/test/core/network/model/short_network_anime_model_test.dart index fd1ef356..b013e472 100644 --- a/test/core/network/model/short_network_anime_model_test.dart +++ b/test/core/network/model/short_network_anime_model_test.dart @@ -1,5 +1,5 @@ import 'package:anime_tracker/core/data/model/anime_title_modle.dart'; -import 'package:anime_tracker/core/network/model/short_anime_dto.dart'; +import 'package:anime_tracker/core/network/model/anime_dto.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { @@ -22,9 +22,9 @@ void main() { } }; test('get_topics', () async { - final res = ShortcutAnimeDto.fromJson(dummyData); + final res = AnimeDto.fromJson(dummyData); expect(res, equals( - ShortcutAnimeDto( + AnimeDto( id: 124, title: AnimeTitle( romaji: "Fushigi Yuugi: Eikoden",