diff --git a/app/Desktop/Discord/DiscordAppSettings.cs b/app/Desktop/Discord/DiscordAppSettings.cs new file mode 100644 index 0000000..486f98b --- /dev/null +++ b/app/Desktop/Discord/DiscordAppSettings.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Runtime.InteropServices; +using System.Text.Json; +using System.Threading.Tasks; +using DHT.Utils.Logging; +using static System.Environment.SpecialFolder; +using static System.Environment.SpecialFolderOption; + +namespace DHT.Desktop.Discord { + static class DiscordAppSettings { + private static readonly Log Log = Log.ForType(typeof(DiscordAppSettings)); + + private const string JsonKeyDevTools = "DANGEROUS_ENABLE_DEVTOOLS_ONLY_ENABLE_IF_YOU_KNOW_WHAT_YOURE_DOING"; + + public static string JsonFilePath { get; } + private static string JsonBackupFilePath { get; } + + [SuppressMessage("ReSharper", "ConvertIfStatementToConditionalTernaryExpression")] + static DiscordAppSettings() { + string rootFolder; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { + rootFolder = Path.Combine(Environment.GetFolderPath(ApplicationData, DoNotVerify), "Discord"); + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { + rootFolder = Path.Combine(Environment.GetFolderPath(UserProfile, DoNotVerify), "Library", "Application Support", "Discord"); + } + else { + rootFolder = Path.Combine(Environment.GetFolderPath(ApplicationData, DoNotVerify), "discord"); + } + + JsonFilePath = Path.Combine(rootFolder, "settings.json"); + JsonBackupFilePath = JsonFilePath + ".bak"; + } + + public static async Task AreDevToolsEnabled() { + try { + return AreDevToolsEnabled(await ReadSettingsJson()); + } catch (Exception) { + return null; + } + } + + private static bool AreDevToolsEnabled(Dictionary json) { + return json.TryGetValue(JsonKeyDevTools, out var value) && value is JsonElement { ValueKind: JsonValueKind.True }; + } + + public static async Task ConfigureDevTools(bool enable) { + Dictionary json; + + try { + json = await ReadSettingsJson(); + } catch (FileNotFoundException) { + return SettingsJsonResult.FileNotFound; + } catch (JsonException) { + return SettingsJsonResult.InvalidJson; + } catch (Exception e) { + Log.Error(e); + return SettingsJsonResult.ReadError; + } + + if (enable == AreDevToolsEnabled(json)) { + return SettingsJsonResult.AlreadySet; + } + + if (enable) { + json[JsonKeyDevTools] = true; + } + else { + json.Remove(JsonKeyDevTools); + } + + try { + if (!File.Exists(JsonBackupFilePath)) { + File.Copy(JsonFilePath, JsonBackupFilePath); + } + + await WriteSettingsJson(json); + } catch (Exception e) { + Log.Error("An error occurred when writing settings file."); + Log.Error(e); + + if (File.Exists(JsonBackupFilePath)) { + try { + File.Move(JsonBackupFilePath, JsonFilePath, true); + Log.Info("Restored settings file from backup."); + } catch (Exception e2) { + Log.Error("Cannot restore settings file from backup."); + Log.Error(e2); + } + } + + return SettingsJsonResult.WriteError; + } + + try { + File.Delete(JsonBackupFilePath); + } catch (Exception e) { + Log.Error("Cannot delete backup file."); + Log.Error(e); + } + + return SettingsJsonResult.Success; + } + + private static async Task> ReadSettingsJson() { + await using var stream = new FileStream(JsonFilePath, FileMode.Open, FileAccess.Read, FileShare.Read); + return await JsonSerializer.DeserializeAsync?>(stream) ?? throw new JsonException(); + } + + private static async Task WriteSettingsJson(Dictionary json) { + await using var stream = new FileStream(JsonFilePath, FileMode.Truncate, FileAccess.Write, FileShare.None); + await JsonSerializer.SerializeAsync(stream, json, new JsonSerializerOptions { WriteIndented = true }); + } + } +} diff --git a/app/Desktop/Discord/SettingsJsonResult.cs b/app/Desktop/Discord/SettingsJsonResult.cs new file mode 100644 index 0000000..227809e --- /dev/null +++ b/app/Desktop/Discord/SettingsJsonResult.cs @@ -0,0 +1,10 @@ +namespace DHT.Desktop.Discord { + enum SettingsJsonResult { + Success, + AlreadySet, + FileNotFound, + ReadError, + InvalidJson, + WriteError + } +} diff --git a/app/Desktop/Main/MainContentScreenModel.cs b/app/Desktop/Main/MainContentScreenModel.cs index 1dc6343..23ef9a4 100644 --- a/app/Desktop/Main/MainContentScreenModel.cs +++ b/app/Desktop/Main/MainContentScreenModel.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; using Avalonia.Controls; using DHT.Desktop.Main.Controls; using DHT.Desktop.Main.Pages; @@ -45,8 +46,8 @@ namespace DHT.Desktop.Main { StatusBarModel.CurrentStatus = ServerLauncher.IsRunning ? StatusBarModel.Status.Ready : StatusBarModel.Status.Stopped; } - public void Initialize() { - TrackingPageModel.Initialize(); + public async Task Initialize() { + await TrackingPageModel.Initialize(); } private void TrackingPageModelOnServerStatusChanged(object? sender, StatusBarModel.Status e) { diff --git a/app/Desktop/Main/MainWindowModel.cs b/app/Desktop/Main/MainWindowModel.cs index bbc70f6..2fb89b1 100644 --- a/app/Desktop/Main/MainWindowModel.cs +++ b/app/Desktop/Main/MainWindowModel.cs @@ -69,7 +69,7 @@ namespace DHT.Desktop.Main { } } - private void WelcomeScreenModelOnPropertyChanged(object? sender, PropertyChangedEventArgs e) { + private async void WelcomeScreenModelOnPropertyChanged(object? sender, PropertyChangedEventArgs e) { if (e.PropertyName == nameof(WelcomeScreenModel.Db)) { if (MainContentScreenModel != null) { MainContentScreenModel.DatabaseClosed -= MainContentScreenModelOnDatabaseClosed; @@ -87,7 +87,7 @@ namespace DHT.Desktop.Main { else { Title = Path.GetFileName(db.Path) + " - " + DefaultTitle; MainContentScreenModel = new MainContentScreenModel(window, db); - MainContentScreenModel.Initialize(); + await MainContentScreenModel.Initialize(); MainContentScreenModel.DatabaseClosed += MainContentScreenModelOnDatabaseClosed; MainContentScreen = new MainContentScreen { DataContext = MainContentScreenModel }; OnPropertyChanged(nameof(MainContentScreen)); diff --git a/app/Desktop/Main/Pages/TrackingPage.axaml b/app/Desktop/Main/Pages/TrackingPage.axaml index 81468f2..9c7f826 100644 --- a/app/Desktop/Main/Pages/TrackingPage.axaml +++ b/app/Desktop/Main/Pages/TrackingPage.axaml @@ -23,13 +23,13 @@ - To start tracking messages, copy the tracking script and paste it into the console of either the Discord app (Ctrl+Shift+I), or your browser with Discord open. + To start tracking messages, copy the tracking script and paste it into the console of either the Discord app, or your browser. The console is usually opened by pressing Ctrl+Shift+I. - + -