Compare commits

..

No commits in common. "master" and "6.3" have entirely different histories.
master ... 6.3

12 changed files with 107 additions and 155 deletions

View File

@ -7,11 +7,10 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Meziantou.Framework.Win32.CredentialManager" Version="1.7.6" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.16" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.16" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.9" /> <PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.5" />
<PackageReference Include="RestSharp" Version="112.1.0" /> <PackageReference Include="RestSharp" Version="112.1.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.14.0" /> <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.10.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -15,8 +15,6 @@ namespace QtCNETAPI.Services.ApiService
private RestClient _client; private RestClient _client;
private LoggingService _loggingService; private LoggingService _loggingService;
private CredentialService _credService = new();
internal string? sessionToken; internal string? sessionToken;
internal string apiUri; internal string apiUri;
@ -237,9 +235,9 @@ namespace QtCNETAPI.Services.ApiService
} }
} }
public async Task<ServiceResponse<string>> LoginAsync(UserLoginDto userLoginDto) public async Task<ServiceResponse<User>> LoginAsync(UserLoginDto userLoginDto)
{ {
var serviceResponse = new ServiceResponse<string>(); var serviceResponse = new ServiceResponse<User>();
try try
{ {
@ -259,11 +257,13 @@ namespace QtCNETAPI.Services.ApiService
{ {
SessionToken = response.Data!; SessionToken = response.Data!;
await File.WriteAllTextAsync("./session.token", response.Message);
var user = await SetCurrentUser(); var user = await SetCurrentUser();
serviceResponse.Success = true; serviceResponse.Success = true;
if (response.Message != null) serviceResponse.Message = response.Message; if (response.Message != null) serviceResponse.Message = response.Message;
serviceResponse.Data = response.Message; serviceResponse.Data = user;
} }
else else
{ {
@ -413,23 +413,21 @@ namespace QtCNETAPI.Services.ApiService
public async Task<ServiceResponse<string>> RefreshSessionIfInvalid() public async Task<ServiceResponse<string>> RefreshSessionIfInvalid()
{ {
var tokenHandler = new JwtSecurityTokenHandler(); var tokenHandler = new JwtSecurityTokenHandler();
var refToken = _credService.GetAccessToken(); // fuck CA1416, if this is being ran on linux it should just crash (theoretically) var refToken = await File.ReadAllTextAsync("./session.token");
if (refToken == null)
{
// treat as session expired
return new ServiceResponse<string> { Success = false, Message = "Refresh Token Not Found. Session Expired." };
}
JwtSecurityToken token = tokenHandler.ReadJwtToken(SessionToken); JwtSecurityToken token = tokenHandler.ReadJwtToken(SessionToken);
if(DateTime.Compare(DateTime.UtcNow, token.ValidTo) > 0) if(DateTime.Compare(DateTime.UtcNow, token.ValidTo) > 0)
{ {
if (!File.Exists("./session.token")) { return new ServiceResponse<string> { Success = false, Message = "Session File Not Found. Session Expired." }; }
var result = await RefreshLogin(refToken); var result = await RefreshLogin(refToken);
if (result == null || result.Success == false) if (result == null || result.Success == false)
{ {
return new ServiceResponse<string> { Success = false, Message = "Session Expired." }; // logging in again should overwrite old token File.Delete("./session.token");
return new ServiceResponse<string> { Success = false, Message = "Session Expired." };
} else return new ServiceResponse<string> { Success = true, Data = refToken }; } else return new ServiceResponse<string> { Success = true, Data = refToken };
} else return new ServiceResponse<string> { Success = true, Data = refToken }; } else return new ServiceResponse<string> { Success = true, Data = refToken };
} }

View File

@ -23,7 +23,7 @@ namespace QtCNETAPI.Services.ApiService
public Task<ServiceResponse<List<UserInformationDto>>> GetOnlineUsersAsync(); public Task<ServiceResponse<List<UserInformationDto>>> GetOnlineUsersAsync();
public Task<ServiceResponse<List<UserInformationDto>>> GetAllUsersAsync(); public Task<ServiceResponse<List<UserInformationDto>>> GetAllUsersAsync();
public Task<ServiceResponse<User>> DeleteUserById(string id); public Task<ServiceResponse<User>> DeleteUserById(string id);
public Task<ServiceResponse<string>> LoginAsync(UserLoginDto userLoginDto); public Task<ServiceResponse<User>> LoginAsync(UserLoginDto userLoginDto);
public Task<ServiceResponse<bool>> ResendVerificationEmail(string email); public Task<ServiceResponse<bool>> ResendVerificationEmail(string email);
public Task<ServiceResponse<bool>> SendPasswordResetEmail(string email); public Task<ServiceResponse<bool>> SendPasswordResetEmail(string email);
public Task<ServiceResponse<bool>> ResetPassword(UserPasswordResetDto request); public Task<ServiceResponse<bool>> ResetPassword(UserPasswordResetDto request);

View File

@ -1,26 +0,0 @@
using Meziantou.Framework.Win32;
namespace QtCNETAPI.Services
{
public class CredentialService()
{
public void SaveAccessToken(string username, string accessToken)
{
string applicationName = "QtC.NET";
if (System.Diagnostics.Debugger.IsAttached) applicationName = "QtC.NET.Development";
CredentialManager.WriteCredential(applicationName, username, accessToken, $"Access Token For User {username} On QtC.NET", CredentialPersistence.LocalMachine);
}
public string? GetAccessToken()
{
string applicationName = "QtC.NET";
if (System.Diagnostics.Debugger.IsAttached) applicationName = "QtC.NET.Development";
var credential = CredentialManager.ReadCredential(applicationName);
if (credential == null) return null;
return credential.Password;
}
}
}

View File

@ -36,6 +36,9 @@ namespace QtCNETAPI.Services.GatewayService
public async Task StartAsync() public async Task StartAsync()
{ {
// just to be safe (it doesn't load the server since it shouldn't request a new one unless its actually expired)
await _apiService.RefreshSessionIfInvalid();
// build connection // build connection
var gwConBuilder = new HubConnectionBuilder() var gwConBuilder = new HubConnectionBuilder()
.WithAutomaticReconnect() .WithAutomaticReconnect()
@ -48,14 +51,8 @@ namespace QtCNETAPI.Services.GatewayService
}) })
.WithUrl(gwBaseUri, options => .WithUrl(gwBaseUri, options =>
{ {
options.AccessTokenProvider = async () => options.AccessTokenProvider = () => Task.FromResult(_apiService.SessionToken);
{ });
// this should hopefully refresh the session every time the gateway connection is used to prevent connection aborts
await _apiService.RefreshSessionIfInvalid();
return _apiService.SessionToken;
};
})
.WithStatefulReconnect();
HubConnection = gwConBuilder.Build(); HubConnection = gwConBuilder.Build();
// register events // register events
@ -122,6 +119,8 @@ namespace QtCNETAPI.Services.GatewayService
public async Task JoinLobbyAsync() public async Task JoinLobbyAsync()
{ {
await _apiService.RefreshSessionIfInvalid();
if (HubConnection == null || HubConnection.State != HubConnectionState.Connected) throw new InvalidOperationException("Function was called before connection was made."); if (HubConnection == null || HubConnection.State != HubConnectionState.Connected) throw new InvalidOperationException("Function was called before connection was made.");
await HubConnection.SendAsync("JoinLobby", _apiService.CurrentUser); await HubConnection.SendAsync("JoinLobby", _apiService.CurrentUser);
@ -131,6 +130,8 @@ namespace QtCNETAPI.Services.GatewayService
public async Task JoinRoomAsync(Room room) public async Task JoinRoomAsync(Room room)
{ {
await _apiService.RefreshSessionIfInvalid();
if (HubConnection == null || HubConnection.State != HubConnectionState.Connected) throw new InvalidOperationException("Function was called before connection was made."); if (HubConnection == null || HubConnection.State != HubConnectionState.Connected) throw new InvalidOperationException("Function was called before connection was made.");
if (InLobby == true) if (InLobby == true)
@ -149,6 +150,8 @@ namespace QtCNETAPI.Services.GatewayService
public async Task LeaveRoomAsync() public async Task LeaveRoomAsync()
{ {
await _apiService.RefreshSessionIfInvalid();
if (HubConnection == null || HubConnection.State != HubConnectionState.Connected) throw new InvalidOperationException("Function was called before connection was made."); if (HubConnection == null || HubConnection.State != HubConnectionState.Connected) throw new InvalidOperationException("Function was called before connection was made.");
if (InLobby) if (InLobby)
@ -165,6 +168,8 @@ namespace QtCNETAPI.Services.GatewayService
public async Task PostMessageAsync(Message message) public async Task PostMessageAsync(Message message)
{ {
await _apiService.RefreshSessionIfInvalid();
if (HubConnection == null || HubConnection.State != HubConnectionState.Connected) throw new InvalidOperationException("Function was called before connection was made."); if (HubConnection == null || HubConnection.State != HubConnectionState.Connected) throw new InvalidOperationException("Function was called before connection was made.");
await HubConnection.SendAsync("SendMessage", _apiService.CurrentUser, message, InLobby, CurrentRoom); await HubConnection.SendAsync("SendMessage", _apiService.CurrentUser, message, InLobby, CurrentRoom);
@ -181,6 +186,8 @@ namespace QtCNETAPI.Services.GatewayService
public async Task UpdateStatus(int status) public async Task UpdateStatus(int status)
{ {
await _apiService.RefreshSessionIfInvalid();
if (HubConnection == null || HubConnection.State != HubConnectionState.Connected) throw new InvalidOperationException("Function was called before connection was made."); if (HubConnection == null || HubConnection.State != HubConnectionState.Connected) throw new InvalidOperationException("Function was called before connection was made.");
await HubConnection.SendAsync("UpdateStatus", _apiService.CurrentUser, status); await HubConnection.SendAsync("UpdateStatus", _apiService.CurrentUser, status);

View File

@ -1,6 +1,6 @@
namespace qtc_net_client_2.Forms namespace qtc_net_client_2.Forms
{ {
partial class Login partial class llblForgotPassword
{ {
/// <summary> /// <summary>
/// Required designer variable. /// Required designer variable.
@ -28,7 +28,7 @@
/// </summary> /// </summary>
private void InitializeComponent() private void InitializeComponent()
{ {
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Login)); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(llblForgotPassword));
pbLoginBanner = new PictureBox(); pbLoginBanner = new PictureBox();
tbEmail = new TextBox(); tbEmail = new TextBox();
lblEmail = new Label(); lblEmail = new Label();

View File

@ -1,5 +1,4 @@
using QtCNETAPI.Services.ApiService; using QtCNETAPI.Services.ApiService;
using QtCNETAPI.Services;
using QtCNETAPI.Dtos.User; using QtCNETAPI.Dtos.User;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -10,15 +9,13 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
using qtc_net_client_2.Services;
namespace qtc_net_client_2.Forms namespace qtc_net_client_2.Forms
{ {
public partial class Login : Form public partial class llblForgotPassword : Form
{ {
private IApiService _apiService; private IApiService _apiService;
private CredentialService _credService = new(); public llblForgotPassword(IApiService apiService)
public Login(IApiService apiService)
{ {
_apiService = apiService; _apiService = apiService;
@ -27,14 +24,14 @@ namespace qtc_net_client_2.Forms
private async void frmLogin_Load(object sender, EventArgs e) private async void frmLogin_Load(object sender, EventArgs e)
{ {
string? accessToken = _credService.GetAccessToken(); if (File.Exists("./session.token"))
if (accessToken != null)
{ {
ToggleControls(false, false); ToggleControls(false, false);
// try logging in with the token in cred storage // try logging in with the token in the file
var result = await _apiService.RefreshLogin(accessToken); string token = File.ReadAllText("./session.token");
var result = await _apiService.RefreshLogin(token);
if (result.Success) if (result.Success)
{ {
DialogResult = DialogResult.OK; DialogResult = DialogResult.OK;
@ -58,9 +55,8 @@ namespace qtc_net_client_2.Forms
RememberMe = cbRememberMe.Checked RememberMe = cbRememberMe.Checked
}); });
if (result.Success && result.Data != null) if (result.Success)
{ {
_credService.SaveAccessToken(_apiService.CurrentUser.Username, result.Data);
DialogResult = DialogResult.OK; DialogResult = DialogResult.OK;
Close(); Close();
} }

View File

@ -49,7 +49,7 @@ namespace qtc_net_client_2
if (_apiService.CurrentUser == null) if (_apiService.CurrentUser == null)
{ {
// not logged in, load the login form // not logged in, load the login form
Login frmLogin = new Login(_apiService); llblForgotPassword frmLogin = new llblForgotPassword(_apiService);
var result = frmLogin.ShowDialog(); var result = frmLogin.ShowDialog();
if (result == DialogResult.OK) if (result == DialogResult.OK)
@ -60,7 +60,7 @@ namespace qtc_net_client_2
private async void llblSignIn_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) private async void llblSignIn_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{ {
// just reshow the login dialog lol // just reshow the login dialog lol
Login frmLogin = new Login(_apiService); llblForgotPassword frmLogin = new llblForgotPassword(_apiService);
var result = frmLogin.ShowDialog(); var result = frmLogin.ShowDialog();
if (result == DialogResult.OK) if (result == DialogResult.OK)
@ -172,29 +172,12 @@ namespace qtc_net_client_2
var res = await _apiService.GetUserInformationAsync(user!.Id); var res = await _apiService.GetUserInformationAsync(user!.Id);
var pfpRes = await _apiService.GetUserProfilePic(user!.Id); var pfpRes = await _apiService.GetUserProfilePic(user!.Id);
// 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 (pfpRes != null && !pfpRes.Success) LoggingService.LogString($"User Has No Profile Picture Or It Could Not Be Loaded.\n{pfpRes.Message}"); 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) if (res.Data != null && res.Success)
{ {
LoggingService.LogString($"Opening Profile For User '{res.Data.Username}'"); LoggingService.LogString($"Opening Profile For User '{res.Data.Username}'");
Profile frmProfile = new Profile(res.Data, pfpRes, Contacts, _apiService, _gatewayService, cosmeticData); Profile frmProfile = new Profile(res.Data, pfpRes, Contacts, _apiService, _gatewayService);
frmProfile.Show(); frmProfile.Show();
} }
} }
@ -313,29 +296,12 @@ namespace qtc_net_client_2
var res = await _apiService.GetUserInformationAsync(user!.Id); var res = await _apiService.GetUserInformationAsync(user!.Id);
var pfpRes = await _apiService.GetUserProfilePic(user!.Id); var pfpRes = await _apiService.GetUserProfilePic(user!.Id);
// 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 (pfpRes != null && !pfpRes.Success) LoggingService.LogString($"User Has No Profile Picture Or It Could Not Be Loaded.\n{pfpRes.Message}"); 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) if (res.Data != null && res.Success)
{ {
LoggingService.LogString($"Opening Profile For User '{res.Data.Username}'"); LoggingService.LogString($"Opening Profile For User '{res.Data.Username}'");
Profile frmProfile = new Profile(res.Data, pfpRes, Contacts, _apiService, _gatewayService, cosmeticData); Profile frmProfile = new Profile(res.Data, pfpRes, Contacts, _apiService, _gatewayService);
frmProfile.Show(); frmProfile.Show();
} }
} }

View File

@ -37,11 +37,13 @@
btnDecline = new Button(); btnDecline = new Button();
btnCancelRequest = new Button(); btnCancelRequest = new Button();
btnMessage = new Button(); btnMessage = new Button();
pbUserStatus = new PictureBox();
pbCurrencyIcon = new PictureBox(); pbCurrencyIcon = new PictureBox();
lblCurrencyAmount = new Label(); lblCurrencyAmount = new Label();
flpUsernameCurrency = new FlowLayoutPanel(); flpUsernameCurrency = new FlowLayoutPanel();
pCurrency = new Panel(); pCurrency = new Panel();
((System.ComponentModel.ISupportInitialize)pbUserPfp).BeginInit(); ((System.ComponentModel.ISupportInitialize)pbUserPfp).BeginInit();
((System.ComponentModel.ISupportInitialize)pbUserStatus).BeginInit();
((System.ComponentModel.ISupportInitialize)pbCurrencyIcon).BeginInit(); ((System.ComponentModel.ISupportInitialize)pbCurrencyIcon).BeginInit();
flpUsernameCurrency.SuspendLayout(); flpUsernameCurrency.SuspendLayout();
pCurrency.SuspendLayout(); pCurrency.SuspendLayout();
@ -50,9 +52,9 @@
// pbUserPfp // pbUserPfp
// //
pbUserPfp.Image = Properties.Resources.DefaultPfp; pbUserPfp.Image = Properties.Resources.DefaultPfp;
pbUserPfp.Location = new Point(9, 5); pbUserPfp.Location = new Point(13, 11);
pbUserPfp.Name = "pbUserPfp"; pbUserPfp.Name = "pbUserPfp";
pbUserPfp.Size = new Size(139, 138); pbUserPfp.Size = new Size(128, 128);
pbUserPfp.SizeMode = PictureBoxSizeMode.StretchImage; pbUserPfp.SizeMode = PictureBoxSizeMode.StretchImage;
pbUserPfp.TabIndex = 2; pbUserPfp.TabIndex = 2;
pbUserPfp.TabStop = false; pbUserPfp.TabStop = false;
@ -146,6 +148,17 @@
btnMessage.Visible = false; btnMessage.Visible = false;
btnMessage.Click += btnMessage_Click; btnMessage.Click += btnMessage_Click;
// //
// pbUserStatus
//
pbUserStatus.BackColor = Color.Transparent;
pbUserStatus.Image = Properties.Resources.OfflineIcon;
pbUserStatus.Location = new Point(115, 1);
pbUserStatus.Name = "pbUserStatus";
pbUserStatus.Size = new Size(32, 32);
pbUserStatus.SizeMode = PictureBoxSizeMode.StretchImage;
pbUserStatus.TabIndex = 10;
pbUserStatus.TabStop = false;
//
// pbCurrencyIcon // pbCurrencyIcon
// //
pbCurrencyIcon.Image = Properties.Resources.CurrencyIcon; pbCurrencyIcon.Image = Properties.Resources.CurrencyIcon;
@ -200,6 +213,7 @@
Controls.Add(btnAccept); Controls.Add(btnAccept);
Controls.Add(btnDecline); Controls.Add(btnDecline);
Controls.Add(btnCancelRequest); Controls.Add(btnCancelRequest);
Controls.Add(pbUserStatus);
Controls.Add(btnAddContact); Controls.Add(btnAddContact);
Controls.Add(rtxtBio); Controls.Add(rtxtBio);
Controls.Add(pbUserPfp); Controls.Add(pbUserPfp);
@ -216,6 +230,7 @@
FormClosed += Profile_FormClosed; FormClosed += Profile_FormClosed;
Load += frmProfile_Load; Load += frmProfile_Load;
((System.ComponentModel.ISupportInitialize)pbUserPfp).EndInit(); ((System.ComponentModel.ISupportInitialize)pbUserPfp).EndInit();
((System.ComponentModel.ISupportInitialize)pbUserStatus).EndInit();
((System.ComponentModel.ISupportInitialize)pbCurrencyIcon).EndInit(); ((System.ComponentModel.ISupportInitialize)pbCurrencyIcon).EndInit();
flpUsernameCurrency.ResumeLayout(false); flpUsernameCurrency.ResumeLayout(false);
flpUsernameCurrency.PerformLayout(); flpUsernameCurrency.PerformLayout();
@ -234,6 +249,7 @@
private Button btnDecline; private Button btnDecline;
private Button btnCancelRequest; private Button btnCancelRequest;
private Button btnMessage; private Button btnMessage;
private PictureBox pbUserStatus;
private PictureBox pbCurrencyIcon; private PictureBox pbCurrencyIcon;
private Label lblCurrencyAmount; private Label lblCurrencyAmount;
private FlowLayoutPanel flpUsernameCurrency; private FlowLayoutPanel flpUsernameCurrency;

View File

@ -1,25 +1,24 @@
using qtc_net_client_2.ClientModel; using QtCNETAPI.Dtos.User;
using qtc_net_client_2.Properties;
using qtc_net_client_2.Services;
using QtCNETAPI.Dtos.User;
using QtCNETAPI.Models;
using QtCNETAPI.Schema;
using QtCNETAPI.Services.ApiService; using QtCNETAPI.Services.ApiService;
using QtCNETAPI.Services.GatewayService; using QtCNETAPI.Models;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Data; using System.Data;
using System.Diagnostics;
using System.Drawing; using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
using QtCNETAPI.Services.GatewayService;
using qtc_net_client_2.ClientModel;
using qtc_net_client_2.Properties;
using qtc_net_client_2.Services;
using QtCNETAPI.Schema;
using System.Diagnostics;
using System.Drawing.Imaging;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
namespace qtc_net_client_2.Forms namespace qtc_net_client_2.Forms
{ {
@ -30,16 +29,13 @@ namespace qtc_net_client_2.Forms
private IGatewayService _gatewayService; private IGatewayService _gatewayService;
private ServiceResponse<byte[]>? pfpRes; private ServiceResponse<byte[]>? pfpRes;
byte[]? cosmeticRes;
private List<Contact> contactsList; private List<Contact> contactsList;
public Profile(UserInformationDto userInfo, ServiceResponse<byte[]>? pfp, List<Contact> contacts, IApiService apiService, IGatewayService gatewayService, byte[]? cosmetic = null) public Profile(UserInformationDto userInfo, ServiceResponse<byte[]>? pfp, List<Contact> contacts, IApiService apiService, IGatewayService gatewayService)
{ {
_userInformationDto = userInfo; _userInformationDto = userInfo;
_apiService = apiService; _apiService = apiService;
_gatewayService = gatewayService; _gatewayService = gatewayService;
pfpRes = pfp; pfpRes = pfp;
cosmeticRes = cosmetic;
contactsList = contacts; contactsList = contacts;
InitializeComponent(); InitializeComponent();
@ -51,45 +47,53 @@ namespace qtc_net_client_2.Forms
lblCurrencyAmount.Text = _userInformationDto.CurrencyAmount.ToString("N0"); lblCurrencyAmount.Text = _userInformationDto.CurrencyAmount.ToString("N0");
rtxtBio.Text = _userInformationDto.Bio; rtxtBio.Text = _userInformationDto.Bio;
Bitmap? pfp = null; pbUserPfp.Location = new(13, 11);
pbUserPfp.Size = new(128, 128);
if (pfpRes != null && pfpRes.Success && pfpRes.Data != null) if (pfpRes != null && pfpRes.Success && pfpRes.Data != null)
{ {
using (var ms = new MemoryStream(pfpRes.Data)) using (var ms = new MemoryStream(pfpRes.Data))
{ {
pfp = new Bitmap(ms); pbUserPfp.Image = new Bitmap(ms);
} }
} }
var userStatus = (UserStatus)_userInformationDto.Status; var userStatus = (UserStatus)_userInformationDto.Status;
Bitmap precenseImage = Resources.OnlineIcon;
switch (userStatus) switch (userStatus)
{ {
case UserStatus.Online: case UserStatus.Online:
precenseImage = Resources.OnlineIcon; pbUserStatus.Image = Resources.OnlineIcon;
break; break;
case UserStatus.Away: case UserStatus.Away:
precenseImage = Resources.AwayIcon; pbUserStatus.Image = Resources.AwayIcon;
break; break;
case UserStatus.DoNotDisturb: case UserStatus.DoNotDisturb:
precenseImage = Resources.DNDIcon; pbUserStatus.Image = Resources.DNDIcon;
break; break;
case UserStatus.Offline: case UserStatus.Offline:
precenseImage = Resources.OfflineIcon; pbUserStatus.Image = Resources.OfflineIcon;
break; break;
} }
Bitmap? cosmetic = null; if (_userInformationDto.ProfileCosmeticId != 0)
if(cosmeticRes != null)
{ {
using var ms = new MemoryStream(cosmeticRes); var res = await _apiService.GetStoreItem(_userInformationDto.ProfileCosmeticId);
cosmetic = new Bitmap(ms); if (res != null && res.Success && res.Data != null)
{
var client = new HttpClient();
var response = await client.GetAsync(res.Data.AssetUrl);
if (response.IsSuccessStatusCode)
{
using (var stream = await response.Content.ReadAsStreamAsync())
{
CombineProfileImageWithCosmetic(pbUserPfp.Image, new Bitmap(stream));
}
response.Dispose();
}
client.Dispose();
}
} }
CreateProfileImage(precenseImage, pfp, cosmetic);
precenseImage.Dispose();
pfp?.Dispose();
cosmetic?.Dispose();
if (_userInformationDto.Id == _apiService.CurrentUser!.Id) if (_userInformationDto.Id == _apiService.CurrentUser!.Id)
{ {
btnAddContact.Visible = false; btnAddContact.Visible = false;
@ -239,30 +243,22 @@ namespace qtc_net_client_2.Forms
frmDirectMessage.Show(); frmDirectMessage.Show();
} }
private void CreateProfileImage(Bitmap precenseImage, Bitmap? pfp = null, Bitmap? cosmetic = null) private void CombineProfileImageWithCosmetic(Image pfp, Bitmap cosmetic)
{ {
cosmetic.MakeTransparent();
Bitmap combined = new Bitmap(139, 138); Bitmap combined = new Bitmap(139, 138);
using Graphics g = Graphics.FromImage(combined); using (Graphics g = Graphics.FromImage(combined))
g.Clear(Color.Transparent);
g.CompositingMode = CompositingMode.SourceOver;
if (pfp != null)
{ {
pfp.MakeTransparent(); g.Clear(Color.Transparent);
g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver;
g.DrawImage(pfp, 4, 6, 128, 128); 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); g.DrawImage(cosmetic, 0, 0, 139, 138);
} }
precenseImage.MakeTransparent(); pbUserPfp.Location = new(9, 5);
g.DrawImage(precenseImage, 104, 0, 35, 35); pbUserPfp.Size = new(139, 138);
pbUserPfp.Image = combined; pbUserPfp.Image = combined;
} }
} }

View File

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

View File

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