diff --git a/src/Shared.Core/KoikatuAPIBase.cs b/src/Shared.Core/KoikatuAPIBase.cs index 69e7e28..23b7270 100644 --- a/src/Shared.Core/KoikatuAPIBase.cs +++ b/src/Shared.Core/KoikatuAPIBase.cs @@ -56,7 +56,7 @@ public static bool EnableDebugLogging } private static ConfigEntry EnableDebugLoggingSetting { get; set; } - internal static ConfigEntry RememberFilePickerFolder { get; set; } + internal static ConfigEntry RememberFilePickerFolder { get; set; } internal static KoikatuAPI Instance { get; private set; } internal static new ManualLogSource Logger { get; private set; } @@ -85,7 +85,7 @@ private void BaseAwake() Logger = base.Logger; EnableDebugLoggingSetting = Config.Bind("Debug", "Show debug messages", false, "Enables display of additional log messages when certain events are triggered within KKAPI. Useful for plugin devs to understand when controller messages are fired. Changes take effect after game restart."); - RememberFilePickerFolder = Config.Bind("General", "Remember last folder in file pickers", true, "If true, file picker dialogs will remember the last opened folder and open already inside of it. If false, the dialogs will always open in the default folder.\n\nWarning: This setting only applies to plugins that use the file picker through this API."); + RememberFilePickerFolder = Config.Bind("General", "Remember last folder in file pickers", RememberFilePickerFolderSetting.Enabled, "If enabled, file picker dialogs will remember the last opened folder and open inside of it instead of the default folder. If disabled, the dialogs will always open in the default folder.\n\n'Reset On Restart' will remember the last opened folders only until the game is restarted, after which they will be reset.\n\nWarning: This setting only applies to plugins that use the file picker through this API."); Logger.LogDebug($"Game version {GetGameVersion()} running under {System.Threading.Thread.CurrentThread.CurrentCulture.Name} culture"); @@ -159,6 +159,7 @@ void PrintFileIfExists(string fileName) } }); } + OpenFileDialog.LoadFilePickerStates(); #if QUITTING_EVENT_AVAILABLE UnityEngine.Application.quitting += () => OnQuitting(EventArgs.Empty); @@ -281,5 +282,12 @@ private static void GameExitPrefix() } } #endif + + internal enum RememberFilePickerFolderSetting + { + Enabled = 1, + ResetOnRestart = 2, + Disabled = 3 + } } } diff --git a/src/Shared.Core/Utilities/OpenFileDialog.cs b/src/Shared.Core/Utilities/OpenFileDialog.cs index 97c8f70..a2a6d70 100644 --- a/src/Shared.Core/Utilities/OpenFileDialog.cs +++ b/src/Shared.Core/Utilities/OpenFileDialog.cs @@ -1,6 +1,9 @@ -using System; +using BepInEx; +using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; +using System.Linq; using System.Runtime.InteropServices; using System.Threading; @@ -30,6 +33,7 @@ public class OpenFileDialog /// Key is the initialDir, value is the last opened path. /// private static readonly Dictionary LastOpenedPaths = new Dictionary(); + private static readonly string lastOpenedPathsCachePath = Path.Combine(Paths.CachePath, "ModdingAPI.lastOpenedPaths"); /// public static string[] ShowDialog(string title, string initialDir, string filter, string defaultExt, OpenSaveFileDialgueFlags flags, IntPtr owner = default) @@ -73,7 +77,7 @@ public static string[] ShowDialog(string title, string initialDir, string filter ofn.filter = filter.Replace("|", "\0") + "\0"; ofn.fileTitle = new String(new char[MAX_FILE_LENGTH]); ofn.maxFileTitle = ofn.fileTitle.Length; - if (KoikatuAPI.RememberFilePickerFolder.Value) + if (KoikatuAPI.RememberFilePickerFolder.Value != KoikatuAPI.RememberFilePickerFolderSetting.Disabled) LastOpenedPaths.TryGetValue(initialDir, out ofn.initialDir); if (string.IsNullOrEmpty(ofn.initialDir)) ofn.initialDir = initialDir; @@ -133,6 +137,7 @@ public static string[] ShowDialog(string title, string initialDir, string filter } LastOpenedPaths[initialDir] = Path.GetDirectoryName(selectedFilesList[0]); + SaveFilePickerStates(); if (selectedFilesList.Count == 1) { // Only one file selected with full path @@ -202,6 +207,44 @@ private static class NativeMethods public static extern IntPtr GetActiveWindow(); } + internal static void SaveFilePickerStates() + { + try + { + using (var fs = File.Create(lastOpenedPathsCachePath)) + using (var wr = new StreamWriter(fs)) + foreach (var path in LastOpenedPaths) + wr.WriteLine($"{path.Key}, {path.Value}"); + } + catch (Exception ex) + { + KoikatuAPI.Logger.LogError($"Failed saving folder states to '{lastOpenedPathsCachePath}' because of error: {ex}"); + } + } + + internal static void LoadFilePickerStates() + { + try + { + if (KoikatuAPI.RememberFilePickerFolder.Value == KoikatuAPI.RememberFilePickerFolderSetting.Enabled && File.Exists(lastOpenedPathsCachePath)) + { + var lines = File.ReadAllLines(lastOpenedPathsCachePath); + foreach (var line in lines) + { + if (string.IsNullOrEmpty(line)) continue; + + var s = line.Split(','); + if (s.Length != 2) continue; + LastOpenedPaths[s[0]] = s[1]; + } + } + } + catch (Exception ex) + { + KoikatuAPI.Logger.LogError($"Failed loading folder states from '{lastOpenedPathsCachePath}' because of error: {ex}"); + } + } + #pragma warning disable 1591 [Flags] public enum OpenSaveFileDialgueFlags