- tweak: server viewmodel cache

This commit is contained in:
2025-01-30 20:18:40 +03:00
parent 88402e7751
commit 329ec268cc
5 changed files with 85 additions and 94 deletions

View File

@@ -16,19 +16,11 @@ public partial class ServerListViewModel
[GenerateProperty] private ConfigurationService ConfigurationService { get; } [GenerateProperty] private ConfigurationService ConfigurationService { get; }
[GenerateProperty] private RestService RestService { get; } [GenerateProperty] private RestService RestService { get; }
public readonly List<(RobustUrl,ServerStatus)> RawFavoriteServers = new(); public ObservableCollection<ServerEntryModelView> FavoriteServers { get; } = new();
public ServerEntryModelView GetServerEntryModelView((RobustUrl, ServerStatus) server) private async void UpdateFavoriteEntries()
{ {
var model = ViewHelperService.GetViewModel<ServerEntryModelView>().WithData(server.Item1, server.Item2); FavoriteServers.Clear();
model.OnFavoriteToggle += ()=> RemoveFavorite(model);
model.IsFavorite = true;
return model;
}
private async void FetchFavorite()
{
RawFavoriteServers.Clear();
var servers = ConfigurationService.GetConfigValue(CurrentConVar.Favorites); var servers = ConfigurationService.GetConfigValue(CurrentConVar.Favorites);
if (servers is null || servers.Length == 0) if (servers is null || servers.Length == 0)
@@ -38,21 +30,9 @@ public partial class ServerListViewModel
foreach (var server in servers) foreach (var server in servers)
{ {
var uri = server.ToRobustUrl(); var s = await ServerViewContainer.Get(server.ToRobustUrl());
try s.IsFavorite = true;
{ FavoriteServers.Add(s);
var serverInfo = await RestService.GetAsync<ServerStatus>(uri.StatusUri, CancellationToken.None);
if (serverInfo.Value is null)
{
throw new Exception("Server info is null");
}
RawFavoriteServers.Add((uri, serverInfo.Value));
}
catch (Exception e)
{
RawFavoriteServers.Add((uri, new ServerStatus("ErrorLand",$"ERROR: {e.Message}",[],"",-1,-1,-1,false,DateTime.Now, -1)));
}
} }
} }
@@ -67,7 +47,7 @@ public partial class ServerListViewModel
var servers = (ConfigurationService.GetConfigValue(CurrentConVar.Favorites) ?? []).ToList(); var servers = (ConfigurationService.GetConfigValue(CurrentConVar.Favorites) ?? []).ToList();
servers.Add(robustUrl.ToString()); servers.Add(robustUrl.ToString());
ConfigurationService.SetConfigValue(CurrentConVar.Favorites, servers.ToArray()); ConfigurationService.SetConfigValue(CurrentConVar.Favorites, servers.ToArray());
FetchFavorite(); UpdateFavoriteEntries();
} }
public void RemoveFavorite(ServerEntryModelView entryModelView) public void RemoveFavorite(ServerEntryModelView entryModelView)
@@ -76,6 +56,6 @@ public partial class ServerListViewModel
servers.Remove(entryModelView.Address.ToString()); servers.Remove(entryModelView.Address.ToString());
ConfigurationService.SetConfigValue(CurrentConVar.Favorites, servers.ToArray()); ConfigurationService.SetConfigValue(CurrentConVar.Favorites, servers.ToArray());
entryModelView.IsFavorite = false; entryModelView.IsFavorite = false;
FetchFavorite(); UpdateFavoriteEntries();
} }
} }

View File

