From af90ae5fbaeeeda25dc2b96f5692dbeb53fc5604 Mon Sep 17 00:00:00 2001 From: Andrei Tudor Date: Wed, 27 Dec 2023 18:03:26 +0200 Subject: [PATCH] Added UI support for LINUX KDE Plasma --- DiscordBot/DiscordBot.csproj | 2 +- DiscordBot/Entry.cs | 4 ++ DiscordBot/Installer.cs | 33 +++++++------ DiscordBot/Program.cs | 15 +++--- PluginManager/Bot/Boot.cs | 2 + PluginManager/Config.cs | 21 ++++++++- PluginManager/PluginManager.csproj | 11 ++++- PluginManager/UX/IOutputModel.cs | 29 ++++++++++++ PluginManager/UX/Linux/KDE.cs | 75 ++++++++++++++++++++++++++++++ PluginManager/UX/Other/Console.cs | 51 ++++++++++++++++++++ PluginManager/UX/UxHandler.cs | 42 +++++++++++++++++ 11 files changed, 259 insertions(+), 26 deletions(-) create mode 100644 PluginManager/UX/IOutputModel.cs create mode 100644 PluginManager/UX/Linux/KDE.cs create mode 100644 PluginManager/UX/Other/Console.cs create mode 100644 PluginManager/UX/UxHandler.cs diff --git a/DiscordBot/DiscordBot.csproj b/DiscordBot/DiscordBot.csproj index 3ae8395..868d4d2 100644 --- a/DiscordBot/DiscordBot.csproj +++ b/DiscordBot/DiscordBot.csproj @@ -1,7 +1,7 @@ Exe - net6.0 + net8.0 disable diff --git a/DiscordBot/Entry.cs b/DiscordBot/Entry.cs index eb61106..b9251b1 100644 --- a/DiscordBot/Entry.cs +++ b/DiscordBot/Entry.cs @@ -1,6 +1,10 @@ using System; using System.IO; using System.Reflection; +using System.Threading; +using System.Threading.Tasks; +using PluginManager.UX; + namespace DiscordBot; diff --git a/DiscordBot/Installer.cs b/DiscordBot/Installer.cs index e310590..571469e 100644 --- a/DiscordBot/Installer.cs +++ b/DiscordBot/Installer.cs @@ -1,28 +1,33 @@ +using System; using PluginManager; using Spectre.Console; +using System.Threading.Tasks; + namespace DiscordBot; public static class Installer { - public static void GenerateStartupConfig() + public static async Task GenerateStartupConfig() { - AnsiConsole.MarkupLine("Welcome to the [bold]SethBot[/] installer !"); - AnsiConsole.MarkupLine("First, we need to configure the bot. Don't worry, it will be quick !"); - - var token = AnsiConsole.Ask("Please enter the bot [yellow]token[/]:"); - var prefix = AnsiConsole.Ask("Please enter the bot [yellow]prefix[/]:"); - var serverId = AnsiConsole.Ask("Please enter the [yellow]Server ID[/]:"); - + string token = await PluginManager.UX.UxHandler.ShowInputBox("SethBot", "Please enter the bot token:"); + string botPrefix = await PluginManager.UX.UxHandler.ShowInputBox("SethBot", "Please enter the bot prefix:"); + string serverId = await PluginManager.UX.UxHandler.ShowInputBox("SethBot", "Please enter the Server ID:"); + if (string.IsNullOrWhiteSpace(serverId)) serverId = "NULL"; + + if (string.IsNullOrWhiteSpace(token) || string.IsNullOrWhiteSpace(botPrefix)) + { + await PluginManager.UX.UxHandler.ShowMessageBox("SethBot", "Invalid token or prefix !", PluginManager.UX.MessageBoxType.Error); + Environment.Exit(-20); + } + Config.AppSettings.Add("token", token); - Config.AppSettings.Add("prefix", prefix); + Config.AppSettings.Add("prefix", botPrefix); Config.AppSettings.Add("ServerID", serverId); - - Config.AppSettings.SaveToFile(); - - AnsiConsole.MarkupLine("[bold]Config saved ![/]"); - + + await Config.AppSettings.SaveToFile(); + Config.Logger.Log("Config Saved", source: typeof(Installer)); } } diff --git a/DiscordBot/Program.cs b/DiscordBot/Program.cs index 42f3437..48e0183 100644 --- a/DiscordBot/Program.cs +++ b/DiscordBot/Program.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; @@ -7,6 +8,7 @@ using DiscordBot.Utilities; using PluginManager.Bot; using PluginManager.Others; using PluginManager.Others.Actions; +using PluginManager.UX; using Spectre.Console; using static PluginManager.Config; @@ -24,7 +26,7 @@ public class Program PreLoadComponents(args).Wait(); if (!AppSettings.ContainsKey("ServerID") || !AppSettings.ContainsKey("token") || !AppSettings.ContainsKey("prefix")) - Installer.GenerateStartupConfig(); + Installer.GenerateStartupConfig().Wait(); HandleInput().Wait(); } @@ -87,7 +89,6 @@ public class Program /// /// Handle user input arguments from the startup of the application /// - /// The arguments private static async Task HandleInput() { await StartNoGui(); @@ -100,12 +101,10 @@ public class Program { if (ex.Message == "No process is on the other end of the pipe." || (uint)ex.HResult == 0x800700E9) { - if (AppSettings.ContainsKey("LaunchMessage")) - AppSettings.Add("LaunchMessage", - "An error occured while closing the bot last time. Please consider closing the bot using the &rexit&c method !\n" + - "There is a risk of losing all data or corruption of the save file, which in some cases requires to reinstall the bot !" - ); - + UxHandler.ShowMessageBox("SethBot", "An error occured while closing the bot last time. Please consider closing the bot using the &rexit&c method !\n" + + "There is a risk of losing all data or corruption of the save file, which in some cases requires to reinstall the bot !", MessageBoxType.Error).Wait(); + + Logger.Log("An error occured while closing the bot last time. Please consider closing the bot using the &rexit&c method !\n" + "There is a risk of losing all data or corruption of the save file, which in some cases requires to reinstall the bot !", source: typeof(Program), type: LogType.ERROR diff --git a/PluginManager/Bot/Boot.cs b/PluginManager/Bot/Boot.cs index 5ac16a3..b85ec98 100644 --- a/PluginManager/Bot/Boot.cs +++ b/PluginManager/Bot/Boot.cs @@ -4,6 +4,7 @@ using Discord; using Discord.Commands; using Discord.WebSocket; using PluginManager.Others; +using PluginManager.UX; namespace PluginManager.Bot; @@ -121,6 +122,7 @@ public class Boot private Task Ready() { isReady = true; + UxHandler.ShowNotification("SethBot", "Seth Discord Bot is now up and running !").Wait(); return Task.CompletedTask; } diff --git a/PluginManager/Config.cs b/PluginManager/Config.cs index 2b32f52..b23daa5 100644 --- a/PluginManager/Config.cs +++ b/PluginManager/Config.cs @@ -1,9 +1,11 @@ using System; using System.IO; using System.Threading.Tasks; +using Avalonia.Controls.Notifications; using PluginManager.Bot; using PluginManager.Others; using PluginManager.Others.Logger; +using OperatingSystem = System.OperatingSystem; namespace PluginManager; @@ -30,15 +32,30 @@ public class Config AppSettings["LogFolder"] = "./Data/Logs"; + if (OperatingSystem.IsLinux()) + { + var windowManager = Environment.GetEnvironmentVariable("XDG_CURRENT_DESKTOP"); + AppSettings["UI"] = windowManager switch + { + "KDE" => "KDE", + "GNOME" => "GNOME", + _ => "CONSOLE" + }; + } else AppSettings["UI"] = "CONSOLE"; + Logger = new Logger(false, true, AppSettings["LogFolder"] + $"/{DateTime.Today.ToShortDateString().Replace("/", "")}.log" ); ArchiveManager.Initialize(); - + + UX.UxHandler.Init(); _isLoaded = true; - + + Logger.Log(message: "Config initialized", source: typeof(Config)); + + } } diff --git a/PluginManager/PluginManager.csproj b/PluginManager/PluginManager.csproj index 4ec873e..f61b9f8 100644 --- a/PluginManager/PluginManager.csproj +++ b/PluginManager/PluginManager.csproj @@ -1,6 +1,6 @@ - net6.0 + net8.0 enable @@ -12,7 +12,16 @@ + + + + + + + ..\..\..\.nuget\packages\spectre.console\0.47.0\lib\net7.0\Spectre.Console.dll + + \ No newline at end of file diff --git a/PluginManager/UX/IOutputModel.cs b/PluginManager/UX/IOutputModel.cs new file mode 100644 index 0000000..fdd9387 --- /dev/null +++ b/PluginManager/UX/IOutputModel.cs @@ -0,0 +1,29 @@ +using System.Threading.Tasks; + +namespace PluginManager.UX; + +public enum MessageBoxType +{ + Info, + Warning, + Error +} + +public enum MessageBoxButtons +{ + YesNo, + YesNoCancel, + ContinueCancel, +} + +internal interface IOutputModel +{ + + internal Task ShowMessageBox(string title, string message, MessageBoxType type); + internal Task ShowInputBox(string title, string message); + + internal Task ShowMessageBox(string message); + internal Task ShowMessageBox(string title, string message, MessageBoxButtons buttons, bool isWarning); + + internal Task ShowNotification(string title, string message, int timeout_seconds = 5); +} diff --git a/PluginManager/UX/Linux/KDE.cs b/PluginManager/UX/Linux/KDE.cs new file mode 100644 index 0000000..3d3673e --- /dev/null +++ b/PluginManager/UX/Linux/KDE.cs @@ -0,0 +1,75 @@ +using System.Diagnostics; +using System.Threading.Tasks; + +namespace PluginManager.UX.Linux; + +internal class KDE : IOutputModel +{ + + public async Task ShowMessageBox(string title, string message, MessageBoxType type) + { + var process = new Process(); + process.StartInfo.FileName = "kdialog"; + + string typeStr = type switch + { + MessageBoxType.Info => "msgbox", + MessageBoxType.Warning => "sorry", + MessageBoxType.Error => "error", + _ => "info" + }; + + process.StartInfo.Arguments = $"--title \"{title}\" --{typeStr} \"{message}\""; + process.Start(); + await process.WaitForExitAsync(); + } + + public async Task ShowInputBox(string title, string message) + { + var process = new Process(); + process.StartInfo.FileName = "kdialog"; + process.StartInfo.Arguments = $"--title \"{title}\" --inputbox \"{message}\""; + process.StartInfo.RedirectStandardOutput = true; + process.Start(); + + await process.WaitForExitAsync(); + return await process.StandardOutput.ReadToEndAsync(); + } + + public async Task ShowMessageBox(string message) + { + var process = new Process(); + process.StartInfo.FileName = "kdialog"; + process.StartInfo.Arguments = $"--msgbox \"{message}\""; + process.Start(); + await process.WaitForExitAsync(); + } + + public async Task ShowMessageBox(string title, string message, MessageBoxButtons buttons, bool isWarning) + { + var process = new Process(); + process.StartInfo.FileName = "kdialog"; + + string buttonsStr = buttons switch + { + MessageBoxButtons.YesNo => "yesno", + MessageBoxButtons.YesNoCancel => "yesnocancel", + MessageBoxButtons.ContinueCancel => "continuecancel", + _ => "yesno" + }; + string typeStr = isWarning ? "warning" : ""; + process.StartInfo.Arguments = $"--title \"{title}\" --{typeStr}{buttonsStr} \"{message}\""; + process.Start(); + await process.WaitForExitAsync(); + return process.ExitCode; + } + + public async Task ShowNotification(string title, string message, int timeout_seconds = 5) + { + var process = new Process(); + process.StartInfo.FileName = "kdialog"; + process.StartInfo.Arguments = $"--title \"{title}\" --passivepopup \"{message}\" {timeout_seconds}"; + process.Start(); + await process.WaitForExitAsync(); + } +} diff --git a/PluginManager/UX/Other/Console.cs b/PluginManager/UX/Other/Console.cs new file mode 100644 index 0000000..94132e0 --- /dev/null +++ b/PluginManager/UX/Other/Console.cs @@ -0,0 +1,51 @@ + +using System.Threading.Tasks; +using Spectre.Console; + +namespace PluginManager.UX.Other; + + +internal class Console : IOutputModel +{ + + public Task ShowMessageBox(string title, string message, MessageBoxType type) + { + AnsiConsole.Markup(title); + AnsiConsole.Markup(message); + + + return Task.CompletedTask; + } + + public Task ShowInputBox(string title, string message) + { + AnsiConsole.Markup(title); + AnsiConsole.Markup(message); + + string input = AnsiConsole.Ask("Please enter the value:"); + + return Task.FromResult(input); + } + + public Task ShowMessageBox(string message) + { + AnsiConsole.Markup(message); + return Task.CompletedTask; + } + + public Task ShowMessageBox(string title, string message,MessageBoxButtons buttons, bool isWarning) + { + AnsiConsole.Markup(title); + AnsiConsole.Markup(message); + + return Task.FromResult(0); + } + + public Task ShowNotification(string title, string message, int timeout_seconds = 5) + { + AnsiConsole.Markup(title); + AnsiConsole.Markup(message); + + return Task.CompletedTask; + } +} diff --git a/PluginManager/UX/UxHandler.cs b/PluginManager/UX/UxHandler.cs new file mode 100644 index 0000000..d127cf0 --- /dev/null +++ b/PluginManager/UX/UxHandler.cs @@ -0,0 +1,42 @@ +using System.Threading.Tasks; + +namespace PluginManager.UX; + +public static class UxHandler +{ + private static IOutputModel _model; + + public static void Init() + { + if (Config.AppSettings["UI"] == "KDE") + _model = new Linux.KDE(); + else + _model = new Other.Console(); + } + + public static async Task ShowMessageBox(string title, string message, MessageBoxType type = MessageBoxType.Info) + { + await _model.ShowMessageBox(title, message, type); + } + + public static async Task ShowInputBox(string title, string message) + { + return await _model.ShowInputBox(title, message); + } + + public static async Task ShowMessageBox(string message) + { + await _model.ShowMessageBox(message); + } + + public static async Task ShowMessageBox(string title, string message, MessageBoxButtons buttons, bool isWarning) + { + return await _model.ShowMessageBox(title, message, buttons, isWarning); + } + + public static async Task ShowNotification(string title, string message, int timeout_seconds = 5) + { + await _model.ShowNotification(title, message, timeout_seconds); + } + +}