Implement Logging

Fix Invocation Exceptions In Some Animated Form Controls
Remove Call To `Login` Gateway Method
This commit is contained in:
Alan Moon 2025-06-29 15:56:27 -07:00
parent 315be1d4ad
commit e6238fcc9a
7 changed files with 113 additions and 19 deletions

View File

@ -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()

View File

@ -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";

View File

@ -15,6 +15,7 @@ namespace qtc_net_client_2
private IGatewayService _gatewayService;
private Config _config;
private AudioService AudioService = new();
private LoggingService LoggingService;
private List<Room> RoomList = [];
private List<UserInformationDto> OnlineUsers = [];
@ -22,17 +23,20 @@ namespace qtc_net_client_2
private List<UserInformationDto> 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<Form>().FirstOrDefault(e => e.Name == "DirectMessage");
if (existingForm != null && existingForm.User.Id == args.User.Id)
{

View File

@ -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!;

View File

@ -81,7 +81,7 @@ namespace qtc_net_client_2.Properties {
}
/// <summary>
/// Looks up a localized string similar to 4.1.1.
/// Looks up a localized string similar to 4.2.
/// </summary>
internal static string AssemblyVersion {
get {

View File

@ -161,7 +161,7 @@
<value>..\Icons\MessageIcon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="AssemblyVersion" xml:space="preserve">
<value>4.1.1</value>
<value>4.2</value>
</data>
<data name="LoginBanner" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\LoginBanner.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>

View File

@ -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>(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();
}
}
}