diff --git a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs index f4e9739a1..ab3e2af19 100644 --- a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs +++ b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs @@ -184,6 +184,9 @@ namespace MediaBrowser.Api.UserLibrary [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] public Guid UserId { get; set; } + [ApiMember(Name = "DatePlayed", Description = "The date the item was played (if any)", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] + public DateTime? DatePlayed { get; set; } + /// /// Gets or sets the id. /// @@ -630,7 +633,7 @@ namespace MediaBrowser.Api.UserLibrary { var user = _userManager.GetUserById(request.UserId); - var task = UpdatePlayedStatus(user, request.Id, true); + var task = UpdatePlayedStatus(user, request.Id, true, request.DatePlayed); return ToOptimizedResult(task.Result); } @@ -703,7 +706,7 @@ namespace MediaBrowser.Api.UserLibrary { var user = _userManager.GetUserById(request.UserId); - var task = UpdatePlayedStatus(user, request.Id, false); + var task = UpdatePlayedStatus(user, request.Id, false, null); return ToOptimizedResult(task.Result); } @@ -714,12 +717,20 @@ namespace MediaBrowser.Api.UserLibrary /// The user. /// The item id. /// if set to true [was played]. + /// The date played. /// Task. - private async Task UpdatePlayedStatus(User user, string itemId, bool wasPlayed) + private async Task UpdatePlayedStatus(User user, string itemId, bool wasPlayed, DateTime? datePlayed) { var item = _dtoService.GetItemByDtoId(itemId, user.Id); - await item.SetPlayedStatus(user, wasPlayed, _userDataRepository).ConfigureAwait(false); + if (wasPlayed) + { + await item.MarkPlayed(user, datePlayed, _userDataRepository).ConfigureAwait(false); + } + else + { + await item.MarkUnplayed(user, _userDataRepository).ConfigureAwait(false); + } return _dtoService.GetUserItemDataDto(_userDataRepository.GetUserData(user.Id, item.GetUserDataKey())); } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index fdd21d240..180bac8ba 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1315,14 +1315,14 @@ namespace MediaBrowser.Controller.Entities } /// - /// Marks the item as either played or unplayed + /// Marks the played. /// /// The user. - /// if set to true [was played]. + /// The date played. /// The user manager. /// Task. /// - public virtual async Task SetPlayedStatus(User user, bool wasPlayed, IUserDataRepository userManager) + public virtual async Task MarkPlayed(User user, DateTime? datePlayed, IUserDataRepository userManager) { if (user == null) { @@ -1333,20 +1333,39 @@ namespace MediaBrowser.Controller.Entities var data = userManager.GetUserData(user.Id, key); - if (wasPlayed) + data.PlayCount = Math.Max(data.PlayCount, 1); + + data.LastPlayedDate = datePlayed ?? data.LastPlayedDate; + data.Played = true; + + await userManager.SaveUserData(user.Id, key, data, CancellationToken.None).ConfigureAwait(false); + } + + /// + /// Marks the unplayed. + /// + /// The user. + /// The user manager. + /// Task. + /// + public virtual async Task MarkUnplayed(User user, IUserDataRepository userManager) + { + if (user == null) { - data.PlayCount = Math.Max(data.PlayCount, 1); - } - else - { - //I think it is okay to do this here. - // if this is only called when a user is manually forcing something to un-played - // then it probably is what we want to do... - data.PlayCount = 0; - data.PlaybackPositionTicks = 0; + throw new ArgumentNullException(); } - data.Played = wasPlayed; + var key = GetUserDataKey(); + + var data = userManager.GetUserData(user.Id, key); + + //I think it is okay to do this here. + // if this is only called when a user is manually forcing something to un-played + // then it probably is what we want to do... + data.PlayCount = 0; + data.PlaybackPositionTicks = 0; + data.LastPlayedDate = null; + data.Played = false; await userManager.SaveUserData(user.Id, key, data, CancellationToken.None).ConfigureAwait(false); } diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 30e87a8ea..a724067d5 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -1161,16 +1161,30 @@ namespace MediaBrowser.Controller.Entities } /// - /// Marks the item as either played or unplayed + /// Marks the played. /// /// The user. - /// if set to true [was played]. + /// The date played. /// The user manager. /// Task. - public override async Task SetPlayedStatus(User user, bool wasPlayed, IUserDataRepository userManager) + public override async Task MarkPlayed(User user, DateTime? datePlayed, IUserDataRepository userManager) { // Sweep through recursively and update status - var tasks = GetRecursiveChildren(user, true).Where(i => !i.IsFolder).Select(c => c.SetPlayedStatus(user, wasPlayed, userManager)); + var tasks = GetRecursiveChildren(user, true).Where(i => !i.IsFolder).Select(c => c.MarkPlayed(user, datePlayed, userManager)); + + await Task.WhenAll(tasks).ConfigureAwait(false); + } + + /// + /// Marks the unplayed. + /// + /// The user. + /// The user manager. + /// Task. + public override async Task MarkUnplayed(User user, IUserDataRepository userManager) + { + // Sweep through recursively and update status + var tasks = GetRecursiveChildren(user, true).Where(i => !i.IsFolder).Select(c => c.MarkUnplayed(user, userManager)); await Task.WhenAll(tasks).ConfigureAwait(false); } diff --git a/MediaBrowser.Model/ApiClient/IApiClient.cs b/MediaBrowser.Model/ApiClient/IApiClient.cs index 784e449a3..44a7673ed 100644 --- a/MediaBrowser.Model/ApiClient/IApiClient.cs +++ b/MediaBrowser.Model/ApiClient/IApiClient.cs @@ -453,18 +453,22 @@ namespace MediaBrowser.Model.ApiClient Task GetCountriesAsync(); /// - /// Marks an item as played or unplayed. - /// This should not be used to update playstate following playback. - /// There are separate playstate check-in methods for that. This should be used for a - /// separate option to reset playstate. + /// Marks the played async. /// /// The item id. /// The user id. - /// if set to true [was played]. - /// Task. - /// itemId - Task UpdatePlayedStatusAsync(string itemId, string userId, bool wasPlayed); + /// The date played. + /// Task{UserItemDataDto}. + Task MarkPlayedAsync(string itemId, string userId, DateTime? datePlayed); + /// + /// Marks the unplayed async. + /// + /// The item id. + /// The user id. + /// Task{UserItemDataDto}. + Task MarkUnplayedAsync(string itemId, string userId); + /// /// Updates the favorite status async. ///