993 lines
44 KiB
C#
993 lines
44 KiB
C#
using QtCNETAPI.Dtos.User;
|
|
using QtCNETAPI.Services.ApiService;
|
|
using QtCNETAPI.Services.GatewayService;
|
|
using QtCNETAPI.Events;
|
|
using QtCNETAPI.Models;
|
|
using qtc_net_client_2.Forms;
|
|
using qtc_net_client_2.Services;
|
|
using qtc_net_client_2.ClientModel;
|
|
using System.Threading.Tasks;
|
|
using QtCNETAPI.Schema;
|
|
using QtCNETAPI.Services;
|
|
|
|
namespace qtc_net_client_2
|
|
{
|
|
public partial class Main : Form
|
|
{
|
|
private IApiService _apiService;
|
|
private IGatewayService _gatewayService;
|
|
|
|
private Config _config;
|
|
private ServerConfig _serverConfig;
|
|
private AudioService AudioService = new();
|
|
private LoggingService LoggingService;
|
|
|
|
public List<Room> RoomList = [];
|
|
public List<UserInformationDto> UserDirectory = [];
|
|
public List<Contact> Contacts = [];
|
|
|
|
private bool FirstMinimize = true;
|
|
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();
|
|
|
|
// check if client is already logged in
|
|
if (_apiService.CurrentUser == null)
|
|
{
|
|
// not logged in, load the login form
|
|
Login frmLogin = new Login(_apiService);
|
|
var result = frmLogin.ShowDialog();
|
|
|
|
if (result == DialogResult.OK)
|
|
await OnSuccessfulLogin();
|
|
}
|
|
}
|
|
|
|
private async void llblSignIn_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
|
{
|
|
// just reshow the login dialog lol
|
|
Login frmLogin = new Login(_apiService);
|
|
var result = frmLogin.ShowDialog();
|
|
|
|
if (result == DialogResult.OK)
|
|
await OnSuccessfulLogin();
|
|
}
|
|
|
|
private async void lbRooms_DoubleClick(object sender, EventArgs e)
|
|
{
|
|
if (lbRooms.SelectedItems.Count > 0)
|
|
{
|
|
string? selectedRoom = (string?)lbRooms.SelectedItems[lbRooms.SelectedItems.Count - 1];
|
|
if (selectedRoom != null)
|
|
{
|
|
if (selectedRoom == "Lobby")
|
|
{
|
|
// join lobby
|
|
if (!_gatewayService.InLobby) await _gatewayService.JoinLobbyAsync();
|
|
|
|
ChatRoom frmChat = new ChatRoom(_gatewayService, _apiService);
|
|
frmChat.Show();
|
|
|
|
LoggingService.LogString("User Has Joined Lobby Room");
|
|
return;
|
|
}
|
|
|
|
// join the room
|
|
Room? room = RoomList.FirstOrDefault(e => e.Name == selectedRoom);
|
|
if (room != null)
|
|
{
|
|
if (_gatewayService.CurrentRoom != room) await _gatewayService.JoinRoomAsync(room);
|
|
|
|
ChatRoom frmChat = new ChatRoom(_gatewayService, _apiService);
|
|
frmChat.Show();
|
|
|
|
LoggingService.LogString($"User Has Joined {room.Name}");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void pbUserPfp_Click(object sender, EventArgs e)
|
|
{
|
|
var args = (MouseEventArgs)e;
|
|
if (args.Button == MouseButtons.Right) return;
|
|
|
|
Thread t = new Thread(new ThreadStart(async () =>
|
|
{
|
|
using (OpenFileDialog openFileDialog = new OpenFileDialog())
|
|
{
|
|
openFileDialog.InitialDirectory = Environment.CurrentDirectory;
|
|
openFileDialog.Title = "Select New Profile Picture";
|
|
openFileDialog.Filter = "Image Files (*.png, *.jpg)|*.png;*.jpg";
|
|
|
|
if (openFileDialog.ShowDialog() == DialogResult.OK)
|
|
{
|
|
// upload to server with api endpoint
|
|
var res = await _apiService.UpdateUserProfilePic(openFileDialog.FileName);
|
|
|
|
if (res.Success)
|
|
{
|
|
// update profile pic in ui
|
|
var pfpRes = await _apiService.GetUserProfilePic(_apiService.CurrentUser.Id);
|
|
if (pfpRes.Success && pfpRes.Data != null)
|
|
{
|
|
using (var ms = new MemoryStream(pfpRes.Data))
|
|
{
|
|
pbUserPfp.Image = Image.FromStream(ms);
|
|
ms.Dispose();
|
|
}
|
|
}
|
|
else LoggingService.LogString($"User Has No Profile Picture Or It Could Not Be Loaded.\n{pfpRes.Message}");
|
|
}
|
|
}
|
|
}
|
|
}));
|
|
|
|
t.SetApartmentState(ApartmentState.STA);
|
|
t.Start();
|
|
}
|
|
|
|
private void llblSignOut_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
|
{
|
|
if (MessageBox.Show("Are You Sure You Want To Sign Out?\nThis Deletes Your session.token, Requiring You To Sign In Again", "are you sure...?", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
|
|
{
|
|
File.Delete("./session.token");
|
|
Environment.Exit(0);
|
|
}
|
|
}
|
|
|
|
private void llblEditProfile_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
|
{
|
|
ProfileEdit frmProfileEdit = new ProfileEdit(_apiService);
|
|
frmProfileEdit.ShowDialog();
|
|
}
|
|
|
|
private async void lvContacts_DoubleClick(object sender, EventArgs e)
|
|
{
|
|
if (lvContacts.SelectedItems.Count > 0)
|
|
{
|
|
string? selectedUser = (string?)lvContacts.SelectedItems[lvContacts.SelectedItems.Count - 1].Text;
|
|
|
|
if (selectedUser != null)
|
|
{
|
|
// split from [ if it exists
|
|
if (selectedUser.Contains('[')) selectedUser = selectedUser.Split('[', options: StringSplitOptions.TrimEntries)[0];
|
|
|
|
// get user info and open profile dialog
|
|
var user = UserDirectory.FirstOrDefault(e => e.Username == selectedUser);
|
|
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, Contacts, _apiService, _gatewayService);
|
|
frmProfile.Show();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void frmMain_Resize(object sender, EventArgs e)
|
|
{
|
|
if (WindowState == FormWindowState.Minimized && _config.MinimizeToTray)
|
|
{
|
|
Hide();
|
|
niMain.Visible = true;
|
|
if (FirstMinimize)
|
|
{
|
|
niMain.ShowBalloonTip(10,
|
|
"I'm over here!",
|
|
"QtC.NET Mimimizes To Tray By Default. To Change This Behaviour, Refer To config.json",
|
|
ToolTipIcon.Info);
|
|
FirstMinimize = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void niMain_DoubleClick(object sender, EventArgs e)
|
|
{
|
|
Show();
|
|
WindowState = FormWindowState.Normal;
|
|
niMain.Visible = false;
|
|
}
|
|
|
|
private async void frmMain_FormClosed(object sender, FormClosedEventArgs e)
|
|
{
|
|
DialogResult = DialogResult.OK;
|
|
|
|
// ensure the gateway stops the connection and disposes properly
|
|
await _gatewayService.StopAsync();
|
|
await _gatewayService.DisposeAsync();
|
|
}
|
|
|
|
private async void ctxmChangeStatus_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
|
|
{
|
|
if (e.ClickedItem != null)
|
|
{
|
|
UserStatus userStatus = UserStatus.Unknown;
|
|
switch (e.ClickedItem.Name)
|
|
{
|
|
case "onlineToolStripMenuItem":
|
|
userStatus = UserStatus.Online;
|
|
onlineToolStripMenuItem.Checked = true;
|
|
awayToolStripMenuItem.Checked = false;
|
|
doNotDisturbToolStripMenuItem.Checked = false;
|
|
invisibleToolStripMenuItem.Checked = false;
|
|
break;
|
|
case "awayToolStripMenuItem":
|
|
userStatus = UserStatus.Away;
|
|
onlineToolStripMenuItem.Checked = false;
|
|
awayToolStripMenuItem.Checked = true;
|
|
doNotDisturbToolStripMenuItem.Checked = false;
|
|
invisibleToolStripMenuItem.Checked = false;
|
|
break;
|
|
case "doNotDisturbToolStripMenuItem":
|
|
userStatus = UserStatus.DoNotDisturb;
|
|
onlineToolStripMenuItem.Checked = false;
|
|
awayToolStripMenuItem.Checked = false;
|
|
doNotDisturbToolStripMenuItem.Checked = true;
|
|
invisibleToolStripMenuItem.Checked = false;
|
|
break;
|
|
case "invisibleToolStripMenuItem":
|
|
userStatus = UserStatus.Offline;
|
|
onlineToolStripMenuItem.Checked = false;
|
|
awayToolStripMenuItem.Checked = false;
|
|
doNotDisturbToolStripMenuItem.Checked = false;
|
|
invisibleToolStripMenuItem.Checked = true;
|
|
break;
|
|
}
|
|
|
|
// set it
|
|
await _gatewayService.UpdateStatus((int)userStatus);
|
|
}
|
|
}
|
|
|
|
private void btnAddRoom_Click(object sender, EventArgs e)
|
|
{
|
|
CreateRoom createRoom = new CreateRoom(_apiService);
|
|
createRoom.ShowDialog();
|
|
}
|
|
|
|
private async void llblClaimSpin_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
|
{
|
|
CurrencyJackpotSpinner tokenJackpotSpinner = new CurrencyJackpotSpinner();
|
|
var frmResult = tokenJackpotSpinner.ShowDialog();
|
|
|
|
if (frmResult == DialogResult.OK && tokenJackpotSpinner.TokensWon > 0)
|
|
{
|
|
// claim
|
|
var result = await _apiService.AddCurrencyToCurrentUser(tokenJackpotSpinner.TokensWon, true);
|
|
if (result.Success)
|
|
{
|
|
lblCurrencyAmount.Text = _apiService.CurrentUser.CurrencyAmount.ToString("N0");
|
|
llblClaimSpin.Visible = false;
|
|
}
|
|
else MessageBox.Show("We Were Unable To Claim Your Prize At This Time. Please Try Again Later.", "Uh Oh.", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
}
|
|
}
|
|
|
|
private async void lbUserDirectory_DoubleClick(object sender, EventArgs e)
|
|
{
|
|
if (lvUserDirectory.SelectedItems.Count > 0)
|
|
{
|
|
string? selectedUser = (string?)lvUserDirectory.SelectedItems[lvUserDirectory.SelectedItems.Count - 1].Text;
|
|
|
|
if (selectedUser != null)
|
|
{
|
|
// get user info and open profile dialog
|
|
var user = UserDirectory.FirstOrDefault(e => e.Username == selectedUser);
|
|
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, Contacts, _apiService, _gatewayService);
|
|
frmProfile.Show();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void lvGames_DoubleClick(object sender, EventArgs e)
|
|
{
|
|
if (lvGames.SelectedItems.Count > 0)
|
|
{
|
|
string? gameSelected = (string?)lvGames.SelectedItems[lvGames.SelectedItems.Count - 1].Tag;
|
|
|
|
switch (gameSelected)
|
|
{
|
|
case "StockMarketGame":
|
|
StockMarketGame stockMarketGame = new StockMarketGame(_apiService);
|
|
stockMarketGame.Show();
|
|
break;
|
|
case "GuessTheNumberGame":
|
|
GuessTheNumber guessTheNumber = new GuessTheNumber(_apiService);
|
|
guessTheNumber.Show();
|
|
break;
|
|
case "TicTacToeGame":
|
|
TicTacToeGame ticTacToeGame = new TicTacToeGame(_apiService, _config);
|
|
ticTacToeGame.Show();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private async void refreshToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
if (tbcMain.SelectedIndex == 0) await RefreshContactsList();
|
|
if (tbcMain.SelectedIndex == 1) await RefreshRoomsList();
|
|
if (tbcMain.SelectedIndex == 2) await RefreshUsers();
|
|
}
|
|
|
|
private void pbDonate_Click(object sender, EventArgs e)
|
|
{
|
|
DonationWindow donationWindow = new DonationWindow();
|
|
donationWindow.Show();
|
|
}
|
|
|
|
private async void tbcMain_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
if (tbcMain.SelectedIndex == 4)
|
|
{
|
|
// get store items
|
|
var storeItems = await _apiService.GetStoreItems();
|
|
if (storeItems != null && storeItems.Success && storeItems.Data != null)
|
|
{
|
|
ilStoreThumbnails.Images.Clear();
|
|
foreach (var item in storeItems.Data)
|
|
{
|
|
await GetAndAddStoreThumbnail(item);
|
|
var lvitem = lvStoreItems.Items.Add(new ListViewItem { Text = item.Name, Name = item.Id.ToString() });
|
|
lvitem.ImageKey = item.Id.ToString();
|
|
}
|
|
}
|
|
}
|
|
else lvStoreItems.Clear();
|
|
}
|
|
|
|
private async void lvStoreItems_DoubleClick(object sender, EventArgs e)
|
|
{
|
|
if (lvStoreItems.SelectedItems.Count > 0)
|
|
{
|
|
string? itemSelected = (string?)lvStoreItems.SelectedItems[lvStoreItems.SelectedItems.Count - 1].Name;
|
|
if (itemSelected != null)
|
|
{
|
|
// get item
|
|
var item = await _apiService.GetStoreItem(int.Parse(itemSelected));
|
|
if (item != null && item.Success && item.Data != null)
|
|
{
|
|
StoreItemDisplay storeItemDisplay = new StoreItemDisplay(item.Data, LoggingService, _apiService);
|
|
storeItemDisplay.ShowDialog();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void addRoomToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
CreateRoom createRoom = new CreateRoom(_apiService);
|
|
createRoom.ShowDialog();
|
|
}
|
|
|
|
private void ctxmAdminRoomList_Opening(object sender, System.ComponentModel.CancelEventArgs e)
|
|
{
|
|
if (lbRooms.SelectedItem == null)
|
|
deleteRoomToolStripMenuItem.Enabled = false;
|
|
else deleteRoomToolStripMenuItem.Enabled = true;
|
|
}
|
|
|
|
private void ctxmAdminUserList_Opening(object sender, System.ComponentModel.CancelEventArgs e)
|
|
{
|
|
if (lvUserDirectory.SelectedItems.Count > 0)
|
|
{
|
|
string? lvUserDirectoryItemSelected = (string?)lvUserDirectory.SelectedItems[lvUserDirectory.SelectedItems.Count - 1].Text;
|
|
if (lvUserDirectoryItemSelected != null && lvUserDirectoryItemSelected == _apiService.CurrentUser.Username)
|
|
{
|
|
deleteUserToolStripMenuItem.Enabled = false;
|
|
adminDirectMessageToolStripMenuItem.Enabled = false;
|
|
copyUserIDToClipboardToolStripMenuItem.Enabled = true;
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
deleteUserToolStripMenuItem.Enabled = false;
|
|
adminDirectMessageToolStripMenuItem.Enabled = false;
|
|
copyUserIDToClipboardToolStripMenuItem.Enabled = false;
|
|
return;
|
|
}
|
|
|
|
deleteUserToolStripMenuItem.Enabled = true;
|
|
adminDirectMessageToolStripMenuItem.Enabled = true;
|
|
copyUserIDToClipboardToolStripMenuItem.Enabled = true;
|
|
}
|
|
|
|
private void copyUserIDToClipboardToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
if (lvUserDirectory.SelectedItems.Count > 0)
|
|
{
|
|
string? itemSelected = (string?)lvUserDirectory.SelectedItems[lvUserDirectory.SelectedItems.Count - 1].Text;
|
|
if (itemSelected != null)
|
|
{
|
|
// get user
|
|
var user = UserDirectory.FirstOrDefault(e => e.Username == itemSelected);
|
|
if (user != null)
|
|
{
|
|
// clipboard requires STA apartment state
|
|
Thread thread = new(delegate () { Clipboard.SetText(user.Id); });
|
|
thread.SetApartmentState(ApartmentState.STA);
|
|
thread.Start();
|
|
|
|
MessageBox.Show("Copied!");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private async void deleteRoomToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
if (lbRooms.SelectedItems.Count > 0)
|
|
{
|
|
string? itemSelected = (string?)lbRooms.SelectedItems[lbRooms.SelectedItems.Count - 1];
|
|
if (itemSelected != null)
|
|
{
|
|
var dialogResult = MessageBox.Show("Are You Sure You Want To Delete This Room?\nThis will kick everyone currently in the room out.",
|
|
"are you sure..?",
|
|
MessageBoxButtons.YesNo,
|
|
MessageBoxIcon.Question);
|
|
|
|
if (dialogResult == DialogResult.Yes)
|
|
{
|
|
// get the room
|
|
var room = RoomList.FirstOrDefault(e => e.Name == itemSelected);
|
|
if (room != null)
|
|
{
|
|
var apiResult = await _apiService.DeleteRoomAsync(room.Id);
|
|
if (apiResult != null && apiResult.Success)
|
|
MessageBox.Show("Deleted!");
|
|
else
|
|
MessageBox.Show("There was an error deleting the room. Try Again?", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
}
|
|
else MessageBox.Show("This room is unknown. It may have already been deleted.");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private async void deleteUserToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
if (lvUserDirectory.SelectedItems.Count > 0)
|
|
{
|
|
string? itemSelected = (string?)lvUserDirectory.SelectedItems[lvUserDirectory.SelectedItems.Count - 1].Text;
|
|
if (itemSelected != null)
|
|
{
|
|
var dialogResult = MessageBox.Show("Are You Sure You Want To Delete This User?\n" +
|
|
"This should only be done as a last resort. You should take the proper percautions to ensure the user cannot make a new account.\n" +
|
|
"Proper moderation tools are coming soon.\n" +
|
|
"Doing this will also log out the user if they are logged in.",
|
|
"are you sure...?",
|
|
MessageBoxButtons.YesNo,
|
|
MessageBoxIcon.Warning);
|
|
|
|
if (dialogResult == DialogResult.Yes)
|
|
{
|
|
// get the user
|
|
var user = UserDirectory.FirstOrDefault(e => e.Username == itemSelected);
|
|
if (user != null)
|
|
{
|
|
var apiResult = await _apiService.DeleteUserById(user.Id);
|
|
if (apiResult != null && apiResult.Success)
|
|
MessageBox.Show("User Deleted!");
|
|
else
|
|
MessageBox.Show("There was an error deleting the user. Try Again?", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
}
|
|
else MessageBox.Show("This user is unknown. They may have already been deleted.");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private async void adminDirectMessageToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
if (lvUserDirectory.SelectedItems.Count > 0)
|
|
{
|
|
string? itemSelected = (string?)lvUserDirectory.SelectedItems[lvUserDirectory.SelectedItems.Count - 1].Text;
|
|
if (itemSelected != null)
|
|
{
|
|
// get the user
|
|
var user = UserDirectory.FirstOrDefault(e => e.Username == itemSelected);
|
|
if (user != null)
|
|
{
|
|
var userDto = await _apiService.GetUserInformationAsync(user.Id);
|
|
if(userDto != null && userDto.Success && userDto.Data != null)
|
|
{
|
|
// immediately start a dm chat with the user, the user will be informed immediately if the user is an admin
|
|
DirectMessage directMessage = new DirectMessage(_gatewayService, _apiService, userDto.Data, null);
|
|
directMessage.Show();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private async Task OnSuccessfulLogin()
|
|
{
|
|
// 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();
|
|
|
|
// subscribe to gateway events
|
|
_gatewayService.OnServerReconnecting += _gatewayService_OnServerReconnecting;
|
|
_gatewayService.OnServerReconnected += _gatewayService_OnServerReconnected;
|
|
_gatewayService.OnServerDisconnect += _gatewayService_OnServerDisconnect;
|
|
_gatewayService.OnDirectMessageReceived += _gatewayService_OnDirectMessageReceived;
|
|
_gatewayService.OnRefreshUserListsReceived += _gatewayService_OnRefreshUserListReceived;
|
|
_gatewayService.OnRefreshRoomListReceived += _gatewayService_OnRefreshRoomListReceived;
|
|
_gatewayService.OnRefreshContactsListReceived += _gatewayService_OnRefreshContactsListReceived;
|
|
_gatewayService.OnServerConfigReceived += _gatewayService_OnServerConfigReceived;
|
|
_gatewayService.OnUserForceLogout += _gatewayService_OnUserForceLogout;
|
|
|
|
_apiService.OnCurrentUserUpdate += _apiService_OnCurrentUserUpdate;
|
|
|
|
if (_gatewayService.HubConnection != null && _gatewayService.HubConnection.State == Microsoft.AspNetCore.SignalR.Client.HubConnectionState.Connected)
|
|
{
|
|
LoggingService.LogString("Connected To SignalR Succesfully.");
|
|
LoggingService.LogString("Building UI...");
|
|
|
|
// we are fully logged in, get current user profile pic and set up ui
|
|
llblSignIn.Visible = false;
|
|
lblWelcome.Text = $"Welcome, {_apiService.CurrentUser.Username}";
|
|
lblCurrencyAmount.Visible = true;
|
|
pbCurrencyIcon.Visible = true;
|
|
lblCurrencyAmount.Text = _apiService.CurrentUser.CurrencyAmount.ToString("N0");
|
|
llblSignOut.Visible = true;
|
|
llblEditProfile.Visible = true;
|
|
tbcMain.Enabled = true;
|
|
|
|
var pfpRes = await _apiService.GetUserProfilePic(_apiService.CurrentUser.Id);
|
|
if (pfpRes.Success && pfpRes.Data != null)
|
|
{
|
|
using (var ms = new MemoryStream(pfpRes.Data))
|
|
{
|
|
pbUserPfp.Image = Image.FromStream(ms);
|
|
ms.Dispose();
|
|
}
|
|
}
|
|
|
|
if (lvUserDirectory.Items.Count <= 0)
|
|
await RefreshUsers(); // prevent edge case where the refresh event never gets sent to connecting client
|
|
|
|
await RefreshContactsList();
|
|
await RefreshRoomsList();
|
|
|
|
// set status context menu checked
|
|
UserStatus cuStatus = (UserStatus)_apiService.CurrentUser.Status;
|
|
switch (cuStatus)
|
|
{
|
|
case UserStatus.Online:
|
|
onlineToolStripMenuItem.Checked = true;
|
|
awayToolStripMenuItem.Checked = false;
|
|
doNotDisturbToolStripMenuItem.Checked = false;
|
|
invisibleToolStripMenuItem.Checked = false;
|
|
break;
|
|
case UserStatus.Away:
|
|
onlineToolStripMenuItem.Checked = false;
|
|
awayToolStripMenuItem.Checked = true;
|
|
doNotDisturbToolStripMenuItem.Checked = false;
|
|
invisibleToolStripMenuItem.Checked = false;
|
|
break;
|
|
case UserStatus.DoNotDisturb:
|
|
onlineToolStripMenuItem.Checked = false;
|
|
awayToolStripMenuItem.Checked = false;
|
|
doNotDisturbToolStripMenuItem.Checked = true;
|
|
invisibleToolStripMenuItem.Checked = false;
|
|
break;
|
|
case UserStatus.Offline:
|
|
onlineToolStripMenuItem.Checked = false;
|
|
awayToolStripMenuItem.Checked = false;
|
|
doNotDisturbToolStripMenuItem.Checked = false;
|
|
invisibleToolStripMenuItem.Checked = true;
|
|
break;
|
|
}
|
|
|
|
var current = DateTime.UtcNow;
|
|
if (current > _apiService.CurrentUser.LastCurrencySpin.ToUniversalTime() || _apiService.CurrentUser.LastCurrencySpin == new DateTime()) llblClaimSpin.Visible = true;
|
|
else llblClaimSpin.Visible = false;
|
|
|
|
if (_config.StartMinimized) WindowState = FormWindowState.Minimized;
|
|
|
|
if (_apiService.CurrentUser.Role == "Admin")
|
|
{
|
|
LoggingService.LogString("Current User Is An Admin. Using Admin Context Menu Strips...");
|
|
lvUserDirectory.ContextMenuStrip = ctxmAdminUserList;
|
|
lbRooms.ContextMenuStrip = ctxmAdminRoomList;
|
|
}
|
|
|
|
LoggingService.LogString("Client Ready");
|
|
}
|
|
}
|
|
}
|
|
|
|
private async Task RefreshUsers()
|
|
{
|
|
LoggingService.LogString("Refreshing All Users List...");
|
|
|
|
if (IsHandleCreated && !IsDisposed)
|
|
{
|
|
await Invoke(async delegate ()
|
|
{
|
|
// get all users on server
|
|
var userList = await _apiService.GetAllUsersAsync();
|
|
|
|
if (userList != null && userList.Success && userList.Data != null)
|
|
{
|
|
// clear the list
|
|
lvUserDirectory.Items.Clear();
|
|
UserDirectory.Clear();
|
|
|
|
// populate list
|
|
foreach (var user in userList.Data)
|
|
{
|
|
lvUserDirectory.Items.Add(user.Username, user.Status);
|
|
UserDirectory.Add(user);
|
|
}
|
|
|
|
if (System.Diagnostics.Debugger.IsAttached)
|
|
LoggingService.LogModel(userList.Data);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
private async Task RefreshRoomsList()
|
|
{
|
|
LoggingService.LogString("Refreshing Rooms List...");
|
|
|
|
if (IsHandleCreated && !IsDisposed)
|
|
{
|
|
await Invoke(async delegate ()
|
|
{
|
|
lbRooms.Items.Clear();
|
|
var roomsRes = await _apiService.GetAllRoomsAsync();
|
|
if (roomsRes.Success && roomsRes.Data != null)
|
|
{
|
|
foreach (var room in roomsRes.Data)
|
|
{
|
|
lbRooms.Items.Add(room.Name);
|
|
}
|
|
RoomList = roomsRes.Data;
|
|
if (System.Diagnostics.Debugger.IsAttached)
|
|
LoggingService.LogModel(roomsRes.Data);
|
|
}
|
|
|
|
// always add lobby room to rooms list
|
|
lbRooms.Items.Add("Lobby");
|
|
});
|
|
}
|
|
}
|
|
|
|
private async Task RefreshContactsList()
|
|
{
|
|
LoggingService.LogString("Refreshing Contacts List...");
|
|
|
|
if (IsHandleCreated && !IsDisposed)
|
|
{
|
|
await Invoke(async delegate ()
|
|
{
|
|
lvContacts.Items.Clear();
|
|
Contacts.Clear();
|
|
lblRequestNotif.Visible = false;
|
|
var contactsRes = await _apiService.GetCurrentUserContacts();
|
|
if (contactsRes.Success && contactsRes.Data != null)
|
|
{
|
|
if (contactsRes.Data.Where(e => e.UserId == _apiService.CurrentUser!.Id && e.UserStatus == Contact.ContactStatus.AwaitingApprovalFromSelf).Count() >= 1)
|
|
lblRequestNotif.Visible = true;
|
|
else
|
|
lblRequestNotif.Visible = false;
|
|
|
|
foreach (var contact in contactsRes.Data)
|
|
{
|
|
ServiceResponse<UserInformationDto> user = null!;
|
|
if (contact.OwnerId == _apiService.CurrentUser!.Id)
|
|
user = await _apiService.GetUserInformationAsync(contact.UserId);
|
|
else if (contact.UserId == _apiService.CurrentUser!.Id)
|
|
user = await _apiService.GetUserInformationAsync(contact.OwnerId);
|
|
|
|
if (user.Data != null)
|
|
{
|
|
Contacts.Add(contact);
|
|
if (contact.OwnerId == _apiService.CurrentUser!.Id)
|
|
{
|
|
switch (contact.OwnerStatus)
|
|
{
|
|
case Contact.ContactStatus.AwaitingApprovalFromOther:
|
|
var lvi = lvContacts.Items.Add($"{user.Data.Username} [Request Sent]");
|
|
await AddProfilePicToList(user.Data.Id);
|
|
if (ilProfilePics.Images.ContainsKey(user.Data.Id))
|
|
lvi.ImageKey = user.Data.Id;
|
|
else lvi.ImageKey = "DEFAULT";
|
|
break;
|
|
case Contact.ContactStatus.Accepted:
|
|
var lvi2 = lvContacts.Items.Add($"{user.Data.Username}");
|
|
await AddProfilePicToList(user.Data.Id);
|
|
if (ilProfilePics.Images.ContainsKey(user.Data.Id))
|
|
lvi2.ImageKey = user.Data.Id;
|
|
else lvi2.ImageKey = "DEFAULT";
|
|
break;
|
|
}
|
|
}
|
|
else if (contact.UserId == _apiService.CurrentUser!.Id)
|
|
{
|
|
switch (contact.UserStatus)
|
|
{
|
|
case Contact.ContactStatus.AwaitingApprovalFromSelf:
|
|
var lvi = lvContacts.Items.Add($"{user.Data.Username} [Contact Request]");
|
|
await AddProfilePicToList(user.Data.Id);
|
|
if (ilProfilePics.Images.ContainsKey(user.Data.Id))
|
|
lvi.ImageKey = user.Data.Id;
|
|
else lvi.ImageKey = "DEFAULT";
|
|
AudioService.PlaySoundEffect("sndContactRequest");
|
|
break;
|
|
case Contact.ContactStatus.Accepted:
|
|
var lvi2 = lvContacts.Items.Add($"{user.Data.Username}");
|
|
await AddProfilePicToList(user.Data.Id);
|
|
if (ilProfilePics.Images.ContainsKey(user.Data.Id))
|
|
lvi2.ImageKey = user.Data.Id;
|
|
else lvi2.ImageKey = "DEFAULT";
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (System.Diagnostics.Debugger.IsAttached)
|
|
LoggingService.LogModel(contactsRes.Data);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
private async Task StartRequestNotifBlankLoop(Label label)
|
|
{
|
|
while (true)
|
|
{
|
|
if (!IsHandleCreated) { LoggingService.LogString("Form Handle Wasn't Created"); return; }
|
|
|
|
if (InvokeRequired && !IsDisposed)
|
|
{
|
|
BeginInvoke(async delegate ()
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
|
|
private async Task AddProfilePicToList(string userId)
|
|
{
|
|
var result = await _apiService.GetUserProfilePic(userId);
|
|
if (result != null && result.Success && result.Data != null)
|
|
{
|
|
using (var ms = new MemoryStream(result.Data))
|
|
{
|
|
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}");
|
|
}
|
|
|
|
private async Task GetAndAddStoreThumbnail(StoreItem item)
|
|
{
|
|
try
|
|
{
|
|
using HttpClient client = new();
|
|
var response = await client.GetAsync(item.ThumbnailUrl);
|
|
if (response != null && response.IsSuccessStatusCode)
|
|
{
|
|
using var stream = await response.Content.ReadAsStreamAsync();
|
|
Image image = Image.FromStream(stream);
|
|
stream.Dispose();
|
|
ilStoreThumbnails.Images.Add(item.Id.ToString(), image);
|
|
}
|
|
else if (response != null) LoggingService.LogString($"Store Item Thumbnail Could Not Be Loaded Due To Status Code {response.StatusCode}");
|
|
else LoggingService.LogString("Store Item Thumbnail Could Not Be Loaded");
|
|
client.Dispose();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LoggingService.LogString("Store Item Thumbnail Could Not Be Loaded\n" + ex.Message);
|
|
}
|
|
}
|
|
|
|
public void RefreshCurrencyCounter()
|
|
{
|
|
if (IsHandleCreated && !IsDisposed)
|
|
{
|
|
Invoke(delegate () { lblCurrencyAmount.Text = _apiService.CurrentUser.CurrencyAmount.ToString("N0"); });
|
|
}
|
|
}
|
|
|
|
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; 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();
|
|
await _gatewayService.StartAsync();
|
|
|
|
if (_gatewayService.HubConnection != null && _gatewayService.HubConnection.State == Microsoft.AspNetCore.SignalR.Client.HubConnectionState.Connected)
|
|
{ BeginInvoke(delegate () { tbcMain.Enabled = true; lblConnectionLost.Visible = false; }); return; }
|
|
|
|
ConnectionClosed frmConnectionClosed = new ConnectionClosed();
|
|
var result = frmConnectionClosed.ShowDialog();
|
|
|
|
if (result == DialogResult.OK)
|
|
{
|
|
// tell the gateway service to attempt reconnection
|
|
Reconnect:
|
|
if (_gatewayService.HubConnection != null)
|
|
{
|
|
await _gatewayService.StopAsync();
|
|
await _gatewayService.StartAsync();
|
|
|
|
if (_gatewayService.HubConnection.State == Microsoft.AspNetCore.SignalR.Client.HubConnectionState.Connected)
|
|
{
|
|
Invoke(delegate () { tbcMain.Enabled = true; lblConnectionLost.Visible = false; });
|
|
}
|
|
else
|
|
{
|
|
// reshow the dialog
|
|
frmConnectionClosed.StatusLabel.Text = "Couldn't Reconnect. The Server Could Be Down.";
|
|
var result1 = frmConnectionClosed.ShowDialog();
|
|
|
|
if (result1 == DialogResult.OK) goto Reconnect;
|
|
else Environment.Exit(0);
|
|
}
|
|
}
|
|
}
|
|
else Environment.Exit(0);
|
|
}
|
|
|
|
private void _gatewayService_OnServerReconnecting(object? sender, EventArgs e)
|
|
{
|
|
var args = (ServerConnectionReconnectingEventArgs)e;
|
|
|
|
if (args.Error == null)
|
|
LoggingService.LogString("Server Requested Reconnect. Reconnecting...");
|
|
else
|
|
LoggingService.LogString($"SignalR Reconnecting Due To An Error.\n{args.Error.Message}\n{args.Error.StackTrace}");
|
|
|
|
if (IsHandleCreated && !IsDisposed)
|
|
{
|
|
Invoke(delegate ()
|
|
{
|
|
tbcMain.Enabled = false;
|
|
lblConnectionLost.Visible = true;
|
|
});
|
|
}
|
|
}
|
|
|
|
private void _gatewayService_OnServerReconnected(object? sender, EventArgs e)
|
|
{
|
|
LoggingService.LogString("SignalR Reconnected");
|
|
|
|
if (IsHandleCreated && !IsDisposed)
|
|
{
|
|
Invoke(delegate ()
|
|
{
|
|
tbcMain.Enabled = true;
|
|
lblConnectionLost.Visible = false;
|
|
});
|
|
}
|
|
}
|
|
|
|
private async void _gatewayService_OnServerConfigReceived(object? sender, EventArgs e)
|
|
{
|
|
var args = (ServerConfigEventArgs)e;
|
|
|
|
LoggingService.LogString($"Server Config Received");
|
|
LoggingService.LogModel(args.ServerConfig);
|
|
|
|
if (_serverConfig != null) return; // only set server config upon client restart, not during reconnect (preventing log spam)
|
|
|
|
if (args.ServerConfig != null)
|
|
{
|
|
_serverConfig = args.ServerConfig;
|
|
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)
|
|
{
|
|
await _gatewayService.StopAsync();
|
|
await _gatewayService.DisposeAsync();
|
|
}
|
|
Environment.Exit(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void _gatewayService_OnDirectMessageReceived(object? sender, EventArgs e)
|
|
{
|
|
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)
|
|
{
|
|
// we want to just add to its text box
|
|
existingForm.Messages.Add($"[{args.User.Username}] {args.Message.Content}\n");
|
|
}
|
|
else
|
|
{
|
|
// start a new form
|
|
DirectMessage frmDirectMessage = new DirectMessage(_gatewayService, _apiService, args.User, args.Message);
|
|
Task.Run(frmDirectMessage.ShowDialog);
|
|
}
|
|
}
|
|
|
|
private async void _gatewayService_OnUserForceLogout(object? sender, EventArgs e)
|
|
{
|
|
MessageBox.Show("Connection To Server Lost. You Were Logged Out.\nTry Signing In Again.\nThe Application Will Now Close.", "oops.", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
|
|
await _gatewayService.StopAsync();
|
|
|
|
if (File.Exists("./session.token")) File.Delete("./session.token");
|
|
|
|
Environment.Exit(0); // dont want the user to try and make a new account right away
|
|
}
|
|
|
|
private void _apiService_OnCurrentUserUpdate(object? sender, EventArgs e)
|
|
{
|
|
lblWelcome.Text = $"Welcome, {_apiService.CurrentUser.Username}";
|
|
RefreshCurrencyCounter();
|
|
}
|
|
|
|
private async void _gatewayService_OnRefreshContactsListReceived(object? sender, EventArgs e) => await RefreshContactsList();
|
|
private async void _gatewayService_OnRefreshRoomListReceived(object? sender, EventArgs e) => await RefreshRoomsList();
|
|
private async void _gatewayService_OnRefreshUserListReceived(object? sender, EventArgs e) => await RefreshUsers();
|
|
}
|
|
}
|