From b358bb54d0ee36792ee4ad283e5237a15de580d2 Mon Sep 17 00:00:00 2001 From: Moonbase Date: Wed, 12 Nov 2025 13:44:22 -0800 Subject: [PATCH] Implement Better Image Creating Change Remember Me Checkbox Text To 30 Days Bug Fixes (i can't remember what i was doing here) --- QtCNETAPI/Services/CredentialService.cs | 8 ++ qtc-net-client-2/Forms/Login.Designer.cs | 8 +- qtc-net-client-2/Forms/Main.Designer.cs | 13 +- qtc-net-client-2/Forms/Main.cs | 159 +++++++++++++++++---- qtc-net-client-2/Forms/Main.resx | 104 +++++++------- qtc-net-client-2/Forms/Profile.cs | 39 ++--- qtc-net-client-2/Forms/ProfileEdit.cs | 8 +- qtc-net-client-2/Forms/StoreItemDisplay.cs | 2 + qtc-net-client-2/Services/ImageFactory.cs | 41 ++++++ 9 files changed, 258 insertions(+), 124 deletions(-) create mode 100644 qtc-net-client-2/Services/ImageFactory.cs diff --git a/QtCNETAPI/Services/CredentialService.cs b/QtCNETAPI/Services/CredentialService.cs index e89c636..688cc1e 100644 --- a/QtCNETAPI/Services/CredentialService.cs +++ b/QtCNETAPI/Services/CredentialService.cs @@ -4,6 +4,14 @@ namespace QtCNETAPI.Services { public class CredentialService() { + /* + + * NOTE * + This does not work on other platforms such as Linux or macOS. + I will probably recode the legacy way of doing this for those other platforms. + + */ + public void SaveAccessToken(string username, string accessToken) { string applicationName = "QtC.NET"; diff --git a/qtc-net-client-2/Forms/Login.Designer.cs b/qtc-net-client-2/Forms/Login.Designer.cs index f5be2e5..244be4b 100644 --- a/qtc-net-client-2/Forms/Login.Designer.cs +++ b/qtc-net-client-2/Forms/Login.Designer.cs @@ -119,9 +119,9 @@ cbRememberMe.ForeColor = SystemColors.ControlLight; cbRememberMe.Location = new Point(198, 168); cbRememberMe.Name = "cbRememberMe"; - cbRememberMe.Size = new Size(157, 19); + cbRememberMe.Size = new Size(163, 19); cbRememberMe.TabIndex = 7; - cbRememberMe.Text = "Remember Me For 7 Days"; + cbRememberMe.Text = "Remember Me For 30 Days"; cbRememberMe.UseVisualStyleBackColor = true; // // llblResendEmail @@ -150,7 +150,7 @@ llblForgotPasswor.Text = "Forgot Password?"; llblForgotPasswor.LinkClicked += llblForgotPasswor_LinkClicked; // - // llblForgotPassword + // Login // AutoScaleDimensions = new SizeF(7F, 15F); AutoScaleMode = AutoScaleMode.Font; @@ -169,7 +169,7 @@ FormBorderStyle = FormBorderStyle.FixedDialog; Icon = (Icon)resources.GetObject("$this.Icon"); MaximizeBox = false; - Name = "llblForgotPassword"; + Name = "Login"; StartPosition = FormStartPosition.CenterParent; Text = "QtC.NET Client - Login"; Load += frmLogin_Load; diff --git a/qtc-net-client-2/Forms/Main.Designer.cs b/qtc-net-client-2/Forms/Main.Designer.cs index abd6f6b..87e6c66 100644 --- a/qtc-net-client-2/Forms/Main.Designer.cs +++ b/qtc-net-client-2/Forms/Main.Designer.cs @@ -469,7 +469,6 @@ // // pbUserPfp // - pbUserPfp.BorderStyle = BorderStyle.FixedSingle; pbUserPfp.ContextMenuStrip = ctxmChangeStatus; pbUserPfp.Cursor = Cursors.Hand; pbUserPfp.Image = Properties.Resources.DefaultPfp; @@ -498,39 +497,39 @@ // ctxmAdminUserList.Items.AddRange(new ToolStripItem[] { refreshToolStripMenuItem1, toolStripSeparator1, copyUserIDToClipboardToolStripMenuItem, deleteUserToolStripMenuItem, adminDirectMessageToolStripMenuItem }); ctxmAdminUserList.Name = "contextMenuStrip1"; - ctxmAdminUserList.Size = new Size(213, 98); + ctxmAdminUserList.Size = new Size(214, 98); ctxmAdminUserList.Opening += ctxmAdminUserList_Opening; // // refreshToolStripMenuItem1 // refreshToolStripMenuItem1.Name = "refreshToolStripMenuItem1"; - refreshToolStripMenuItem1.Size = new Size(212, 22); + refreshToolStripMenuItem1.Size = new Size(213, 22); refreshToolStripMenuItem1.Text = "Refresh"; refreshToolStripMenuItem1.Click += refreshToolStripMenuItem_Click; // // toolStripSeparator1 // toolStripSeparator1.Name = "toolStripSeparator1"; - toolStripSeparator1.Size = new Size(209, 6); + toolStripSeparator1.Size = new Size(210, 6); // // copyUserIDToClipboardToolStripMenuItem // copyUserIDToClipboardToolStripMenuItem.Name = "copyUserIDToClipboardToolStripMenuItem"; - copyUserIDToClipboardToolStripMenuItem.Size = new Size(212, 22); + copyUserIDToClipboardToolStripMenuItem.Size = new Size(213, 22); copyUserIDToClipboardToolStripMenuItem.Text = "Copy User ID To Clipboard"; copyUserIDToClipboardToolStripMenuItem.Click += copyUserIDToClipboardToolStripMenuItem_Click; // // deleteUserToolStripMenuItem // deleteUserToolStripMenuItem.Name = "deleteUserToolStripMenuItem"; - deleteUserToolStripMenuItem.Size = new Size(212, 22); + deleteUserToolStripMenuItem.Size = new Size(213, 22); deleteUserToolStripMenuItem.Text = "Delete User"; deleteUserToolStripMenuItem.Click += deleteUserToolStripMenuItem_Click; // // adminDirectMessageToolStripMenuItem // adminDirectMessageToolStripMenuItem.Name = "adminDirectMessageToolStripMenuItem"; - adminDirectMessageToolStripMenuItem.Size = new Size(212, 22); + adminDirectMessageToolStripMenuItem.Size = new Size(213, 22); adminDirectMessageToolStripMenuItem.Text = "Admin Direct Message"; adminDirectMessageToolStripMenuItem.Click += adminDirectMessageToolStripMenuItem_Click; // diff --git a/qtc-net-client-2/Forms/Main.cs b/qtc-net-client-2/Forms/Main.cs index 75b50ae..012a6d7 100644 --- a/qtc-net-client-2/Forms/Main.cs +++ b/qtc-net-client-2/Forms/Main.cs @@ -1,14 +1,15 @@ -using QtCNETAPI.Dtos.User; -using QtCNETAPI.Services.ApiService; -using QtCNETAPI.Services.GatewayService; -using QtCNETAPI.Events; -using QtCNETAPI.Models; +using Microsoft.VisualBasic.ApplicationServices; +using qtc_net_client_2.ClientModel; using qtc_net_client_2.Forms; using qtc_net_client_2.Services; -using qtc_net_client_2.ClientModel; -using System.Threading.Tasks; +using QtCNETAPI.Dtos.User; +using QtCNETAPI.Events; +using QtCNETAPI.Models; using QtCNETAPI.Schema; using QtCNETAPI.Services; +using QtCNETAPI.Services.ApiService; +using QtCNETAPI.Services.GatewayService; +using System.Threading.Tasks; namespace qtc_net_client_2 { @@ -20,6 +21,7 @@ namespace qtc_net_client_2 private Config _config; private ServerConfig _serverConfig; private AudioService AudioService = new(); + private ImageFactory _imgFactory = new(); private LoggingService LoggingService; public List RoomList = []; @@ -123,15 +125,30 @@ namespace qtc_net_client_2 { // update profile pic in ui var pfpRes = await _apiService.GetUserProfilePic(_apiService.CurrentUser.Id); + var cosmeticRes = await GetCosmeticImage(_apiService.CurrentUser.ActiveProfileCosmetic); + + // TODO - refactor this a bit if (pfpRes.Success && pfpRes.Data != null) { - using (var ms = new MemoryStream(pfpRes.Data)) + using var pfpMS = new MemoryStream(pfpRes.Data); + var pfp = (Bitmap)Image.FromStream(pfpMS); + + if (cosmeticRes != null) { - pbUserPfp.Image = Image.FromStream(ms); - ms.Dispose(); + using var cosmeticMS = new MemoryStream(cosmeticRes); + var cosmetic = (Bitmap)Image.FromStream(cosmeticMS); + + pbUserPfp.Image = _imgFactory.CreateProfileImage(null, pfp, cosmetic); } + else pbUserPfp.Image = _imgFactory.CreateProfileImage(null, pfp, null); + } + else if (cosmeticRes != null) + { + using var cosmeticMS = new MemoryStream(cosmeticRes); + var cosmetic = (Bitmap)Image.FromStream(cosmeticMS); + + pbUserPfp.Image = _imgFactory.CreateProfileImage(null, null, cosmetic); } - else LoggingService.LogString($"User Has No Profile Picture Or It Could Not Be Loaded.\n{pfpRes.Message}"); } } } @@ -150,10 +167,39 @@ namespace qtc_net_client_2 } } - private void llblEditProfile_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + private async void llblEditProfile_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { ProfileEdit frmProfileEdit = new ProfileEdit(_apiService); - frmProfileEdit.ShowDialog(); + var result = frmProfileEdit.ShowDialog(); + if (result == DialogResult.Yes) + { + // update profile pic in ui + var pfpRes = await _apiService.GetUserProfilePic(_apiService.CurrentUser.Id); + var cosmeticRes = await GetCosmeticImage(_apiService.CurrentUser.ActiveProfileCosmetic); + + // TODO - refactor this a bit + if (pfpRes.Success && pfpRes.Data != null) + { + using var pfpMS = new MemoryStream(pfpRes.Data); + var pfp = (Bitmap)Image.FromStream(pfpMS); + + if (cosmeticRes != null) + { + using var cosmeticMS = new MemoryStream(cosmeticRes); + var cosmetic = (Bitmap)Image.FromStream(cosmeticMS); + + pbUserPfp.Image = _imgFactory.CreateProfileImage(null, pfp, cosmetic); + } + else pbUserPfp.Image = _imgFactory.CreateProfileImage(null, pfp, null); + } + else if (cosmeticRes != null) + { + using var cosmeticMS = new MemoryStream(cosmeticRes); + var cosmetic = (Bitmap)Image.FromStream(cosmeticMS); + + pbUserPfp.Image = _imgFactory.CreateProfileImage(null, null, cosmetic); + } + } } private async void lvContacts_DoubleClick(object sender, EventArgs e) @@ -315,20 +361,7 @@ namespace qtc_net_client_2 // get cosmetic byte[]? cosmeticData = null; - if (user.ProfileCosmeticId != 0) - { - var storeRes = await _apiService.GetStoreItem(user.ProfileCosmeticId); - if (storeRes != null && storeRes.Success && storeRes.Data != null) - { - using var client = new HttpClient(); - using var response = await client.GetAsync(storeRes.Data.AssetUrl); - if (response.IsSuccessStatusCode) - { - cosmeticData = await response.Content.ReadAsByteArrayAsync(); - } - else LoggingService.LogString($"Could Not Get User Cosmetic.\nStatus Code: {response.StatusCode}"); - } - } + if (user.ProfileCosmeticId != 0) cosmeticData = await GetCosmeticImage(user.ProfileCosmeticId); if (pfpRes != null && !pfpRes.Success) LoggingService.LogString($"User Has No Profile Picture Or It Could Not Be Loaded.\n{pfpRes.Message}"); @@ -412,7 +445,36 @@ namespace qtc_net_client_2 if (item != null && item.Success && item.Data != null) { StoreItemDisplay storeItemDisplay = new StoreItemDisplay(item.Data, LoggingService, _apiService); - storeItemDisplay.ShowDialog(); + var result = storeItemDisplay.ShowDialog(); + if (result == DialogResult.Yes) + { + // update pfp in ui + var pfpRes = await _apiService.GetUserProfilePic(_apiService.CurrentUser.Id); + var cosmeticRes = await GetCosmeticImage(_apiService.CurrentUser.ActiveProfileCosmetic); + + // TODO - refactor this a bit + if (pfpRes.Success && pfpRes.Data != null) + { + using var pfpMS = new MemoryStream(pfpRes.Data); + var pfp = (Bitmap)Image.FromStream(pfpMS); + + if (cosmeticRes != null) + { + using var cosmeticMS = new MemoryStream(cosmeticRes); + var cosmetic = (Bitmap)Image.FromStream(cosmeticMS); + + pbUserPfp.Image = _imgFactory.CreateProfileImage(null, pfp, cosmetic); + } + else pbUserPfp.Image = _imgFactory.CreateProfileImage(null, pfp, null); + } + else if (cosmeticRes != null) + { + using var cosmeticMS = new MemoryStream(cosmeticRes); + var cosmetic = (Bitmap)Image.FromStream(cosmeticMS); + + pbUserPfp.Image = _imgFactory.CreateProfileImage(null, null, cosmetic); + } + } } } } @@ -605,13 +667,29 @@ namespace qtc_net_client_2 tbcMain.Enabled = true; var pfpRes = await _apiService.GetUserProfilePic(_apiService.CurrentUser.Id); + var cosmeticRes = await GetCosmeticImage(_apiService.CurrentUser.ActiveProfileCosmetic); + + // TODO - refactor this a bit if (pfpRes.Success && pfpRes.Data != null) { - using (var ms = new MemoryStream(pfpRes.Data)) + using var pfpMS = new MemoryStream(pfpRes.Data); + var pfp = (Bitmap)Image.FromStream(pfpMS); + + if (cosmeticRes != null) { - pbUserPfp.Image = Image.FromStream(ms); - ms.Dispose(); + using var cosmeticMS = new MemoryStream(cosmeticRes); + var cosmetic = (Bitmap)Image.FromStream(cosmeticMS); + + pbUserPfp.Image = _imgFactory.CreateProfileImage(null, pfp, cosmetic); } + else pbUserPfp.Image = _imgFactory.CreateProfileImage(null, pfp, null); + } + else if (cosmeticRes != null) + { + using var cosmeticMS = new MemoryStream(cosmeticRes); + var cosmetic = (Bitmap)Image.FromStream(cosmeticMS); + + pbUserPfp.Image = _imgFactory.CreateProfileImage(null, null, cosmetic); } if (lvUserDirectory.Items.Count <= 0) @@ -862,6 +940,25 @@ namespace qtc_net_client_2 } } + private async Task GetCosmeticImage(int profileCosmeticId) + { + if (profileCosmeticId <= 0) return null; + + var storeRes = await _apiService.GetStoreItem(profileCosmeticId); + if (storeRes != null && storeRes.Success && storeRes.Data != null) + { + using var client = new HttpClient(); + using var response = await client.GetAsync(storeRes.Data.AssetUrl); + if (response.IsSuccessStatusCode) + { + return await response.Content.ReadAsByteArrayAsync(); + } + else LoggingService.LogString($"Could Not Get User Cosmetic.\nStatus Code: {response.StatusCode}"); + } + + return null; + } + public void RefreshCurrencyCounter() { if (IsHandleCreated && !IsDisposed) diff --git a/qtc-net-client-2/Forms/Main.resx b/qtc-net-client-2/Forms/Main.resx index 1c8f44c..5f9280d 100644 --- a/qtc-net-client-2/Forms/Main.resx +++ b/qtc-net-client-2/Forms/Main.resx @@ -128,7 +128,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAEZTeXN0ZW0uV2luZG93cy5Gb3JtcywgQ3VsdHVyZT1uZXV0cmFs LCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAAAmU3lzdGVtLldpbmRvd3MuRm9ybXMu SW1hZ2VMaXN0U3RyZWFtZXIBAAAABERhdGEHAgIAAAAJAwAAAA8DAAAA0A0AAAJNU0Z0AUkBTAMBAQAB - mAEBAZgBAQEgAQABIAEABP8BIQEACP8BQgFNATYHAAE2AwABKAMAAYADAAEgAwABAQEAASAGAAFAEgAD + oAEBAaABAQEgAQABIAEABP8BIQEACP8BQgFNATYHAAE2AwABKAMAAYADAAEgAwABAQEAASAGAAFAEgAD rQH/A7oB/wO6Af8DuQH/A7oB/wO6Af8D2gX/A/wB/wP+Df8D/QH/A/wR/wP8Af8D/g3/A/0B/wPZAf8D ugH/A7oB/wO6Af8DugH/A7oB/wO6Af//AIEAA58B/wO6Af8DugH/A7oB/wO6Af8DugH/A9oJ/wP9Af8D /g3/A/0B/wP9Ef8D/AH/A/4N/wPaAf8DugH/A7oB/wO6Af8DugH/A7oB/wO6Af//AIEAA6IB/wO6Af8D @@ -197,30 +197,30 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAEZTeXN0ZW0uV2luZG93cy5Gb3JtcywgQ3VsdHVyZT1uZXV0cmFs LCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAAAmU3lzdGVtLldpbmRvd3MuRm9ybXMu SW1hZ2VMaXN0U3RyZWFtZXIBAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAohMAAAJNU0Z0AUkBTAIBAQQB - AAFQAQEBUAEBARABAAEQAQAE/wEhAQAI/wFCAU0BNgcAATYDAAEoAwABQAMAASADAAEBAQABIAYAASD/ + AAFYAQEBWAEBARABAAEQAQAE/wEhAQAI/wFCAU0BNgcAATYDAAEoAwABQAMAASADAAEBAQABIAYAASD/ AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AC4AAwYBBwM0AVQDUQGiA14B0gNaAekDYAHoA10B 0QNQAZ8DMQFNAwUBBhgAAwYBBwM0AVQDUQGiA14B0gNaAekDYAHoA10B0QNQAZ8DMQFNAwUBBhgAAwYB BwM0AVQDUQGiA14B0gNaAekDYAHoA10B0QNQAZ8DMQFNAwUBBhgAAwYBBwM0AVQDUQGiA14B0gNaAekD - YAHoA10B0QNQAZ8DMQFNAwUBBhQAAyABLQNUAasDWwHkA1oB9QMkAfsDTgH+A04B/gMkAfsDUwH0A2IB - 4QNRAaEDHgEqEAADIAEtA1QBqwNbAeQDWgH1ASEBXgEhAfsBKgFqASoB/gEqAWoBKgH+ASEBXgEhAfsD - UwH0A2IB4QNRAaEDHgEqEAADIAEtA1QBqwNbAeQDWgH1ASECXgH7ASoCagH+ASoCagH+ASECXgH7A1MB - 9ANiAeEDUQGhAx4BKhAAAyABLQNUAasDWwHkA1oB9QIhAV4B+wIqAWoB/gIqAWoB/gIhAV4B+wNTAfQD - YgHhA1EBoQMeASoMAAMbASUDWAG9A1oB8gNSAf4DMAH/AzkB/wM8Af8DNgH/AyoB/wMkAf8DQAH9A14B - 8ANWAbIDGgEjCAADGwElA1gBvQNaAfIBKgFyASoB/gEAAVcBAAH/AQABZwEAAf8BAAFsAQAB/wEAAWEB - AAH/AQABTAEAAf8BAAFAAQAB/wNAAf0DXgHwA1YBsgEZARoBGQEjCAADGwElA1gBvQNaAfIBKgJyAf4B + YAHoA10B0QNQAZ8DMQFNAwUBBhQAAyABLQNUAasDWwHkA1oB9QMkAfsDTwH+A08B/gMkAfsDUwH0A2IB + 4QNRAaEDHgEqEAADIAEtA1QBqwNbAeQDWgH1ASEBXgEhAfsBKwFrASsB/gErAWsBKwH+ASEBXgEhAfsD + UwH0A2IB4QNRAaEDHgEqEAADIAEtA1QBqwNbAeQDWgH1ASECXgH7ASsCawH+ASsCawH+ASECXgH7A1MB + 9ANiAeEDUQGhAx4BKhAAAyABLQNUAasDWwHkA1oB9QIhAV4B+wIrAWsB/gIrAWsB/gIhAV4B+wNTAfQD + YgHhA1EBoQMeASoMAAMbASUDWAG9A1oB8gNTAf4DMAH/AzkB/wM8Af8DNgH/AyoB/wMkAf8DQAH9A14B + 8ANWAbIDGgEjCAADGwElA1gBvQNaAfIBKwFzASsB/gEAAVcBAAH/AQABZwEAAf8BAAFsAQAB/wEAAWEB + AAH/AQABTAEAAf8BAAFAAQAB/wNAAf0DXgHwA1YBsgEZARoBGQEjCAADGwElA1gBvQNaAfIBKwJzAf4B AAJXAf8BAAJnAf8BAAJsAf8BAAJhAf8BAAJMAf8BAAJAAf8DQAH9A14B8ANWAbIBGQIaASMIAAMbASUD - WAG9A1oB8gIqAXIB/gIAAVcB/wIAAWcB/wIAAWwB/wIAAWEB/wIAAUwB/wIAAUAB/wNAAf0DXgHwA1YB - sgIZARoBIwQAAwMBBANSAaUDYAHzA0kB/wNVAf8DZQH/A3EB/wN1Af8DcQH/A2QB/wNMAf8DMQH/A04B + WAG9A1oB8gIrAXMB/gIAAVcB/wIAAWcB/wIAAWwB/wIAAWEB/wIAAUwB/wIAAUAB/wNAAf0DXgHwA1YB + sgIZARoBIwQAAwMBBANSAaUDYAHzA0kB/wNVAf8DZQH/A3EB/wN1Af8DcQH/A2QB/wNMAf8DMQH/A08B /gNiAe4DUAGaAwMBBAMDAQQBUgFTAVIBpQFgAW8BYAHzAQABggEAAf8BAAGZAQAB/wEAAbYBAAH/AQAB - zAEAAf8BAAHTAQAB/wEAAcsBAAH/AQABswEAAf8BAAGIAQAB/wEAAVcBAAH/ASoBagEqAf4DYgHuA1AB + zAEAAf8BAAHTAQAB/wEAAcsBAAH/AQABswEAAf8BAAGIAQAB/wEAAVcBAAH/ASsBawErAf4DYgHuA1AB mgMDAQQDAwEEAVICUwGlAWACbwHzAQACggH/AQACmQH/AQACtgH/AQACzAH/AQAC0wH/AQACywH/AQAC - swH/AQACiAH/AQACVwH/ASoCagH+A2IB7gNQAZoDAwEEAwMBBAJSAVMBpQJgAW8B8wIAAYIB/wIAAZkB - /wIAAbYB/wIAAcwB/wIAAdMB/wIAAcsB/wIAAbMB/wIAAYgB/wIAAVcB/wIqAWoB/gNiAe4DUAGaAwMB + swH/AQACiAH/AQACVwH/ASsCawH+A2IB7gNQAZoDAwEEAwMBBAJSAVMBpQJgAW8B8wIAAYIB/wIAAZkB + /wIAAbYB/wIAAcwB/wIAAdMB/wIAAcsB/wIAAbMB/wIAAYgB/wIAAVcB/wIrAWsB/gNiAe4DUAGaAwMB BAMtAUQDYAHoA4AB/gNuAf8DewH/A4UB/wOKAf8DjAH/A4oB/wOFAf8DdgH/A1cB/wMyAf8DQAH9A14B - 3QMqAT8DLQFEAWABaQFgAegBKgGAASoB/gEAAcYBAAH/AQAB3AEAAf8BAAHuAQAB/wEAAfgBAAH/AQAB + 3QMqAT8DLQFEAWABaQFgAegBKwGAASsB/gEAAcYBAAH/AQAB3AEAAf8BAAHuAQAB/wEAAfgBAAH/AQAB +wEAAf8BAAH5AQAB/wEAAe8BAAH/AQAB1AEAAf8BAAGcAQAB/wEAAVoBAAH/A0AB/QNeAd0DKgE/Ay0B - RAFgAmkB6AEqAoAB/gEAAsYB/wEAAtwB/wEAAu4B/wEAAvgB/wEAAvsB/wEAAvkB/wEAAu8B/wEAAtQB - /wEAApwB/wEAAloB/wNAAf0DXgHdAyoBPwMtAUQCYAFpAegCKgGAAf4CAAHGAf8CAAHcAf8CAAHuAf8C + RAFgAmkB6AErAoAB/gEAAsYB/wEAAtwB/wEAAu4B/wEAAvgB/wEAAvsB/wEAAvkB/wEAAu8B/wEAAtQB + /wEAApwB/wEAAloB/wNAAf0DXgHdAyoBPwMtAUQCYAFpAegCKwGAAf4CAAHGAf8CAAHcAf8CAAHuAf8C AAH4Af8CAAH7Af8CAAH5Af8CAAHvAf8CAAHUAf8CAAGcAf8CAAFaAf8DQAH9A14B3QMqAT8DTgGVA3cB +AN/Af8DhQH/A4oB/wONAf8DjgH/A44B/wOOAf8DjQH/A4kB/wN3Af8DTQH/AyUB/wNaAfIDSgGLA04B lQFcAXwBXAH4AQAB5QEAAf8BAAHvAQAB/wEAAfgBAAH/AQAB/QEAAf8BAAH/AQAB/wEAAf8BAAH/AQAB @@ -234,50 +234,50 @@ +wH/AQMC/QH/AQAC/gH/AQAD/wEAA/8BAAP/AQAD/wEAA/8BAAL9Af8BAALvAf8BAAK5Af8BAAJdAf8D QQH5A1oBxAJbAV8B0wIrAX4B/AIOAfsB/wIDAf0B/wIAAf4B/wIAAv8CAAL/AgAC/wIAAv8CAAL/AgAB /QH/AgAB7wH/AgABuQH/AgABXQH/A0EB+QNaAcQDbgH1A4AB/gOfAf8DkwH/A48B/wOOAf8DjgH/A44B - /wOOAf8DjgH/A44B/wOLAf8DdwH/A0gB/wNAAf0DYgHhAVoBbgFaAfUBTgGrAU4B/gEnAf8BJwH/AQsB + /wOOAf8DjgH/A44B/wOLAf8DdwH/A0gB/wNAAf0DYgHhAVoBbgFaAfUBTwGpAU8B/gEnAf8BJwH/AQsB /wELAf8BAQH/AQEB/wEAAf8BAAH/AQAB/wEAAf8BAAH/AQAB/wEAAf8BAAH/AQAB/wEAAf8BAAH/AQAB - /wEAAfkBAAH/AQAB1gEAAf8BAAGBAQAB/wNAAf0DYgHhAVoCbgH1AU4CqwH+AScD/wELA/8BAQP/AQAD - /wEAA/8BAAP/AQAD/wEAA/8BAAP/AQAC+QH/AQAC1gH/AQACgQH/A0AB/QNiAeECWgFuAfUCTgGrAf4C + /wEAAfkBAAH/AQAB1gEAAf8BAAGBAQAB/wNAAf0DYgHhAVoCbgH1AU8CqQH+AScD/wELA/8BAQP/AQAD + /wEAA/8BAAP/AQAD/wEAA/8BAAP/AQAC+QH/AQAC1gH/AQACgQH/A0AB/QNiAeECWgFuAfUCTwGpAf4C JwL/AgsC/wIBAv8CAAL/AgAC/wIAAv8CAAL/AgAC/wIAAv8CAAH5Af8CAAHWAf8CAAGBAf8DQAH9A2IB 4QNjAfYDgAH+A6sB/wOZAf8DkAH/A44B/wOOAf8DjgH/A44B/wOOAf8DjgH/A40B/wN/Af8DVQH/A0AB - /QNeAeIBSAFjAUgB9gFxAasBcQH+AUIB/wFCAf8BGQH/ARkB/wEEAf8BBAH/AQAB/wEAAf8BAAH/AQAB + /QNeAeIBSAFjAUgB9gFyAakBcgH+AUIB/wFCAf8BGQH/ARkB/wEEAf8BBAH/AQAB/wEAAf8BAAH/AQAB /wEAAf8BAAH/AQAB/wEAAf8BAAH/AQAB/wEAAf8BAAH/AQAB/QEAAf8BAAHkAQAB/wEAAZgBAAH/A0AB - /QNeAeIBSAJjAfYBcQKrAf4BQgP/ARkD/wEEA/8BAAP/AQAD/wEAA/8BAAP/AQAD/wEAA/8BAAL9Af8B - AALkAf8BAAKYAf8DQAH9A14B4gJIAWMB9gJxAasB/gJCAv8CGQL/AgQC/wIAAv8CAAL/AgAC/wIAAv8C + /QNeAeIBSAJjAfYBcgKpAf4BQgP/ARkD/wEEA/8BAAP/AQAD/wEAA/8BAAP/AQAD/wEAA/8BAAL9Af8B + AALkAf8BAAKYAf8DQAH9A14B4gJIAWMB9gJyAakB/gJCAv8CGQL/AgQC/wIAAv8CAAL/AgAC/wIAAv8C AAL/AgAC/wIAAf0B/wIAAeQB/wIAAZgB/wNAAf0DXgHiA2EB1gN+AfwDuAH/A6MB/wOTAf8DjgH/A44B - /wOOAf8DjgH/A44B/wOOAf8DjQH/A4IB/wNcAf8DTQH6A1oBxwFcAWEBXAHWAWQBgwFkAfwBXwH/AV8B + /wOOAf8DjgH/A44B/wOOAf8DjQH/A4IB/wNcAf8DTQH6A1oBxwFcAWEBXAHWAWQBgAFkAfwBXwH/AV8B /wEvAf8BLwH/AQwB/wEMAf8BAQH/AQEB/wEAAf8BAAH/AQAB/wEAAf8BAAH/AQAB/wEAAf8BAAH/AQAB - /wEAAf8BAAH+AQAB/wEAAeoBAAH/AQABpQEAAf8BSAFNAUgB+gNaAccBXAJhAdYBZAKDAfwBXwP/AS8D - /wEMA/8BAQP/AQAD/wEAA/8BAAP/AQAD/wEAA/8BAAL+Af8BAALqAf8BAAKlAf8BSAJNAfoDWgHHAlwB - YQHWAmQBgwH8Al8C/wIvAv8CDAL/AgEC/wIAAv8CAAL/AgAC/wIAAv8CAAL/AgAB/gH/AgAB6gH/AgAB - pQH/AkgBTQH6A1oBxwNQAZoDbQH5A8UB/wOyAf8DnAH/A5EB/wOOAf8DjgH/A44B/wOOAf8DjwH/A44B - /wODAf8DYAH/A1oB8gNMAZADUAGaAWoBfwFqAfkBfAH/AXwB/wFRAf8BUQH/AR8B/wEfAf8BBwH/AQcB + /wEAAf8BAAH+AQAB/wEAAeoBAAH/AQABpQEAAf8BSgFNAUoB+gNaAccBXAJhAdYBZAKAAfwBXwP/AS8D + /wEMA/8BAQP/AQAD/wEAA/8BAAP/AQAD/wEAA/8BAAL+Af8BAALqAf8BAAKlAf8BSgJNAfoDWgHHAlwB + YQHWAmQBgAH8Al8C/wIvAv8CDAL/AgEC/wIAAv8CAAL/AgAC/wIAAv8CAAL/AgAB/gH/AgAB6gH/AgAB + pQH/AkoBTQH6A1oBxwNQAZoDawH5A8UB/wOyAf8DnAH/A5EB/wOOAf8DjgH/A44B/wOOAf8DjwH/A44B + /wODAf8DYAH/A1oB8gNMAZADUAGaAWoBfQFqAfkBfAH/AXwB/wFRAf8BUQH/AR8B/wEfAf8BBwH/AQcB /wEBAf8BAQH/AQAB/wEAAf8BAAH/AQAB/wEAAf8BAAH/AQIB/wECAf8BAgH+AQIB/wEAAesBAAH/AQAB - rQEAAf8BWgFrAVoB8gNMAZADUAGaAWoCfwH5AXwD/wFRA/8BHwP/AQcD/wEBA/8BAAP/AQAD/wEAA/8B - AgP/AQIC/gH/AQAC6wH/AQACrQH/AVoCawHyA0wBkANQAZoCagF/AfkCfAL/AlEC/wIfAv8CBwL/AgEC + rQEAAf8BWgFrAVoB8gNMAZADUAGaAWoCfQH5AXwD/wFRA/8BHwP/AQcD/wEBA/8BAAP/AQAD/wEAA/8B + AgP/AQIC/gH/AQAC6wH/AQACrQH/AVoCawHyA0wBkANQAZoCagF9AfkCfAL/AlEC/wIfAv8CBwL/AgEC /wIAAv8CAAL/AgAC/wICAv8CAgH+Af8CAAHrAf8CAAGtAf8CWgFrAfIDTAGQAy8BSQNsAesDgAH+A8YB /wOuAf8DnAH/A5MB/wOQAf8DjwH/A5AB/wOTAf8DkwH/A4UB/wNAAf0DYAHgAy0BRQMvAUkDbAHrAYAB - qwGAAf4BfwH/AX8B/wFJAf8BSQH/AR8B/wEfAf8BDAH/AQwB/wEFAf8BBQH/AQMB/wEDAf8BBQH/AQUB - /wEKAf8BCgH/AQoB/gEKAf8BAQHtAQEB/wFAAbYBQAH9AWABZgFgAeADLQFFAy8BSQNsAesBgAKrAf4B + qQGAAf4BfwH/AX8B/wFJAf8BSQH/AR8B/wEfAf8BDAH/AQwB/wEFAf8BBQH/AQMB/wEDAf8BBQH/AQUB + /wEKAf8BCgH/AQoB/gEKAf8BAQHtAQEB/wFAAbYBQAH9AWABZgFgAeADLQFFAy8BSQNsAesBgAKpAf4B fwP/AUkD/wEfA/8BDAP/AQUD/wEDA/8BBQP/AQoD/wEKAv4B/wEBAu0B/wFAArYB/QFgAmYB4AMtAUUD - LwFJA2wB6wKAAasB/gJ/Av8CSQL/Ah8C/wIMAv8CBQL/AgMC/wIFAv8CCgL/AgoB/gH/AgEB7QH/AkAB + LwFJA2wB6wKAAakB/gJ/Av8CSQL/Ah8C/wIMAv8CBQL/AgMC/wIFAv8CCgL/AgoB/gH/AgEB7QH/AkAB tgH9AmABZgHgAy0BRQMDAQQDVgGuA24B9QPZAf8DywH/A7cB/wOnAf8DnQH/A5oB/wOcAf8DnwH/A5sB /wOJAf8DaAHwA1IBowMDAQQDAwEEA1YBrgNuAfUBqAH/AagB/wGJAf8BiQH/AVwB/wFcAf8BNwH/ATcB /wEiAf8BIgH/ARsB/wEbAf8BHwH/AR8B/wEmAf8BJgH/AR0B/wEdAf8BBQHzAQUB/wFeAWgBXgHwA1IB owMDAQQDAwEEA1YBrgNuAfUBqAP/AYkD/wFcA/8BNwP/ASID/wEbA/8BHwP/ASYD/wEdA/8BBQLzAf8B XgJoAfADUgGjAwMBBAMDAQQDVgGuA24B9QKoAv8CiQL/AlwC/wI3Av8CIgL/AhsC/wIfAv8CJgL/Ah0C - /wIFAfMB/wJeAWgB8ANSAaMDAwEEBAADHAEnA10BxwNjAfYDiwH+A9cB/wPMAf8DwgH/A7sB/wO3Af8D - sQH/A4AB/gNoAfQDWQG8AxsBJggAAxwBJwNdAccDYwH2AYABqwGAAf4BpQH/AaUB/wGLAf8BiwH/AXQB - /wF0Af8BZgH/AWYB/wFcAf8BXAH/AU4B/wFOAf8BWgGrAVoB/gFTAWgBUwH0AVcBWQFXAbwDGwEmCAAD - HAEnA10BxwNjAfYBgAKrAf4BpQP/AYsD/wF0A/8BZgP/AVwD/wFOA/8BWgKrAf4BUwJoAfQBVwJZAbwD - GwEmCAADHAEnA10BxwNjAfYCgAGrAf4CpQL/AosC/wJ0Av8CZgL/AlwC/wJOAv8CWgGrAf4CUwFoAfQC + /wIFAfMB/wJeAWgB8ANSAaMDAwEEBAADHAEnA10BxwNjAfYDiQH+A9cB/wPMAf8DwgH/A7sB/wO3Af8D + sQH/A4AB/gNoAfQDWQG8AxsBJggAAxwBJwNdAccDYwH2AYABqQGAAf4BpQH/AaUB/wGLAf8BiwH/AXQB + /wF0Af8BZgH/AWYB/wFcAf8BXAH/AU4B/wFOAf8BWwGpAVsB/gFTAWgBUwH0AVcBWQFXAbwDGwEmCAAD + HAEnA10BxwNjAfYBgAKpAf4BpQP/AYsD/wF0A/8BZgP/AVwD/wFOA/8BWwKpAf4BUwJoAfQBVwJZAbwD + GwEmCAADHAEnA10BxwNjAfYCgAGpAf4CpQL/AosC/wJ0Av8CZgL/AlwC/wJOAv8CWwGpAf4CUwFoAfQC VwFZAbwDGwEmDAADIQEwA1kBtgNiAe4DfQH6A74B/QPUAf8DzAH/A74B/QNqAfkDbAHrA1UBrAMfASwQ - AAMhATADWQG2A2IB7gN9AfoBrgG+Aa4B/QGfAf8BnwH/AYwB/wGMAf8BTAG+AUwB/QFoAX8BaAH5AWEB - bAFhAesDVQGsAx8BLBAAAyEBMANZAbYDYgHuA30B+gGuAr4B/QGfA/8BjAP/AUwCvgH9AWgCfwH5AWEC - bAHrA1UBrAMfASwQAAMhATADWQG2A2IB7gN9AfoCrgG+Af0CnwL/AowC/wJMAb4B/QJoAX8B+QJhAWwB - 6wNVAawDHwEsFAADBgEHAzYBWANVAawDZgHlA34B/AOBAfsDZQHiA1MBpwMzAVEDBgEHGAADBgEHAzYB - WANVAawDZgHlAX4BgwF+AfwBXwGMAV8B+wNlAeIDUwGnAzMBUQMGAQcYAAMGAQcDNgFYA1UBrANmAeUB - fgKDAfwBXwKMAfsDZQHiA1MBpwMzAVEDBgEHGAADBgEHAzYBWANVAawDZgHlAn4BgwH8Al8BjAH7A2UB + AAMhATADWQG2A2IB7gN9AfoBrgG+Aa4B/QGfAf8BnwH/AYwB/wGMAf8BSwG+AUsB/QFoAX0BaAH5AWEB + bAFhAesDVQGsAx8BLBAAAyEBMANZAbYDYgHuA30B+gGuAr4B/QGfA/8BjAP/AUsCvgH9AWgCfQH5AWEC + bAHrA1UBrAMfASwQAAMhATADWQG2A2IB7gN9AfoCrgG+Af0CnwL/AowC/wJLAb4B/QJoAX0B+QJhAWwB + 6wNVAawDHwEsFAADBgEHAzYBWANVAawDZgHlA34B/AOAAfsDZQHiA1MBpwMzAVEDBgEHGAADBgEHAzYB + WANVAawDZgHlAX4BgAF+AfwBXwGLAV8B+wNlAeIDUwGnAzMBUQMGAQcYAAMGAQcDNgFYA1UBrANmAeUB + fgKAAfwBXwKLAfsDZQHiA1MBpwMzAVEDBgEHGAADBgEHAzYBWANVAawDZgHlAn4BgAH8Al8BiwH7A2UB 4gNTAacDMwFRAwYBBwwAAUIBTQE+BwABPgMAASgDAAFAAwABIAMAAQEBAAEBBgABARYAA/+BAAHgAQcB 4AEHAeABBwHgAQcBwAEDAcABAwHAAQMBwAEDAYABAQGAAQEBgAEBAYABAVAAAYABAQGAAQEBgAEBAYAB AQHAAQMBwAEDAcABAwHAAQMB4AEHAeABBwHgAQcB4AEHCw== @@ -291,7 +291,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAEZTeXN0ZW0uV2luZG93cy5Gb3JtcywgQ3VsdHVyZT1uZXV0cmFs LCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAAAmU3lzdGVtLldpbmRvd3MuRm9ybXMu SW1hZ2VMaXN0U3RyZWFtZXIBAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAKCUAAAJNU0Z0AUkBTAIBAQMB - AAEQAQIBEAECASABAAEgAQAE/wEhAQAI/wFCAU0BNgcAATYDAAEoAwABgAMAASADAAEBAQABIAYAAUB6 + AAEYAQIBGAECASABAAEgAQAE/wEhAQAI/wFCAU0BNgcAATYDAAEoAwABgAMAASADAAEBAQABIAYAAUB6 AANcAecBCAEKAQAB/wMqAUAMAAMqAUADNgFXAz8BbAM/AWwDPwFsAz8BbAM/AWwDPwFsAz8BbAM/AWwD PwFsAz8BbAM/AWwDPwFsAz8BbAM/AWwDPwFsAz8BbAI7AToBYgMzAVEDGAEhVAADUwGiA1sBwCAAA1QB pgNZAbzwAAMhATADRgGAFAABFQEfAQQB/wENARUBAAH/AQgBCgEAAf8BCAEKAQAB/wwAA0QBegNTAacC @@ -377,7 +377,7 @@ UgGMAQgB/wFSAYwBCAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEQAf8BUgGMARAB/wFaAZQB EAH/AVoBlAEQAf8BWgGbARAB/wFaAZwBEAH/AVoBnAEQAf8BWgGcARAB/wFaAZYBFgH/AVoBlAEYAf8B XQGXARgB/wFjAZwBGAH/AWMBpQEXAf8BYwGlARcB/wFwAbMBIAH/ASsBUAEEAf8IAAMnAToCUwFRAaIB - gwFfASEB+wJlAVwB5wJcAVoBxAJDAUIBdQMxAU0CQAE/AW4CUQFQAZ8CZQFgAeMB/wF4AQAC/wF4AQAB + ggFfASEB+wJlAVwB5wJcAVoBxAJDAUIBdQMxAU0CQAE/AW4CUQFQAZ8CZQFgAeMB/wF4AQAC/wF4AQAB /wJRAVABnwMSARgcAAMZASIDTgGVAlsBXgHNAlYBVwGyA0QBegMdASkDBgEIBAIEATAAA18B0ANiAe4g AANhAdQDYwHpvAABSgGEAQYB/wFSAYwBCAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEIAf8B ZwGpARcB/wFSAYwBCAH/AUoBhAEGAf8BSgGEAQYB/wFSAYwBEAH/AVoBlAEQAf8BWgGXARAB/wFaAZwB @@ -397,13 +397,13 @@ YgHclAABSgGMAQAB/wFSAYwBCAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBCAH/AWcBnQEnAf8BCAEKAQAB /wEKAQ8BAAH/AUIBdwEDAf8BUgGMARAB/wFaAZwBEAH/ASUBQQEFAf8EAAM6AWABCAEKAQAB/wEIAQoB AAH/BAADRgGAA0YBgANGAYAcAAMKAQ0DIgExAzQBVANEAXgCUQFQAZ8CYQFdAc8CagFeAe0CZQFdAewC - aAFeAfABgwFfASEB+wH/AXgBAAL/AXgBAAH/AlEBUAGfAxIBGBwAAwYBCAMYASEDMQFNAkwBTQGRAlgB + aAFeAfABggFfASEB+wH/AXgBAAL/AXgBAAH/AlEBUAGfAxIBGBwAAwYBCAMYASEDMQFNAkwBTQGRAlgB WgG9Al0BYQHRAlkBXAHDAlEBUwGiAz0BZwIZARoBIwMMAQ8DQAFvA1UBrQNVAa0DVQGtA1UBrQNVAa0D VQGtA1UBrQNVAa0DVQGtA2gB8AN9AfoDVQGtA1UBrQNVAa0DVQGtA1UBrQNVAa0DVQGtA1UBrQNwAfED fAH4A1UBrQNVAa0DVQGtA1UBrQNVAa0DVQGtA1UBrQNVAa0DVQGtA0cBgZQAATsBbQECAf8BUgGMAQgB /wFSAYwBCAH/AVIBjAEIAf8BUgGMAQgB/wFTAY4BEAH/AQ8BGwEAAf8BIwFDAQAB/wFSAYwBEAH/AVIB jAEQAf8BewG9ATAB/wEIAQoBAAH/AQgBCgEAAf8BCAEKAQAB/wEIAQoBAAH/AQgBCgEAAf8BCAEKAQAB - /wEIAQoBAAH/KAADAwEEAwkBCwMiATEDOAFbAk8BTgGXAl8BXAHIAmYBXwHlAm8BUQH3Ab4BRQFAAf0B + /wEIAQoBAAH/KAADAwEEAwkBCwMiATEDOAFbAk8BTgGXAl8BXAHIAmYBXwHlAm8BUQH3Ab4BRAFAAf0B /wF4AQAC/wF4AQAB/wJRAVABnwMSARgcAAQBAwIBAwMVARwDNQFWAksBTAGPAlwBXwHIAl0BYwHfAmAB ZQHjAlIBUwGlAzQBUwMcAScoAANfAdADYgHuIAADYQHUA2MB6bwAAQgBCgEAAf8BUgGMAQgB/wFSAYwB CAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBCAH/AU4BggEPAf8BSgGEAQYB/wFSAYwBEAH/AWMBpQEXAf8B @@ -413,7 +413,7 @@ 0AJQAVEBnwMzAVEoAANfAdADYgHuIAADYQHUA2MB6cAAAUIBcwEGAf8BUgGMAQgB/wFSAYwBCAH/AVIB jAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEQAf8BUgGMARAB/wFKAYQBBgH/ARABHgEAAf8BMQFaAQAB /wFNAYQBDQH/AVoBnAEQAf8BWgGcARAB/wFSAYwBCAH/ARABHgEAAf8BCAEKAQAB/wEIAQoBAAH/A0YB - gCwAAwIBAwMLAQ4DIAEuA0MBdgJXAVUBsQJmAWAB4AJjAUgB9gFtAWoBQQH5AlEBUAGcAxIBFwwABAED + gCwAAwIBAwMLAQ4DIAEuA0MBdgJXAVUBsQJmAWAB4AJjAUgB9gFrAWoBQQH5AlEBUAGcAxIBFwwABAED DAEQAxcBHwMdASgDHQEoAwwBDwgAAw8BFAImAScBOQJHAUgBgwNiAeECXAFlAecDXgHSAj8BQAFuKAAD XwHQA2IB7iAAA2EB1ANjAenEAAFJAYkBAAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEIAf8B UgGMARAB/wFSAYwBEAH/AVIBjAEQAf8BUgGMARAB/wFaAZQBEAH/AVoBnAEQAf8BWgGcARAB/wFaAZwB @@ -463,7 +463,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAEZTeXN0ZW0uV2luZG93cy5Gb3JtcywgQ3VsdHVyZT1uZXV0cmFs LCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAAAmU3lzdGVtLldpbmRvd3MuRm9ybXMu SW1hZ2VMaXN0U3RyZWFtZXIBAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAshIAAAJNU0Z0AUkBTAIBAQQB - AAEQAQMBEAEDARABAAEQAQAE/wEhAQAI/wFCAU0BNgcAATYDAAEoAwABQAMAASADAAEBAQABIAYAASD/ + AAEYAQMBGAEDARABAAEQAQAE/wEhAQAI/wFCAU0BNgcAATYDAAEoAwABQAMAASADAAEBAQABIAYAASD/ AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/ACIAA2cB7wJnAVkB7wFnAV0BWQHvAWcBWwFZAe8B ZwFbAVkB7wFnAlkB7wFnAWQBWQHvA2cB7wNnAe8DZwHvA2cB7wNnAe8DZwHvA2cB7wNnAe8DZwHvAwcB CQMqAT8DRQF8A1kBuwNjAd8DaAH0A4AB/gOBAf8DgQH/A4EB/wOAAf4DaAH0A2MB3wNaAboDRAF6AycB @@ -489,7 +489,7 @@ YAH/AYMBggF/Af8BhQGCAX0B/wGzAZMBRAH/Ac8BlAEAAf8B3gHMAZ8B/wOwAf8DsAH/A7AB/wOwAf8D sAH/A7AB/wOwAf8DsAH/A6gB/wMCAQMDGgEjAzgBXANUAagDYgHXA3AB8QOAAf4DgQH/A4EB/wOBAf8D gQH9A2gB8ANhAdQDUwGlAzYBWQMYASAIAAMaASQDUgGgAmMBSAH2AaIBcwEAAf8BrgF8AQAB/wGwAX0B - AAH/AagBeAEAAf8BlQFqAQAB/wKAAWIB/gFcAlkBxgNXAbUDFgEeCAAB/wGyAW8B/wH9AYABEQH/AfwB + AAH/AagBeAEAAf8BlQFqAQAB/wKAAWMB/gFcAlkBxgNXAbUDFgEeCAAB/wGyAW8B/wH9AYABEQH/AfwB dwEBAf8B/QF3AQAC/wF4AQAC/wF/AQ8C/wGSATsC/wGzAYMC/wHqAeAC/wGQAT0C/wF7AQoB/wH8AXcB AAH/AeUBbAEAAf8BsQFUAQAB/wGEAUsBGgH/A2MB3wT/AdkBqgE3Af8BvgGYATgB/wHAAZgBNgH/AdwB ogEUAf8BzwGUAQAB/wHeAcwBnwH/A4EB/wOBAf8DgQH/A4EB/wOBAf8DgQH/A4EB/wOBAf8DkwH/RAAD diff --git a/qtc-net-client-2/Forms/Profile.cs b/qtc-net-client-2/Forms/Profile.cs index 81d1483..364bafb 100644 --- a/qtc-net-client-2/Forms/Profile.cs +++ b/qtc-net-client-2/Forms/Profile.cs @@ -26,6 +26,7 @@ namespace qtc_net_client_2.Forms public partial class Profile : Form { private UserInformationDto _userInformationDto; + private ImageFactory _imgFactory = new(); private IApiService _apiService; private IGatewayService _gatewayService; @@ -85,7 +86,7 @@ namespace qtc_net_client_2.Forms cosmetic = new Bitmap(ms); } - CreateProfileImage(precenseImage, pfp, cosmetic); + pbUserPfp.Image = _imgFactory.CreateProfileImage(precenseImage, pfp, cosmetic); precenseImage.Dispose(); pfp?.Dispose(); cosmetic?.Dispose(); @@ -181,6 +182,9 @@ namespace qtc_net_client_2.Forms private async void btnAddContact_Click_Remove(object sender, EventArgs e) { + var msgBoxResult = MessageBox.Show("Are You Sure You Want To Remove This User From Your Contacts?", "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + if (msgBoxResult == DialogResult.No) return; + var result = await _apiService.RemoveContactFromCurrentUser(_userInformationDto.Id); if (result.Success) { @@ -207,6 +211,9 @@ namespace qtc_net_client_2.Forms private async void btnDecline_Click(object sender, EventArgs e) { + var msgBoxResult = MessageBox.Show("Are You Sure You Want To Decline This Request?", "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + if (msgBoxResult == DialogResult.No) return; + var result = await _apiService.RemoveContactFromCurrentUser(_userInformationDto.Id); if (result.Success) { @@ -221,6 +228,9 @@ namespace qtc_net_client_2.Forms private async void btnCancelRequest_Click(object sender, EventArgs e) { + var msgBoxResult = MessageBox.Show("Are You Sure You Want To Cancel This Request?", "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + if (msgBoxResult == DialogResult.No) return; + var result = await _apiService.RemoveContactFromCurrentUser(_userInformationDto.Id); if (result.Success) { @@ -238,32 +248,5 @@ namespace qtc_net_client_2.Forms Close(); frmDirectMessage.Show(); } - - private void CreateProfileImage(Bitmap precenseImage, Bitmap? pfp = null, Bitmap? cosmetic = null) - { - Bitmap combined = new Bitmap(139, 138); - - using Graphics g = Graphics.FromImage(combined); - g.Clear(Color.Transparent); - g.CompositingMode = CompositingMode.SourceOver; - - if (pfp != null) - { - pfp.MakeTransparent(); - g.DrawImage(pfp, 4, 6, 128, 128); - } - else g.DrawImage(pbUserPfp.Image, 4, 6, 128, 128); - - if (cosmetic != null) - { - cosmetic.MakeTransparent(); - g.DrawImage(cosmetic, 0, 0, 139, 138); - } - - precenseImage.MakeTransparent(); - g.DrawImage(precenseImage, 104, 0, 35, 35); - - pbUserPfp.Image = combined; - } } } diff --git a/qtc-net-client-2/Forms/ProfileEdit.cs b/qtc-net-client-2/Forms/ProfileEdit.cs index bd0dd28..0f880d2 100644 --- a/qtc-net-client-2/Forms/ProfileEdit.cs +++ b/qtc-net-client-2/Forms/ProfileEdit.cs @@ -17,6 +17,7 @@ namespace qtc_net_client_2.Forms public partial class ProfileEdit : Form { IApiService _apiService; + private int currentCosmetic = 0; public ProfileEdit(IApiService apiService) { _apiService = apiService; @@ -65,11 +66,13 @@ namespace qtc_net_client_2.Forms cbCosmetic.DataSource = items; cbCosmetic.SelectedIndex = cbCosmetic.Items.IndexOf(items.FirstOrDefault(e => (int?)e.Value == _apiService.CurrentUser.ActiveProfileCosmetic)); + currentCosmetic = cbCosmetic.Items.IndexOf(items.FirstOrDefault(e => (int?)e.Value == _apiService.CurrentUser.ActiveProfileCosmetic)); } private async void btnSave_Click(object sender, EventArgs e) { ComboBoxItem? selectedItem = (ComboBoxItem?)cbCosmetic.SelectedItem; + int selectedItemId = 0; // update user info UserUpdateInformationDto userUpdateInformationDto = new UserUpdateInformationDto @@ -82,7 +85,7 @@ namespace qtc_net_client_2.Forms if (selectedItem != null) { - int selectedItemId = (int?)selectedItem.Value ?? 0; + selectedItemId = (int?)selectedItem.Value ?? 0; userUpdateInformationDto.ProfileCosmeticId = selectedItemId; } @@ -90,7 +93,8 @@ namespace qtc_net_client_2.Forms if (res.Success) { - DialogResult = DialogResult.OK; + if (currentCosmetic != selectedItemId) DialogResult = DialogResult.Yes; // trigger ui refresh + else DialogResult = DialogResult.OK; Close(); } else diff --git a/qtc-net-client-2/Forms/StoreItemDisplay.cs b/qtc-net-client-2/Forms/StoreItemDisplay.cs index 361ede8..5cbc41d 100644 --- a/qtc-net-client-2/Forms/StoreItemDisplay.cs +++ b/qtc-net-client-2/Forms/StoreItemDisplay.cs @@ -87,10 +87,12 @@ namespace qtc_net_client_2.Forms }; await _apiService.UpdateUserInformationAsync(updateDto); + DialogResult = DialogResult.Yes; } } else MessageBox.Show("We Weren't Able To Complete Your Purchase.\nYou May Not Have Enough Funds For This Item.", "Oops.", MessageBoxButtons.OK, MessageBoxIcon.Error); + DialogResult = DialogResult.OK; Close(); } } diff --git a/qtc-net-client-2/Services/ImageFactory.cs b/qtc-net-client-2/Services/ImageFactory.cs new file mode 100644 index 0000000..c5a9206 --- /dev/null +++ b/qtc-net-client-2/Services/ImageFactory.cs @@ -0,0 +1,41 @@ +using qtc_net_client_2.Properties; +using System; +using System.Collections.Generic; +using System.Drawing.Drawing2D; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace qtc_net_client_2.Services +{ + public class ImageFactory + { + public Bitmap CreateProfileImage(Bitmap? precenseImage = null, Bitmap? pfp = null, Bitmap? cosmetic = null) + { + Bitmap combined = new Bitmap(139, 138); + + using Graphics g = Graphics.FromImage(combined); + g.Clear(Color.Transparent); + g.CompositingMode = CompositingMode.SourceOver; + + pfp ??= Resources.DefaultPfp; + + pfp.MakeTransparent(); + g.DrawImage(pfp, 4, 6, 128, 128); + + if (cosmetic != null) + { + cosmetic.MakeTransparent(); + g.DrawImage(cosmetic, 0, 0, 139, 138); + } + + if(precenseImage != null) + { + precenseImage.MakeTransparent(); + g.DrawImage(precenseImage, 104, 0, 35, 35); + } + + return combined; + } + } +}