Compare commits
44 Commits
Author | SHA1 | Date | |
---|---|---|---|
a95d012d69 | |||
d1d3af2ec9 | |||
4e61a1d7b9 | |||
446745d4df | |||
00df7505a7 | |||
b17d391406 | |||
2092d2c6d3 | |||
fd743dcb42 | |||
9214460927 | |||
1b30636937 | |||
72d9b99c4c | |||
c7137e4c7e | |||
4ee524778d | |||
cfcc5ad4c1 | |||
b81b059177 | |||
5d553cdf58 | |||
8cb59e1b21 | |||
6acb72975e | |||
098a59f555 | |||
e6c842cb19 | |||
758a5a96dc | |||
6bf77aa12e | |||
f98e5a490c | |||
75b61c0a8c | |||
0432fec3cd | |||
de2a81d485 | |||
fca34d5479 | |||
932ee5fe62 | |||
34f478213e | |||
ffa44ff036 | |||
217e3f301a | |||
28358f44f8 | |||
eb9fd6c8cf | |||
a325a622a5 | |||
0c76a206f7 | |||
502dda6436 | |||
868f6fa067 | |||
003d01fe4e | |||
0d93557959 | |||
9fecd1fb74 | |||
074b68c698 | |||
922528c61c | |||
846a477587 | |||
ad5345512a |
@ -11,5 +11,6 @@
|
||||
public DateTime CreatedAt { get; set; } = new DateTime();
|
||||
public int Status { get; set; } = 0;
|
||||
public int CurrencyAmount { get; set; } = 0;
|
||||
public int ProfileCosmeticId { get; set; } = 0;
|
||||
}
|
||||
}
|
||||
|
14
QtCNETAPI/Dtos/User/UserPasswordResetDto.cs
Normal file
14
QtCNETAPI/Dtos/User/UserPasswordResetDto.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace QtCNETAPI.Dtos.User
|
||||
{
|
||||
public class UserPasswordResetDto
|
||||
{
|
||||
public string Token { get; set; } = string.Empty;
|
||||
public string Password { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
@ -6,5 +6,6 @@
|
||||
public string Username { get; set; } = string.Empty;
|
||||
public string Bio { get; set; } = string.Empty;
|
||||
public DateTime DateOfBirth { get; set; } = new DateTime();
|
||||
public int ProfileCosmeticId { get; set; } = 0;
|
||||
}
|
||||
}
|
||||
|
8
QtCNETAPI/Enums/StoreItemType.cs
Normal file
8
QtCNETAPI/Enums/StoreItemType.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace QtCNETAPI.Enums
|
||||
{
|
||||
public enum StoreItemType
|
||||
{
|
||||
ProfileCosmetic = 1,
|
||||
ClientCosmetic = 2
|
||||
}
|
||||
}
|
13
QtCNETAPI/Events/GuestUserJoinEventArgs.cs
Normal file
13
QtCNETAPI/Events/GuestUserJoinEventArgs.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace QtCNETAPI.Events
|
||||
{
|
||||
public class GuestUserJoinEventArgs : EventArgs
|
||||
{
|
||||
public required string Username { get; set; }
|
||||
}
|
||||
}
|
14
QtCNETAPI/Models/OwnedStoreItem.cs
Normal file
14
QtCNETAPI/Models/OwnedStoreItem.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace QtCNETAPI.Models
|
||||
{
|
||||
public class OwnedStoreItem
|
||||
{
|
||||
[Key]
|
||||
public int Id { get; set; }
|
||||
public string UserId { get; set; } = string.Empty;
|
||||
public int StoreItemId { get; set; }
|
||||
|
||||
public virtual User? User { get; }
|
||||
}
|
||||
}
|
@ -15,9 +15,11 @@
|
||||
public int CurrencyAmount { get; set; } = 0;
|
||||
public int StockAmount { get; set; } = 0;
|
||||
public DateTime LastCurrencySpin { get; set; }
|
||||
public int ActiveProfileCosmetic { get; set; } = 0;
|
||||
|
||||
public virtual IEnumerable<RefreshToken>? RefreshTokens { get; }
|
||||
public virtual IEnumerable<Contact>? ContactsMade { get; }
|
||||
public virtual IEnumerable<Contact>? ContactsList { get; }
|
||||
public virtual IEnumerable<OwnedStoreItem>? OwnedStoreItems { get; }
|
||||
}
|
||||
}
|
||||
|
@ -7,10 +7,11 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<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.SignalR.Client" Version="9.0.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.9" />
|
||||
<PackageReference Include="RestSharp" Version="112.1.0" />
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.10.0" />
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.14.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
23
QtCNETAPI/Schema/StoreItem.cs
Normal file
23
QtCNETAPI/Schema/StoreItem.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using QtCNETAPI.Enums;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace QtCNETAPI.Schema
|
||||
{
|
||||
public class StoreItem
|
||||
{
|
||||
[JsonPropertyName("Id")]
|
||||
public int Id { get; set; }
|
||||
[JsonPropertyName("Type")]
|
||||
public StoreItemType Type { get; set; }
|
||||
[JsonPropertyName("Price")]
|
||||
public int Price { get; set; }
|
||||
[JsonPropertyName("Name")]
|
||||
public string Name { get; set; } = string.Empty;
|
||||
[JsonPropertyName("Description")]
|
||||
public string Description { get; set; } = string.Empty;
|
||||
[JsonPropertyName("AssetUrl")]
|
||||
public string AssetUrl { get; set; } = string.Empty;
|
||||
[JsonPropertyName("ThumbnailUrl")]
|
||||
public string ThumbnailUrl { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
@ -2,9 +2,9 @@
|
||||
using QtCNETAPI.Dtos.User;
|
||||
using QtCNETAPI.Enums;
|
||||
using QtCNETAPI.Models;
|
||||
using QtCNETAPI.Schema;
|
||||
using RestSharp;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Resources;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace QtCNETAPI.Services.ApiService
|
||||
@ -13,10 +13,15 @@ namespace QtCNETAPI.Services.ApiService
|
||||
{
|
||||
private User? user;
|
||||
private RestClient _client;
|
||||
private LoggingService _loggingService;
|
||||
|
||||
private CredentialService _credService = new();
|
||||
|
||||
internal string? sessionToken;
|
||||
internal string apiUri;
|
||||
|
||||
public event EventHandler? OnCurrentUserUpdate;
|
||||
|
||||
public string? SessionToken
|
||||
{
|
||||
get { return sessionToken; }
|
||||
@ -28,9 +33,10 @@ namespace QtCNETAPI.Services.ApiService
|
||||
get { return user; }
|
||||
}
|
||||
|
||||
public ApiService(string apiUrl)
|
||||
public ApiService(string apiUrl, LoggingService loggingService)
|
||||
{
|
||||
apiUri = apiUrl;
|
||||
_loggingService = loggingService;
|
||||
_client = new RestClient(apiUri);
|
||||
}
|
||||
|
||||
@ -151,10 +157,9 @@ namespace QtCNETAPI.Services.ApiService
|
||||
serviceResponse.Success = true;
|
||||
serviceResponse.Data = response.Data;
|
||||
|
||||
// update currentuser model
|
||||
CurrentUser!.Username = response.Data!.Username;
|
||||
CurrentUser.Bio = response.Data.Bio;
|
||||
CurrentUser.DateOfBirth = response.Data.DateOfBirth;
|
||||
// anything that changes the user should tell the api service to set it again
|
||||
await SetCurrentUser();
|
||||
OnCurrentUserUpdate?.Invoke(this, EventArgs.Empty);
|
||||
} else
|
||||
{
|
||||
serviceResponse.Success = false;
|
||||
@ -180,6 +185,10 @@ namespace QtCNETAPI.Services.ApiService
|
||||
{
|
||||
serviceResponse.Success = true;
|
||||
serviceResponse.Data = response.Data;
|
||||
|
||||
// anything that changes the user should tell the api service to set it again
|
||||
await SetCurrentUser();
|
||||
OnCurrentUserUpdate?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -228,9 +237,9 @@ namespace QtCNETAPI.Services.ApiService
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ServiceResponse<User>> LoginAsync(UserLoginDto userLoginDto)
|
||||
public async Task<ServiceResponse<string>> LoginAsync(UserLoginDto userLoginDto)
|
||||
{
|
||||
var serviceResponse = new ServiceResponse<User>();
|
||||
var serviceResponse = new ServiceResponse<string>();
|
||||
|
||||
try
|
||||
{
|
||||
@ -250,13 +259,11 @@ namespace QtCNETAPI.Services.ApiService
|
||||
{
|
||||
SessionToken = response.Data!;
|
||||
|
||||
await File.WriteAllTextAsync("./session.token", response.Message);
|
||||
|
||||
var user = await SetCurrentUser();
|
||||
|
||||
serviceResponse.Success = true;
|
||||
if (response.Message != null) serviceResponse.Message = response.Message;
|
||||
serviceResponse.Data = user;
|
||||
serviceResponse.Data = response.Message;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -273,16 +280,85 @@ namespace QtCNETAPI.Services.ApiService
|
||||
return serviceResponse;
|
||||
}
|
||||
|
||||
private async Task<User> SetCurrentUser()
|
||||
public async Task<ServiceResponse<bool>> ResendVerificationEmail(string email)
|
||||
{
|
||||
var serviceResponse = new ServiceResponse<bool>();
|
||||
|
||||
var restRequest = new RestRequest($"auth/resend-verification-email")
|
||||
.AddQueryParameter("email", email);
|
||||
var response = await _client.PostAsync<ServiceResponse<bool>>(restRequest);
|
||||
|
||||
if (response != null)
|
||||
{
|
||||
serviceResponse.Success = true;
|
||||
serviceResponse.Data = response.Data;
|
||||
}
|
||||
else
|
||||
{
|
||||
serviceResponse.Success = false;
|
||||
serviceResponse.Message = "API never responded.";
|
||||
}
|
||||
|
||||
return serviceResponse;
|
||||
}
|
||||
|
||||
public async Task<ServiceResponse<bool>> SendPasswordResetEmail(string email)
|
||||
{
|
||||
var serviceResponse = new ServiceResponse<bool>();
|
||||
|
||||
var restRequest = new RestRequest($"auth/request-password-reset")
|
||||
.AddQueryParameter("email", email);
|
||||
var response = await _client.PostAsync<ServiceResponse<bool>>(restRequest);
|
||||
|
||||
if (response != null)
|
||||
{
|
||||
serviceResponse.Success = true;
|
||||
serviceResponse.Data = response.Data;
|
||||
}
|
||||
else
|
||||
{
|
||||
serviceResponse.Success = false;
|
||||
serviceResponse.Message = "API never responded.";
|
||||
}
|
||||
|
||||
return serviceResponse;
|
||||
}
|
||||
|
||||
public async Task<ServiceResponse<bool>> ResetPassword(UserPasswordResetDto request)
|
||||
{
|
||||
var serviceResponse = new ServiceResponse<bool>();
|
||||
|
||||
var restRequest = new RestRequest($"auth/reset-password")
|
||||
.AddJsonBody(request);
|
||||
var response = await _client.PostAsync<ServiceResponse<bool>>(restRequest);
|
||||
|
||||
if (response != null)
|
||||
{
|
||||
serviceResponse.Success = true;
|
||||
serviceResponse.Data = response.Data;
|
||||
}
|
||||
else
|
||||
{
|
||||
serviceResponse.Success = false;
|
||||
serviceResponse.Message = "API never responded.";
|
||||
}
|
||||
|
||||
return serviceResponse;
|
||||
}
|
||||
|
||||
public async Task<User> SetCurrentUser()
|
||||
{
|
||||
var userRequest = new RestRequest("users/user-authorized")
|
||||
.AddHeader("Authorization", $"Bearer {SessionToken}");
|
||||
var userResponse = await _client.GetAsync<ServiceResponse<User>>(userRequest);
|
||||
|
||||
if (userResponse != null || userResponse!.Data != null)
|
||||
if (userResponse != null && userResponse.Success && userResponse.Data != null)
|
||||
{
|
||||
user = userResponse.Data;
|
||||
return userResponse.Data!;
|
||||
|
||||
_loggingService.LogString($"Current User's Status Is {userResponse.Data.Status}");
|
||||
|
||||
return userResponse.Data;
|
||||
} else
|
||||
{
|
||||
throw new NullReferenceException("Current User could not be set.");
|
||||
@ -337,21 +413,23 @@ namespace QtCNETAPI.Services.ApiService
|
||||
public async Task<ServiceResponse<string>> RefreshSessionIfInvalid()
|
||||
{
|
||||
var tokenHandler = new JwtSecurityTokenHandler();
|
||||
var refToken = await File.ReadAllTextAsync("./session.token");
|
||||
var refToken = _credService.GetAccessToken(); // fuck CA1416, if this is being ran on linux it should just crash (theoretically)
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
if (result == null || result.Success == false)
|
||||
{
|
||||
File.Delete("./session.token");
|
||||
|
||||
return new ServiceResponse<string> { Success = false, Message = "Session Expired." };
|
||||
return new ServiceResponse<string> { Success = false, Message = "Session Expired." }; // logging in again should overwrite old token
|
||||
} else return new ServiceResponse<string> { Success = true, Data = refToken };
|
||||
} else return new ServiceResponse<string> { Success = true, Data = refToken };
|
||||
}
|
||||
@ -590,6 +668,10 @@ namespace QtCNETAPI.Services.ApiService
|
||||
{
|
||||
serviceResponse.Success = true;
|
||||
serviceResponse.Data = response.Data;
|
||||
|
||||
// anything that changes the user should tell the api service to set it again
|
||||
await SetCurrentUser();
|
||||
OnCurrentUserUpdate?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
return serviceResponse;
|
||||
@ -637,6 +719,10 @@ namespace QtCNETAPI.Services.ApiService
|
||||
{
|
||||
serviceResponse.Success = true;
|
||||
serviceResponse.Data = response.Data;
|
||||
|
||||
// anything that changes the user should tell the api service to set it again
|
||||
await SetCurrentUser();
|
||||
OnCurrentUserUpdate?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
return serviceResponse;
|
||||
@ -661,6 +747,10 @@ namespace QtCNETAPI.Services.ApiService
|
||||
{
|
||||
serviceResponse.Success = true;
|
||||
serviceResponse.Data = response.Data;
|
||||
|
||||
// anything that changes the user should tell the api service to set it again
|
||||
await SetCurrentUser();
|
||||
OnCurrentUserUpdate?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
return serviceResponse;
|
||||
@ -713,5 +803,151 @@ namespace QtCNETAPI.Services.ApiService
|
||||
|
||||
return serviceResponse;
|
||||
}
|
||||
|
||||
public async Task<ServiceResponse<List<StoreItem>>> GetStoreItems()
|
||||
{
|
||||
await RefreshSessionIfInvalid();
|
||||
|
||||
var serviceResponse = new ServiceResponse<List<StoreItem>>();
|
||||
|
||||
if (SessionToken == null) throw new NullReferenceException("Function Was Called Before A Session Was Made.");
|
||||
|
||||
var restRequest = new RestRequest("store/all-items")
|
||||
.AddHeader("Authorization", $"Bearer {SessionToken}");
|
||||
var response = await _client.GetAsync<ServiceResponse<List<StoreItem>>>(restRequest);
|
||||
|
||||
if (response == null) { serviceResponse.Success = false; serviceResponse.Message = "API did not respond."; return serviceResponse; }
|
||||
|
||||
if (response.Success)
|
||||
{
|
||||
serviceResponse.Success = true;
|
||||
serviceResponse.Data = response.Data;
|
||||
}
|
||||
|
||||
return serviceResponse;
|
||||
}
|
||||
|
||||
public async Task<ServiceResponse<StoreItem>> GetStoreItem(int id)
|
||||
{
|
||||
await RefreshSessionIfInvalid();
|
||||
|
||||
var serviceResponse = new ServiceResponse<StoreItem>();
|
||||
|
||||
if (SessionToken == null) throw new NullReferenceException("Function Was Called Before A Session Was Made.");
|
||||
|
||||
var restRequest = new RestRequest("store/item")
|
||||
.AddHeader("Authorization", $"Bearer {SessionToken}")
|
||||
.AddQueryParameter("id", id);
|
||||
var response = await _client.GetAsync<ServiceResponse<StoreItem>>(restRequest);
|
||||
|
||||
if (response == null) { serviceResponse.Success = false; serviceResponse.Message = "API did not respond."; return serviceResponse; }
|
||||
|
||||
if (response.Success)
|
||||
{
|
||||
serviceResponse.Success = true;
|
||||
serviceResponse.Data = response.Data;
|
||||
}
|
||||
|
||||
return serviceResponse;
|
||||
}
|
||||
|
||||
public async Task<ServiceResponse<bool>> BuyStoreItem(int id)
|
||||
{
|
||||
await RefreshSessionIfInvalid();
|
||||
|
||||
var serviceResponse = new ServiceResponse<bool>();
|
||||
|
||||
if (SessionToken == null) throw new NullReferenceException("Function Was Called Before A Session Was Made.");
|
||||
|
||||
var restRequest = new RestRequest("store/buy-item")
|
||||
.AddHeader("Authorization", $"Bearer {SessionToken}")
|
||||
.AddQueryParameter("id", id);
|
||||
var response = await _client.PostAsync<ServiceResponse<bool>>(restRequest);
|
||||
|
||||
if (response == null) { serviceResponse.Success = false; serviceResponse.Message = "API did not respond."; return serviceResponse; }
|
||||
|
||||
if (response.Success)
|
||||
{
|
||||
serviceResponse.Success = true;
|
||||
serviceResponse.Data = response.Data;
|
||||
|
||||
// anything that changes the user should tell the api service to set it again
|
||||
await SetCurrentUser();
|
||||
OnCurrentUserUpdate?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
return serviceResponse;
|
||||
}
|
||||
|
||||
public async Task<ServiceResponse<List<OwnedStoreItem>>> GetOwnedStoreItems()
|
||||
{
|
||||
await RefreshSessionIfInvalid();
|
||||
|
||||
var serviceResponse = new ServiceResponse<List<OwnedStoreItem>>();
|
||||
|
||||
if (SessionToken == null) throw new NullReferenceException("Function Was Called Before A Session Was Made.");
|
||||
|
||||
var restRequest = new RestRequest("store/bought-items")
|
||||
.AddHeader("Authorization", $"Bearer {SessionToken}");
|
||||
var response = await _client.GetAsync<ServiceResponse<List<OwnedStoreItem>>>(restRequest);
|
||||
|
||||
if (response == null) { serviceResponse.Success = false; serviceResponse.Message = "API did not respond."; return serviceResponse; }
|
||||
|
||||
if (response.Success)
|
||||
{
|
||||
serviceResponse.Success = true;
|
||||
serviceResponse.Data = response.Data;
|
||||
}
|
||||
|
||||
return serviceResponse;
|
||||
}
|
||||
|
||||
public async Task<ServiceResponse<OwnedStoreItem>> GetOwnedStoreItem(int id)
|
||||
{
|
||||
await RefreshSessionIfInvalid();
|
||||
|
||||
var serviceResponse = new ServiceResponse<OwnedStoreItem>();
|
||||
|
||||
if (SessionToken == null) throw new NullReferenceException("Function Was Called Before A Session Was Made.");
|
||||
|
||||
var restRequest = new RestRequest("store/bought-item")
|
||||
.AddHeader("Authorization", $"Bearer {SessionToken}")
|
||||
.AddQueryParameter("id", id);
|
||||
var response = await _client.GetAsync<ServiceResponse<OwnedStoreItem>>(restRequest);
|
||||
|
||||
if (response == null) { serviceResponse.Success = false; serviceResponse.Message = "API did not respond."; return serviceResponse; }
|
||||
|
||||
if (response.Success)
|
||||
{
|
||||
serviceResponse.Success = true;
|
||||
serviceResponse.Data = response.Data;
|
||||
}
|
||||
|
||||
return serviceResponse;
|
||||
}
|
||||
|
||||
public async Task<ServiceResponse<User>> DeleteUserById(string id)
|
||||
{
|
||||
await RefreshSessionIfInvalid();
|
||||
|
||||
var serviceResponse = new ServiceResponse<User>();
|
||||
|
||||
if (SessionToken == null) throw new NullReferenceException("Function Was Called Before A Session Was Made.");
|
||||
|
||||
var restRequest = new RestRequest("users/delete-user")
|
||||
.AddHeader("Authorization", $"Bearer {SessionToken}")
|
||||
.AddQueryParameter("id", id);
|
||||
var response = await _client.DeleteAsync<ServiceResponse<User>>(restRequest);
|
||||
|
||||
if (response == null) { serviceResponse.Success = false; serviceResponse.Message = "API did not respond."; return serviceResponse; }
|
||||
|
||||
if (response.Success)
|
||||
{
|
||||
serviceResponse.Success = true;
|
||||
serviceResponse.Data = response.Data;
|
||||
}
|
||||
|
||||
return serviceResponse;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using QtCNETAPI.Enums;
|
||||
using QtCNETAPI.Schema;
|
||||
|
||||
namespace QtCNETAPI.Services.ApiService
|
||||
{
|
||||
@ -16,12 +17,19 @@ namespace QtCNETAPI.Services.ApiService
|
||||
public string? SessionToken { get; set; }
|
||||
public User CurrentUser { get; }
|
||||
|
||||
public event EventHandler? OnCurrentUserUpdate;
|
||||
|
||||
public Task<ServiceResponse<string>> PingServerAsync();
|
||||
public Task<ServiceResponse<List<UserInformationDto>>> GetOnlineUsersAsync();
|
||||
public Task<ServiceResponse<List<UserInformationDto>>> GetAllUsersAsync();
|
||||
public Task<ServiceResponse<User>> LoginAsync(UserLoginDto userLoginDto);
|
||||
public Task<ServiceResponse<User>> DeleteUserById(string id);
|
||||
public Task<ServiceResponse<string>> LoginAsync(UserLoginDto userLoginDto);
|
||||
public Task<ServiceResponse<bool>> ResendVerificationEmail(string email);
|
||||
public Task<ServiceResponse<bool>> SendPasswordResetEmail(string email);
|
||||
public Task<ServiceResponse<bool>> ResetPassword(UserPasswordResetDto request);
|
||||
public Task<ServiceResponse<User>> RefreshLogin(string refreshToken);
|
||||
public Task<ServiceResponse<string>> RefreshSessionIfInvalid();
|
||||
public Task<User> SetCurrentUser();
|
||||
public Task<ServiceResponse<User>> RegisterAsync(UserDto userDto);
|
||||
public Task<ServiceResponse<UserInformationDto>> GetUserInformationAsync(string id);
|
||||
public Task<ServiceResponse<UserInformationDto>> UpdateUserInformationAsync(UserUpdateInformationDto request);
|
||||
@ -40,5 +48,10 @@ namespace QtCNETAPI.Services.ApiService
|
||||
public Task<ServiceResponse<UserStockActionResultDto>> SellStock(int amount);
|
||||
public Task<ServiceResponse<int>> GetRandomNumber();
|
||||
public Task<ServiceResponse<NumberGuessResult>> GuessRandomNumber(int original, int guess);
|
||||
public Task<ServiceResponse<List<StoreItem>>> GetStoreItems();
|
||||
public Task<ServiceResponse<StoreItem>> GetStoreItem(int id);
|
||||
public Task<ServiceResponse<bool>> BuyStoreItem(int id);
|
||||
public Task<ServiceResponse<List<OwnedStoreItem>>> GetOwnedStoreItems();
|
||||
public Task<ServiceResponse<OwnedStoreItem>> GetOwnedStoreItem(int id);
|
||||
}
|
||||
}
|
||||
|
26
QtCNETAPI/Services/CredentialService.cs
Normal file
26
QtCNETAPI/Services/CredentialService.cs
Normal file
@ -0,0 +1,26 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
using Microsoft.AspNetCore.SignalR.Client;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using QtCNETAPI.Dtos.User;
|
||||
using QtCNETAPI.Events;
|
||||
using QtCNETAPI.Models;
|
||||
@ -6,47 +7,55 @@ using QtCNETAPI.Services.ApiService;
|
||||
|
||||
namespace QtCNETAPI.Services.GatewayService
|
||||
{
|
||||
public class GatewayService : IGatewayService, IAsyncDisposable
|
||||
public class GatewayService(string GWUrl, IApiService apiService, LoggingService loggingService) : IGatewayService, IAsyncDisposable
|
||||
{
|
||||
internal string gwBaseUri = "127.0.0.1";
|
||||
internal string gwBaseUri = GWUrl;
|
||||
|
||||
public Room? CurrentRoom { get; private set; }
|
||||
public bool InLobby { get; private set; }
|
||||
public HubConnection? HubConnection { get; private set; }
|
||||
|
||||
|
||||
public event EventHandler OnRoomMessageReceived;
|
||||
public event EventHandler OnRoomUserListReceived;
|
||||
public event EventHandler OnRefreshUserListsReceived;
|
||||
public event EventHandler OnRefreshRoomListReceived;
|
||||
public event EventHandler OnRefreshContactsListReceived;
|
||||
public event EventHandler OnClientFunctionReceived;
|
||||
public event EventHandler OnDirectMessageReceived;
|
||||
public event EventHandler OnServerConfigReceived;
|
||||
public event EventHandler OnServerDisconnect;
|
||||
public event EventHandler OnServerReconnecting;
|
||||
public event EventHandler OnServerReconnected;
|
||||
public event EventHandler? OnRoomMessageReceived;
|
||||
public event EventHandler? OnRoomUserListReceived;
|
||||
public event EventHandler? OnGuestUserJoin;
|
||||
public event EventHandler? OnRefreshUserListsReceived;
|
||||
public event EventHandler? OnRefreshRoomListReceived;
|
||||
public event EventHandler? OnRoomDeleted;
|
||||
public event EventHandler? OnRefreshContactsListReceived;
|
||||
public event EventHandler? OnClientFunctionReceived;
|
||||
public event EventHandler? OnDirectMessageReceived;
|
||||
public event EventHandler? OnServerConfigReceived;
|
||||
public event EventHandler? OnServerDisconnect;
|
||||
public event EventHandler? OnServerReconnecting;
|
||||
public event EventHandler? OnServerReconnected;
|
||||
public event EventHandler? OnUserForceLogout;
|
||||
|
||||
private IApiService _apiService;
|
||||
|
||||
public GatewayService(string GWUrl, IApiService apiService)
|
||||
{
|
||||
gwBaseUri = GWUrl;
|
||||
_apiService = apiService;
|
||||
}
|
||||
private IApiService _apiService = apiService;
|
||||
private LoggingService _loggingService = loggingService;
|
||||
|
||||
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
|
||||
var gwConBuilder = new HubConnectionBuilder()
|
||||
.WithAutomaticReconnect()
|
||||
.ConfigureLogging((builder) =>
|
||||
{
|
||||
builder.AddProvider(new LoggingServiceProvider(_loggingService));
|
||||
|
||||
if (System.Diagnostics.Debugger.IsAttached) builder.SetMinimumLevel(LogLevel.Debug);
|
||||
else builder.SetMinimumLevel(LogLevel.Error);
|
||||
})
|
||||
.WithUrl(gwBaseUri, options =>
|
||||
{
|
||||
options.AccessTokenProvider = () => Task.FromResult(_apiService.SessionToken);
|
||||
});
|
||||
options.AccessTokenProvider = async () =>
|
||||
{
|
||||
// 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();
|
||||
|
||||
// register events
|
||||
@ -58,14 +67,28 @@ namespace QtCNETAPI.Services.GatewayService
|
||||
HubConnection.On("RefreshContactsList", () => OnRefreshContactsListReceived?.Invoke(this, EventArgs.Empty));
|
||||
HubConnection.On<ServerConfig>("ReceiveServerConfig", (serverConfig) => OnServerConfigReceived?.Invoke(this, new ServerConfigEventArgs { ServerConfig = serverConfig }));
|
||||
HubConnection.On<List<User>>("RoomUserList", (userList) => OnRoomUserListReceived?.Invoke(this, new RoomListEventArgs { UserList = userList }));
|
||||
HubConnection.On<string>("GuestJoin", (username) => OnGuestUserJoin?.Invoke(this, new GuestUserJoinEventArgs { Username = username }));
|
||||
HubConnection.On("RoomDeleted", () => OnRoomDeleted?.Invoke(this, EventArgs.Empty));
|
||||
HubConnection.On("ForceSignOut", () => OnUserForceLogout?.Invoke(this, EventArgs.Empty));
|
||||
|
||||
HubConnection.Closed += HubConnection_Closed;
|
||||
HubConnection.Reconnecting += HubConnection_Reconnecting;
|
||||
HubConnection.Reconnected += HubConnection_Reconnected;
|
||||
|
||||
// start connection
|
||||
try
|
||||
{
|
||||
await HubConnection.StartAsync();
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
_loggingService.LogString($"Unable To Connect To SignalR.\n{ex.Message}\n{ex.StackTrace}");
|
||||
return;
|
||||
}
|
||||
|
||||
// ensure current user is up to date (particularly status)
|
||||
await _apiService.SetCurrentUser();
|
||||
}
|
||||
|
||||
public async Task StopAsync()
|
||||
{
|
||||
@ -99,8 +122,6 @@ namespace QtCNETAPI.Services.GatewayService
|
||||
|
||||
public async Task JoinLobbyAsync()
|
||||
{
|
||||
await _apiService.RefreshSessionIfInvalid();
|
||||
|
||||
if (HubConnection == null || HubConnection.State != HubConnectionState.Connected) throw new InvalidOperationException("Function was called before connection was made.");
|
||||
|
||||
await HubConnection.SendAsync("JoinLobby", _apiService.CurrentUser);
|
||||
@ -110,8 +131,6 @@ namespace QtCNETAPI.Services.GatewayService
|
||||
|
||||
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 (InLobby == true)
|
||||
@ -130,8 +149,6 @@ namespace QtCNETAPI.Services.GatewayService
|
||||
|
||||
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 (InLobby)
|
||||
@ -146,19 +163,8 @@ namespace QtCNETAPI.Services.GatewayService
|
||||
}
|
||||
}
|
||||
|
||||
public async Task RefreshContactsForUser(UserInformationDto user)
|
||||
{
|
||||
await _apiService.RefreshSessionIfInvalid();
|
||||
|
||||
if (HubConnection == null || HubConnection.State != HubConnectionState.Connected) throw new InvalidOperationException("Function was called before connection was made.");
|
||||
|
||||
await HubConnection.SendAsync("RefreshContactsListOnUser", user, _apiService.CurrentUser);
|
||||
}
|
||||
|
||||
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.");
|
||||
|
||||
await HubConnection.SendAsync("SendMessage", _apiService.CurrentUser, message, InLobby, CurrentRoom);
|
||||
@ -175,11 +181,12 @@ namespace QtCNETAPI.Services.GatewayService
|
||||
|
||||
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.");
|
||||
|
||||
await HubConnection.SendAsync("UpdateStatus", _apiService.CurrentUser, status);
|
||||
|
||||
// anything that changes the user should tell the api service to set it again
|
||||
await _apiService.SetCurrentUser();
|
||||
}
|
||||
|
||||
|
||||
|
@ -85,14 +85,6 @@ namespace QtCNETAPI.Services.GatewayService
|
||||
/// <returns></returns>
|
||||
public Task SendDirectMessageAsync(UserInformationDto user, Message message);
|
||||
|
||||
/// <summary>
|
||||
/// Refreshes Contacts List For A Specified User
|
||||
/// </summary>
|
||||
/// <param name="user">The User You Wish To Refresh</param>
|
||||
/// <param name="currentUser">Yourself</param>
|
||||
/// <returns></returns>
|
||||
public Task RefreshContactsForUser(UserInformationDto user);
|
||||
|
||||
/// <summary>
|
||||
/// Updates The Status For The Current User
|
||||
/// </summary>
|
||||
@ -112,6 +104,16 @@ namespace QtCNETAPI.Services.GatewayService
|
||||
/// </summary>
|
||||
public event EventHandler OnRoomUserListReceived;
|
||||
|
||||
/// <summary>
|
||||
/// Fires When The Room The User Is In Gets Deleted By An Admin
|
||||
/// </summary>
|
||||
public event EventHandler OnRoomDeleted;
|
||||
|
||||
/// <summary>
|
||||
/// Fires When A Guest User Joins Your Room
|
||||
/// </summary>
|
||||
public event EventHandler OnGuestUserJoin;
|
||||
|
||||
/// <summary>
|
||||
/// When A Client Function/Event Is Received, This Event Fires
|
||||
/// </summary>
|
||||
@ -156,5 +158,10 @@ namespace QtCNETAPI.Services.GatewayService
|
||||
/// When the Connection Reconnects, This Event Fires
|
||||
/// </summary>
|
||||
public event EventHandler OnServerReconnected;
|
||||
|
||||
/// <summary>
|
||||
/// Fires When The Current User Is Signed Out By The Server
|
||||
/// </summary>
|
||||
public event EventHandler OnUserForceLogout;
|
||||
}
|
||||
}
|
||||
|
93
QtCNETAPI/Services/LoggingService.cs
Normal file
93
QtCNETAPI/Services/LoggingService.cs
Normal file
@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Diagnostics;
|
||||
using System.Text.Json;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.IdentityModel.Abstractions;
|
||||
|
||||
namespace QtCNETAPI.Services
|
||||
{
|
||||
public class LoggingService : IDisposable, ILogger
|
||||
{
|
||||
private DateTime LogDate { get; set; }
|
||||
private string LogFilePath { get; set; }
|
||||
private StreamWriter LogFile { get; set; }
|
||||
public LoggingService()
|
||||
{
|
||||
LogDate = DateTime.Now;
|
||||
LogFilePath = $"./Logs/QtCClientLog_{LogDate:ddMMyyy-hhmm}.log";
|
||||
|
||||
// create log file
|
||||
|
||||
if (!Directory.Exists("./Logs")) Directory.CreateDirectory("./Logs");
|
||||
LogFile = new StreamWriter(File.Create(LogFilePath));
|
||||
|
||||
Debug.WriteLine($"Log File Created At {LogFilePath}");
|
||||
}
|
||||
|
||||
public void LogString(string message)
|
||||
{
|
||||
try
|
||||
{
|
||||
Debug.WriteLine($"({DateTime.Now.ToLocalTime():hh:mm}) {message}");
|
||||
LogFile.WriteLine($"({DateTime.Now.ToLocalTime():hh:mm}) {message}");
|
||||
} catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public void LogModel<T>(T model)
|
||||
{
|
||||
try
|
||||
{
|
||||
// serialize the model as json
|
||||
string modelSerialized = JsonSerializer.Serialize(model, options: new JsonSerializerOptions { WriteIndented = true });
|
||||
|
||||
// log it
|
||||
Debug.WriteLine($"({DateTime.Now.ToLocalTime():hh:mm}) {modelSerialized}");
|
||||
LogFile.WriteLine($"({DateTime.Now.ToLocalTime():hh:mm}) {modelSerialized}");
|
||||
} catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
LogFile.WriteLine("--- END OF LOG ---");
|
||||
LogFile.Close();
|
||||
LogFile.Dispose();
|
||||
}
|
||||
|
||||
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
|
||||
{
|
||||
try
|
||||
{
|
||||
// format message
|
||||
string message = $"({DateTime.Now.ToLocalTime():hh:mm}) [{logLevel}] {formatter(state, exception)}";
|
||||
|
||||
// log it
|
||||
Debug.WriteLine(message);
|
||||
LogFile.WriteLine(message);
|
||||
} catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsEnabled(LogLevel logLevel) => true;
|
||||
public IDisposable? BeginScope<TState>(TState state) where TState : notnull => default!;
|
||||
}
|
||||
|
||||
public class LoggingServiceProvider(LoggingService? loggingService = null) : ILoggerProvider
|
||||
{
|
||||
public ILogger CreateLogger(string categoryName)
|
||||
{
|
||||
if (loggingService != null) return loggingService;
|
||||
else return new LoggingService();
|
||||
}
|
||||
|
||||
public void Dispose() { }
|
||||
}
|
||||
}
|
19
qtc-net-client-2/ClientModel/ComboBoxItem.cs
Normal file
19
qtc-net-client-2/ClientModel/ComboBoxItem.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace qtc_net_client_2.ClientModel
|
||||
{
|
||||
public class ComboBoxItem
|
||||
{
|
||||
public string? Name { get; set; }
|
||||
public object? Value { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name ?? string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
@ -15,6 +15,9 @@ namespace qtc_net_client_2.ClientModel
|
||||
[JsonPropertyName("minimizeToTray")]
|
||||
[JsonRequired]
|
||||
public bool MinimizeToTray { get; set; } = true;
|
||||
[JsonPropertyName("enableDebugLogs")]
|
||||
[JsonRequired]
|
||||
public bool EnableDebugLogs { get; set; } = false;
|
||||
|
||||
[JsonPropertyName("serverUrl")]
|
||||
[JsonRequired]
|
||||
|
@ -1,17 +1,7 @@
|
||||
using qtc_net_client_2.Services;
|
||||
using QtCNETAPI.Events;
|
||||
using QtCNETAPI.Models;
|
||||
using QtCNETAPI.Services.ApiService;
|
||||
using QtCNETAPI.Services.GatewayService;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace qtc_net_client_2.Forms
|
||||
{
|
||||
@ -33,6 +23,8 @@ namespace qtc_net_client_2.Forms
|
||||
// subscribe to server message event
|
||||
_gatewayService.OnRoomMessageReceived += _gatewayService_OnServerMessageReceived;
|
||||
_gatewayService.OnRoomUserListReceived += _gatewayService_OnRoomUserListReceived;
|
||||
_gatewayService.OnRoomDeleted += _gatewayService_OnRoomDeleted;
|
||||
_gatewayService.OnGuestUserJoin += _gatewayService_OnGuestUserJoin;
|
||||
|
||||
if (_gatewayService.CurrentRoom != null) { Text = $"QtC.NET Client - Chat Room - {_gatewayService.CurrentRoom.Name}"; lblRoomName.Text = _gatewayService.CurrentRoom.Name; }
|
||||
else if (_gatewayService.InLobby) { Text = $"QtC.NET Client - Chat Room - Lobby"; lblRoomName.Text = "Lobby"; }
|
||||
@ -93,8 +85,10 @@ namespace qtc_net_client_2.Forms
|
||||
{
|
||||
// get user info and open profile dialog
|
||||
var user = mainForm.UserDirectory.FirstOrDefault(e => e.Username == selectedUser);
|
||||
var res = await _apiService.GetUserInformationAsync(user!.Id);
|
||||
var pfpRes = await _apiService.GetUserProfilePic(user!.Id);
|
||||
if (user != null)
|
||||
{
|
||||
var res = await _apiService.GetUserInformationAsync(user.Id);
|
||||
var pfpRes = await _apiService.GetUserProfilePic(user.Id);
|
||||
|
||||
if (res.Data != null && res.Success)
|
||||
{
|
||||
@ -105,6 +99,7 @@ namespace qtc_net_client_2.Forms
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void _gatewayService_OnServerMessageReceived(object? sender, EventArgs e)
|
||||
{
|
||||
@ -118,20 +113,50 @@ namespace qtc_net_client_2.Forms
|
||||
{
|
||||
var args = (RoomListEventArgs)e;
|
||||
|
||||
if (!IsHandleCreated) return;
|
||||
|
||||
lvUserList.BeginInvoke(lvUserList.Clear);
|
||||
if (IsHandleCreated && !IsDisposed)
|
||||
{
|
||||
Invoke(delegate ()
|
||||
{
|
||||
lvUserList.Clear();
|
||||
foreach (var user in args.UserList)
|
||||
{
|
||||
lvUserList.BeginInvoke(delegate () { lvUserList.Items.Add(user.Username, user.Status); });
|
||||
lvUserList.Items.Add(user.Username, user.Status);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
private void _gatewayService_OnGuestUserJoin(object? sender, EventArgs e)
|
||||
{
|
||||
var args = (GuestUserJoinEventArgs)e;
|
||||
AddMessage($"[SERVER] Guest User {args.Username} Has Joined {_gatewayService.CurrentRoom?.Name}");
|
||||
}
|
||||
|
||||
private void _gatewayService_OnRoomDeleted(object? sender, EventArgs e)
|
||||
{
|
||||
if(IsHandleCreated && !IsDisposed)
|
||||
{
|
||||
Invoke(delegate ()
|
||||
{
|
||||
AddMessage($"[SERVER] This Room Was Deleted By An Admin.");
|
||||
lvUserList.Clear();
|
||||
|
||||
lvUserList.Enabled = false;
|
||||
rtxtChatbox.Enabled = false;
|
||||
btnSend.Enabled = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void AddMessage(string message)
|
||||
{
|
||||
if (InvokeRequired)
|
||||
Invoke(delegate { rtxtChat.AppendText(message + Environment.NewLine); });
|
||||
else rtxtChat.AppendText(message + Environment.NewLine);
|
||||
if(IsHandleCreated && !IsDisposed)
|
||||
{
|
||||
Invoke(delegate ()
|
||||
{
|
||||
rtxtChat.AppendText(message + Environment.NewLine);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
21
qtc-net-client-2/Forms/ConnectionClosed.Designer.cs
generated
21
qtc-net-client-2/Forms/ConnectionClosed.Designer.cs
generated
@ -31,18 +31,17 @@
|
||||
lblHead = new Label();
|
||||
btnReconnect = new Button();
|
||||
btnQuit = new Button();
|
||||
lblReason = new Label();
|
||||
SuspendLayout();
|
||||
//
|
||||
// lblHead
|
||||
//
|
||||
lblHead.AutoSize = true;
|
||||
lblHead.Font = new Font("Segoe UI", 11F, FontStyle.Bold);
|
||||
lblHead.Location = new Point(12, 9);
|
||||
lblHead.Name = "lblHead";
|
||||
lblHead.Size = new Size(444, 20);
|
||||
lblHead.TabIndex = 0;
|
||||
lblHead.Text = "Your Connection To The QtC.NET Server Was Lost. What Now?";
|
||||
lblHead.TextAlign = ContentAlignment.MiddleCenter;
|
||||
//
|
||||
// btnReconnect
|
||||
//
|
||||
@ -66,23 +65,12 @@
|
||||
btnQuit.UseVisualStyleBackColor = true;
|
||||
btnQuit.Click += btnQuit_Click;
|
||||
//
|
||||
// lblReason
|
||||
//
|
||||
lblReason.AutoSize = true;
|
||||
lblReason.Font = new Font("Segoe UI", 5F, FontStyle.Bold);
|
||||
lblReason.Location = new Point(88, 40);
|
||||
lblReason.Name = "lblReason";
|
||||
lblReason.Size = new Size(72, 10);
|
||||
lblReason.TabIndex = 3;
|
||||
lblReason.Text = "Reason: ${REASON}";
|
||||
//
|
||||
// frmConnectionClosed
|
||||
// ConnectionClosed
|
||||
//
|
||||
AutoScaleDimensions = new SizeF(7F, 15F);
|
||||
AutoScaleMode = AutoScaleMode.Font;
|
||||
BackColor = Color.DodgerBlue;
|
||||
ClientSize = new Size(463, 65);
|
||||
Controls.Add(lblReason);
|
||||
Controls.Add(btnQuit);
|
||||
Controls.Add(btnReconnect);
|
||||
Controls.Add(lblHead);
|
||||
@ -92,12 +80,10 @@
|
||||
Margin = new Padding(4, 3, 4, 3);
|
||||
MaximizeBox = false;
|
||||
MinimizeBox = false;
|
||||
Name = "frmConnectionClosed";
|
||||
Name = "ConnectionClosed";
|
||||
StartPosition = FormStartPosition.CenterScreen;
|
||||
Text = "QtC.NET Client - Connection Lost";
|
||||
Load += frmConnectionClosed_Load;
|
||||
ResumeLayout(false);
|
||||
PerformLayout();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@ -105,6 +91,5 @@
|
||||
private Label lblHead;
|
||||
private Button btnReconnect;
|
||||
private Button btnQuit;
|
||||
private Label lblReason;
|
||||
}
|
||||
}
|
@ -12,19 +12,12 @@ namespace qtc_net_client_2.Forms
|
||||
{
|
||||
public partial class ConnectionClosed : Form
|
||||
{
|
||||
public string? Reason { get; set; } = string.Empty;
|
||||
public ConnectionClosed(string? reason = "")
|
||||
public Label StatusLabel { get { return lblHead; } }
|
||||
public ConnectionClosed()
|
||||
{
|
||||
Reason = reason;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void frmConnectionClosed_Load(object sender, EventArgs e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(Reason)) lblReason.Visible = false;
|
||||
else lblReason.Text = $"Reason: {Reason}";
|
||||
}
|
||||
|
||||
private void btnReconnect_Click(object sender, EventArgs e)
|
||||
{
|
||||
DialogResult = DialogResult.OK;
|
||||
|
@ -42,6 +42,11 @@ namespace qtc_net_client_2.Forms
|
||||
Text = $"QtC.NET Client - Direct Message With {User.Username}";
|
||||
Messages.CollectionChanged += Messages_CollectionChanged;
|
||||
|
||||
if (User.Role == "Admin")
|
||||
{
|
||||
Messages.Add($"[SERVER] This User Is A Server Admin. You should comply with anything this user asks. however admins should not ask for personal information.\n");
|
||||
}
|
||||
|
||||
if (InitMessage != null)
|
||||
{
|
||||
Messages.Add($"[{User.Username}] {InitMessage.Content}\n");
|
||||
@ -58,7 +63,7 @@ namespace qtc_net_client_2.Forms
|
||||
if (!string.IsNullOrEmpty(rtxtChatbox.Text))
|
||||
{
|
||||
await _gatewayService.SendDirectMessageAsync(User, new QtCNETAPI.Models.Message { Content = rtxtChatbox.Text, AuthorId = _apiService.CurrentUser.Id });
|
||||
Messages.Add($"[{_apiService.CurrentUser.Username}] {rtxtChatbox.Text}");
|
||||
Messages.Add($"[{_apiService.CurrentUser.Username}] {rtxtChatbox.Text}\n");
|
||||
rtxtChatbox.Clear();
|
||||
AudioService.PlaySoundEffect("sndSendClick");
|
||||
}
|
||||
@ -69,7 +74,7 @@ namespace qtc_net_client_2.Forms
|
||||
if (!string.IsNullOrEmpty(rtxtChatbox.Text))
|
||||
{
|
||||
await _gatewayService.SendDirectMessageAsync(User, new QtCNETAPI.Models.Message { Content = rtxtChatbox.Text, AuthorId = _apiService.CurrentUser.Id });
|
||||
Messages.Add($"[{_apiService.CurrentUser.Username}] {rtxtChatbox.Text}");
|
||||
Messages.Add($"[{_apiService.CurrentUser.Username}] {rtxtChatbox.Text}\n");
|
||||
rtxtChatbox.Clear();
|
||||
AudioService.PlaySoundEffect("sndSendClick");
|
||||
}
|
||||
|
112
qtc-net-client-2/Forms/DonationWindow.Designer.cs
generated
Normal file
112
qtc-net-client-2/Forms/DonationWindow.Designer.cs
generated
Normal file
@ -0,0 +1,112 @@
|
||||
namespace qtc_net_client_2.Forms
|
||||
{
|
||||
partial class DonationWindow
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DonationWindow));
|
||||
lblHi = new Label();
|
||||
lblInfo = new Label();
|
||||
pbKofi = new PictureBox();
|
||||
pbCobaltPuter = new PictureBox();
|
||||
((System.ComponentModel.ISupportInitialize)pbKofi).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)pbCobaltPuter).BeginInit();
|
||||
SuspendLayout();
|
||||
//
|
||||
// lblHi
|
||||
//
|
||||
lblHi.AutoSize = true;
|
||||
lblHi.Font = new Font("Segoe UI", 30F, FontStyle.Bold | FontStyle.Italic);
|
||||
lblHi.Location = new Point(231, 7);
|
||||
lblHi.Name = "lblHi";
|
||||
lblHi.Size = new Size(81, 54);
|
||||
lblHi.TabIndex = 0;
|
||||
lblHi.Text = "Hi!";
|
||||
//
|
||||
// lblInfo
|
||||
//
|
||||
lblInfo.Font = new Font("Segoe UI", 7F, FontStyle.Bold);
|
||||
lblInfo.Location = new Point(12, 51);
|
||||
lblInfo.Name = "lblInfo";
|
||||
lblInfo.Size = new Size(290, 177);
|
||||
lblInfo.TabIndex = 1;
|
||||
lblInfo.Text = resources.GetString("lblInfo.Text");
|
||||
lblInfo.TextAlign = ContentAlignment.MiddleLeft;
|
||||
//
|
||||
// pbKofi
|
||||
//
|
||||
pbKofi.Cursor = Cursors.Hand;
|
||||
pbKofi.Image = Properties.Resources.support_me_on_kofi_badge_blue;
|
||||
pbKofi.Location = new Point(89, 239);
|
||||
pbKofi.Name = "pbKofi";
|
||||
pbKofi.Size = new Size(149, 78);
|
||||
pbKofi.SizeMode = PictureBoxSizeMode.Zoom;
|
||||
pbKofi.TabIndex = 2;
|
||||
pbKofi.TabStop = false;
|
||||
pbKofi.Click += pbKofi_Click;
|
||||
//
|
||||
// pbCobaltPuter
|
||||
//
|
||||
pbCobaltPuter.Image = Properties.Resources.cobalt_sittingatputer;
|
||||
pbCobaltPuter.Location = new Point(316, 29);
|
||||
pbCobaltPuter.Name = "pbCobaltPuter";
|
||||
pbCobaltPuter.Size = new Size(339, 270);
|
||||
pbCobaltPuter.SizeMode = PictureBoxSizeMode.Zoom;
|
||||
pbCobaltPuter.TabIndex = 3;
|
||||
pbCobaltPuter.TabStop = false;
|
||||
//
|
||||
// DonationWindow
|
||||
//
|
||||
AutoScaleDimensions = new SizeF(7F, 15F);
|
||||
AutoScaleMode = AutoScaleMode.Font;
|
||||
BackColor = Color.DodgerBlue;
|
||||
ClientSize = new Size(667, 328);
|
||||
Controls.Add(pbCobaltPuter);
|
||||
Controls.Add(pbKofi);
|
||||
Controls.Add(lblInfo);
|
||||
Controls.Add(lblHi);
|
||||
ForeColor = Color.White;
|
||||
FormBorderStyle = FormBorderStyle.FixedDialog;
|
||||
MaximizeBox = false;
|
||||
MinimizeBox = false;
|
||||
Name = "DonationWindow";
|
||||
StartPosition = FormStartPosition.CenterScreen;
|
||||
Text = "QtC.NET Client - Donate!";
|
||||
((System.ComponentModel.ISupportInitialize)pbKofi).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)pbCobaltPuter).EndInit();
|
||||
ResumeLayout(false);
|
||||
PerformLayout();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private Label lblHi;
|
||||
private Label lblInfo;
|
||||
private PictureBox pbKofi;
|
||||
private PictureBox pbCobaltPuter;
|
||||
}
|
||||
}
|
51
qtc-net-client-2/Forms/DonationWindow.cs
Normal file
51
qtc-net-client-2/Forms/DonationWindow.cs
Normal file
@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Policy;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace qtc_net_client_2.Forms
|
||||
{
|
||||
public partial class DonationWindow : Form
|
||||
{
|
||||
public DonationWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void pbKofi_Click(object sender, EventArgs e)
|
||||
{
|
||||
var url = "https://ko-fi.com/moonbase__";
|
||||
try
|
||||
{
|
||||
Process.Start(url);
|
||||
} catch
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
url = url.Replace("&", "^&");
|
||||
Process.Start(new ProcessStartInfo("cmd", $"/c start {url}") { CreateNoWindow = true });
|
||||
}
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
{
|
||||
Process.Start("xdg-open", url);
|
||||
}
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
||||
{
|
||||
Process.Start("open", url);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
136
qtc-net-client-2/Forms/DonationWindow.resx
Normal file
136
qtc-net-client-2/Forms/DonationWindow.resx
Normal file
@ -0,0 +1,136 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="lblInfo.Text" xml:space="preserve">
|
||||
<value>I'm Moonbase, Thanks For Using QtC.NET!
|
||||
|
||||
If you wish, you can send a few bucks to my KoFi
|
||||
linked below. It will help imensely in improving the
|
||||
performance of the platform by upgrading the VPS
|
||||
this is currently being hosted on.
|
||||
|
||||
This project is and always will be mostly just a passion
|
||||
project, similar to the likes of SillyPost. The protocol
|
||||
has existed for a bit now, however
|
||||
this is the most I've worked
|
||||
on it.
|
||||
|
||||
Thanks again for your interest!</value>
|
||||
</data>
|
||||
</root>
|
60
qtc-net-client-2/Forms/Login.Designer.cs
generated
60
qtc-net-client-2/Forms/Login.Designer.cs
generated
@ -32,11 +32,13 @@
|
||||
pbLoginBanner = new PictureBox();
|
||||
tbEmail = new TextBox();
|
||||
lblEmail = new Label();
|
||||
label1 = new Label();
|
||||
lblPassword = new Label();
|
||||
tbPassword = new TextBox();
|
||||
btnLogin = new Button();
|
||||
llblRegister = new LinkLabel();
|
||||
cbRememberMe = new CheckBox();
|
||||
llblResendEmail = new LinkLabel();
|
||||
llblForgotPasswor = new LinkLabel();
|
||||
((System.ComponentModel.ISupportInitialize)pbLoginBanner).BeginInit();
|
||||
SuspendLayout();
|
||||
//
|
||||
@ -68,16 +70,16 @@
|
||||
lblEmail.TabIndex = 2;
|
||||
lblEmail.Text = "Email";
|
||||
//
|
||||
// label1
|
||||
// lblPassword
|
||||
//
|
||||
label1.AutoSize = true;
|
||||
label1.Font = new Font("Segoe UI Light", 9F);
|
||||
label1.ForeColor = SystemColors.ControlLight;
|
||||
label1.Location = new Point(11, 138);
|
||||
label1.Name = "label1";
|
||||
label1.Size = new Size(55, 15);
|
||||
label1.TabIndex = 4;
|
||||
label1.Text = "Password";
|
||||
lblPassword.AutoSize = true;
|
||||
lblPassword.Font = new Font("Segoe UI Light", 9F);
|
||||
lblPassword.ForeColor = SystemColors.ControlLight;
|
||||
lblPassword.Location = new Point(11, 138);
|
||||
lblPassword.Name = "lblPassword";
|
||||
lblPassword.Size = new Size(55, 15);
|
||||
lblPassword.TabIndex = 4;
|
||||
lblPassword.Text = "Password";
|
||||
//
|
||||
// tbPassword
|
||||
//
|
||||
@ -122,16 +124,44 @@
|
||||
cbRememberMe.Text = "Remember Me For 7 Days";
|
||||
cbRememberMe.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// frmLogin
|
||||
// llblResendEmail
|
||||
//
|
||||
llblResendEmail.AutoSize = true;
|
||||
llblResendEmail.Font = new Font("Segoe UI Light", 9F);
|
||||
llblResendEmail.LinkColor = SystemColors.ControlLight;
|
||||
llblResendEmail.Location = new Point(369, 164);
|
||||
llblResendEmail.Name = "llblResendEmail";
|
||||
llblResendEmail.Size = new Size(129, 15);
|
||||
llblResendEmail.TabIndex = 8;
|
||||
llblResendEmail.TabStop = true;
|
||||
llblResendEmail.Text = "Resend Verification Email";
|
||||
llblResendEmail.LinkClicked += llblResendEmail_LinkClicked;
|
||||
//
|
||||
// llblForgotPasswor
|
||||
//
|
||||
llblForgotPasswor.AutoSize = true;
|
||||
llblForgotPasswor.Font = new Font("Segoe UI Light", 9F);
|
||||
llblForgotPasswor.LinkColor = SystemColors.ControlLight;
|
||||
llblForgotPasswor.Location = new Point(401, 181);
|
||||
llblForgotPasswor.Name = "llblForgotPasswor";
|
||||
llblForgotPasswor.Size = new Size(98, 15);
|
||||
llblForgotPasswor.TabIndex = 9;
|
||||
llblForgotPasswor.TabStop = true;
|
||||
llblForgotPasswor.Text = "Forgot Password?";
|
||||
llblForgotPasswor.LinkClicked += llblForgotPasswor_LinkClicked;
|
||||
//
|
||||
// llblForgotPassword
|
||||
//
|
||||
AutoScaleDimensions = new SizeF(7F, 15F);
|
||||
AutoScaleMode = AutoScaleMode.Font;
|
||||
BackColor = Color.DodgerBlue;
|
||||
ClientSize = new Size(515, 203);
|
||||
Controls.Add(llblForgotPasswor);
|
||||
Controls.Add(llblResendEmail);
|
||||
Controls.Add(cbRememberMe);
|
||||
Controls.Add(llblRegister);
|
||||
Controls.Add(btnLogin);
|
||||
Controls.Add(label1);
|
||||
Controls.Add(lblPassword);
|
||||
Controls.Add(tbPassword);
|
||||
Controls.Add(lblEmail);
|
||||
Controls.Add(tbEmail);
|
||||
@ -139,7 +169,7 @@
|
||||
FormBorderStyle = FormBorderStyle.FixedDialog;
|
||||
Icon = (Icon)resources.GetObject("$this.Icon");
|
||||
MaximizeBox = false;
|
||||
Name = "frmLogin";
|
||||
Name = "llblForgotPassword";
|
||||
StartPosition = FormStartPosition.CenterParent;
|
||||
Text = "QtC.NET Client - Login";
|
||||
Load += frmLogin_Load;
|
||||
@ -153,10 +183,12 @@
|
||||
private PictureBox pbLoginBanner;
|
||||
private TextBox tbEmail;
|
||||
private Label lblEmail;
|
||||
private Label label1;
|
||||
private Label lblPassword;
|
||||
private TextBox tbPassword;
|
||||
private Button btnLogin;
|
||||
private LinkLabel llblRegister;
|
||||
private CheckBox cbRememberMe;
|
||||
private LinkLabel llblResendEmail;
|
||||
private LinkLabel llblForgotPasswor;
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
using QtCNETAPI.Services.ApiService;
|
||||
using QtCNETAPI.Services;
|
||||
using QtCNETAPI.Dtos.User;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -9,12 +10,14 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using qtc_net_client_2.Services;
|
||||
|
||||
namespace qtc_net_client_2.Forms
|
||||
{
|
||||
public partial class Login : Form
|
||||
{
|
||||
private IApiService _apiService;
|
||||
private CredentialService _credService = new();
|
||||
public Login(IApiService apiService)
|
||||
{
|
||||
_apiService = apiService;
|
||||
@ -24,14 +27,14 @@ namespace qtc_net_client_2.Forms
|
||||
|
||||
private async void frmLogin_Load(object sender, EventArgs e)
|
||||
{
|
||||
if (File.Exists("./session.token"))
|
||||
string? accessToken = _credService.GetAccessToken();
|
||||
|
||||
if (accessToken != null)
|
||||
{
|
||||
ToggleControls(false, false);
|
||||
|
||||
// try logging in with the token in the file
|
||||
string token = File.ReadAllText("./session.token");
|
||||
|
||||
var result = await _apiService.RefreshLogin(token);
|
||||
// try logging in with the token in cred storage
|
||||
var result = await _apiService.RefreshLogin(accessToken);
|
||||
if (result.Success)
|
||||
{
|
||||
DialogResult = DialogResult.OK;
|
||||
@ -55,8 +58,9 @@ namespace qtc_net_client_2.Forms
|
||||
RememberMe = cbRememberMe.Checked
|
||||
});
|
||||
|
||||
if (result.Success)
|
||||
if (result.Success && result.Data != null)
|
||||
{
|
||||
_credService.SaveAccessToken(_apiService.CurrentUser.Username, result.Data);
|
||||
DialogResult = DialogResult.OK;
|
||||
Close();
|
||||
}
|
||||
@ -68,6 +72,24 @@ namespace qtc_net_client_2.Forms
|
||||
}
|
||||
}
|
||||
|
||||
private void llblRegister_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||
{
|
||||
Register frmRegister = new Register(_apiService);
|
||||
frmRegister.ShowDialog();
|
||||
}
|
||||
|
||||
private void llblResendEmail_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||
{
|
||||
ResendVerificationEmail resendVerificationEmail = new ResendVerificationEmail(_apiService);
|
||||
resendVerificationEmail.ShowDialog();
|
||||
}
|
||||
|
||||
private void llblForgotPasswor_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||
{
|
||||
ResetPassword resetPassword = new ResetPassword(_apiService);
|
||||
resetPassword.ShowDialog();
|
||||
}
|
||||
|
||||
private void ToggleControls(bool enable, bool clearText)
|
||||
{
|
||||
tbEmail.Enabled = enable;
|
||||
@ -81,11 +103,5 @@ namespace qtc_net_client_2.Forms
|
||||
tbPassword.Text = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
private void llblRegister_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||
{
|
||||
Register frmRegister = new Register(_apiService);
|
||||
frmRegister.ShowDialog();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
220
qtc-net-client-2/Forms/Main.Designer.cs
generated
220
qtc-net-client-2/Forms/Main.Designer.cs
generated
@ -40,7 +40,6 @@
|
||||
refreshToolStripMenuItem = new ToolStripMenuItem();
|
||||
ilProfilePics = new ImageList(components);
|
||||
tbpRooms = new TabPage();
|
||||
btnAddRoom = new Button();
|
||||
lbRooms = new ListBox();
|
||||
tbpUsers = new TabPage();
|
||||
lvUserDirectory = new ListView();
|
||||
@ -48,6 +47,9 @@
|
||||
tbpGames = new TabPage();
|
||||
lvGames = new ListView();
|
||||
ilGames = new ImageList(components);
|
||||
tbpStore = new TabPage();
|
||||
lvStoreItems = new ListView();
|
||||
ilStoreThumbnails = new ImageList(components);
|
||||
ilTabIcons = new ImageList(components);
|
||||
ctxmChangeStatus = new ContextMenuStrip(components);
|
||||
onlineToolStripMenuItem = new ToolStripMenuItem();
|
||||
@ -66,17 +68,34 @@
|
||||
llblSignIn = new LinkLabel();
|
||||
lblWelcome = new Label();
|
||||
pbUserPfp = new PictureBox();
|
||||
pbDonate = new PictureBox();
|
||||
ctxmAdminUserList = new ContextMenuStrip(components);
|
||||
refreshToolStripMenuItem1 = new ToolStripMenuItem();
|
||||
toolStripSeparator1 = new ToolStripSeparator();
|
||||
copyUserIDToClipboardToolStripMenuItem = new ToolStripMenuItem();
|
||||
deleteUserToolStripMenuItem = new ToolStripMenuItem();
|
||||
adminDirectMessageToolStripMenuItem = new ToolStripMenuItem();
|
||||
ctxmAdminRoomList = new ContextMenuStrip(components);
|
||||
toolStripMenuItem1 = new ToolStripMenuItem();
|
||||
toolStripSeparator2 = new ToolStripSeparator();
|
||||
addRoomToolStripMenuItem = new ToolStripMenuItem();
|
||||
deleteRoomToolStripMenuItem = new ToolStripMenuItem();
|
||||
lblConnectionLost = new Label();
|
||||
tbcMain.SuspendLayout();
|
||||
tbpContacts.SuspendLayout();
|
||||
ctxmRefresh.SuspendLayout();
|
||||
tbpRooms.SuspendLayout();
|
||||
tbpUsers.SuspendLayout();
|
||||
tbpGames.SuspendLayout();
|
||||
tbpStore.SuspendLayout();
|
||||
ctxmChangeStatus.SuspendLayout();
|
||||
pCurrencyArea.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)pbCurrencyIcon).BeginInit();
|
||||
pCurrentUser.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)pbUserPfp).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)pbDonate).BeginInit();
|
||||
ctxmAdminUserList.SuspendLayout();
|
||||
ctxmAdminRoomList.SuspendLayout();
|
||||
SuspendLayout();
|
||||
//
|
||||
// tbcMain
|
||||
@ -86,13 +105,15 @@
|
||||
tbcMain.Controls.Add(tbpRooms);
|
||||
tbcMain.Controls.Add(tbpUsers);
|
||||
tbcMain.Controls.Add(tbpGames);
|
||||
tbcMain.Controls.Add(tbpStore);
|
||||
tbcMain.Enabled = false;
|
||||
tbcMain.ImageList = ilTabIcons;
|
||||
tbcMain.Location = new Point(12, 66);
|
||||
tbcMain.Location = new Point(12, 83);
|
||||
tbcMain.Name = "tbcMain";
|
||||
tbcMain.SelectedIndex = 0;
|
||||
tbcMain.Size = new Size(305, 535);
|
||||
tbcMain.Size = new Size(352, 499);
|
||||
tbcMain.TabIndex = 0;
|
||||
tbcMain.SelectedIndexChanged += tbcMain_SelectedIndexChanged;
|
||||
//
|
||||
// tbpContacts
|
||||
//
|
||||
@ -101,7 +122,7 @@
|
||||
tbpContacts.Location = new Point(4, 24);
|
||||
tbpContacts.Name = "tbpContacts";
|
||||
tbpContacts.Padding = new Padding(3);
|
||||
tbpContacts.Size = new Size(297, 507);
|
||||
tbpContacts.Size = new Size(344, 471);
|
||||
tbpContacts.TabIndex = 0;
|
||||
tbpContacts.Text = "Contacts";
|
||||
tbpContacts.UseVisualStyleBackColor = true;
|
||||
@ -109,13 +130,13 @@
|
||||
// lvContacts
|
||||
//
|
||||
lvContacts.Alignment = ListViewAlignment.Left;
|
||||
lvContacts.Anchor = AnchorStyles.Left | AnchorStyles.Right;
|
||||
lvContacts.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
|
||||
lvContacts.ContextMenuStrip = ctxmRefresh;
|
||||
lvContacts.LargeImageList = ilProfilePics;
|
||||
lvContacts.Location = new Point(0, 0);
|
||||
lvContacts.MultiSelect = false;
|
||||
lvContacts.Name = "lvContacts";
|
||||
lvContacts.Size = new Size(297, 514);
|
||||
lvContacts.Size = new Size(344, 478);
|
||||
lvContacts.SmallImageList = ilProfilePics;
|
||||
lvContacts.TabIndex = 1;
|
||||
lvContacts.UseCompatibleStateImageBehavior = false;
|
||||
@ -144,37 +165,25 @@
|
||||
//
|
||||
// tbpRooms
|
||||
//
|
||||
tbpRooms.Controls.Add(btnAddRoom);
|
||||
tbpRooms.Controls.Add(lbRooms);
|
||||
tbpRooms.ImageKey = "RoomsChatIcon.png";
|
||||
tbpRooms.Location = new Point(4, 24);
|
||||
tbpRooms.Name = "tbpRooms";
|
||||
tbpRooms.Padding = new Padding(3);
|
||||
tbpRooms.Size = new Size(297, 507);
|
||||
tbpRooms.Size = new Size(344, 471);
|
||||
tbpRooms.TabIndex = 1;
|
||||
tbpRooms.Text = "Rooms";
|
||||
tbpRooms.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// btnAddRoom
|
||||
//
|
||||
btnAddRoom.FlatAppearance.BorderSize = 0;
|
||||
btnAddRoom.FlatStyle = FlatStyle.Flat;
|
||||
btnAddRoom.Location = new Point(342, 485);
|
||||
btnAddRoom.Name = "btnAddRoom";
|
||||
btnAddRoom.Size = new Size(20, 22);
|
||||
btnAddRoom.TabIndex = 7;
|
||||
btnAddRoom.UseVisualStyleBackColor = true;
|
||||
btnAddRoom.Click += btnAddRoom_Click;
|
||||
//
|
||||
// lbRooms
|
||||
//
|
||||
lbRooms.Anchor = AnchorStyles.Left | AnchorStyles.Right;
|
||||
lbRooms.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
|
||||
lbRooms.ContextMenuStrip = ctxmRefresh;
|
||||
lbRooms.FormattingEnabled = true;
|
||||
lbRooms.ItemHeight = 15;
|
||||
lbRooms.Location = new Point(0, 0);
|
||||
lbRooms.Name = "lbRooms";
|
||||
lbRooms.Size = new Size(297, 514);
|
||||
lbRooms.Size = new Size(344, 484);
|
||||
lbRooms.TabIndex = 0;
|
||||
lbRooms.DoubleClick += lbRooms_DoubleClick;
|
||||
//
|
||||
@ -184,7 +193,7 @@
|
||||
tbpUsers.ImageIndex = 1;
|
||||
tbpUsers.Location = new Point(4, 24);
|
||||
tbpUsers.Name = "tbpUsers";
|
||||
tbpUsers.Size = new Size(297, 507);
|
||||
tbpUsers.Size = new Size(344, 471);
|
||||
tbpUsers.TabIndex = 3;
|
||||
tbpUsers.Text = "Users";
|
||||
tbpUsers.UseVisualStyleBackColor = true;
|
||||
@ -192,12 +201,13 @@
|
||||
// lvUserDirectory
|
||||
//
|
||||
lvUserDirectory.Alignment = ListViewAlignment.Left;
|
||||
lvUserDirectory.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
|
||||
lvUserDirectory.ContextMenuStrip = ctxmRefresh;
|
||||
lvUserDirectory.Location = new Point(0, 0);
|
||||
lvUserDirectory.MultiSelect = false;
|
||||
lvUserDirectory.Name = "lvUserDirectory";
|
||||
lvUserDirectory.RightToLeft = RightToLeft.Yes;
|
||||
lvUserDirectory.Size = new Size(297, 514);
|
||||
lvUserDirectory.Size = new Size(344, 484);
|
||||
lvUserDirectory.SmallImageList = ilStatusIcons;
|
||||
lvUserDirectory.TabIndex = 0;
|
||||
lvUserDirectory.UseCompatibleStateImageBehavior = false;
|
||||
@ -220,14 +230,14 @@
|
||||
tbpGames.ImageIndex = 3;
|
||||
tbpGames.Location = new Point(4, 24);
|
||||
tbpGames.Name = "tbpGames";
|
||||
tbpGames.Size = new Size(297, 507);
|
||||
tbpGames.Size = new Size(344, 471);
|
||||
tbpGames.TabIndex = 4;
|
||||
tbpGames.Text = "Games";
|
||||
tbpGames.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// lvGames
|
||||
//
|
||||
lvGames.Anchor = AnchorStyles.Left | AnchorStyles.Right;
|
||||
lvGames.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
|
||||
listViewItem1.Tag = "StockMarketGame";
|
||||
listViewItem2.Tag = "GuessTheNumberGame";
|
||||
listViewItem3.Tag = "TicTacToeGame";
|
||||
@ -236,7 +246,7 @@
|
||||
lvGames.Location = new Point(0, 0);
|
||||
lvGames.MultiSelect = false;
|
||||
lvGames.Name = "lvGames";
|
||||
lvGames.Size = new Size(297, 514);
|
||||
lvGames.Size = new Size(344, 484);
|
||||
lvGames.SmallImageList = ilGames;
|
||||
lvGames.TabIndex = 2;
|
||||
lvGames.UseCompatibleStateImageBehavior = false;
|
||||
@ -251,6 +261,35 @@
|
||||
ilGames.Images.SetKeyName(1, "NumberGuessGameIcon.png");
|
||||
ilGames.Images.SetKeyName(2, "Tic-tac-toe.png");
|
||||
//
|
||||
// tbpStore
|
||||
//
|
||||
tbpStore.Controls.Add(lvStoreItems);
|
||||
tbpStore.ImageIndex = 3;
|
||||
tbpStore.Location = new Point(4, 24);
|
||||
tbpStore.Name = "tbpStore";
|
||||
tbpStore.Padding = new Padding(3);
|
||||
tbpStore.Size = new Size(344, 471);
|
||||
tbpStore.TabIndex = 5;
|
||||
tbpStore.Text = "Store";
|
||||
tbpStore.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// lvStoreItems
|
||||
//
|
||||
lvStoreItems.LargeImageList = ilStoreThumbnails;
|
||||
lvStoreItems.Location = new Point(0, 0);
|
||||
lvStoreItems.Name = "lvStoreItems";
|
||||
lvStoreItems.Size = new Size(344, 484);
|
||||
lvStoreItems.SmallImageList = ilStoreThumbnails;
|
||||
lvStoreItems.TabIndex = 0;
|
||||
lvStoreItems.UseCompatibleStateImageBehavior = false;
|
||||
lvStoreItems.DoubleClick += lvStoreItems_DoubleClick;
|
||||
//
|
||||
// ilStoreThumbnails
|
||||
//
|
||||
ilStoreThumbnails.ColorDepth = ColorDepth.Depth32Bit;
|
||||
ilStoreThumbnails.ImageSize = new Size(64, 64);
|
||||
ilStoreThumbnails.TransparentColor = Color.Transparent;
|
||||
//
|
||||
// ilTabIcons
|
||||
//
|
||||
ilTabIcons.ColorDepth = ColorDepth.Depth32Bit;
|
||||
@ -298,10 +337,10 @@
|
||||
//
|
||||
// lblRequestNotif
|
||||
//
|
||||
lblRequestNotif.Anchor = AnchorStyles.Top | AnchorStyles.Right;
|
||||
lblRequestNotif.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
|
||||
lblRequestNotif.AutoSize = true;
|
||||
lblRequestNotif.Font = new Font("Segoe UI", 6F, FontStyle.Bold);
|
||||
lblRequestNotif.Location = new Point(215, 53);
|
||||
lblRequestNotif.Location = new Point(12, 67);
|
||||
lblRequestNotif.Name = "lblRequestNotif";
|
||||
lblRequestNotif.Size = new Size(109, 11);
|
||||
lblRequestNotif.TabIndex = 6;
|
||||
@ -334,7 +373,7 @@
|
||||
pCurrencyArea.Controls.Add(llblClaimSpin);
|
||||
pCurrencyArea.Controls.Add(pbCurrencyIcon);
|
||||
pCurrencyArea.Controls.Add(lblCurrencyAmount);
|
||||
pCurrencyArea.Location = new Point(223, 5);
|
||||
pCurrencyArea.Location = new Point(270, 5);
|
||||
pCurrencyArea.Name = "pCurrencyArea";
|
||||
pCurrencyArea.Size = new Size(95, 46);
|
||||
pCurrencyArea.TabIndex = 12;
|
||||
@ -442,16 +481,116 @@
|
||||
pbUserPfp.TabStop = false;
|
||||
pbUserPfp.Click += pbUserPfp_Click;
|
||||
//
|
||||
// pbDonate
|
||||
//
|
||||
pbDonate.Anchor = AnchorStyles.Top | AnchorStyles.Right;
|
||||
pbDonate.Cursor = Cursors.Hand;
|
||||
pbDonate.Image = Properties.Resources.donatebtn;
|
||||
pbDonate.Location = new Point(288, 56);
|
||||
pbDonate.Name = "pbDonate";
|
||||
pbDonate.Size = new Size(77, 22);
|
||||
pbDonate.SizeMode = PictureBoxSizeMode.Zoom;
|
||||
pbDonate.TabIndex = 14;
|
||||
pbDonate.TabStop = false;
|
||||
pbDonate.Click += pbDonate_Click;
|
||||
//
|
||||
// ctxmAdminUserList
|
||||
//
|
||||
ctxmAdminUserList.Items.AddRange(new ToolStripItem[] { refreshToolStripMenuItem1, toolStripSeparator1, copyUserIDToClipboardToolStripMenuItem, deleteUserToolStripMenuItem, adminDirectMessageToolStripMenuItem });
|
||||
ctxmAdminUserList.Name = "contextMenuStrip1";
|
||||
ctxmAdminUserList.Size = new Size(213, 98);
|
||||
ctxmAdminUserList.Opening += ctxmAdminUserList_Opening;
|
||||
//
|
||||
// refreshToolStripMenuItem1
|
||||
//
|
||||
refreshToolStripMenuItem1.Name = "refreshToolStripMenuItem1";
|
||||
refreshToolStripMenuItem1.Size = new Size(212, 22);
|
||||
refreshToolStripMenuItem1.Text = "Refresh";
|
||||
refreshToolStripMenuItem1.Click += refreshToolStripMenuItem_Click;
|
||||
//
|
||||
// toolStripSeparator1
|
||||
//
|
||||
toolStripSeparator1.Name = "toolStripSeparator1";
|
||||
toolStripSeparator1.Size = new Size(209, 6);
|
||||
//
|
||||
// copyUserIDToClipboardToolStripMenuItem
|
||||
//
|
||||
copyUserIDToClipboardToolStripMenuItem.Name = "copyUserIDToClipboardToolStripMenuItem";
|
||||
copyUserIDToClipboardToolStripMenuItem.Size = new Size(212, 22);
|
||||
copyUserIDToClipboardToolStripMenuItem.Text = "Copy User ID To Clipboard";
|
||||
copyUserIDToClipboardToolStripMenuItem.Click += copyUserIDToClipboardToolStripMenuItem_Click;
|
||||
//
|
||||
// deleteUserToolStripMenuItem
|
||||
//
|
||||
deleteUserToolStripMenuItem.Name = "deleteUserToolStripMenuItem";
|
||||
deleteUserToolStripMenuItem.Size = new Size(212, 22);
|
||||
deleteUserToolStripMenuItem.Text = "Delete User";
|
||||
deleteUserToolStripMenuItem.Click += deleteUserToolStripMenuItem_Click;
|
||||
//
|
||||
// adminDirectMessageToolStripMenuItem
|
||||
//
|
||||
adminDirectMessageToolStripMenuItem.Name = "adminDirectMessageToolStripMenuItem";
|
||||
adminDirectMessageToolStripMenuItem.Size = new Size(212, 22);
|
||||
adminDirectMessageToolStripMenuItem.Text = "Admin Direct Message";
|
||||
adminDirectMessageToolStripMenuItem.Click += adminDirectMessageToolStripMenuItem_Click;
|
||||
//
|
||||
// ctxmAdminRoomList
|
||||
//
|
||||
ctxmAdminRoomList.Items.AddRange(new ToolStripItem[] { toolStripMenuItem1, toolStripSeparator2, addRoomToolStripMenuItem, deleteRoomToolStripMenuItem });
|
||||
ctxmAdminRoomList.Name = "contextMenuStrip1";
|
||||
ctxmAdminRoomList.Size = new Size(143, 76);
|
||||
ctxmAdminRoomList.Opening += ctxmAdminRoomList_Opening;
|
||||
//
|
||||
// toolStripMenuItem1
|
||||
//
|
||||
toolStripMenuItem1.Name = "toolStripMenuItem1";
|
||||
toolStripMenuItem1.Size = new Size(142, 22);
|
||||
toolStripMenuItem1.Text = "Refresh";
|
||||
toolStripMenuItem1.Click += refreshToolStripMenuItem_Click;
|
||||
//
|
||||
// toolStripSeparator2
|
||||
//
|
||||
toolStripSeparator2.Name = "toolStripSeparator2";
|
||||
toolStripSeparator2.Size = new Size(139, 6);
|
||||
//
|
||||
// addRoomToolStripMenuItem
|
||||
//
|
||||
addRoomToolStripMenuItem.Name = "addRoomToolStripMenuItem";
|
||||
addRoomToolStripMenuItem.Size = new Size(142, 22);
|
||||
addRoomToolStripMenuItem.Text = "Add Room";
|
||||
addRoomToolStripMenuItem.Click += addRoomToolStripMenuItem_Click;
|
||||
//
|
||||
// deleteRoomToolStripMenuItem
|
||||
//
|
||||
deleteRoomToolStripMenuItem.Name = "deleteRoomToolStripMenuItem";
|
||||
deleteRoomToolStripMenuItem.Size = new Size(142, 22);
|
||||
deleteRoomToolStripMenuItem.Text = "Delete Room";
|
||||
deleteRoomToolStripMenuItem.Click += deleteRoomToolStripMenuItem_Click;
|
||||
//
|
||||
// lblConnectionLost
|
||||
//
|
||||
lblConnectionLost.AutoSize = true;
|
||||
lblConnectionLost.Font = new Font("Segoe UI", 6F, FontStyle.Bold);
|
||||
lblConnectionLost.ForeColor = Color.Red;
|
||||
lblConnectionLost.Location = new Point(12, 67);
|
||||
lblConnectionLost.Name = "lblConnectionLost";
|
||||
lblConnectionLost.Size = new Size(175, 11);
|
||||
lblConnectionLost.TabIndex = 15;
|
||||
lblConnectionLost.Text = "Server Connection Lost. Trying To Reconnect...";
|
||||
lblConnectionLost.Visible = false;
|
||||
//
|
||||
// Main
|
||||
//
|
||||
AutoScaleDimensions = new SizeF(7F, 15F);
|
||||
AutoScaleMode = AutoScaleMode.Font;
|
||||
BackColor = Color.DodgerBlue;
|
||||
ClientSize = new Size(329, 613);
|
||||
ClientSize = new Size(376, 594);
|
||||
Controls.Add(pbDonate);
|
||||
Controls.Add(pCurrentUser);
|
||||
Controls.Add(pCurrencyArea);
|
||||
Controls.Add(lblRequestNotif);
|
||||
Controls.Add(tbcMain);
|
||||
Controls.Add(lblConnectionLost);
|
||||
FormBorderStyle = FormBorderStyle.FixedDialog;
|
||||
Icon = (Icon)resources.GetObject("$this.Icon");
|
||||
MaximizeBox = false;
|
||||
@ -467,6 +606,7 @@
|
||||
tbpRooms.ResumeLayout(false);
|
||||
tbpUsers.ResumeLayout(false);
|
||||
tbpGames.ResumeLayout(false);
|
||||
tbpStore.ResumeLayout(false);
|
||||
ctxmChangeStatus.ResumeLayout(false);
|
||||
pCurrencyArea.ResumeLayout(false);
|
||||
pCurrencyArea.PerformLayout();
|
||||
@ -474,6 +614,9 @@
|
||||
pCurrentUser.ResumeLayout(false);
|
||||
pCurrentUser.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)pbUserPfp).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)pbDonate).EndInit();
|
||||
ctxmAdminUserList.ResumeLayout(false);
|
||||
ctxmAdminRoomList.ResumeLayout(false);
|
||||
ResumeLayout(false);
|
||||
PerformLayout();
|
||||
}
|
||||
@ -494,7 +637,6 @@
|
||||
private ToolStripMenuItem awayToolStripMenuItem;
|
||||
private ToolStripMenuItem doNotDisturbToolStripMenuItem;
|
||||
private ToolStripMenuItem invisibleToolStripMenuItem;
|
||||
private Button btnAddRoom;
|
||||
private LinkLabel llblClaimSpin;
|
||||
private Panel pCurrencyArea;
|
||||
private Panel pCurrentUser;
|
||||
@ -513,5 +655,21 @@
|
||||
private ImageList ilStatusIcons;
|
||||
private TabPage tbpUsers;
|
||||
private ListView lvUserDirectory;
|
||||
private PictureBox pbDonate;
|
||||
private TabPage tbpStore;
|
||||
private ListView lvStoreItems;
|
||||
private ImageList ilStoreThumbnails;
|
||||
private ContextMenuStrip ctxmAdminUserList;
|
||||
private ToolStripMenuItem refreshToolStripMenuItem1;
|
||||
private ToolStripSeparator toolStripSeparator1;
|
||||
private ToolStripMenuItem copyUserIDToClipboardToolStripMenuItem;
|
||||
private ToolStripMenuItem deleteUserToolStripMenuItem;
|
||||
private ToolStripMenuItem adminDirectMessageToolStripMenuItem;
|
||||
private ContextMenuStrip ctxmAdminRoomList;
|
||||
private ToolStripMenuItem toolStripMenuItem1;
|
||||
private ToolStripSeparator toolStripSeparator2;
|
||||
private ToolStripMenuItem addRoomToolStripMenuItem;
|
||||
private ToolStripMenuItem deleteRoomToolStripMenuItem;
|
||||
private Label lblConnectionLost;
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,9 @@ using QtCNETAPI.Models;
|
||||
using qtc_net_client_2.Forms;
|
||||
using qtc_net_client_2.Services;
|
||||
using qtc_net_client_2.ClientModel;
|
||||
using System.Threading.Tasks;
|
||||
using QtCNETAPI.Schema;
|
||||
using QtCNETAPI.Services;
|
||||
|
||||
namespace qtc_net_client_2
|
||||
{
|
||||
@ -13,7 +16,9 @@ namespace qtc_net_client_2
|
||||
{
|
||||
private IApiService _apiService;
|
||||
private IGatewayService _gatewayService;
|
||||
|
||||
private Config _config;
|
||||
private ServerConfig _serverConfig;
|
||||
private AudioService AudioService = new();
|
||||
private LoggingService LoggingService;
|
||||
|
||||
@ -125,7 +130,8 @@ namespace qtc_net_client_2
|
||||
pbUserPfp.Image = Image.FromStream(ms);
|
||||
ms.Dispose();
|
||||
}
|
||||
} else LoggingService.LogString($"User Has No Profile Picture Or It Could Not Be Loaded.\n{pfpRes.Message}");
|
||||
}
|
||||
else LoggingService.LogString($"User Has No Profile Picture Or It Could Not Be Loaded.\n{pfpRes.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -147,11 +153,7 @@ namespace qtc_net_client_2
|
||||
private void llblEditProfile_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||
{
|
||||
ProfileEdit frmProfileEdit = new ProfileEdit(_apiService);
|
||||
var dialogResult = frmProfileEdit.ShowDialog();
|
||||
if (dialogResult == DialogResult.OK)
|
||||
{
|
||||
MessageBox.Show("If you updated your username, hit the refresh button to see it update on your lists.\nThe top username will not update until you restart your client.");
|
||||
}
|
||||
frmProfileEdit.ShowDialog();
|
||||
}
|
||||
|
||||
private async void lvContacts_DoubleClick(object sender, EventArgs e)
|
||||
@ -170,12 +172,29 @@ namespace qtc_net_client_2
|
||||
var res = await _apiService.GetUserInformationAsync(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 (res.Data != null && res.Success)
|
||||
{
|
||||
LoggingService.LogString($"Opening Profile For User '{res.Data.Username}'");
|
||||
Profile frmProfile = new Profile(res.Data, pfpRes, Contacts, _apiService, _gatewayService);
|
||||
Profile frmProfile = new Profile(res.Data, pfpRes, Contacts, _apiService, _gatewayService, cosmeticData);
|
||||
frmProfile.Show();
|
||||
}
|
||||
}
|
||||
@ -274,7 +293,7 @@ namespace qtc_net_client_2
|
||||
var result = await _apiService.AddCurrencyToCurrentUser(tokenJackpotSpinner.TokensWon, true);
|
||||
if (result.Success)
|
||||
{
|
||||
lblCurrencyAmount.Text = (_apiService.CurrentUser.CurrencyAmount + tokenJackpotSpinner.TokensWon).ToString("N0");
|
||||
lblCurrencyAmount.Text = _apiService.CurrentUser.CurrencyAmount.ToString("N0");
|
||||
llblClaimSpin.Visible = false;
|
||||
}
|
||||
else MessageBox.Show("We Were Unable To Claim Your Prize At This Time. Please Try Again Later.", "Uh Oh.", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
@ -294,12 +313,29 @@ namespace qtc_net_client_2
|
||||
var res = await _apiService.GetUserInformationAsync(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 (res.Data != null && res.Success)
|
||||
{
|
||||
LoggingService.LogString($"Opening Profile For User '{res.Data.Username}'");
|
||||
Profile frmProfile = new Profile(res.Data, pfpRes, Contacts, _apiService, _gatewayService);
|
||||
Profile frmProfile = new Profile(res.Data, pfpRes, Contacts, _apiService, _gatewayService, cosmeticData);
|
||||
frmProfile.Show();
|
||||
}
|
||||
}
|
||||
@ -332,10 +368,201 @@ namespace qtc_net_client_2
|
||||
|
||||
private async void refreshToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
// refresh all controls (TODO - probably restrict this to currently visible control)
|
||||
await RefreshContactsList();
|
||||
await RefreshRoomsList();
|
||||
await RefreshUsers();
|
||||
if (tbcMain.SelectedIndex == 0) await RefreshContactsList();
|
||||
if (tbcMain.SelectedIndex == 1) await RefreshRoomsList();
|
||||
if (tbcMain.SelectedIndex == 2) await RefreshUsers();
|
||||
}
|
||||
|
||||
private void pbDonate_Click(object sender, EventArgs e)
|
||||
{
|
||||
DonationWindow donationWindow = new DonationWindow();
|
||||
donationWindow.Show();
|
||||
}
|
||||
|
||||
private async void tbcMain_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (tbcMain.SelectedIndex == 4)
|
||||
{
|
||||
// get store items
|
||||
var storeItems = await _apiService.GetStoreItems();
|
||||
if (storeItems != null && storeItems.Success && storeItems.Data != null)
|
||||
{
|
||||
if (lvStoreItems.Items.Count == storeItems.Data.Count) return;
|
||||
|
||||
ilStoreThumbnails.Images.Clear();
|
||||
foreach (var item in storeItems.Data)
|
||||
{
|
||||
await GetAndAddStoreThumbnail(item);
|
||||
var lvitem = lvStoreItems.Items.Add(new ListViewItem { Text = item.Name, Name = item.Id.ToString() });
|
||||
lvitem.ImageKey = item.Id.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async void lvStoreItems_DoubleClick(object sender, EventArgs e)
|
||||
{
|
||||
if (lvStoreItems.SelectedItems.Count > 0)
|
||||
{
|
||||
string? itemSelected = (string?)lvStoreItems.SelectedItems[lvStoreItems.SelectedItems.Count - 1].Name;
|
||||
if (itemSelected != null)
|
||||
{
|
||||
// get item
|
||||
var item = await _apiService.GetStoreItem(int.Parse(itemSelected));
|
||||
if (item != null && item.Success && item.Data != null)
|
||||
{
|
||||
StoreItemDisplay storeItemDisplay = new StoreItemDisplay(item.Data, LoggingService, _apiService);
|
||||
storeItemDisplay.ShowDialog();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addRoomToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
CreateRoom createRoom = new CreateRoom(_apiService);
|
||||
createRoom.ShowDialog();
|
||||
}
|
||||
|
||||
private void ctxmAdminRoomList_Opening(object sender, System.ComponentModel.CancelEventArgs e)
|
||||
{
|
||||
if (lbRooms.SelectedItem == null)
|
||||
deleteRoomToolStripMenuItem.Enabled = false;
|
||||
else deleteRoomToolStripMenuItem.Enabled = true;
|
||||
}
|
||||
|
||||
private void ctxmAdminUserList_Opening(object sender, System.ComponentModel.CancelEventArgs e)
|
||||
{
|
||||
if (lvUserDirectory.SelectedItems.Count > 0)
|
||||
{
|
||||
string? lvUserDirectoryItemSelected = (string?)lvUserDirectory.SelectedItems[lvUserDirectory.SelectedItems.Count - 1].Text;
|
||||
if (lvUserDirectoryItemSelected != null && lvUserDirectoryItemSelected == _apiService.CurrentUser.Username)
|
||||
{
|
||||
deleteUserToolStripMenuItem.Enabled = false;
|
||||
adminDirectMessageToolStripMenuItem.Enabled = false;
|
||||
copyUserIDToClipboardToolStripMenuItem.Enabled = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
deleteUserToolStripMenuItem.Enabled = false;
|
||||
adminDirectMessageToolStripMenuItem.Enabled = false;
|
||||
copyUserIDToClipboardToolStripMenuItem.Enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
deleteUserToolStripMenuItem.Enabled = true;
|
||||
adminDirectMessageToolStripMenuItem.Enabled = true;
|
||||
copyUserIDToClipboardToolStripMenuItem.Enabled = true;
|
||||
}
|
||||
|
||||
private void copyUserIDToClipboardToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (lvUserDirectory.SelectedItems.Count > 0)
|
||||
{
|
||||
string? itemSelected = (string?)lvUserDirectory.SelectedItems[lvUserDirectory.SelectedItems.Count - 1].Text;
|
||||
if (itemSelected != null)
|
||||
{
|
||||
// get user
|
||||
var user = UserDirectory.FirstOrDefault(e => e.Username == itemSelected);
|
||||
if (user != null)
|
||||
{
|
||||
// clipboard requires STA apartment state
|
||||
Thread thread = new(delegate () { Clipboard.SetText(user.Id); });
|
||||
thread.SetApartmentState(ApartmentState.STA);
|
||||
thread.Start();
|
||||
|
||||
MessageBox.Show("Copied!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async void deleteRoomToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (lbRooms.SelectedItems.Count > 0)
|
||||
{
|
||||
string? itemSelected = (string?)lbRooms.SelectedItems[lbRooms.SelectedItems.Count - 1];
|
||||
if (itemSelected != null)
|
||||
{
|
||||
var dialogResult = MessageBox.Show("Are You Sure You Want To Delete This Room?\nThis will kick everyone currently in the room out.",
|
||||
"are you sure..?",
|
||||
MessageBoxButtons.YesNo,
|
||||
MessageBoxIcon.Question);
|
||||
|
||||
if (dialogResult == DialogResult.Yes)
|
||||
{
|
||||
// get the room
|
||||
var room = RoomList.FirstOrDefault(e => e.Name == itemSelected);
|
||||
if (room != null)
|
||||
{
|
||||
var apiResult = await _apiService.DeleteRoomAsync(room.Id);
|
||||
if (apiResult != null && apiResult.Success)
|
||||
MessageBox.Show("Deleted!");
|
||||
else
|
||||
MessageBox.Show("There was an error deleting the room. Try Again?", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
else MessageBox.Show("This room is unknown. It may have already been deleted.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async void deleteUserToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (lvUserDirectory.SelectedItems.Count > 0)
|
||||
{
|
||||
string? itemSelected = (string?)lvUserDirectory.SelectedItems[lvUserDirectory.SelectedItems.Count - 1].Text;
|
||||
if (itemSelected != null)
|
||||
{
|
||||
var dialogResult = MessageBox.Show("Are You Sure You Want To Delete This User?\n" +
|
||||
"This should only be done as a last resort. You should take the proper percautions to ensure the user cannot make a new account.\n" +
|
||||
"Proper moderation tools are coming soon.\n" +
|
||||
"Doing this will also log out the user if they are logged in.",
|
||||
"are you sure...?",
|
||||
MessageBoxButtons.YesNo,
|
||||
MessageBoxIcon.Warning);
|
||||
|
||||
if (dialogResult == DialogResult.Yes)
|
||||
{
|
||||
// get the user
|
||||
var user = UserDirectory.FirstOrDefault(e => e.Username == itemSelected);
|
||||
if (user != null)
|
||||
{
|
||||
var apiResult = await _apiService.DeleteUserById(user.Id);
|
||||
if (apiResult != null && apiResult.Success)
|
||||
MessageBox.Show("User Deleted!");
|
||||
else
|
||||
MessageBox.Show("There was an error deleting the user. Try Again?", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
else MessageBox.Show("This user is unknown. They may have already been deleted.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async void adminDirectMessageToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (lvUserDirectory.SelectedItems.Count > 0)
|
||||
{
|
||||
string? itemSelected = (string?)lvUserDirectory.SelectedItems[lvUserDirectory.SelectedItems.Count - 1].Text;
|
||||
if (itemSelected != null)
|
||||
{
|
||||
// get the user
|
||||
var user = UserDirectory.FirstOrDefault(e => e.Username == itemSelected);
|
||||
if (user != null)
|
||||
{
|
||||
var userDto = await _apiService.GetUserInformationAsync(user.Id);
|
||||
if(userDto != null && userDto.Success && userDto.Data != null)
|
||||
{
|
||||
// immediately start a dm chat with the user, the user will be informed immediately if the user is an admin
|
||||
DirectMessage directMessage = new DirectMessage(_gatewayService, _apiService, userDto.Data, null);
|
||||
directMessage.Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnSuccessfulLogin()
|
||||
@ -358,10 +585,14 @@ namespace qtc_net_client_2
|
||||
_gatewayService.OnRefreshRoomListReceived += _gatewayService_OnRefreshRoomListReceived;
|
||||
_gatewayService.OnRefreshContactsListReceived += _gatewayService_OnRefreshContactsListReceived;
|
||||
_gatewayService.OnServerConfigReceived += _gatewayService_OnServerConfigReceived;
|
||||
_gatewayService.OnUserForceLogout += _gatewayService_OnUserForceLogout;
|
||||
|
||||
_apiService.OnCurrentUserUpdate += _apiService_OnCurrentUserUpdate;
|
||||
|
||||
if (_gatewayService.HubConnection != null && _gatewayService.HubConnection.State == Microsoft.AspNetCore.SignalR.Client.HubConnectionState.Connected)
|
||||
{
|
||||
LoggingService.LogString("Connected To SignalR Succesfully.");
|
||||
LoggingService.LogString("Building UI...");
|
||||
|
||||
// we are fully logged in, get current user profile pic and set up ui
|
||||
llblSignIn.Visible = false;
|
||||
@ -383,14 +614,14 @@ namespace qtc_net_client_2
|
||||
}
|
||||
}
|
||||
|
||||
if (lvUserDirectory.Items.Count <= 0)
|
||||
await RefreshUsers(); // prevent edge case where the refresh event never gets sent to connecting client
|
||||
|
||||
await RefreshContactsList();
|
||||
await RefreshRoomsList();
|
||||
await RefreshUsers();
|
||||
|
||||
// TODO - figure out server side why online status is invisible on login
|
||||
_apiService.CurrentUser.Status = 1;
|
||||
|
||||
// set status context menu checked
|
||||
// TODO - figure out more efficient way to do this
|
||||
UserStatus cuStatus = (UserStatus)_apiService.CurrentUser.Status;
|
||||
switch (cuStatus)
|
||||
{
|
||||
@ -420,15 +651,19 @@ namespace qtc_net_client_2
|
||||
break;
|
||||
}
|
||||
|
||||
if (_apiService.CurrentUser.Role == "Admin") btnAddRoom.Enabled = true;
|
||||
else btnAddRoom.Enabled = false;
|
||||
|
||||
var current = DateTime.UtcNow;
|
||||
if (current > _apiService.CurrentUser.LastCurrencySpin.ToUniversalTime() || _apiService.CurrentUser.LastCurrencySpin == new DateTime()) llblClaimSpin.Visible = true;
|
||||
else llblClaimSpin.Visible = false;
|
||||
|
||||
if (_config.StartMinimized) WindowState = FormWindowState.Minimized;
|
||||
|
||||
if (_apiService.CurrentUser.Role == "Admin")
|
||||
{
|
||||
LoggingService.LogString("Current User Is An Admin. Using Admin Context Menu Strips...");
|
||||
lvUserDirectory.ContextMenuStrip = ctxmAdminUserList;
|
||||
lbRooms.ContextMenuStrip = ctxmAdminRoomList;
|
||||
}
|
||||
|
||||
LoggingService.LogString("Client Ready");
|
||||
}
|
||||
}
|
||||
@ -438,29 +673,30 @@ namespace qtc_net_client_2
|
||||
{
|
||||
LoggingService.LogString("Refreshing All Users List...");
|
||||
|
||||
if (IsHandleCreated && !IsDisposed)
|
||||
{
|
||||
await Invoke(async delegate ()
|
||||
{
|
||||
// get all users on server
|
||||
var userList = await _apiService.GetAllUsersAsync();
|
||||
|
||||
if (userList != null && userList.Success && userList.Data != null)
|
||||
{
|
||||
// clear the list
|
||||
if (lvUserDirectory.InvokeRequired) lvUserDirectory.BeginInvoke(lvUserDirectory.Items.Clear);
|
||||
else lvUserDirectory.Items.Clear();
|
||||
lvUserDirectory.Items.Clear();
|
||||
UserDirectory.Clear();
|
||||
|
||||
// populate list
|
||||
foreach (var user in userList.Data)
|
||||
{
|
||||
if (lvUserDirectory.InvokeRequired)
|
||||
{
|
||||
lvUserDirectory.BeginInvoke(delegate () { lvUserDirectory.Items.Add(user.Username, user.Status); });
|
||||
}
|
||||
else
|
||||
{
|
||||
lvUserDirectory.Items.Add(user.Username, user.Status);
|
||||
}
|
||||
UserDirectory.Add(user);
|
||||
}
|
||||
|
||||
if (System.Diagnostics.Debugger.IsAttached || _config.EnableDebugLogs)
|
||||
LoggingService.LogModel(userList.Data);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -468,7 +704,7 @@ namespace qtc_net_client_2
|
||||
{
|
||||
LoggingService.LogString("Refreshing Rooms List...");
|
||||
|
||||
if (InvokeRequired)
|
||||
if (IsHandleCreated && !IsDisposed)
|
||||
{
|
||||
await Invoke(async delegate ()
|
||||
{
|
||||
@ -481,35 +717,21 @@ namespace qtc_net_client_2
|
||||
lbRooms.Items.Add(room.Name);
|
||||
}
|
||||
RoomList = roomsRes.Data;
|
||||
if (System.Diagnostics.Debugger.IsAttached || _config.EnableDebugLogs)
|
||||
LoggingService.LogModel(roomsRes.Data);
|
||||
}
|
||||
|
||||
// always add lobby room to rooms list
|
||||
lbRooms.Items.Add("Lobby");
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
lbRooms.Items.Clear();
|
||||
var roomsRes = await _apiService.GetAllRoomsAsync();
|
||||
if (roomsRes.Success && roomsRes.Data != null)
|
||||
{
|
||||
lbRooms.Items.Clear();
|
||||
foreach (var room in roomsRes.Data)
|
||||
{
|
||||
lbRooms.Items.Add(room.Name);
|
||||
}
|
||||
RoomList = roomsRes.Data;
|
||||
}
|
||||
|
||||
// always add lobby room to rooms list
|
||||
lbRooms.Items.Add("Lobby");
|
||||
}
|
||||
|
||||
private async Task RefreshContactsList()
|
||||
{
|
||||
LoggingService.LogString("Refreshing Contacts List...");
|
||||
|
||||
if (InvokeRequired)
|
||||
if (IsHandleCreated && !IsDisposed)
|
||||
{
|
||||
await Invoke(async delegate ()
|
||||
{
|
||||
@ -578,76 +800,11 @@ namespace qtc_net_client_2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (System.Diagnostics.Debugger.IsAttached || _config.EnableDebugLogs)
|
||||
LoggingService.LogModel(contactsRes.Data);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
lvContacts.Items.Clear();
|
||||
Contacts.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)
|
||||
{
|
||||
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);
|
||||
|
||||
if (user.Data != null)
|
||||
{
|
||||
Contacts.Add(contact);
|
||||
if (contact.OwnerId == _apiService.CurrentUser!.Id)
|
||||
{
|
||||
switch (contact.OwnerStatus)
|
||||
{
|
||||
case Contact.ContactStatus.AwaitingApprovalFromOther:
|
||||
var lvi = lvContacts.Items.Add($"{user.Data.Username} [Request Sent]");
|
||||
await AddProfilePicToList(user.Data.Id);
|
||||
if (ilProfilePics.Images.ContainsKey(user.Data.Id))
|
||||
lvi.ImageKey = user.Data.Id;
|
||||
else lvi.ImageKey = "DEFAULT";
|
||||
break;
|
||||
case Contact.ContactStatus.Accepted:
|
||||
var lvi2 = lvContacts.Items.Add($"{user.Data.Username}");
|
||||
await AddProfilePicToList(user.Data.Id);
|
||||
if (ilProfilePics.Images.ContainsKey(user.Data.Id))
|
||||
lvi2.ImageKey = user.Data.Id;
|
||||
else lvi2.ImageKey = "DEFAULT";
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (contact.UserId == _apiService.CurrentUser!.Id)
|
||||
{
|
||||
switch (contact.UserStatus)
|
||||
{
|
||||
case Contact.ContactStatus.AwaitingApprovalFromSelf:
|
||||
var lvi = lvContacts.Items.Add($"{user.Data.Username} [Contact Request]");
|
||||
await AddProfilePicToList(user.Data.Id);
|
||||
if (ilProfilePics.Images.ContainsKey(user.Data.Id))
|
||||
lvi.ImageKey = user.Data.Id;
|
||||
else lvi.ImageKey = "DEFAULT";
|
||||
AudioService.PlaySoundEffect("sndContactRequest");
|
||||
break;
|
||||
case Contact.ContactStatus.Accepted:
|
||||
var lvi2 = lvContacts.Items.Add($"{user.Data.Username}");
|
||||
await AddProfilePicToList(user.Data.Id);
|
||||
if (ilProfilePics.Images.ContainsKey(user.Data.Id))
|
||||
lvi2.ImageKey = user.Data.Id;
|
||||
else lvi2.ImageKey = "DEFAULT";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -655,11 +812,9 @@ namespace qtc_net_client_2
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (!IsHandleCreated) { LoggingService.LogString("Form Handle Wasn't Created"); return; }
|
||||
|
||||
if (InvokeRequired && !IsDisposed)
|
||||
if(IsHandleCreated && !IsDisposed)
|
||||
{
|
||||
BeginInvoke(async delegate ()
|
||||
await Invoke(async delegate ()
|
||||
{
|
||||
label.ForeColor = Color.Red;
|
||||
await Task.Delay(500);
|
||||
@ -667,11 +822,6 @@ namespace qtc_net_client_2
|
||||
await Task.Delay(500);
|
||||
});
|
||||
}
|
||||
|
||||
label.ForeColor = Color.Red;
|
||||
await Task.Delay(500);
|
||||
label.ForeColor = Color.Blue;
|
||||
await Task.Delay(500);
|
||||
}
|
||||
}
|
||||
|
||||
@ -685,21 +835,38 @@ namespace qtc_net_client_2
|
||||
ilProfilePics.Images.Add(userId, Image.FromStream(ms));
|
||||
ms.Dispose();
|
||||
}
|
||||
} else if (result != null) LoggingService.LogString($"User Has No Profile Picture Or It Could Not Be Loaded.\n{result.Message}");
|
||||
}
|
||||
else if (result != null) LoggingService.LogString($"User Has No Profile Picture Or It Could Not Be Loaded.\n{result.Message}");
|
||||
}
|
||||
|
||||
private async Task GetAndAddStoreThumbnail(StoreItem item)
|
||||
{
|
||||
try
|
||||
{
|
||||
using HttpClient client = new();
|
||||
var response = await client.GetAsync(item.ThumbnailUrl);
|
||||
if (response != null && response.IsSuccessStatusCode)
|
||||
{
|
||||
using var stream = await response.Content.ReadAsStreamAsync();
|
||||
Image image = Image.FromStream(stream);
|
||||
stream.Dispose();
|
||||
ilStoreThumbnails.Images.Add(item.Id.ToString(), image);
|
||||
}
|
||||
else if (response != null) LoggingService.LogString($"Store Item Thumbnail Could Not Be Loaded Due To Status Code {response.StatusCode}");
|
||||
else LoggingService.LogString("Store Item Thumbnail Could Not Be Loaded");
|
||||
client.Dispose();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggingService.LogString("Store Item Thumbnail Could Not Be Loaded\n" + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public void RefreshCurrencyCounter()
|
||||
{
|
||||
if (lblCurrencyAmount.InvokeRequired)
|
||||
if (IsHandleCreated && !IsDisposed)
|
||||
{
|
||||
lblCurrencyAmount.BeginInvoke(delegate ()
|
||||
{
|
||||
lblCurrencyAmount.Text = _apiService.CurrentUser.CurrencyAmount.ToString("N0");
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
lblCurrencyAmount.Text = _apiService.CurrentUser.CurrencyAmount.ToString("N0");
|
||||
Invoke(delegate () { lblCurrencyAmount.Text = _apiService.CurrentUser.CurrencyAmount.ToString("N0"); });
|
||||
}
|
||||
}
|
||||
|
||||
@ -718,9 +885,9 @@ namespace qtc_net_client_2
|
||||
await _gatewayService.StartAsync();
|
||||
|
||||
if (_gatewayService.HubConnection != null && _gatewayService.HubConnection.State == Microsoft.AspNetCore.SignalR.Client.HubConnectionState.Connected)
|
||||
{ BeginInvoke(delegate () { Enabled = true; }); return; }
|
||||
{ BeginInvoke(delegate () { tbcMain.Enabled = true; lblConnectionLost.Visible = false; }); return; }
|
||||
|
||||
ConnectionClosed frmConnectionClosed = new ConnectionClosed(error);
|
||||
ConnectionClosed frmConnectionClosed = new ConnectionClosed();
|
||||
var result = frmConnectionClosed.ShowDialog();
|
||||
|
||||
if (result == DialogResult.OK)
|
||||
@ -728,19 +895,20 @@ namespace qtc_net_client_2
|
||||
// tell the gateway service to attempt reconnection
|
||||
Reconnect:
|
||||
if (_gatewayService.HubConnection != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _gatewayService.StopAsync();
|
||||
await _gatewayService.StartAsync();
|
||||
|
||||
if (_gatewayService.HubConnection.State == Microsoft.AspNetCore.SignalR.Client.HubConnectionState.Connected)
|
||||
BeginInvoke(delegate () { Enabled = true; });
|
||||
{
|
||||
Invoke(delegate () { tbcMain.Enabled = true; lblConnectionLost.Visible = false; });
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
else
|
||||
{
|
||||
// reshow the dialog
|
||||
frmConnectionClosed.Reason = ex.Message;
|
||||
frmConnectionClosed.StatusLabel.Text = "Couldn't Reconnect. The Server Could Be Down.";
|
||||
var result1 = frmConnectionClosed.ShowDialog();
|
||||
|
||||
if (result1 == DialogResult.OK) goto Reconnect;
|
||||
else Environment.Exit(0);
|
||||
}
|
||||
@ -749,8 +917,47 @@ namespace qtc_net_client_2
|
||||
else Environment.Exit(0);
|
||||
}
|
||||
|
||||
private void _gatewayService_OnServerReconnecting(object? sender, EventArgs e) => BeginInvoke(delegate () { Enabled = false; });
|
||||
private void _gatewayService_OnServerReconnected(object? sender, EventArgs e) => BeginInvoke(delegate () { Enabled = true; });
|
||||
private void _gatewayService_OnServerReconnecting(object? sender, EventArgs e)
|
||||
{
|
||||
var args = (ServerConnectionReconnectingEventArgs)e;
|
||||
|
||||
if (args.Error == null)
|
||||
LoggingService.LogString("Server Requested Reconnect. Reconnecting...");
|
||||
else
|
||||
LoggingService.LogString($"SignalR Reconnecting Due To An Error.\n{args.Error.Message}\n{args.Error.StackTrace}");
|
||||
|
||||
if (IsHandleCreated && !IsDisposed)
|
||||
{
|
||||
Invoke(delegate ()
|
||||
{
|
||||
tbcMain.Enabled = false;
|
||||
lblConnectionLost.Visible = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async void _gatewayService_OnServerReconnected(object? sender, EventArgs e)
|
||||
{
|
||||
LoggingService.LogString("SignalR Reconnected");
|
||||
|
||||
if (IsHandleCreated && !IsDisposed)
|
||||
{
|
||||
Invoke(delegate ()
|
||||
{
|
||||
tbcMain.Enabled = true;
|
||||
lblConnectionLost.Visible = false;
|
||||
});
|
||||
}
|
||||
|
||||
// ensure status is set to whatever the current user was set to
|
||||
try
|
||||
{
|
||||
await _gatewayService.UpdateStatus(_apiService.CurrentUser.Status);
|
||||
} catch (InvalidOperationException)
|
||||
{
|
||||
LoggingService.LogString("Could Not Set Status Back To Online");
|
||||
}
|
||||
}
|
||||
|
||||
private async void _gatewayService_OnServerConfigReceived(object? sender, EventArgs e)
|
||||
{
|
||||
@ -759,8 +966,11 @@ namespace qtc_net_client_2
|
||||
LoggingService.LogString($"Server Config Received");
|
||||
LoggingService.LogModel(args.ServerConfig);
|
||||
|
||||
if (_serverConfig != null) return; // only set server config upon client restart, not during reconnect (preventing log spam)
|
||||
|
||||
if (args.ServerConfig != null)
|
||||
{
|
||||
_serverConfig = args.ServerConfig;
|
||||
if (args.ServerConfig.IsDown)
|
||||
{
|
||||
LoggingService.LogString("Server Is Marked As Down");
|
||||
@ -796,6 +1006,23 @@ namespace qtc_net_client_2
|
||||
}
|
||||
}
|
||||
|
||||
private async void _gatewayService_OnUserForceLogout(object? sender, EventArgs e)
|
||||
{
|
||||
MessageBox.Show("Connection To Server Lost. You Were Logged Out.\nTry Signing In Again.\nThe Application Will Now Close.", "oops.", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
|
||||
await _gatewayService.StopAsync();
|
||||
|
||||
if (File.Exists("./session.token")) File.Delete("./session.token");
|
||||
|
||||
Environment.Exit(0); // dont want the user to try and make a new account right away
|
||||
}
|
||||
|
||||
private void _apiService_OnCurrentUserUpdate(object? sender, EventArgs e)
|
||||
{
|
||||
lblWelcome.Text = $"Welcome, {_apiService.CurrentUser.Username}";
|
||||
RefreshCurrencyCounter();
|
||||
}
|
||||
|
||||
private async void _gatewayService_OnRefreshContactsListReceived(object? sender, EventArgs e) => await RefreshContactsList();
|
||||
private async void _gatewayService_OnRefreshRoomListReceived(object? sender, EventArgs e) => await RefreshRoomsList();
|
||||
private async void _gatewayService_OnRefreshUserListReceived(object? sender, EventArgs e) => await RefreshUsers();
|
||||
|
@ -128,7 +128,7 @@
|
||||
AAEAAAD/////AQAAAAAAAAAMAgAAAEZTeXN0ZW0uV2luZG93cy5Gb3JtcywgQ3VsdHVyZT1uZXV0cmFs
|
||||
LCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAAAmU3lzdGVtLldpbmRvd3MuRm9ybXMu
|
||||
SW1hZ2VMaXN0U3RyZWFtZXIBAAAABERhdGEHAgIAAAAJAwAAAA8DAAAA0A0AAAJNU0Z0AUkBTAMBAQAB
|
||||
4AEAAeABAAEgAQABIAEABP8BIQEACP8BQgFNATYHAAE2AwABKAMAAYADAAEgAwABAQEAASAGAAFAEgAD
|
||||
mAEBAZgBAQEgAQABIAEABP8BIQEACP8BQgFNATYHAAE2AwABKAMAAYADAAEgAwABAQEAASAGAAFAEgAD
|
||||
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
|
||||
@ -196,90 +196,88 @@
|
||||
<value>
|
||||
AAEAAAD/////AQAAAAAAAAAMAgAAAEZTeXN0ZW0uV2luZG93cy5Gb3JtcywgQ3VsdHVyZT1uZXV0cmFs
|
||||
LCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAAAmU3lzdGVtLldpbmRvd3MuRm9ybXMu
|
||||
SW1hZ2VMaXN0U3RyZWFtZXIBAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAGhQAAAJNU0Z0AUkBTAIBAQQB
|
||||
AAGYAQABmAEAARABAAEQAQAE/wEhAQAI/wFCAU0BNgcAATYDAAEoAwABQAMAASADAAEBAQABIAYAASD/
|
||||
SW1hZ2VMaXN0U3RyZWFtZXIBAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAohMAAAJNU0Z0AUkBTAIBAQQB
|
||||
AAFQAQEBUAEBARABAAEQAQAE/wEhAQAI/wFCAU0BNgcAATYDAAEoAwABQAMAASADAAEBAQABIAYAASD/
|
||||
AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AC4AAwYBBwM0AVQDUQGiA14B0gNaAekDYAHoA10B
|
||||
0QNQAZ8DMQFNAwUBBhgAAwYBBwM0AVQDUQGiA14B0gNaAekDYAHoA10B0QNQAZ8DMQFNAwUBBhgAAwYB
|
||||
BwM0AVQDUQGiA14B0gNaAekDYAHoA10B0QNQAZ8DMQFNAwUBBhgAAwYBBwM0AVQDUQGiA14B0gNaAekD
|
||||
YAHoA10B0QNQAZ8DMQFNAwUBBhQAAyABLQNUAasDWwHkA0wB9QMkAfsDNwH+AzcB/gMkAfsDUwH0A2IB
|
||||
4QNRAaEDHgEqEAADIAEtA1QBqwNbAeQBRgFYAUYB9QEhAVMBIQH7ARMBUwETAf4BEwFTARMB/gEhAVMB
|
||||
IQH7AU8BUwFPAfQDYgHhA1EBoQMeASoQAAMgAS0DVAGrA1sB5AFGAlgB9QEhAlMB+wETAlMB/gETAlMB
|
||||
/gEhAlMB+wFPAlMB9ANiAeEDUQGhAx4BKhAAAyABLQNUAasDWwHkAkYBWAH1AiEBUwH7AhMBUwH+AhMB
|
||||
UwH+AiEBUwH7Ak8BUwH0A2IB4QNRAaEDHgEqDAADGwElA1gBvQNaAfIDOwH+AzAB/wM5Af8DPAH/AzYB
|
||||
/wMqAf8DJAH/A0AB/QNZAfADVgGyAxoBIwgAAxsBJQNYAb0BVwFaAVcB8gETAVsBEwH+AQABVwEAAf8B
|
||||
AAFnAQAB/wEAAWwBAAH/AQABYQEAAf8BAAFMAQAB/wEAAUABAAH/ASYBQAEmAf0BVAFeAVQB8ANWAbIB
|
||||
GQEaARkBIwgAAxsBJQNYAb0BVwJaAfIBEwJbAf4BAAJXAf8BAAJnAf8BAAJsAf8BAAJhAf8BAAJMAf8B
|
||||
AAJAAf8BJgJAAf0BVAJeAfADVgGyARkCGgEjCAADGwElA1gBvQJXAVoB8gITAVsB/gIAAVcB/wIAAWcB
|
||||
/wIAAWwB/wIAAWEB/wIAAUwB/wIAAUAB/wImAUAB/QJUAV4B8ANWAbICGQEaASMEAAMDAQQDUgGlA18B
|
||||
8wNJAf8DVQH/A2UB/wNxAf8DdQH/A3EB/wNkAf8DTAH/AzEB/wM3Af4DXQHuA1ABmgMDAQQDAwEEAVIB
|
||||
UwFSAaUBUQFvAVEB8wEAAYIBAAH/AQABmQEAAf8BAAG2AQAB/wEAAcwBAAH/AQAB0wEAAf8BAAHLAQAB
|
||||
/wEAAbMBAAH/AQABiAEAAf8BAAFXAQAB/wETAVMBEwH+AVoBYQFaAe4DUAGaAwMBBAMDAQQBUgJTAaUB
|
||||
UQJvAfMBAAKCAf8BAAKZAf8BAAK2Af8BAALMAf8BAALTAf8BAALLAf8BAAKzAf8BAAKIAf8BAAJXAf8B
|
||||
EwJTAf4BWgJhAe4DUAGaAwMBBAMDAQQCUgFTAaUCUQFvAfMCAAGCAf8CAAGZAf8CAAG2Af8CAAHMAf8C
|
||||
AAHTAf8CAAHLAf8CAAGzAf8CAAGIAf8CAAFXAf8CEwFTAf4CWgFhAe4DUAGaAwMBBAMtAUQDYAHoA3YB
|
||||
/gNuAf8DewH/A4UB/wOKAf8DjAH/A4oB/wOFAf8DdgH/A1cB/wMyAf8DQAH9A14B3QMqAT8DLQFEAWAB
|
||||
aQFgAegBEwGOARMB/gEAAcYBAAH/AQAB3AEAAf8BAAHuAQAB/wEAAfgBAAH/AQAB+wEAAf8BAAH5AQAB
|
||||
/wEAAe8BAAH/AQAB1AEAAf8BAAGcAQAB/wEAAVoBAAH/ASYBQAEmAf0DXgHdAyoBPwMtAUQBYAJpAegB
|
||||
EwKOAf4BAALGAf8BAALcAf8BAALuAf8BAAL4Af8BAAL7Af8BAAL5Af8BAALvAf8BAALUAf8BAAKcAf8B
|
||||
AAJaAf8BJgJAAf0DXgHdAyoBPwMtAUQCYAFpAegCEwGOAf4CAAHGAf8CAAHcAf8CAAHuAf8CAAH4Af8C
|
||||
AAH7Af8CAAH5Af8CAAHvAf8CAAHUAf8CAAGcAf8CAAFaAf8CJgFAAf0DXgHdAyoBPwNOAZUDdwH4A38B
|
||||
/wOFAf8DigH/A40B/wOOAf8DjgH/A44B/wONAf8DiQH/A3cB/wNNAf8DJQH/A1oB8gNKAYsDTgGVAT0B
|
||||
kAE9AfgBAAHlAQAB/wEAAe8BAAH/AQAB+AEAAf8BAAH9AQAB/wEAAf8BAAH/AQAB/wEAAf8BAAH/AQAB
|
||||
/wEAAf4BAAH/AQAB9gEAAf8BAAHVAQAB/wEAAYsBAAH/AQABQQEAAf8BVwFaAVcB8gNKAYsDTgGVAT0C
|
||||
kAH4AQAC5QH/AQAC7wH/AQAC+AH/AQAC/QH/AQAD/wEAA/8BAAP/AQAC/gH/AQAC9gH/AQAC1QH/AQAC
|
||||
iwH/AQACQQH/AVcCWgHyA0oBiwNOAZUCPQGQAfgCAAHlAf8CAAHvAf8CAAH4Af8CAAH9Af8CAAL/AgAC
|
||||
/wIAAv8CAAH+Af8CAAH2Af8CAAHVAf8CAAGLAf8CAAFBAf8CVwFaAfIDSgGLA18B0wN+AfwDkwH/A44B
|
||||
/wONAf8DjgH/A44B/wOOAf8DjgH/A44B/wONAf8DhQH/A2cB/wM0Af8DQQH5A1oBxAFbAV8BWwHTASsB
|
||||
ugErAfwBDgH7AQ4B/wEDAf0BAwH/AQAB/gEAAf8BAAH/AQAB/wEAAf8BAAH/AQAB/wEAAf8BAAH/AQAB
|
||||
/wEAAf8BAAH/AQAB/QEAAf8BAAHvAQAB/wEAAbkBAAH/AQABXQEAAf8BOAFBATgB+QNaAcQBWwJfAdMB
|
||||
KwK6AfwBDgL7Af8BAwL9Af8BAAL+Af8BAAP/AQAD/wEAA/8BAAP/AQAD/wEAAv0B/wEAAu8B/wEAArkB
|
||||
/wEAAl0B/wE4AkEB+QNaAcQCWwFfAdMCKwG6AfwCDgH7Af8CAwH9Af8CAAH+Af8CAAL/AgAC/wIAAv8C
|
||||
AAL/AgAC/wIAAf0B/wIAAe8B/wIAAbkB/wIAAV0B/wI4AUEB+QNaAcQDbgH1A4AB/gOfAf8DkwH/A48B
|
||||
/wOOAf8DjgH/A44B/wOOAf8DjgH/A44B/wOLAf8DdwH/A0gB/wNAAf0DYgHhAUsBgwFLAfUBNwHZATcB
|
||||
/gEnAf8BJwH/AQsB/wELAf8BAQH/AQEB/wEAAf8BAAH/AQAB/wEAAf8BAAH/AQAB/wEAAf8BAAH/AQAB
|
||||
/wEAAf8BAAH/AQAB/wEAAfkBAAH/AQAB1gEAAf8BAAGBAQAB/wEmAUABJgH9A2IB4QFLAoMB9QE3AtkB
|
||||
/gEnA/8BCwP/AQED/wEAA/8BAAP/AQAD/wEAA/8BAAP/AQAD/wEAAvkB/wEAAtYB/wEAAoEB/wEmAkAB
|
||||
/QNiAeECSwGDAfUCNwHZAf4CJwL/AgsC/wIBAv8CAAL/AgAC/wIAAv8CAAL/AgAC/wIAAv8CAAH5Af8C
|
||||
AAHWAf8CAAGBAf8CJgFAAf0DYgHhA3QB9gOIAf4DqwH/A5kB/wOQAf8DjgH/A44B/wOOAf8DjgH/A44B
|
||||
/wOOAf8DjQH/A38B/wNVAf8DQAH9A14B4gFIAYcBSAH2AVoB2QFaAf4BQgH/AUIB/wEZAf8BGQH/AQQB
|
||||
/wEEAf8BAAH/AQAB/wEAAf8BAAH/AQAB/wEAAf8BAAH/AQAB/wEAAf8BAAH/AQAB/wEAAf8BAAH9AQAB
|
||||
/wEAAeQBAAH/AQABmAEAAf8BJgFAASYB/QNeAeIBSAKHAfYBWgLZAf4BQgP/ARkD/wEEA/8BAAP/AQAD
|
||||
/wEAA/8BAAP/AQAD/wEAA/8BAAL9Af8BAALkAf8BAAKYAf8BJgJAAf0DXgHiAkgBhwH2AloB2QH+AkIC
|
||||
/wIZAv8CBAL/AgAC/wIAAv8CAAL/AgAC/wIAAv8CAAL/AgAB/QH/AgAB5AH/AgABmAH/AiYBQAH9A14B
|
||||
4gNhAdYDiQH8A7gB/wOjAf8DkwH/A44B/wOOAf8DjgH/A44B/wOOAf8DjgH/A40B/wOCAf8DXAH/A00B
|
||||
+gNaAccBXAFhAVwB1gFkAb4BZAH8AV8B/wFfAf8BLwH/AS8B/wEMAf8BDAH/AQEB/wEBAf8BAAH/AQAB
|
||||
/wEAAf8BAAH/AQAB/wEAAf8BAAH/AQAB/wEAAf8BAAH/AQAB/gEAAf8BAAHqAQAB/wEAAaUBAAH/AScB
|
||||
TQEnAfoDWgHHAVwCYQHWAWQCvgH8AV8D/wEvA/8BDAP/AQED/wEAA/8BAAP/AQAD/wEAA/8BAAP/AQAC
|
||||
/gH/AQAC6gH/AQACpQH/AScCTQH6A1oBxwJcAWEB1gJkAb4B/AJfAv8CLwL/AgwC/wIBAv8CAAL/AgAC
|
||||
/wIAAv8CAAL/AgAC/wIAAf4B/wIAAeoB/wIAAaUB/wInAU0B+gNaAccDUAGaA40B+QPFAf8DsgH/A5wB
|
||||
/wORAf8DjgH/A44B/wOOAf8DjgH/A48B/wOOAf8DgwH/A2AB/wNaAfIDTAGQA1ABmgFqAaEBagH5AXwB
|
||||
/wF8Af8BUQH/AVEB/wEfAf8BHwH/AQcB/wEHAf8BAQH/AQEB/wEAAf8BAAH/AQAB/wEAAf8BAAH/AQAB
|
||||
/wECAf8BAgH/AQIB/gECAf8BAAHrAQAB/wEAAa0BAAH/AVcBawFXAfIDTAGQA1ABmgFqAqEB+QF8A/8B
|
||||
UQP/AR8D/wEHA/8BAQP/AQAD/wEAA/8BAAP/AQID/wECAv4B/wEAAusB/wEAAq0B/wFXAmsB8gNMAZAD
|
||||
UAGaAmoBoQH5AnwC/wJRAv8CHwL/AgcC/wIBAv8CAAL/AgAC/wIAAv8CAgL/AgIB/gH/AgAB6wH/AgAB
|
||||
rQH/AlcBawHyA0wBkAMvAUkDbAHrA6oB/gPGAf8DrgH/A5wB/wOTAf8DkAH/A48B/wOQAf8DkwH/A5MB
|
||||
/wOFAf8DUwH9A2AB4AMtAUUDLwFJA2wB6wGAAdkBgAH+AX8B/wF/Af8BSQH/AUkB/wEfAf8BHwH/AQwB
|
||||
/wEMAf8BBQH/AQUB/wEDAf8BAwH/AQUB/wEFAf8BCgH/AQoB/wEKAf4BCgH/AQEB7QEBAf8BJgG2ASYB
|
||||
/QFgAWYBYAHgAy0BRQMvAUkDbAHrAYAC2QH+AX8D/wFJA/8BHwP/AQwD/wEFA/8BAwP/AQUD/wEKA/8B
|
||||
CgL+Af8BAQLtAf8BJgK2Af0BYAJmAeADLQFFAy8BSQNsAesCgAHZAf4CfwL/AkkC/wIfAv8CDAL/AgUC
|
||||
/wIDAv8CBQL/AgoC/wIKAf4B/wIBAe0B/wImAbYB/QJgAWYB4AMtAUUDAwEEA1YBrgN8AfUD2QH/A8sB
|
||||
/wO3Af8DpwH/A50B/wOaAf8DnAH/A58B/wObAf8DiQH/A2gB8ANSAaMDAwEEAwMBBANWAa4BbwGDAW8B
|
||||
9QGoAf8BqAH/AYkB/wGJAf8BXAH/AVwB/wE3Af8BNwH/ASIB/wEiAf8BGwH/ARsB/wEfAf8BHwH/ASYB
|
||||
/wEmAf8BHQH/AR0B/wEFAfMBBQH/AVQBawFUAfADUgGjAwMBBAMDAQQDVgGuAW8CgwH1AagD/wGJA/8B
|
||||
XAP/ATcD/wEiA/8BGwP/AR8D/wEmA/8BHQP/AQUC8wH/AVQCawHwA1IBowMDAQQDAwEEA1YBrgJvAYMB
|
||||
9QKoAv8CiQL/AlwC/wI3Av8CIgL/AhsC/wIfAv8CJgL/Ah0C/wIFAfMB/wJUAWsB8ANSAaMDAwEEBAAD
|
||||
HAEnA10BxwN9AfYDuQH+A9cB/wPMAf8DwgH/A7sB/wO3Af8DsQH/A4AB/gNpAfQDWQG8AxsBJggAAxwB
|
||||
JwNdAccBdwGHAXcB9gGRAdkBkQH+AaUB/wGlAf8BiwH/AYsB/wF0Af8BdAH/AWYB/wFmAf8BXAH/AVwB
|
||||
/wFOAf8BTgH/AUMB2QFDAf4BUgF9AVIB9AFXAVkBVwG8AxsBJggAAxwBJwNdAccBdwKHAfYBkQLZAf4B
|
||||
pQP/AYsD/wF0A/8BZgP/AVwD/wFOA/8BQwLZAf4BUgJ9AfQBVwJZAbwDGwEmCAADHAEnA10BxwJ3AYcB
|
||||
9gKRAdkB/gKlAv8CiwL/AnQC/wJmAv8CXAL/Ak4C/wJDAdkB/gJSAX0B9AJXAVkBvAMbASYMAAMhATAD
|
||||
WQG2A2wB7gOfAfoDvgH9A9QB/wPMAf8DvgH9A4kB+QNsAesDVQGsAx8BLBAAAyEBMANZAbYBagFuAWoB
|
||||
7gGHAakBhwH6Aa4BxgGuAf0BnwH/AZ8B/wGMAf8BjAH/AWMBxgFjAf0BaAGhAWgB+QFhAWwBYQHrA1UB
|
||||
rAMfASwQAAMhATADWQG2AWoCbgHuAYcCqQH6Aa4CxgH9AZ8D/wGMA/8BYwLGAf0BaAKhAfkBYQJsAesD
|
||||
VQGsAx8BLBAAAyEBMANZAbYCagFuAe4ChwGpAfoCrgHGAf0CnwL/AowC/wJjAcYB/QJoAaEB+QJhAWwB
|
||||
6wNVAawDHwEsFAADBgEHAzYBWANVAawDZgHlA60B/AOYAfsDZQHiA1MBpwMzAVEDBgEHGAADBgEHAzYB
|
||||
WANVAawDZgHlAX4BvgF+AfwBdwGyAXcB+wNlAeIDUwGnAzMBUQMGAQcYAAMGAQcDNgFYA1UBrANmAeUB
|
||||
fgK+AfwBdwKyAfsDZQHiA1MBpwMzAVEDBgEHGAADBgEHAzYBWANVAawDZgHlAn4BvgH8AncBsgH7A2UB
|
||||
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
|
||||
AAJXAf8BAAJnAf8BAAJsAf8BAAJhAf8BAAJMAf8BAAJAAf8DQAH9A14B8ANWAbIBGQIaASMIAAMbASUD
|
||||
WAG9A1oB8gIqAXIB/gIAAVcB/wIAAWcB/wIAAWwB/wIAAWEB/wIAAUwB/wIAAUAB/wNAAf0DXgHwA1YB
|
||||
sgIZARoBIwQAAwMBBANSAaUDYAHzA0kB/wNVAf8DZQH/A3EB/wN1Af8DcQH/A2QB/wNMAf8DMQH/A04B
|
||||
/gNiAe4DUAGaAwMBBAMDAQQBUgFTAVIBpQFgAW8BYAHzAQABggEAAf8BAAGZAQAB/wEAAbYBAAH/AQAB
|
||||
zAEAAf8BAAHTAQAB/wEAAcsBAAH/AQABswEAAf8BAAGIAQAB/wEAAVcBAAH/ASoBagEqAf4DYgHuA1AB
|
||||
mgMDAQQDAwEEAVICUwGlAWACbwHzAQACggH/AQACmQH/AQACtgH/AQACzAH/AQAC0wH/AQACywH/AQAC
|
||||
swH/AQACiAH/AQACVwH/ASoCagH+A2IB7gNQAZoDAwEEAwMBBAJSAVMBpQJgAW8B8wIAAYIB/wIAAZkB
|
||||
/wIAAbYB/wIAAcwB/wIAAdMB/wIAAcsB/wIAAbMB/wIAAYgB/wIAAVcB/wIqAWoB/gNiAe4DUAGaAwMB
|
||||
BAMtAUQDYAHoA4AB/gNuAf8DewH/A4UB/wOKAf8DjAH/A4oB/wOFAf8DdgH/A1cB/wMyAf8DQAH9A14B
|
||||
3QMqAT8DLQFEAWABaQFgAegBKgGAASoB/gEAAcYBAAH/AQAB3AEAAf8BAAHuAQAB/wEAAfgBAAH/AQAB
|
||||
+wEAAf8BAAH5AQAB/wEAAe8BAAH/AQAB1AEAAf8BAAGcAQAB/wEAAVoBAAH/A0AB/QNeAd0DKgE/Ay0B
|
||||
RAFgAmkB6AEqAoAB/gEAAsYB/wEAAtwB/wEAAu4B/wEAAvgB/wEAAvsB/wEAAvkB/wEAAu8B/wEAAtQB
|
||||
/wEAApwB/wEAAloB/wNAAf0DXgHdAyoBPwMtAUQCYAFpAegCKgGAAf4CAAHGAf8CAAHcAf8CAAHuAf8C
|
||||
AAH4Af8CAAH7Af8CAAH5Af8CAAHvAf8CAAHUAf8CAAGcAf8CAAFaAf8DQAH9A14B3QMqAT8DTgGVA3cB
|
||||
+AN/Af8DhQH/A4oB/wONAf8DjgH/A44B/wOOAf8DjQH/A4kB/wN3Af8DTQH/AyUB/wNaAfIDSgGLA04B
|
||||
lQFcAXwBXAH4AQAB5QEAAf8BAAHvAQAB/wEAAfgBAAH/AQAB/QEAAf8BAAH/AQAB/wEAAf8BAAH/AQAB
|
||||
/wEAAf8BAAH+AQAB/wEAAfYBAAH/AQAB1QEAAf8BAAGLAQAB/wEAAUEBAAH/A1oB8gNKAYsDTgGVAVwC
|
||||
fAH4AQAC5QH/AQAC7wH/AQAC+AH/AQAC/QH/AQAD/wEAA/8BAAP/AQAC/gH/AQAC9gH/AQAC1QH/AQAC
|
||||
iwH/AQACQQH/A1oB8gNKAYsDTgGVAlwBfAH4AgAB5QH/AgAB7wH/AgAB+AH/AgAB/QH/AgAC/wIAAv8C
|
||||
AAL/AgAB/gH/AgAB9gH/AgAB1QH/AgABiwH/AgABQQH/A1oB8gNKAYsDXwHTA34B/AOTAf8DjgH/A40B
|
||||
/wOOAf8DjgH/A44B/wOOAf8DjgH/A40B/wOFAf8DZwH/AzQB/wNBAfkDWgHEAVsBXwFbAdMBKwF+ASsB
|
||||
/AEOAfsBDgH/AQMB/QEDAf8BAAH+AQAB/wEAAf8BAAH/AQAB/wEAAf8BAAH/AQAB/wEAAf8BAAH/AQAB
|
||||
/wEAAf8BAAH9AQAB/wEAAe8BAAH/AQABuQEAAf8BAAFdAQAB/wNBAfkDWgHEAVsCXwHTASsCfgH8AQ4C
|
||||
+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
|
||||
/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
|
||||
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
|
||||
/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
|
||||
AAL/AgAC/wIAAf0B/wIAAeQB/wIAAZgB/wNAAf0DXgHiA2EB1gN+AfwDuAH/A6MB/wOTAf8DjgH/A44B
|
||||
/wOOAf8DjgH/A44B/wOOAf8DjQH/A4IB/wNcAf8DTQH6A1oBxwFcAWEBXAHWAWQBgwFkAfwBXwH/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
|
||||
/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
|
||||
/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
|
||||
fwP/AUkD/wEfA/8BDAP/AQUD/wEDA/8BBQP/AQoD/wEKAv4B/wEBAu0B/wFAArYB/QFgAmYB4AMtAUUD
|
||||
LwFJA2wB6wKAAasB/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
|
||||
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
|
||||
4gNTAacDMwFRAwYBBwwAAUIBTQE+BwABPgMAASgDAAFAAwABIAMAAQEBAAEBBgABARYAA/+BAAHgAQcB
|
||||
4AEHAeABBwHgAQcBwAEDAcABAwHAAQMBwAEDAYABAQGAAQEBgAEBAYABAVAAAYABAQGAAQEBgAEBAYAB
|
||||
AQHAAQMBwAEDAcABAwHAAQMB4AEHAeABBwHgAQcB4AEHCw==
|
||||
@ -292,168 +290,171 @@
|
||||
<value>
|
||||
AAEAAAD/////AQAAAAAAAAAMAgAAAEZTeXN0ZW0uV2luZG93cy5Gb3JtcywgQ3VsdHVyZT1uZXV0cmFs
|
||||
LCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAAAmU3lzdGVtLldpbmRvd3MuRm9ybXMu
|
||||
SW1hZ2VMaXN0U3RyZWFtZXIBAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAPCUAAAJNU0Z0AUkBTAIBAQMB
|
||||
AAFYAQEBWAEBASABAAEgAQAE/wEhAQAI/wFCAU0BNgcAATYDAAEoAwABgAMAASADAAEBAQABIAYAAUB6
|
||||
SW1hZ2VMaXN0U3RyZWFtZXIBAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAKCUAAAJNU0Z0AUkBTAIBAQMB
|
||||
AAEQAQIBEAECASABAAEgAQAE/wEhAQAI/wFCAU0BNgcAATYDAAEoAwABgAMAASADAAEBAQABIAYAAUB6
|
||||
AANcAecBCAEKAQAB/wMqAUAMAAMqAUADNgFXAz8BbAM/AWwDPwFsAz8BbAM/AWwDPwFsAz8BbAM/AWwD
|
||||
PwFsAz8BbAM/AWwDPwFsAz8BbAM/AWwDPwFsAz8BbAI7AToBYgMzAVEDGAEhVAADZAGiA28BwCAAA2YB
|
||||
pgNtAbzwAAMhATADRgGAFAABFQEfAQQB/wENARUBAAH/AQgBCgEAAf8BCAEKAQAB/wwAA0QBegNTAacC
|
||||
PwFsAz8BbAM/AWwDPwFsAz8BbAM/AWwDPwFsAz8BbAI7AToBYgMzAVEDGAEhVAADUwGiA1sBwCAAA1QB
|
||||
pgNZAbzwAAMhATADRgGAFAABFQEfAQQB/wENARUBAAH/AQgBCgEAAf8BCAEKAQAB/wwAA0QBegNTAacC
|
||||
YQFdAc8CYQFdAc8CYQFdAc8CYQFdAc8CYQFdAc8CYQFdAc8CYQFdAc8CYQFdAc8CYQFdAc8CYQFdAc8C
|
||||
YQFdAc8CYQFdAc8CYQFdAc8CYQFdAc8CYQFdAc8CYAFdAc4DWQG7AlABTwGbAyoBQFQAA3QB0AN7Ae4g
|
||||
AAN1AdQDegHp5AADWgG/AQgBCgEAAf8BCAEKAQAB/wEIAQoBAAH/AQgBCgEAAf8BCAEKAQAB/wEIAQoB
|
||||
YQFdAc8CYQFdAc8CYQFdAc8CYQFdAc8CYQFdAc8CYAFdAc4DWQG7AlABTwGbAyoBQFQAA18B0ANiAe4g
|
||||
AANhAdQDYwHp5AADWgG/AQgBCgEAAf8BCAEKAQAB/wEIAQoBAAH/AQgBCgEAAf8BCAEKAQAB/wEIAQoB
|
||||
AAH/AQgBCgEAAf8DWgG/A1oBvwFDAXQBBwH/AUcBdwEMAf8BJQFHAQAB/wEOARkBAAH/DAACSwFKAYoC
|
||||
WgFYAb0CZwFdAeoCZwFdAeoCZwFdAeoCZwFdAeoCZwFdAeoCZwFdAeoCZwFdAeoCZwFdAeoCZwFdAeoC
|
||||
ZwFdAeoCZwFdAeoCZwFdAeoCZwFdAeoCZwFdAeoCZwFdAeoCYwFaAekCXwFbAdMDVQGvAy4BSFQAA3QB
|
||||
0AN7Ae4gAAN1AdQDegHp4AABCAEKAQAB/wEQAR4BAAH/ASEBQQEAAf8BJwFLAQAB/wEmAUoBAAH/ASEB
|
||||
ZwFdAeoCZwFdAeoCZwFdAeoCZwFdAeoCZwFdAeoCZwFdAeoCYwFaAekCXwFbAdMDVQGvAy4BSFQAA18B
|
||||
0ANiAe4gAANhAdQDYwHp4AABCAEKAQAB/wEQAR4BAAH/ASEBQQEAAf8BJwFLAQAB/wEmAUoBAAH/ASEB
|
||||
QQEAAf8BEAEeAQAB/wEIAQoBAAH/AQgBCgEAAf8BCAEKAQAB/wEpAU4BAAH/AVoBlgEQAf8BWgGcARAB
|
||||
/wFzAbYBJgH/ARgBLgEAAf8MAANJAYYCWgFYAbcCZQFgAeMCZQFgAeMCZQFgAeMCZQFgAeMCagFhAeYC
|
||||
agFeAe0BcwFoAVMB9AGsAXcBKwH8Af8BeAEAAv8BeAEAAf8BbwFuAVEB9QJqAWEB5gJlAWAB4wJlAWAB
|
||||
4wJlAWAB4wJlAV4B4gJeAVsBzQJVAVMBqgIuAS0BRlQAA3QB0AN7Ae4gAAN1AdQDegHp3AABCAEKAQAB
|
||||
/wE9AXEBAgH/AUwBhgEHAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBEAH/AUwB
|
||||
fwEPAf8BOwFnAQgB/wEhATQBCAH/AVMBjgELAf8BWgGcARAB/wFyAbMBJwH/AVMBgQEbAf8QAAMrAUED
|
||||
NgFZAkABPwFuAkABPwFuAkABPwFuAkABPwFuA0QBewJRAVABnwJdAVsBxQFlAmIB7gH/AXgBAAL/AXgB
|
||||
AAH/Al8BXQHJA0UBfAJAAT8BbgJAAT8BbgJAAT8BbgM/AW0DOwFjAzMBUgMZASJUAAN0AdADewHuIAAD
|
||||
dQHUA3oB6dgAARUBKQEAAf8BSgGEAQQB/wFSAYwBCAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIB
|
||||
jAEIAf8BUgGMARAB/wFSAYwBEAH/AVIBjAEQAf8BWgGUARAB/wFWAZABDAH/AVoBmgEQAf8BWgGcARAB
|
||||
/wFyAakBMAH/AQgBCgEAAf8BCAEKAQAB/wwAAwwBEAMRARYDFQEcAxUBHAMVARwDFQEcAyEBMAI+AT0B
|
||||
aQJTAVIBpQJmAV8B5QH/AXgBAAL/AXgBAAH/AlUBUwGqAyIBMQMVARwDFQEcAxUBHAMUARsDEwEZAxAB
|
||||
FQMHAQlUAAN0AdADewHuIAADdQHUA3oB6dQAARYBJwECAf8BSQGAAQcB/wFSAYwBCAH/AVIBjAEIAf8B
|
||||
UgGMAQgB/wFSAYwBCAH/AVIBjAEIAf8BUgGMAQsB/wFSAYwBEAH/AVIBjAEQAf8BWAGSARAB/wFaAZQB
|
||||
EAH/AVoBmwEQAf8BWgGcARAB/wFcAZ4BEgH/ATsBbQEDAf8BCAEKAQAB/wEIAQoBAAH/AQgBCgEAAf8I
|
||||
AAMFBAYECAEKAwgBCgMIAQoDCAEKAxcBHwI5ATgBXQNRAZ4CZQFgAeMB/wF4AQAC/wF4AQAB/wNSAaMD
|
||||
GAEhAwgBCgMIAQoDCAEKAwgBCgMHAQkDBgEHAwIBA1QAA3QB0AN7Ae4gAAN1AdQDegHp0AADXQHfAUcB
|
||||
gAEDAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEIAf8BUgGMARAB
|
||||
/wFSAYwBEAH/AVIBjAEQAf8BWgGUARAB/wFaAZQBEAH/AVoBnAEQAf8BWgGcARAB/wFaAZwBEAH/AVoB
|
||||
nAEQAf8BWgGYARAB/wEWASoBAAH/AQgBCgEAAf8BCAEKAQAB/xwAAxIBFwM1AVYDUAGaA2IB4QH/AXgB
|
||||
AAL/AXgBAAH/AlEBUAGfAxIBGHAAA3QB0AN7Ae4gAAN1AdQDegHp0AABLAFQAQAB/wFKAYwBAAH/AVIB
|
||||
jAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBDgH/AVUBkgEQAf8BWgGcARAB
|
||||
/wFaAZwBEAH/AVoBlAEQAf8BWgGcARAB/wFaAZwBEAH/AVoBnAEQAf8BWgGcARAB/wFaAZwBEAH/AVoB
|
||||
lAEYAf8BWAGSARYB/wEQAR4BAAH/AQgBCgEAAf8cAAMSARcDNQFWA1ABmgNiAeEB/wF4AQAC/wF4AQAB
|
||||
/wJRAVABnwMSARhwAAN0AdADewHuIAADdQHUA3oB6dQAA0sBjwEzAV4BAAH/AVIBjAEIAf8BUgGMAQgB
|
||||
/wFSAYwBCAH/AVIBjAEQAf8BfwHAATMB/wFfAZ4BFwH/ASABPwEAAf8BCAEKAQAB/wFSAYwBEAH/AVoB
|
||||
nAEQAf8BWgGcARAB/wFaAZwBEAH/AVoBnAEQAf8BWgGVARcB/wFaAZQBGAH/AVoBlAEYAf8BWgGUARgB
|
||||
/wEIAQoBAAH/AQgBCgEAAf8YAAMSARcDNQFWA1ABmgNiAeEB/wF4AQAC/wF4AQAB/wJRAVABnwMSARgU
|
||||
AAQBAwMBBAMGBAcBCQMHAQkDBAEFBAIEARQAAxIBFgMkAS8DJAEvAyQBLwMkAS8DJAEvAyQBLwMkAS8D
|
||||
JAEvAyQBLwN1AdkDfAHxAyQBLwMkAS8DJAEvAyQBLwMkAS8DJAEvAyQBLwMkAS8DdwHcA3sB7QMkAS8D
|
||||
JAEvAyQBLwMkAS8DJAEvAyQBLwMkAS8DJAEvAyQBLwMOARG4AAFCAXsBAAH/AVIBjAEIAf8BewHGASkB
|
||||
/wMzAVAEAAMMARABOQFrAQAB/wFaAZwBEAH/AVoBnAEQAf8BXQGXARMB/wFWAZQBDAH/AVoBnAEQAf8B
|
||||
WgGUARgB/wFaAZQBGAH/AWMBnAEYAf8BYwGlARcB/wEpAVABAAH/AQgBCgEAAf8YAAMSARcDNQFWA1AB
|
||||
mgNiAeEB/wF4AQAC/wF4AQAB/wJRAVABnwMSARgUAAQCAwkBDAMPARQDEwEaAxIBGAMKAQ0DBAEFBAEU
|
||||
AAN7AegDfwH/A38B/wN/Af8DfwH/A38B/wN/Af8DfwH/A38B/wN/Af8DfwH/A38B/wN/Af8DfwH/A38B
|
||||
/wN/Af8DfwH/A38B/wN/Af8DfwH/A38B/wN/Af8DfwH/A38B/wN/Af8DfwH/A38B/wN/Af8DfwH/A38B
|
||||
/wN/Af8DcwHPvAABCAEKAQAB/wwAARMBIwEAAf8BWgGUARAB/wFaAZwBEAH/AZQB1gFKAf8BDQERAQIB
|
||||
/wExAVoBAAH/AVoBlAESAf8BWgGUARgB/wFaAZQBGAH/AWMBnAEYAf8BYwGlARcB/wFrAaUBIQH/ARAB
|
||||
HgEAAf8YAAMSARcDNQFWA1ABmgNiAeEB/wF4AQAC/wF4AQAB/wJRAVABnwMSARgUAAMFAQYDHQEpAzAB
|
||||
SgI7ATwBZQI7ATwBZAMoATwCFQEWAR0DBgEIFAADRgFkA1wBjwNcAY8DXAGPA1wBjwNcAY8DXAGPA1wB
|
||||
jwNcAY8DXAGPA3oB6gN9AfgDXAGPA1wBjwNcAY8DXAGPA1wBjwNcAY8DXAGPA1wBjwN7AewDfAH1A1wB
|
||||
jwNcAY8DXAGPA1wBjwNcAY8DXAGPA1wBjwNcAY8DXAGPAz4BVqgAA10B3wEIAQoBAAH/AQgBCgEAAf8B
|
||||
CAEKAQAB/wEIAQoBAAH/AQgBCgEAAf8BCAEKAQAB/wMzAVADOgFgAUsBhQEHAf8BWgGUARAB/wFaAZwB
|
||||
EAH/ATkBawEAAf8DCQEMARABHgEAAf8BVAGOARIB/wFaAZQBGAH/AWMBnAEYAf8BYwGcARgB/wFjAaUB
|
||||
FwH/AXMBtAEpAf8BEAEeAQAB/xgAAxIBFwM1AVYDUAGaA2IB4QH/AXgBAAL/AXgBAAH/AlEBUAGfAxIB
|
||||
GBQAAwkBDAMzAVACTAFNAZECXQFfAckCWwFdAcoDRAF6AykBPQMMARA8AAN0AdADewHuIAADdQHUA3oB
|
||||
6cwAAQgBCgEAAf8BCAEKAQAB/wEIAQoBAAH/AQgBCgEAAf8BCAEKAQAB/wEIAQoBAAH/AQgBCgEAAf8B
|
||||
CAEKAQAB/wEIAQoBAAH/ATMBXwECAf8BWgGUARAB/wFaAZwBEAH/Aa0B5wFjAf8BEAEeAQAB/wEIAQoB
|
||||
AAH/ARQBJgEAAf8BVAGOARIB/wFiAZsBGAH/AWMBnAEYAf8BYwGlARcB/wFjAaUBFwH/AWMBnAEhAf8B
|
||||
GAEuAQAB/xgAAxIBFwM1AVYDUAGaA2IB4QH/AXgBAAL/AXgBAAH/AlEBUAGfAxIBGBQAAwkBCwMuAUcD
|
||||
SAGEAlkBXAHDAlwBXwHLA0kBhQMuAUcDDwETPAADdAHQA3sB7iAAA3UB1AN6AenIAAEIAQoBAAH/ASsB
|
||||
UgEAAf8BQQFyAQUB/wFKAYQBBgH/AUoBhAEGAf8BSgGEAQYB/wFCAXMBBgH/ASkBUAEAAf8BEAEeAQAB
|
||||
/wEfAToBAAH/AVUBjwELAf8BWgGVARAB/wFaAZwBEAH/AdYB/wGMAf8BEAEeAQAB/wEYAS4BAAH/AUIB
|
||||
eAEDAf8BWgGUARgB/wFiAZsBGAH/AWMBnAEYAf8BYwGlARcB/wFjAaUBFwH/AXMBtAEpAf8BEAEeAQAB
|
||||
/xgAAxIBFwM1AVYDUAGaA2IB4QH/AXgBAAL/AXgBAAH/AlEBUAGfAxIBGBQAAwYBCAMkATQDPAFmA1MB
|
||||
pwNYAbgCRwFIAYMDMQFNAw8BFDwAA3QB0AN7Ae4gAAN1AdQDegHpxAABKAFNAQAB/wFOAYgBBwH/AVIB
|
||||
jAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEQAf8BUgGMARAB
|
||||
/wFSAYwBEAH/AVoBlAEQAf8BWgGcARAB/wFjAaUBFwH/AUIBewEAAf8BSgGEAQYB/wFSAYwBCAH/AVoB
|
||||
mAEUAf8BWgGUARgB/wFjAZwBGAH/AWMBpQEXAf8BYwGlARcB/wFjAaUBFwH/AZQByQFNAf8EAAMQARUD
|
||||
GgEkAyEBLwMRARYEAgQBAxIBFwM1AVYDUAGaA2IB4QH/AXgBAAL/AXgBAAH/AlEBUAGfAxIBGBQAAwMB
|
||||
BAMTARkDJQE2AjsBPAFkAkEBQgFyAzMBUQMhAS8DCQEMPAADdAHQA3sB7iAAA3UB1AN6AenAAAEpAU4B
|
||||
AgH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEIAf8B
|
||||
UgGMARAB/wFSAYwBEAH/AVIBjAEQAf8BWgGUARAB/wFaAZUBEAH/AVoBnAEQAf8BWgGcARAB/wFaAZwB
|
||||
EAH/AVoBnAEQAf8BWgGUARgB/wFaAZQBGAH/AWMBnAEYAf8BYwGcARgB/wFjAaUBFwH/AWMBpQEXAf8B
|
||||
YwGlARcB/wFlAaABIQH/BAADHgErAjEBMAFMAzsBYwMiATEDBwEJAwQBBQMSARgDNgFXA1ABmgNiAeEB
|
||||
/wF4AQAC/wF4AQAB/wJRAVABnwMSARgcAAMHAQkDHAEnAyMBMgIZARoBIwMPARQDBAEFPAADdAHQA3sB
|
||||
7iAAA3UB1AN6Aem8AANGAYABTgGIAQcB/wFSAYwBCAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIB
|
||||
jAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEQAf8BUgGMARAB/wFSAYwBEAH/AVoBlAEQAf8BWgGXARAB
|
||||
/wFaAZwBEAH/AVoBnAEQAf8BWgGcARAB/wFaAZwBEAH/AVoBlAEYAf8BWgGUARgB/wFjAZwBGAH/AWMB
|
||||
oQEYAf8BYwGlARcB/wFjAaUBFwH/AXgBugEsAf8BCAEKAQAB/wQAAyQBNANFAXwCWgFYAbcDTgGUAz8B
|
||||
bQMoATsDHwEsAzkBXgNQAZoDYgHhAf8BeAEAAv8BeAEAAf8CUQFQAZ8DEgEYHAADEgEXAzwBZgNKAYkD
|
||||
QAFvAy4BRwMOARI8AAN0AdADewHuIAADdQHUA3oB6bwAATUBXgEHAf8BUgGMAQgB/wFSAYwBCAH/AVIB
|
||||
jAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEQAf8BUgGMARAB
|
||||
/wFaAZQBEAH/AVoBlAEQAf8BWgGbARAB/wFaAZwBEAH/AVoBnAEQAf8BWgGcARAB/wFaAZYBFgH/AVoB
|
||||
lAEYAf8BXQGXARgB/wFjAZwBGAH/AWMBpQEXAf8BYwGlARcB/wFwAbMBIAH/ASsBUAEEAf8IAAMnAToC
|
||||
UwFRAaIBmgFfASEB+wJlAVwB5wJcAVoBxAJDAUIBdQMxAU0CQAE/AW4CUQFQAZ8CZQFgAeMB/wF4AQAC
|
||||
/wF4AQAB/wJRAVABnwMSARgcAAMZASIDTgGVAlsBXgHNAlYBVwGyA0QBegMdASkDBgEIBAIEATAAA3QB
|
||||
0AN7Ae4gAAN1AdQDegHpvAABSgGEAQYB/wFSAYwBCAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIB
|
||||
jAEIAf8BZwGpARcB/wFSAYwBCAH/AUoBhAEGAf8BSgGEAQYB/wFSAYwBEAH/AVoBlAEQAf8BWgGXARAB
|
||||
/wFaAZwBEAH/AVoBnAEQAf8BWgGcARAB/wFaAZwBEAH/AVoBlAEYAf8BWgGUARgB/wFfAZgBGAH/AWMB
|
||||
ngEYAf8BYwGlARcB/wFrAakBHQH/ASkBUAEAAf8MAAMiATEDTgGYAm8BXAHzAmgBXgHwAmoBYQHmAloB
|
||||
VwHCAlUBUwGqA1MBpwJZAVcBvAJsAWEB6wH/AXgBAAL/AXgBAAH/AlEBUAGfAxIBGBwAAxQBGwJDAUQB
|
||||
dwJWAVkBtgJbAV4BzQJWAVgBswM/AWwDJgE4AwwBDwMCAQMIAAMCAQMDDgERAw4BEQMOAREDDgERAw4B
|
||||
EQMOAREDDgERAw4BEQMOAREDdAHTA3sB7wMOAREDDgERAw4BEQMOAREDDgERAw4BEQMOAREDDgERA3QB
|
||||
1wN7AeoDDgERAw4BEQMOAREDDgERAw4BEQMOAREDDgERAw4BEQMOAREDBAEFlAABSgGEAQYB/wFSAYwB
|
||||
CAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBCAH/AWkBpAEeAf8BLAFQAQMB/wEIAQoBAAH/ATcBYQEHAf8B
|
||||
UgGMAQ4B/wFSAYwBEAH/AX8BwQEyAf8BWwFeAVsB0wNaAb8BLwFZAQAB/wFEAXoBBQH/AVABigEIAf8B
|
||||
WgGcAQ4B/wFaAZwBEAH/AVoBnAEQAf8BTwGGARAB/wFEAXQBDAH/A1oBvxAAAhoBGQEjA0QBewJdAVsB
|
||||
ygJjAV8B2gJpAWAB6AJnAVkB7wJlAV0B7AJhAVwB1gJfAVsB2AFzAWgBUwH0Af8BeAEAAv8BeAEAAf8C
|
||||
UQFQAZ8DEgEYHAADDwETAzQBUwNNAZICXQFhAc8CXQFhAdQCUgFUAagCQQFCAXIDJgE4AxQBGwMGAQgD
|
||||
AgEDA3ABwgN/Af8DfwH/A38B/wN/Af8DfwH/A38B/wN/Af8DfwH/A38B/wN/Af8DfwH/A38B/wN/Af8D
|
||||
agFeAe0CaAFTAfQBfgF3ASsB/AH/AXgBAAL/AXgBAAH/Am4BWgH1AmoBYQHmAmUBYAHjAmUBYAHjAmUB
|
||||
YAHjAmUBXgHiAl4BWwHNAlUBUwGqAi4BLQFGVAADXwHQA2IB7iAAA2EB1ANjAencAAEIAQoBAAH/AT0B
|
||||
cQECAf8BTAGGAQcB/wFSAYwBCAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEQAf8BTAF/AQ8B
|
||||
/wE7AWcBCAH/ASEBNAEIAf8BUwGOAQsB/wFaAZwBEAH/AXIBswEnAf8BUwGBARsB/xAAAysBQQM2AVkC
|
||||
QAE/AW4CQAE/AW4CQAE/AW4CQAE/AW4DRAF7AlEBUAGfAl0BWwHFA2IB7gH/AXgBAAL/AXgBAAH/Al8B
|
||||
XQHJA0UBfAJAAT8BbgJAAT8BbgJAAT8BbgM/AW0DOwFjAzMBUgMZASJUAANfAdADYgHuIAADYQHUA2MB
|
||||
6dgAARUBKQEAAf8BSgGEAQQB/wFSAYwBCAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEIAf8B
|
||||
UgGMARAB/wFSAYwBEAH/AVIBjAEQAf8BWgGUARAB/wFWAZABDAH/AVoBmgEQAf8BWgGcARAB/wFyAakB
|
||||
MAH/AQgBCgEAAf8BCAEKAQAB/wwAAwwBEAMRARYDFQEcAxUBHAMVARwDFQEcAyEBMAI+AT0BaQJTAVIB
|
||||
pQJmAV8B5QH/AXgBAAL/AXgBAAH/AlUBUwGqAyIBMQMVARwDFQEcAxUBHAMUARsDEwEZAxABFQMHAQlU
|
||||
AANfAdADYgHuIAADYQHUA2MB6dQAARYBJwECAf8BSQGAAQcB/wFSAYwBCAH/AVIBjAEIAf8BUgGMAQgB
|
||||
/wFSAYwBCAH/AVIBjAEIAf8BUgGMAQsB/wFSAYwBEAH/AVIBjAEQAf8BWAGSARAB/wFaAZQBEAH/AVoB
|
||||
mwEQAf8BWgGcARAB/wFcAZ4BEgH/ATsBbQEDAf8BCAEKAQAB/wEIAQoBAAH/AQgBCgEAAf8IAAMFBAYE
|
||||
CAEKAwgBCgMIAQoDCAEKAxcBHwI5ATgBXQNRAZ4CZQFgAeMB/wF4AQAC/wF4AQAB/wNSAaMDGAEhAwgB
|
||||
CgMIAQoDCAEKAwgBCgMHAQkDBgEHAwIBA1QAA18B0ANiAe4gAANhAdQDYwHp0AADXQHfAUcBgAEDAf8B
|
||||
UgGMAQgB/wFSAYwBCAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEIAf8BUgGMARAB/wFSAYwB
|
||||
EAH/AVIBjAEQAf8BWgGUARAB/wFaAZQBEAH/AVoBnAEQAf8BWgGcARAB/wFaAZwBEAH/AVoBnAEQAf8B
|
||||
WgGYARAB/wEWASoBAAH/AQgBCgEAAf8BCAEKAQAB/xwAAxIBFwM1AVYDUAGaA2IB4QH/AXgBAAL/AXgB
|
||||
AAH/AlEBUAGfAxIBGHAAA18B0ANiAe4gAANhAdQDYwHp0AABLAFQAQAB/wFKAYwBAAH/AVIBjAEIAf8B
|
||||
UgGMAQgB/wFSAYwBCAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBDgH/AVUBkgEQAf8BWgGcARAB/wFaAZwB
|
||||
EAH/AVoBlAEQAf8BWgGcARAB/wFaAZwBEAH/AVoBnAEQAf8BWgGcARAB/wFaAZwBEAH/AVoBlAEYAf8B
|
||||
WAGSARYB/wEQAR4BAAH/AQgBCgEAAf8cAAMSARcDNQFWA1ABmgNiAeEB/wF4AQAC/wF4AQAB/wJRAVAB
|
||||
nwMSARhwAANfAdADYgHuIAADYQHUA2MB6dQAA0sBjwEzAV4BAAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwB
|
||||
CAH/AVIBjAEQAf8BfwHAATMB/wFfAZ4BFwH/ASABPwEAAf8BCAEKAQAB/wFSAYwBEAH/AVoBnAEQAf8B
|
||||
WgGcARAB/wFaAZwBEAH/AVoBnAEQAf8BWgGVARcB/wFaAZQBGAH/AVoBlAEYAf8BWgGUARgB/wEIAQoB
|
||||
AAH/AQgBCgEAAf8YAAMSARcDNQFWA1ABmgNiAeEB/wF4AQAC/wF4AQAB/wJRAVABnwMSARgUAAQBAwMB
|
||||
BAMGBAcBCQMHAQkDBAEFBAIEARQAAxEBFgMhAS8DIQEvAyEBLwMhAS8DIQEvAyEBLwMhAS8DIQEvAyEB
|
||||
LwNhAdkDcAHxAyEBLwMhAS8DIQEvAyEBLwMhAS8DIQEvAyEBLwMhAS8DYgHcA2oB7QMhAS8DIQEvAyEB
|
||||
LwMhAS8DIQEvAyEBLwMhAS8DIQEvAyEBLwMNARG4AAFCAXsBAAH/AVIBjAEIAf8BewHGASkB/wMzAVAE
|
||||
AAMMARABOQFrAQAB/wFaAZwBEAH/AVoBnAEQAf8BXQGXARMB/wFWAZQBDAH/AVoBnAEQAf8BWgGUARgB
|
||||
/wFaAZQBGAH/AWMBnAEYAf8BYwGlARcB/wEpAVABAAH/AQgBCgEAAf8YAAMSARcDNQFWA1ABmgNiAeEB
|
||||
/wF4AQAC/wF4AQAB/wJRAVABnwMSARgUAAQCAwkBDAMPARQDEwEaAxIBGAMKAQ0DBAEFBAEUAANpAegD
|
||||
fwH/A38B/wN/Af8DfwH/A38B/wN/Af8DfwH/A38B/wN/Af8DfwH/A38B/wN/Af8DfwH/A38B/wN/Af8D
|
||||
fwH/A38B/wN4AdyUAAFKAYwBAAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEIAf8BZwGdAScB
|
||||
/wEIAQoBAAH/AQoBDwEAAf8BQgF3AQMB/wFSAYwBEAH/AVoBnAEQAf8BJQFBAQUB/wQAAzoBYAEIAQoB
|
||||
AAH/AQgBCgEAAf8EAANGAYADRgGAA0YBgBwAAwoBDQMiATEDNAFUA0QBeAJRAVABnwJhAV0BzwJqAV4B
|
||||
7QJlAV0B7AJoAV4B8AGaAV8BIQH7Af8BeAEAAv8BeAEAAf8CUQFQAZ8DEgEYHAADBgEIAxgBIQMxAU0C
|
||||
TAFNAZECWAFaAb0CXQFhAdECWQFcAcMCUQFTAaIDPQFnAhkBGgEjAwwBDwNMAW8DaAGtA2gBrQNoAa0D
|
||||
aAGtA2gBrQNoAa0DaAGtA2gBrQNoAa0DewHwA30B+gNoAa0DaAGtA2gBrQNoAa0DaAGtA2gBrQNoAa0D
|
||||
aAGtA3wB8QN9AfgDaAGtA2gBrQNoAa0DaAGtA2gBrQNoAa0DaAGtA2gBrQNoAa0DVQGBlAABOwFtAQIB
|
||||
/wFSAYwBCAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBCAH/AVMBjgEQAf8BDwEbAQAB/wEjAUMBAAH/AVIB
|
||||
jAEQAf8BUgGMARAB/wF7Ab0BMAH/AQgBCgEAAf8BCAEKAQAB/wEIAQoBAAH/AQgBCgEAAf8BCAEKAQAB
|
||||
/wEIAQoBAAH/AQgBCgEAAf8oAAMDAQQDCQELAyIBMQM4AVsCTwFOAZcCXwFcAcgCZgFfAeUBhQFvAVEB
|
||||
9wG+AVwBOAH9Af8BeAEAAv8BeAEAAf8CUQFQAZ8DEgEYHAAEAQMCAQMDFQEcAzUBVgJLAUwBjwJcAV8B
|
||||
yAJdAWMB3wJgAWUB4wJSAVMBpQM0AVMDHAEnKAADdAHQA3sB7iAAA3UB1AN6Aem8AAEIAQoBAAH/AVIB
|
||||
jAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEIAf8BUgGMAQgB/wFOAYIBDwH/AUoBhAEGAf8BUgGMARAB
|
||||
/wFjAaUBFwH/AQgBCgEAAf8BCAEKAQAB/wETASMBAAH/AUIBcwEGAf8BIAE/AQAB/wEIAQoBAAH/AQgB
|
||||
CgEAAf8BCAEKAQAB/wEIAQoBAAH/AQgBCgEAAf8gAAQBAwMBBAMMARADGAEgAykBPQM+AWoCVwFWAbUC
|
||||
ZgFfAeUBhQFvAVEB9wH/AXgBAAL/AXgBAAH/AlEBUAGfAxIBGCAABAEDBwEJAxQBGwMqAUADQwF2A1UB
|
||||
rwJaAWMB6QJbAV8B0AJQAVEBnwMzAVEoAAN0AdADewHuIAADdQHUA3oB6cAAAUIBcwEGAf8BUgGMAQgB
|
||||
/wFSAYwBCAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEQAf8BUgGMARAB/wFKAYQBBgH/ARAB
|
||||
HgEAAf8BMQFaAQAB/wFNAYQBDQH/AVoBnAEQAf8BWgGcARAB/wFSAYwBCAH/ARABHgEAAf8BCAEKAQAB
|
||||
/wEIAQoBAAH/A0YBgCwAAwIBAwMLAQ4DIAEuA0MBdgJXAVUBsQJmAWAB4AF2AWMBSAH2AY0BagFBAfkC
|
||||
UQFQAZwDEgEXDAAEAQMMARADFwEfAx0BKAMdASgDDAEPCAADDwEUAiYBJwE5AkcBSAGDA2IB4QJcAWUB
|
||||
5wNeAdICPwFAAW4oAAN0AdADewHuIAADdQHUA3oB6cQAAUkBiQEAAf8BUgGMAQgB/wFSAYwBCAH/AVIB
|
||||
jAEIAf8BUgGMAQgB/wFSAYwBEAH/AVIBjAEQAf8BUgGMARAB/wFSAYwBEAH/AVoBlAEQAf8BWgGcARAB
|
||||
/wFaAZwBEAH/AVoBnAEQAf8BWgGcARAB/wFaAZQBGAH/AUIBcwEGAf8BCgEOAQAB/zAABAEDAwEEAwwB
|
||||
DwMeASoDOgFhAlkBVwG5AmMBWwHkAWUCYgHuAk8BTgGXAxIBFwwAAwIBAwMhAS8DNgFZAkIBQwF1AkEB
|
||||
QgFzAx4BKwgAAwQBBQMMAQ8DOAFcAl0BYAHOAl0BZQHsAlkBZwHvA0YBfygAA3QB0AN7Ae4gAAN1AdQD
|
||||
egHpyAABOgFrAQAB/wFSAYwBCAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBEAH/AVIBjAEQAf8BWgGUARAB
|
||||
/wFaAZQBEAH/AVoBnAEQAf8BWgGcARAB/wFaAZwBEAH/AVoBnAEQAf8BWgGUARgB/wFaAZQBGAH/AWMB
|
||||
pQEXAf8BGQEsAQMB/zgAAwIBAwMIAQoDIAEtAkEBQAFxAk0BTAGRA1ABmgI7AToBYgMMAQ8MAAMDAQQD
|
||||
KwFBA0QBegNTAacDVQGtAzcBWgMYASADCQELAwYBBwMNAREDOQFfAl0BYQHRAlkBZwHvAlwBbwHzAkYB
|
||||
RwGBKAADdAHQA3sB7iAAA3UB1AN6AenMAAEsAVUBAAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBEAH/AVIB
|
||||
jAEQAf8BWgGUARAB/wFaAZQBEAH/AVoBnAEQAf8BWgGcARAB/wFaAZwBEAH/AVoBnAEQAf8BWgGUARgB
|
||||
/wFaAZQBGAH/ASEBQQEAAf9AAAQCAwcBCQMQBBUBHAIWARUBHQMPARMDAgEDDAADAwEEAzADSwFMAY8C
|
||||
WwFdAcoCWwFhAd4DTgGUAzQBUwMVARwDDQERAx4BKwJDAUQBdwJdAWMB3wJiAXAB8QJaAWMB6QNEAXso
|
||||
AAN0AdADewHuIAADdQHUA3oB6cgAARIBIgEAAf8BTAGGAQYB/wFSAYwBCAH/AVoBnAEQAf8BUAGKAQgB
|
||||
/wFSAYwBEAH/AVoBlAEQAf8BWgGcARAB/wFaAZwBEAH/AVoBnAEQAf8BWgGcARAB/wFaAZwBEQH/AWkB
|
||||
qwEfAf8BCAEKAQAB/2wAAwIBAwMhAS8DOgFhA1UBrQJfAWMB2gNaAb8CUAFRAZ8DRAF6AkEBQgFyA0kB
|
||||
hQJWAVcBsgJeAWoB7QJgAWQB2wJVAVcBsQM4AVsoAAN0AdADewHuIAADdQHUA3oB6cgAARABHgEAAf8B
|
||||
SAF9AQcB/wFZAZMBEwH/AVUBiAEYAf8IAAEhAUEBAAH/AUIBewEAAf8BUgGMAQgB/wFVAZEBCAH/ATkB
|
||||
ZgEEAf8DWQHveAADBgEIAxcBHwNEAXsCWQFcAcYCWwFjAeQCUwFzAfQCYgFlAe4CYgFlAe4CYgFwAfEC
|
||||
SAF2AfYCKwGsAfwCWQFcAb4DPgFrAyQBNCgAA3QB0AN7Ae4gAAN1AdQDegHp0AABHgE6AQAB/5wABAID
|
||||
CQEMAyoDPwFAAW4DTgGWAlYBWAGzAlkBXAHBAloBXQHHAloBXQHHAlcBWQG5AlEBUgGkAkABQQFxAyUB
|
||||
NgMTARkoAAN0AdADewHuIAADdQHUA3oB6f8AeQAEAQMLAQ4DJgE4AzkBXgNGAX0CSgFLAYsDSgGJAz4B
|
||||
awMqAT8DFwEfAwIBAywAA2QBogNuAb8gAANmAaYDbQG7qAABQgFNAT4HAAE+AwABKAMAAYADAAEgAwAB
|
||||
AQEAAQEGAAECFgAD/wEAA/8BxwIAAQcC/wHPAfMB/wQAAv8BzwGHAgABBwL/Ac8B8wH/BAAB/wH+AQAB
|
||||
BwIAAQcC/wHPAfMB/wQAAf8B/AEAAQcCAAEHAv8BzwHzAf8EAAH/AfgBAAEPAgABBwL/Ac8B8wH/BAAB
|
||||
/wHwAQABBwIAAQcC/wHPAfMB/wQAAf8B4AEAAQMCAAEHAv8BzwHzAf8EAAH/AcABAAEBAfwBAwP/Ac8B
|
||||
8wH/BAAB/wHAAQABAQH8AQMD/wHPAfMB/wQAAf8B4AIAAfwBAwHgAR8IAAH/AfwBIAEAAfwBAwHgAR8I
|
||||
AAH/Af4B4AEAAfwBAwHgAR8IAAH/AcACAAH8AQMB4AEfAf8BzwHzAf8EAAH/AYACAAH8AQMB4AEfAf8B
|
||||
zwHzAf8EAAH/AwAB/AEDAeABHwH/Ac8B8wH/BAAB/gIAAQEBAAEDAeABHwH/Ac8B8wH/BAAB/AIAAQEB
|
||||
AAEDAfgBHwH/Ac8B8wH/BAAB+AIAAQEBAAEDAfgBHwH/Ac8B8wH/BAAB+AIAAQMBAAEDAfgBAwH/Ac8B
|
||||
8wH/BAAB+AIAAQcBAAEDAfgBAwgAAfgCAAEPAQABAwH4CQAB+AEAAUQBfwEAAQMB+AkAAfgBAAEBAf8B
|
||||
gAEDAfgBAAH/Ac8B8wH/BAAB+AIAAX8BgAEDAfwBAAH/Ac8B8wH/BAAB/AIAAX8B8AEDAYEBgAH/Ac8B
|
||||
8wH/BAAB/gIAAf8B8AEDAYEBgAH/Ac8B8wH/BAAB/wIAAf8B/AEDAYABAAH/Ac8B8wH/BAAB/wGAAQEB
|
||||
/wH+AQMBgAEAAf8BzwHzAf8EAAH/AQABAwP/AYABAAH/Ac8B8wH/BAAB/wEMAQ8D/wHAAQAB/wHPAfMB
|
||||
/wQAAf8B3wT/AcABAAH/Ac8B8wH/BAAG/wHwAQEB/wHPAfMB/wQACw==
|
||||
fwH/A38B/wN/Af8DfwH/A38B/wN/Af8DfwH/A38B/wN/Af8DfwH/A38B/wN/Af8DfwH/A38B/wN/Af8D
|
||||
YQHPvAABCAEKAQAB/wwAARMBIwEAAf8BWgGUARAB/wFaAZwBEAH/AZQB1gFKAf8BDQERAQIB/wExAVoB
|
||||
AAH/AVoBlAESAf8BWgGUARgB/wFaAZQBGAH/AWMBnAEYAf8BYwGlARcB/wFrAaUBIQH/ARABHgEAAf8Y
|
||||
AAMSARcDNQFWA1ABmgNiAeEB/wF4AQAC/wF4AQAB/wJRAVABnwMSARgUAAMFAQYDHQEpAzABSgI7ATwB
|
||||
ZQI7ATwBZAMoATwCFQEWAR0DBgEIFAADPAFkA0wBjwNMAY8DTAGPA0wBjwNMAY8DTAGPA0wBjwNMAY8D
|
||||
TAGPA2cB6gN8AfgDTAGPA0wBjwNMAY8DTAGPA0wBjwNMAY8DTAGPA0wBjwNlAewDbgH1A0wBjwNMAY8D
|
||||
TAGPA0wBjwNMAY8DTAGPA0wBjwNMAY8DTAGPAzUBVqgAA10B3wEIAQoBAAH/AQgBCgEAAf8BCAEKAQAB
|
||||
/wEIAQoBAAH/AQgBCgEAAf8BCAEKAQAB/wMzAVADOgFgAUsBhQEHAf8BWgGUARAB/wFaAZwBEAH/ATkB
|
||||
awEAAf8DCQEMARABHgEAAf8BVAGOARIB/wFaAZQBGAH/AWMBnAEYAf8BYwGcARgB/wFjAaUBFwH/AXMB
|
||||
tAEpAf8BEAEeAQAB/xgAAxIBFwM1AVYDUAGaA2IB4QH/AXgBAAL/AXgBAAH/AlEBUAGfAxIBGBQAAwkB
|
||||
DAMzAVACTAFNAZECXQFfAckCWwFdAcoDRAF6AykBPQMMARA8AANfAdADYgHuIAADYQHUA2MB6cwAAQgB
|
||||
CgEAAf8BCAEKAQAB/wEIAQoBAAH/AQgBCgEAAf8BCAEKAQAB/wEIAQoBAAH/AQgBCgEAAf8BCAEKAQAB
|
||||
/wEIAQoBAAH/ATMBXwECAf8BWgGUARAB/wFaAZwBEAH/Aa0B5wFjAf8BEAEeAQAB/wEIAQoBAAH/ARQB
|
||||
JgEAAf8BVAGOARIB/wFiAZsBGAH/AWMBnAEYAf8BYwGlARcB/wFjAaUBFwH/AWMBnAEhAf8BGAEuAQAB
|
||||
/xgAAxIBFwM1AVYDUAGaA2IB4QH/AXgBAAL/AXgBAAH/AlEBUAGfAxIBGBQAAwkBCwMuAUcDSAGEAlkB
|
||||
XAHDAlwBXwHLA0kBhQMuAUcDDwETPAADXwHQA2IB7iAAA2EB1ANjAenIAAEIAQoBAAH/ASsBUgEAAf8B
|
||||
QQFyAQUB/wFKAYQBBgH/AUoBhAEGAf8BSgGEAQYB/wFCAXMBBgH/ASkBUAEAAf8BEAEeAQAB/wEfAToB
|
||||
AAH/AVUBjwELAf8BWgGVARAB/wFaAZwBEAH/AdYB/wGMAf8BEAEeAQAB/wEYAS4BAAH/AUIBeAEDAf8B
|
||||
WgGUARgB/wFiAZsBGAH/AWMBnAEYAf8BYwGlARcB/wFjAaUBFwH/AXMBtAEpAf8BEAEeAQAB/xgAAxIB
|
||||
FwM1AVYDUAGaA2IB4QH/AXgBAAL/AXgBAAH/AlEBUAGfAxIBGBQAAwYBCAMkATQDPAFmA1MBpwNYAbgC
|
||||
RwFIAYMDMQFNAw8BFDwAA18B0ANiAe4gAANhAdQDYwHpxAABKAFNAQAB/wFOAYgBBwH/AVIBjAEIAf8B
|
||||
UgGMAQgB/wFSAYwBCAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEQAf8BUgGMARAB/wFSAYwB
|
||||
EAH/AVoBlAEQAf8BWgGcARAB/wFjAaUBFwH/AUIBewEAAf8BSgGEAQYB/wFSAYwBCAH/AVoBmAEUAf8B
|
||||
WgGUARgB/wFjAZwBGAH/AWMBpQEXAf8BYwGlARcB/wFjAaUBFwH/AZQByQFNAf8EAAMQARUDGgEkAyEB
|
||||
LwMRARYEAgQBAxIBFwM1AVYDUAGaA2IB4QH/AXgBAAL/AXgBAAH/AlEBUAGfAxIBGBQAAwMBBAMTARkD
|
||||
JQE2AjsBPAFkAkEBQgFyAzMBUQMhAS8DCQEMPAADXwHQA2IB7iAAA2EB1ANjAenAAAEpAU4BAgH/AVIB
|
||||
jAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEIAf8BUgGMARAB
|
||||
/wFSAYwBEAH/AVIBjAEQAf8BWgGUARAB/wFaAZUBEAH/AVoBnAEQAf8BWgGcARAB/wFaAZwBEAH/AVoB
|
||||
nAEQAf8BWgGUARgB/wFaAZQBGAH/AWMBnAEYAf8BYwGcARgB/wFjAaUBFwH/AWMBpQEXAf8BYwGlARcB
|
||||
/wFlAaABIQH/BAADHgErAjEBMAFMAzsBYwMiATEDBwEJAwQBBQMSARgDNgFXA1ABmgNiAeEB/wF4AQAC
|
||||
/wF4AQAB/wJRAVABnwMSARgcAAMHAQkDHAEnAyMBMgIZARoBIwMPARQDBAEFPAADXwHQA2IB7iAAA2EB
|
||||
1ANjAem8AANGAYABTgGIAQcB/wFSAYwBCAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEIAf8B
|
||||
UgGMAQgB/wFSAYwBCAH/AVIBjAEQAf8BUgGMARAB/wFSAYwBEAH/AVoBlAEQAf8BWgGXARAB/wFaAZwB
|
||||
EAH/AVoBnAEQAf8BWgGcARAB/wFaAZwBEAH/AVoBlAEYAf8BWgGUARgB/wFjAZwBGAH/AWMBoQEYAf8B
|
||||
YwGlARcB/wFjAaUBFwH/AXgBugEsAf8BCAEKAQAB/wQAAyQBNANFAXwCWgFYAbcDTgGUAz8BbQMoATsD
|
||||
HwEsAzkBXgNQAZoDYgHhAf8BeAEAAv8BeAEAAf8CUQFQAZ8DEgEYHAADEgEXAzwBZgNKAYkDQAFvAy4B
|
||||
RwMOARI8AANfAdADYgHuIAADYQHUA2MB6bwAATUBXgEHAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEIAf8B
|
||||
UgGMAQgB/wFSAYwBCAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEQAf8BUgGMARAB/wFaAZQB
|
||||
EAH/AVoBlAEQAf8BWgGbARAB/wFaAZwBEAH/AVoBnAEQAf8BWgGcARAB/wFaAZYBFgH/AVoBlAEYAf8B
|
||||
XQGXARgB/wFjAZwBGAH/AWMBpQEXAf8BYwGlARcB/wFwAbMBIAH/ASsBUAEEAf8IAAMnAToCUwFRAaIB
|
||||
gwFfASEB+wJlAVwB5wJcAVoBxAJDAUIBdQMxAU0CQAE/AW4CUQFQAZ8CZQFgAeMB/wF4AQAC/wF4AQAB
|
||||
/wJRAVABnwMSARgcAAMZASIDTgGVAlsBXgHNAlYBVwGyA0QBegMdASkDBgEIBAIEATAAA18B0ANiAe4g
|
||||
AANhAdQDYwHpvAABSgGEAQYB/wFSAYwBCAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEIAf8B
|
||||
ZwGpARcB/wFSAYwBCAH/AUoBhAEGAf8BSgGEAQYB/wFSAYwBEAH/AVoBlAEQAf8BWgGXARAB/wFaAZwB
|
||||
EAH/AVoBnAEQAf8BWgGcARAB/wFaAZwBEAH/AVoBlAEYAf8BWgGUARgB/wFfAZgBGAH/AWMBngEYAf8B
|
||||
YwGlARcB/wFrAakBHQH/ASkBUAEAAf8MAAMiATEDTgGYAm8BYAHzAmgBXgHwAmoBYQHmAloBVwHCAlUB
|
||||
UwGqA1MBpwJZAVcBvAJsAWEB6wH/AXgBAAL/AXgBAAH/AlEBUAGfAxIBGBwAAxQBGwJDAUQBdwJWAVkB
|
||||
tgJbAV4BzQJWAVgBswM/AWwDJgE4AwwBDwMCAQMIAAMCAQMDDQERAw0BEQMNAREDDQERAw0BEQMNARED
|
||||
DQERAw0BEQMNAREDXwHTA2cB7wMNAREDDQERAw0BEQMNAREDDQERAw0BEQMNAREDDQERA2IB1wNnAeoD
|
||||
DQERAw0BEQMNAREDDQERAw0BEQMNAREDDQERAw0BEQMNAREDBAEFlAABSgGEAQYB/wFSAYwBCAH/AVIB
|
||||
jAEIAf8BUgGMAQgB/wFSAYwBCAH/AWkBpAEeAf8BLAFQAQMB/wEIAQoBAAH/ATcBYQEHAf8BUgGMAQ4B
|
||||
/wFSAYwBEAH/AX8BwQEyAf8BWwFeAVsB0wNaAb8BLwFZAQAB/wFEAXoBBQH/AVABigEIAf8BWgGcAQ4B
|
||||
/wFaAZwBEAH/AVoBnAEQAf8BTwGGARAB/wFEAXQBDAH/A1oBvxAAAhoBGQEjA0QBewJdAVsBygJjAV8B
|
||||
2gJpAWAB6AJnAVkB7wJlAV0B7AJhAVwB1gJfAVsB2AJoAVMB9AH/AXgBAAL/AXgBAAH/AlEBUAGfAxIB
|
||||
GBwAAw8BEwM0AVMDTQGSAl0BYQHPAl0BYQHUAlIBVAGoAkEBQgFyAyYBOAMUARsDBgEIAwIBAwNaAcID
|
||||
fwH/A38B/wN/Af8DfwH/A38B/wN/Af8DfwH/A38B/wN/Af8DfwH/A38B/wN/Af8DfwH/A38B/wN/Af8D
|
||||
fwH/A38B/wN/Af8DfwH/A38B/wN/Af8DfwH/A38B/wN/Af8DfwH/A38B/wN/Af8DfwH/A38B/wN/Af8D
|
||||
YgHclAABSgGMAQAB/wFSAYwBCAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBCAH/AWcBnQEnAf8BCAEKAQAB
|
||||
/wEKAQ8BAAH/AUIBdwEDAf8BUgGMARAB/wFaAZwBEAH/ASUBQQEFAf8EAAM6AWABCAEKAQAB/wEIAQoB
|
||||
AAH/BAADRgGAA0YBgANGAYAcAAMKAQ0DIgExAzQBVANEAXgCUQFQAZ8CYQFdAc8CagFeAe0CZQFdAewC
|
||||
aAFeAfABgwFfASEB+wH/AXgBAAL/AXgBAAH/AlEBUAGfAxIBGBwAAwYBCAMYASEDMQFNAkwBTQGRAlgB
|
||||
WgG9Al0BYQHRAlkBXAHDAlEBUwGiAz0BZwIZARoBIwMMAQ8DQAFvA1UBrQNVAa0DVQGtA1UBrQNVAa0D
|
||||
VQGtA1UBrQNVAa0DVQGtA2gB8AN9AfoDVQGtA1UBrQNVAa0DVQGtA1UBrQNVAa0DVQGtA1UBrQNwAfED
|
||||
fAH4A1UBrQNVAa0DVQGtA1UBrQNVAa0DVQGtA1UBrQNVAa0DVQGtA0cBgZQAATsBbQECAf8BUgGMAQgB
|
||||
/wFSAYwBCAH/AVIBjAEIAf8BUgGMAQgB/wFTAY4BEAH/AQ8BGwEAAf8BIwFDAQAB/wFSAYwBEAH/AVIB
|
||||
jAEQAf8BewG9ATAB/wEIAQoBAAH/AQgBCgEAAf8BCAEKAQAB/wEIAQoBAAH/AQgBCgEAAf8BCAEKAQAB
|
||||
/wEIAQoBAAH/KAADAwEEAwkBCwMiATEDOAFbAk8BTgGXAl8BXAHIAmYBXwHlAm8BUQH3Ab4BRQFAAf0B
|
||||
/wF4AQAC/wF4AQAB/wJRAVABnwMSARgcAAQBAwIBAwMVARwDNQFWAksBTAGPAlwBXwHIAl0BYwHfAmAB
|
||||
ZQHjAlIBUwGlAzQBUwMcAScoAANfAdADYgHuIAADYQHUA2MB6bwAAQgBCgEAAf8BUgGMAQgB/wFSAYwB
|
||||
CAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBCAH/AU4BggEPAf8BSgGEAQYB/wFSAYwBEAH/AWMBpQEXAf8B
|
||||
CAEKAQAB/wEIAQoBAAH/ARMBIwEAAf8BQgFzAQYB/wEgAT8BAAH/AQgBCgEAAf8BCAEKAQAB/wEIAQoB
|
||||
AAH/AQgBCgEAAf8BCAEKAQAB/yAABAEDAwEEAwwBEAMYASADKQE9Az4BagJXAVYBtQJmAV8B5QJvAVEB
|
||||
9wH/AXgBAAL/AXgBAAH/AlEBUAGfAxIBGCAABAEDBwEJAxQBGwMqAUADQwF2A1UBrwJaAWMB6QJbAV8B
|
||||
0AJQAVEBnwMzAVEoAANfAdADYgHuIAADYQHUA2MB6cAAAUIBcwEGAf8BUgGMAQgB/wFSAYwBCAH/AVIB
|
||||
jAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEQAf8BUgGMARAB/wFKAYQBBgH/ARABHgEAAf8BMQFaAQAB
|
||||
/wFNAYQBDQH/AVoBnAEQAf8BWgGcARAB/wFSAYwBCAH/ARABHgEAAf8BCAEKAQAB/wEIAQoBAAH/A0YB
|
||||
gCwAAwIBAwMLAQ4DIAEuA0MBdgJXAVUBsQJmAWAB4AJjAUgB9gFtAWoBQQH5AlEBUAGcAxIBFwwABAED
|
||||
DAEQAxcBHwMdASgDHQEoAwwBDwgAAw8BFAImAScBOQJHAUgBgwNiAeECXAFlAecDXgHSAj8BQAFuKAAD
|
||||
XwHQA2IB7iAAA2EB1ANjAenEAAFJAYkBAAH/AVIBjAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEIAf8B
|
||||
UgGMARAB/wFSAYwBEAH/AVIBjAEQAf8BUgGMARAB/wFaAZQBEAH/AVoBnAEQAf8BWgGcARAB/wFaAZwB
|
||||
EAH/AVoBnAEQAf8BWgGUARgB/wFCAXMBBgH/AQoBDgEAAf8wAAQBAwMBBAMMAQ8DHgEqAzoBYQJZAVcB
|
||||
uQJjAVsB5ANiAe4CTwFOAZcDEgEXDAADAgEDAyEBLwM2AVkCQgFDAXUCQQFCAXMDHgErCAADBAEFAwwB
|
||||
DwM4AVwCXQFgAc4CXQFlAewCWQFnAe8DRgF/KAADXwHQA2IB7iAAA2EB1ANjAenIAAE6AWsBAAH/AVIB
|
||||
jAEIAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEQAf8BUgGMARAB/wFaAZQBEAH/AVoBlAEQAf8BWgGcARAB
|
||||
/wFaAZwBEAH/AVoBnAEQAf8BWgGcARAB/wFaAZQBGAH/AVoBlAEYAf8BYwGlARcB/wEZASwBAwH/OAAD
|
||||
AgEDAwgBCgMgAS0CQQFAAXECTQFMAZEDUAGaAjsBOgFiAwwBDwwAAwMBBAMrAUEDRAF6A1MBpwNVAa0D
|
||||
NwFaAxgBIAMJAQsDBgEHAw0BEQM5AV8CXQFhAdECWQFnAe8CYAFvAfMCRgFHAYEoAANfAdADYgHuIAAD
|
||||
YQHUA2MB6cwAASwBVQEAAf8BUgGMAQgB/wFSAYwBCAH/AVIBjAEQAf8BUgGMARAB/wFaAZQBEAH/AVoB
|
||||
lAEQAf8BWgGcARAB/wFaAZwBEAH/AVoBnAEQAf8BWgGcARAB/wFaAZQBGAH/AVoBlAEYAf8BIQFBAQAB
|
||||
/0AABAIDBwEJAxAEFQEcAhYBFQEdAw8BEwMCAQMMAAMDAQQDMANLAUwBjwJbAV0BygJbAWEB3gNOAZQD
|
||||
NAFTAxUBHAMNAREDHgErAkMBRAF3Al0BYwHfAmUBcAHxAloBYwHpA0QBeygAA18B0ANiAe4gAANhAdQD
|
||||
YwHpyAABEgEiAQAB/wFMAYYBBgH/AVIBjAEIAf8BWgGcARAB/wFQAYoBCAH/AVIBjAEQAf8BWgGUARAB
|
||||
/wFaAZwBEAH/AVoBnAEQAf8BWgGcARAB/wFaAZwBEAH/AVoBnAERAf8BaQGrAR8B/wEIAQoBAAH/bAAD
|
||||
AgEDAyEBLwM6AWEDVQGtAl8BYwHaA1oBvwJQAVEBnwNEAXoCQQFCAXIDSQGFAlYBVwGyAl4BagHtAmAB
|
||||
ZAHbAlUBVwGxAzgBWygAA18B0ANiAe4gAANhAdQDYwHpyAABEAEeAQAB/wFIAX0BBwH/AVkBkwETAf8B
|
||||
VQGIARgB/wgAASEBQQEAAf8BQgF7AQAB/wFSAYwBCAH/AVUBkQEIAf8BOQFmAQQB/wNZAe94AAMGAQgD
|
||||
FwEfA0QBewJZAVwBxgJbAWMB5AJTAWgB9ANiAe4DYgHuAmUBcAHxAkgBYwH2AisBfgH8AlkBXAG+Az4B
|
||||
awMkATQoAANfAdADYgHuIAADYQHUA2MB6dAAAR4BOgEAAf+cAAQCAwkBDAMqAz8BQAFuA04BlgJWAVgB
|
||||
swJZAVwBwQJaAV0BxwJaAV0BxwJXAVkBuQJRAVIBpAJAAUEBcQMlATYDEwEZKAADXwHQA2IB7iAAA2EB
|
||||
1ANjAen/AHkABAEDCwEOAyYBOAM5AV4DRgF9AkoBSwGLA0oBiQM+AWsDKgE/AxcBHwMCAQMsAANTAaID
|
||||
WgG/IAADVAGmA1kBu6gAAUIBTQE+BwABPgMAASgDAAGAAwABIAMAAQEBAAEBBgABAhYAA/8BAAP/AccC
|
||||
AAEHAv8BzwHzAf8EAAL/Ac8BhwIAAQcC/wHPAfMB/wQAAf8B/gEAAQcCAAEHAv8BzwHzAf8EAAH/AfwB
|
||||
AAEHAgABBwL/Ac8B8wH/BAAB/wH4AQABDwIAAQcC/wHPAfMB/wQAAf8B8AEAAQcCAAEHAv8BzwHzAf8E
|
||||
AAH/AeABAAEDAgABBwL/Ac8B8wH/BAAB/wHAAQABAQH8AQMD/wHPAfMB/wQAAf8BwAEAAQEB/AEDA/8B
|
||||
zwHzAf8EAAH/AeACAAH8AQMB4AEfCAAB/wH8ASABAAH8AQMB4AEfCAAB/wH+AeABAAH8AQMB4AEfCAAB
|
||||
/wHAAgAB/AEDAeABHwH/Ac8B8wH/BAAB/wGAAgAB/AEDAeABHwH/Ac8B8wH/BAAB/wMAAfwBAwHgAR8B
|
||||
/wHPAfMB/wQAAf4CAAEBAQABAwHgAR8B/wHPAfMB/wQAAfwCAAEBAQABAwH4AR8B/wHPAfMB/wQAAfgC
|
||||
AAEBAQABAwH4AR8B/wHPAfMB/wQAAfgCAAEDAQABAwH4AQMB/wHPAfMB/wQAAfgCAAEHAQABAwH4AQMI
|
||||
AAH4AgABDwEAAQMB+AkAAfgBAAFEAX8BAAEDAfgJAAH4AQABAQH/AYABAwH4AQAB/wHPAfMB/wQAAfgC
|
||||
AAF/AYABAwH8AQAB/wHPAfMB/wQAAfwCAAF/AfABAwGBAYAB/wHPAfMB/wQAAf4CAAH/AfABAwGBAYAB
|
||||
/wHPAfMB/wQAAf8CAAH/AfwBAwGAAQAB/wHPAfMB/wQAAf8BgAEBAf8B/gEDAYABAAH/Ac8B8wH/BAAB
|
||||
/wEAAQMD/wGAAQAB/wHPAfMB/wQAAf8BDAEPA/8BwAEAAf8BzwHzAf8EAAH/Ad8E/wHAAQAB/wHPAfMB
|
||||
/wQABv8B8AEBAf8BzwHzAf8EAAs=
|
||||
</value>
|
||||
</data>
|
||||
<metadata name="ilStoreThumbnails.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>12, 128</value>
|
||||
</metadata>
|
||||
<metadata name="ilTabIcons.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>20, 44</value>
|
||||
</metadata>
|
||||
@ -461,8 +462,8 @@
|
||||
<value>
|
||||
AAEAAAD/////AQAAAAAAAAAMAgAAAEZTeXN0ZW0uV2luZG93cy5Gb3JtcywgQ3VsdHVyZT1uZXV0cmFs
|
||||
LCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAAAmU3lzdGVtLldpbmRvd3MuRm9ybXMu
|
||||
SW1hZ2VMaXN0U3RyZWFtZXIBAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAuhIAAAJNU0Z0AUkBTAIBAQQB
|
||||
AAFYAQIBWAECARABAAEQAQAE/wEhAQAI/wFCAU0BNgcAATYDAAEoAwABQAMAASADAAEBAQABIAYAASD/
|
||||
SW1hZ2VMaXN0U3RyZWFtZXIBAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAshIAAAJNU0Z0AUkBTAIBAQQB
|
||||
AAEQAQMBEAEDARABAAEQAQAE/wEhAQAI/wFCAU0BNgcAATYDAAEoAwABQAMAASADAAEBAQABIAYAASD/
|
||||
AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/ACIAA2cB7wJnAVkB7wFnAV0BWQHvAWcBWwFZAe8B
|
||||
ZwFbAVkB7wFnAlkB7wFnAWQBWQHvA2cB7wNnAe8DZwHvA2cB7wNnAe8DZwHvA2cB7wNnAe8DZwHvAwcB
|
||||
CQMqAT8DRQF8A1kBuwNjAd8DaAH0A4AB/gOBAf8DgQH/A4EB/wOAAf4DaAH0A2MB3wNaAboDRAF6AycB
|
||||
@ -488,7 +489,7 @@
|
||||
YAH/AYMBggF/Af8BhQGCAX0B/wGzAZMBRAH/Ac8BlAEAAf8B3gHMAZ8B/wOwAf8DsAH/A7AB/wOwAf8D
|
||||
sAH/A7AB/wOwAf8DsAH/A6gB/wMCAQMDGgEjAzgBXANUAagDYgHXA3AB8QOAAf4DgQH/A4EB/wOBAf8D
|
||||
gQH9A2gB8ANhAdQDUwGlAzYBWQMYASAIAAMaASQDUgGgAmMBSAH2AaIBcwEAAf8BrgF8AQAB/wGwAX0B
|
||||
AAH/AagBeAEAAf8BlQFqAQAB/wKAAUsB/gFcAlkBxgNXAbUDFgEeCAAB/wGyAW8B/wH9AYABEQH/AfwB
|
||||
AAH/AagBeAEAAf8BlQFqAQAB/wKAAWIB/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
|
||||
@ -524,24 +525,24 @@
|
||||
AwH/AeIBhAEyAf8DYwHfBP8BpwGUAWcB/wGDAYIBfwH/AYUBgwF+Af8BsAGUAU4B/wHTAZcBAgH/AeAB
|
||||
zgGfAf8D5wH/A+cB/wPnAf8D5wH/A+cB/wPnAf8D5wH/A+cB/wPAAf8DZAHbA2gB9AOBAf8DgQH/A4EB
|
||||
/wOBAf8DgQH/A4EB/wOBAf8DgQH/A4EB/wOBAf8DgQH/A4EB/wOBAf8DVQGvAwcBCQNiAe4B8QG8ATsB
|
||||
/wH6AeoBwgH/A9wB/wN3Af8DaAH/A2gB/wNoAf8DMgn/AfIB3QGpAf8B6gGpAQgB/wM+AWoEAANeAdIB
|
||||
fQFvAWoB+QH/AbsBfQL/AaMBUgL/AZABLAL/AYIBEwL/AX0BCAL/AXoBBAL/AXkBAgL/AXoBBAL/AX0B
|
||||
CQL/AYABDwL/AX8BDQH/AfgBhgEgAf8DaAH0A1gBuAT/AdcBsQFSAf8BmgGPAXQB/wGgAZIBbQH/AeAB
|
||||
rwE3Af8B5wGpARAB/wHrAdUBoAH/A4EB/wOBAf8DgQH/A4EB/wOBAf8DgQH/A4EB/wOBAf8DkwH/AzwB
|
||||
ZANfAckDfQH6A4EB/wOBAf8DgQH/A4EB/wOBAf8DgQH/A4EB/wOBAf8DgQH/A4EB/wOBAf8DfQH6A1UB
|
||||
qgQAAzMBUQNoAfAB8wHGAVgB/wH6AecBuBb/Af4B+wH/AfkB4gGqAf8B7wG4AS0B/wNOAZYEAgQAAzwB
|
||||
ZgNjAdUDfAH4Af8BvgGFAv8BqgFfAv8BmQE+Av8BjQEnAv8BhgEaAv8BgwEVAv8BhQEZAv8BigEiAv8B
|
||||
jQEoAv8BkwEzAf8CbgFoAfUDXQHFAzYBWQT/AfQBzQFsAf8B9AHLAWYB/wH0AcsBZQH/AfQBywFlAf8B
|
||||
8QHBAUkB/wH5AeMBrAH/A4kB/wOJAf8DiQH/A4kB/wOJAf8DiQH/A4kB/wOJAf8DmgH/AwYBCAMxAUwD
|
||||
UAGbA2UB7AN9AfoDgQH/A4EB/wOBAf8DgQH/A4EB/wOBAf8DgQH/A30B+gNqAe0DUAGbAy8BSQgAAyIB
|
||||
MQNfAckCfQFnAfoB8wHKAWUB/wH5AeEBpgH/AfsB7QHMAf8B+wHsAcgB/wH4Ad0BmwH/A4AB/gJlAV4B
|
||||
4gM9AWgEAQwAA0IBcgNjAdUBfQFzAWoB+QH/AckBmQL/AbwBfwL/Aa4BZgL/AaQBUwL/AZ8BSgL/AZ8B
|
||||
SwL/AaMBUQL/AacBWAH/A3wB+ANdAccDOwFiBABA/wgAAwUBBgMSARcDOgFgA1EBnwNfAdMDZwHvA2MB
|
||||
9gNiAe4DXgHSA1EBngM5AV8DEQEWAwUBBhQAAw8BEwNHAYIDZAHbAn4BbwH8A2cB6gNUAagDKAE7HAAD
|
||||
PAFlA14B0gH/Ae8B4AL/AdwBvAL/Ac0BnwL/AcEBigL/AbsBfwL/Ab8BhgL/Ac0BoQL/AekB1gH/A1wB
|
||||
xAM1AVUIAAFCAU0BPgcAAT4DAAEoAwABQAMAASADAAEBAQABAQYAAQEWAAP/hQAB/wH8AcABAwQAAf8B
|
||||
/AGAAQEEAAH/AfkGAAH/AfkGAAHwARMGAAHAAQMEAAL/AYABAQQAAcABAQGAAQEEAAGAAgABAQcAAQEH
|
||||
AAEBBwABAQcAAQEGAAGAAQEGAAHAAQMBgAEBAgABwAEBAfABHwHAAQML
|
||||
/wH6AeoBwgH/A9wB/wN3Af8DaAH/A2gB/wNoAf8DMgn/AfIB3QGpAf8B6gGpAQgB/wM+AWoEAANeAdID
|
||||
agH5Af8BuwF9Av8BowFSAv8BkAEsAv8BggETAv8BfQEIAv8BegEEAv8BeQECAv8BegEEAv8BfQEJAv8B
|
||||
gAEPAv8BfwENAf8B+AGGASAB/wNoAfQDWAG4BP8B1wGxAVIB/wGaAY8BdAH/AaABkgFtAf8B4AGvATcB
|
||||
/wHnAakBEAH/AesB1QGgAf8DgQH/A4EB/wOBAf8DgQH/A4EB/wOBAf8DgQH/A4EB/wOTAf8DPAFkA18B
|
||||
yQN9AfoDgQH/A4EB/wOBAf8DgQH/A4EB/wOBAf8DgQH/A4EB/wOBAf8DgQH/A4EB/wN9AfoDVQGqBAAD
|
||||
MwFRA2gB8AHzAcYBWAH/AfoB5wG4Fv8B/gH7Af8B+QHiAaoB/wHvAbgBLQH/A04BlgQCBAADPAFmA2MB
|
||||
1QN8AfgB/wG+AYUC/wGqAV8C/wGZAT4C/wGNAScC/wGGARoC/wGDARUC/wGFARkC/wGKASIC/wGNASgC
|
||||
/wGTATMB/wJuAWgB9QNdAcUDNgFZBP8B9AHNAWwB/wH0AcsBZgH/AfQBywFlAf8B9AHLAWUB/wHxAcEB
|
||||
SQH/AfkB4wGsAf8DiQH/A4kB/wOJAf8DiQH/A4kB/wOJAf8DiQH/A4kB/wOaAf8DBgEIAzEBTANQAZsD
|
||||
ZQHsA30B+gOBAf8DgQH/A4EB/wOBAf8DgQH/A4EB/wOBAf8DfQH6A2oB7QNQAZsDLwFJCAADIgExA18B
|
||||
yQJ9AWcB+gHzAcoBZQH/AfkB4QGmAf8B+wHtAcwB/wH7AewByAH/AfgB3QGbAf8DgAH+AmUBXgHiAz0B
|
||||
aAQBDAADQgFyA2MB1QNqAfkB/wHJAZkC/wG8AX8C/wGuAWYC/wGkAVMC/wGfAUoC/wGfAUsC/wGjAVEC
|
||||
/wGnAVgB/wN8AfgDXQHHAzsBYgQAQP8IAAMFAQYDEgEXAzoBYANRAZ8DXwHTA2cB7wNjAfYDYgHuA14B
|
||||
0gNRAZ4DOQFfAxEBFgMFAQYUAAMPARMDRwGCA2QB2wJ+AW8B/ANnAeoDVAGoAygBOxwAAzwBZQNeAdIB
|
||||
/wHvAeAC/wHcAbwC/wHNAZ8C/wHBAYoC/wG7AX8C/wG/AYYC/wHNAaEC/wHpAdYB/wNcAcQDNQFVCAAB
|
||||
QgFNAT4HAAE+AwABKAMAAUADAAEgAwABAQEAAQEGAAEBFgAD/4UAAf8B/AHAAQMEAAH/AfwBgAEBBAAB
|
||||
/wH5BgAB/wH5BgAB8AETBgABwAEDBAAC/wGAAQEEAAHAAQEBgAEBBAABgAIAAQEHAAEBBwABAQcAAQEH
|
||||
AAEBBgABgAEBBgABwAEDAYABAQIAAcABAQHwAR8BwAEDCw==
|
||||
</value>
|
||||
</data>
|
||||
<metadata name="ctxmChangeStatus.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
@ -627,8 +628,14 @@
|
||||
AB/+AAA//wAAf/+AAP//4AP///4///////8=
|
||||
</value>
|
||||
</data>
|
||||
<metadata name="ctxmAdminUserList.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>461, 24</value>
|
||||
</metadata>
|
||||
<metadata name="ctxmAdminRoomList.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>461, 49</value>
|
||||
</metadata>
|
||||
<metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>133</value>
|
||||
<value>90</value>
|
||||
</metadata>
|
||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
|
50
qtc-net-client-2/Forms/Profile.Designer.cs
generated
50
qtc-net-client-2/Forms/Profile.Designer.cs
generated
@ -37,25 +37,22 @@
|
||||
btnDecline = new Button();
|
||||
btnCancelRequest = new Button();
|
||||
btnMessage = new Button();
|
||||
pbUserStatus = new PictureBox();
|
||||
pbCurrencyIcon = new PictureBox();
|
||||
lblCurrencyAmount = new Label();
|
||||
flpUsernameCurrency = new FlowLayoutPanel();
|
||||
panel1 = new Panel();
|
||||
pCurrency = new Panel();
|
||||
((System.ComponentModel.ISupportInitialize)pbUserPfp).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)pbUserStatus).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)pbCurrencyIcon).BeginInit();
|
||||
flpUsernameCurrency.SuspendLayout();
|
||||
panel1.SuspendLayout();
|
||||
pCurrency.SuspendLayout();
|
||||
SuspendLayout();
|
||||
//
|
||||
// pbUserPfp
|
||||
//
|
||||
pbUserPfp.BorderStyle = BorderStyle.FixedSingle;
|
||||
pbUserPfp.Image = Properties.Resources.DefaultPfp;
|
||||
pbUserPfp.Location = new Point(12, 12);
|
||||
pbUserPfp.Location = new Point(9, 5);
|
||||
pbUserPfp.Name = "pbUserPfp";
|
||||
pbUserPfp.Size = new Size(128, 126);
|
||||
pbUserPfp.Size = new Size(139, 138);
|
||||
pbUserPfp.SizeMode = PictureBoxSizeMode.StretchImage;
|
||||
pbUserPfp.TabIndex = 2;
|
||||
pbUserPfp.TabStop = false;
|
||||
@ -64,7 +61,7 @@
|
||||
//
|
||||
lblUsername.AutoSize = true;
|
||||
lblUsername.Font = new Font("Segoe UI Light", 15F, FontStyle.Bold);
|
||||
lblUsername.ForeColor = SystemColors.ControlLight;
|
||||
lblUsername.ForeColor = Color.White;
|
||||
lblUsername.Location = new Point(3, 0);
|
||||
lblUsername.Name = "lblUsername";
|
||||
lblUsername.Size = new Size(105, 28);
|
||||
@ -149,17 +146,6 @@
|
||||
btnMessage.Visible = false;
|
||||
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.Image = Properties.Resources.CurrencyIcon;
|
||||
@ -188,21 +174,21 @@
|
||||
//
|
||||
flpUsernameCurrency.BackColor = Color.Transparent;
|
||||
flpUsernameCurrency.Controls.Add(lblUsername);
|
||||
flpUsernameCurrency.Controls.Add(panel1);
|
||||
flpUsernameCurrency.Controls.Add(pCurrency);
|
||||
flpUsernameCurrency.Location = new Point(152, 8);
|
||||
flpUsernameCurrency.Name = "flpUsernameCurrency";
|
||||
flpUsernameCurrency.Size = new Size(246, 33);
|
||||
flpUsernameCurrency.TabIndex = 13;
|
||||
flpUsernameCurrency.WrapContents = false;
|
||||
//
|
||||
// panel1
|
||||
// pCurrency
|
||||
//
|
||||
panel1.Controls.Add(pbCurrencyIcon);
|
||||
panel1.Controls.Add(lblCurrencyAmount);
|
||||
panel1.Location = new Point(114, 3);
|
||||
panel1.Name = "panel1";
|
||||
panel1.Size = new Size(73, 24);
|
||||
panel1.TabIndex = 14;
|
||||
pCurrency.Controls.Add(pbCurrencyIcon);
|
||||
pCurrency.Controls.Add(lblCurrencyAmount);
|
||||
pCurrency.Location = new Point(114, 3);
|
||||
pCurrency.Name = "pCurrency";
|
||||
pCurrency.Size = new Size(73, 24);
|
||||
pCurrency.TabIndex = 14;
|
||||
//
|
||||
// Profile
|
||||
//
|
||||
@ -214,12 +200,12 @@
|
||||
Controls.Add(btnAccept);
|
||||
Controls.Add(btnDecline);
|
||||
Controls.Add(btnCancelRequest);
|
||||
Controls.Add(pbUserStatus);
|
||||
Controls.Add(btnAddContact);
|
||||
Controls.Add(rtxtBio);
|
||||
Controls.Add(pbUserPfp);
|
||||
Controls.Add(btnMessage);
|
||||
Font = new Font("Segoe UI Light", 9F);
|
||||
ForeColor = Color.White;
|
||||
FormBorderStyle = FormBorderStyle.FixedDialog;
|
||||
Icon = (Icon)resources.GetObject("$this.Icon");
|
||||
MaximizeBox = false;
|
||||
@ -230,12 +216,11 @@
|
||||
FormClosed += Profile_FormClosed;
|
||||
Load += frmProfile_Load;
|
||||
((System.ComponentModel.ISupportInitialize)pbUserPfp).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)pbUserStatus).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)pbCurrencyIcon).EndInit();
|
||||
flpUsernameCurrency.ResumeLayout(false);
|
||||
flpUsernameCurrency.PerformLayout();
|
||||
panel1.ResumeLayout(false);
|
||||
panel1.PerformLayout();
|
||||
pCurrency.ResumeLayout(false);
|
||||
pCurrency.PerformLayout();
|
||||
ResumeLayout(false);
|
||||
}
|
||||
|
||||
@ -249,10 +234,9 @@
|
||||
private Button btnDecline;
|
||||
private Button btnCancelRequest;
|
||||
private Button btnMessage;
|
||||
private PictureBox pbUserStatus;
|
||||
private PictureBox pbCurrencyIcon;
|
||||
private Label lblCurrencyAmount;
|
||||
private FlowLayoutPanel flpUsernameCurrency;
|
||||
private Panel panel1;
|
||||
private Panel pCurrency;
|
||||
}
|
||||
}
|
@ -1,18 +1,25 @@
|
||||
using QtCNETAPI.Dtos.User;
|
||||
using QtCNETAPI.Services.ApiService;
|
||||
using qtc_net_client_2.ClientModel;
|
||||
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.GatewayService;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Design;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using QtCNETAPI.Services.GatewayService;
|
||||
using qtc_net_client_2.ClientModel;
|
||||
using qtc_net_client_2.Properties;
|
||||
|
||||
namespace qtc_net_client_2.Forms
|
||||
{
|
||||
@ -23,50 +30,66 @@ namespace qtc_net_client_2.Forms
|
||||
private IGatewayService _gatewayService;
|
||||
|
||||
private ServiceResponse<byte[]>? pfpRes;
|
||||
byte[]? cosmeticRes;
|
||||
|
||||
private List<Contact> contactsList;
|
||||
public Profile(UserInformationDto userInfo, ServiceResponse<byte[]>? pfp, List<Contact> contacts, IApiService apiService, IGatewayService gatewayService)
|
||||
public Profile(UserInformationDto userInfo, ServiceResponse<byte[]>? pfp, List<Contact> contacts, IApiService apiService, IGatewayService gatewayService, byte[]? cosmetic = null)
|
||||
{
|
||||
_userInformationDto = userInfo;
|
||||
_apiService = apiService;
|
||||
_gatewayService = gatewayService;
|
||||
pfpRes = pfp;
|
||||
cosmeticRes = cosmetic;
|
||||
contactsList = contacts;
|
||||
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void frmProfile_Load(object sender, EventArgs e)
|
||||
private async void frmProfile_Load(object sender, EventArgs e)
|
||||
{
|
||||
lblUsername.Text = _userInformationDto.Username;
|
||||
lblCurrencyAmount.Text = _userInformationDto.CurrencyAmount.ToString("N0");
|
||||
rtxtBio.Text = _userInformationDto.Bio;
|
||||
|
||||
Bitmap? pfp = null;
|
||||
if (pfpRes != null && pfpRes.Success && pfpRes.Data != null)
|
||||
{
|
||||
using (var ms = new MemoryStream(pfpRes.Data))
|
||||
{
|
||||
pbUserPfp.Image = Image.FromStream(ms);
|
||||
ms.Dispose();
|
||||
pfp = new Bitmap(ms);
|
||||
}
|
||||
}
|
||||
|
||||
var userStatus = (UserStatus)_userInformationDto.Status;
|
||||
Bitmap precenseImage = Resources.OnlineIcon;
|
||||
switch (userStatus)
|
||||
{
|
||||
case UserStatus.Online:
|
||||
pbUserStatus.Image = Resources.OnlineIcon;
|
||||
precenseImage = Resources.OnlineIcon;
|
||||
break;
|
||||
case UserStatus.Away:
|
||||
pbUserStatus.Image = Resources.AwayIcon;
|
||||
precenseImage = Resources.AwayIcon;
|
||||
break;
|
||||
case UserStatus.DoNotDisturb:
|
||||
pbUserStatus.Image = Resources.DNDIcon;
|
||||
precenseImage = Resources.DNDIcon;
|
||||
break;
|
||||
case UserStatus.Offline:
|
||||
pbUserStatus.Image = Resources.OfflineIcon;
|
||||
precenseImage = Resources.OfflineIcon;
|
||||
break;
|
||||
}
|
||||
|
||||
Bitmap? cosmetic = null;
|
||||
if(cosmeticRes != null)
|
||||
{
|
||||
using var ms = new MemoryStream(cosmeticRes);
|
||||
cosmetic = new Bitmap(ms);
|
||||
}
|
||||
|
||||
CreateProfileImage(precenseImage, pfp, cosmetic);
|
||||
precenseImage.Dispose();
|
||||
pfp?.Dispose();
|
||||
cosmetic?.Dispose();
|
||||
|
||||
if (_userInformationDto.Id == _apiService.CurrentUser!.Id)
|
||||
{
|
||||
btnAddContact.Visible = false;
|
||||
@ -153,8 +176,6 @@ namespace qtc_net_client_2.Forms
|
||||
btnAddContact.Enabled = false;
|
||||
using (var ms = new MemoryStream(Resources.RequestSentIcon)) { btnAddContact.Image = Image.FromStream(ms); ms.Dispose(); }
|
||||
btnCancelRequest.Visible = true;
|
||||
|
||||
await _gatewayService.RefreshContactsForUser(_userInformationDto);
|
||||
}
|
||||
}
|
||||
|
||||
@ -166,8 +187,6 @@ namespace qtc_net_client_2.Forms
|
||||
btnAddContact.Image = Resources.AddContactIcon;
|
||||
btnAddContact.Click += btnAddContact_Click_Add;
|
||||
btnMessage.Visible = false;
|
||||
|
||||
await _gatewayService.RefreshContactsForUser(_userInformationDto);
|
||||
}
|
||||
}
|
||||
|
||||
@ -183,8 +202,6 @@ namespace qtc_net_client_2.Forms
|
||||
btnAddContact.Image = Resources.RemoveContactIcon;
|
||||
btnAddContact.Click += btnAddContact_Click_Remove;
|
||||
if (_userInformationDto.Status >= 1) btnMessage.Visible = true;
|
||||
|
||||
await _gatewayService.RefreshContactsForUser(_userInformationDto);
|
||||
}
|
||||
}
|
||||
|
||||
@ -199,8 +216,6 @@ namespace qtc_net_client_2.Forms
|
||||
btnAddContact.Visible = true;
|
||||
btnAddContact.Image = Resources.AddContactIcon;
|
||||
btnAddContact.Click += btnAddContact_Click_Add;
|
||||
|
||||
await _gatewayService.RefreshContactsForUser(_userInformationDto);
|
||||
}
|
||||
}
|
||||
|
||||
@ -214,8 +229,6 @@ namespace qtc_net_client_2.Forms
|
||||
btnAddContact.Click += btnAddContact_Click_Add;
|
||||
|
||||
btnCancelRequest.Visible = false;
|
||||
|
||||
await _gatewayService.RefreshContactsForUser(_userInformationDto);
|
||||
}
|
||||
}
|
||||
|
||||
@ -225,5 +238,32 @@ 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
32
qtc-net-client-2/Forms/ProfileEdit.Designer.cs
generated
32
qtc-net-client-2/Forms/ProfileEdit.Designer.cs
generated
@ -33,6 +33,8 @@
|
||||
rtxtBio = new RichTextBox();
|
||||
lblBio = new Label();
|
||||
btnSave = new Button();
|
||||
cbCosmetic = new ComboBox();
|
||||
lblCosmetic = new Label();
|
||||
SuspendLayout();
|
||||
//
|
||||
// tbUsername
|
||||
@ -71,7 +73,7 @@
|
||||
// btnSave
|
||||
//
|
||||
btnSave.ForeColor = Color.Black;
|
||||
btnSave.Location = new Point(76, 148);
|
||||
btnSave.Location = new Point(76, 177);
|
||||
btnSave.Name = "btnSave";
|
||||
btnSave.Size = new Size(43, 23);
|
||||
btnSave.TabIndex = 4;
|
||||
@ -79,12 +81,32 @@
|
||||
btnSave.UseVisualStyleBackColor = true;
|
||||
btnSave.Click += btnSave_Click;
|
||||
//
|
||||
// frmProfileEdit
|
||||
// cbCosmetic
|
||||
//
|
||||
cbCosmetic.FormattingEnabled = true;
|
||||
cbCosmetic.Items.AddRange(new object[] { "(None)" });
|
||||
cbCosmetic.Location = new Point(76, 148);
|
||||
cbCosmetic.Name = "cbCosmetic";
|
||||
cbCosmetic.Size = new Size(121, 23);
|
||||
cbCosmetic.TabIndex = 5;
|
||||
//
|
||||
// lblCosmetic
|
||||
//
|
||||
lblCosmetic.AutoSize = true;
|
||||
lblCosmetic.Location = new Point(21, 151);
|
||||
lblCosmetic.Name = "lblCosmetic";
|
||||
lblCosmetic.Size = new Size(53, 15);
|
||||
lblCosmetic.TabIndex = 6;
|
||||
lblCosmetic.Text = "Cosmetic";
|
||||
//
|
||||
// ProfileEdit
|
||||
//
|
||||
AutoScaleDimensions = new SizeF(6F, 15F);
|
||||
AutoScaleMode = AutoScaleMode.Font;
|
||||
BackColor = Color.DodgerBlue;
|
||||
ClientSize = new Size(345, 187);
|
||||
ClientSize = new Size(345, 208);
|
||||
Controls.Add(lblCosmetic);
|
||||
Controls.Add(cbCosmetic);
|
||||
Controls.Add(btnSave);
|
||||
Controls.Add(lblBio);
|
||||
Controls.Add(rtxtBio);
|
||||
@ -95,7 +117,7 @@
|
||||
FormBorderStyle = FormBorderStyle.FixedDialog;
|
||||
MaximizeBox = false;
|
||||
MinimizeBox = false;
|
||||
Name = "frmProfileEdit";
|
||||
Name = "ProfileEdit";
|
||||
StartPosition = FormStartPosition.CenterParent;
|
||||
Text = "QtC.NET Client - Edit Profile";
|
||||
Load += frmProfileEdit_Load;
|
||||
@ -110,5 +132,7 @@
|
||||
private RichTextBox rtxtBio;
|
||||
private Label lblBio;
|
||||
private Button btnSave;
|
||||
private ComboBox cbCosmetic;
|
||||
private Label lblCosmetic;
|
||||
}
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
using QtCNETAPI.Dtos.User;
|
||||
using Microsoft.AspNetCore.Mvc.TagHelpers;
|
||||
using qtc_net_client_2.ClientModel;
|
||||
using QtCNETAPI.Dtos.User;
|
||||
using QtCNETAPI.Services.ApiService;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@ -21,16 +23,54 @@ namespace qtc_net_client_2.Forms
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void frmProfileEdit_Load(object sender, EventArgs e)
|
||||
private async void frmProfileEdit_Load(object sender, EventArgs e)
|
||||
{
|
||||
tbUsername.Text = _apiService.CurrentUser!.Username;
|
||||
rtxtBio.Text = _apiService.CurrentUser!.Bio;
|
||||
tbUsername.Text = _apiService.CurrentUser.Username;
|
||||
rtxtBio.Text = _apiService.CurrentUser.Bio;
|
||||
|
||||
// get all owned cosmetics
|
||||
var boughtItems = await _apiService.GetOwnedStoreItems();
|
||||
List<ComboBoxItem> items = new List<ComboBoxItem>();
|
||||
|
||||
if(boughtItems != null && boughtItems.Success && boughtItems.Data != null)
|
||||
{
|
||||
items.Add(new ComboBoxItem
|
||||
{
|
||||
Name = "(None)",
|
||||
Value = 0
|
||||
});
|
||||
|
||||
foreach (var item in boughtItems.Data)
|
||||
{
|
||||
// get item from the store
|
||||
var storeItem = await _apiService.GetStoreItem(item.StoreItemId);
|
||||
if(storeItem != null && storeItem.Success && storeItem.Data != null)
|
||||
{
|
||||
var cbi = new ComboBoxItem
|
||||
{
|
||||
Name = storeItem.Data.Name,
|
||||
Value = storeItem.Data.Id
|
||||
};
|
||||
items.Add(cbi);
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
items.Add(new ComboBoxItem
|
||||
{
|
||||
Name = "(None)",
|
||||
Value = 0
|
||||
});
|
||||
}
|
||||
|
||||
cbCosmetic.DataSource = items;
|
||||
cbCosmetic.SelectedIndex = cbCosmetic.Items.IndexOf(items.FirstOrDefault(e => (int?)e.Value == _apiService.CurrentUser.ActiveProfileCosmetic));
|
||||
}
|
||||
|
||||
private async void btnSave_Click(object sender, EventArgs e)
|
||||
{
|
||||
if(!string.IsNullOrEmpty(tbUsername.Text) && (tbUsername.Text != _apiService.CurrentUser!.Username || rtxtBio.Text != _apiService.CurrentUser!.Bio))
|
||||
{
|
||||
ComboBoxItem? selectedItem = (ComboBoxItem?)cbCosmetic.SelectedItem;
|
||||
|
||||
// update user info
|
||||
UserUpdateInformationDto userUpdateInformationDto = new UserUpdateInformationDto
|
||||
{
|
||||
@ -40,6 +80,12 @@ namespace qtc_net_client_2.Forms
|
||||
DateOfBirth = _apiService.CurrentUser.DateOfBirth
|
||||
};
|
||||
|
||||
if (selectedItem != null)
|
||||
{
|
||||
int selectedItemId = (int?)selectedItem.Value ?? 0;
|
||||
userUpdateInformationDto.ProfileCosmeticId = selectedItemId;
|
||||
}
|
||||
|
||||
var res = await _apiService.UpdateUserInformationAsync(userUpdateInformationDto);
|
||||
|
||||
if (res.Success)
|
||||
@ -55,5 +101,4 @@ namespace qtc_net_client_2.Forms
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ namespace qtc_net_client_2.Forms
|
||||
|
||||
if(registerResult.Success)
|
||||
{
|
||||
MessageBox.Show("Registration Complete. If the server has email verification on, you may need to check your email for a verification link.\nIf you do not receive one, try logging in.");
|
||||
DialogResult = DialogResult.OK;
|
||||
Close();
|
||||
} else
|
||||
|
104
qtc-net-client-2/Forms/ResendVerificationEmail.Designer.cs
generated
Normal file
104
qtc-net-client-2/Forms/ResendVerificationEmail.Designer.cs
generated
Normal file
@ -0,0 +1,104 @@
|
||||
namespace qtc_net_client_2.Forms
|
||||
{
|
||||
partial class ResendVerificationEmail
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
pbLoginBanner = new PictureBox();
|
||||
tbEmail = new TextBox();
|
||||
lblHeader = new Label();
|
||||
btnSend = new Button();
|
||||
((System.ComponentModel.ISupportInitialize)pbLoginBanner).BeginInit();
|
||||
SuspendLayout();
|
||||
//
|
||||
// pbLoginBanner
|
||||
//
|
||||
pbLoginBanner.Image = Properties.Resources.LoginBanner;
|
||||
pbLoginBanner.Location = new Point(-4, 0);
|
||||
pbLoginBanner.Name = "pbLoginBanner";
|
||||
pbLoginBanner.Size = new Size(521, 99);
|
||||
pbLoginBanner.SizeMode = PictureBoxSizeMode.StretchImage;
|
||||
pbLoginBanner.TabIndex = 1;
|
||||
pbLoginBanner.TabStop = false;
|
||||
//
|
||||
// tbEmail
|
||||
//
|
||||
tbEmail.Location = new Point(50, 124);
|
||||
tbEmail.Name = "tbEmail";
|
||||
tbEmail.Size = new Size(424, 23);
|
||||
tbEmail.TabIndex = 3;
|
||||
//
|
||||
// lblHeader
|
||||
//
|
||||
lblHeader.AutoSize = true;
|
||||
lblHeader.Font = new Font("Segoe UI Light", 9F);
|
||||
lblHeader.ForeColor = SystemColors.ControlLight;
|
||||
lblHeader.Location = new Point(54, 106);
|
||||
lblHeader.Name = "lblHeader";
|
||||
lblHeader.Size = new Size(412, 15);
|
||||
lblHeader.TabIndex = 5;
|
||||
lblHeader.Text = "Please Enter Your Email, If An Account Exists With This Email, We'll Send You A Link";
|
||||
//
|
||||
// btnSend
|
||||
//
|
||||
btnSend.Location = new Point(224, 153);
|
||||
btnSend.Name = "btnSend";
|
||||
btnSend.Size = new Size(75, 23);
|
||||
btnSend.TabIndex = 6;
|
||||
btnSend.Text = "Send";
|
||||
btnSend.UseVisualStyleBackColor = true;
|
||||
btnSend.Click += btnSend_Click;
|
||||
//
|
||||
// ResendVerificationEmail
|
||||
//
|
||||
AutoScaleDimensions = new SizeF(7F, 15F);
|
||||
AutoScaleMode = AutoScaleMode.Font;
|
||||
BackColor = Color.DodgerBlue;
|
||||
ClientSize = new Size(515, 187);
|
||||
Controls.Add(btnSend);
|
||||
Controls.Add(lblHeader);
|
||||
Controls.Add(tbEmail);
|
||||
Controls.Add(pbLoginBanner);
|
||||
FormBorderStyle = FormBorderStyle.FixedDialog;
|
||||
MaximizeBox = false;
|
||||
MinimizeBox = false;
|
||||
Name = "ResendVerificationEmail";
|
||||
StartPosition = FormStartPosition.CenterScreen;
|
||||
Text = "QtC.NET Client - Resend Verification Email";
|
||||
((System.ComponentModel.ISupportInitialize)pbLoginBanner).EndInit();
|
||||
ResumeLayout(false);
|
||||
PerformLayout();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private PictureBox pbLoginBanner;
|
||||
private TextBox tbEmail;
|
||||
private Label lblHeader;
|
||||
private Button btnSend;
|
||||
}
|
||||
}
|
43
qtc-net-client-2/Forms/ResendVerificationEmail.cs
Normal file
43
qtc-net-client-2/Forms/ResendVerificationEmail.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using QtCNETAPI.Services.ApiService;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace qtc_net_client_2.Forms
|
||||
{
|
||||
public partial class ResendVerificationEmail : Form
|
||||
{
|
||||
private IApiService _apiService;
|
||||
public ResendVerificationEmail(IApiService apiService)
|
||||
{
|
||||
_apiService = apiService;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private async void btnSend_Click(object sender, EventArgs e)
|
||||
{
|
||||
if(!string.IsNullOrEmpty(tbEmail.Text))
|
||||
{
|
||||
tbEmail.Enabled = false;
|
||||
btnSend.Enabled = false;
|
||||
|
||||
var result = await _apiService.ResendVerificationEmail(tbEmail.Text);
|
||||
if(result != null && result.Success && result.Data)
|
||||
{
|
||||
MessageBox.Show("Got It! You should receive an email shortly.\nIf you do not receive an email, check your spam.", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
Close();
|
||||
} else
|
||||
{
|
||||
MessageBox.Show("Sorry, This Server Doesn't Have Email Features Enabled Or Something Went Wrong.\nIf you cannot login, you may need to contact the server admin.", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
120
qtc-net-client-2/Forms/ResendVerificationEmail.resx
Normal file
120
qtc-net-client-2/Forms/ResendVerificationEmail.resx
Normal file
@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
221
qtc-net-client-2/Forms/ResetPassword.Designer.cs
generated
Normal file
221
qtc-net-client-2/Forms/ResetPassword.Designer.cs
generated
Normal file
@ -0,0 +1,221 @@
|
||||
namespace qtc_net_client_2.Forms
|
||||
{
|
||||
partial class ResetPassword
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
pEmailBox = new Panel();
|
||||
btnSend = new Button();
|
||||
lblHeader = new Label();
|
||||
tbEmail = new TextBox();
|
||||
pResetPasswordBox = new Panel();
|
||||
btnResetPassword = new Button();
|
||||
tbConfirmPassword = new TextBox();
|
||||
lblConfirmPassword = new Label();
|
||||
tbNewPassword = new TextBox();
|
||||
lblNewPassword = new Label();
|
||||
tbToken = new TextBox();
|
||||
lblToken = new Label();
|
||||
pbLoginBanner = new PictureBox();
|
||||
pEmailBox.SuspendLayout();
|
||||
pResetPasswordBox.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)pbLoginBanner).BeginInit();
|
||||
SuspendLayout();
|
||||
//
|
||||
// pEmailBox
|
||||
//
|
||||
pEmailBox.Anchor = AnchorStyles.Bottom;
|
||||
pEmailBox.BorderStyle = BorderStyle.FixedSingle;
|
||||
pEmailBox.Controls.Add(btnSend);
|
||||
pEmailBox.Controls.Add(lblHeader);
|
||||
pEmailBox.Controls.Add(tbEmail);
|
||||
pEmailBox.Location = new Point(101, 125);
|
||||
pEmailBox.Name = "pEmailBox";
|
||||
pEmailBox.Size = new Size(458, 94);
|
||||
pEmailBox.TabIndex = 0;
|
||||
//
|
||||
// btnSend
|
||||
//
|
||||
btnSend.Location = new Point(193, 59);
|
||||
btnSend.Name = "btnSend";
|
||||
btnSend.Size = new Size(75, 23);
|
||||
btnSend.TabIndex = 9;
|
||||
btnSend.Text = "Send";
|
||||
btnSend.UseVisualStyleBackColor = true;
|
||||
btnSend.Click += btnSend_Click;
|
||||
//
|
||||
// lblHeader
|
||||
//
|
||||
lblHeader.AutoSize = true;
|
||||
lblHeader.Font = new Font("Segoe UI Light", 9F);
|
||||
lblHeader.ForeColor = SystemColors.ControlLight;
|
||||
lblHeader.Location = new Point(23, 12);
|
||||
lblHeader.Name = "lblHeader";
|
||||
lblHeader.Size = new Size(412, 15);
|
||||
lblHeader.TabIndex = 8;
|
||||
lblHeader.Text = "Please Enter Your Email, If An Account Exists With This Email, We'll Send You A Link";
|
||||
//
|
||||
// tbEmail
|
||||
//
|
||||
tbEmail.Location = new Point(19, 30);
|
||||
tbEmail.Name = "tbEmail";
|
||||
tbEmail.Size = new Size(424, 23);
|
||||
tbEmail.TabIndex = 7;
|
||||
//
|
||||
// pResetPasswordBox
|
||||
//
|
||||
pResetPasswordBox.Anchor = AnchorStyles.Bottom;
|
||||
pResetPasswordBox.BorderStyle = BorderStyle.FixedSingle;
|
||||
pResetPasswordBox.Controls.Add(btnResetPassword);
|
||||
pResetPasswordBox.Controls.Add(tbConfirmPassword);
|
||||
pResetPasswordBox.Controls.Add(lblConfirmPassword);
|
||||
pResetPasswordBox.Controls.Add(tbNewPassword);
|
||||
pResetPasswordBox.Controls.Add(lblNewPassword);
|
||||
pResetPasswordBox.Controls.Add(tbToken);
|
||||
pResetPasswordBox.Controls.Add(lblToken);
|
||||
pResetPasswordBox.Location = new Point(17, 106);
|
||||
pResetPasswordBox.Name = "pResetPasswordBox";
|
||||
pResetPasswordBox.Size = new Size(596, 138);
|
||||
pResetPasswordBox.TabIndex = 1;
|
||||
pResetPasswordBox.Visible = false;
|
||||
//
|
||||
// btnResetPassword
|
||||
//
|
||||
btnResetPassword.Location = new Point(270, 102);
|
||||
btnResetPassword.Name = "btnResetPassword";
|
||||
btnResetPassword.Size = new Size(100, 23);
|
||||
btnResetPassword.TabIndex = 15;
|
||||
btnResetPassword.Text = "Reset Password";
|
||||
btnResetPassword.UseVisualStyleBackColor = true;
|
||||
btnResetPassword.Click += btnResetPassword_Click;
|
||||
//
|
||||
// tbConfirmPassword
|
||||
//
|
||||
tbConfirmPassword.Location = new Point(123, 73);
|
||||
tbConfirmPassword.Name = "tbConfirmPassword";
|
||||
tbConfirmPassword.PasswordChar = '*';
|
||||
tbConfirmPassword.Size = new Size(424, 23);
|
||||
tbConfirmPassword.TabIndex = 14;
|
||||
//
|
||||
// lblConfirmPassword
|
||||
//
|
||||
lblConfirmPassword.AutoSize = true;
|
||||
lblConfirmPassword.Font = new Font("Segoe UI Light", 9F);
|
||||
lblConfirmPassword.ForeColor = SystemColors.ControlLight;
|
||||
lblConfirmPassword.Location = new Point(20, 76);
|
||||
lblConfirmPassword.Name = "lblConfirmPassword";
|
||||
lblConfirmPassword.Size = new Size(97, 15);
|
||||
lblConfirmPassword.TabIndex = 13;
|
||||
lblConfirmPassword.Text = "Confirm Password";
|
||||
//
|
||||
// tbNewPassword
|
||||
//
|
||||
tbNewPassword.Location = new Point(123, 44);
|
||||
tbNewPassword.Name = "tbNewPassword";
|
||||
tbNewPassword.PasswordChar = '*';
|
||||
tbNewPassword.Size = new Size(424, 23);
|
||||
tbNewPassword.TabIndex = 12;
|
||||
//
|
||||
// lblNewPassword
|
||||
//
|
||||
lblNewPassword.AutoSize = true;
|
||||
lblNewPassword.Font = new Font("Segoe UI Light", 9F);
|
||||
lblNewPassword.ForeColor = SystemColors.ControlLight;
|
||||
lblNewPassword.Location = new Point(36, 47);
|
||||
lblNewPassword.Name = "lblNewPassword";
|
||||
lblNewPassword.Size = new Size(81, 15);
|
||||
lblNewPassword.TabIndex = 11;
|
||||
lblNewPassword.Text = "New Password";
|
||||
//
|
||||
// tbToken
|
||||
//
|
||||
tbToken.Location = new Point(123, 15);
|
||||
tbToken.Name = "tbToken";
|
||||
tbToken.Size = new Size(424, 23);
|
||||
tbToken.TabIndex = 10;
|
||||
//
|
||||
// lblToken
|
||||
//
|
||||
lblToken.AutoSize = true;
|
||||
lblToken.Font = new Font("Segoe UI Light", 9F);
|
||||
lblToken.ForeColor = SystemColors.ControlLight;
|
||||
lblToken.Location = new Point(82, 18);
|
||||
lblToken.Name = "lblToken";
|
||||
lblToken.Size = new Size(35, 15);
|
||||
lblToken.TabIndex = 9;
|
||||
lblToken.Text = "Token";
|
||||
//
|
||||
// pbLoginBanner
|
||||
//
|
||||
pbLoginBanner.Image = Properties.Resources.LoginBanner;
|
||||
pbLoginBanner.Location = new Point(-3, -1);
|
||||
pbLoginBanner.Name = "pbLoginBanner";
|
||||
pbLoginBanner.Size = new Size(521, 99);
|
||||
pbLoginBanner.SizeMode = PictureBoxSizeMode.StretchImage;
|
||||
pbLoginBanner.TabIndex = 2;
|
||||
pbLoginBanner.TabStop = false;
|
||||
//
|
||||
// ResetPassword
|
||||
//
|
||||
AutoScaleDimensions = new SizeF(7F, 15F);
|
||||
AutoScaleMode = AutoScaleMode.Font;
|
||||
BackColor = Color.DodgerBlue;
|
||||
ClientSize = new Size(622, 256);
|
||||
Controls.Add(pEmailBox);
|
||||
Controls.Add(pResetPasswordBox);
|
||||
Controls.Add(pbLoginBanner);
|
||||
FormBorderStyle = FormBorderStyle.FixedDialog;
|
||||
MaximizeBox = false;
|
||||
MinimizeBox = false;
|
||||
Name = "ResetPassword";
|
||||
StartPosition = FormStartPosition.CenterScreen;
|
||||
Text = "QtC.NET Client - Reset Password";
|
||||
pEmailBox.ResumeLayout(false);
|
||||
pEmailBox.PerformLayout();
|
||||
pResetPasswordBox.ResumeLayout(false);
|
||||
pResetPasswordBox.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)pbLoginBanner).EndInit();
|
||||
ResumeLayout(false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private Panel pEmailBox;
|
||||
private Button btnSend;
|
||||
private Label lblHeader;
|
||||
private TextBox tbEmail;
|
||||
private Panel pResetPasswordBox;
|
||||
private TextBox tbConfirmPassword;
|
||||
private Label lblConfirmPassword;
|
||||
private TextBox tbNewPassword;
|
||||
private Label lblNewPassword;
|
||||
private TextBox tbToken;
|
||||
private Label lblToken;
|
||||
private Button btnResetPassword;
|
||||
private PictureBox pbLoginBanner;
|
||||
}
|
||||
}
|
68
qtc-net-client-2/Forms/ResetPassword.cs
Normal file
68
qtc-net-client-2/Forms/ResetPassword.cs
Normal file
@ -0,0 +1,68 @@
|
||||
using QtCNETAPI.Services.ApiService;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace qtc_net_client_2.Forms
|
||||
{
|
||||
public partial class ResetPassword : Form
|
||||
{
|
||||
private IApiService _apiService;
|
||||
public ResetPassword(IApiService apiService)
|
||||
{
|
||||
_apiService = apiService;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private async void btnSend_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(tbEmail.Text))
|
||||
{
|
||||
tbEmail.Enabled = false;
|
||||
btnSend.Enabled = false;
|
||||
|
||||
var result = await _apiService.SendPasswordResetEmail(tbEmail.Text);
|
||||
if (result != null && result.Success && result.Data)
|
||||
{
|
||||
pEmailBox.Visible = false;
|
||||
pResetPasswordBox.Visible = true;
|
||||
|
||||
MessageBox.Show("Got It! You should receive an email shortly.\nIf you do not receive an email, check your spam.");
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("Sorry, This Server Doesn't Have Email Features Enabled Or Something Went Wrong.\nIf you cannot login, you may need to contact the server admin.", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async void btnResetPassword_Click(object sender, EventArgs e)
|
||||
{
|
||||
if(!string.IsNullOrEmpty(tbToken.Text) && !string.IsNullOrEmpty(tbNewPassword.Text) && !string.IsNullOrEmpty(tbConfirmPassword.Text))
|
||||
{
|
||||
tbToken.Enabled = false;
|
||||
tbNewPassword.Enabled = false;
|
||||
tbConfirmPassword.Enabled = false;
|
||||
btnResetPassword.Enabled = false;
|
||||
|
||||
var result = await _apiService.ResetPassword(new QtCNETAPI.Dtos.User.UserPasswordResetDto { Token = tbToken.Text, Password = tbNewPassword.Text });
|
||||
if(result != null && result.Success && result.Data)
|
||||
{
|
||||
MessageBox.Show("Your Password Has Been Reset. You may now login with the new password.", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
Close();
|
||||
} else
|
||||
{
|
||||
MessageBox.Show(result?.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
120
qtc-net-client-2/Forms/ResetPassword.resx
Normal file
120
qtc-net-client-2/Forms/ResetPassword.resx
Normal file
@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
12
qtc-net-client-2/Forms/StockMarketGame.Designer.cs
generated
12
qtc-net-client-2/Forms/StockMarketGame.Designer.cs
generated
@ -52,7 +52,7 @@
|
||||
pStockManagement.Controls.Add(btnSell);
|
||||
pStockManagement.Controls.Add(btnBuy);
|
||||
pStockManagement.Controls.Add(lblStockCount);
|
||||
pStockManagement.Location = new Point(242, 134);
|
||||
pStockManagement.Location = new Point(230, 138);
|
||||
pStockManagement.Name = "pStockManagement";
|
||||
pStockManagement.Size = new Size(135, 81);
|
||||
pStockManagement.TabIndex = 3;
|
||||
@ -106,7 +106,7 @@
|
||||
pMarketStatus.Controls.Add(lblMarketStatus);
|
||||
pMarketStatus.Controls.Add(pbDollarSignRight);
|
||||
pMarketStatus.Controls.Add(pbDollarSignLeft);
|
||||
pMarketStatus.Location = new Point(9, 7);
|
||||
pMarketStatus.Location = new Point(3, 7);
|
||||
pMarketStatus.Name = "pMarketStatus";
|
||||
pMarketStatus.Size = new Size(586, 100);
|
||||
pMarketStatus.TabIndex = 4;
|
||||
@ -135,7 +135,7 @@
|
||||
// pbDollarSignRight
|
||||
//
|
||||
pbDollarSignRight.Image = Properties.Resources.dollar_money;
|
||||
pbDollarSignRight.Location = new Point(498, 3);
|
||||
pbDollarSignRight.Location = new Point(500, 3);
|
||||
pbDollarSignRight.Name = "pbDollarSignRight";
|
||||
pbDollarSignRight.Size = new Size(83, 94);
|
||||
pbDollarSignRight.SizeMode = PictureBoxSizeMode.Zoom;
|
||||
@ -145,7 +145,7 @@
|
||||
// pbDollarSignLeft
|
||||
//
|
||||
pbDollarSignLeft.Image = Properties.Resources.dollar_money;
|
||||
pbDollarSignLeft.Location = new Point(6, 3);
|
||||
pbDollarSignLeft.Location = new Point(3, 3);
|
||||
pbDollarSignLeft.Name = "pbDollarSignLeft";
|
||||
pbDollarSignLeft.Size = new Size(83, 94);
|
||||
pbDollarSignLeft.SizeMode = PictureBoxSizeMode.Zoom;
|
||||
@ -156,7 +156,7 @@
|
||||
//
|
||||
btnRefresh.Enabled = false;
|
||||
btnRefresh.ForeColor = Color.Black;
|
||||
btnRefresh.Location = new Point(282, 109);
|
||||
btnRefresh.Location = new Point(270, 113);
|
||||
btnRefresh.Name = "btnRefresh";
|
||||
btnRefresh.Size = new Size(56, 23);
|
||||
btnRefresh.TabIndex = 10;
|
||||
@ -169,7 +169,7 @@
|
||||
AutoScaleDimensions = new SizeF(7F, 15F);
|
||||
AutoScaleMode = AutoScaleMode.Font;
|
||||
BackColor = Color.DodgerBlue;
|
||||
ClientSize = new Size(606, 227);
|
||||
ClientSize = new Size(595, 227);
|
||||
Controls.Add(btnRefresh);
|
||||
Controls.Add(pMarketStatus);
|
||||
Controls.Add(pStockManagement);
|
||||
|
@ -44,19 +44,6 @@ namespace qtc_net_client_2.Forms
|
||||
_apiService.CurrentUser.StockAmount = result.Data.StockAmount;
|
||||
_apiService.CurrentUser.CurrencyAmount = result.Data.CurrencyAmount;
|
||||
|
||||
Main? mainWindow = (Main?)Application.OpenForms[0];
|
||||
if (mainWindow != null)
|
||||
{
|
||||
if (mainWindow.InvokeRequired)
|
||||
{
|
||||
mainWindow.Invoke(mainWindow.RefreshCurrencyCounter);
|
||||
}
|
||||
else
|
||||
{
|
||||
mainWindow.RefreshCurrencyCounter();
|
||||
}
|
||||
}
|
||||
|
||||
nudStockBuySellAmount.Enabled = true;
|
||||
nudStockBuySellAmount.Value = 0;
|
||||
btnBuy.Enabled = true;
|
||||
@ -95,19 +82,6 @@ namespace qtc_net_client_2.Forms
|
||||
_apiService.CurrentUser.StockAmount = result.Data.StockAmount;
|
||||
_apiService.CurrentUser.CurrencyAmount = result.Data.CurrencyAmount;
|
||||
|
||||
Main? mainWindow = (Main?)Application.OpenForms[0];
|
||||
if (mainWindow != null)
|
||||
{
|
||||
if (mainWindow.InvokeRequired)
|
||||
{
|
||||
mainWindow.Invoke(mainWindow.RefreshCurrencyCounter);
|
||||
}
|
||||
else
|
||||
{
|
||||
mainWindow.RefreshCurrencyCounter();
|
||||
}
|
||||
}
|
||||
|
||||
nudStockBuySellAmount.Enabled = true;
|
||||
nudStockBuySellAmount.Value = 0;
|
||||
btnBuy.Enabled = true;
|
||||
|
135
qtc-net-client-2/Forms/StoreItemDisplay.Designer.cs
generated
Normal file
135
qtc-net-client-2/Forms/StoreItemDisplay.Designer.cs
generated
Normal file
@ -0,0 +1,135 @@
|
||||
namespace qtc_net_client_2.Forms
|
||||
{
|
||||
partial class StoreItemDisplay
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(StoreItemDisplay));
|
||||
pbItemThumbnail = new PictureBox();
|
||||
lblName = new Label();
|
||||
lblDescription = new Label();
|
||||
btnBuy = new Button();
|
||||
pbCurrencyIcon = new PictureBox();
|
||||
lblPrice = new Label();
|
||||
((System.ComponentModel.ISupportInitialize)pbItemThumbnail).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)pbCurrencyIcon).BeginInit();
|
||||
SuspendLayout();
|
||||
//
|
||||
// pbItemThumbnail
|
||||
//
|
||||
pbItemThumbnail.Location = new Point(12, 12);
|
||||
pbItemThumbnail.Name = "pbItemThumbnail";
|
||||
pbItemThumbnail.Size = new Size(148, 141);
|
||||
pbItemThumbnail.SizeMode = PictureBoxSizeMode.StretchImage;
|
||||
pbItemThumbnail.TabIndex = 0;
|
||||
pbItemThumbnail.TabStop = false;
|
||||
//
|
||||
// lblName
|
||||
//
|
||||
lblName.AutoSize = true;
|
||||
lblName.Font = new Font("Segoe UI", 21.75F, FontStyle.Bold | FontStyle.Italic, GraphicsUnit.Point, 0);
|
||||
lblName.Location = new Point(165, 7);
|
||||
lblName.Name = "lblName";
|
||||
lblName.Size = new Size(239, 40);
|
||||
lblName.TabIndex = 1;
|
||||
lblName.Text = "Item Name Here";
|
||||
//
|
||||
// lblDescription
|
||||
//
|
||||
lblDescription.Location = new Point(169, 44);
|
||||
lblDescription.Name = "lblDescription";
|
||||
lblDescription.Size = new Size(448, 109);
|
||||
lblDescription.TabIndex = 2;
|
||||
lblDescription.Text = resources.GetString("lblDescription.Text");
|
||||
//
|
||||
// btnBuy
|
||||
//
|
||||
btnBuy.ForeColor = Color.Black;
|
||||
btnBuy.Location = new Point(542, 157);
|
||||
btnBuy.Name = "btnBuy";
|
||||
btnBuy.Size = new Size(75, 23);
|
||||
btnBuy.TabIndex = 3;
|
||||
btnBuy.Text = "Buy";
|
||||
btnBuy.UseVisualStyleBackColor = true;
|
||||
btnBuy.Click += btnBuy_Click;
|
||||
//
|
||||
// pbCurrencyIcon
|
||||
//
|
||||
pbCurrencyIcon.Image = Properties.Resources.CurrencyIcon;
|
||||
pbCurrencyIcon.Location = new Point(48, 161);
|
||||
pbCurrencyIcon.Name = "pbCurrencyIcon";
|
||||
pbCurrencyIcon.Size = new Size(15, 14);
|
||||
pbCurrencyIcon.SizeMode = PictureBoxSizeMode.StretchImage;
|
||||
pbCurrencyIcon.TabIndex = 19;
|
||||
pbCurrencyIcon.TabStop = false;
|
||||
//
|
||||
// lblPrice
|
||||
//
|
||||
lblPrice.AutoEllipsis = true;
|
||||
lblPrice.Font = new Font("Segoe UI", 8F, FontStyle.Bold, GraphicsUnit.Point, 0);
|
||||
lblPrice.Location = new Point(64, 162);
|
||||
lblPrice.Name = "lblPrice";
|
||||
lblPrice.Size = new Size(61, 13);
|
||||
lblPrice.TabIndex = 20;
|
||||
lblPrice.Text = "99,999,999";
|
||||
//
|
||||
// StoreItemDisplay
|
||||
//
|
||||
AutoScaleDimensions = new SizeF(7F, 15F);
|
||||
AutoScaleMode = AutoScaleMode.Font;
|
||||
BackColor = Color.DodgerBlue;
|
||||
ClientSize = new Size(629, 188);
|
||||
Controls.Add(lblPrice);
|
||||
Controls.Add(pbCurrencyIcon);
|
||||
Controls.Add(btnBuy);
|
||||
Controls.Add(lblDescription);
|
||||
Controls.Add(lblName);
|
||||
Controls.Add(pbItemThumbnail);
|
||||
ForeColor = Color.White;
|
||||
FormBorderStyle = FormBorderStyle.FixedDialog;
|
||||
MaximizeBox = false;
|
||||
MinimizeBox = false;
|
||||
Name = "StoreItemDisplay";
|
||||
StartPosition = FormStartPosition.CenterScreen;
|
||||
Text = "QtC.NET Client - Store Item";
|
||||
Load += StoreItemDisplay_Load;
|
||||
((System.ComponentModel.ISupportInitialize)pbItemThumbnail).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)pbCurrencyIcon).EndInit();
|
||||
ResumeLayout(false);
|
||||
PerformLayout();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private PictureBox pbItemThumbnail;
|
||||
private Label lblName;
|
||||
private Label lblDescription;
|
||||
private Button btnBuy;
|
||||
private PictureBox pbCurrencyIcon;
|
||||
private Label lblPrice;
|
||||
}
|
||||
}
|
97
qtc-net-client-2/Forms/StoreItemDisplay.cs
Normal file
97
qtc-net-client-2/Forms/StoreItemDisplay.cs
Normal file
@ -0,0 +1,97 @@
|
||||
using QtCNETAPI.Dtos.User;
|
||||
using QtCNETAPI.Schema;
|
||||
using QtCNETAPI.Services;
|
||||
using QtCNETAPI.Services.ApiService;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace qtc_net_client_2.Forms
|
||||
{
|
||||
public partial class StoreItemDisplay : Form
|
||||
{
|
||||
private StoreItem StoreItem { get; set; }
|
||||
|
||||
private LoggingService _loggingService;
|
||||
private IApiService _apiService;
|
||||
public StoreItemDisplay(StoreItem item, LoggingService loggingService, IApiService apiService)
|
||||
{
|
||||
StoreItem = item;
|
||||
_loggingService = loggingService;
|
||||
_apiService = apiService;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private async void StoreItemDisplay_Load(object sender, EventArgs e)
|
||||
{
|
||||
lblName.Text = StoreItem.Name;
|
||||
lblDescription.Text = StoreItem.Description;
|
||||
lblPrice.Text = StoreItem.Price.ToString("N0");
|
||||
|
||||
// does the user already own this item?
|
||||
var ownedItem = await _apiService.GetOwnedStoreItem(StoreItem.Id);
|
||||
if (ownedItem != null && ownedItem.Success && ownedItem.Data != null)
|
||||
{
|
||||
btnBuy.Enabled = false;
|
||||
btnBuy.Text = "Bought";
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using HttpClient client = new();
|
||||
var response = await client.GetAsync(StoreItem.ThumbnailUrl);
|
||||
if (response != null && response.IsSuccessStatusCode)
|
||||
{
|
||||
using var stream = await response.Content.ReadAsStreamAsync();
|
||||
Image image = Image.FromStream(stream);
|
||||
stream.Dispose();
|
||||
pbItemThumbnail.Image = image;
|
||||
}
|
||||
else if (response != null) _loggingService.LogString($"Store Item Thumbnail Could Not Be Loaded Due To Status Code {response.StatusCode}");
|
||||
else _loggingService.LogString("Store Item Thumbnail Could Not Be Loaded");
|
||||
client.Dispose();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_loggingService.LogString("Store Item Thumbnail Could Not Be Loaded\n" + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private async void btnBuy_Click(object sender, EventArgs e)
|
||||
{
|
||||
Enabled = false;
|
||||
|
||||
// attempt to buy item
|
||||
var ownedStoreItem = await _apiService.BuyStoreItem(StoreItem.Id);
|
||||
if (ownedStoreItem != null && ownedStoreItem.Success)
|
||||
{
|
||||
Enabled = true;
|
||||
|
||||
var result = MessageBox.Show($"Successfully Bought '{StoreItem.Name}'! Would You Like To Wear It Now?", "Success!", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
|
||||
if (result == DialogResult.Yes)
|
||||
{
|
||||
// send an update dto that only updates the current users cosmetic
|
||||
UserUpdateInformationDto updateDto = new UserUpdateInformationDto
|
||||
{
|
||||
Id = _apiService.CurrentUser.Id,
|
||||
Bio = _apiService.CurrentUser.Bio,
|
||||
DateOfBirth = _apiService.CurrentUser.DateOfBirth,
|
||||
Username = _apiService.CurrentUser.Username,
|
||||
ProfileCosmeticId = StoreItem.Id
|
||||
};
|
||||
|
||||
await _apiService.UpdateUserInformationAsync(updateDto);
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
123
qtc-net-client-2/Forms/StoreItemDisplay.resx
Normal file
123
qtc-net-client-2/Forms/StoreItemDisplay.resx
Normal file
@ -0,0 +1,123 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="lblDescription.Text" xml:space="preserve">
|
||||
<value>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum</value>
|
||||
</data>
|
||||
</root>
|
@ -261,11 +261,6 @@ namespace qtc_net_client_2
|
||||
{
|
||||
await _apiService.AddCurrencyToCurrentUser(currencyJackpotSpinner.TokensWon, false);
|
||||
_apiService.CurrentUser.CurrencyAmount += currencyJackpotSpinner.TokensWon;
|
||||
|
||||
// find the main form to refresh currency count
|
||||
Main? mainForm = (Main?)Application.OpenForms[0];
|
||||
if (mainForm != null)
|
||||
mainForm.RefreshCurrencyCounter();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
using qtc_net_client_2.ClientModel;
|
||||
using qtc_net_client_2.Services;
|
||||
using QtCNETAPI.Services;
|
||||
using QtCNETAPI.Services.ApiService;
|
||||
using QtCNETAPI.Services.GatewayService;
|
||||
using System.Text.Json;
|
||||
@ -52,8 +53,8 @@ namespace qtc_net_client_2
|
||||
|
||||
// instantiate new ApiService and GatewayService for this session
|
||||
// this will keep the gateway thread in the main thread (i think)
|
||||
IApiService api = new ApiService($"{clientConfig.ServerUrl}/api");
|
||||
IGatewayService gateway = new GatewayService($"{clientConfig.ServerUrl}/chat", api);
|
||||
IApiService api = new ApiService($"{clientConfig.ServerUrl}/api", loggingService);
|
||||
IGatewayService gateway = new GatewayService($"{clientConfig.ServerUrl}/chat", api, loggingService);
|
||||
|
||||
// ping api
|
||||
var pingResult = await api.PingServerAsync();
|
||||
|
32
qtc-net-client-2/Properties/Resources.Designer.cs
generated
32
qtc-net-client-2/Properties/Resources.Designer.cs
generated
@ -81,7 +81,7 @@ namespace qtc_net_client_2.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 5.1.
|
||||
/// Looks up a localized string similar to 6.3.4.
|
||||
/// </summary>
|
||||
internal static string AssemblyVersion {
|
||||
get {
|
||||
@ -109,6 +109,16 @@ namespace qtc_net_client_2.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap cobalt_sittingatputer {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("cobalt_sittingatputer", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
@ -159,6 +169,16 @@ namespace qtc_net_client_2.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap donatebtn {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("donatebtn", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
@ -259,6 +279,16 @@ namespace qtc_net_client_2.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap support_me_on_kofi_badge_blue {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("support_me_on_kofi_badge_blue", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
|
@ -154,12 +154,18 @@
|
||||
<data name="CurrencyIcon" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Icons\CurrencyIcon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="DefaultPfp" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\DefaultPfp.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
<data name="AddContactIcon" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Icons\AddContactIcon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="RequestSentIcon" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Icons\RequestSentIcon.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="support_me_on_kofi_badge_blue" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\support_me_on_kofi_badge_blue.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="O" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\O.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="RemoveContactIcon" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Icons\RemoveContactIcon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
@ -167,7 +173,10 @@
|
||||
<value>..\Icons\MessageIcon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="AssemblyVersion" xml:space="preserve">
|
||||
<value>5.1</value>
|
||||
<value>6.3.4</value>
|
||||
</data>
|
||||
<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>
|
||||
</data>
|
||||
<data name="LoginBanner" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\LoginBanner.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
@ -175,13 +184,13 @@
|
||||
<data name="DeclineContactIcon" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Icons\DeclineContactIcon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="AddContactIcon" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Icons\AddContactIcon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
<data name="donatebtn" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\donatebtn.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="AcceptContactIcon" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Icons\AcceptContactIcon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="O" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\O.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
<data name="DefaultPfp" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\DefaultPfp.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
</root>
|
Binary file not shown.
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 13 KiB |
BIN
qtc-net-client-2/Resources/cobalt_sittingatputer.jpg
Normal file
BIN
qtc-net-client-2/Resources/cobalt_sittingatputer.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
BIN
qtc-net-client-2/Resources/donatebtn.png
Normal file
BIN
qtc-net-client-2/Resources/donatebtn.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.5 KiB |
BIN
qtc-net-client-2/Resources/support_me_on_kofi_badge_blue.png
Normal file
BIN
qtc-net-client-2/Resources/support_me_on_kofi_badge_blue.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
@ -1,52 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Diagnostics;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace qtc_net_client_2.Services
|
||||
{
|
||||
public class LoggingService : IDisposable
|
||||
{
|
||||
private DateTime LogDate { get; set; }
|
||||
private string LogFilePath { get; set; }
|
||||
private StreamWriter LogFile { get; set; }
|
||||
public LoggingService()
|
||||
{
|
||||
LogDate = DateTime.Now;
|
||||
LogFilePath = $"./Logs/QtCClientLog_{LogDate.ToString("ddMMyyy-hhmm")}.log";
|
||||
|
||||
// create log file
|
||||
|
||||
if (!Directory.Exists("./Logs")) Directory.CreateDirectory("./Logs");
|
||||
LogFile = new StreamWriter(File.Create(LogFilePath));
|
||||
|
||||
Debug.WriteLine($"Log File Created At {LogFilePath}");
|
||||
}
|
||||
|
||||
public void LogString(string message)
|
||||
{
|
||||
Debug.WriteLine($"({DateTime.Now.ToLocalTime().ToString("hh:mm")}) {message}");
|
||||
LogFile.WriteLine($"({DateTime.Now.ToLocalTime().ToString("hh:mm")}) {message}");
|
||||
}
|
||||
|
||||
public void LogModel<T>(T model)
|
||||
{
|
||||
// serialize the model as json
|
||||
string modelSerialized = JsonSerializer.Serialize(model, options: new JsonSerializerOptions { WriteIndented = true });
|
||||
|
||||
// log it
|
||||
Debug.WriteLine($"({DateTime.Now.ToLocalTime().ToString("hh:mm")}) {modelSerialized}");
|
||||
LogFile.WriteLine($"({DateTime.Now.ToLocalTime().ToString("hh:mm")}) {modelSerialized}");
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
LogFile.WriteLine("--- END OF LOG ---");
|
||||
LogFile.Close();
|
||||
LogFile.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
@ -68,6 +68,9 @@ namespace qtc_net_client_2.Services
|
||||
|
||||
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");
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user