diff --git a/Nebula.Launcher/ViewModels/Pages/ServerListViewModel.Favorite.cs b/Nebula.Launcher/ViewModels/Pages/ServerListViewModel.Favorite.cs index ba42115..d5201f5 100644 --- a/Nebula.Launcher/ViewModels/Pages/ServerListViewModel.Favorite.cs +++ b/Nebula.Launcher/ViewModels/Pages/ServerListViewModel.Favorite.cs @@ -16,19 +16,11 @@ public partial class ServerListViewModel [GenerateProperty] private ConfigurationService ConfigurationService { get; } [GenerateProperty] private RestService RestService { get; } - public readonly List<(RobustUrl,ServerStatus)> RawFavoriteServers = new(); + public ObservableCollection FavoriteServers { get; } = new(); - public ServerEntryModelView GetServerEntryModelView((RobustUrl, ServerStatus) server) + private async void UpdateFavoriteEntries() { - var model = ViewHelperService.GetViewModel().WithData(server.Item1, server.Item2); - model.OnFavoriteToggle += ()=> RemoveFavorite(model); - model.IsFavorite = true; - return model; - } - - private async void FetchFavorite() - { - RawFavoriteServers.Clear(); + FavoriteServers.Clear(); var servers = ConfigurationService.GetConfigValue(CurrentConVar.Favorites); if (servers is null || servers.Length == 0) @@ -38,21 +30,9 @@ public partial class ServerListViewModel foreach (var server in servers) { - var uri = server.ToRobustUrl(); - try - { - var serverInfo = await RestService.GetAsync(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))); - } + var s = await ServerViewContainer.Get(server.ToRobustUrl()); + s.IsFavorite = true; + FavoriteServers.Add(s); } } @@ -67,7 +47,7 @@ public partial class ServerListViewModel var servers = (ConfigurationService.GetConfigValue(CurrentConVar.Favorites) ?? []).ToList(); servers.Add(robustUrl.ToString()); ConfigurationService.SetConfigValue(CurrentConVar.Favorites, servers.ToArray()); - FetchFavorite(); + UpdateFavoriteEntries(); } public void RemoveFavorite(ServerEntryModelView entryModelView) @@ -76,6 +56,6 @@ public partial class ServerListViewModel servers.Remove(entryModelView.Address.ToString()); ConfigurationService.SetConfigValue(CurrentConVar.Favorites, servers.ToArray()); entryModelView.IsFavorite = false; - FetchFavorite(); + UpdateFavoriteEntries(); } } \ No newline at end of file diff --git a/Nebula.Launcher/ViewModels/Pages/ServerListViewModel.cs b/Nebula.Launcher/ViewModels/Pages/ServerListViewModel.cs index cb7ae97..ec4feb1 100644 --- a/Nebula.Launcher/ViewModels/Pages/ServerListViewModel.cs +++ b/Nebula.Launcher/ViewModels/Pages/ServerListViewModel.cs @@ -22,27 +22,30 @@ public partial class ServerListViewModel : ViewModelBase, IViewModelPage [ObservableProperty] private string _searchText = string.Empty; [ObservableProperty] private bool _isFavoriteMode; - public SortedList Servers { get; } = new(Comparer.Create((x,y)=>y.CompareTo(x))); - private ServerViewContainer ServerViewContainer; - + public ObservableCollection Servers { get; }= new(); + public Action? OnSearchChange; - [GenerateProperty] private HubService HubService { get; } = default!; + [GenerateProperty] private HubService HubService { 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 UnsortedServers { get; } = new(); //Design think protected override void InitialiseInDesignMode() { - ServerViewContainer = new ServerViewContainer(this); + ServerViewContainer = new ServerViewContainer(this, RestService, CancellationService, DebugService, ViewHelperService); } //real think 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); @@ -51,40 +54,35 @@ public partial class ServerListViewModel : ViewModelBase, IViewModelPage OnSearchChange += OnChangeSearch; if (!HubService.IsUpdating) UpdateServerEntries(); - //FetchFavorite(); + UpdateFavoriteEntries(); } private void UpdateServerEntries() { Servers.Clear(); - OnPropertyChanged(nameof(Servers)); - foreach (var info in UnsortedServers.Where(a=>CheckServerThink(a.StatusData))) + Task.Run(async () => { - var view = ServerViewContainer.Get(info.Address.ToRobustUrl(), info.StatusData); - float players = info.StatusData.Players; - - while (true) + UnsortedServers.Sort(new ServerComparer()); + foreach (var info in UnsortedServers.Where(a => CheckServerThink(a.StatusData))) { - try - { - Servers.Add(players,view); - OnPropertyChanged(nameof(Servers)); - break; - } - catch (Exception e) - { - Console.WriteLine(e); - players += 0.01f; - } + var view = await ServerViewContainer.Get(info.Address.ToRobustUrl(), info.StatusData); + Servers.Add(view); } - } + }); } private void OnChangeSearch() { if(string.IsNullOrEmpty(SearchText)) return; - UpdateServerEntries(); + if(IsFavoriteMode) + { + UpdateFavoriteEntries(); + } + else + { + UpdateServerEntries(); + } } private void HubServerChangedEventArgs(HubServerChangedEventArgs obj) @@ -95,7 +93,13 @@ public partial class ServerListViewModel : ViewModelBase, IViewModelPage if (obj.Action == HubServerChangeAction.Remove) foreach (var info in obj.Items) 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) @@ -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 _entries = new(); - public ServerEntryModelView Get(RobustUrl url, ServerStatus serverStatus) + public void Clear() + { + _entries.Clear(); + } + + public async Task Get(RobustUrl url, ServerStatus? serverStatus = null) { if (_entries.TryGetValue(url, out var entry)) { return entry; } - entry = serverListViewModel.GetServerEntryModelView((url, serverStatus)); + try + { + serverStatus ??= await restService.GetAsync(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().WithData(url, serverStatus); + entry.OnFavoriteToggle += () => + { + if (entry.IsFavorite) serverListViewModel.RemoveFavorite(entry); + else serverListViewModel.AddFavorite(entry); + }; _entries.Add(url, entry); return entry; diff --git a/Nebula.Launcher/ViewModels/ServerEntryModelView.cs b/Nebula.Launcher/ViewModels/ServerEntryModelView.cs index 2a59f1a..d564ae7 100644 --- a/Nebula.Launcher/ViewModels/ServerEntryModelView.cs +++ b/Nebula.Launcher/ViewModels/ServerEntryModelView.cs @@ -54,10 +54,7 @@ public partial class ServerEntryModelView : ViewModelBase { try { - var result = - await RestService.GetAsync(Address.InfoUri, CancellationService.Token); - if (result.Value == null) return null; - _serverInfo = result.Value; + _serverInfo = await RestService.GetAsync(Address.InfoUri, CancellationService.Token); } catch (Exception e) { @@ -100,23 +97,6 @@ public partial class ServerEntryModelView : ViewModelBase CurrLog = ViewHelperService.GetViewModel(); } - 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) { Status = serverStatus; diff --git a/Nebula.Launcher/Views/Pages/ServerListView.axaml b/Nebula.Launcher/Views/Pages/ServerListView.axaml index 67f63b7..8bb5cda 100644 --- a/Nebula.Launcher/Views/Pages/ServerListView.axaml +++ b/Nebula.Launcher/Views/Pages/ServerListView.axaml @@ -25,11 +25,11 @@ diff --git a/Nebula.Shared/Services/RestService.cs b/Nebula.Shared/Services/RestService.cs index 1546278..5273960 100644 --- a/Nebula.Shared/Services/RestService.cs +++ b/Nebula.Shared/Services/RestService.cs @@ -23,7 +23,7 @@ public class RestService _debug = debug; } - public async Task> GetAsync(Uri uri, CancellationToken cancellationToken) + public async Task> GetAsync(Uri uri, CancellationToken cancellationToken) where T : notnull { var response = await _client.GetAsync(uri, cancellationToken); return await ReadResult(response, cancellationToken); @@ -35,7 +35,7 @@ public class RestService return result.Value ?? defaultValue; } - public async Task> PostAsync(T information, Uri uri, CancellationToken cancellationToken) + public async Task> PostAsync(T information, Uri uri, CancellationToken cancellationToken) where K : notnull { var json = JsonSerializer.Serialize(information, _serializerOptions); var content = new StringContent(json, Encoding.UTF8, "application/json"); @@ -43,7 +43,7 @@ public class RestService return await ReadResult(response, cancellationToken); } - public async Task> PostAsync(Stream stream, Uri uri, CancellationToken cancellationToken) + public async Task> PostAsync(Stream stream, Uri uri, CancellationToken cancellationToken) where T : notnull { using var multipartFormContent = new MultipartFormDataContent("Upload----" + DateTime.Now.ToString(CultureInfo.InvariantCulture)); @@ -52,7 +52,7 @@ public class RestService return await ReadResult(response, cancellationToken); } - public async Task> DeleteAsync(Uri uri, CancellationToken cancellationToken) + public async Task> DeleteAsync(Uri uri, CancellationToken cancellationToken) where T : notnull { var response = await _client.DeleteAsync(uri, cancellationToken); return await ReadResult(response, cancellationToken); @@ -61,19 +61,19 @@ public class RestService private async Task> ReadResult(HttpResponseMessage response, CancellationToken cancellationToken) where T : notnull { var content = await response.Content.ReadAsStringAsync(cancellationToken); + + if (typeof(T) == typeof(RawResult)) + return (new RestResult(new RawResult(content), null, response.StatusCode) as RestResult)!; if (response.IsSuccessStatusCode) { _debug.Debug($"SUCCESSFUL GET CONTENT {typeof(T)}"); - if (typeof(T) == typeof(RawResult)) - return (new RestResult(new RawResult(content), null, response.StatusCode) as RestResult)!; return new RestResult(await response.Content.AsJson(), null, response.StatusCode); } - - _debug.Error("ERROR " + response.StatusCode + " " + content); - return new RestResult(default, "response code:" + response.StatusCode, response.StatusCode); + + throw new HttpRequestException(); } } @@ -81,16 +81,16 @@ public class RestResult { public string Message = "Ok"; 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; if (message != null) Message = message; StatusCode = statusCode; } - public static implicit operator T?(RestResult result) + public static implicit operator T(RestResult result) { return result.Value; }