fixes #762 - Marking unwatched doesn't update display

This commit is contained in:
Luke Pulverenti
2014-07-03 22:22:57 -04:00
parent 59dc591f66
commit 7fa9b14f56
55 changed files with 706 additions and 438 deletions

View File

@@ -0,0 +1,21 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Model.Branding;
using System.Collections.Generic;
namespace MediaBrowser.Server.Implementations.Branding
{
public class BrandingConfigurationFactory : IConfigurationFactory
{
public IEnumerable<ConfigurationStore> GetConfigurations()
{
return new[]
{
new ConfigurationStore
{
ConfigurationType = typeof(BrandingOptions),
Key = "branding"
}
};
}
}
}

View File

@@ -212,6 +212,12 @@ namespace MediaBrowser.Server.Implementations.Dto
{
if (item.IsFolder)
{
var userData = _userDataRepository.GetUserData(user.Id, item.GetUserDataKey());
// Skip the user data manager because we've already looped through the recursive tree and don't want to do it twice
// TODO: Improve in future
dto.UserData = GetUserItemDataDto(userData);
var folder = (Folder)item;
dto.ChildCount = GetChildCount(folder, user);
@@ -220,15 +226,15 @@ namespace MediaBrowser.Server.Implementations.Dto
{
SetSpecialCounts(folder, user, dto, fields);
}
dto.UserData.Played = dto.PlayedPercentage.HasValue && dto.PlayedPercentage.Value >= 100;
dto.UserData.PlayedPercentage = dto.PlayedPercentage;
dto.UserData.UnplayedItemCount = dto.RecursiveUnplayedItemCount;
}
var userData = _userDataRepository.GetUserData(user.Id, item.GetUserDataKey());
dto.UserData = GetUserItemDataDto(userData);
if (item.IsFolder)
else
{
dto.UserData.Played = dto.PlayedPercentage.HasValue && dto.PlayedPercentage.Value >= 100;
dto.UserData = _userDataRepository.GetUserDataDto(item, user);
}
dto.PlayAccess = item.GetPlayAccess(user);
@@ -1110,16 +1116,17 @@ namespace MediaBrowser.Server.Implementations.Dto
if (episode != null)
{
series = item.FindParent<Series>();
series = episode.Series;
dto.SeriesId = GetDtoId(series);
dto.SeriesName = series.Name;
dto.AirTime = series.AirTime;
dto.SeriesStudio = series.Studios.FirstOrDefault();
dto.SeriesThumbImageTag = GetImageCacheTag(series, ImageType.Thumb);
dto.SeriesPrimaryImageTag = GetImageCacheTag(series, ImageType.Primary);
if (series != null)
{
dto.SeriesId = GetDtoId(series);
dto.SeriesName = series.Name;
dto.AirTime = series.AirTime;
dto.SeriesStudio = series.Studios.FirstOrDefault();
dto.SeriesThumbImageTag = GetImageCacheTag(series, ImageType.Thumb);
dto.SeriesPrimaryImageTag = GetImageCacheTag(series, ImageType.Primary);
}
}
// Add SeasonInfo
@@ -1127,14 +1134,17 @@ namespace MediaBrowser.Server.Implementations.Dto
if (season != null)
{
series = item.FindParent<Series>();
series = season.Series;
dto.SeriesId = GetDtoId(series);
dto.SeriesName = series.Name;
dto.AirTime = series.AirTime;
dto.SeriesStudio = series.Studios.FirstOrDefault();
if (series != null)
{
dto.SeriesId = GetDtoId(series);
dto.SeriesName = series.Name;
dto.AirTime = series.AirTime;
dto.SeriesStudio = series.Studios.FirstOrDefault();
dto.SeriesPrimaryImageTag = GetImageCacheTag(series, ImageType.Primary);
dto.SeriesPrimaryImageTag = GetImageCacheTag(series, ImageType.Primary);
}
}
var game = item as Game;

View File

@@ -1,10 +1,11 @@
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Session;
using MoreLinq;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -17,21 +18,21 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
{
private readonly ISessionManager _sessionManager;
private readonly ILogger _logger;
private readonly IDtoService _dtoService;
private readonly IUserDataManager _userDataManager;
private readonly IUserManager _userManager;
private readonly object _syncLock = new object();
private Timer UpdateTimer { get; set; }
private const int UpdateDuration = 500;
private readonly Dictionary<Guid, List<string>> _changedKeys = new Dictionary<Guid, List<string>>();
private readonly Dictionary<Guid, List<IHasUserData>> _changedItems = new Dictionary<Guid, List<IHasUserData>>();
public UserDataChangeNotifier(IUserDataManager userDataManager, ISessionManager sessionManager, IDtoService dtoService, ILogger logger)
public UserDataChangeNotifier(IUserDataManager userDataManager, ISessionManager sessionManager, ILogger logger, IUserManager userManager)
{
_userDataManager = userDataManager;
_sessionManager = sessionManager;
_dtoService = dtoService;
_logger = logger;
_userManager = userManager;
}
public void Run()
@@ -58,15 +59,28 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
UpdateTimer.Change(UpdateDuration, Timeout.Infinite);
}
List<string> keys;
List<IHasUserData> keys;
if (!_changedKeys.TryGetValue(e.UserId, out keys))
if (!_changedItems.TryGetValue(e.UserId, out keys))
{
keys = new List<string>();
_changedKeys[e.UserId] = keys;
keys = new List<IHasUserData>();
_changedItems[e.UserId] = keys;
}
keys.Add(e.Key);
keys.Add(e.Item);
var baseItem = e.Item as BaseItem;
// Go up one level for indicators
if (baseItem != null)
{
var parent = baseItem.Parent;
if (parent != null)
{
keys.Add(parent);
}
}
}
}
@@ -75,8 +89,8 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
lock (_syncLock)
{
// Remove dupes in case some were saved multiple times
var changes = _changedKeys.ToList();
_changedKeys.Clear();
var changes = _changedItems.ToList();
_changedItems.Clear();
SendNotifications(changes, CancellationToken.None);
@@ -88,7 +102,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
}
}
private async Task SendNotifications(IEnumerable<KeyValuePair<Guid, List<string>>> changes, CancellationToken cancellationToken)
private async Task SendNotifications(IEnumerable<KeyValuePair<Guid, List<IHasUserData>>> changes, CancellationToken cancellationToken)
{
foreach (var pair in changes)
{
@@ -99,8 +113,11 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
if (userSessions.Count > 0)
{
var user = _userManager.GetUserById(userId);
var dtoList = pair.Value
.Select(i => _dtoService.GetUserItemDataDto(_userDataManager.GetUserData(userId, i)))
.DistinctBy(i => i.Id)
.Select(i => _userDataManager.GetUserDataDto(i, user))
.ToList();
var info = new UserDataChangeInfo

View File

@@ -363,19 +363,15 @@ namespace MediaBrowser.Server.Implementations.HttpServer
{
try
{
var errorResponse = new ErrorResponse
{
ResponseStatus = new ResponseStatus
{
ErrorCode = ex.GetType().GetOperationName(),
Message = ex.Message,
StackTrace = ex.StackTrace,
}
};
var operationName = context.Request.GetOperationName();
var httpReq = GetRequest(context, operationName);
var httpRes = httpReq.Response;
if (httpRes.IsClosed)
{
return;
}
var contentType = httpReq.ResponseContentType;
var serializer = HostContext.ContentTypes.GetResponseSerializer(contentType);
@@ -398,6 +394,16 @@ namespace MediaBrowser.Server.Implementations.HttpServer
httpRes.ContentType = contentType;
var errorResponse = new ErrorResponse
{
ResponseStatus = new ResponseStatus
{
ErrorCode = ex.GetType().GetOperationName(),
Message = ex.Message,
StackTrace = ex.StackTrace,
}
};
serializer(httpReq, errorResponse, httpRes);
httpRes.Close();

View File

@@ -36,6 +36,13 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
auth.TryGetValue("Version", out version);
}
var token = httpReq.Headers["X-MediaBrowser-Token"];
if (string.IsNullOrWhiteSpace(token))
{
token = httpReq.QueryString["api_key"];
}
return new AuthorizationInfo
{
Client = client,
@@ -43,7 +50,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
DeviceId = deviceId,
UserId = userId,
Version = version,
Token = httpReq.Headers["X-AUTH-TOKEN"]
Token = token
};
}

View File

@@ -2,6 +2,7 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using System;
@@ -125,5 +126,41 @@ namespace MediaBrowser.Server.Implementations.Library
{
return userId + key;
}
public UserItemDataDto GetUserDataDto(IHasUserData item, User user)
{
var userData = GetUserData(user.Id, item.GetUserDataKey());
var dto = GetUserItemDataDto(userData);
item.FillUserDataDtoValues(dto, userData, user);
return dto;
}
/// <summary>
/// Converts a UserItemData to a DTOUserItemData
/// </summary>
/// <param name="data">The data.</param>
/// <returns>DtoUserItemData.</returns>
/// <exception cref="System.ArgumentNullException"></exception>
private UserItemDataDto GetUserItemDataDto(UserItemData data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
return new UserItemDataDto
{
IsFavorite = data.IsFavorite,
Likes = data.Likes,
PlaybackPositionTicks = data.PlaybackPositionTicks,
PlayCount = data.PlayCount,
Rating = data.Rating,
Played = data.Played,
LastPlayedDate = data.LastPlayedDate,
Key = data.Key
};
}
}
}

View File

@@ -4,7 +4,6 @@ using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.Logging;
@@ -23,15 +22,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv
private readonly IUserDataManager _userDataManager;
private readonly IDtoService _dtoService;
private readonly IItemRepository _itemRepo;
public LiveTvDtoService(IDtoService dtoService, IUserDataManager userDataManager, IImageProcessor imageProcessor, ILogger logger, IItemRepository itemRepo)
public LiveTvDtoService(IDtoService dtoService, IUserDataManager userDataManager, IImageProcessor imageProcessor, ILogger logger)
{
_dtoService = dtoService;
_userDataManager = userDataManager;
_imageProcessor = imageProcessor;
_logger = logger;
_itemRepo = itemRepo;
}
public TimerInfoDto GetTimerInfoDto(TimerInfo info, ILiveTvService service, LiveTvProgram program, LiveTvChannel channel)
@@ -249,7 +246,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
if (user != null)
{
dto.UserData = _dtoService.GetUserItemDataDto(_userDataManager.GetUserData(user.Id, recording.GetUserDataKey()));
dto.UserData = _userDataManager.GetUserDataDto(recording, user);
dto.PlayAccess = recording.GetPlayAccess(user);
}
@@ -322,7 +319,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
if (user != null)
{
dto.UserData = _dtoService.GetUserItemDataDto(_userDataManager.GetUserData(user.Id, info.GetUserDataKey()));
dto.UserData = _userDataManager.GetUserDataDto(info, user);
dto.PlayAccess = info.GetPlayAccess(user);
}
@@ -401,7 +398,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
if (user != null)
{
dto.UserData = _dtoService.GetUserItemDataDto(_userDataManager.GetUserData(user.Id, item.GetUserDataKey()));
dto.UserData = _userDataManager.GetUserDataDto(item, user);
dto.PlayAccess = item.GetPlayAccess(user);
}

View File

@@ -40,7 +40,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
private readonly IUserDataManager _userDataManager;
private readonly ILibraryManager _libraryManager;
private readonly ITaskManager _taskManager;
private readonly IJsonSerializer _json;
private readonly IDtoService _dtoService;
private readonly ILocalizationManager _localization;
@@ -58,7 +57,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
private readonly SemaphoreSlim _refreshSemaphore = new SemaphoreSlim(1, 1);
public LiveTvManager(IServerConfigurationManager config, IFileSystem fileSystem, ILogger logger, IItemRepository itemRepo, IImageProcessor imageProcessor, IUserDataManager userDataManager, IDtoService dtoService, IUserManager userManager, ILibraryManager libraryManager, ITaskManager taskManager, IJsonSerializer json, ILocalizationManager localization)
public LiveTvManager(IServerConfigurationManager config, IFileSystem fileSystem, ILogger logger, IItemRepository itemRepo, IImageProcessor imageProcessor, IUserDataManager userDataManager, IDtoService dtoService, IUserManager userManager, ILibraryManager libraryManager, ITaskManager taskManager, ILocalizationManager localization)
{
_config = config;
_fileSystem = fileSystem;
@@ -67,12 +66,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv
_userManager = userManager;
_libraryManager = libraryManager;
_taskManager = taskManager;
_json = json;
_localization = localization;
_dtoService = dtoService;
_userDataManager = userDataManager;
_tvDtoService = new LiveTvDtoService(dtoService, userDataManager, imageProcessor, logger, _itemRepo);
_tvDtoService = new LiveTvDtoService(dtoService, userDataManager, imageProcessor, logger);
}
/// <summary>

View File

@@ -258,11 +258,11 @@
"LabelCachePath": "Cache path:",
"LabelCachePathHelp": "This folder contains server cache files, such as images.",
"LabelImagesByNamePath": "Images by name path:",
"LabelImagesByNamePathHelp": "This folder contains actor, artist, genre and studio images.",
"LabelImagesByNamePathHelp": "This folder contains downloaded actor, artist, genre and studio images.",
"LabelMetadataPath": "Metadata path:",
"LabelMetadataPathHelp": "This location contains downloaded artwork and metadata that is not configured to be stored in media folders.",
"LabelTranscodingTempPath": "Transcoding temporary path:",
"LabelTranscodingTempPathHelp": "This folder contains working files used by the transcoder.",
"LabelTranscodingTempPathHelp": "This folder contains working files used by the transcoder. Specify a custom path, or leave empty to use the default within the server's data folder.",
"TabBasics": "Basics",
"TabTV": "TV",
"TabGames": "Games",
@@ -284,7 +284,7 @@
"ButtonAutoScroll": "Auto-scroll",
"LabelImageSavingConvention": "Image saving convention:",
"LabelImageSavingConventionHelp": "Media Browser recognizes images from most major media applications. Choosing your downloading convention is useful if you also use other products.",
"OptionImageSavingCompatible": "Compatible - Media Browser/Plex/Xbmc",
"OptionImageSavingCompatible": "Compatible - Media Browser/Xbmc/Plex",
"OptionImageSavingStandard": "Standard - MB2",
"ButtonSignIn": "Sign In",
"TitleSignIn": "Sign In",
@@ -849,5 +849,14 @@
"LabelXbmcMetadataEnablePathSubstitutionHelp2": "See path substitution.",
"LabelGroupChannelsIntoViews": "Display the following channels directly within my views:",
"LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.",
"LabelDisplayCollectionsView": "Display a Collections view to show movie collections"
"LabelDisplayCollectionsView": "Display a Collections view to show movie collections",
"LabelXbmcMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs",
"LabelXbmcMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Xbmc skin compatibility.",
"TabServices": "Services",
"TabLogs": "Logs",
"HeaderServerLogFiles": "Server log files:",
"TabBranding": "Branding",
"HeaderBrandingHelp": "Customize the appearance of Media Browser to fit the needs of your group or organization.",
"LabelLoginDisclaimer": "Login disclaimer:",
"LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page."
}