@@ -22,27 +22,30 @@ public partial class ServerListViewModel : ViewModelBase, IViewModelPage
[ObservableProperty] private string _searchText = string.Empty; [ObservableProperty] private string _searchText = string.Empty;
[ObservableProperty] private bool _isFavoriteMode; [ObservableProperty] private bool _isFavoriteMode;
public SortedList<float, ServerEntryModelView> Servers { get; } = new(Comparer<float>.Create((x,y)=>y.CompareTo(x)));
private ServerViewContainer ServerViewContainer; public ObservableCollection<ServerEntryModelView> Servers { get; }= new();
public Action? OnSearchChange; public Action? OnSearchChange;
[GenerateProperty] private HubService HubService { get; } = default!; [GenerateProperty] private HubService HubService { get; }
[GenerateProperty] private PopupMessageService PopupMessageService { get; } [GenerateProperty] private PopupMessageService PopupMessageService { get; }
[GenerateProperty, DesignConstruct] private ViewHelperService ViewHelperService { get; } = default!; [GenerateProperty] private CancellationService CancellationService { get; }
[GenerateProperty] private DebugService DebugService { get; }
[GenerateProperty, DesignConstruct] private ViewHelperService ViewHelperService { get; }
private ServerViewContainer ServerViewContainer { get; set; }
private List<ServerHubInfo> UnsortedServers { get; } = new(); private List<ServerHubInfo> UnsortedServers { get; } = new();
//Design think //Design think
protected override void InitialiseInDesignMode() protected override void InitialiseInDesignMode()
{ {
ServerViewContainer = new ServerViewContainer(this); ServerViewContainer = new ServerViewContainer(this, RestService, CancellationService, DebugService, ViewHelperService);
} }
//real think //real think
protected override void Initialise() protected override void Initialise()
{ {
ServerViewContainer = new ServerViewContainer(this); ServerViewContainer = new ServerViewContainer(this, RestService, CancellationService, DebugService, ViewHelperService);
foreach (var info in HubService.ServerList) UnsortedServers.Add(info); foreach (var info in HubService.ServerList) UnsortedServers.Add(info);
@@ -51,40 +54,35 @@ public partial class ServerListViewModel : ViewModelBase, IViewModelPage
OnSearchChange += OnChangeSearch; OnSearchChange += OnChangeSearch;
if (!HubService.IsUpdating) UpdateServerEntries(); if (!HubService.IsUpdating) UpdateServerEntries();
//FetchFavorite(); UpdateFavoriteEntries();
} }
private void UpdateServerEntries() private void UpdateServerEntries()
{ {
Servers.Clear(); Servers.Clear();
OnPropertyChanged(nameof(Servers)); Task.Run(async () =>
foreach (var info in UnsortedServers.Where(a=>CheckServerThink(a.StatusData)))
{ {
var view = ServerViewContainer.Get(info.Address.ToRobustUrl(), info.StatusData); UnsortedServers.Sort(new ServerComparer());
float players = info.StatusData.Players; foreach (var info in UnsortedServers.Where(a => CheckServerThink(a.StatusData)))
while (true)
{ {
try var view = await ServerViewContainer.Get(info.Address.ToRobustUrl(), info.StatusData);
{ Servers.Add(view);
Servers.Add(players,view);
OnPropertyChanged(nameof(Servers));
break;
}
catch (Exception e)
{
Console.WriteLine(e);
players += 0.01f;
}
} }
} });
} }
private void OnChangeSearch() private void OnChangeSearch()
{ {
if(string.IsNullOrEmpty(SearchText)) return; if(string.IsNullOrEmpty(SearchText)) return;
UpdateServerEntries(); if(IsFavoriteMode)
{
UpdateFavoriteEntries();
}
else
{
UpdateServerEntries();
}
} }
private void HubServerChangedEventArgs(HubServerChangedEventArgs obj) private void HubServerChangedEventArgs(HubServerChangedEventArgs obj)
@@ -95,7 +93,13 @@ public partial class ServerListViewModel : ViewModelBase, IViewModelPage
if (obj.Action == HubServerChangeAction.Remove) if (obj.Action == HubServerChangeAction.Remove)
foreach (var info in obj.Items) foreach (var info in obj.Items)
UnsortedServers.Remove(info); UnsortedServers.Remove(info);
if (obj.Action == HubServerChangeAction.Clear) UnsortedServers.Clear(); if (obj.Action == HubServerChangeAction.Clear)
{
UnsortedServers.Clear();
ServerViewContainer.Clear();
Servers.Clear();
UpdateFavoriteEntries();
}
} }
private bool CheckServerThink(ServerStatus hubInfo) private bool CheckServerThink(ServerStatus hubInfo)
@@ -128,18 +132,45 @@ public partial class ServerListViewModel : ViewModelBase, IViewModelPage
} }
} }
public class ServerViewContainer(ServerListViewModel serverListViewModel) public class ServerViewContainer(
ServerListViewModel serverListViewModel,
RestService restService,
CancellationService cancellationService,
DebugService debugService,
ViewHelperService viewHelperService
)
{ {
private readonly Dictionary<RobustUrl, ServerEntryModelView> _entries = new(); private readonly Dictionary<RobustUrl, ServerEntryModelView> _entries = new();
public ServerEntryModelView Get(RobustUrl url, ServerStatus serverStatus) public void Clear()
{
_entries.Clear();
}
public async Task<ServerEntryModelView> Get(RobustUrl url, ServerStatus? serverStatus = null)
{ {
if (_entries.TryGetValue(url, out var entry)) if (_entries.TryGetValue(url, out var entry))
{ {
return entry; return entry;
} }
entry = serverListViewModel.GetServerEntryModelView((url, serverStatus)); try
{
serverStatus ??= await restService.GetAsync<ServerStatus>(url.StatusUri, cancellationService.Token);
}
catch (Exception e)
{
debugService.Error(e);
serverStatus = new ServerStatus("ErrorLand", $"ERROR: {e.Message}", [], "", -1, -1, -1, false, DateTime.Now,
-1);
}
entry = viewHelperService.GetViewModel<ServerEntryModelView>().WithData(url, serverStatus);
entry.OnFavoriteToggle += () =>
{
if (entry.IsFavorite) serverListViewModel.RemoveFavorite(entry);
else serverListViewModel.AddFavorite(entry);
};
_entries.Add(url, entry); _entries.Add(url, entry);
return entry; return entry;

View File

@@ -54,10 +54,7 @@ public partial class ServerEntryModelView : ViewModelBase
{ {
try try
{ {
var result = _serverInfo = await RestService.GetAsync<ServerInfo>(Address.InfoUri, CancellationService.Token);
await RestService.GetAsync<ServerInfo>(Address.InfoUri, CancellationService.Token);
if (result.Value == null) return null;
_serverInfo = result.Value;
} }
catch (Exception e) catch (Exception e)
{ {
@@ -100,23 +97,6 @@ public partial class ServerEntryModelView : ViewModelBase
CurrLog = ViewHelperService.GetViewModel<LogPopupModelView>(); CurrLog = ViewHelperService.GetViewModel<LogPopupModelView>();
} }
public ServerEntryModelView WithData(ServerHubInfo value)
{
Status = value.StatusData;
Address = value.Address.ToRobustUrl();
Tags.Clear();
foreach (var tag in Status.Tags)
{
Tags.Add(tag);
}
foreach (var tag in value.InferredTags)
{
Tags.Add(tag);
}
return this;
}
public ServerEntryModelView WithData(RobustUrl url, ServerStatus serverStatus) public ServerEntryModelView WithData(RobustUrl url, ServerStatus serverStatus)
{ {
Status = serverStatus; Status = serverStatus;

View File

@@ -25,11 +25,11 @@
<Panel> <Panel>
<ItemsControl <ItemsControl
IsVisible="{Binding IsFavoriteMode}" IsVisible="{Binding IsFavoriteMode}"
ItemsSource="{Binding Servers.Values}" ItemsSource="{Binding FavoriteServers}"
Padding="0" /> Padding="0" />
<ItemsControl <ItemsControl
IsVisible="{Binding !IsFavoriteMode}" IsVisible="{Binding !IsFavoriteMode}"
ItemsSource="{Binding Servers.Values}" ItemsSource="{Binding Servers}"
Padding="0" /> Padding="0" />
</Panel> </Panel>
</ScrollViewer> </ScrollViewer>

View File

@@ -23,7 +23,7 @@ public class RestService
_debug = debug; _debug = debug;
} }
public async Task<RestResult<T>> GetAsync<T>(Uri uri, CancellationToken cancellationToken) public async Task<RestResult<T>> GetAsync<T>(Uri uri, CancellationToken cancellationToken) where T : notnull
{ {
var response = await _client.GetAsync(uri, cancellationToken); var response = await _client.GetAsync(uri, cancellationToken);
return await ReadResult<T>(response, cancellationToken); return await ReadResult<T>(response, cancellationToken);
@@ -35,7 +35,7 @@ public class RestService
return result.Value ?? defaultValue; return result.Value ?? defaultValue;
} }
public async Task<RestResult<K>> PostAsync<K, T>(T information, Uri uri, CancellationToken cancellationToken) public async Task<RestResult<K>> PostAsync<K, T>(T information, Uri uri, CancellationToken cancellationToken) where K : notnull
{ {
var json = JsonSerializer.Serialize(information, _serializerOptions); var json = JsonSerializer.Serialize(information, _serializerOptions);
var content = new StringContent(json, Encoding.UTF8, "application/json"); var content = new StringContent(json, Encoding.UTF8, "application/json");
@@ -43,7 +43,7 @@ public class RestService
return await ReadResult<K>(response, cancellationToken); return await ReadResult<K>(response, cancellationToken);
} }
public async Task<RestResult<T>> PostAsync<T>(Stream stream, Uri uri, CancellationToken cancellationToken) public async Task<RestResult<T>> PostAsync<T>(Stream stream, Uri uri, CancellationToken cancellationToken) where T : notnull
{ {
using var multipartFormContent = using var multipartFormContent =
new MultipartFormDataContent("Upload----" + DateTime.Now.ToString(CultureInfo.InvariantCulture)); new MultipartFormDataContent("Upload----" + DateTime.Now.ToString(CultureInfo.InvariantCulture));
@@ -52,7 +52,7 @@ public class RestService
return await ReadResult<T>(response, cancellationToken); return await ReadResult<T>(response, cancellationToken);
} }
public async Task<RestResult<T>> DeleteAsync<T>(Uri uri, CancellationToken cancellationToken) public async Task<RestResult<T>> DeleteAsync<T>(Uri uri, CancellationToken cancellationToken) where T : notnull
{ {
var response = await _client.DeleteAsync(uri, cancellationToken); var response = await _client.DeleteAsync(uri, cancellationToken);
return await ReadResult<T>(response, cancellationToken); return await ReadResult<T>(response, cancellationToken);
@@ -61,19 +61,19 @@ public class RestService
private async Task<RestResult<T>> ReadResult<T>(HttpResponseMessage response, CancellationToken cancellationToken) where T : notnull private async Task<RestResult<T>> ReadResult<T>(HttpResponseMessage response, CancellationToken cancellationToken) where T : notnull
{ {
var content = await response.Content.ReadAsStringAsync(cancellationToken); var content = await response.Content.ReadAsStringAsync(cancellationToken);
if (typeof(T) == typeof(RawResult))
return (new RestResult<RawResult>(new RawResult(content), null, response.StatusCode) as RestResult<T>)!;
if (response.IsSuccessStatusCode) if (response.IsSuccessStatusCode)
{ {
_debug.Debug($"SUCCESSFUL GET CONTENT {typeof(T)}"); _debug.Debug($"SUCCESSFUL GET CONTENT {typeof(T)}");
if (typeof(T) == typeof(RawResult))
return (new RestResult<RawResult>(new RawResult(content), null, response.StatusCode) as RestResult<T>)!;
return new RestResult<T>(await response.Content.AsJson<T>(), null, return new RestResult<T>(await response.Content.AsJson<T>(), null,
response.StatusCode); response.StatusCode);
} }
_debug.Error("ERROR " + response.StatusCode + " " + content); throw new HttpRequestException();
return new RestResult<T>(default, "response code:" + response.StatusCode, response.StatusCode);
} }
} }
@@ -81,16 +81,16 @@ public class RestResult<T>
{ {
public string Message = "Ok"; public string Message = "Ok";
public HttpStatusCode StatusCode; public HttpStatusCode StatusCode;
public T? Value; public T Value;
public RestResult(T? value, string? message, HttpStatusCode statusCode) public RestResult(T value, string? message, HttpStatusCode statusCode)
{ {
Value = value; Value = value;
if (message != null) Message = message; if (message != null) Message = message;
StatusCode = statusCode; StatusCode = statusCode;
} }
public static implicit operator T?(RestResult<T> result) public static implicit operator T(RestResult<T> result)
{ {
return result.Value; return result.Value;
} }