Rework UI Updating
Fix Update Service Tripping If Version Is Newer On Client Server Now Sends Refresh Command For Rooms
This commit is contained in:
parent
852ec739cb
commit
fb039c6b87
@ -1,7 +1,9 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc.Routing;
|
||||||
using Microsoft.VisualBasic.ApplicationServices;
|
using Microsoft.VisualBasic.ApplicationServices;
|
||||||
using qtc_net_client_2.ClientModel;
|
using qtc_net_client_2.ClientModel;
|
||||||
using qtc_net_client_2.Controls;
|
using qtc_net_client_2.Controls;
|
||||||
using qtc_net_client_2.Forms;
|
using qtc_net_client_2.Forms;
|
||||||
|
using qtc_net_client_2.Properties;
|
||||||
using qtc_net_client_2.Services;
|
using qtc_net_client_2.Services;
|
||||||
using QtCNETAPI.Dtos.User;
|
using QtCNETAPI.Dtos.User;
|
||||||
using QtCNETAPI.Events;
|
using QtCNETAPI.Events;
|
||||||
@ -647,12 +649,6 @@ namespace qtc_net_client_2
|
|||||||
pbUserPfp.Image = _imgFactory.CreateProfileImage(null, null, cosmetic);
|
pbUserPfp.Image = _imgFactory.CreateProfileImage(null, null, cosmetic);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lvUserDirectory.Items.Count <= 0)
|
|
||||||
await RefreshUsers(); // prevent edge case where the refresh event never gets sent to connecting client
|
|
||||||
|
|
||||||
await RefreshContactsList();
|
|
||||||
await RefreshRoomsList();
|
|
||||||
|
|
||||||
// set status context menu checked
|
// set status context menu checked
|
||||||
// TODO - figure out more efficient way to do this
|
// TODO - figure out more efficient way to do this
|
||||||
UserStatus cuStatus = (UserStatus)_apiService.CurrentUser.Status;
|
UserStatus cuStatus = (UserStatus)_apiService.CurrentUser.Status;
|
||||||
@ -733,153 +729,206 @@ namespace qtc_net_client_2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly SemaphoreSlim _roomsRefreshLock = new(1, 1);
|
||||||
private async Task RefreshRoomsList()
|
private async Task RefreshRoomsList()
|
||||||
{
|
{
|
||||||
LoggingService.LogString("Refreshing Rooms List...");
|
LoggingService.LogString("Refreshing Rooms List...");
|
||||||
|
|
||||||
if (IsHandleCreated && !IsDisposed)
|
if (IsHandleCreated && !IsDisposed)
|
||||||
{
|
{
|
||||||
await Invoke(async delegate ()
|
if (!await _roomsRefreshLock.WaitAsync(0))
|
||||||
|
return;
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
flpRooms.Controls.Clear();
|
|
||||||
|
|
||||||
// always add lobby room to rooms list
|
|
||||||
var lobbyCtrl = new RoomEntryControl
|
|
||||||
{
|
|
||||||
RoomName = "Lobby",
|
|
||||||
HideUserCount = true,
|
|
||||||
BackColor = flpRooms.BackColor
|
|
||||||
};
|
|
||||||
|
|
||||||
lobbyCtrl.Margin = new Padding(0, 4, 0, 4);
|
|
||||||
lobbyCtrl.Width = flpRooms.ClientSize.Width - flpRooms.Padding.Horizontal;
|
|
||||||
lobbyCtrl.OnRoomDoubleClicked += OnRoomDoubleClicked;
|
|
||||||
|
|
||||||
flpRooms.Controls.Add(lobbyCtrl);
|
|
||||||
|
|
||||||
var roomsRes = await _apiService.GetAllRoomsAsync();
|
var roomsRes = await _apiService.GetAllRoomsAsync();
|
||||||
if (roomsRes.Success && roomsRes.Data != null)
|
|
||||||
|
if (!roomsRes.Success || roomsRes.Data == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
roomsRes.Data.Add(new Room
|
||||||
{
|
{
|
||||||
foreach (var room in roomsRes.Data)
|
Id = "LOBBY",
|
||||||
{
|
Name = "Lobby"
|
||||||
// create room entry
|
});
|
||||||
var ctrl = new RoomEntryControl
|
|
||||||
{
|
|
||||||
RoomName = room.Name,
|
|
||||||
RoomUserCount = room.UserCount, // placeholder
|
|
||||||
BackColor = flpRooms.BackColor
|
|
||||||
};
|
|
||||||
|
|
||||||
ctrl.Margin = new Padding(0, 4, 0, 4);
|
var uniqueRooms = roomsRes.Data
|
||||||
ctrl.Width = flpRooms.ClientSize.Width - flpRooms.Padding.Horizontal;
|
.GroupBy(r => r.Id)
|
||||||
ctrl.OnRoomDoubleClicked += OnRoomDoubleClicked;
|
.Select(g => g.First())
|
||||||
|
.ToList();
|
||||||
|
|
||||||
flpRooms.Controls.Add(ctrl);
|
if (InvokeRequired)
|
||||||
}
|
{
|
||||||
RoomList = roomsRes.Data;
|
Invoke(() => ApplyRooms(uniqueRooms));
|
||||||
if (System.Diagnostics.Debugger.IsAttached || _config.EnableDebugLogs)
|
|
||||||
LoggingService.LogModel(roomsRes.Data);
|
|
||||||
}
|
}
|
||||||
});
|
else
|
||||||
|
{
|
||||||
|
ApplyRooms(uniqueRooms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_roomsRefreshLock.Release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ApplyRooms(List<Room> newRooms)
|
||||||
|
{
|
||||||
|
RoomList.Clear();
|
||||||
|
RoomList.AddRange(newRooms.DistinctBy(r => r.Id));
|
||||||
|
|
||||||
|
var roomsSnap = RoomList.ToList();
|
||||||
|
|
||||||
|
flpRooms.SuspendLayout();
|
||||||
|
flpRooms.Controls.Clear();
|
||||||
|
|
||||||
|
foreach (var room in roomsSnap)
|
||||||
|
{
|
||||||
|
var ctrl = new RoomEntryControl
|
||||||
|
{
|
||||||
|
RoomName = room.Name,
|
||||||
|
RoomUserCount = room.UserCount,
|
||||||
|
};
|
||||||
|
|
||||||
|
if(room.Id == "LOBBY")
|
||||||
|
ctrl.HideUserCount = true; // TODO - probably make this work with the lobby room (might need backend work)
|
||||||
|
|
||||||
|
ctrl.Margin = new Padding(0, 4, 0, 4);
|
||||||
|
ctrl.Width = flpRooms.ClientSize.Width - flpRooms.Padding.Horizontal;
|
||||||
|
ctrl.OnRoomDoubleClicked += OnRoomDoubleClicked;
|
||||||
|
|
||||||
|
flpRooms.Controls.Add(ctrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
flpRooms.ResumeLayout(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly SemaphoreSlim _contactsRefreshLock = new(1, 1);
|
||||||
private async Task RefreshContactsList()
|
private async Task RefreshContactsList()
|
||||||
{
|
{
|
||||||
LoggingService.LogString("Refreshing Contacts List...");
|
if (!await _contactsRefreshLock.WaitAsync(0))
|
||||||
|
return; // already refreshing, skip
|
||||||
|
|
||||||
if (IsHandleCreated && !IsDisposed)
|
try
|
||||||
{
|
{
|
||||||
await Invoke(async delegate ()
|
var contactsRes = await _apiService.GetCurrentUserContacts();
|
||||||
{
|
if (!contactsRes.Success || contactsRes.Data == null)
|
||||||
Contacts.Clear();
|
return;
|
||||||
flpContacts.Controls.Clear();
|
|
||||||
lblRequestNotif.Visible = false;
|
|
||||||
var contactsRes = await _apiService.GetCurrentUserContacts();
|
|
||||||
if (contactsRes.Success && contactsRes.Data != null)
|
|
||||||
{
|
|
||||||
if (contactsRes.Data.Where(e => e.UserId == _apiService.CurrentUser!.Id && e.UserStatus == Contact.ContactStatus.AwaitingApprovalFromSelf).Count() >= 1)
|
|
||||||
lblRequestNotif.Visible = true;
|
|
||||||
else
|
|
||||||
lblRequestNotif.Visible = false;
|
|
||||||
|
|
||||||
foreach (var contact in contactsRes.Data)
|
var uniqueContacts = contactsRes.Data
|
||||||
{
|
.GroupBy(c => c.UserId)
|
||||||
ServiceResponse<UserInformationDto> user = null!;
|
.Select(g => g.First())
|
||||||
if (contact.OwnerId == _apiService.CurrentUser!.Id)
|
.ToList();
|
||||||
user = await _apiService.GetUserInformationAsync(contact.UserId);
|
|
||||||
else if (contact.UserId == _apiService.CurrentUser!.Id)
|
|
||||||
user = await _apiService.GetUserInformationAsync(contact.OwnerId);
|
|
||||||
|
|
||||||
var ctrl = new ContactEntryControl();
|
if (InvokeRequired)
|
||||||
|
Invoke(() => ApplyContacts(uniqueContacts));
|
||||||
if (user.Data != null)
|
else
|
||||||
{
|
ApplyContacts(uniqueContacts);
|
||||||
Contacts.Add(contact);
|
|
||||||
|
|
||||||
switch(user.Data.Status)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
ctrl.StatusColor = Color.Gray;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
ctrl.StatusColor = Color.LightGreen;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
ctrl.StatusColor = Color.Gold;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
ctrl.StatusColor = Color.Red;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (contact.OwnerId == _apiService.CurrentUser!.Id)
|
|
||||||
{
|
|
||||||
switch (contact.OwnerStatus)
|
|
||||||
{
|
|
||||||
case Contact.ContactStatus.AwaitingApprovalFromOther:
|
|
||||||
ctrl.Username = $"{user.Data.Username} [Request Sent]";
|
|
||||||
await AddProfilePicToList(user.Data.Id);
|
|
||||||
ctrl.Avatar = ilProfilePics.Images[user.Data.Id] ?? ilProfilePics.Images[0];
|
|
||||||
break;
|
|
||||||
case Contact.ContactStatus.Accepted:
|
|
||||||
ctrl.Username = user.Data.Username;
|
|
||||||
await AddProfilePicToList(user.Data.Id);
|
|
||||||
ctrl.Avatar = ilProfilePics.Images[user.Data.Id] ?? ilProfilePics.Images[0];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (contact.UserId == _apiService.CurrentUser!.Id)
|
|
||||||
{
|
|
||||||
switch (contact.UserStatus)
|
|
||||||
{
|
|
||||||
case Contact.ContactStatus.AwaitingApprovalFromSelf:
|
|
||||||
ctrl.Username = $"{user.Data.Username} [Contact Request]";
|
|
||||||
await AddProfilePicToList(user.Data.Id);
|
|
||||||
ctrl.Avatar = ilProfilePics.Images[user.Data.Id] ?? ilProfilePics.Images[0];
|
|
||||||
AudioService.PlaySoundEffect("sndContactRequest");
|
|
||||||
break;
|
|
||||||
case Contact.ContactStatus.Accepted:
|
|
||||||
ctrl.Username = user.Data.Username;
|
|
||||||
await AddProfilePicToList(user.Data.Id);
|
|
||||||
ctrl.Avatar = ilProfilePics.Images[user.Data.Id] ?? ilProfilePics.Images[0];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add the control to the flow panel
|
|
||||||
ctrl.Margin = new Padding(0, 4, 0, 4);
|
|
||||||
ctrl.Width = flpContacts.ClientSize.Width - flpContacts.Padding.Horizontal;
|
|
||||||
ctrl.ContactDoubleClicked += Ctrl_ContactDoubleClicked;
|
|
||||||
flpContacts.Controls.Add(ctrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (System.Diagnostics.Debugger.IsAttached || _config.EnableDebugLogs)
|
|
||||||
LoggingService.LogModel(contactsRes.Data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_contactsRefreshLock.Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void ApplyContacts(List<Contact> newContacts)
|
||||||
|
{
|
||||||
|
lblRequestNotif.Visible =
|
||||||
|
newContacts.Any(e =>
|
||||||
|
e.UserId == _apiService.CurrentUser!.Id &&
|
||||||
|
e.UserStatus == Contact.ContactStatus.AwaitingApprovalFromSelf);
|
||||||
|
|
||||||
|
Contacts.Clear();
|
||||||
|
Contacts.AddRange(newContacts.DistinctBy(c => c.UserId));
|
||||||
|
|
||||||
|
// Snapshot to avoid concurrent modification
|
||||||
|
var contactsSnapshot = Contacts.ToList();
|
||||||
|
|
||||||
|
flpContacts.SuspendLayout();
|
||||||
|
flpContacts.Controls.Clear();
|
||||||
|
|
||||||
|
foreach (var contact in contactsSnapshot)
|
||||||
|
{
|
||||||
|
var ctrl = await BuildContactControl(contact);
|
||||||
|
if (ctrl != null)
|
||||||
|
flpContacts.Controls.Add(ctrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
flpContacts.ResumeLayout(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<ContactEntryControl?> BuildContactControl(Contact contact)
|
||||||
|
{
|
||||||
|
ServiceResponse<UserInformationDto> user = null!;
|
||||||
|
if (contact.OwnerId == _apiService.CurrentUser!.Id)
|
||||||
|
user = await _apiService.GetUserInformationAsync(contact.UserId);
|
||||||
|
else if (contact.UserId == _apiService.CurrentUser!.Id)
|
||||||
|
user = await _apiService.GetUserInformationAsync(contact.OwnerId);
|
||||||
|
|
||||||
|
var ctrl = new ContactEntryControl();
|
||||||
|
|
||||||
|
if (user.Data != null)
|
||||||
|
{
|
||||||
|
switch (user.Data.Status)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
ctrl.StatusColor = Color.Gray;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
ctrl.StatusColor = Color.LightGreen;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
ctrl.StatusColor = Color.Gold;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
ctrl.StatusColor = Color.Red;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contact.OwnerId == _apiService.CurrentUser!.Id)
|
||||||
|
{
|
||||||
|
switch (contact.OwnerStatus)
|
||||||
|
{
|
||||||
|
case Contact.ContactStatus.AwaitingApprovalFromOther:
|
||||||
|
ctrl.Username = $"{user.Data.Username} [Request Sent]";
|
||||||
|
await AddProfilePicToList(user.Data.Id);
|
||||||
|
ctrl.Avatar = ilProfilePics.Images[user.Data.Id] ?? ilProfilePics.Images[0];
|
||||||
|
break;
|
||||||
|
case Contact.ContactStatus.Accepted:
|
||||||
|
ctrl.Username = user.Data.Username;
|
||||||
|
await AddProfilePicToList(user.Data.Id);
|
||||||
|
ctrl.Avatar = ilProfilePics.Images[user.Data.Id] ?? ilProfilePics.Images[0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (contact.UserId == _apiService.CurrentUser!.Id)
|
||||||
|
{
|
||||||
|
switch (contact.UserStatus)
|
||||||
|
{
|
||||||
|
case Contact.ContactStatus.AwaitingApprovalFromSelf:
|
||||||
|
ctrl.Username = $"{user.Data.Username} [Contact Request]";
|
||||||
|
await AddProfilePicToList(user.Data.Id);
|
||||||
|
ctrl.Avatar = ilProfilePics.Images[user.Data.Id] ?? ilProfilePics.Images[0];
|
||||||
|
AudioService.PlaySoundEffect("sndContactRequest");
|
||||||
|
break;
|
||||||
|
case Contact.ContactStatus.Accepted:
|
||||||
|
ctrl.Username = user.Data.Username;
|
||||||
|
await AddProfilePicToList(user.Data.Id);
|
||||||
|
ctrl.Avatar = ilProfilePics.Images[user.Data.Id] ?? ilProfilePics.Images[0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the control to the flow panel
|
||||||
|
ctrl.Margin = new Padding(0, 4, 0, 4);
|
||||||
|
ctrl.Width = flpContacts.ClientSize.Width - flpContacts.Padding.Horizontal;
|
||||||
|
ctrl.ContactDoubleClicked += Ctrl_ContactDoubleClicked;
|
||||||
|
|
||||||
|
// return the control
|
||||||
|
return ctrl;
|
||||||
|
}
|
||||||
|
else return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void Ctrl_ContactDoubleClicked(object? sender, EventArgs e)
|
private async void Ctrl_ContactDoubleClicked(object? sender, EventArgs e)
|
||||||
|
|||||||
@ -81,7 +81,7 @@ namespace qtc_net_client_2.Properties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to 6.5.5.
|
/// Looks up a localized string similar to 6.5.6.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string AssemblyVersion {
|
internal static string AssemblyVersion {
|
||||||
get {
|
get {
|
||||||
|
|||||||
@ -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.5.5</value>
|
<value>6.5.6</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>
|
||||||
|
|||||||
@ -19,15 +19,24 @@ namespace qtc_net_client_2.Services
|
|||||||
if (Debugger.IsAttached) return;
|
if (Debugger.IsAttached) return;
|
||||||
|
|
||||||
// get client update info
|
// get client update info
|
||||||
HttpClient client = new();
|
HttpClient client = new()
|
||||||
client.BaseAddress = new Uri("https://qtcclient.alanmoon.net");
|
{
|
||||||
|
BaseAddress = new Uri("https://qtcclient.alanmoon.net")
|
||||||
|
};
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ClientUpdateInfo? updateInfo = await client.GetFromJsonAsync<ClientUpdateInfo>("clientinfo.json");
|
ClientUpdateInfo? updateInfo = await client.GetFromJsonAsync<ClientUpdateInfo>("clientinfo.json");
|
||||||
if (updateInfo != null)
|
if (updateInfo != null)
|
||||||
{
|
{
|
||||||
if (updateInfo.Version != Resources.AssemblyVersion)
|
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
|
// inform the user an update is available
|
||||||
if (!updateInfo.IsUpdateMandatory)
|
if (!updateInfo.IsUpdateMandatory)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user