diff --git a/.gitignore b/.gitignore
index 8d72798..ea8246b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,4 +4,5 @@ obj/
riderModule.iml
/_ReSharper.Caches/
release/
-publish/
\ No newline at end of file
+publish/
+/.vs
\ No newline at end of file
diff --git a/Nebula.Launcher/Nebula.Launcher.csproj b/Nebula.Launcher/Nebula.Launcher.csproj
index 5f6b17a..82891c5 100644
--- a/Nebula.Launcher/Nebula.Launcher.csproj
+++ b/Nebula.Launcher/Nebula.Launcher.csproj
@@ -32,6 +32,7 @@
+
@@ -63,8 +64,4 @@
-
-
-
-
diff --git a/Nebula.Launcher/ServerListProviders/TestServerList.cs b/Nebula.Launcher/ServerListProviders/TestServerList.cs
index 5a8e863..a899b66 100644
--- a/Nebula.Launcher/ServerListProviders/TestServerList.cs
+++ b/Nebula.Launcher/ServerListProviders/TestServerList.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using Nebula.Launcher.Controls;
using Nebula.Launcher.ViewModels;
using Nebula.Launcher.ViewModels.Pages;
diff --git a/Nebula.Launcher/ViewModels/Pages/ServerOverviewModel.cs b/Nebula.Launcher/ViewModels/Pages/ServerOverviewModel.cs
index 4ba302d..c1422bd 100644
--- a/Nebula.Launcher/ViewModels/Pages/ServerOverviewModel.cs
+++ b/Nebula.Launcher/ViewModels/Pages/ServerOverviewModel.cs
@@ -118,6 +118,14 @@ public sealed class ServerViewContainer
private readonly List _favorites = [];
private readonly Dictionary _customNames = [];
+ private readonly Dictionary> _entries = new();
+
+ public ICollection Items =>
+ _entries.Values
+ .Select(wr => wr.TryGetTarget(out var target) ? target : null)
+ .Where(t => t != null)
+ .ToList()!;
+
public ServerViewContainer()
{
_viewHelperService = new ViewHelperService();
@@ -131,108 +139,124 @@ public sealed class ServerViewContainer
configurationService.SubscribeVarChanged(LauncherConVar.ServerCustomNames, OnCustomNamesChanged, true);
}
- private void OnCustomNamesChanged(Dictionary? value)
- {
- var oldNames =
- _customNames.ToDictionary(k => k.Key, v => v.Value); //Clone think
-
- _customNames.Clear();
-
- if(value == null)
- {
- foreach (var (ip,_) in oldNames)
- {
- if(!_entries.TryGetValue(ip, out var listEntry) || listEntry is not IEntryNameHolder entryNameHolder)
- continue;
-
- entryNameHolder.Name = null;
- }
-
- return;
- }
-
- foreach (var (oldIp, oldName) in oldNames)
- {
- if(value.TryGetValue(oldIp, out var newName))
- {
- if (oldName == newName)
- value.Remove(newName);
-
- continue;
- }
-
- if(!_entries.TryGetValue(oldIp, out var listEntry) ||
- listEntry is not IEntryNameHolder entryNameHolder)
- continue;
-
- entryNameHolder.Name = null;
- }
-
- foreach (var (ip, name) in value)
- {
- _customNames.Add(ip, name);
- if(!_entries.TryGetValue(ip, out var listEntry) || listEntry is not IEntryNameHolder entryNameHolder)
- continue;
-
- entryNameHolder.Name = name;
- }
- }
-
- private void OnFavoritesChange(string[]? value)
- {
- _favorites.Clear();
- if(value == null) return;
-
- foreach (var favorite in value)
- {
- _favorites.Add(favorite);
- if (_entries.TryGetValue(favorite, out var entry) && entry is IFavoriteEntryModelView favoriteView)
- {
- favoriteView.IsFavorite = true;
- }
- }
- }
-
- private readonly Dictionary _entries = new();
-
- public ICollection Items => _entries.Values;
-
public void Clear()
{
- foreach (var (_, value) in _entries)
+ foreach (var (_, weakRef) in _entries)
{
- value.Dispose();
+ if (weakRef.TryGetTarget(out var value))
+ value.Dispose();
}
+
_entries.Clear();
}
public IListEntryModelView Get(RobustUrl url, ServerStatus? serverStatus = null)
{
+ var key = url.ToString();
IListEntryModelView? entry;
-
+
lock (_entries)
{
- _customNames.TryGetValue(url.ToString(), out var customName);
-
- if (_entries.TryGetValue(url.ToString(), out entry))
+ _customNames.TryGetValue(key, out var customName);
+
+ if (_entries.TryGetValue(key, out var weakEntry)
+ && weakEntry.TryGetTarget(out entry))
{
return entry;
}
if (serverStatus is not null)
- entry = _viewHelperService.GetViewModel().WithData(url, customName, serverStatus);
+ {
+ entry = _viewHelperService
+ .GetViewModel()
+ .WithData(url, customName, serverStatus);
+ }
else
- entry = _viewHelperService.GetViewModel().LoadServerEntry(url, customName, CancellationToken.None);
-
- if(_favorites.Contains(url.ToString()) &&
- entry is IFavoriteEntryModelView favoriteEntryModelView)
- favoriteEntryModelView.IsFavorite = true;
-
- _entries.Add(url.ToString(), entry);
+ {
+ entry = _viewHelperService
+ .GetViewModel()
+ .LoadServerEntry(url, customName, CancellationToken.None);
+ }
+
+ if (_favorites.Contains(key)
+ && entry is IFavoriteEntryModelView fav)
+ {
+ fav.IsFavorite = true;
+ }
+
+ _entries[key] = new WeakReference(entry);
}
-
+
return entry;
}
+
+ private void OnFavoritesChange(string[]? value)
+ {
+ _favorites.Clear();
+ if (value == null) return;
+
+ foreach (var favorite in value)
+ {
+ _favorites.Add(favorite);
+ if (_entries.TryGetValue(favorite, out var weak)
+ && weak.TryGetTarget(out var entry)
+ && entry is IFavoriteEntryModelView fav)
+ {
+ fav.IsFavorite = true;
+ }
+ }
+ }
+
+ private void OnCustomNamesChanged(Dictionary? value)
+ {
+ var oldNames = _customNames.ToDictionary(x => x.Key, x => x.Value);
+ _customNames.Clear();
+
+ if (value == null)
+ {
+ foreach (var (ip, _) in oldNames)
+ {
+ ResetName(ip);
+ }
+
+ return;
+ }
+
+ foreach (var (oldIp, oldName) in oldNames)
+ {
+ if (value.TryGetValue(oldIp, out var newName))
+ {
+ if (oldName == newName)
+ value.Remove(newName);
+
+ continue;
+ }
+
+ ResetName(oldIp);
+ }
+
+ foreach (var (ip, name) in value)
+ {
+ _customNames.Add(ip, name);
+
+ if (_entries.TryGetValue(ip, out var weak)
+ && weak.TryGetTarget(out var entry)
+ && entry is IEntryNameHolder holder)
+ {
+ holder.Name = name;
+ }
+ }
+ }
+
+ private void ResetName(string ip)
+ {
+ if (_entries.TryGetValue(ip, out var weak)
+ && weak.TryGetTarget(out var entry)
+ && entry is IEntryNameHolder holder)
+ {
+ holder.Name = null;
+ }
+ }
}
public interface IListEntryModelView : IDisposable
diff --git a/Nebula.Launcher/ViewModels/ServerCompoundEntryModelView.cs b/Nebula.Launcher/ViewModels/ServerCompoundEntryModelView.cs
index 40b8ca5..459c226 100644
--- a/Nebula.Launcher/ViewModels/ServerCompoundEntryModelView.cs
+++ b/Nebula.Launcher/ViewModels/ServerCompoundEntryModelView.cs
@@ -1,7 +1,6 @@
using System;
using System.Threading;
using System.Threading.Tasks;
-using Avalonia.Controls;
using CommunityToolkit.Mvvm.ComponentModel;
using Microsoft.Extensions.DependencyInjection;
using Nebula.Launcher.Models;
@@ -19,7 +18,7 @@ namespace Nebula.Launcher.ViewModels;
public sealed partial class ServerCompoundEntryViewModel :
ViewModelBase, IFavoriteEntryModelView, IFilterConsumer, IListEntryModelView, IEntryNameHolder
{
- [ObservableProperty] private ServerEntryModelView? _currentEntry;
+ private ServerEntryModelView? _currentEntry;
[ObservableProperty] private string _message = "Loading server entry...";
[ObservableProperty] private bool _isFavorite;
[ObservableProperty] private bool _loading = true;
@@ -28,6 +27,28 @@ public sealed partial class ServerCompoundEntryViewModel :
private RobustUrl? _url;
private ServerFilter? _currentFilter;
+ public ServerEntryModelView? CurrentEntry
+ {
+ get => _currentEntry;
+ set
+ {
+ if (value == _currentEntry) return;
+
+ _currentEntry = value;
+
+ if (_currentEntry != null)
+ {
+ _currentEntry.IsFavorite = IsFavorite;
+ _currentEntry.Name = Name;
+ _currentEntry.ProcessFilter(_currentFilter);
+ }
+
+ Loading = _currentEntry == null;
+
+ OnPropertyChanged();
+ }
+ }
+
public string? Name
{
get => _name;
@@ -54,31 +75,43 @@ public sealed partial class ServerCompoundEntryViewModel :
{
}
- public ServerCompoundEntryViewModel LoadServerEntry(RobustUrl url,string? name, CancellationToken cancellationToken)
+ public ServerCompoundEntryViewModel LoadWithEntry(ServerEntryModelView? entry)
{
- Task.Run(async () =>
- {
- _url = url;
- try
- {
- Message = "Loading server entry...";
- var status = await RestService.GetAsync(_url.StatusUri, cancellationToken);
-
- CurrentEntry = ServiceProvider.GetService()!.WithData(_url, name, status);
- CurrentEntry.IsFavorite = IsFavorite;
- CurrentEntry.Loading = false;
- CurrentEntry.ProcessFilter(_currentFilter);
- Loading = false;
- }
- catch (Exception e)
- {
- Message = e.Message;
- }
- }, cancellationToken);
-
+ CurrentEntry = entry;
return this;
}
+ public ServerCompoundEntryViewModel LoadServerEntry(RobustUrl url, string? name, CancellationToken cancellationToken)
+ {
+ _url = url;
+ _name = name;
+ Task.Run(LoadServer, cancellationToken);
+ return this;
+ }
+
+ private async Task LoadServer()
+ {
+ if (_url is null)
+ {
+ Message = "Url is not set";
+ return;
+ }
+
+ try
+ {
+ Message = "Loading server entry...";
+ var status = await RestService.GetAsync(_url.StatusUri, CancellationToken.None);
+
+ CurrentEntry = ServiceProvider.GetService()!.WithData(_url, null, status);
+
+ Loading = false;
+ }
+ catch (Exception e)
+ {
+ Message = "Error while fetching data from " + _url + " : " + e.Message;
+ }
+ }
+
public void ToggleFavorites()
{
if (CurrentEntry is null && _url is not null)
diff --git a/Nebula.Launcher/ViewModels/ServerEntryModelView.cs b/Nebula.Launcher/ViewModels/ServerEntryModelView.cs
index c801993..6b822a3 100644
--- a/Nebula.Launcher/ViewModels/ServerEntryModelView.cs
+++ b/Nebula.Launcher/ViewModels/ServerEntryModelView.cs
@@ -28,8 +28,6 @@ public sealed partial class ServerEntryModelView : ViewModelBase, IFilterConsume
[ObservableProperty] private bool _isFavorite;
[ObservableProperty] private bool _isVisible;
[ObservableProperty] private bool _runVisible = true;
- [ObservableProperty] private bool _tagDataVisible;
- [ObservableProperty] private bool _loading;
[ObservableProperty] private string _realName;
public string? Name
@@ -131,7 +129,7 @@ public sealed partial class ServerEntryModelView : ViewModelBase, IFilterConsume
OnPropertyChanged(nameof(Status));
}
- public ServerEntryModelView WithData(RobustUrl url, string? name,ServerStatus serverStatus)
+ public ServerEntryModelView WithData(RobustUrl url, string? name, ServerStatus serverStatus)
{
Address = url;
SetStatus(serverStatus);
diff --git a/Nebula.Launcher/Views/ServerCompoundEntryView.axaml b/Nebula.Launcher/Views/ServerCompoundEntryView.axaml
index a9b1122..caacfcb 100644
--- a/Nebula.Launcher/Views/ServerCompoundEntryView.axaml
+++ b/Nebula.Launcher/Views/ServerCompoundEntryView.axaml
@@ -70,9 +70,9 @@
-
-
-
+
diff --git a/Nebula.Launcher/Views/ServerListView.axaml b/Nebula.Launcher/Views/ServerListView.axaml
index 6c73c6a..88f5690 100644
--- a/Nebula.Launcher/Views/ServerListView.axaml
+++ b/Nebula.Launcher/Views/ServerListView.axaml
@@ -2,7 +2,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:viewModels="clr-namespace:Nebula.Launcher.Controls"
xmlns:services="clr-namespace:Nebula.Launcher.Services"
xmlns:viewModels1="clr-namespace:Nebula.Launcher.ViewModels"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
diff --git a/Nebula.SourceGenerators/ViewConstructGenerator.cs b/Nebula.SourceGenerators/ViewConstructGenerator.cs
index 9fb160e..9bc2681 100644
--- a/Nebula.SourceGenerators/ViewConstructGenerator.cs
+++ b/Nebula.SourceGenerators/ViewConstructGenerator.cs
@@ -64,18 +64,18 @@ namespace {viewNamespace}
}}";
// Add the source code to the compilation.
- context.AddSource($"{viewName}_viewConstructAuto.g.cs", SourceText.From(code, Encoding.UTF8));
+ context.AddSource($"{viewModelName}_{viewName}_viewConstructAuto.g.cs", SourceText.From(code, Encoding.UTF8));
}
catch (Exception e)
{
var coder1 = $@"
//
-// Error!
+// Error! {e.Message}
namespace {viewModelNamespace}
{{
public partial class {viewModelName}
{{
- // {e.Message}
+ // ERROR: {e.Message}
}}
}}";
@@ -84,6 +84,4 @@ namespace {viewModelNamespace}
}
}
}
-
-
}
\ No newline at end of file
diff --git a/Nebula.sln.DotSettings.user b/Nebula.sln.DotSettings.user
index 45a2645..4ededbf 100644
--- a/Nebula.sln.DotSettings.user
+++ b/Nebula.sln.DotSettings.user
@@ -2,6 +2,7 @@
ForceIncluded
ForceIncluded
ForceIncluded
+ ForceIncluded
ForceIncluded
ForceIncluded
ForceIncluded