diff --git a/qtcnet-client/Forms/MainForm.Designer.cs b/qtcnet-client/Forms/MainForm.Designer.cs
index 95fd610..d200ff8 100644
--- a/qtcnet-client/Forms/MainForm.Designer.cs
+++ b/qtcnet-client/Forms/MainForm.Designer.cs
@@ -28,8 +28,43 @@
///
private void InitializeComponent()
{
+ components = new System.ComponentModel.Container();
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
+ niMain = new NotifyIcon(components);
+ ctxNotifyIcon = new ContextMenuStrip(components);
+ tsiShow = new ToolStripMenuItem();
+ tsiExit = new ToolStripMenuItem();
+ ctxNotifyIcon.SuspendLayout();
SuspendLayout();
//
+ // niMain
+ //
+ niMain.ContextMenuStrip = ctxNotifyIcon;
+ niMain.Icon = (Icon)resources.GetObject("niMain.Icon");
+ niMain.Text = "QtC.NET";
+ niMain.Visible = true;
+ niMain.DoubleClick += niMain_DoubleClick;
+ //
+ // ctxNotifyIcon
+ //
+ ctxNotifyIcon.Items.AddRange(new ToolStripItem[] { tsiShow, tsiExit });
+ ctxNotifyIcon.Name = "ctxNotifyIcon";
+ ctxNotifyIcon.Size = new Size(104, 48);
+ //
+ // tsiShow
+ //
+ tsiShow.Name = "tsiShow";
+ tsiShow.Size = new Size(103, 22);
+ tsiShow.Text = "Show";
+ tsiShow.Click += tsiShow_Click;
+ //
+ // tsiExit
+ //
+ tsiExit.Name = "tsiExit";
+ tsiExit.Size = new Size(103, 22);
+ tsiExit.Text = "Exit";
+ tsiExit.Click += tsiExit_Click;
+ //
// MainForm
//
AutoScaleDimensions = new SizeF(7F, 15F);
@@ -45,9 +80,15 @@
Load += MainForm_Load;
Paint += MainForm_Paint;
Resize += MainForm_Resize;
+ ctxNotifyIcon.ResumeLayout(false);
ResumeLayout(false);
}
#endregion
+
+ private NotifyIcon niMain;
+ private ContextMenuStrip ctxNotifyIcon;
+ private ToolStripMenuItem tsiShow;
+ private ToolStripMenuItem tsiExit;
}
}
diff --git a/qtcnet-client/Forms/MainForm.cs b/qtcnet-client/Forms/MainForm.cs
index ce81d54..fa86b5d 100644
--- a/qtcnet-client/Forms/MainForm.cs
+++ b/qtcnet-client/Forms/MainForm.cs
@@ -45,12 +45,12 @@ namespace qtcnet_client
private readonly UpdateService _updateService;
private readonly AudioService _audioService;
- public MainForm(IApiService apiService,
- IGatewayService gatewayService,
- LoggingService loggingService,
- CredentialService credentialService,
- ClientConfig config,
- ImageFactory imageFactory,
+ public MainForm(IApiService apiService,
+ IGatewayService gatewayService,
+ LoggingService loggingService,
+ CredentialService credentialService,
+ ClientConfig config,
+ ImageFactory imageFactory,
UpdateService updateService,
AudioService audioService)
{
@@ -74,7 +74,7 @@ namespace qtcnet_client
Graphics g = e.Graphics;
Rectangle _formRect = ClientRectangle;
- if (_formRect.IsEmpty)
+ if (_formRect.IsEmpty)
_formRect = e.ClipRectangle;
// draw gradient background
@@ -82,7 +82,13 @@ namespace qtcnet_client
g.FillRectangle(b, _formRect);
}
- private void MainForm_Resize(object sender, EventArgs e) => Invalidate();
+ private void MainForm_Resize(object sender, EventArgs e)
+ {
+ if (WindowState == FormWindowState.Minimized && _config.MinimizeToTray)
+ Hide();
+
+ Invalidate();
+ }
private async void MainForm_Load(object sender, EventArgs e)
{
@@ -145,7 +151,7 @@ namespace qtcnet_client
Controls.Remove(LoginControl);
LoginControl?.Dispose();
LoginControl = null;
-
+
// create register control
RegisterControl = new()
{
@@ -247,7 +253,7 @@ namespace qtcnet_client
{
if (sender is RoomControl _roomCtrl)
{
- if(OpenChatRoomForms.Count > 0)
+ if (OpenChatRoomForms.Count > 0)
{
KryptonMessageBox.Show("Joining Multiple Rooms Is Currently Unsupported.", ":(");
return;
@@ -346,12 +352,12 @@ namespace qtcnet_client
private async void MainTabControl_OnUserItemDoubleClicked(object? sender, EventArgs e)
{
- if(sender is MainTabControl _mtCtrl)
+ if (sender is MainTabControl _mtCtrl)
{
- if(_mtCtrl.SelectedUser != null)
+ if (_mtCtrl.SelectedUser != null)
{
// get the user to open the profile for
- if(_mtCtrl.SelectedUser.Tag is string _tagString)
+ if (_mtCtrl.SelectedUser.Tag is string _tagString)
{
var _user = await _apiService.GetUserInformationAsync(_tagString);
if (_user.Success && _user.Data != null)
@@ -421,7 +427,7 @@ namespace qtcnet_client
private void _gatewayService_OnServerConfigReceived(object? sender, EventArgs e)
{
- if(e is ServerConfigEventArgs _args)
+ if (e is ServerConfigEventArgs _args)
{
if (InvokeRequired)
Invoke(() => Text = $"{Text} - Connected To {_args.ServerConfig.Name}");
@@ -438,7 +444,8 @@ namespace qtcnet_client
UserContactsList.Clear();
UserContactsList.AddRange([.. _currentUserContacts.Data.DistinctBy(c => c.Id)]);
await SetupContactsUI(_currentUserContacts.Data);
- } else
+ }
+ else
{
// if no contacts are found, just clear the lists
UserContactsList.Clear();
@@ -464,9 +471,9 @@ namespace qtcnet_client
private async void _gatewayService_OnServerDisconnect(object? sender, EventArgs e)
{
- if(e is ServerConnectionClosedEventArgs _args)
+ if (e is ServerConnectionClosedEventArgs _args)
{
- if(_args.Error != null)
+ if (_args.Error != null)
{
Reconnect: // probably not the best idea to use labels but whatever
var _dialogRes = KryptonMessageBox.Show($"Connection To The Server Lost. Would You Like To Try Again?\n\nError - {_args.Error?.Message}", "Uh Oh.",
@@ -638,11 +645,15 @@ namespace qtcnet_client
ResumeLayout(true);
+ // minimize main window if start minimized is on
+ if (_config.StartMinimized)
+ WindowState = FormWindowState.Minimized;
+
// check for daily spin eligibility
var now = DateTime.UtcNow;
var lastSpin = _apiService.CurrentUser.LastCurrencySpin;
- if(lastSpin.Date < now.Date)
+ if (lastSpin.Date < now.Date)
{
Random rnd = new();
@@ -651,7 +662,7 @@ namespace qtcnet_client
CurrencyWon = rnd.Next(0, 200)
};
var _dialogRes = _jackpotSpin.ShowDialog();
- if(_dialogRes == DialogResult.OK)
+ if (_dialogRes == DialogResult.OK)
{
// claim
var _apiRes = await _apiService.AddCurrencyToCurrentUser(_jackpotSpin.CurrencyWon, true);
@@ -673,11 +684,11 @@ namespace qtcnet_client
private async void MainTabControl_OnStoreItemDoubleClicked(object? sender, EventArgs e)
{
- if(sender is MainTabControl _ctrl && _ctrl.SelectedStoreItem?.Tag is int _itemId)
+ if (sender is MainTabControl _ctrl && _ctrl.SelectedStoreItem?.Tag is int _itemId)
{
// get store item
var _item = await _apiService.GetStoreItem(_itemId);
- if(_item.Success && _item.Data != null)
+ if (_item.Success && _item.Data != null)
{
// create buy form
StoreItemForm _itemForm = new(_apiService)
@@ -696,7 +707,7 @@ namespace qtcnet_client
private async void _itemForm_OnBuyClicked(object? sender, EventArgs e)
{
- if(sender is StoreItemForm _form)
+ if (sender is StoreItemForm _form)
{
// buy the item
var _res = await _apiService.BuyStoreItem(_form.ItemId);
@@ -796,11 +807,9 @@ namespace qtcnet_client
Username = _user.Data.Username,
Bio = _user.Data.Bio,
Status = _user.Data.Status,
+ ProfileImage = await _imgFactory.GetAndCreateProfileImage(_user.Data.Id, _user.Data.Status, _user.Data.ProfileCosmeticId)
};
- // get profile image
- _profile.ProfileImage = await _imgFactory.GetAndCreateProfileImage(_user.Data.Id, _user.Data.Status, _user.Data.ProfileCosmeticId);
-
_profile.OnClose += ProfileForm_OnClose;
OpenProfileForms.Add(_profile);
@@ -810,11 +819,11 @@ namespace qtcnet_client
private void _gatewayService_OnRoomUserListReceived(object? sender, EventArgs e)
{
- if(e is RoomListEventArgs _args)
+ if (e is RoomListEventArgs _args)
{
// get the open chat room form
var _chatRoom = OpenChatRoomForms.FirstOrDefault(e => e.RoomId == _args.Room.Id);
- if(_chatRoom != null)
+ if (_chatRoom != null)
{
// the users to the list
_chatRoom.AddUsersToRoomList(_args.UserList);
@@ -828,7 +837,7 @@ namespace qtcnet_client
{
// get the open chat room form
var _chatRoom = OpenChatRoomForms.FirstOrDefault(e => e.RoomId == _args.Room.Id);
- if(_chatRoom != null)
+ if (_chatRoom != null)
{
// build message control
MessageControl _msg = new()
@@ -840,7 +849,7 @@ namespace qtcnet_client
// add message
_chatRoom.AddMessage(_msg);
- if(_args.User.Id != "0")
+ if (_args.User.Id != "0")
await _chatRoom.LoadProfileImage(_msg, _args.User);
// play sound
@@ -973,5 +982,28 @@ namespace qtcnet_client
return default;
}
+
+ private void niMain_DoubleClick(object sender, EventArgs e)
+ {
+ if (WindowState == FormWindowState.Minimized)
+ {
+ Show();
+ WindowState = FormWindowState.Normal;
+ }
+ }
+
+ private void tsiShow_Click(object sender, EventArgs e)
+ {
+ if (WindowState == FormWindowState.Minimized)
+ {
+ Show();
+ WindowState = FormWindowState.Normal;
+ }
+ }
+
+ private void tsiExit_Click(object sender, EventArgs e)
+ {
+ Close();
+ }
}
}
diff --git a/qtcnet-client/Forms/MainForm.resx b/qtcnet-client/Forms/MainForm.resx
index 8b2ff64..1fb4ee5 100644
--- a/qtcnet-client/Forms/MainForm.resx
+++ b/qtcnet-client/Forms/MainForm.resx
@@ -117,4 +117,87 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ 17, 17
+
+
+ 108, 17
+
+
+
+
+ AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAABMLAAATCwAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAA24wAANuMAADbjAAO24wAMtuMAFjbjABy24wAetuMAHHbjABW24wAL9uMAAzbjAAA24wAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAA24wAANuMAADbjAAf24wAdNuMAMTbjADu24wA/duMAP/bjAD/24wA/9uMAPzbjADs24wAv9uM
+ AG3bjAAa24wAANuMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAANuMAADbjAAJ24wAYduMANXbjAD+24wA/9uMAP/bjAD/24wA/9uMAP/bjAD/24wA/9uM
+ AP/bjAD/24wA/duMAM7bjABY24wABtuMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAANuMAADbjAAA24wAEtuMAJPbjAD324wA/9uMAP/bjAD/24wA/9uMAP/bjAD/24wA/9uM
+ AP/bjAD/24wA/9uMAP/bjAD/24wA/9uMAPTbjACH24wADtuMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAA24wAANuMABDbjACf24wA/duMAP/bjAD/24wA/9uMAP/bjAD/24wA/9uM
+ AP/bjAD/24wA/9uMAP/bjAD/24wA/9uMAP/bjAD/24wA/9uMAPzbjACT24wAC9uMAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAANuMAADbjAAE24wAh9uMAP3bjAD/24wA/9uMAP/bjAD/24wA/9uM
+ AP/bjAD/24wA/9uMAP/bjAD/24wA/9uMAP/bjAD/24wA/9uMAP/bjAD/24wA/9uMAPrbjAB524wAAtuM
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADbjAAA24wAANuMAE3bjADw24wA/9uMAP/bjAD/24wA/9uM
+ AP/bjAD/24wA/9uMAP/bjAD/24wA/9uMAP/bjAD/24wA/9uMAP/bjAD/24wA/9uMAP/bjAD/24wA/9uM
+ AOrbjABA24wAANuMAAAAAAAAAAAAAAAAAAAAAAAAAAAAANuMAADbjAAQ24wAvduMAP/bjAD/24wA/9uM
+ AP/bjAD/24wA/9uMAP/bjAD/24wA/9uMAP/bjAD/24wA/9uMAP/bjAD/24wA/9uMAP/bjAD/24wA/9uM
+ AP/bjAD/24wA/9uMAK/bjAAK24wAAAAAAAAAAAAAAAAAAAAAAADbjAAA24wAANuMAFHbjAD324wA/9uM
+ AP/bjAD/24wA/9uLAP/biwD/24wA/9uMAP/bjAD/24wA/9uMAP/biwD/24wA/9uMAP/bjAD/24sA/9uL
+ AP/bjAD/24wA/9uMAP/bjAD/24wA8tuMAEPbjAAAAAAAAAAAAAAAAAAAAAAAANuMAADbjAAC24wAntuM
+ AP/bjAD/24wA/9uLAP/ckQz/4Jwj/9+YG//bjQP/3JEM/9yPB//biwD/3ZIN/96YGv/bjQP/24wA/9uM
+ Af/elRX/4Jwk/92TD//biwD/24wA/9uMAP/bjAD/24wAj9uMAADbjAAAAAAAAAAAAAAAAAAA24wAANuM
+ ABbbjADU24wA/9uMAP/biwD/4qM1//Tet//57dj/+OnR/+/Ok//y16f/5atG/92TD//y2Kr/9N63/96V
+ FP/bjAL/6Lhi//fnzf/47Nf/9uPB/+WrR//biwD/24wA/9uMAP/bjADH24wAD9uMAAAAAAAAAAAAAAAA
+ AADbjAAA24wAMtuMAO7bjAD/24wA/92TD//14b3/89mt/+SoP//w0Jj///////Parv/dkg3/4qIy//rw
+ 3v/msFH/24wA/+OlOf/68N//7MJ5/+KkNf/uy47/+OrS/+CcJP/biwD/24wA/9uMAObbjAAm24wAAAAA
+ AAAAAAAAAAAAANuMAADbjABI24wA+duMAP/biwD/4qIy//nv3f/iozX/3pUX//LWpv/25cj/8tis/9uM
+ AP/ipDb/+ezY/+CcJ//aiQD/68F3//bjwv/ckAz/24oA/92RD//puWX/4Jwl/9uLAP/bjAD/24wA89uM
+ ADrbjAAAAAAAAAAAAAAAAAAA24wAANuMAFHbjAD824wA/9uKAP/jpzz/+e7b/+CdJ//bjAH/3ZMQ/+zD
+ fP/137v/240D/+KkNv/57Nj/4J0n/9qJAP/tx4X/89yz/9uNBP/bjAD/24wA/9qKAP/biwD/24wA/9uM
+ AP/bjAD324wAQtuMAAAAAAAAAAAAAAAAAADbjAAA24wATNuMAPrbjAD/24oA/+OnPP/57tv/4J0n/9uL
+ AP/aigD/7MJ6//Xfu//cjgX/5axI//rv3v/kqED/24sA/+3Hhf/z3LL/244E/9uMAP/bjAD/24sA/9uM
+ AP/bjAD/24wA/9uMAPXbjAA924wAAAAAAAAAAAAAAAAAANuMAADbjAA524wA8tuMAP/bigD/46Y6//nu
+ 2//gnin/24sA/9qKAP/sw37/9N+4/9yRC//x0p7//v37//Tdtv/dkxD/7cWB//Tdtv/cjgX/24wA/9uM
+ Av/elRb/3JAK/9uMAP/bjAD/24wA69uMACzbjAAAAAAAAAAAAAAAAAAA24wAANuMAB7bjADd24wA/9uL
+ AP/gmyL/+e3Z/+i4Yv/bjAD/3ZMP//TdtP/w0Jj/24sA/+WuS//68eD/5KpD/9uLAP/otl3/+e3Y/+Gf
+ Kv/biwD/46c8//XiwP/iozT/24sA/9uMAP/bjADS24wAFduMAAAAAAAAAAAAAAAAAADbjAAA24wABtuM
+ AK/bjAD/24wA/9uNAv/sxH3/+vDg//LZq//14sH/+OvU/+KkNv/aigD/4Z4p//HUov/fmB3/24oA/96V
+ Fv/03bX/+OnQ//LWpv/57dn/8NGa/9yQCv/bjAD/24wA/9uMAKDbjAAC24wAAAAAAAAAAAAAAAAAANuM
+ AADbjAAA24wAZtuMAP3bjAD/24wA/9yPCf/mr0//7cmI/+zCef/hoCz/24wA/9uMAP/bjQL/3I8I/9uN
+ Af/bjAD/24sA/96XGf/pu2r/7sqK/+i1XP/dkg//24sA/9uMAP/bjAD624wAVtuMAADbjAAAAAAAAAAA
+ AAAAAAAAAAAAANuMAADbjAAc24wA09uMAP/bjAD/24wA/9qKAP/biwD/2ooA/9uLAP/bjAD/24wA/9uM
+ AP/bjAD/24wA/9uMAP/bjAD/24sA/9qKAP/biwD/2ooA/9uMAP/bjAD/24wA/9uMAMfbjAAU24wAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAA24wAANuMAADbjABr24wA+9uMAP/bjAD/24wA/9uMAP/bjAD/24wA/9uM
+ AP/bjAD/24wA/9uMAP/bjAD/24wA/9uMAP/bjAD/24wA/9uMAP/bjAD/24wA/9uMAP/bjAD324wAXNuM
+ AADbjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA24wAANuMAA7bjACr24wA/9uMAP/bjAD/24wA/9uM
+ AP/bjAD/24wA/9uMAP/bjAD/24wA/9uMAP/bjAD/24wA/9uMAP/bjAD/24wA/9uMAP/bjAD/24wA/9uM
+ AJ7bjAAJ24wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADbjAAA24wAANuMACTbjADG24wA/9uM
+ AP/bjAD/24wA/9uMAP/bjAD/24wA/9uMAP/bjAD/24wA/9uMAP/bjAD/24wA/9uMAP/bjAD/24wA/9uM
+ AP/bjAC724wAHduMAADbjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADbjAAA24wAANuM
+ ACvbjADA24wA/9uMAP/bjAD/24wA/9uMAP/bjAD/24wA/9uMAP/bjAD/24wA/9uMAP/bjAD/24wA/9uM
+ AP/bjAD+24wAtduMACPbjAAA24wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AADbjAAA24wAANuMABzbjACV24wA8duMAP/bjAD/24wA/9uMAP/bjAD/24wA/9uMAP/bjAD/24wA/9uM
+ AP/bjAD/24wA7tuMAIvbjAAW24wAANuMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAA24wAANuMAAbbjABG24wAqtuMAOnbjAD+24wA/9uMAP/bjAD/24wA/9uM
+ AP/bjAD924wA59uMAKTbjAA/24wABNuMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA24wAANuMAADbjAAH24wALtuMAGXbjACS24wAq9uM
+ ALPbjACq24wAj9uMAGHbjAAq24wABduMAADbjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA24wAANuM
+ AADbjAAD24wABduMAALbjAAA24wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAA//////////////////AH///AAf//AAB//gAAP/wAAB/4AAAP+AAAD/AA
+ AAfwAAAH4AAAB+AAAAPgAAAD4AAAA+AAAAPgAAAD4AAAA+AAAAPgAAAD8AAAB/AAAAf4AAAP+AAAD/wA
+ AB/+AAA//wAAf/+AAP//4AP///4///////8=
+
+
\ No newline at end of file