feature: Re-implemented syncing

This commit is contained in:
PartyDonut 2025-07-27 10:54:29 +02:00
parent c5c7f71b84
commit 86ff355e21
51 changed files with 3067 additions and 1147 deletions

View file

@ -45,6 +45,7 @@ class EpisodeModel extends ItemStreamModel with EpisodeModelMappable {
final String? seriesName;
final int season;
final int episode;
final int? episodeEnd;
final List<Chapter> chapters;
final ItemLocation? location;
final DateTime? dateAired;
@ -52,6 +53,7 @@ class EpisodeModel extends ItemStreamModel with EpisodeModelMappable {
required this.seriesName,
required this.season,
required this.episode,
required this.episodeEnd,
this.chapters = const [],
this.location,
this.dateAired,
@ -134,12 +136,26 @@ class EpisodeModel extends ItemStreamModel with EpisodeModelMappable {
String seasonAnnotation(BuildContext context) => context.localized.season(1)[0];
String episodeAnnotation(BuildContext context) => context.localized.episode(1)[0];
int get episodeCount {
if (episodeEnd != null && episodeEnd! > episode) {
return episodeEnd! - episode + 1;
}
return 1;
}
String get episodeRange {
if (episodeEnd != null && episodeEnd! > episode) {
return "$episode-${episodeEnd!}";
}
return episode.toString();
}
String seasonEpisodeLabel(BuildContext context) {
return "${seasonAnnotation(context)}$season - ${episodeAnnotation(context)}$episode";
return "${seasonAnnotation(context)}$season - ${episodeAnnotation(context)}$episodeRange";
}
String seasonEpisodeLabelFull(BuildContext context) {
return "${context.localized.season(1)} $season - ${context.localized.episode(1)} $episode";
return "${context.localized.season(1)} $season - ${context.localized.episode(episodeCount)} $episodeRange";
}
String episodeLabel(BuildContext context) {
@ -147,7 +163,7 @@ class EpisodeModel extends ItemStreamModel with EpisodeModelMappable {
}
String get fullName {
return "$episode. $subText";
return "$episodeRange. $subText";
}
@override
@ -169,6 +185,7 @@ class EpisodeModel extends ItemStreamModel with EpisodeModelMappable {
primaryRatio: item.primaryImageAspectRatio,
season: item.parentIndexNumber ?? 0,
episode: item.indexNumber ?? 0,
episodeEnd: item.indexNumberEnd,
location: ItemLocation.fromDto(item.locationType),
parentImages: ImagesData.fromBaseItemParent(item, ref),
canDelete: item.canDelete,

View file

@ -31,6 +31,9 @@ class EpisodeModelMapper extends SubClassMapperBase<EpisodeModel> {
static int _$episode(EpisodeModel v) => v.episode;
static const Field<EpisodeModel, int> _f$episode =
Field('episode', _$episode);
static int? _$episodeEnd(EpisodeModel v) => v.episodeEnd;
static const Field<EpisodeModel, int> _f$episodeEnd =
Field('episodeEnd', _$episodeEnd);
static List<Chapter> _$chapters(EpisodeModel v) => v.chapters;
static const Field<EpisodeModel, List<Chapter>> _f$chapters =
Field('chapters', _$chapters, opt: true, def: const []);
@ -86,6 +89,7 @@ class EpisodeModelMapper extends SubClassMapperBase<EpisodeModel> {
#seriesName: _f$seriesName,
#season: _f$season,
#episode: _f$episode,
#episodeEnd: _f$episodeEnd,
#chapters: _f$chapters,
#location: _f$location,
#dateAired: _f$dateAired,
@ -120,6 +124,7 @@ class EpisodeModelMapper extends SubClassMapperBase<EpisodeModel> {
seriesName: data.dec(_f$seriesName),
season: data.dec(_f$season),
episode: data.dec(_f$episode),
episodeEnd: data.dec(_f$episodeEnd),
chapters: data.dec(_f$chapters),
location: data.dec(_f$location),
dateAired: data.dec(_f$dateAired),
@ -166,6 +171,7 @@ abstract class EpisodeModelCopyWith<$R, $In extends EpisodeModel, $Out>
{String? seriesName,
int? season,
int? episode,
int? episodeEnd,
List<Chapter>? chapters,
ItemLocation? location,
DateTime? dateAired,
@ -209,6 +215,7 @@ class _EpisodeModelCopyWithImpl<$R, $Out>
{Object? seriesName = $none,
int? season,
int? episode,
Object? episodeEnd = $none,
List<Chapter>? chapters,
Object? location = $none,
Object? dateAired = $none,
@ -230,6 +237,7 @@ class _EpisodeModelCopyWithImpl<$R, $Out>
if (seriesName != $none) #seriesName: seriesName,
if (season != null) #season: season,
if (episode != null) #episode: episode,
if (episodeEnd != $none) #episodeEnd: episodeEnd,
if (chapters != null) #chapters: chapters,
if (location != $none) #location: location,
if (dateAired != $none) #dateAired: dateAired,
@ -253,6 +261,7 @@ class _EpisodeModelCopyWithImpl<$R, $Out>
seriesName: data.get(#seriesName, or: $value.seriesName),
season: data.get(#season, or: $value.season),
episode: data.get(#episode, or: $value.episode),
episodeEnd: data.get(#episodeEnd, or: $value.episodeEnd),
chapters: data.get(#chapters, or: $value.chapters),
location: data.get(#location, or: $value.location),
dateAired: data.get(#dateAired, or: $value.dateAired),

View file

@ -50,6 +50,21 @@ class UserData with UserDataMappable {
Duration get playBackPosition => Duration(milliseconds: playbackPositionTicks ~/ 10000);
static UserData? determineLastUserData(List<UserData?> data) {
return data.where((data) => data != null).reduce((a, b) {
final aDate = a?.lastPlayed;
final bDate = b?.lastPlayed;
if (aDate != null && bDate != null) {
return aDate.isAfter(bDate) ? a : b;
} else if (aDate != null) {
return a;
} else {
return b;
}
});
}
factory UserData.fromMap(Map<String, dynamic> map) => UserDataMapper.fromMap(map);
factory UserData.fromJson(String json) => UserDataMapper.fromJson(json);
}

View file

@ -75,7 +75,7 @@ class SeasonModel extends ItemBaseModel with SeasonModelMappable {
}
@override
bool get syncAble => true;
bool get syncAble => episodes.isNotEmpty && episodes.any((element) => element.syncAble);
@override
ImagesData? get getPosters => images ?? parentImages;