Reimplement Auto Update
Use ImageFactory Whenever Images Are Grabbed
This commit is contained in:
parent
a0e83ad4df
commit
91c733c3ee
@ -17,11 +17,11 @@ namespace qtcnet_client.Factories
|
||||
_apiService = apiService;
|
||||
}
|
||||
|
||||
public async Task<Bitmap> GetAndCreateProfileImage(string userId, int status, int cosmeticStoreId = 0)
|
||||
public async Task<Bitmap> GetAndCreateProfileImage(string userId, int status = -1, int cosmeticStoreId = 0)
|
||||
{
|
||||
Bitmap combined = new(139, 138);
|
||||
|
||||
Image img1 = Resources.DefaultPfp;
|
||||
Bitmap img1 = Resources.DefaultPfp;
|
||||
Bitmap? img2 = null;
|
||||
Bitmap img3 = Resources.OfflineIcon;
|
||||
|
||||
@ -30,7 +30,7 @@ namespace qtcnet_client.Factories
|
||||
if (_pfpRes.Success && _pfpRes.Data != null)
|
||||
{
|
||||
using var ms = new MemoryStream(_pfpRes.Data);
|
||||
img1 = Image.FromStream(ms);
|
||||
img1 = (Bitmap)Image.FromStream(ms);
|
||||
}
|
||||
|
||||
// get cosmetic image
|
||||
@ -51,7 +51,9 @@ namespace qtcnet_client.Factories
|
||||
}
|
||||
|
||||
// set status image
|
||||
switch(status)
|
||||
if(!int.IsNegative(status))
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case 0:
|
||||
img3 = Resources.OfflineIcon;
|
||||
@ -66,6 +68,7 @@ namespace qtcnet_client.Factories
|
||||
img3 = Resources.DNDIcon;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// finally, combine the images
|
||||
Graphics g = Graphics.FromImage(combined);
|
||||
@ -80,9 +83,11 @@ namespace qtcnet_client.Factories
|
||||
g.DrawImage(img2, 0, 0, 139, 138);
|
||||
}
|
||||
|
||||
|
||||
if(!int.IsNegative(status))
|
||||
{
|
||||
img3.MakeTransparent();
|
||||
g.DrawImage(img3, 104, 0, 35, 35);
|
||||
}
|
||||
|
||||
return combined;
|
||||
}
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
using qtcnet_client.Controls;
|
||||
using qtcnet_client.Factories;
|
||||
using QtCNETAPI.Dtos.User;
|
||||
using QtCNETAPI.Events;
|
||||
using QtCNETAPI.Models;
|
||||
using QtCNETAPI.Services.ApiService;
|
||||
using QtCNETAPI.Services.GatewayService;
|
||||
using System.ComponentModel;
|
||||
using System.Reflection.Metadata.Ecma335;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
namespace qtcnet_client.Forms
|
||||
@ -16,7 +18,7 @@ namespace qtcnet_client.Forms
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
||||
public string RoomName { get; set; } = "Room";
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
public Dictionary<string, Image> UserProfileImages { get; set; } = [];
|
||||
public Dictionary<string, Bitmap> UserProfileImages { get; set; } = [];
|
||||
public string SentMessage { get; private set; } = string.Empty;
|
||||
|
||||
public event EventHandler? OnSend;
|
||||
@ -24,11 +26,13 @@ namespace qtcnet_client.Forms
|
||||
|
||||
private readonly IGatewayService _gatewayService;
|
||||
private readonly IApiService _apiService;
|
||||
private readonly ImageFactory _imgFactory;
|
||||
|
||||
public ChatRoomForm(IGatewayService gatewayService, IApiService apiService)
|
||||
public ChatRoomForm(IGatewayService gatewayService, IApiService apiService, ImageFactory imageFactory)
|
||||
{
|
||||
_gatewayService = gatewayService;
|
||||
_apiService = apiService;
|
||||
_imgFactory = imageFactory;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
@ -127,11 +131,11 @@ namespace qtcnet_client.Forms
|
||||
lvUsers.Items.Add(lvi);
|
||||
}
|
||||
|
||||
public async Task LoadProfileImage(MessageControl ctrl, string userId)
|
||||
public async Task LoadProfileImage(MessageControl ctrl, User user)
|
||||
{
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
var img = await AddUserProfileImageToDictionary(userId);
|
||||
var img = await AddUserProfileImageToDictionary(user);
|
||||
|
||||
if (img == null || ctrl.IsDisposed)
|
||||
return;
|
||||
@ -150,22 +154,15 @@ namespace qtcnet_client.Forms
|
||||
});
|
||||
}
|
||||
|
||||
private async Task<Image?> AddUserProfileImageToDictionary(string userId)
|
||||
private async Task<Bitmap?> AddUserProfileImageToDictionary(User user)
|
||||
{
|
||||
if(UserProfileImages.TryGetValue(userId, out var image))
|
||||
if(UserProfileImages.TryGetValue(user.Id, out var image))
|
||||
return image;
|
||||
else
|
||||
{
|
||||
var _res = await _apiService.GetUserProfilePic(userId);
|
||||
if (_res.Success && _res.Data != null)
|
||||
{
|
||||
using var ms = new MemoryStream(_res.Data);
|
||||
Image img = Image.FromStream(ms);
|
||||
UserProfileImages.Add(userId, img);
|
||||
return UserProfileImages[userId];
|
||||
}
|
||||
else
|
||||
return default;
|
||||
var img = await _imgFactory.GetAndCreateProfileImage(user.Id, -1, user.ActiveProfileCosmetic);
|
||||
UserProfileImages.Add(user.Id, img);
|
||||
return img;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@ using qtcnet_client.Factories;
|
||||
using qtcnet_client.Forms;
|
||||
using qtcnet_client.Model;
|
||||
using qtcnet_client.Properties;
|
||||
using qtcnet_client.Services;
|
||||
using QtCNETAPI.Dtos.User;
|
||||
using QtCNETAPI.Events;
|
||||
using QtCNETAPI.Models;
|
||||
@ -13,6 +14,7 @@ using QtCNETAPI.Services;
|
||||
using QtCNETAPI.Services.ApiService;
|
||||
using QtCNETAPI.Services.GatewayService;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace qtcnet_client
|
||||
@ -39,8 +41,15 @@ namespace qtcnet_client
|
||||
private readonly CredentialService _credentialService;
|
||||
private readonly ClientConfig _config;
|
||||
private readonly ImageFactory _imgFactory;
|
||||
private readonly UpdateService _updateService;
|
||||
|
||||
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)
|
||||
{
|
||||
_apiService = apiService;
|
||||
_gatewayService = gatewayService;
|
||||
@ -48,6 +57,7 @@ namespace qtcnet_client
|
||||
_credentialService = credentialService;
|
||||
_config = config;
|
||||
_imgFactory = imageFactory;
|
||||
_updateService = updateService;
|
||||
|
||||
// sub to currentuser updates
|
||||
_apiService.OnCurrentUserUpdate += _apiService_OnCurrentUserUpdate;
|
||||
@ -72,6 +82,9 @@ namespace qtcnet_client
|
||||
|
||||
private async void MainForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
// first check for updates
|
||||
await _updateService.CheckForUpdatesAsync();
|
||||
|
||||
SuspendLayout();
|
||||
Size = LoggedOutSize;
|
||||
|
||||
@ -237,7 +250,7 @@ namespace qtcnet_client
|
||||
}
|
||||
|
||||
// open the room form
|
||||
ChatRoomForm _chatRoom = new(_gatewayService, _apiService)
|
||||
ChatRoomForm _chatRoom = new(_gatewayService, _apiService, _imgFactory)
|
||||
{
|
||||
RoomId = _roomCtrl.RoomId,
|
||||
RoomName = _roomCtrl.RoomName,
|
||||
@ -569,6 +582,9 @@ namespace qtcnet_client
|
||||
|
||||
if (_res)
|
||||
{
|
||||
if (_apiService.CurrentUser.Status == 0)
|
||||
await _gatewayService.UpdateStatus(1);
|
||||
|
||||
// setup current profile control based on current user
|
||||
CurrentProfileControl = new()
|
||||
{
|
||||
@ -581,13 +597,7 @@ namespace qtcnet_client
|
||||
CurrentProfileControl.OnSignOutClicked += CurrentProfileControl_OnSignOutClicked;
|
||||
|
||||
// get profile image for the current user
|
||||
var _currentProfileImageRes = await _apiService.GetUserProfilePic(_apiService.CurrentUser.Id);
|
||||
if (_currentProfileImageRes.Success && _currentProfileImageRes.Data != null)
|
||||
{
|
||||
using MemoryStream ms = new(_currentProfileImageRes.Data);
|
||||
Image img = Image.FromStream(ms);
|
||||
CurrentProfileControl.ProfileImage = img;
|
||||
}
|
||||
CurrentProfileControl.ProfileImage = await _imgFactory.GetAndCreateProfileImage(_apiService.CurrentUser.Id, _apiService.CurrentUser.Status, _apiService.CurrentUser.ActiveProfileCosmetic);
|
||||
|
||||
// setup main tab control
|
||||
MainTabControl = new()
|
||||
@ -791,7 +801,7 @@ namespace qtcnet_client
|
||||
_chatRoom.AddMessage(_msg);
|
||||
|
||||
if(_args.User.Id != "0")
|
||||
await _chatRoom.LoadProfileImage(_msg, _args.User.Id);
|
||||
await _chatRoom.LoadProfileImage(_msg, _args.User);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
23
qtcnet-client/Model/ClientUpdateInfo.cs
Normal file
23
qtcnet-client/Model/ClientUpdateInfo.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace qtcnet_client.Model
|
||||
{
|
||||
public class ClientUpdateInfo
|
||||
{
|
||||
[JsonPropertyName("clientFileName")]
|
||||
[JsonRequired]
|
||||
public string ClientFileName { get; set; } = "QtCNetChat.exe";
|
||||
[JsonPropertyName("version")]
|
||||
[JsonRequired]
|
||||
public string Version { get; set; } = string.Empty;
|
||||
[JsonPropertyName("downloadUri")]
|
||||
[JsonRequired]
|
||||
public string DownloadUrl { get; set; } = string.Empty;
|
||||
[JsonPropertyName("updateMandatory")]
|
||||
[JsonRequired]
|
||||
public bool IsUpdateMandatory { get; set; } = false;
|
||||
}
|
||||
}
|
||||
@ -3,6 +3,7 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using qtcnet_client.Factories;
|
||||
using qtcnet_client.Model;
|
||||
using qtcnet_client.Services;
|
||||
using QtCNETAPI.Services;
|
||||
using QtCNETAPI.Services.ApiService;
|
||||
using QtCNETAPI.Services.GatewayService;
|
||||
@ -39,6 +40,7 @@ namespace qtcnet_client
|
||||
service.AddSingleton<LoggingService>();
|
||||
service.AddSingleton<CredentialService>();
|
||||
service.AddSingleton<ImageFactory>();
|
||||
service.AddSingleton<UpdateService>();
|
||||
service.AddSingleton(provider => GetOrCreateClientConfig());
|
||||
service.AddSingleton<IApiService>(provider => new ApiService(provider.GetService<ClientConfig>()!.ServerBaseUri + "/api", provider.GetService<LoggingService>()!, provider.GetService<CredentialService>()!));
|
||||
service.AddSingleton<IGatewayService>(provider => new GatewayService(provider.GetService<ClientConfig>()!.ServerBaseUri + "/chat", provider.GetService<IApiService>()!, provider.GetService<LoggingService>()!));
|
||||
|
||||
9
qtcnet-client/Properties/Resources.Designer.cs
generated
9
qtcnet-client/Properties/Resources.Designer.cs
generated
@ -80,6 +80,15 @@ namespace qtcnet_client.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 1.0.0.
|
||||
/// </summary>
|
||||
internal static string AssemblyVersion {
|
||||
get {
|
||||
return ResourceManager.GetString("AssemblyVersion", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
|
||||
@ -166,4 +166,7 @@
|
||||
<data name="DNDIcon" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\DNDIcon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="AssemblyVersion" xml:space="preserve">
|
||||
<value>1.0.0</value>
|
||||
</data>
|
||||
</root>
|
||||
117
qtcnet-client/Services/UpdateService.cs
Normal file
117
qtcnet-client/Services/UpdateService.cs
Normal file
@ -0,0 +1,117 @@
|
||||
using qtcnet_client.Properties;
|
||||
using qtcnet_client.Model;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Net.Http.Json;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace qtcnet_client.Services
|
||||
{
|
||||
public class UpdateService
|
||||
{
|
||||
public async Task CheckForUpdatesAsync()
|
||||
{
|
||||
if (Debugger.IsAttached) return;
|
||||
|
||||
// get client update info
|
||||
HttpClient client = new()
|
||||
{
|
||||
BaseAddress = new Uri("https://qtcclient.alanmoon.net")
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
ClientUpdateInfo? updateInfo = await client.GetFromJsonAsync<ClientUpdateInfo>("clientinfo.json");
|
||||
if (updateInfo != null)
|
||||
{
|
||||
var serverVersion = Version.Parse(updateInfo.Version);
|
||||
var clientVersion = Version.Parse(Resources.AssemblyVersion);
|
||||
|
||||
int relativeComparison = clientVersion.CompareTo(serverVersion);
|
||||
|
||||
if (relativeComparison > 0) return; // probably a version being developed or tested without a debugger, so don't do anything
|
||||
|
||||
if (relativeComparison < 0)
|
||||
{
|
||||
// inform the user an update is available
|
||||
if (!updateInfo.IsUpdateMandatory)
|
||||
{
|
||||
var result = MessageBox.Show(
|
||||
$"An Update For QtC.NET Is Available. You Can View The Changelog At {updateInfo.DownloadUrl}. Do You Want To Update Now?",
|
||||
"Update Available",
|
||||
MessageBoxButtons.YesNo,
|
||||
MessageBoxIcon.Information);
|
||||
if (result == DialogResult.Yes) await UpdateAsync(updateInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = MessageBox.Show(
|
||||
"Your QtC.NET Client Is Not Up To Date. Using This Version Of The Client With The Current Version Of The Server Could Lead To Data Loss.\n" +
|
||||
$"You Can View The Changelog At {updateInfo.DownloadUrl}. Do You Want To Update Now?",
|
||||
"Update Required",
|
||||
MessageBoxButtons.YesNo,
|
||||
MessageBoxIcon.Error);
|
||||
if (result == DialogResult.Yes) await UpdateAsync(updateInfo);
|
||||
else Environment.Exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
Debug.WriteLine("Client Update HTTP Request Failed - " + ex.Message);
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
Debug.WriteLine("Client Update Info From Server Invalid");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task UpdateAsync(ClientUpdateInfo updateInfo)
|
||||
{
|
||||
HttpClient client = new();
|
||||
client.BaseAddress = new Uri("https://qtcclient.alanmoon.net");
|
||||
|
||||
try
|
||||
{
|
||||
// if bak file already exists, delete it
|
||||
if (File.Exists($"/{updateInfo.ClientFileName}.bak")) File.Delete($"/{updateInfo.ClientFileName}.bak");
|
||||
|
||||
// move old client to backup file
|
||||
File.Move($"./{updateInfo.ClientFileName}", $"{updateInfo.ClientFileName}.bak");
|
||||
|
||||
// download new client version
|
||||
var clientFileStream = await client.GetStreamAsync(updateInfo.ClientFileName);
|
||||
using (var fs = new FileStream($"./{updateInfo.ClientFileName}", FileMode.Create))
|
||||
{
|
||||
clientFileStream.CopyTo(fs);
|
||||
fs.Dispose();
|
||||
}
|
||||
clientFileStream.Dispose();
|
||||
|
||||
// restart the process
|
||||
Process process = new Process();
|
||||
process.StartInfo = new ProcessStartInfo { FileName = $"./{updateInfo.ClientFileName}", WorkingDirectory = Environment.CurrentDirectory };
|
||||
|
||||
process.Start();
|
||||
Environment.Exit(0);
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
MessageBox.Show($"Update Failed. Please Check Your Internet Connection.\n{ex.Message}",
|
||||
"Update Failed",
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Error);
|
||||
}
|
||||
catch (UnauthorizedAccessException ex)
|
||||
{
|
||||
MessageBox.Show($"Update Failed. Permissions In Client Folder Are Wrong.\n{ex.Message}",
|
||||
"Update Failed",
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -8,6 +8,8 @@
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<ApplicationIcon>QtCNETAppIconV2.ico</ApplicationIcon>
|
||||
<AssemblyName>QtCNetClient</AssemblyName>
|
||||
<AssemblyTitle>QtCNET</AssemblyTitle>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user