diff options
Diffstat (limited to 'Jellyfin.Server.Implementations')
5 files changed, 712 insertions, 39 deletions
diff --git a/Jellyfin.Server.Implementations/JellyfinDb.cs b/Jellyfin.Server.Implementations/JellyfinDb.cs index bf8818f8d..a8aa9b319 100644 --- a/Jellyfin.Server.Implementations/JellyfinDb.cs +++ b/Jellyfin.Server.Implementations/JellyfinDb.cs @@ -34,6 +34,8 @@ namespace Jellyfin.Server.Implementations public virtual DbSet<ItemDisplayPreferences> ItemDisplayPreferences { get; set; } + public virtual DbSet<CustomItemDisplayPreferences> CustomItemDisplayPreferences { get; set; } + public virtual DbSet<Permission> Permissions { get; set; } public virtual DbSet<Preference> Preferences { get; set; } @@ -153,6 +155,14 @@ namespace Jellyfin.Server.Implementations modelBuilder.Entity<DisplayPreferences>() .HasIndex(entity => new { entity.UserId, entity.Client }) .IsUnique(); + + modelBuilder.Entity<CustomItemDisplayPreferences>() + .HasIndex(entity => entity.UserId) + .IsUnique(false); + + modelBuilder.Entity<CustomItemDisplayPreferences>() + .HasIndex(entity => new { entity.UserId, entity.Client, entity.Key }) + .IsUnique(); } } } diff --git a/Jellyfin.Server.Implementations/Migrations/20201203203707_AddCustomDisplayPreferences.Designer.cs b/Jellyfin.Server.Implementations/Migrations/20201203203707_AddCustomDisplayPreferences.Designer.cs new file mode 100644 index 000000000..ce3e30b59 --- /dev/null +++ b/Jellyfin.Server.Implementations/Migrations/20201203203707_AddCustomDisplayPreferences.Designer.cs @@ -0,0 +1,516 @@ +#pragma warning disable CS1591 +// <auto-generated /> +using System; +using Jellyfin.Server.Implementations; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace Jellyfin.Server.Implementations.Migrations +{ + [DbContext(typeof(JellyfinDb))] + [Migration("20201203203707_AddCustomDisplayPreferences")] + partial class AddCustomDisplayPreferences + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("jellyfin") + .HasAnnotation("ProductVersion", "5.0.0"); + + modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property<int>("DayOfWeek") + .HasColumnType("INTEGER"); + + b.Property<double>("EndHour") + .HasColumnType("REAL"); + + b.Property<double>("StartHour") + .HasColumnType("REAL"); + + b.Property<Guid>("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AccessSchedules"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property<DateTime>("DateCreated") + .HasColumnType("TEXT"); + + b.Property<string>("ItemId") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property<int>("LogSeverity") + .HasColumnType("INTEGER"); + + b.Property<string>("Name") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("TEXT"); + + b.Property<string>("Overview") + .HasMaxLength(512) + .HasColumnType("TEXT"); + + b.Property<uint>("RowVersion") + .IsConcurrencyToken() + .HasColumnType("INTEGER"); + + b.Property<string>("ShortOverview") + .HasMaxLength(512) + .HasColumnType("TEXT"); + + b.Property<string>("Type") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property<Guid>("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("ActivityLogs"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.CustomItemDisplayPreferences", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property<string>("Client") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("TEXT"); + + b.Property<string>("Key") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property<Guid>("UserId") + .HasColumnType("TEXT"); + + b.Property<string>("Value") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.HasIndex("UserId", "Client", "Key") + .IsUnique(); + + b.ToTable("CustomItemDisplayPreferences"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property<int>("ChromecastVersion") + .HasColumnType("INTEGER"); + + b.Property<string>("Client") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("TEXT"); + + b.Property<string>("DashboardTheme") + .HasMaxLength(32) + .HasColumnType("TEXT"); + + b.Property<bool>("EnableNextVideoInfoOverlay") + .HasColumnType("INTEGER"); + + b.Property<int?>("IndexBy") + .HasColumnType("INTEGER"); + + b.Property<int>("ScrollDirection") + .HasColumnType("INTEGER"); + + b.Property<bool>("ShowBackdrop") + .HasColumnType("INTEGER"); + + b.Property<bool>("ShowSidebar") + .HasColumnType("INTEGER"); + + b.Property<int>("SkipBackwardLength") + .HasColumnType("INTEGER"); + + b.Property<int>("SkipForwardLength") + .HasColumnType("INTEGER"); + + b.Property<string>("TvHome") + .HasMaxLength(32) + .HasColumnType("TEXT"); + + b.Property<Guid>("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.HasIndex("UserId", "Client") + .IsUnique(); + + b.ToTable("DisplayPreferences"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property<int>("DisplayPreferencesId") + .HasColumnType("INTEGER"); + + b.Property<int>("Order") + .HasColumnType("INTEGER"); + + b.Property<int>("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("DisplayPreferencesId"); + + b.ToTable("HomeSection"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property<DateTime>("LastModified") + .HasColumnType("TEXT"); + + b.Property<string>("Path") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("TEXT"); + + b.Property<Guid?>("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("ImageInfos"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property<string>("Client") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("TEXT"); + + b.Property<int?>("IndexBy") + .HasColumnType("INTEGER"); + + b.Property<Guid>("ItemId") + .HasColumnType("TEXT"); + + b.Property<bool>("RememberIndexing") + .HasColumnType("INTEGER"); + + b.Property<bool>("RememberSorting") + .HasColumnType("INTEGER"); + + b.Property<string>("SortBy") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("TEXT"); + + b.Property<int>("SortOrder") + .HasColumnType("INTEGER"); + + b.Property<Guid>("UserId") + .HasColumnType("TEXT"); + + b.Property<int>("ViewType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("ItemDisplayPreferences"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property<int>("Kind") + .HasColumnType("INTEGER"); + + b.Property<Guid?>("Permission_Permissions_Guid") + .HasColumnType("TEXT"); + + b.Property<uint>("RowVersion") + .IsConcurrencyToken() + .HasColumnType("INTEGER"); + + b.Property<bool>("Value") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("Permission_Permissions_Guid"); + + b.ToTable("Permissions"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property<int>("Kind") + .HasColumnType("INTEGER"); + + b.Property<Guid?>("Preference_Preferences_Guid") + .HasColumnType("TEXT"); + + b.Property<uint>("RowVersion") + .IsConcurrencyToken() + .HasColumnType("INTEGER"); + + b.Property<string>("Value") + .IsRequired() + .HasMaxLength(65535) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Preference_Preferences_Guid"); + + b.ToTable("Preferences"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.User", b => + { + b.Property<Guid>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property<string>("AudioLanguagePreference") + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property<string>("AuthenticationProviderId") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property<bool>("DisplayCollectionsView") + .HasColumnType("INTEGER"); + + b.Property<bool>("DisplayMissingEpisodes") + .HasColumnType("INTEGER"); + + b.Property<string>("EasyPassword") + .HasMaxLength(65535) + .HasColumnType("TEXT"); + + b.Property<bool>("EnableAutoLogin") + .HasColumnType("INTEGER"); + + b.Property<bool>("EnableLocalPassword") + .HasColumnType("INTEGER"); + + b.Property<bool>("EnableNextEpisodeAutoPlay") + .HasColumnType("INTEGER"); + + b.Property<bool>("EnableUserPreferenceAccess") + .HasColumnType("INTEGER"); + + b.Property<bool>("HidePlayedInLatest") + .HasColumnType("INTEGER"); + + b.Property<long>("InternalId") + .HasColumnType("INTEGER"); + + b.Property<int>("InvalidLoginAttemptCount") + .HasColumnType("INTEGER"); + + b.Property<DateTime?>("LastActivityDate") + .HasColumnType("TEXT"); + + b.Property<DateTime?>("LastLoginDate") + .HasColumnType("TEXT"); + + b.Property<int?>("LoginAttemptsBeforeLockout") + .HasColumnType("INTEGER"); + + b.Property<int>("MaxActiveSessions") + .HasColumnType("INTEGER"); + + b.Property<int?>("MaxParentalAgeRating") + .HasColumnType("INTEGER"); + + b.Property<bool>("MustUpdatePassword") + .HasColumnType("INTEGER"); + + b.Property<string>("Password") + .HasMaxLength(65535) + .HasColumnType("TEXT"); + + b.Property<string>("PasswordResetProviderId") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property<bool>("PlayDefaultAudioTrack") + .HasColumnType("INTEGER"); + + b.Property<bool>("RememberAudioSelections") + .HasColumnType("INTEGER"); + + b.Property<bool>("RememberSubtitleSelections") + .HasColumnType("INTEGER"); + + b.Property<int?>("RemoteClientBitrateLimit") + .HasColumnType("INTEGER"); + + b.Property<uint>("RowVersion") + .IsConcurrencyToken() + .HasColumnType("INTEGER"); + + b.Property<string>("SubtitleLanguagePreference") + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property<int>("SubtitleMode") + .HasColumnType("INTEGER"); + + b.Property<int>("SyncPlayAccess") + .HasColumnType("INTEGER"); + + b.Property<string>("Username") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => + { + b.HasOne("Jellyfin.Data.Entities.User", null) + .WithMany("AccessSchedules") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => + { + b.HasOne("Jellyfin.Data.Entities.User", null) + .WithOne("DisplayPreferences") + .HasForeignKey("Jellyfin.Data.Entities.DisplayPreferences", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => + { + b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null) + .WithMany("HomeSections") + .HasForeignKey("DisplayPreferencesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => + { + b.HasOne("Jellyfin.Data.Entities.User", null) + .WithOne("ProfileImage") + .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => + { + b.HasOne("Jellyfin.Data.Entities.User", null) + .WithMany("ItemDisplayPreferences") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => + { + b.HasOne("Jellyfin.Data.Entities.User", null) + .WithMany("Permissions") + .HasForeignKey("Permission_Permissions_Guid"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => + { + b.HasOne("Jellyfin.Data.Entities.User", null) + .WithMany("Preferences") + .HasForeignKey("Preference_Preferences_Guid"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => + { + b.Navigation("HomeSections"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.User", b => + { + b.Navigation("AccessSchedules"); + + b.Navigation("DisplayPreferences") + .IsRequired(); + + b.Navigation("ItemDisplayPreferences"); + + b.Navigation("Permissions"); + + b.Navigation("Preferences"); + + b.Navigation("ProfileImage"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Jellyfin.Server.Implementations/Migrations/20201203203707_AddCustomDisplayPreferences.cs b/Jellyfin.Server.Implementations/Migrations/20201203203707_AddCustomDisplayPreferences.cs new file mode 100644 index 000000000..a07b26592 --- /dev/null +++ b/Jellyfin.Server.Implementations/Migrations/20201203203707_AddCustomDisplayPreferences.cs @@ -0,0 +1,70 @@ +#pragma warning disable CS1591 +// <auto-generated /> +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Jellyfin.Server.Implementations.Migrations +{ + public partial class AddCustomDisplayPreferences : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn<int>( + name: "MaxActiveSessions", + schema: "jellyfin", + table: "Users", + type: "INTEGER", + nullable: false, + defaultValue: 0, + oldClrType: typeof(int), + oldType: "INTEGER", + oldNullable: true); + + migrationBuilder.CreateTable( + name: "CustomItemDisplayPreferences", + schema: "jellyfin", + columns: table => new + { + Id = table.Column<int>(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + UserId = table.Column<Guid>(type: "TEXT", nullable: false), + Client = table.Column<string>(type: "TEXT", maxLength: 32, nullable: false), + Key = table.Column<string>(type: "TEXT", nullable: false), + Value = table.Column<string>(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_CustomItemDisplayPreferences", x => x.Id); + }); + + migrationBuilder.CreateIndex( + name: "IX_CustomItemDisplayPreferences_UserId", + schema: "jellyfin", + table: "CustomItemDisplayPreferences", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_CustomItemDisplayPreferences_UserId_Client_Key", + schema: "jellyfin", + table: "CustomItemDisplayPreferences", + columns: new[] { "UserId", "Client", "Key" }, + unique: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "CustomItemDisplayPreferences", + schema: "jellyfin"); + + migrationBuilder.AlterColumn<int>( + name: "MaxActiveSessions", + schema: "jellyfin", + table: "Users", + type: "INTEGER", + nullable: true, + oldClrType: typeof(int), + oldType: "INTEGER"); + } + } +} diff --git a/Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs b/Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs index 16d62f482..3b85c911c 100644 --- a/Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs +++ b/Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs @@ -15,7 +15,7 @@ namespace Jellyfin.Server.Implementations.Migrations #pragma warning disable 612, 618 modelBuilder .HasDefaultSchema("jellyfin") - .HasAnnotation("ProductVersion", "3.1.8"); + .HasAnnotation("ProductVersion", "5.0.0"); modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => { @@ -52,33 +52,33 @@ namespace Jellyfin.Server.Implementations.Migrations .HasColumnType("TEXT"); b.Property<string>("ItemId") - .HasColumnType("TEXT") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("TEXT"); b.Property<int>("LogSeverity") .HasColumnType("INTEGER"); b.Property<string>("Name") .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(512); + .HasMaxLength(512) + .HasColumnType("TEXT"); b.Property<string>("Overview") - .HasColumnType("TEXT") - .HasMaxLength(512); + .HasMaxLength(512) + .HasColumnType("TEXT"); b.Property<uint>("RowVersion") .IsConcurrencyToken() .HasColumnType("INTEGER"); b.Property<string>("ShortOverview") - .HasColumnType("TEXT") - .HasMaxLength(512); + .HasMaxLength(512) + .HasColumnType("TEXT"); b.Property<string>("Type") .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("TEXT"); b.Property<Guid>("UserId") .HasColumnType("TEXT"); @@ -88,6 +88,38 @@ namespace Jellyfin.Server.Implementations.Migrations b.ToTable("ActivityLogs"); }); + modelBuilder.Entity("Jellyfin.Data.Entities.CustomItemDisplayPreferences", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property<string>("Client") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("TEXT"); + + b.Property<string>("Key") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property<Guid>("UserId") + .HasColumnType("TEXT"); + + b.Property<string>("Value") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.HasIndex("UserId", "Client", "Key") + .IsUnique(); + + b.ToTable("CustomItemDisplayPreferences"); + }); + modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => { b.Property<int>("Id") @@ -99,12 +131,12 @@ namespace Jellyfin.Server.Implementations.Migrations b.Property<string>("Client") .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(32); + .HasMaxLength(32) + .HasColumnType("TEXT"); b.Property<string>("DashboardTheme") - .HasColumnType("TEXT") - .HasMaxLength(32); + .HasMaxLength(32) + .HasColumnType("TEXT"); b.Property<bool>("EnableNextVideoInfoOverlay") .HasColumnType("INTEGER"); @@ -128,8 +160,8 @@ namespace Jellyfin.Server.Implementations.Migrations .HasColumnType("INTEGER"); b.Property<string>("TvHome") - .HasColumnType("TEXT") - .HasMaxLength(32); + .HasMaxLength(32) + .HasColumnType("TEXT"); b.Property<Guid>("UserId") .HasColumnType("TEXT"); @@ -177,8 +209,8 @@ namespace Jellyfin.Server.Implementations.Migrations b.Property<string>("Path") .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(512); + .HasMaxLength(512) + .HasColumnType("TEXT"); b.Property<Guid?>("UserId") .HasColumnType("TEXT"); @@ -199,8 +231,8 @@ namespace Jellyfin.Server.Implementations.Migrations b.Property<string>("Client") .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(32); + .HasMaxLength(32) + .HasColumnType("TEXT"); b.Property<int?>("IndexBy") .HasColumnType("INTEGER"); @@ -216,8 +248,8 @@ namespace Jellyfin.Server.Implementations.Migrations b.Property<string>("SortBy") .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(64); + .HasMaxLength(64) + .HasColumnType("TEXT"); b.Property<int>("SortOrder") .HasColumnType("INTEGER"); @@ -279,8 +311,8 @@ namespace Jellyfin.Server.Implementations.Migrations b.Property<string>("Value") .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(65535); + .HasMaxLength(65535) + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -296,13 +328,13 @@ namespace Jellyfin.Server.Implementations.Migrations .HasColumnType("TEXT"); b.Property<string>("AudioLanguagePreference") - .HasColumnType("TEXT") - .HasMaxLength(255); + .HasMaxLength(255) + .HasColumnType("TEXT"); b.Property<string>("AuthenticationProviderId") .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(255); + .HasMaxLength(255) + .HasColumnType("TEXT"); b.Property<bool>("DisplayCollectionsView") .HasColumnType("INTEGER"); @@ -311,8 +343,8 @@ namespace Jellyfin.Server.Implementations.Migrations .HasColumnType("INTEGER"); b.Property<string>("EasyPassword") - .HasColumnType("TEXT") - .HasMaxLength(65535); + .HasMaxLength(65535) + .HasColumnType("TEXT"); b.Property<bool>("EnableAutoLogin") .HasColumnType("INTEGER"); @@ -354,13 +386,13 @@ namespace Jellyfin.Server.Implementations.Migrations .HasColumnType("INTEGER"); b.Property<string>("Password") - .HasColumnType("TEXT") - .HasMaxLength(65535); + .HasMaxLength(65535) + .HasColumnType("TEXT"); b.Property<string>("PasswordResetProviderId") .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(255); + .HasMaxLength(255) + .HasColumnType("TEXT"); b.Property<bool>("PlayDefaultAudioTrack") .HasColumnType("INTEGER"); @@ -379,8 +411,8 @@ namespace Jellyfin.Server.Implementations.Migrations .HasColumnType("INTEGER"); b.Property<string>("SubtitleLanguagePreference") - .HasColumnType("TEXT") - .HasMaxLength(255); + .HasMaxLength(255) + .HasColumnType("TEXT"); b.Property<int>("SubtitleMode") .HasColumnType("INTEGER"); @@ -390,8 +422,8 @@ namespace Jellyfin.Server.Implementations.Migrations b.Property<string>("Username") .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(255); + .HasMaxLength(255) + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -454,6 +486,27 @@ namespace Jellyfin.Server.Implementations.Migrations .WithMany("Preferences") .HasForeignKey("Preference_Preferences_Guid"); }); + + modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => + { + b.Navigation("HomeSections"); + }); + + modelBuilder.Entity("Jellyfin.Data.Entities.User", b => + { + b.Navigation("AccessSchedules"); + + b.Navigation("DisplayPreferences") + .IsRequired(); + + b.Navigation("ItemDisplayPreferences"); + + b.Navigation("Permissions"); + + b.Navigation("Preferences"); + + b.Navigation("ProfileImage"); + }); #pragma warning restore 612, 618 } } diff --git a/Jellyfin.Server.Implementations/Users/DisplayPreferencesManager.cs b/Jellyfin.Server.Implementations/Users/DisplayPreferencesManager.cs index 76f943385..1f3b4ff17 100644 --- a/Jellyfin.Server.Implementations/Users/DisplayPreferencesManager.cs +++ b/Jellyfin.Server.Implementations/Users/DisplayPreferencesManager.cs @@ -67,6 +67,30 @@ namespace Jellyfin.Server.Implementations.Users } /// <inheritdoc /> + public IDictionary<string, string> ListCustomItemDisplayPreferences(Guid userId, string client) + { + return _dbContext.CustomItemDisplayPreferences + .AsQueryable() + .Where(prefs => prefs.UserId == userId && string.Equals(prefs.Client, client)) + .ToDictionary(prefs => prefs.Key, prefs => prefs.Value); + } + + /// <inheritdoc /> + public void SetCustomItemDisplayPreferences(Guid userId, string client, Dictionary<string, string> customPreferences) + { + var existingPrefs = _dbContext.CustomItemDisplayPreferences + .AsQueryable() + .Where(prefs => prefs.UserId == userId && string.Equals(prefs.Client, client)); + _dbContext.CustomItemDisplayPreferences.RemoveRange(existingPrefs); + + foreach (var (key, value) in customPreferences) + { + _dbContext.CustomItemDisplayPreferences + .Add(new CustomItemDisplayPreferences(userId, client, key, value)); + } + } + + /// <inheritdoc /> public void SaveChanges() { _dbContext.SaveChanges(); |