View File

@@ -101,6 +101,7 @@
<Compile Include="..\SharedVersion.cs">
<Link>Properties\SharedVersion.cs</Link>
</Compile>
<Compile Include="Branding\BrandingConfigurationFactory.cs" />
<Compile Include="Channels\ChannelConfigurations.cs" />
<Compile Include="Channels\ChannelDownloadScheduledTask.cs" />
<Compile Include="Channels\ChannelImageProvider.cs" />

View File

@@ -4,7 +4,6 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Notifications;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Notifications;
using System;
@@ -93,7 +92,9 @@ namespace MediaBrowser.Server.Implementations.Notifications
if (options != null && !string.IsNullOrWhiteSpace(request.NotificationType))
{
return _userManager.Users.Where(i => _config.Configuration.NotificationOptions.IsEnabledToSendToUser(request.NotificationType, i.Id.ToString("N"), i.Configuration))
var config = GetConfiguration();
return _userManager.Users.Where(i => config.IsEnabledToSendToUser(request.NotificationType, i.Id.ToString("N"), i.Configuration))
.Select(i => i.Id.ToString("N"));
}

View File

@@ -1,4 +1,6 @@
using MediaBrowser.Common.Events;
using System.Security.Cryptography;
using System.Text;
using MediaBrowser.Common.Events;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
@@ -1185,6 +1187,24 @@ namespace MediaBrowser.Server.Implementations.Session
};
}
private bool IsLocal(string remoteEndpoint)
{
if (string.IsNullOrWhiteSpace(remoteEndpoint))
{
throw new ArgumentNullException("remoteEndpoint");
}
// Private address space:
// http://en.wikipedia.org/wiki/Private_network
return remoteEndpoint.IndexOf("localhost", StringComparison.OrdinalIgnoreCase) != -1 ||
remoteEndpoint.StartsWith("10.", StringComparison.OrdinalIgnoreCase) ||
remoteEndpoint.StartsWith("192.", StringComparison.OrdinalIgnoreCase) ||
remoteEndpoint.StartsWith("172.", StringComparison.OrdinalIgnoreCase) ||
remoteEndpoint.StartsWith("127.", StringComparison.OrdinalIgnoreCase) ||
remoteEndpoint.StartsWith("::", StringComparison.OrdinalIgnoreCase);
}
/// <summary>
/// Reports the capabilities.
/// </summary>
@@ -1283,15 +1303,10 @@ namespace MediaBrowser.Server.Implementations.Session
DeviceName = session.DeviceName,
Id = session.Id,
LastActivityDate = session.LastActivityDate,
NowPlayingPositionTicks = session.PlayState.PositionTicks,
IsPaused = session.PlayState.IsPaused,
IsMuted = session.PlayState.IsMuted,
NowViewingItem = session.NowViewingItem,
ApplicationVersion = session.ApplicationVersion,
CanSeek = session.PlayState.CanSeek,
QueueableMediaTypes = session.QueueableMediaTypes,
PlayableMediaTypes = session.PlayableMediaTypes,
RemoteEndPoint = session.RemoteEndPoint,
AdditionalUsers = session.AdditionalUsers,
SupportedCommands = session.SupportedCommands,
UserName = session.UserName,

View File

@@ -26,13 +26,36 @@ namespace MediaBrowser.Server.Implementations.Sorting
/// <returns>System.String.</returns>
private DateTime GetValue(BaseItem x)
{
var series = (x as Series) ?? x.FindParent<Series>();
var series = x as Series;
DateTime result;
if (series != null && DateTime.TryParse(series.AirTime, out result))
if (series == null)
{
return result;
}
var season = x as Season;
if (season != null)
{
series = season.Series;
}
else
{
var episode = x as Episode;
if (episode != null)
{
series = episode.Series;
}
}
}
if (series != null)
{
DateTime result;
if (DateTime.TryParse(series.AirTime, out result))
{
return result;
}
}
return DateTime.MinValue;
}