diff --git a/MediaBrowser.Api/ApiService.cs b/MediaBrowser.Api/ApiService.cs index 46303ddc4..06929de73 100644 --- a/MediaBrowser.Api/ApiService.cs +++ b/MediaBrowser.Api/ApiService.cs @@ -172,7 +172,7 @@ namespace MediaBrowser.Api dto.Type = item.GetType().Name; dto.UserRating = item.UserRating; - dto.UserData = GetDTOUserItemData(item.GetUserData(user)); + dto.UserData = GetDTOUserItemData(item.GetUserData(user, false)); Folder folder = item as Folder; diff --git a/MediaBrowser.Api/HttpHandlers/FavoriteStatusHandler.cs b/MediaBrowser.Api/HttpHandlers/FavoriteStatusHandler.cs index 851120230..1c640e89a 100644 --- a/MediaBrowser.Api/HttpHandlers/FavoriteStatusHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/FavoriteStatusHandler.cs @@ -11,7 +11,7 @@ namespace MediaBrowser.Api.HttpHandlers /// Provides a handler to set user favorite status for an item /// [Export(typeof(BaseHandler))] - public class FavoriteStatus : BaseSerializationHandler + public class FavoriteStatusHandler : BaseSerializationHandler { public override bool HandlesRequest(HttpListenerRequest request) { @@ -27,13 +27,7 @@ namespace MediaBrowser.Api.HttpHandlers User user = ApiService.GetUserById(QueryString["userid"], true); // Get the user data for this item - UserItemData data = item.GetUserData(user); - - if (data == null) - { - data = new UserItemData(); - item.AddUserData(user, data); - } + UserItemData data = item.GetUserData(user, true); // Set favorite status data.IsFavorite = QueryString["isfavorite"] == "1"; diff --git a/MediaBrowser.Api/HttpHandlers/PlayedStatusHandler.cs b/MediaBrowser.Api/HttpHandlers/PlayedStatusHandler.cs new file mode 100644 index 000000000..ae32b23da --- /dev/null +++ b/MediaBrowser.Api/HttpHandlers/PlayedStatusHandler.cs @@ -0,0 +1,38 @@ +using MediaBrowser.Common.Net.Handlers; +using MediaBrowser.Model.DTO; +using MediaBrowser.Model.Entities; +using System.ComponentModel.Composition; +using System.Net; +using System.Threading.Tasks; + +namespace MediaBrowser.Api.HttpHandlers +{ + /// + /// Provides a handler to set played status for an item + /// + [Export(typeof(BaseHandler))] + public class PlayedStatusHandler : BaseSerializationHandler + { + public override bool HandlesRequest(HttpListenerRequest request) + { + return ApiService.IsApiUrlMatch("PlayedStatus", request); + } + + protected override Task GetObjectToSerialize() + { + // Get the item + BaseItem item = ApiService.GetItemById(QueryString["id"]); + + // Get the user + User user = ApiService.GetUserById(QueryString["userid"], true); + + bool wasPlayed = QueryString["played"] == "1"; + + item.SetPlayedStatus(user, wasPlayed); + + UserItemData data = item.GetUserData(user, true); + + return Task.FromResult(ApiService.GetDTOUserItemData(data)); + } + } +} \ No newline at end of file diff --git a/MediaBrowser.Api/HttpHandlers/UserItemRatingHandler.cs b/MediaBrowser.Api/HttpHandlers/UserItemRatingHandler.cs index a83bb07f7..216bcac7f 100644 --- a/MediaBrowser.Api/HttpHandlers/UserItemRatingHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/UserItemRatingHandler.cs @@ -27,13 +27,7 @@ namespace MediaBrowser.Api.HttpHandlers User user = ApiService.GetUserById(QueryString["userid"], true); // Get the user data for this item - UserItemData data = item.GetUserData(user); - - if (data == null) - { - data = new UserItemData(); - item.AddUserData(user, data); - } + UserItemData data = item.GetUserData(user, true); // If clearing the rating, set it to null if (QueryString["clear"] == "1") diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index 9c9e32359..858717e6e 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -62,6 +62,7 @@ + diff --git a/MediaBrowser.ApiInteraction.Portable/ApiClient.cs b/MediaBrowser.ApiInteraction.Portable/ApiClient.cs index a49c0f7cf..b41572cd3 100644 --- a/MediaBrowser.ApiInteraction.Portable/ApiClient.cs +++ b/MediaBrowser.ApiInteraction.Portable/ApiClient.cs @@ -410,6 +410,19 @@ namespace MediaBrowser.ApiInteraction.Portable GetDataAsync(url, callback); } + /// + /// Updates played status for an item + /// + public void UpdatePlayedStatusAsync(Guid itemId, Guid userId, bool wasPlayed, Action callback) + { + string url = ApiUrl + "/PlayedStatus?id=" + itemId; + + url += "&userid=" + userId; + url += "&played=" + (wasPlayed ? "1" : "0"); + + GetDataAsync(url, callback); + } + /// /// Clears a user's rating for an item /// diff --git a/MediaBrowser.ApiInteraction/BaseHttpApiClient.cs b/MediaBrowser.ApiInteraction/BaseHttpApiClient.cs index ca29f8ff4..0b87ef4cd 100644 --- a/MediaBrowser.ApiInteraction/BaseHttpApiClient.cs +++ b/MediaBrowser.ApiInteraction/BaseHttpApiClient.cs @@ -464,6 +464,22 @@ namespace MediaBrowser.ApiInteraction } } + /// + /// Updates played status for an item + /// + public async Task UpdatePlayedStatusAsync(Guid itemId, Guid userId, bool wasPlayed) + { + string url = ApiUrl + "/PlayedStatus?id=" + itemId; + + url += "&userid=" + userId; + url += "&played=" + (wasPlayed ? "1" : "0"); + + using (Stream stream = await GetSerializedStreamAsync(url).ConfigureAwait(false)) + { + return DeserializeFromStream(stream); + } + } + /// /// Updates a user's favorite status for an item and returns the updated UserItemData object. /// diff --git a/MediaBrowser.Model/Entities/BaseItem.cs b/MediaBrowser.Model/Entities/BaseItem.cs index 775120742..51cb34a53 100644 --- a/MediaBrowser.Model/Entities/BaseItem.cs +++ b/MediaBrowser.Model/Entities/BaseItem.cs @@ -72,17 +72,24 @@ namespace MediaBrowser.Model.Entities public Dictionary UserData { get; set; } - public UserItemData GetUserData(User user) + public UserItemData GetUserData(User user, bool createIfNull) { if (UserData == null || !UserData.ContainsKey(user.Id)) { - return null; + if (createIfNull) + { + AddUserData(user, new UserItemData()); + } + else + { + return null; + } } return UserData[user.Id]; } - public void AddUserData(User user, UserItemData data) + private void AddUserData(User user, UserItemData data) { if (UserData == null) { @@ -143,5 +150,23 @@ namespace MediaBrowser.Model.Entities People[person.Name] = person; } + + /// + /// Marks the item as either played or unplayed + /// + public virtual void SetPlayedStatus(User user, bool wasPlayed) + { + UserItemData data = GetUserData(user, true); + + if (wasPlayed) + { + data.PlayCount = Math.Max(data.PlayCount, 1); + } + else + { + data.PlayCount = 0; + data.PlaybackPositionTicks = 0; + } + } } } diff --git a/MediaBrowser.Model/Entities/Folder.cs b/MediaBrowser.Model/Entities/Folder.cs index ec37107c3..ef0507138 100644 --- a/MediaBrowser.Model/Entities/Folder.cs +++ b/MediaBrowser.Model/Entities/Folder.cs @@ -103,7 +103,7 @@ namespace MediaBrowser.Model.Entities { return GetParentalAllowedRecursiveChildren(user).Where(c => { - UserItemData data = c.GetUserData(user); + UserItemData data = c.GetUserData(user, false); if (data != null) { @@ -171,21 +171,30 @@ namespace MediaBrowser.Model.Entities return GetInProgressItems(GetParentalAllowedRecursiveChildren(user), user); } + /// + /// Takes a list of items and returns the ones that are recently added + /// private static IEnumerable GetRecentlyAddedItems(IEnumerable itemSet, User user) { return itemSet.Where(i => !(i.IsFolder) && i.IsRecentlyAdded(user)); } + /// + /// Takes a list of items and returns the ones that are recently added and unplayed + /// private static IEnumerable GetRecentlyAddedUnplayedItems(IEnumerable itemSet, User user) { return GetRecentlyAddedItems(itemSet, user).Where(i => { - var userdata = i.GetUserData(user); + var userdata = i.GetUserData(user, false); return userdata == null || userdata.PlayCount == 0; }); } + /// + /// Takes a list of items and returns the ones that are in progress + /// private static IEnumerable GetInProgressItems(IEnumerable itemSet, User user) { return itemSet.Where(i => @@ -195,12 +204,15 @@ namespace MediaBrowser.Model.Entities return false; } - var userdata = i.GetUserData(user); + var userdata = i.GetUserData(user, false); return userdata != null && userdata.PlaybackPositionTicks > 0; }); } + /// + /// Gets the total played percentage for a set of items + /// private static decimal GetPlayedPercentage(IEnumerable itemSet, User user) { itemSet = itemSet.Where(i => !(i.IsFolder)); @@ -214,7 +226,7 @@ namespace MediaBrowser.Model.Entities foreach (BaseItem item in itemSet) { - UserItemData data = item.GetUserData(user); + UserItemData data = item.GetUserData(user, false); if (data == null) { @@ -236,6 +248,20 @@ namespace MediaBrowser.Model.Entities return totalPercent / itemSet.Count(); } + /// + /// Marks the item as either played or unplayed + /// + public override void SetPlayedStatus(User user, bool wasPlayed) + { + base.SetPlayedStatus(user, wasPlayed); + + // Now sweep through recursively and update status + foreach (BaseItem item in GetParentalAllowedChildren(user)) + { + item.SetPlayedStatus(user, wasPlayed); + } + } + /// /// Finds an item by ID, recursively ///