diff options
Diffstat (limited to 'Emby.Server.Implementations/Library/UserDataManager.cs')
| -rw-r--r-- | Emby.Server.Implementations/Library/UserDataManager.cs | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/Emby.Server.Implementations/Library/UserDataManager.cs b/Emby.Server.Implementations/Library/UserDataManager.cs index 962dd6fda8..4fda853bb1 100644 --- a/Emby.Server.Implementations/Library/UserDataManager.cs +++ b/Emby.Server.Implementations/Library/UserDataManager.cs @@ -247,6 +247,72 @@ namespace Emby.Server.Implementations.Library return result; } + /// <inheritdoc /> + public VersionResumeData? GetResumeUserData(User user, BaseItem item) + { + return GetResumeUserDataBatch([item], user).GetValueOrDefault(item.Id); + } + + /// <inheritdoc /> + public IReadOnlyDictionary<Guid, VersionResumeData> GetResumeUserDataBatch(IReadOnlyList<BaseItem> items, User user) + { + ArgumentNullException.ThrowIfNull(user); + + var result = new Dictionary<Guid, VersionResumeData>(); + List<(Guid PrimaryId, IReadOnlyList<Video> Versions)>? versionGroups = null; + List<BaseItem>? allVersions = null; + + foreach (var item in items) + { + // Only primary items aggregate over their versions; a directly queried version keeps its own data. + if (item is not Video video + || video.PrimaryVersionId.HasValue + || (video.LinkedAlternateVersions.Length == 0 && !video.HasLocalAlternateVersions)) + { + continue; + } + + var versions = video.GetAllVersions(); + if (versions.Count < 2) + { + continue; + } + + (versionGroups ??= []).Add((item.Id, versions)); + (allVersions ??= []).AddRange(versions); + } + + if (versionGroups is null) + { + return result; + } + + var userDataByVersion = GetUserDataBatch(allVersions!.DistinctBy(i => i.Id).ToList(), user); + + foreach (var (primaryId, versions) in versionGroups) + { + Video? resumeVersion = null; + UserItemData? resumeData = null; + foreach (var version in versions) + { + if (userDataByVersion.TryGetValue(version.Id, out var data) + && data.PlaybackPositionTicks > 0 + && (resumeData is null || (data.LastPlayedDate ?? DateTime.MinValue) > (resumeData.LastPlayedDate ?? DateTime.MinValue))) + { + resumeVersion = version; + resumeData = data; + } + } + + if (resumeData is not null) + { + result[primaryId] = new VersionResumeData(resumeData, resumeVersion!.RunTimeTicks); + } + } + + return result; + } + /// <summary> /// Gets the internal key. /// </summary> @@ -281,6 +347,10 @@ namespace Emby.Server.Implementations.Library var dto = GetUserItemDataDto(userData, item.Id); item.FillUserDataDtoValues(dto, userData, itemDto, user, options); + + // For an item with alternate versions, surface the most recently played version's resume point. + GetResumeUserData(user, item)?.ApplyTo(dto); + return dto; } |
