diff --git a/CHANGELOG.md b/CHANGELOG.md index d4d4647..ea2ffb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,11 @@ # Latest Changelog -- Fixed OSC map values being mixed up sometimes. It should be consistent now. -- Fixed OSC Item Status for CorkScrew coil. - - Please note that Item Status only works with a specific set of items. -- Fixed a button on the Settings window slicing the text on high DPI resolution. -- Updated Japanese localization. (Thank you @nomlasvrc) \ No newline at end of file +- The Save Manager program is a single file now. YAY +- Removed the pop-up message when you click a save code. A better less intrusive method have been implemented. +- Aditionally, a sound will play when you copy a save code. (Can be disabled in Settings) + - The custom sound notifications in settings have been reworked too. + - The 'Auto Copy' feature will also play an audio if the 'Play Audio on Copy' setting is enabled. +- Fixed OSC colors for Double Trouble. +- Stats for the chatbox is now stored in the correct location. +- Reworked the Automatic Updates. +- Updated Traditional Chinese localization (Thank you @XoF-eLtTiL) \ No newline at end of file diff --git a/Localization/Language/en-US.json b/Localization/Language/en-US.json index f207ed0..326ad00 100644 --- a/Localization/Language/en-US.json +++ b/Localization/Language/en-US.json @@ -60,6 +60,7 @@ "MAIN.ENTRY_PLAYERS": "Players in room:", "MAIN.ENTRY_MAP": "Map:", "MAIN.ENTRY_WARNING": "$$SAVE.TAG_X$$ Warning!! This save was generated before you loaded your Save Code.\nIf you are not a new player, go back one save and load that instead.", + "MAIN.ENTRY_COPIED": "COPIED TO CLIPBOARD!", "ROUND_TYPE.INTERMISSION": "Intermission", "ROUND_TYPE.CLASSIC": "Classic", @@ -91,6 +92,7 @@ "SAVE.TAG_D": "🔌", "SAVE.TAG_L": "💀", "SAVE.TAG_X": "❗", + "SAVE.TAG_C": "✅", "SETTINGS.CHECK_UPDATE": "Check For Updates", "SETTINGS.OPEN_DATA_BTN": "Data", @@ -200,9 +202,19 @@ "SETTINGS.XSOVERLAY.MESSAGE": "ToN: Save Data Stored", "SETTINGS.XSOVERLAY.TOGGLE": "ToN: Notifications Enabled", - "SETTINGS.PLAYAUDIO": "Play Audio ({0})", - "SETTINGS.PLAYAUDIO.TT": "Double click to select custom audio file.\nRight click to reset back to 'default.wav'", - "SETTINGS.PLAYAUDIO.TITLE": "Select Custom Audio", + + "SETTINGS.PLAYAUDIO.TITLE": "Select Custom Audio File", + + "SETTINGS.PLAYAUDIOSAVE": "Play Audio on Save", + "SETTINGS.PLAYAUDIOSAVE.TT": "Plays an audio when a new save code is created.", + + "SETTINGS.PLAYAUDIOCOPY": "Play Audio on Copy", + "SETTINGS.PLAYAUDIOCOPY.TT": "Plays an audio when you copy a save code entry.", + + "SETTINGS.PLAYAUDIO_SELECT": "(Select Audio File)", + "SETTINGS.PLAYAUDIO_SELECT.TT": "Select a custom audio file on your computer for this notification.", + "SETTINGS.PLAYAUDIO_SELECT.ALT": "$$SETTINGS.PLAYAUDIO_SELECT.TT$$\nRight click this button to reset this notification audio back to default.", + "SETTINGS.GROUP.TIME_FORMAT": "Time Formatting", "SETTINGS.USE24HOUR": "24 Hour Time", diff --git a/Localization/Language/zh-TW.json b/Localization/Language/zh-TW.json index 29a14c9..713b4bf 100644 --- a/Localization/Language/zh-TW.json +++ b/Localization/Language/zh-TW.json @@ -6,6 +6,7 @@ "EDIT.DELETE": "刪除", "EDIT.OK": "確定", "EDIT.CANCEL": "取消", + "EDIT.INSERT_TEMPLATE": "導入範本參數", "MESSAGE.WRITE_SETTINGS_ERROR": "嘗試將你的設定寫入檔案時發生錯誤\n\n請確保該程式具備在當前資料夾寫入檔案的權限", "MESSAGE.COPY_FILES_ERROR": "嘗試將你的文件複製到選擇位置時發生錯誤\n\n請確保該程式具備向目標位置寫入檔案的權限\n路徑: {0}", @@ -62,11 +63,11 @@ "ROUND_TYPE.INTERMISSION": "中場休息 (Intermission)", "ROUND_TYPE.CLASSIC": "經典 (Classic)", - "ROUND_TYPE.FOG": "農霧 (Fog)", + "ROUND_TYPE.FOG": "濃霧 (Fog)", "ROUND_TYPE.PUNISHED": "懲罰 (Punished)", "ROUND_TYPE.SABOTAGE": "破壞 (Sabotage)", "ROUND_TYPE.CRACKED": "崩裂 (Cracked)", - "ROUND_TYPE.BLOODBATH": "血浴 (Bloodbath)", + "ROUND_TYPE.BLOODBATH": "血戰 (Bloodbath)", "ROUND_TYPE.DOUBLE_TROUBLE": "雙重麻煩 (Double Trouble)", "ROUND_TYPE.EX": "EX (EX)", "ROUND_TYPE.GHOST": "幽靈 (Ghost)", @@ -184,6 +185,8 @@ "SETTINGS.OSCSENDCHATBOX_EDIT.TT": "自訂要顯示在聊天框中的訊息模板", "SETTINGS.OSCSENDCOLOR": "發送怪物顏色", "SETTINGS.OSCSENDCOLOR.TT": "以 HSV 形式發送當前的怪物顏色\n顏色將作為 3 個浮點參數發送:\n- ToN_ColorH (色相)\n- ToN_ColorS (飽和度)\n- ToN_ColorV (值)", + "SETTINGS.OSCSENDCOLORFORMAT": "變更顏色格式", + "SETTINGS.OSCSENDCOLORFORMAT.TT": "交替使用 OSC 傳送值的目前顏色格式。\n可用格式為 HSV、HSL、RGB 及 RGB32。", "SETTINGS.OSCDAMAGEDEVENT": "發送傷害事件", "SETTINGS.OSCDAMAGEDEVENT.TT": "向整數參數發送傷害事件,數字表示接收到的傷害值\n該值將發送到名為 'ToN_Damaged' 的參數,然後在間隔後重設為 0\n如果玩家死亡,傷害值將為 255,表示最大痛苦", "SETTINGS.OSCDAMAGEDEVENT_EDIT": "(設定間隔)", @@ -207,6 +210,8 @@ "SETTINGS.INVERTMD": "反轉月份/日期", "SETTINGS.SHOWDATE": "右側面板日期", "SETTINGS.SHOWDATE.TT": "右側面板的條目將顯示完整日期", + "SETTINGS.SHOWTIME": "右側面板時間", + "SETTINGS.SHOWTIME.TT": "右側面板的條目將顯示完整時間", "SETTINGS.GROUP.STYLE": "樣式", "SETTINGS.COLORFULOBJECTIVES": "多彩目標", @@ -220,7 +225,7 @@ "OBJECTIVES.TITLE": "ToN 目標 (ToN Objectives)", "OBJECTIVES.EVENT_ITEMS_UNLOCKS": "事件物品解鎖 (Event Items Unlocks)", "OBJECTIVES.SEALED_SWORD": "封印之劍 (Sealed Sword)", - "OBJECTIVES.SEALED_SWORD.TT": "在博物館中找到用閃電工具打破保險櫃 (Found in Museum. Break case with a stun tool.)", + "OBJECTIVES.SEALED_SWORD.TT": "在博物館中找到用擊暈道具打破保險櫃 (Found in Museum. Break case with a stun tool.)", "OBJECTIVES.GRAN_FAUST": "格蘭·福斯特 (Gran Faust)", "OBJECTIVES.GRAN_FAUST.TT": "使用 '$$OBJECTIVES.SEALED_SWORD$$' 生存下來,抵抗阿爾庫斯 (Survive Arkus with '$$OBJECTIVES.SEALED_SWORD$$'.)", "OBJECTIVES.DIVINE_AVENGER": "神聖復仇者 (Divine Avenger)", @@ -228,9 +233,9 @@ "OBJECTIVES.MAXWELL": "麥克斯威爾 (Maxwell)", "OBJECTIVES.MAXWELL.TT": "在迷宮中找到(每回合生成一次) (Found in Its Maze. (spawns once per round))", "OBJECTIVES.ROCK": "石頭 (Rock)", - "OBJECTIVES.ROCK.TT": "生存下來對抗融合駕駛員 (Survive Fusion Pilot.)", + "OBJECTIVES.ROCK.TT": "Fusion Pilot 手中生存下來 (Survive Fusion Pilot.)", "OBJECTIVES.ILLUMINA": "光明 (Illumina)", - "OBJECTIVES.ILLUMINA.TT": "生存下來對抗極樂 (Survive Bliss.)", + "OBJECTIVES.ILLUMINA.TT": "在 Bliss 中生存下來 (Survive Bliss.)", "OBJECTIVES.REDBULL": "紅牛 (Redbull)", "OBJECTIVES.REDBULL.TT": "生存下來對抗羅布蘭德 (Survive Roblander.)", "OBJECTIVES.OMORI_PLUSH": "小小的 OMORI (Omori Plush)", @@ -241,17 +246,17 @@ "OBJECTIVES.RED_MEDKIT": "紅色醫療包 (Red Medkit)", "OBJECTIVES.RED_MEDKIT.TT": "使用醫療包抵抗病毒生存 (Survive Virus with Medkit.)", "OBJECTIVES.PSYCHO_COIL": "瘋狂線圈 (Psycho Coil)", - "OBJECTIVES.PSYCHO_COIL.TT": "使用發光線圈在心靈噩夢中生存下來 (Survive Psychosis with Glow Coil.)", + "OBJECTIVES.PSYCHO_COIL.TT": "使用發光線圈在 Psychosis 中生存下來 (Survive Psychosis with Glow Coil.)", "OBJECTIVES.BLOODY_TELEPORTER": "血腥傳送器 (Bloody Teleporter)", - "OBJECTIVES.BLOODY_TELEPORTER.TT": "在血浴回合中使用傳送器生存 (Survive a Bloodbath round with Teleporter.)", + "OBJECTIVES.BLOODY_TELEPORTER.TT": "在血戰回合中使用傳送器生存 (Survive a Bloodbath round with Teleporter.)", "OBJECTIVES.PALE_SUITCASE": "蒼白的手提箱 (Pale Suitcase)", "OBJECTIVES.PALE_SUITCASE.TT": "在精英回合中使用傳送器生存 (Survive an Alternate round with Teleporter.)", "OBJECTIVES.THORN_HACKER": "荊棘駭客 (Thorn Hacker)", "OBJECTIVES.THORN_HACKER.TT": "在潘多拉中使用傳送器生存 (Survive Pandora with Teleporter.)", "OBJECTIVES.BLOODY_COIL": "血腥線圈 (Bloody Coil)", - "OBJECTIVES.BLOODY_COIL.TT": "在血浴回合中使用速度線圈生存 (Survive a Bloodbath round with Speed Coil.)", + "OBJECTIVES.BLOODY_COIL.TT": "在血戰回合中使用速度線圈生存 (Survive a Bloodbath round with Speed Coil.)", "OBJECTIVES.BLOODY_BAT": "血腥球棒 (Bloody Bat)", - "OBJECTIVES.BLOODY_BAT.TT": "在血浴回合中使用金屬棒生存 (Survive a Bloodbath round with Metal Bat.)", + "OBJECTIVES.BLOODY_BAT.TT": "在血戰回合中使用金屬棒生存 (Survive a Bloodbath round with Metal Bat.)", "OBJECTIVES.METAL_PIPE": "金屬管 (Metal Pipe)", "OBJECTIVES.METAL_PIPE.TT": "在精英回合中使用金屬棒生存 (Survive an Alternate round with Metal Bat.)", "OBJECTIVES.COLORABLE_BAT": "彩色球棒 (Colorable Bat)", @@ -266,7 +271,7 @@ "OBJECTIVES.SNOWY_SPEED_COIL": "雪地速度線圈 (Snowy Speed Coil)", "OBJECTIVES.SNOWY_SPEED_COIL.TT": "雪中有你想要的東西 (There's something in the snow for you.)", "OBJECTIVES.TORCH_OF_OBSESSION": "痴謎之火把 (Torch Of Obsession)", - "OBJECTIVES.TORCH_OF_OBSESSION.TT": "生存下來對抗寒冷之夜 (Survive the Cold Night.)", + "OBJECTIVES.TORCH_OF_OBSESSION.TT": "在寒冷之夜生存下來 (Survive the Cold Night.)", "STATS.TITLE": "ToN 統計追蹤器", "STATS.SHOW_LOBBY": "顯示房間統計", diff --git a/Models/AppSettings.cs b/Models/AppSettings.cs index b6810af..ed20606 100644 --- a/Models/AppSettings.cs +++ b/Models/AppSettings.cs @@ -74,13 +74,14 @@ static Settings() { /// /// Play notification audio when a new save is detected. /// - public bool PlayAudio { get; set; } - public bool PlayAudioCopy { get; set; } + public bool PlayAudioSave { get; set; } = true; + public bool PlayAudioCopy { get; set; } = true; /// /// Custom audio location, must be .wav /// public string? AudioLocation { get; set; } + public string? AudioCopyLocation { get; set; } /// /// Saves a list of players that were in the same room as you at the time of the save. diff --git a/Models/Entry.cs b/Models/Entry.cs index 111a785..552405f 100644 --- a/Models/Entry.cs +++ b/Models/Entry.cs @@ -42,12 +42,15 @@ internal class Entry { static string TextPlayers = "Players in room:"; static string TextMap = "Map:"; static string TextWarn = "Warning!! You forgot to load your save code."; + public static string TextCopied = TextTagC + Separator + "COPIED TO CLIPBOARD!"; static string TextTagR = "🔄"; static string TextTagW = "🏆"; static string TextTagD = "🔌"; static string TextTagL = "💀"; static string TextTagX = "⚠️"; + static string TextTagC = "✅"; + const string Separator = " | "; internal static void LocalizeContent() { TextNote = LANG.S("MAIN.ENTRY_NOTE") ?? "Note:"; @@ -56,12 +59,16 @@ internal static void LocalizeContent() { TextPlayers = LANG.S("MAIN.ENTRY_PLAYERS") ?? "Players in room:"; TextMap = LANG.S("MAIN.ENTRY_MAP") ?? "Map:"; TextWarn = LANG.S("MAIN.ENTRY_WARNING") ?? "Warning!! You forgot to load your save code."; + TextCopied = LANG.S("MAIN.ENTRY_COPIED") ?? "COPIED TO CLIPBOARD!"; TextTagR = LANG.S("SAVE.TAG_R") ?? "🔄"; TextTagW = LANG.S("SAVE.TAG_W") ?? "🏆"; TextTagD = LANG.S("SAVE.TAG_D") ?? "🔌"; TextTagL = LANG.S("SAVE.TAG_L") ?? "💀"; TextTagX = LANG.S("SAVE.TAG_X") ?? "⚠️"; + TextTagC = LANG.S("SAVE.TAG_C") ?? "✅"; + + TextCopied = TextTagC + Separator + TextCopied; } public string Note = string.Empty; @@ -98,7 +105,6 @@ public Entry(string content, DateTime timestamp) public override string ToString() { - const string separator = " | "; StringBuilder sb = new StringBuilder(); if (Settings.Get.SaveRoundInfo && Settings.Get.ShowWinLose) { @@ -112,13 +118,13 @@ public override string ToString() case ToNRoundResult.X: sb.Append(TextTagX); break; } - sb.Append(separator); + sb.Append(Separator); } string? dateFormat = EntryDate.GetDateFormat(true); if (!string.IsNullOrEmpty(dateFormat)) { sb.Append(Timestamp.ToString(dateFormat)); - sb.Append(separator); + sb.Append(Separator); } if (!string.IsNullOrEmpty(Note)) diff --git a/Models/GitHubRelease.cs b/Models/GitHubRelease.cs index 5ff115a..95c5902 100644 --- a/Models/GitHubRelease.cs +++ b/Models/GitHubRelease.cs @@ -1,4 +1,5 @@ using Newtonsoft.Json; +using static ToNSaveManager.Models.GitHubRelease; namespace ToNSaveManager.Models { @@ -17,7 +18,7 @@ internal class GitHubRelease public string body { get; set; } = string.Empty; public DateTime created_at { get; set; } public DateTime published_at { get; set; } - public Asset[] assets { get; set; } = new Asset[0]; + public Asset[] assets { get; set; } = Array.Empty(); internal class Asset { @@ -49,4 +50,32 @@ internal class Asset } } } + + internal class GitHubUpdate { + internal static GitHubRelease? Release; + internal static Asset? Asset; + + internal static bool Update { get; set; } + + internal static void Set(GitHubRelease release, GitHubRelease.Asset asset) { + Release = release; + Asset = asset; + Update = true; + + List
openForms = new List(); + + foreach (Form f in Application.OpenForms) { + openForms.Add(f); + } + + foreach (Form f in openForms) { + f.Close(); + } + } + + internal static void Start() { + if (!Update || Release == null || Asset == null) return; + Updater.Start(Release, Asset); + } + } } diff --git a/Models/Index/TerrorMatrix.cs b/Models/Index/TerrorMatrix.cs index 60805a9..767d1b1 100644 --- a/Models/Index/TerrorMatrix.cs +++ b/Models/Index/TerrorMatrix.cs @@ -157,11 +157,15 @@ public TerrorMatrix(string roundType, params int[] indexes) { dupes.Clear(); } - Terrors = new ToNIndex.TerrorInfo[indexes.Length]; + Terrors = new ToNIndex.TerrorInfo[3]; for (int i = 0; i < Terrors.Length; i++) { - ToNIndex.TerrorInfo info = new(indexes[i], i > 1 && RoundType == ToNRoundType.Midnight ? ToNIndex.TerrorGroup.Alternates : ToNIndex.TerrorGroup.Terrors); - if (i == StartIndex && lvl > 1) info.Level = lvl; - Terrors[i] = info; + if (i < TerrorCount) { + ToNIndex.TerrorInfo info = new(indexes[i], i > 1 && RoundType == ToNRoundType.Midnight ? ToNIndex.TerrorGroup.Alternates : ToNIndex.TerrorGroup.Terrors); + if (i == StartIndex && lvl > 1) info.Level = lvl; + Terrors[i] = info; + } else { + Terrors[i] = Terrors[0]; + } } break; @@ -212,9 +216,10 @@ private Color GetDisplayColor() { RoundType != ToNRoundType.Fog_Alternate) { Color c = Color.White; int R = 0, G = 0, B = 0, L = 0; - for (int i = StartIndex; i < TerrorCount; i++) { + for (int i = 0; i < Terrors.Length; i++) { if (i > 2) break; + if (Terrors[i].IsEmpty) continue; c = Terrors[i].Value.Color; R += c.R; diff --git a/Models/SaveData.cs b/Models/SaveData.cs index 6cb9ce6..8ac4be9 100644 --- a/Models/SaveData.cs +++ b/Models/SaveData.cs @@ -27,7 +27,6 @@ internal static string Destination m_Destination = value; string? dirName = Path.GetDirectoryName(m_Destination); History.Destination = Path.Combine(dirName ?? "./", "Database"); - ToNStats.Destination = dirName ?? "./"; } } diff --git a/Models/Stats/ToNStats.cs b/Models/Stats/ToNStats.cs index 526b158..3db1589 100644 --- a/Models/Stats/ToNStats.cs +++ b/Models/Stats/ToNStats.cs @@ -59,13 +59,9 @@ internal static class ToNStats { static readonly LoggerSource Log = new LoggerSource(nameof(ToNStats)); #region Settings - private static string m_Destination = "Stats.json"; + private static string? m_Destination = null; internal static string Destination { - get => m_Destination; - set { - Log.Print("Setting destination: " + value); - m_Destination = Path.Combine(value, "Stats.json"); - } + get => m_Destination ?? (m_Destination = Path.Combine(Program.DataLocation, "Stats.json")); } #endregion diff --git a/Program.cs b/Program.cs index ffbda2f..29f765f 100644 --- a/Program.cs +++ b/Program.cs @@ -17,6 +17,10 @@ internal static class Program internal const string ProgramName = "ToNSaveManager"; internal static readonly string ProgramDirectory = AppContext.BaseDirectory ?? string.Empty; + internal static readonly string ProgramLocation = Path.Combine(ProgramDirectory, ProgramFile); + internal static readonly string ProgramLocationTemporary = Path.Combine(ProgramDirectory, "__" + ProgramFile); + internal const string ProgramFile = ProgramName + ".exe"; + internal static readonly string DataLocation = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), ProgramName); internal static readonly string LegacyDataLocation = Path.Combine(LogWatcher.GetVRChatDataLocation(), ProgramName); @@ -52,9 +56,10 @@ static void Main(string[] args) Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture; - LANG.Initialize(); + if (!Directory.Exists(DataLocation)) Directory.CreateDirectory(DataLocation); - UpdateWindow.RunPostUpdateCheck(args); + LANG.Initialize(); + Updater.CheckPostUpdate(args); if (CheckMutex()) { @@ -67,22 +72,27 @@ static void Main(string[] args) Application.SetCompatibleTextRenderingDefault(true); InitializeFont(); - Application.ApplicationExit += delegate { - Logger.Log("Disposing used resources..."); - FontCollection.Dispose(); - DefaultFont?.Dispose(); - ReleaseMutex(); - Logger.Log("Saving before app exit..."); - MainWindow.SaveData.Export(); - StatsWindow.WriteChanges(); - Logger.Log("Done."); - }; - - if (!Directory.Exists(DataLocation)) Directory.CreateDirectory(DataLocation); + MainWindow.Started = false; if (!StartCheckForUpdate()) { + Application.ApplicationExit += OnApplicationExit; Application.Run(new MainWindow()); } + + // Check when all forms close + Logger.Info("All windows are closed..."); + GitHubUpdate.Start(); + } + + private static void OnApplicationExit(object? sender, EventArgs e) { + Logger.Log("Disposing used resources..."); + FontCollection.Dispose(); + DefaultFont?.Dispose(); + ReleaseMutex(); + Logger.Log("Saving before app exit..."); + MainWindow.SaveData.Export(); + StatsWindow.WriteChanges(); + Logger.Log("Done."); } static readonly PrivateFontCollection FontCollection = new PrivateFontCollection(); @@ -132,9 +142,6 @@ static void InitializeFont() /// Shows a message if there's no updates available. internal static bool StartCheckForUpdate(bool showUpToDate = false) { -#if DEBUG - return false; -#else Version? currentVersion = GetVersion(); if (currentVersion == null) return false; // No current version? @@ -161,8 +168,7 @@ internal static bool StartCheckForUpdate(bool showUpToDate = false) DialogResult result = MessageBox.Show((LANG.S("MESSAGE.UPDATE_AVAILABLE") ?? "A new update have been released on GitHub.\n\nWould you like to automatically download and update to the new version?") + body, LANG.S("MESSAGE.UPDATE_AVAILABLE.TITLE") ?? "New update available", MessageBoxButtons.YesNo, MessageBoxIcon.Information); if (result == DialogResult.Yes) { - UpdateWindow updateWindow = new UpdateWindow(release, asset); - updateWindow.ShowDialog(); + GitHubUpdate.Set(release, asset); return true; } else if (!showUpToDate) { @@ -175,7 +181,6 @@ internal static bool StartCheckForUpdate(bool showUpToDate = false) } return false; -#endif } internal static bool CreateFileBackup(string filePath) diff --git a/Resources/notification_copy.wav b/Resources/notification_copy.wav index c28679c..ea5bc69 100644 Binary files a/Resources/notification_copy.wav and b/Resources/notification_copy.wav differ diff --git a/Resources/notification_secret.wav b/Resources/notification_secret.wav index 9a95535..d035eab 100644 Binary files a/Resources/notification_secret.wav and b/Resources/notification_secret.wav differ diff --git a/ToNSaveManager.csproj b/ToNSaveManager.csproj index 21c6de4..368ddc6 100644 --- a/ToNSaveManager.csproj +++ b/ToNSaveManager.csproj @@ -12,9 +12,19 @@ 7.0 SystemAware true + + true $(DefineConstants)$(FeatureFlags.Replace("#",";")) + + embedded + + + + embedded + + @@ -49,6 +59,7 @@ + diff --git a/Updater.cs b/Updater.cs new file mode 100644 index 0000000..a49fc2c --- /dev/null +++ b/Updater.cs @@ -0,0 +1,237 @@ +using System.Diagnostics; +using System.Runtime.InteropServices; +using ToNSaveManager.Models; +using ICSharpCode.SharpZipLib.Zip; + +namespace ToNSaveManager { + internal static class Updater { + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + static extern bool AllocConsole(); + + internal class UpdateProgressBar : IProgress { + string start = "["; + string end = "]"; + char fill = '#'; + char back = '-'; + + int top = 0; + int left = 0; + int length = 0; + + int full_len = 0; + + string final = "Done."; + + internal UpdateProgressBar (int length = 20) { + this.top = Console.CursorTop; + this.left = Console.CursorLeft; + this.length = length; + } + + public void Start() { + Console.CursorVisible = false; + } + + public void Report(float value) { + lock (start) { + Console.SetCursorPosition(left, top); + + + int c = (int)Math.Round(value * length); + Console.Write(start); + Console.Write(new string(fill, c).PadRight(length, back)); + Console.Write(end); + Console.Write(' '); + + float percent = value * 100; + Console.Write(percent.ToString("0.00").PadLeft(6, ' ')); + Console.Write('%'); + + full_len = Console.CursorLeft - left; + } + } + + public void Done() { + Report(1); + Console.SetCursorPosition(left, top); + Console.WriteLine((start + final + end).PadRight(full_len)); + Console.CursorVisible = true; + } + } + + const string POST_UPDATE_ARG = "--clean-update"; + internal static void Start(GitHubRelease release, GitHubRelease.Asset asset) { + AllocConsole(); + + Console.Title = "ToNSaveManager - Updating " + release.name; + + string TempFileName = release.tag_name + ".temp.zip"; + string TempFileLocation = Path.Combine(Program.ProgramDirectory, TempFileName); + + try { + if (File.Exists(TempFileLocation)) + File.Delete(TempFileLocation); + + Console.Write($"Downloading '{asset.name}' . . . "); + + UpdateProgressBar progress = new UpdateProgressBar(); + progress.Start(); + string downloadUrl = asset.browser_download_url; + + using (HttpClient client = new HttpClient()) { + client.Timeout = TimeSpan.FromMinutes(5); + + using (var file = new FileStream(TempFileLocation, FileMode.Create, FileAccess.Write, FileShare.None)) { + client.Download(downloadUrl, file, progress); + } + } + + progress.Done(); + + // Move current executable + Logger.Info("Moving from: " + Program.ProgramLocation); + Logger.Info("Moving to: " + Program.ProgramLocationTemporary); + File.Move(Program.ProgramLocation, Program.ProgramLocationTemporary, true); + + Console.WriteLine("Extracting update files . . ."); + Logger.Info("Extracting: " + TempFileLocation); + FastZip zip = new FastZip(); + zip.ExtractZip(TempFileLocation, Program.ProgramDirectory, null); + + Console.WriteLine("Finishing update . . ."); + File.Delete(TempFileLocation); // .zip file cleanup + + Console.WriteLine("Update complete, restarting . . ."); + + Program.ReleaseMutex(); // Release mutex so downloaded app opens properly + // Start new process with --post-update + ProcessStartInfo processInfo = new ProcessStartInfo(Program.ProgramFile, POST_UPDATE_ARG); + Process.Start(processInfo); + // Exit this app + Application.Exit(); + return; + } catch (Exception ex) { + Logger.Error("Automatic update failed."); + Logger.Error(ex); + + + MessageBox.Show("Automatic update has failed. Try using the file 'update.bat' instead.\nPlease report this error to on the GitHub page.\n\n" + ex, "Update Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + + if (File.Exists(Program.ProgramLocationTemporary)) { + File.Move(Program.ProgramLocationTemporary, Program.ProgramLocation, true); + } + } + + const string LEGACY_POST_UPDATE_ARG = "--post-update"; + internal static void CheckPostUpdate(string[] args) { + bool updateLegacy = Program.ContainsArg(LEGACY_POST_UPDATE_ARG); + if (!updateLegacy && !Program.ContainsArg(POST_UPDATE_ARG)) return; + Logger.Info("Running post-update cleanup."); + + try { + using (Process currentProcess = Process.GetCurrentProcess()) { + Process[] processes = Process.GetProcessesByName(currentProcess.ProcessName); + foreach (Process process in processes) { + using (process) { + if (process.Id != currentProcess.Id) { + Logger.Info("Killing old running process: " + process.Id); + process.Kill(); + process.WaitForExit(); + } + } + } + } + + if (updateLegacy) { + // Run legacy cleanup, old to new transition + Logger.Info("Updated from legacy version, running legacy cleanup..."); + + try { + string legacyTempFiles = Path.Combine(Program.ProgramDirectory, ".temp_files"); + if (Directory.Exists(legacyTempFiles)) { + Logger.Info("Deleting legacy temp files: " + legacyTempFiles); + Directory.Delete(legacyTempFiles, true); + } + } catch (Exception ex) { + Logger.Error(ex); + } + + try { + Logger.Info("Deleting unused legacy files."); + var unusedFiles = Directory.GetFiles(Program.ProgramDirectory) + .Where(f => f.EndsWith(".pdb") || f.EndsWith(".dll")); + + foreach (string file in unusedFiles) { + try { + Logger.Info("Deleting unused file: " + file); + File.Delete(file); + } catch { } + } + } catch (Exception ex) { + Logger.Error(ex); + } + } + + if (File.Exists(Program.ProgramLocationTemporary)) { + Logger.Info("Deleting old program files."); + File.Delete(Program.ProgramLocationTemporary); + } + + Logger.Info("Post-update success."); + MessageBox.Show("Successfully updated to version " + Program.GetVersion(), Program.ProgramName, MessageBoxButtons.OK, MessageBoxIcon.Information); + } catch (Exception ex) { + Logger.Error("Failed to run post-update."); + Logger.Error(ex); + + MessageBox.Show("Failed to run post-update.\nPlease report this issue on the GitHub page.\n\n" + ex, "Update Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + #region Extensions + static void CopyTo(this Stream source, Stream destination, int bufferSize, IProgress? progress = null) { + ArgumentNullException.ThrowIfNull(source); + ArgumentNullException.ThrowIfNull(destination); + ArgumentOutOfRangeException.ThrowIfNegative(bufferSize); + + if (!source.CanRead) + throw new ArgumentException("Has to be readable", nameof(source)); + if (!destination.CanWrite) + throw new ArgumentException("Has to be writable", nameof(destination)); + + var buffer = new byte[bufferSize]; + long totalBytesRead = 0; + int bytesRead; + while ((bytesRead = source.Read(buffer, 0, buffer.Length)) != 0) { + destination.Write(buffer, 0, bytesRead); + totalBytesRead += bytesRead; + progress?.Report(totalBytesRead); + } + } + + static void Download(this HttpClient client, string requestUri, Stream destination, IProgress? progress = null) { + // Get the http headers first to examine the content length + using (var response = client.GetAsync(requestUri, HttpCompletionOption.ResponseHeadersRead).Result) { + var contentLength = response.Content.Headers.ContentLength; + + using (var download = response.Content.ReadAsStream()) { + + // Ignore progress reporting when no progress reporter was + // passed or when the content length is unknown + if (progress == null || !contentLength.HasValue) { + download.CopyTo(destination); + return; + } + + // Convert absolute progress (bytes downloaded) into relative progress (0% - 100%) + var relativeProgress = new Progress(totalBytes => progress.Report((float)totalBytes / contentLength.Value)); + // Use extension method to report progress while downloading + download.CopyTo(destination, 81920, relativeProgress); + progress.Report(1); + } + } + } + #endregion + } +} diff --git a/Utils/Audio/NotificationManager.cs b/Utils/Audio/NotificationManager.cs new file mode 100644 index 0000000..4a3ebc6 --- /dev/null +++ b/Utils/Audio/NotificationManager.cs @@ -0,0 +1,70 @@ +using System.Media; +using ToNSaveManager.Models; + +namespace ToNSaveManager.Utils { + internal static class NotificationManager { + // Get default notification in the embeded resources + static readonly Stream? SecretSaveStream = Program.GetEmbededResource("notification_secret.wav"); + static readonly Stream? DefaultSaveStream = Program.GetEmbededResource("notification.wav"); + static readonly Stream? DefaultCopyStream = Program.GetEmbededResource("notification_copy.wav"); + + static readonly SoundPlayer StreamPlayer = new SoundPlayer(); + static readonly SoundPlayer AudioPlayer = new SoundPlayer(); + + internal static void Reset() { + StreamPlayer.Stop(); + AudioPlayer.Stop(); + } + + internal static void PlaySave() { + if (StartPlaying(Settings.Get.AudioLocation, Random.Shared.Next(0,127) == 87 ? SecretSaveStream : DefaultSaveStream)) { + Settings.Get.AudioLocation = null; + Settings.Export(); + } + } + + internal static void PlayCopy() { + if (StartPlaying(Settings.Get.AudioCopyLocation, DefaultCopyStream)) { + Settings.Get.AudioCopyLocation = null; + Settings.Export(); + } + } + + static bool StartPlaying(string? fileName, Stream? fallback) { + if (!string.IsNullOrEmpty(fileName)) { + try { + if (File.Exists(fileName)) { + AudioPlayer.Stop(); + AudioPlayer.SoundLocation = fileName; + AudioPlayer.Play(); + return false; + } + + Logger.Warning("Custom audio location is missing: " + fileName); + } catch (Exception ex) { + Logger.Error("Error trying to play custom audio."); + Logger.Error(ex); + } + + return true; + } + + if (fallback != null) { + try { + StreamPlayer.Stop(); + StreamPlayer.Stream = null; + + fallback.Position = 0; + StreamPlayer.Stream = fallback; + + StreamPlayer.Play(); + } catch (Exception ex) { + Logger.Error("Exception trying to play default audio."); + Logger.Error(ex); + } + } + + return false; + } + } +} diff --git a/Utils/LogParser/ToNLogContext.cs b/Utils/LogParser/ToNLogContext.cs index c24b65c..39afae7 100644 --- a/Utils/LogParser/ToNLogContext.cs +++ b/Utils/LogParser/ToNLogContext.cs @@ -40,7 +40,10 @@ public override void Enter(string name, DateTime date) { base.Enter(name, date); HasLoadedSave = false; - if (Settings.Get.AutoCopy && Settings.Get.CopyOnJoin && MainWindow.Started) MainWindow.Instance?.CopyRecent(true); + if (Settings.Get.AutoCopy && Settings.Get.CopyOnJoin && MainWindow.Started) { + MainWindow.Instance?.CopyRecent(true); + NotificationManager.PlayCopy(); + } if (IsRecent) ToNGameState.ClearStates(); } public override void Enter(string instanceID, bool isHomeWorld) { diff --git a/Windows/Controls/TooltipUtil.cs b/Windows/Controls/TooltipUtil.cs index 52d6976..f060f2a 100644 --- a/Windows/Controls/TooltipUtil.cs +++ b/Windows/Controls/TooltipUtil.cs @@ -24,5 +24,10 @@ public static void Set(Control control, string? text) Instance.SetToolTip(control, text); Instance.Active = true; } + + public static void Show(Control control, string? text) { + Set(control, text); + Instance.Show(text, control); + } } } diff --git a/Windows/MainWindow.cs b/Windows/MainWindow.cs index 8198f8e..3a96006 100644 --- a/Windows/MainWindow.cs +++ b/Windows/MainWindow.cs @@ -1,5 +1,4 @@ using System.Diagnostics; -using System.Media; using ToNSaveManager.Extensions; using ToNSaveManager.Models; using ToNSaveManager.Utils; @@ -29,6 +28,10 @@ public MainWindow() { InitializeComponent(); listBoxKeys.FixItemHeight(); listBoxEntries.FixItemHeight(); + + JustCopiedTimer.Interval = 1000; + JustCopiedTimer.Tick += JustCopiedTimer_Tick; + Instance = this; } #endregion @@ -280,6 +283,8 @@ private void listBoxEntries_MouseDown(object sender, MouseEventArgs e) { } } + int JustCopiedIndex = -1; + System.Windows.Forms.Timer JustCopiedTimer = new System.Windows.Forms.Timer(); private void listBoxEntries_MouseUp(object sender, MouseEventArgs e) { bool isRight = e.Button == MouseButtons.Right; if (e.Button == MouseButtons.Left || isRight) { @@ -294,13 +299,36 @@ private void listBoxEntries_MouseUp(object sender, MouseEventArgs e) { if (listBoxEntries.SelectedItem != null) { Entry entry = (Entry)listBoxEntries.SelectedItem; entry.CopyToClipboard(); - MessageBox.Show(LANG.S("MESSAGE.COPY_TO_CLIPBOARD") ?? "Copied to clipboard!\n\nYou can now paste the code in game.", LANG.S("MESSAGE.COPY_TO_CLIPBOARD.TITLE") ?? "Copied", MessageBoxButtons.OK, MessageBoxIcon.Information); + + SetJustCopied(index); + + if (Settings.Get.PlayAudioCopy) + NotificationManager.PlayCopy(); } listBoxEntries.SelectedIndex = -1; } } + private void SetJustCopied(int index) { + JustCopiedTimer.Stop(); + JustCopiedIndex = index; + + if (JustCopiedIndex > -1) { + listBoxEntries.Refresh(); + JustCopiedTimer.Start(); + } + } + + private void JustCopiedTimer_Tick(object? sender, EventArgs e) { + JustCopiedTimer.Stop(); + + if (JustCopiedIndex > -1) { + JustCopiedIndex = -1; + listBoxEntries.Refresh(); + } + } + private void listBoxEntries_DrawItem(object sender, DrawItemEventArgs e) { if (e.Index < 0) return; @@ -310,6 +338,10 @@ private void listBoxEntries_DrawItem(object sender, DrawItemEventArgs e) { ListBox listBox = (ListBox)sender; string itemText = listBox.Items[e.Index].ToString() ?? string.Empty; + if (e.Index == JustCopiedIndex && listBox == listBoxEntries) { + itemText = Entry.TextCopied; + } + int maxWidth = e.Bounds.Width; TextRenderer.DrawText(e.Graphics, GetTruncatedText(itemText, listBox.Font, maxWidth), listBox.Font, e.Bounds, e.ForeColor, TextFormatFlags.VerticalCenter | TextFormatFlags.NoPrefix); @@ -488,36 +520,29 @@ private void splitContainer1_SplitterMoved(object sender, SplitterEventArgs e) { #region Form Methods #region Notifications static readonly XSOverlay XSOverlay = new XSOverlay(); - static readonly SoundPlayer CustomNotificationPlayer = new SoundPlayer(); - static readonly SoundPlayer DefaultNotificationPlayer = new SoundPlayer(); - - static readonly Stream? DefaultAudioStream = // Get default notification in the embeded resources - Program.GetEmbededResource("notification.wav"); - - static readonly Stream? SecretAudioStream = - Program.GetEmbededResource("notification_secret.wav"); - - static readonly Stream? CopiedAudioStream = - Program.GetEmbededResource("notification_copy.wav"); internal static void ResetNotification() { - CustomNotificationPlayer.Stop(); - DefaultNotificationPlayer.Stop(); + NotificationManager.Reset(); } - internal static void PlayNotification(bool forceDefault = false) { - if ((!Started || !Settings.Get.PlayAudio) && !forceDefault) return; + internal static void PlayCopyNotification() { + if (!Started || !Settings.Get.PlayAudioCopy) return; try { - if (!forceDefault && !string.IsNullOrEmpty(Settings.Get.AudioLocation) && File.Exists(Settings.Get.AudioLocation)) { - CustomNotificationPlayer.SoundLocation = Settings.Get.AudioLocation; - CustomNotificationPlayer.Play(); - return; - } + NotificationManager.PlayCopy(); + } catch (Exception ex) { + Logger.Error(ex); + } + } + + internal static void PlaySaveNotification() { + if (!Started || !Settings.Get.PlayAudioSave) return; - DefaultNotificationPlayer.Stream = Random.Shared.Next(0, 100) == 87 ? SecretAudioStream : DefaultAudioStream; - DefaultNotificationPlayer.Play(); - } catch { } + try { + NotificationManager.PlaySave(); + } catch (Exception ex) { + Logger.Error(ex); + } } internal static void SendXSNotification(bool test = false) { @@ -537,6 +562,7 @@ internal static void RefreshLists() { private void UpdateEntries() { listBoxEntries.Items.Clear(); + if (JustCopiedIndex > -1) SetJustCopied(-1); if (listBoxKeys.SelectedItem == null) return; @@ -908,7 +934,10 @@ private void FirstImport() { if (Settings.Get.AutoCopy) { Entry? first = temp?.Database.FirstOrDefault(); - if (first != null) SetRecent(first); + if (first != null) { + SetRecent(first); + NotificationManager.PlayCopy(); + } } } @@ -979,7 +1008,7 @@ private void AddLogEntry(string dateKey, string content, DateTime timestamp, ToN SaveData.SetDirty(); if (context.Initialized) { - PlayNotification(); + PlaySaveNotification(); SendXSNotification(); DSWebHook.Send(entry); diff --git a/Windows/SettingsWindow.Designer.cs b/Windows/SettingsWindow.Designer.cs index 4e149c4..1667ee2 100644 --- a/Windows/SettingsWindow.Designer.cs +++ b/Windows/SettingsWindow.Designer.cs @@ -37,7 +37,7 @@ private void InitializeComponent() { checkAutoCopy = new CheckBox(); checkSkipParsedLogs = new CheckBox(); checkOSCEnabled = new CheckBox(); - checkPlayAudio = new CheckBox(); + checkPlayAudioSave = new CheckBox(); checkXSOverlay = new CheckBox(); checkShowDate = new CheckBox(); checkInvertMD = new CheckBox(); @@ -91,6 +91,11 @@ private void InitializeComponent() { checkDiscordCustomStart = new CheckBox(); linkEditDiscordStart = new LinkLabel(); labelGroupNotifications = new Label(); + flowLayoutPanel7 = new FlowLayoutPanel(); + linkSelectAudioSave = new LinkLabel(); + flowLayoutPanel8 = new FlowLayoutPanel(); + checkPlayAudioCopy = new CheckBox(); + linkSelectAudioCopy = new LinkLabel(); labelGroupOSC = new Label(); flowTerrorColor = new FlowLayoutPanel(); linkOSCFormat = new LinkLabel(); @@ -118,6 +123,8 @@ private void InitializeComponent() { flowDiscordImageText.SuspendLayout(); flowDiscordIconText.SuspendLayout(); flowDiscordIconStart.SuspendLayout(); + flowLayoutPanel7.SuspendLayout(); + flowLayoutPanel8.SuspendLayout(); flowTerrorColor.SuspendLayout(); flowLayoutPanel3.SuspendLayout(); flowLayoutPanel2.SuspendLayout(); @@ -221,7 +228,7 @@ private void InitializeComponent() { // checkOSCEnabled // checkOSCEnabled.AutoSize = true; - checkOSCEnabled.Location = new Point(3, 598); + checkOSCEnabled.Location = new Point(3, 619); checkOSCEnabled.Margin = new Padding(3, 1, 3, 1); checkOSCEnabled.Name = "checkOSCEnabled"; checkOSCEnabled.Padding = new Padding(20, 0, 3, 0); @@ -232,26 +239,23 @@ private void InitializeComponent() { checkOSCEnabled.UseVisualStyleBackColor = true; checkOSCEnabled.MouseUp += checkOSCEnabled_MouseUp; // - // checkPlayAudio - // - checkPlayAudio.AutoCheck = false; - checkPlayAudio.AutoSize = true; - checkPlayAudio.Location = new Point(3, 526); - checkPlayAudio.Margin = new Padding(3, 1, 3, 1); - checkPlayAudio.Name = "checkPlayAudio"; - checkPlayAudio.Padding = new Padding(20, 0, 3, 0); - checkPlayAudio.Size = new Size(180, 19); - checkPlayAudio.TabIndex = 1; - checkPlayAudio.Tag = "PlayAudio|Double click to select custom audio file.\\nRight click to reset back to 'default.wav'"; - checkPlayAudio.Text = "Play Sound (default.wav)"; - checkPlayAudio.UseVisualStyleBackColor = true; - checkPlayAudio.MouseDown += checkPlayAudio_MouseDown; - checkPlayAudio.MouseUp += checkPlayAudio_MouseUp; + // checkPlayAudioSave + // + checkPlayAudioSave.AutoSize = true; + checkPlayAudioSave.Location = new Point(3, 0); + checkPlayAudioSave.Margin = new Padding(0); + checkPlayAudioSave.Name = "checkPlayAudioSave"; + checkPlayAudioSave.Padding = new Padding(20, 0, 3, 0); + checkPlayAudioSave.Size = new Size(152, 19); + checkPlayAudioSave.TabIndex = 1; + checkPlayAudioSave.Tag = "PlayAudioSave"; + checkPlayAudioSave.Text = "Play Sound on Save"; + checkPlayAudioSave.UseVisualStyleBackColor = true; // // checkXSOverlay // checkXSOverlay.AutoSize = true; - checkXSOverlay.Location = new Point(3, 547); + checkXSOverlay.Location = new Point(3, 568); checkXSOverlay.Margin = new Padding(3, 1, 3, 1); checkXSOverlay.Name = "checkXSOverlay"; checkXSOverlay.Padding = new Padding(20, 0, 3, 0); @@ -264,7 +268,7 @@ private void InitializeComponent() { // checkShowDate // checkShowDate.AutoSize = true; - checkShowDate.Location = new Point(3, 775); + checkShowDate.Location = new Point(3, 796); checkShowDate.Margin = new Padding(3, 1, 3, 1); checkShowDate.Name = "checkShowDate"; checkShowDate.Padding = new Padding(20, 0, 3, 0); @@ -277,7 +281,7 @@ private void InitializeComponent() { // checkInvertMD // checkInvertMD.AutoSize = true; - checkInvertMD.Location = new Point(3, 733); + checkInvertMD.Location = new Point(3, 754); checkInvertMD.Margin = new Padding(3, 1, 3, 1); checkInvertMD.Name = "checkInvertMD"; checkInvertMD.Padding = new Padding(20, 0, 3, 0); @@ -290,7 +294,7 @@ private void InitializeComponent() { // checkShowSeconds // checkShowSeconds.AutoSize = true; - checkShowSeconds.Location = new Point(3, 754); + checkShowSeconds.Location = new Point(3, 775); checkShowSeconds.Margin = new Padding(3, 1, 3, 1); checkShowSeconds.Name = "checkShowSeconds"; checkShowSeconds.Padding = new Padding(20, 0, 3, 0); @@ -303,7 +307,7 @@ private void InitializeComponent() { // check24Hour // check24Hour.AutoSize = true; - check24Hour.Location = new Point(3, 712); + check24Hour.Location = new Point(3, 733); check24Hour.Margin = new Padding(3, 1, 3, 1); check24Hour.Name = "check24Hour"; check24Hour.Padding = new Padding(20, 0, 3, 0); @@ -379,7 +383,7 @@ private void InitializeComponent() { // checkColorObjectives // checkColorObjectives.AutoSize = true; - checkColorObjectives.Location = new Point(3, 847); + checkColorObjectives.Location = new Point(3, 868); checkColorObjectives.Margin = new Padding(3, 1, 3, 1); checkColorObjectives.Name = "checkColorObjectives"; checkColorObjectives.Padding = new Padding(20, 0, 3, 0); @@ -484,7 +488,8 @@ private void InitializeComponent() { flowLayoutPanel1.Controls.Add(flowDiscordIconText); flowLayoutPanel1.Controls.Add(flowDiscordIconStart); flowLayoutPanel1.Controls.Add(labelGroupNotifications); - flowLayoutPanel1.Controls.Add(checkPlayAudio); + flowLayoutPanel1.Controls.Add(flowLayoutPanel7); + flowLayoutPanel1.Controls.Add(flowLayoutPanel8); flowLayoutPanel1.Controls.Add(checkXSOverlay); flowLayoutPanel1.Controls.Add(labelGroupOSC); flowLayoutPanel1.Controls.Add(checkOSCEnabled); @@ -504,7 +509,7 @@ private void InitializeComponent() { flowLayoutPanel1.FlowDirection = FlowDirection.TopDown; flowLayoutPanel1.Location = new Point(3, 3); flowLayoutPanel1.Name = "flowLayoutPanel1"; - flowLayoutPanel1.Size = new Size(544, 888); + flowLayoutPanel1.Size = new Size(544, 909); flowLayoutPanel1.TabIndex = 0; flowLayoutPanel1.WrapContents = false; // @@ -998,10 +1003,83 @@ private void InitializeComponent() { labelGroupNotifications.TabIndex = 12; labelGroupNotifications.Text = "Notifications"; // + // flowLayoutPanel7 + // + flowLayoutPanel7.AutoSize = true; + flowLayoutPanel7.AutoSizeMode = AutoSizeMode.GrowAndShrink; + flowLayoutPanel7.Controls.Add(checkPlayAudioSave); + flowLayoutPanel7.Controls.Add(linkSelectAudioSave); + flowLayoutPanel7.Location = new Point(0, 526); + flowLayoutPanel7.Margin = new Padding(0, 1, 0, 1); + flowLayoutPanel7.Name = "flowLayoutPanel7"; + flowLayoutPanel7.Padding = new Padding(3, 0, 0, 0); + flowLayoutPanel7.Size = new Size(257, 19); + flowLayoutPanel7.TabIndex = 17; + flowLayoutPanel7.WrapContents = false; + // + // linkSelectAudioSave + // + linkSelectAudioSave.ActiveLinkColor = Color.White; + linkSelectAudioSave.AutoSize = true; + linkSelectAudioSave.LinkBehavior = LinkBehavior.HoverUnderline; + linkSelectAudioSave.LinkColor = Color.Gray; + linkSelectAudioSave.Location = new Point(155, 0); + linkSelectAudioSave.Margin = new Padding(0); + linkSelectAudioSave.Name = "linkSelectAudioSave"; + linkSelectAudioSave.Size = new Size(102, 15); + linkSelectAudioSave.TabIndex = 11; + linkSelectAudioSave.TabStop = true; + linkSelectAudioSave.Text = "(Select Audio File)"; + linkSelectAudioSave.TextAlign = ContentAlignment.MiddleLeft; + linkSelectAudioSave.VisitedLinkColor = Color.Gray; + // + // flowLayoutPanel8 + // + flowLayoutPanel8.AutoSize = true; + flowLayoutPanel8.AutoSizeMode = AutoSizeMode.GrowAndShrink; + flowLayoutPanel8.Controls.Add(checkPlayAudioCopy); + flowLayoutPanel8.Controls.Add(linkSelectAudioCopy); + flowLayoutPanel8.Location = new Point(0, 547); + flowLayoutPanel8.Margin = new Padding(0, 1, 0, 1); + flowLayoutPanel8.Name = "flowLayoutPanel8"; + flowLayoutPanel8.Padding = new Padding(3, 0, 0, 0); + flowLayoutPanel8.Size = new Size(261, 19); + flowLayoutPanel8.TabIndex = 18; + flowLayoutPanel8.WrapContents = false; + // + // checkPlayAudioCopy + // + checkPlayAudioCopy.AutoSize = true; + checkPlayAudioCopy.Location = new Point(3, 0); + checkPlayAudioCopy.Margin = new Padding(0); + checkPlayAudioCopy.Name = "checkPlayAudioCopy"; + checkPlayAudioCopy.Padding = new Padding(20, 0, 3, 0); + checkPlayAudioCopy.Size = new Size(156, 19); + checkPlayAudioCopy.TabIndex = 1; + checkPlayAudioCopy.Tag = "PlayAudioCopy"; + checkPlayAudioCopy.Text = "Play Sound on Copy"; + checkPlayAudioCopy.UseVisualStyleBackColor = true; + // + // linkSelectAudioCopy + // + linkSelectAudioCopy.ActiveLinkColor = Color.White; + linkSelectAudioCopy.AutoSize = true; + linkSelectAudioCopy.LinkBehavior = LinkBehavior.HoverUnderline; + linkSelectAudioCopy.LinkColor = Color.Gray; + linkSelectAudioCopy.Location = new Point(159, 0); + linkSelectAudioCopy.Margin = new Padding(0); + linkSelectAudioCopy.Name = "linkSelectAudioCopy"; + linkSelectAudioCopy.Size = new Size(102, 15); + linkSelectAudioCopy.TabIndex = 11; + linkSelectAudioCopy.TabStop = true; + linkSelectAudioCopy.Text = "(Select Audio File)"; + linkSelectAudioCopy.TextAlign = ContentAlignment.MiddleLeft; + linkSelectAudioCopy.VisitedLinkColor = Color.Gray; + // // labelGroupOSC // labelGroupOSC.AutoSize = true; - labelGroupOSC.Location = new Point(3, 582); + labelGroupOSC.Location = new Point(3, 603); labelGroupOSC.Margin = new Padding(3, 15, 3, 0); labelGroupOSC.Name = "labelGroupOSC"; labelGroupOSC.Size = new Size(30, 15); @@ -1015,7 +1093,7 @@ private void InitializeComponent() { flowTerrorColor.Controls.Add(checkOSCSendColor); flowTerrorColor.Controls.Add(linkOSCFormat); flowTerrorColor.Controls.Add(labelOSCFormat); - flowTerrorColor.Location = new Point(0, 619); + flowTerrorColor.Location = new Point(0, 640); flowTerrorColor.Margin = new Padding(0, 1, 0, 1); flowTerrorColor.Name = "flowTerrorColor"; flowTerrorColor.Padding = new Padding(3, 0, 0, 0); @@ -1062,7 +1140,7 @@ private void InitializeComponent() { flowLayoutPanel3.AutoSizeMode = AutoSizeMode.GrowAndShrink; flowLayoutPanel3.Controls.Add(checkOSCSendDamage); flowLayoutPanel3.Controls.Add(linkSetDamageInterval); - flowLayoutPanel3.Location = new Point(3, 640); + flowLayoutPanel3.Location = new Point(3, 661); flowLayoutPanel3.Margin = new Padding(3, 1, 3, 1); flowLayoutPanel3.Name = "flowLayoutPanel3"; flowLayoutPanel3.Size = new Size(286, 19); @@ -1106,7 +1184,7 @@ private void InitializeComponent() { flowLayoutPanel2.AutoSizeMode = AutoSizeMode.GrowAndShrink; flowLayoutPanel2.Controls.Add(checkSendChatbox); flowLayoutPanel2.Controls.Add(linkEditChatbox); - flowLayoutPanel2.Location = new Point(0, 661); + flowLayoutPanel2.Location = new Point(0, 682); flowLayoutPanel2.Margin = new Padding(0, 1, 0, 1); flowLayoutPanel2.Name = "flowLayoutPanel2"; flowLayoutPanel2.Padding = new Padding(3, 0, 0, 0); @@ -1134,7 +1212,7 @@ private void InitializeComponent() { // labelGroupFormat // labelGroupFormat.AutoSize = true; - labelGroupFormat.Location = new Point(3, 696); + labelGroupFormat.Location = new Point(3, 717); labelGroupFormat.Margin = new Padding(3, 15, 3, 0); labelGroupFormat.Name = "labelGroupFormat"; labelGroupFormat.Size = new Size(74, 15); @@ -1144,7 +1222,7 @@ private void InitializeComponent() { // checkShowTime // checkShowTime.AutoSize = true; - checkShowTime.Location = new Point(3, 796); + checkShowTime.Location = new Point(3, 817); checkShowTime.Margin = new Padding(3, 1, 3, 1); checkShowTime.Name = "checkShowTime"; checkShowTime.Padding = new Padding(20, 0, 3, 0); @@ -1157,7 +1235,7 @@ private void InitializeComponent() { // labelGroupStyle // labelGroupStyle.AutoSize = true; - labelGroupStyle.Location = new Point(3, 831); + labelGroupStyle.Location = new Point(3, 852); labelGroupStyle.Margin = new Padding(3, 15, 3, 0); labelGroupStyle.Name = "labelGroupStyle"; labelGroupStyle.Size = new Size(32, 15); @@ -1170,7 +1248,7 @@ private void InitializeComponent() { flowLayoutPanel4.AutoSizeMode = AutoSizeMode.GrowAndShrink; flowLayoutPanel4.Controls.Add(checkOpenRGBEnabled); flowLayoutPanel4.Controls.Add(linkOpenRGB); - flowLayoutPanel4.Location = new Point(0, 868); + flowLayoutPanel4.Location = new Point(0, 889); flowLayoutPanel4.Margin = new Padding(0, 1, 0, 1); flowLayoutPanel4.Name = "flowLayoutPanel4"; flowLayoutPanel4.Padding = new Padding(3, 0, 0, 0); @@ -1250,6 +1328,10 @@ private void InitializeComponent() { flowDiscordIconText.PerformLayout(); flowDiscordIconStart.ResumeLayout(false); flowDiscordIconStart.PerformLayout(); + flowLayoutPanel7.ResumeLayout(false); + flowLayoutPanel7.PerformLayout(); + flowLayoutPanel8.ResumeLayout(false); + flowLayoutPanel8.PerformLayout(); flowTerrorColor.ResumeLayout(false); flowTerrorColor.PerformLayout(); flowLayoutPanel3.ResumeLayout(false); @@ -1265,7 +1347,7 @@ private void InitializeComponent() { private CheckBox checkAutoCopy; private CheckBox checkPlayerNames; private Button btnCheckForUpdates; - private CheckBox checkPlayAudio; + private CheckBox checkPlayAudioSave; private CheckBox checkXSOverlay; private CheckBox checkInvertMD; private CheckBox checkShowSeconds; @@ -1339,5 +1421,10 @@ private void InitializeComponent() { private LinkLabel linkOSCFormat; private Label labelOSCFormat; private CheckBox checkShowTime; + private FlowLayoutPanel flowLayoutPanel7; + private LinkLabel linkSelectAudioSave; + private FlowLayoutPanel flowLayoutPanel8; + private CheckBox checkPlayAudioCopy; + private LinkLabel linkSelectAudioCopy; } } \ No newline at end of file diff --git a/Windows/SettingsWindow.cs b/Windows/SettingsWindow.cs index fc8f525..f200ae5 100644 --- a/Windows/SettingsWindow.cs +++ b/Windows/SettingsWindow.cs @@ -18,12 +18,8 @@ public partial class SettingsWindow : Form { #region Initialization internal static SettingsWindow? Instance; - readonly Timer ClickTimer = new Timer() { Interval = 200 }; - readonly Stopwatch Stopwatch = new Stopwatch(); - public SettingsWindow() { InitializeComponent(); - ClickTimer.Tick += ClickTimer_Tick; languageSelectBox.FixItemHeight(true); #if DEBUG @@ -83,7 +79,7 @@ internal void LocalizeContent() { foreach (KeyValuePair pair in LocalizedControlCache) { LANG.C(pair.Value, pair.Key, toolTip); - if (pair.Key == "SETTINGS.PLAYAUDIO") PostAudioLocationSet(); + // if (pair.Key == "SETTINGS.PLAYAUDIO") PostAudioLocationSet(); } LANG.C(labelGroupGeneral, "SETTINGS.GROUP.GENERAL", toolTip); @@ -106,6 +102,10 @@ internal void LocalizeContent() { LANG.C(linkEditDiscordIcon, "SETTINGS.DISCORDRICHPRESENCE_EDIT", toolTip); LANG.C(linkEditDiscordStart, "SETTINGS.DISCORDRICHPRESENCE_EDIT", toolTip); + LANG.C(linkSelectAudioSave, "SETTINGS.PLAYAUDIO_SELECT", toolTip); + LANG.C(linkSelectAudioCopy, "SETTINGS.PLAYAUDIO_SELECT", toolTip); + UpdatePlayLink(); + LANG.C(linkOSCFormat, "SETTINGS.OSCSENDCOLORFORMAT", toolTip); string? tt = LANG.S("SETTINGS.OSCSENDCOLOR.TT"); if (tt != null) ColorFormatTooltip = tt; @@ -125,6 +125,19 @@ internal void LocalizeContent() { RightToLeft = LANG.IsRightToLeft ? RightToLeft.Yes : RightToLeft.No; } + private void UpdateAudioLink(LinkLabel audioLinkLabel, string? location) { + LANG.C(audioLinkLabel, "SETTINGS.PLAYAUDIO_SELECT", toolTip); + if (!string.IsNullOrEmpty(location)) { + toolTip.SetToolTip(audioLinkLabel, LANG.S("SETTINGS.PLAYAUDIO_SELECT.ALT")); + string fileName = Path.GetFileName(location); + if (!string.IsNullOrEmpty(fileName)) audioLinkLabel.Text = $"({fileName})"; + } + } + private void UpdatePlayLink() { + UpdateAudioLink(linkSelectAudioSave, Settings.Get.AudioLocation); + UpdateAudioLink(linkSelectAudioCopy, Settings.Get.AudioCopyLocation); + } + private static Font? GroupLabelFont { get; set; } // Subscribe to events on load private void SettingsWindow_Load(object sender, EventArgs e) { @@ -145,8 +158,14 @@ private void SettingsWindow_Load(object sender, EventArgs e) { labelGroupOSC.Font = GroupLabelFont; // Custom audio handling - PostAudioLocationSet(); - checkPlayAudio.CheckedChanged += CheckPlayAudio_CheckedChanged; + checkPlayAudioSave.CheckedChanged += CheckPlayAudio_CheckedChanged; + checkPlayAudioCopy.CheckedChanged += CheckPlayAudio_CheckedChanged; + CheckPlayAudio_CheckedChanged(null, EventArgs.Empty); + + linkSelectAudioSave.LinkClicked += LinkSelectAudio_LinkClicked; + linkSelectAudioCopy.LinkClicked += LinkSelectAudio_LinkClicked; + + // Other notifications checkXSOverlay.CheckedChanged += CheckXSOverlay_CheckedChanged; // Refresh lists when time format changes check24Hour.CheckedChanged += TimeFormat_CheckedChanged; @@ -212,6 +231,28 @@ private void SettingsWindow_Load(object sender, EventArgs e) { FillLanguageBox(); } + private void LinkSelectAudio_LinkClicked(object? sender, LinkLabelLinkClickedEventArgs e) { + bool isLeft = e.Button == MouseButtons.Left; + + string? file = null; + if (isLeft) { + file = SelectAudioFile(); + if (string.IsNullOrEmpty(file)) return; + } + + bool isSave = sender == linkSelectAudioSave; + if (isSave) { + Settings.Get.AudioLocation = file; + NotificationManager.PlaySave(); + } else { + Settings.Get.AudioCopyLocation = file; + NotificationManager.PlayCopy(); + } + + Settings.Export(); + UpdatePlayLink(); + } + private void LinkOSCFormat_LinkClicked(object? sender, LinkLabelLinkClickedEventArgs? e) { int index = Settings.Get.OSCSendColorFormat; if (sender != null && e != null) { @@ -436,8 +477,6 @@ private void CheckOSCSendColor_CheckedChanged(object? sender, EventArgs e) { } private void SettingsWindow_FormClosed(object sender, FormClosedEventArgs e) { - ClickTimer.Dispose(); - MainWindow.RefreshLists(); MainWindow.ResetNotification(); } @@ -445,8 +484,22 @@ private void SettingsWindow_FormClosed(object sender, FormClosedEventArgs e) { private void TimeFormat_CheckedChanged(object? sender, EventArgs e) => MainWindow.RefreshLists(); private void CheckXSOverlay_CheckedChanged(object? sender, EventArgs e) => MainWindow.SendXSNotification(true); private void CheckPlayAudio_CheckedChanged(object? sender, EventArgs e) { - MainWindow.PlayNotification(); - if (!checkPlayAudio.Checked) MainWindow.ResetNotification(); + linkSelectAudioCopy.Visible = checkPlayAudioCopy.Checked; + linkSelectAudioSave.Visible = checkPlayAudioSave.Checked; + + if (sender == null) return; + + CheckBox checkbox = (CheckBox)sender; + bool isChecked = checkbox.Checked; + + if (!isChecked) { + MainWindow.ResetNotification(); + return; + } + + if (checkbox == checkPlayAudioSave) + MainWindow.PlaySaveNotification(); + else MainWindow.PlayCopyNotification(); } private void checkSaveTerrors_CheckedChanged(object? sender, EventArgs e) { @@ -500,12 +553,6 @@ private void btnOpenData_Click(object sender, EventArgs e) { SaveData.OpenDataLocation(); } - private void checkPlayAudio_MouseDown(object sender, MouseEventArgs e) { - if (e.Button != MouseButtons.Left) return; - Stopwatch.Start(); - CancelNext = false; - } - private void checkSendChatbox_CheckedChanged(object? sender, EventArgs e) { if (checkSendChatbox.Checked) StatsWindow.UpdateChatboxContent(); else LilOSC.SetChatboxMessage(string.Empty); @@ -554,39 +601,9 @@ private void linkLogUpdateRate_LinkClicked(object sender, LinkLabelLinkClickedEv } } - private void checkPlayAudio_MouseUp(object sender, MouseEventArgs e) { - if (e.Button == MouseButtons.Right && !string.IsNullOrEmpty(Settings.Get.AudioLocation)) { - Settings.Get.AudioLocation = null; - Settings.Export(); - PostAudioLocationSet(); - return; - } - - if (e.Button != MouseButtons.Left) return; - - Stopwatch.Stop(); - long elapsed = Stopwatch.ElapsedMilliseconds; - Stopwatch.Reset(); - - if (CancelNext) { - CancelNext = false; - return; - } - - if (elapsed > 210) { - TogglePlayAudio(); - return; - } - - if (!DoubleClickCheck) { - DoubleClickCheck = true; - ClickTimer.Stop(); - ClickTimer.Start(); - return; - } - - DoubleClickCheck = false; - ClickTimer.Stop(); + /// TODO: Move this function somewhere else + private string? SelectAudioFile() { + string? result = null; using (OpenFileDialog fileDialog = new OpenFileDialog()) { fileDialog.InitialDirectory = "./"; @@ -594,11 +611,13 @@ private void checkPlayAudio_MouseUp(object sender, MouseEventArgs e) { fileDialog.Filter = "Waveform (*.wav)|*.wav"; if (fileDialog.ShowDialog() == DialogResult.OK && !string.IsNullOrEmpty(fileDialog.FileName)) { - Settings.Get.AudioLocation = fileDialog.FileName; - Settings.Export(); - PostAudioLocationSet(); + result = fileDialog.FileName; + } else { + result = null; } } + + return result; } private void checkAutoCopy_CheckedChanged(object? sender, EventArgs e) { @@ -630,18 +649,6 @@ private void CheckColorObjectives_CheckedChanged(object? sender, EventArgs e) { ObjectivesWindow.RefreshLists(); } - // Double click - private bool DoubleClickCheck = false; - private bool CancelNext = false; - private void ClickTimer_Tick(object? sender, EventArgs e) { - ClickTimer.Stop(); - if (DoubleClickCheck) { - DoubleClickCheck = false; - CancelNext = true; - TogglePlayAudio(); - } - } - private void languageSelectBox_SelectedIndexChanged(object sender, EventArgs e) { if (!FilledLanguages || languageSelectBox.SelectedIndex < 0 || languageSelectBox.SelectedItem == null) return; LANG.LangKey langKey = (LANG.LangKey)languageSelectBox.SelectedItem; @@ -683,10 +690,6 @@ internal void FillLanguageBox() { #endregion #region Utils - private void TogglePlayAudio() { - checkPlayAudio.Checked = !checkPlayAudio.Checked; - } - private void BindControlsRecursive(Control.ControlCollection controls) { foreach (Control c in controls) { string? tag = c.Tag?.ToString(); @@ -716,12 +719,6 @@ private void BindControlsRecursive(Control.ControlCollection controls) { } } } - - private void PostAudioLocationSet() { - bool hasLocation = string.IsNullOrEmpty(Settings.Get.AudioLocation); - string? name = (hasLocation ? "default.wav" : (Path.GetFileName(Settings.Get.AudioLocation) ?? "custom.wav")); - checkPlayAudio.Text = LANG.S("SETTINGS.PLAYAUDIO", name) ?? $"Play Audio ({name})"; - } #endregion } diff --git a/Windows/UpdateWindow.Designer.cs b/Windows/UpdateWindow.Designer.cs deleted file mode 100644 index 0cbd8b4..0000000 --- a/Windows/UpdateWindow.Designer.cs +++ /dev/null @@ -1,70 +0,0 @@ -namespace ToNSaveManager -{ - partial class UpdateWindow - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(UpdateWindow)); - textBox1 = new TextBox(); - SuspendLayout(); - // - // textBox1 - // - textBox1.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; - textBox1.BackColor = SystemColors.WindowText; - textBox1.BorderStyle = BorderStyle.FixedSingle; - textBox1.ForeColor = Color.White; - textBox1.Location = new Point(12, 12); - textBox1.Multiline = true; - textBox1.Name = "textBox1"; - textBox1.ReadOnly = true; - textBox1.ShortcutsEnabled = false; - textBox1.Size = new Size(409, 170); - textBox1.TabIndex = 1; - textBox1.TabStop = false; - textBox1.UseWaitCursor = true; - // - // UpdateWindow - // - AutoScaleDimensions = new SizeF(7F, 15F); - AutoScaleMode = AutoScaleMode.Font; - BackColor = Color.FromArgb(46, 52, 64); - ClientSize = new Size(433, 194); - ControlBox = false; - Controls.Add(textBox1); - Icon = (Icon)resources.GetObject("$this.Icon"); - MinimumSize = new Size(400, 200); - Name = "UpdateWindow"; - Text = "ToNSaveManager | Updating"; - Load += UpdateWindow_Load; - ResumeLayout(false); - PerformLayout(); - } - - #endregion - private TextBox textBox1; - } -} \ No newline at end of file diff --git a/Windows/UpdateWindow.cs b/Windows/UpdateWindow.cs deleted file mode 100644 index 17156dd..0000000 --- a/Windows/UpdateWindow.cs +++ /dev/null @@ -1,163 +0,0 @@ -using System.ComponentModel; -using System.Diagnostics; -using System.IO.Compression; -using ToNSaveManager.Models; - -namespace ToNSaveManager -{ - public partial class UpdateWindow : Form - { - private void Print(string message) - { - textBox1.AppendText(message + Environment.NewLine); - textBox1.SelectionStart = textBox1.Text.Length; - textBox1.ScrollToCaret(); - } - - string OldTempDir; - string TempFileName; - string TempFileLocation; - - GitHubRelease Release; - GitHubRelease.Asset Asset; - - internal UpdateWindow(GitHubRelease release, GitHubRelease.Asset asset) - { - Release = release; - Asset = asset; - - TempFileName = release.tag_name + ".temp.zip"; - TempFileLocation = Path.Combine(Program.ProgramDirectory, TempFileName); - OldTempDir = Path.Combine(Program.ProgramDirectory, ".temp_files"); - - InitializeComponent(); - } - - public static void RunPostUpdateCheck(string[] args) - { - int index = Array.IndexOf(args, "--post-update") + 1; - if (index == 0 || index >= args.Length) return; - string temp = args[index]; - - try - { - using (Process currentProcess = Process.GetCurrentProcess()) - { - Process[] processes = Process.GetProcessesByName(currentProcess.ProcessName); - foreach (Process process in processes) - { - using (process) - { - if (process.Id != currentProcess.Id) - { - process.Kill(); - process.WaitForExit(); - } - } - } - } - - if (Directory.Exists(temp)) - Directory.Delete(temp, true); - } - catch (Exception ex) - { - MessageBox.Show("Failed to do post update.\n\n" + ex, "Update Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - } - } - - private void BackgroundWr_DoWork(object? sender, DoWorkEventArgs e) - { - if (sender == null) return; - BackgroundWorker worker = (BackgroundWorker)sender; - - try - { - - if (File.Exists(TempFileLocation)) - File.Delete(TempFileLocation); - - worker.ReportProgress(0, $"Downloading asset '{Asset.name}'"); - string downloadUrl = Asset.browser_download_url; - using (HttpClient client = new HttpClient()) - { - using (var s = client.GetStreamAsync(downloadUrl).Result) - { - using (var fs = new FileStream(TempFileLocation, FileMode.CreateNew)) - { - s.CopyTo(fs); - } - } - } - - worker.ReportProgress(50, $"Asset downloaded, decompressing..."); - string outputDir = Path.Combine(Program.ProgramDirectory, Path.GetFileNameWithoutExtension(TempFileLocation)); - ZipFile.ExtractToDirectory(TempFileLocation, outputDir, true); - File.Delete(TempFileLocation); // .zip cleanup - - if (!Directory.Exists(OldTempDir)) Directory.CreateDirectory(OldTempDir); - - string[] files = Directory.GetFiles(outputDir); - worker.ReportProgress(90, $"Decompressed '{files.Length}' files..."); - - foreach (string file in files) - { - worker.ReportProgress(95, ($" > {file}")); - string fileName = Path.GetFileName(file); - string f = Path.Combine(Program.ProgramDirectory, fileName); - string n = Path.Combine(OldTempDir, fileName); - if (File.Exists(f)) - File.Move(f, n, true); - - File.Move(file, f); - } - - worker.ReportProgress(100, ($"Cleaning up...")); - Directory.Delete(outputDir, true); - e.Result = null; - } - catch (Exception ex) - { - e.Result = ex; - } - } - - private void UpdateWindow_Load(object sender, EventArgs e) - { - Print($"Updating to '{Release.tag_name}'"); - BackgroundWorker worker = new BackgroundWorker() - { - WorkerReportsProgress = true, - }; - worker.DoWork += BackgroundWr_DoWork; - worker.RunWorkerCompleted += Worker_RunWorkerCompleted; - worker.ProgressChanged += Worker_ProgressChanged; - worker.RunWorkerAsync(); - } - - private void Worker_ProgressChanged(object? sender, ProgressChangedEventArgs e) - { - if (e.UserState == null) return; - Print(" * " + e.UserState); - } - - private void Worker_RunWorkerCompleted(object? sender, RunWorkerCompletedEventArgs e) - { - if (e.Result != null) - { - MessageBox.Show("Failed to download update package.\n\n" + e.Result, "Update Error", MessageBoxButtons.OK, MessageBoxIcon.Error); - this.Close(); - return; - } - - Print(string.Empty); - Print("Running post update... please wait..."); - Program.ReleaseMutex(); // Release mutex so downloaded app opens properly - // Start new process with --post-update - ProcessStartInfo processInfo = new ProcessStartInfo("ToNSaveManager.exe", $"--post-update \"{OldTempDir}\""); - Process.Start(processInfo); - // Exit this app - Application.Exit(); - } - } -} diff --git a/Windows/UpdateWindow.resx b/Windows/UpdateWindow.resx deleted file mode 100644 index c5e88dd..0000000 --- a/Windows/UpdateWindow.resx +++ /dev/null @@ -1,138 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - - AAABAAEAICAQAAEABADoAgAAFgAAACgAAAAgAAAAQAAAAAEABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAyJ/8A+v7+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIgAA - AAAAAAAAAAACIiIiIiIAAAAAAAAAAAAAAiIiIiIiAAAAAAARAAAAAAIiIiIiIgAAAAAAEQAAAAACIiIi - IiIAAAAAAREQAAAAAiIiIAACAAAAAAEREAAAAAIiIiAAAgAAAAABERAAAAACIiIgAiIAAAEAAREQABAA - AiIiIAIiAAARAAEREAARAAIiIiIiIgAAEQABERAAEQACIiIgAiIAABEAAREQABEAAiIiIAIiAAARAAER - EAARAAIiIiACIgAAEQABERAAEQACIiIgAiIAABEAAREQABEAAiIiIAIiAAABAAEREAAQAAIiIiIiIgAA - AAABERAAAAACIiIgAiIAAAAAABEAAAAAAiIiIAIiAAAAAAARAAAAAAIiIiACIgAAAAAAAAAAAAACIiIg - AiIAAAAAAAAAAAAAAiIiIAIiAAAAAAAAAAAAAAIiIiIiIiIiIiIiIiIiIiIiIiIgAiIiIiIiIiIiACIi - IiIiIAIiIiIiIiIiIgAiIiIiIiAAAgAAAgAAAgAAIiIiIiIgAAIAAAIAAAIAACIiIiIiIiIiIiIiIiIi - IiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiL/////////////////AAAH/wAAB/8A - AAf/AAAH/wAAB+EAAAfhAAAH5wAAB+cAAAf/AAAH5wAAB+cAAAfnAAAH5wAAB+cAAAf/AAAH5wAAB+cA - AAfnAAAH5wAAB+cAAAf/////5//8/+f//P/hBBD/4QQQ/////////////////w== - - - \ No newline at end of file