From e6238fcc9ac8e2a13fb6aa90a207ff947c756c7a Mon Sep 17 00:00:00 2001 From: AlanMoonbase Date: Sun, 29 Jun 2025 15:56:27 -0700 Subject: [PATCH] Implement Logging Fix Invocation Exceptions In Some Animated Form Controls Remove Call To `Login` Gateway Method --- .../Services/GatewayService/GatewayService.cs | 4 -- .../Forms/CurrencyJackpotSpinner.cs | 2 + qtc-net-client-2/Forms/Main.cs | 64 +++++++++++++++---- qtc-net-client-2/Program.cs | 6 +- .../Properties/Resources.Designer.cs | 2 +- qtc-net-client-2/Properties/Resources.resx | 2 +- qtc-net-client-2/Services/LoggingService.cs | 52 +++++++++++++++ 7 files changed, 113 insertions(+), 19 deletions(-) create mode 100644 qtc-net-client-2/Services/LoggingService.cs diff --git a/QtCNETAPI/Services/GatewayService/GatewayService.cs b/QtCNETAPI/Services/GatewayService/GatewayService.cs index 4c7fdc3..3c4b978 100644 --- a/QtCNETAPI/Services/GatewayService/GatewayService.cs +++ b/QtCNETAPI/Services/GatewayService/GatewayService.cs @@ -63,10 +63,6 @@ namespace QtCNETAPI.Services.GatewayService // start connection await HubConnection.StartAsync(); - - if (HubConnection != null && HubConnection.State == HubConnectionState.Connected) - // send login hub method - await HubConnection.SendAsync("LoginHub", _apiService.CurrentUser); } public async Task StopAsync() diff --git a/qtc-net-client-2/Forms/CurrencyJackpotSpinner.cs b/qtc-net-client-2/Forms/CurrencyJackpotSpinner.cs index ea43d88..23fce7f 100644 --- a/qtc-net-client-2/Forms/CurrencyJackpotSpinner.cs +++ b/qtc-net-client-2/Forms/CurrencyJackpotSpinner.cs @@ -68,12 +68,14 @@ namespace qtc_net_client_2.Forms while (_audioService.OutputDevice?.PlaybackState == NAudio.Wave.PlaybackState.Playing) { + if (!IsHandleCreated) return; label.BeginInvoke(delegate () { label.Text = $"{rnd.Next(0, 300)} Q's Won"; }); await Task.Delay(10); } var win = rnd.Next(0, 300); + if (!IsHandleCreated) return; label.BeginInvoke(delegate () { label.Text = $"{win} Q's Won"; diff --git a/qtc-net-client-2/Forms/Main.cs b/qtc-net-client-2/Forms/Main.cs index e4ef9b0..52ac754 100644 --- a/qtc-net-client-2/Forms/Main.cs +++ b/qtc-net-client-2/Forms/Main.cs @@ -15,6 +15,7 @@ namespace qtc_net_client_2 private IGatewayService _gatewayService; private Config _config; private AudioService AudioService = new(); + private LoggingService LoggingService; private List RoomList = []; private List OnlineUsers = []; @@ -22,17 +23,20 @@ namespace qtc_net_client_2 private List Contacts = []; private bool FirstMinimize = true; - public Main(IApiService apiService, IGatewayService gatewayService, Config config) + public Main(IApiService apiService, IGatewayService gatewayService, Config config, LoggingService loggingService) { _apiService = apiService; _gatewayService = gatewayService; _config = config; + LoggingService = loggingService; InitializeComponent(); } private async void frmMain_Load(object sender, EventArgs e) { + LoggingService.LogString("Main Form Loaded"); + // start request notif blink task Thread blinkThread = new Thread(async () => await StartRequestNotifBlankLoop(lblRequestNotif)); blinkThread.Start(); @@ -73,6 +77,8 @@ namespace qtc_net_client_2 Chat frmChat = new Chat(_gatewayService, _apiService); frmChat.Show(); + + LoggingService.LogString("User Has Joined Lobby Room"); return; } @@ -84,6 +90,8 @@ namespace qtc_net_client_2 Chat frmChat = new Chat(_gatewayService, _apiService); frmChat.Show(); + + LoggingService.LogString($"User Has Joined {room.Name}"); } } } @@ -118,7 +126,7 @@ namespace qtc_net_client_2 pbUserPfp.Image = Image.FromStream(ms); ms.Dispose(); } - } + } else LoggingService.LogString($"User Has No Profile Picture Or It Could Not Be Loaded.\n{pfpRes.Message}"); } } } @@ -150,8 +158,11 @@ namespace qtc_net_client_2 var res = await _apiService.GetUserInformationAsync(user!.Id); var pfpRes = await _apiService.GetUserProfilePic(user!.Id); + if (pfpRes != null && !pfpRes.Success) LoggingService.LogString($"User Has No Profile Picture Or It Could Not Be Loaded.\n{pfpRes.Message}"); + if (res.Data != null && res.Success) { + LoggingService.LogString($"Opening Profile For User '{res.Data.Username}'"); Profile frmProfile = new Profile(res.Data, pfpRes, _apiService, _gatewayService); frmProfile.Show(); } @@ -185,8 +196,11 @@ namespace qtc_net_client_2 var res = await _apiService.GetUserInformationAsync(user!.Id); var pfpRes = await _apiService.GetUserProfilePic(user!.Id); + if (pfpRes != null && !pfpRes.Success) LoggingService.LogString($"User Has No Profile Picture Or It Could Not Be Loaded.\n{pfpRes.Message}"); + if (res.Data != null && res.Success) { + LoggingService.LogString($"Opening Profile For User '{res.Data.Username}'"); Profile frmProfile = new Profile(res.Data, pfpRes, _apiService, _gatewayService); frmProfile.Show(); } @@ -306,8 +320,11 @@ namespace qtc_net_client_2 var res = await _apiService.GetUserInformationAsync(user!.Id); var pfpRes = await _apiService.GetUserProfilePic(user!.Id); + if (pfpRes != null && !pfpRes.Success) LoggingService.LogString($"User Has No Profile Picture Or It Could Not Be Loaded.\n{pfpRes.Message}"); + if (res.Data != null && res.Success) { + LoggingService.LogString($"Opening Profile For User '{res.Data.Username}'"); Profile frmProfile = new Profile(res.Data, pfpRes, _apiService, _gatewayService); frmProfile.Show(); } @@ -349,6 +366,9 @@ namespace qtc_net_client_2 // double check if (_apiService.CurrentUser != null && _apiService.SessionToken != null) { + LoggingService.LogString($"Logged In As '{_apiService.CurrentUser.Username}'"); + LoggingService.LogString("Starting SignalR Connection..."); + // start gateway connection await _gatewayService.StartAsync(); @@ -364,6 +384,8 @@ namespace qtc_net_client_2 if (_gatewayService.HubConnection != null && _gatewayService.HubConnection.State == Microsoft.AspNetCore.SignalR.Client.HubConnectionState.Connected) { + LoggingService.LogString("Connected To SignalR Succesfully."); + // we are fully logged in, get current user profile pic and set up ui llblSignIn.Visible = false; lblWelcome.Text = $"Welcome, {_apiService.CurrentUser.Username}"; @@ -430,12 +452,16 @@ namespace qtc_net_client_2 else llblClaimSpin.Visible = false; if (_config.StartMinimized) WindowState = FormWindowState.Minimized; + + LoggingService.LogString("Client Ready"); } } } private async Task RefreshOnlineUsersList() { + LoggingService.LogString("Refreshing Online Users List..."); + if (InvokeRequired) { await Invoke(async delegate () @@ -469,6 +495,8 @@ namespace qtc_net_client_2 private async Task RefreshUserDirectory() { + LoggingService.LogString("Refreshing All Users List..."); + // get all users on server var userList = await _apiService.GetAllUsersAsync(); @@ -497,6 +525,8 @@ namespace qtc_net_client_2 private async Task RefreshRoomsList() { + LoggingService.LogString("Refreshing Rooms List..."); + if (InvokeRequired) { await Invoke(async delegate () @@ -536,6 +566,8 @@ namespace qtc_net_client_2 private async Task RefreshContactsList() { + LoggingService.LogString("Refreshing Contacts List..."); + if (InvokeRequired) { await Invoke(async delegate () @@ -682,7 +714,9 @@ namespace qtc_net_client_2 { while (true) { - if (InvokeRequired && label.IsHandleCreated) + if (!IsHandleCreated) { LoggingService.LogString("Form Handle Wasn't Created"); return; } + + if (InvokeRequired) { await Invoke(async delegate () { @@ -692,13 +726,11 @@ namespace qtc_net_client_2 await Task.Delay(500); }); } - else if (label.IsHandleCreated) - { - label.ForeColor = Color.Red; - await Task.Delay(500); - label.ForeColor = Color.Blue; - await Task.Delay(500); - } + + label.ForeColor = Color.Red; + await Task.Delay(500); + label.ForeColor = Color.Blue; + await Task.Delay(500); } } @@ -712,7 +744,7 @@ namespace qtc_net_client_2 ilProfilePics.Images.Add(userId, Image.FromStream(ms)); ms.Dispose(); } - } + } else if (result != null) LoggingService.LogString($"User Has No Profile Picture Or It Could Not Be Loaded.\n{result.Message}"); } public void RefreshCurrencyCounter() @@ -732,11 +764,13 @@ namespace qtc_net_client_2 private async void _gatewayService_OnServerDisconnect(object? sender, EventArgs e) { + LoggingService.LogString("Disconnected From SignalR"); + if (DialogResult == DialogResult.OK) return; var args = (ServerConnectionClosedEventArgs)e; string? error = string.Empty; - if (args.Error != null) error = args.Error.Message; + if (args.Error != null) { error = args.Error.Message; LoggingService.LogString($"{args.Error.Message}\n{args.Error.StackTrace}"); } // disconnect can sometimes be caused by an expired JWT token, attempt connection restart await _gatewayService.StopAsync(); @@ -781,10 +815,14 @@ namespace qtc_net_client_2 { var args = (ServerConfigEventArgs)e; + LoggingService.LogString($"Server Config Received"); + LoggingService.LogModel(args.ServerConfig); + if (args.ServerConfig != null) { if (args.ServerConfig.IsDown) { + LoggingService.LogString("Server Is Marked As Down"); MessageBox.Show($"Sorry, This Server Is Currently Down.\nMessage: {args.ServerConfig.IsDownMessage}\n\nPlease Try Again Later"); if (_gatewayService.HubConnection != null && _gatewayService.HubConnection.State == Microsoft.AspNetCore.SignalR.Client.HubConnectionState.Connected) @@ -801,6 +839,8 @@ namespace qtc_net_client_2 { var args = (DirectMessageEventArgs)e; + LoggingService.LogString($"Direct Message Received From '{args.User.Username}'"); + DirectMessage? existingForm = (DirectMessage?)Application.OpenForms.Cast
().FirstOrDefault(e => e.Name == "DirectMessage"); if (existingForm != null && existingForm.User.Id == args.User.Id) { diff --git a/qtc-net-client-2/Program.cs b/qtc-net-client-2/Program.cs index a26675a..edbf47f 100644 --- a/qtc-net-client-2/Program.cs +++ b/qtc-net-client-2/Program.cs @@ -15,6 +15,9 @@ namespace qtc_net_client_2 [STAThread] static async Task Main() { + // first thing, create a new log + LoggingService loggingService = new(); + Config clientConfig = new Config(); if(System.Diagnostics.Debugger.IsAttached) @@ -68,10 +71,11 @@ namespace qtc_net_client_2 // To customize application configuration such as set high DPI settings or default font, // see https://aka.ms/applicationconfiguration. ApplicationConfiguration.Initialize(); - Application.Run(new Main(api, gateway, clientConfig)); + Application.Run(new Main(api, gateway, clientConfig, loggingService)); // if application loop is exited, dispose everything await gateway.DisposeAsync(); + loggingService.Dispose(); api = null!; // shut up compiler >:( gateway = null!; diff --git a/qtc-net-client-2/Properties/Resources.Designer.cs b/qtc-net-client-2/Properties/Resources.Designer.cs index 8023512..65038c5 100644 --- a/qtc-net-client-2/Properties/Resources.Designer.cs +++ b/qtc-net-client-2/Properties/Resources.Designer.cs @@ -81,7 +81,7 @@ namespace qtc_net_client_2.Properties { } /// - /// Looks up a localized string similar to 4.1.1. + /// Looks up a localized string similar to 4.2. /// internal static string AssemblyVersion { get { diff --git a/qtc-net-client-2/Properties/Resources.resx b/qtc-net-client-2/Properties/Resources.resx index 40ef658..136f5d3 100644 --- a/qtc-net-client-2/Properties/Resources.resx +++ b/qtc-net-client-2/Properties/Resources.resx @@ -161,7 +161,7 @@ ..\Icons\MessageIcon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - 4.1.1 + 4.2 ..\Resources\LoginBanner.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a diff --git a/qtc-net-client-2/Services/LoggingService.cs b/qtc-net-client-2/Services/LoggingService.cs new file mode 100644 index 0000000..9bf45af --- /dev/null +++ b/qtc-net-client-2/Services/LoggingService.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Diagnostics; +using System.Text.Json; + +namespace qtc_net_client_2.Services +{ + public class LoggingService : IDisposable + { + private DateTime LogDate { get; set; } + private string LogFilePath { get; set; } + private StreamWriter LogFile { get; set; } + public LoggingService() + { + LogDate = DateTime.Now; + LogFilePath = $"./Logs/QtCClientLog_{LogDate.ToString("ddMMyyy-hhmm")}.log"; + + // create log file + + if (!Directory.Exists("./Logs")) Directory.CreateDirectory("./Logs"); + LogFile = new StreamWriter(File.Create(LogFilePath)); + + Debug.WriteLine($"Log File Created At {LogFilePath}"); + } + + public void LogString(string message) + { + Debug.WriteLine($"({DateTime.Now.ToLocalTime().ToString("hh:mm")}) {message}"); + LogFile.WriteLine($"({DateTime.Now.ToLocalTime().ToString("hh:mm")}) {message}"); + } + + public void LogModel(T model) + { + // serialize the model as json + string modelSerialized = JsonSerializer.Serialize(model, options: new JsonSerializerOptions { WriteIndented = true }); + + // log it + Debug.WriteLine($"({DateTime.Now.ToLocalTime().ToString("hh:mm")}) {modelSerialized}"); + LogFile.WriteLine($"({DateTime.Now.ToLocalTime().ToString("hh:mm")}) {modelSerialized}"); + } + + public void Dispose() + { + LogFile.WriteLine("--- END OF LOG ---"); + LogFile.Close(); + LogFile.Dispose(); + } + } +}