using System.Globalization; using System.Text.Json.Serialization; using Semver; using StabilityMatrix.Core.Converters.Json; using StabilityMatrix.Core.Extensions; using StabilityMatrix.Core.Models.Api; using StabilityMatrix.Core.Models.Update; namespace StabilityMatrix.Core.Models.Settings; public class Settings { public int? Version { get; set; } = 1; public bool FirstLaunchSetupComplete { get; set; } public string? Theme { get; set; } = "Dark"; public string? Language { get; set; } = GetDefaultCulture().Name; public List InstalledPackages { get; set; } = new(); [JsonPropertyName("ActiveInstalledPackage")] public Guid? ActiveInstalledPackageId { get; set; } /// /// The first installed package matching the /// or null if no matching package /// [JsonIgnore] public InstalledPackage? ActiveInstalledPackage { get => ActiveInstalledPackageId == null ? null : InstalledPackages.FirstOrDefault(x => x.Id == ActiveInstalledPackageId); set => ActiveInstalledPackageId = value?.Id; } public bool HasSeenWelcomeNotification { get; set; } public List? PathExtensions { get; set; } public string? WebApiHost { get; set; } public string? WebApiPort { get; set; } /// /// Preferred update channel /// public UpdateChannel PreferredUpdateChannel { get; set; } = UpdateChannel.Stable; /// /// Whether to check for updates /// public bool CheckForUpdates { get; set; } = true; /// /// The last auto-update version that had a notification dismissed by the user /// [JsonConverter(typeof(SemVersionJsonConverter))] public SemVersion? LastSeenUpdateVersion { get; set; } // UI states public bool ModelBrowserNsfwEnabled { get; set; } public bool IsNavExpanded { get; set; } public bool IsImportAsConnected { get; set; } public bool ShowConnectedModelImages { get; set; } [JsonConverter(typeof(JsonStringEnumConverter))] public SharedFolderType SharedFolderVisibleCategories { get; set; } = SharedFolderType.StableDiffusion | SharedFolderType.Lora | SharedFolderType.LyCORIS; public WindowSettings? WindowSettings { get; set; } public ModelSearchOptions? ModelSearchOptions { get; set; } /// /// Whether prompt auto completion is enabled /// public bool IsPromptCompletionEnabled { get; set; } = true; /// /// Relative path to the tag completion CSV file from 'LibraryDir/Tags' /// public string? TagCompletionCsv { get; set; } /// /// Whether to remove underscores from completions /// public bool IsCompletionRemoveUnderscoresEnabled { get; set; } = true; /// /// Format for Inference output image file names /// public string? InferenceOutputImageFileNameFormat { get; set; } /// /// Whether the Inference Image Viewer shows pixel grids at high zoom levels /// public bool IsImageViewerPixelGridEnabled { get; set; } = true; public bool RemoveFolderLinksOnShutdown { get; set; } public bool IsDiscordRichPresenceEnabled { get; set; } public Dictionary? EnvironmentVariables { get; set; } public HashSet? InstalledModelHashes { get; set; } = new(); public float AnimationScale { get; set; } = 1.0f; public bool AutoScrollLaunchConsoleToEnd { get; set; } = true; public HashSet FavoriteModels { get; set; } = new(); public HashSet SeenTeachingTips { get; set; } = new(); public Dictionary NotificationOptions { get; set; } = new(); public List SelectedBaseModels { get; set; } = Enum.GetValues() .Where(x => x != CivitBaseModelType.All) .Select(x => x.GetStringValue()) .ToList(); public Size InferenceImageSize { get; set; } = new(150, 190); public Size OutputsImageSize { get; set; } = new(300, 300); public HolidayMode HolidayModeSetting { get; set; } = HolidayMode.Automatic; [JsonIgnore] public bool IsHolidayModeActive => HolidayModeSetting == HolidayMode.Automatic ? DateTimeOffset.Now.Month == 12 : HolidayModeSetting == HolidayMode.Enabled; public void RemoveInstalledPackageAndUpdateActive(InstalledPackage package) { RemoveInstalledPackageAndUpdateActive(package.Id); } public void RemoveInstalledPackageAndUpdateActive(Guid id) { InstalledPackages.RemoveAll(x => x.Id == id); UpdateActiveInstalledPackage(); } /// /// Update ActiveInstalledPackage if not valid /// uses first package or null if no packages /// public void UpdateActiveInstalledPackage() { // Empty packages - set to null if (InstalledPackages.Count == 0) { ActiveInstalledPackageId = null; } // Active package is not in package - set to first package else if (InstalledPackages.All(x => x.Id != ActiveInstalledPackageId)) { ActiveInstalledPackageId = InstalledPackages[0].Id; } } /// /// Return either the system default culture, if supported, or en-US /// /// public static CultureInfo GetDefaultCulture() { var supportedCultures = new[] { "en-US", "ja-JP", "zh-Hans", "zh-Hant" }; var systemCulture = CultureInfo.InstalledUICulture; if (systemCulture.Name.StartsWith("zh-Hans", StringComparison.OrdinalIgnoreCase)) { return new CultureInfo("zh-Hans"); } if (systemCulture.Name.StartsWith("zh-Hant")) { return new CultureInfo("zh-Hant"); } return supportedCultures.Contains(systemCulture.Name) ? systemCulture : new CultureInfo("en-US"); } } [JsonSourceGenerationOptions( WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull )] [JsonSerializable(typeof(Settings))] [JsonSerializable(typeof(bool))] [JsonSerializable(typeof(int))] [JsonSerializable(typeof(string))] internal partial class SettingsSerializerContext : JsonSerializerContext;