From 3db6ae91f6aa68a1eaf3da3d385b069bdd7721ee Mon Sep 17 00:00:00 2001 From: crobibero Date: Fri, 4 Dec 2020 16:00:11 -0700 Subject: [PATCH] Add ItemId to all display preferences --- .../DisplayPreferencesController.cs | 10 ++--- .../Entities/CustomItemDisplayPreferences.cs | 12 +++++- Jellyfin.Data/Entities/DisplayPreferences.cs | 12 +++++- Jellyfin.Data/Jellyfin.Data.csproj | 2 +- Jellyfin.Server.Implementations/JellyfinDb.cs | 4 +- ...5_AddCustomDisplayPreferences.Designer.cs} | 12 ++++-- ...1204223655_AddCustomDisplayPreferences.cs} | 42 ++++++++++++++++++- .../Migrations/JellyfinDbModelSnapshot.cs | 10 ++++- .../Users/DisplayPreferencesManager.cs | 20 +++++---- .../Routines/MigrateDisplayPreferencesDb.cs | 16 +++++-- .../IDisplayPreferencesManager.cs | 9 ++-- 11 files changed, 117 insertions(+), 32 deletions(-) rename Jellyfin.Server.Implementations/Migrations/{20201203203707_AddCustomDisplayPreferences.Designer.cs => 20201204223655_AddCustomDisplayPreferences.Designer.cs} (97%) rename Jellyfin.Server.Implementations/Migrations/{20201203203707_AddCustomDisplayPreferences.cs => 20201204223655_AddCustomDisplayPreferences.cs} (60%) diff --git a/Jellyfin.Api/Controllers/DisplayPreferencesController.cs b/Jellyfin.Api/Controllers/DisplayPreferencesController.cs index bf3d23e444..7e67dfe948 100644 --- a/Jellyfin.Api/Controllers/DisplayPreferencesController.cs +++ b/Jellyfin.Api/Controllers/DisplayPreferencesController.cs @@ -48,14 +48,14 @@ namespace Jellyfin.Api.Controllers [FromQuery, Required] string client) { _ = Guid.TryParse(displayPreferencesId, out var itemId); - var displayPreferences = _displayPreferencesManager.GetDisplayPreferences(userId, client); + var displayPreferences = _displayPreferencesManager.GetDisplayPreferences(userId, itemId, client); var itemPreferences = _displayPreferencesManager.GetItemDisplayPreferences(displayPreferences.UserId, itemId, displayPreferences.Client); itemPreferences.ItemId = itemId; var dto = new DisplayPreferencesDto { Client = displayPreferences.Client, - Id = displayPreferences.UserId.ToString(), + Id = displayPreferences.ItemId.ToString(), ViewType = itemPreferences.ViewType.ToString(), SortBy = itemPreferences.SortBy, SortOrder = itemPreferences.SortOrder, @@ -84,7 +84,7 @@ namespace Jellyfin.Api.Controllers dto.CustomPrefs["tvhome"] = displayPreferences.TvHome; // Load all custom display preferences - var customDisplayPreferences = _displayPreferencesManager.ListCustomItemDisplayPreferences(displayPreferences.UserId, displayPreferences.Client); + var customDisplayPreferences = _displayPreferencesManager.ListCustomItemDisplayPreferences(displayPreferences.UserId, itemId, displayPreferences.Client); if (customDisplayPreferences != null) { foreach (var (key, value) in customDisplayPreferences) @@ -128,7 +128,7 @@ namespace Jellyfin.Api.Controllers }; _ = Guid.TryParse(displayPreferencesId, out var itemId); - var existingDisplayPreferences = _displayPreferencesManager.GetDisplayPreferences(userId, client); + var existingDisplayPreferences = _displayPreferencesManager.GetDisplayPreferences(userId, itemId, client); existingDisplayPreferences.IndexBy = Enum.TryParse(displayPreferences.IndexBy, true, out var indexBy) ? indexBy : (IndexingKind?)null; existingDisplayPreferences.ShowBackdrop = displayPreferences.ShowBackdrop; existingDisplayPreferences.ShowSidebar = displayPreferences.ShowSidebar; @@ -201,7 +201,7 @@ namespace Jellyfin.Api.Controllers } // Set all remaining custom preferences. - _displayPreferencesManager.SetCustomItemDisplayPreferences(userId, existingDisplayPreferences.Client, displayPreferences.CustomPrefs); + _displayPreferencesManager.SetCustomItemDisplayPreferences(userId, itemId, existingDisplayPreferences.Client, displayPreferences.CustomPrefs); _displayPreferencesManager.SaveChanges(); return NoContent(); diff --git a/Jellyfin.Data/Entities/CustomItemDisplayPreferences.cs b/Jellyfin.Data/Entities/CustomItemDisplayPreferences.cs index 452d933eba..511e3b281a 100644 --- a/Jellyfin.Data/Entities/CustomItemDisplayPreferences.cs +++ b/Jellyfin.Data/Entities/CustomItemDisplayPreferences.cs @@ -13,12 +13,14 @@ namespace Jellyfin.Data.Entities /// Initializes a new instance of the class. /// /// The user id. + /// The item id. /// The client. /// The preference key. /// The preference value. - public CustomItemDisplayPreferences(Guid userId, string client, string preferenceKey, string preferenceValue) + public CustomItemDisplayPreferences(Guid userId, Guid itemId, string client, string preferenceKey, string preferenceValue) { UserId = userId; + ItemId = itemId; Client = client; Key = preferenceKey; Value = preferenceValue; @@ -48,6 +50,14 @@ namespace Jellyfin.Data.Entities /// public Guid UserId { get; set; } + /// + /// Gets or sets the id of the associated item. + /// + /// + /// Required. + /// + public Guid ItemId { get; set; } + /// /// Gets or sets the client string. /// diff --git a/Jellyfin.Data/Entities/DisplayPreferences.cs b/Jellyfin.Data/Entities/DisplayPreferences.cs index 701e4df004..1a8ca1da37 100644 --- a/Jellyfin.Data/Entities/DisplayPreferences.cs +++ b/Jellyfin.Data/Entities/DisplayPreferences.cs @@ -17,10 +17,12 @@ namespace Jellyfin.Data.Entities /// Initializes a new instance of the class. /// /// The user's id. + /// The item id. /// The client string. - public DisplayPreferences(Guid userId, string client) + public DisplayPreferences(Guid userId, Guid itemId, string client) { UserId = userId; + ItemId = itemId; Client = client; ShowSidebar = false; ShowBackdrop = true; @@ -58,6 +60,14 @@ namespace Jellyfin.Data.Entities /// public Guid UserId { get; set; } + /// + /// Gets or sets the id of the associated item. + /// + /// + /// Required. + /// + public Guid ItemId { get; set; } + /// /// Gets or sets the client string. /// diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj index 9ae129d072..89d6f4d9b7 100644 --- a/Jellyfin.Data/Jellyfin.Data.csproj +++ b/Jellyfin.Data/Jellyfin.Data.csproj @@ -29,7 +29,7 @@ - + diff --git a/Jellyfin.Server.Implementations/JellyfinDb.cs b/Jellyfin.Server.Implementations/JellyfinDb.cs index a8aa9b319b..7f3f837494 100644 --- a/Jellyfin.Server.Implementations/JellyfinDb.cs +++ b/Jellyfin.Server.Implementations/JellyfinDb.cs @@ -153,7 +153,7 @@ namespace Jellyfin.Server.Implementations .IsUnique(false); modelBuilder.Entity() - .HasIndex(entity => new { entity.UserId, entity.Client }) + .HasIndex(entity => new { entity.UserId, entity.ItemId, entity.Client }) .IsUnique(); modelBuilder.Entity() @@ -161,7 +161,7 @@ namespace Jellyfin.Server.Implementations .IsUnique(false); modelBuilder.Entity() - .HasIndex(entity => new { entity.UserId, entity.Client, entity.Key }) + .HasIndex(entity => new { entity.UserId, entity.ItemId, entity.Client, entity.Key }) .IsUnique(); } } diff --git a/Jellyfin.Server.Implementations/Migrations/20201203203707_AddCustomDisplayPreferences.Designer.cs b/Jellyfin.Server.Implementations/Migrations/20201204223655_AddCustomDisplayPreferences.Designer.cs similarity index 97% rename from Jellyfin.Server.Implementations/Migrations/20201203203707_AddCustomDisplayPreferences.Designer.cs rename to Jellyfin.Server.Implementations/Migrations/20201204223655_AddCustomDisplayPreferences.Designer.cs index ce3e30b599..10663d0655 100644 --- a/Jellyfin.Server.Implementations/Migrations/20201203203707_AddCustomDisplayPreferences.Designer.cs +++ b/Jellyfin.Server.Implementations/Migrations/20201204223655_AddCustomDisplayPreferences.Designer.cs @@ -10,7 +10,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace Jellyfin.Server.Implementations.Migrations { [DbContext(typeof(JellyfinDb))] - [Migration("20201203203707_AddCustomDisplayPreferences")] + [Migration("20201204223655_AddCustomDisplayPreferences")] partial class AddCustomDisplayPreferences { protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -102,6 +102,9 @@ namespace Jellyfin.Server.Implementations.Migrations .HasMaxLength(32) .HasColumnType("TEXT"); + b.Property("ItemId") + .HasColumnType("TEXT"); + b.Property("Key") .IsRequired() .HasColumnType("TEXT"); @@ -117,7 +120,7 @@ namespace Jellyfin.Server.Implementations.Migrations b.HasIndex("UserId"); - b.HasIndex("UserId", "Client", "Key") + b.HasIndex("UserId", "ItemId", "Client", "Key") .IsUnique(); b.ToTable("CustomItemDisplayPreferences"); @@ -147,6 +150,9 @@ namespace Jellyfin.Server.Implementations.Migrations b.Property("IndexBy") .HasColumnType("INTEGER"); + b.Property("ItemId") + .HasColumnType("TEXT"); + b.Property("ScrollDirection") .HasColumnType("INTEGER"); @@ -173,7 +179,7 @@ namespace Jellyfin.Server.Implementations.Migrations b.HasIndex("UserId"); - b.HasIndex("UserId", "Client") + b.HasIndex("UserId", "ItemId", "Client") .IsUnique(); b.ToTable("DisplayPreferences"); diff --git a/Jellyfin.Server.Implementations/Migrations/20201203203707_AddCustomDisplayPreferences.cs b/Jellyfin.Server.Implementations/Migrations/20201204223655_AddCustomDisplayPreferences.cs similarity index 60% rename from Jellyfin.Server.Implementations/Migrations/20201203203707_AddCustomDisplayPreferences.cs rename to Jellyfin.Server.Implementations/Migrations/20201204223655_AddCustomDisplayPreferences.cs index a07b265928..fbc0bffa97 100644 --- a/Jellyfin.Server.Implementations/Migrations/20201203203707_AddCustomDisplayPreferences.cs +++ b/Jellyfin.Server.Implementations/Migrations/20201204223655_AddCustomDisplayPreferences.cs @@ -9,6 +9,11 @@ namespace Jellyfin.Server.Implementations.Migrations { protected override void Up(MigrationBuilder migrationBuilder) { + migrationBuilder.DropIndex( + name: "IX_DisplayPreferences_UserId_Client", + schema: "jellyfin", + table: "DisplayPreferences"); + migrationBuilder.AlterColumn( name: "MaxActiveSessions", schema: "jellyfin", @@ -20,6 +25,14 @@ namespace Jellyfin.Server.Implementations.Migrations oldType: "INTEGER", oldNullable: true); + migrationBuilder.AddColumn( + name: "ItemId", + schema: "jellyfin", + table: "DisplayPreferences", + type: "TEXT", + nullable: false, + defaultValue: new Guid("00000000-0000-0000-0000-000000000000")); + migrationBuilder.CreateTable( name: "CustomItemDisplayPreferences", schema: "jellyfin", @@ -28,6 +41,7 @@ namespace Jellyfin.Server.Implementations.Migrations Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), UserId = table.Column(type: "TEXT", nullable: false), + ItemId = table.Column(type: "TEXT", nullable: false), Client = table.Column(type: "TEXT", maxLength: 32, nullable: false), Key = table.Column(type: "TEXT", nullable: false), Value = table.Column(type: "TEXT", nullable: false) @@ -37,6 +51,13 @@ namespace Jellyfin.Server.Implementations.Migrations table.PrimaryKey("PK_CustomItemDisplayPreferences", x => x.Id); }); + migrationBuilder.CreateIndex( + name: "IX_DisplayPreferences_UserId_ItemId_Client", + schema: "jellyfin", + table: "DisplayPreferences", + columns: new[] { "UserId", "ItemId", "Client" }, + unique: true); + migrationBuilder.CreateIndex( name: "IX_CustomItemDisplayPreferences_UserId", schema: "jellyfin", @@ -44,10 +65,10 @@ namespace Jellyfin.Server.Implementations.Migrations column: "UserId"); migrationBuilder.CreateIndex( - name: "IX_CustomItemDisplayPreferences_UserId_Client_Key", + name: "IX_CustomItemDisplayPreferences_UserId_ItemId_Client_Key", schema: "jellyfin", table: "CustomItemDisplayPreferences", - columns: new[] { "UserId", "Client", "Key" }, + columns: new[] { "UserId", "ItemId", "Client", "Key" }, unique: true); } @@ -57,6 +78,16 @@ namespace Jellyfin.Server.Implementations.Migrations name: "CustomItemDisplayPreferences", schema: "jellyfin"); + migrationBuilder.DropIndex( + name: "IX_DisplayPreferences_UserId_ItemId_Client", + schema: "jellyfin", + table: "DisplayPreferences"); + + migrationBuilder.DropColumn( + name: "ItemId", + schema: "jellyfin", + table: "DisplayPreferences"); + migrationBuilder.AlterColumn( name: "MaxActiveSessions", schema: "jellyfin", @@ -65,6 +96,13 @@ namespace Jellyfin.Server.Implementations.Migrations nullable: true, oldClrType: typeof(int), oldType: "INTEGER"); + + migrationBuilder.CreateIndex( + name: "IX_DisplayPreferences_UserId_Client", + schema: "jellyfin", + table: "DisplayPreferences", + columns: new[] { "UserId", "Client" }, + unique: true); } } } diff --git a/Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs b/Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs index 3b85c911cd..1614a88efb 100644 --- a/Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs +++ b/Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs @@ -99,6 +99,9 @@ namespace Jellyfin.Server.Implementations.Migrations .HasMaxLength(32) .HasColumnType("TEXT"); + b.Property("ItemId") + .HasColumnType("TEXT"); + b.Property("Key") .IsRequired() .HasColumnType("TEXT"); @@ -114,7 +117,7 @@ namespace Jellyfin.Server.Implementations.Migrations b.HasIndex("UserId"); - b.HasIndex("UserId", "Client", "Key") + b.HasIndex("UserId", "ItemId", "Client", "Key") .IsUnique(); b.ToTable("CustomItemDisplayPreferences"); @@ -144,6 +147,9 @@ namespace Jellyfin.Server.Implementations.Migrations b.Property("IndexBy") .HasColumnType("INTEGER"); + b.Property("ItemId") + .HasColumnType("TEXT"); + b.Property("ScrollDirection") .HasColumnType("INTEGER"); @@ -170,7 +176,7 @@ namespace Jellyfin.Server.Implementations.Migrations b.HasIndex("UserId"); - b.HasIndex("UserId", "Client") + b.HasIndex("UserId", "ItemId", "Client") .IsUnique(); b.ToTable("DisplayPreferences"); diff --git a/Jellyfin.Server.Implementations/Users/DisplayPreferencesManager.cs b/Jellyfin.Server.Implementations/Users/DisplayPreferencesManager.cs index 1f3b4ff17d..c8a589cabc 100644 --- a/Jellyfin.Server.Implementations/Users/DisplayPreferencesManager.cs +++ b/Jellyfin.Server.Implementations/Users/DisplayPreferencesManager.cs @@ -26,16 +26,16 @@ namespace Jellyfin.Server.Implementations.Users } /// - public DisplayPreferences GetDisplayPreferences(Guid userId, string client) + public DisplayPreferences GetDisplayPreferences(Guid userId, Guid itemId, string client) { var prefs = _dbContext.DisplayPreferences .Include(pref => pref.HomeSections) .FirstOrDefault(pref => - pref.UserId == userId && string.Equals(pref.Client, client)); + pref.UserId == userId && string.Equals(pref.Client, client) && pref.ItemId == itemId); if (prefs == null) { - prefs = new DisplayPreferences(userId, client); + prefs = new DisplayPreferences(userId, itemId, client); _dbContext.DisplayPreferences.Add(prefs); } @@ -67,26 +67,30 @@ namespace Jellyfin.Server.Implementations.Users } /// - public IDictionary ListCustomItemDisplayPreferences(Guid userId, string client) + public IDictionary ListCustomItemDisplayPreferences(Guid userId, Guid itemId, string client) { return _dbContext.CustomItemDisplayPreferences .AsQueryable() - .Where(prefs => prefs.UserId == userId && string.Equals(prefs.Client, client)) + .Where(prefs => prefs.UserId == userId + && prefs.ItemId == itemId + && string.Equals(prefs.Client, client)) .ToDictionary(prefs => prefs.Key, prefs => prefs.Value); } /// - public void SetCustomItemDisplayPreferences(Guid userId, string client, Dictionary customPreferences) + public void SetCustomItemDisplayPreferences(Guid userId, Guid itemId, string client, Dictionary customPreferences) { var existingPrefs = _dbContext.CustomItemDisplayPreferences .AsQueryable() - .Where(prefs => prefs.UserId == userId && string.Equals(prefs.Client, client)); + .Where(prefs => prefs.UserId == userId + && prefs.ItemId == itemId + && string.Equals(prefs.Client, client)); _dbContext.CustomItemDisplayPreferences.RemoveRange(existingPrefs); foreach (var (key, value) in customPreferences) { _dbContext.CustomItemDisplayPreferences - .Add(new CustomItemDisplayPreferences(userId, client, key, value)); + .Add(new CustomItemDisplayPreferences(userId, itemId, client, key, value)); } } diff --git a/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs b/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs index 7b79184fc0..1a037053f2 100644 --- a/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs +++ b/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs @@ -8,6 +8,7 @@ using System.Text.Json.Serialization; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; using Jellyfin.Server.Implementations; +using MediaBrowser.Common.Extensions; using MediaBrowser.Controller; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Entities; @@ -80,6 +81,7 @@ namespace Jellyfin.Server.Migrations.Routines { "unstable", ChromecastVersion.Unstable } }; + var defaultDisplayPrefsId = "usersettings".GetMD5(); var dbFilePath = Path.Combine(_paths.DataPath, DbFilename); using (var connection = SQLite3.Open(dbFilePath, ConnectionFlags.ReadOnly, null)) { @@ -94,6 +96,12 @@ namespace Jellyfin.Server.Migrations.Routines continue; } + var itemId = new Guid(result[1].ToBlob()); + if (itemId == defaultDisplayPrefsId) + { + itemId = Guid.Empty; + } + var dtoUserId = new Guid(result[1].ToBlob()); var existingUser = _userManager.GetUserById(dtoUserId); if (existingUser == null) @@ -107,7 +115,7 @@ namespace Jellyfin.Server.Migrations.Routines : ChromecastVersion.Stable; dto.CustomPrefs.Remove("chromecastVersion"); - var displayPreferences = new DisplayPreferences(dtoUserId, result[2].ToString()) + var displayPreferences = new DisplayPreferences(dtoUserId, itemId, result[2].ToString()) { IndexBy = Enum.TryParse(dto.IndexBy, true, out var indexBy) ? indexBy : (IndexingKind?)null, ShowBackdrop = dto.ShowBackdrop, @@ -159,12 +167,12 @@ namespace Jellyfin.Server.Migrations.Routines foreach (var key in dto.CustomPrefs.Keys.Where(key => key.StartsWith("landing-", StringComparison.Ordinal))) { - if (!Guid.TryParse(key.AsSpan().Slice("landing-".Length), out var itemId)) + if (!Guid.TryParse(key.AsSpan().Slice("landing-".Length), out var landingItemId)) { continue; } - var libraryDisplayPreferences = new ItemDisplayPreferences(displayPreferences.UserId, itemId, displayPreferences.Client) + var libraryDisplayPreferences = new ItemDisplayPreferences(displayPreferences.UserId, landingItemId, displayPreferences.Client) { SortBy = dto.SortBy ?? "SortName", SortOrder = dto.SortOrder, @@ -183,7 +191,7 @@ namespace Jellyfin.Server.Migrations.Routines foreach (var (key, value) in dto.CustomPrefs) { - dbContext.Add(new CustomItemDisplayPreferences(displayPreferences.UserId, displayPreferences.Client, key, value)); + dbContext.Add(new CustomItemDisplayPreferences(displayPreferences.UserId, itemId, displayPreferences.Client, key, value)); } dbContext.Add(displayPreferences); diff --git a/MediaBrowser.Controller/IDisplayPreferencesManager.cs b/MediaBrowser.Controller/IDisplayPreferencesManager.cs index 97176eb92c..041eeea62a 100644 --- a/MediaBrowser.Controller/IDisplayPreferencesManager.cs +++ b/MediaBrowser.Controller/IDisplayPreferencesManager.cs @@ -16,9 +16,10 @@ namespace MediaBrowser.Controller /// This will create the display preferences if it does not exist, but it will not save automatically. /// /// The user's id. + /// The item id. /// The client string. /// The associated display preferences. - DisplayPreferences GetDisplayPreferences(Guid userId, string client); + DisplayPreferences GetDisplayPreferences(Guid userId, Guid itemId, string client); /// /// Gets the default item display preferences for the user and client. @@ -44,17 +45,19 @@ namespace MediaBrowser.Controller /// Gets all of the custom item display preferences for the user and client. /// /// The user id. + /// The item id. /// The client string. /// The dictionary of custom item display preferences. - IDictionary ListCustomItemDisplayPreferences(Guid userId, string client); + IDictionary ListCustomItemDisplayPreferences(Guid userId, Guid itemId, string client); /// /// Sets the custom item display preference for the user and client. /// /// The user id. + /// The item id. /// The client id. /// A dictionary of custom item display preferences. - void SetCustomItemDisplayPreferences(Guid userId, string client, Dictionary customPreferences); + void SetCustomItemDisplayPreferences(Guid userId, Guid itemId, string client, Dictionary customPreferences); /// /// Saves changes made to the database.