diff --git a/Directory.Packages.props b/Directory.Packages.props
index 36d49a39..2ec3752b 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -20,6 +20,7 @@
+
diff --git a/SS14.Launcher/App.xaml b/SS14.Launcher/App.xaml
index 07ee32fd..5fa52b9a 100644
--- a/SS14.Launcher/App.xaml
+++ b/SS14.Launcher/App.xaml
@@ -9,8 +9,8 @@
-
+
@@ -23,10 +23,10 @@
-
-
+
+
diff --git a/SS14.Launcher/Assets/Locale/el/text.ftl b/SS14.Launcher/Assets/Locale/el/text.ftl
index a294afb0..f47d0850 100644
--- a/SS14.Launcher/Assets/Locale/el/text.ftl
+++ b/SS14.Launcher/Assets/Locale/el/text.ftl
@@ -542,8 +542,4 @@ connecting-privacy-policy-decline = Δεν αποδέχομαι (αποσύνδ
tab-servers-table-round-time = Χρόνος
server-entry-status-lobby = Λόμπι
connecting-status-update-error-unknown = Άγνωστο
-server-entry-round-time =
- { $hours ->
- [0] { $mins }M
- *[1] { $hours }H { $mins }M
- }
+server-entry-round-time = { $hours }h { $mins }m
diff --git a/SS14.Launcher/Assets/Locale/en-US/text.ftl b/SS14.Launcher/Assets/Locale/en-US/text.ftl
index 3d9d62ba..d846a062 100644
--- a/SS14.Launcher/Assets/Locale/en-US/text.ftl
+++ b/SS14.Launcher/Assets/Locale/en-US/text.ftl
@@ -301,10 +301,7 @@ server-entry-player-count =
[0] ∞
*[1] { $max }
}
-server-entry-round-time = { $hours ->
- [0] { $mins }M
-*[1] { $hours }H { $mins }M
-}
+server-entry-round-time = { $hours }h { $mins }m
server-entry-fetching = Fetching…
server-entry-description-offline = Unable to contact server
server-entry-description-fetching = Fetching server status…
diff --git a/SS14.Launcher/Assets/Locale/nl/text.ftl b/SS14.Launcher/Assets/Locale/nl/text.ftl
index 8eefdb61..1684a1d6 100644
--- a/SS14.Launcher/Assets/Locale/nl/text.ftl
+++ b/SS14.Launcher/Assets/Locale/nl/text.ftl
@@ -540,10 +540,6 @@ connecting-privacy-policy-view = Bekijk privacybeleid
connecting-privacy-policy-accept = Accepteer (doorgaan)
connecting-privacy-policy-decline = Weigeren (verbreken)
tab-servers-table-round-time = Tijd
-server-entry-round-time =
- { $hours ->
- [0] { $mins }M
- *[1] { $hours }U { $mins }M
- }
+server-entry-round-time = { $hours }u { $mins }m
server-entry-status-lobby = Lobby
connecting-status-update-error-unknown = Onbekend
diff --git a/SS14.Launcher/Assets/Locale/pl/text.ftl b/SS14.Launcher/Assets/Locale/pl/text.ftl
index 37a25f33..d03b3e3d 100644
--- a/SS14.Launcher/Assets/Locale/pl/text.ftl
+++ b/SS14.Launcher/Assets/Locale/pl/text.ftl
@@ -539,11 +539,7 @@ connecting-status-update-error-unknown = Nieznany
server-entry-status-lobby = Menu
connecting-privacy-policy-text = Ten serwer wymaga zaakceptowania swojej polityki prywatności przed połączeniem.
tab-servers-table-round-time = Czas
-server-entry-round-time =
- { $hours ->
- [0] { $mins }M
- *[1] { $hours }G { $mins }M
- }
+server-entry-round-time = { $hours }g { $mins }m
connecting-privacy-policy-text-version-changed = Ten serwer zaktualizował swoją politykę prywatności od twojej ostatniej rozgrywki. Musisz zaakceptować nową wersję przed połączeniem.
connecting-privacy-policy-view = Pokaż politykę prywatności
connecting-privacy-policy-accept = Zaakceptuj (kontynuuj)
diff --git a/SS14.Launcher/Assets/Locale/ru/text.ftl b/SS14.Launcher/Assets/Locale/ru/text.ftl
index abe124b1..1ac6bc63 100644
--- a/SS14.Launcher/Assets/Locale/ru/text.ftl
+++ b/SS14.Launcher/Assets/Locale/ru/text.ftl
@@ -540,11 +540,7 @@ connecting-privacy-policy-text = Перед подключением к этом
connecting-privacy-policy-view = Посмотреть политику конфиденциальности
connecting-privacy-policy-accept = Принять (продолжить)
connecting-privacy-policy-decline = Отклонить (отключиться)
-server-entry-round-time =
- { $hours ->
- [0] { $mins }м
- *[1] { $hours }ч { $mins }м
- }
+server-entry-round-time = { $hours }ч { $mins }м
tab-servers-table-round-time = Время
connecting-status-update-error-unknown = Неизвестно
server-entry-status-lobby = Лобби
diff --git a/SS14.Launcher/Assets/Locale/tr/text.ftl b/SS14.Launcher/Assets/Locale/tr/text.ftl
index f0eda6bf..f19d2314 100644
--- a/SS14.Launcher/Assets/Locale/tr/text.ftl
+++ b/SS14.Launcher/Assets/Locale/tr/text.ftl
@@ -541,11 +541,7 @@ connecting-privacy-policy-text-version-changed = Bu sunucu son oynadığınızda
connecting-privacy-policy-accept = Kabul et (devam et)
connecting-privacy-policy-decline = Reddet (bağlantıyı kes)
tab-servers-table-round-time = Zaman
-server-entry-round-time =
- { $hours ->
- [0] { $mins }M
- *[1] { $hours }H { $mins }M
- }
+server-entry-round-time = { $hours }h { $mins }m
server-entry-status-lobby = Lobi
connecting-status-update-error-unknown = Bilinmeyen
connecting-status-update-error-no-engine-for-platform = Bu oyun platformunuzu desteklemeyen eski bir versiyon kullanmaktadır. Lütfen farklı bir sunucu deneyiniz ya da yeniden deneyiniz.
diff --git a/SS14.Launcher/Assets/Locale/uk/text.ftl b/SS14.Launcher/Assets/Locale/uk/text.ftl
index 712e6893..523a03ce 100644
--- a/SS14.Launcher/Assets/Locale/uk/text.ftl
+++ b/SS14.Launcher/Assets/Locale/uk/text.ftl
@@ -540,11 +540,7 @@ connecting-privacy-policy-text-version-changed = Цей сервер онови
connecting-privacy-policy-view = Переглянути політику конфіденційності
connecting-privacy-policy-accept = Прийняти (продовжити)
connecting-privacy-policy-decline = Відхилити (відключитися)
-server-entry-round-time =
- { $hours ->
- [0] { $mins }хв
- *[1] { $hours }г { $mins }хв
- }
+server-entry-round-time = { $hours }г { $mins }хв
tab-servers-table-round-time = Час
server-entry-status-lobby = Лоббі
connecting-status-update-error-unknown = Невідомо
diff --git a/SS14.Launcher/Assets/Locale/zh_Hans/text.ftl b/SS14.Launcher/Assets/Locale/zh_Hans/text.ftl
index a09e4707..066b8a5f 100644
--- a/SS14.Launcher/Assets/Locale/zh_Hans/text.ftl
+++ b/SS14.Launcher/Assets/Locale/zh_Hans/text.ftl
@@ -539,11 +539,7 @@ connecting-privacy-policy-view = 查看隐私条款
connecting-privacy-policy-accept = 同意(继续)
connecting-privacy-policy-decline = 拒绝(断开连接)
login-login-show-password = 显示密码
-server-entry-round-time =
- { $hours ->
- [0] { $mins }分
- *[1] { $hours }时 { $mins }分
- }
+server-entry-round-time = { $hours }时 { $mins }分
connecting-status-update-error-unknown = 未知
tab-servers-table-round-time = 时间
server-entry-status-lobby = 大厅
diff --git a/SS14.Launcher/Controls/TimerTextCell.xaml.cs b/SS14.Launcher/Controls/TimerTextCell.xaml.cs
deleted file mode 100644
index 56b27461..00000000
--- a/SS14.Launcher/Controls/TimerTextCell.xaml.cs
+++ /dev/null
@@ -1,94 +0,0 @@
-using System;
-using Avalonia;
-using Avalonia.Controls.Primitives;
-using Avalonia.Threading;
-using SS14.Launcher.Localization;
-
-namespace SS14.Launcher.Controls;
-
-public class TimerTextCell : TemplatedControl
-{
- private readonly LocalizationManager _loc = LocalizationManager.Instance;
-
- public static readonly DirectProperty ValueProperty =
- AvaloniaProperty.RegisterDirect(
- nameof(Value),
- o => o.Value,
- (o, v) => o.Value = v
- );
-
- public static readonly DirectProperty TextProperty =
- AvaloniaProperty.RegisterDirect(
- nameof(Text),
- o => o.Text,
- (o, v) => o.Text = v
- );
-
- private DateTime? _value;
- private bool _attached;
-
- public DateTime? Value
- {
- get => _value;
- set => SetAndRaise(ValueProperty, ref _value, value);
- }
-
- private string _text = "";
-
- public string Text
- {
- get => _text;
- set => SetAndRaise(TextProperty, ref _text, value);
- }
-
- private IDisposable? _timer;
-
- protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
- {
- base.OnPropertyChanged(change);
-
- if (change.Property == ValueProperty)
- {
- UpdateText();
- }
- }
-
- protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
- {
- _attached = true;
- StartTimer();
- }
-
- protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
- {
- _attached = false;
- _timer?.Dispose();
- }
-
- // Trigger an update when the visible timer will roll over to the next minute
- private void StartTimer()
- {
- _timer?.Dispose();
-
- // Only start a new timer if we have a DateTime
- // and we’re on the visual tree.
- if (_attached && Value is { } dt)
- {
- var ts = DateTime.UtcNow.Subtract(dt);
- _timer = DispatcherTimer.RunOnce(UpdateText, TimeSpan.FromSeconds((ts.Seconds >= 0 ? ts.Seconds : 60)));
- }
- }
-
- private void UpdateText()
- {
- this.Text = Value is { } dt ? GetTimeStringSince(dt) : "";
- StartTimer();
- }
-
- private string GetTimeStringSince(DateTime dateTime)
- {
- var ts = DateTime.UtcNow.Subtract(dateTime);
- return _loc.GetString("server-entry-round-time", ("hours", Math.Floor(ts.TotalHours)),
- ("mins", ts.Minutes.ToString().PadLeft(2, '0')));
- }
-}
diff --git a/SS14.Launcher/Models/ServerStatus/IServerStatusData.cs b/SS14.Launcher/Models/ServerStatus/IServerStatusData.cs
index 5c68ae7d..cf6482b8 100644
--- a/SS14.Launcher/Models/ServerStatus/IServerStatusData.cs
+++ b/SS14.Launcher/Models/ServerStatus/IServerStatusData.cs
@@ -27,7 +27,5 @@ public interface IServerStatusData : INotifyPropertyChanged
int SoftMaxPlayerCount { get; set; }
- DateTime? RoundStartTime { get; set; }
-
GameRoundStatus RoundStatus { get; set; }
}
diff --git a/SS14.Launcher/Models/ServerStatus/ServerStatusCache.Data.cs b/SS14.Launcher/Models/ServerStatus/ServerStatusCache.Data.cs
index d229f305..b4b491d3 100644
--- a/SS14.Launcher/Models/ServerStatus/ServerStatusCache.Data.cs
+++ b/SS14.Launcher/Models/ServerStatus/ServerStatusCache.Data.cs
@@ -79,12 +79,6 @@ public int SoftMaxPlayerCount
set => SetProperty(ref _softMaxPlayerCount, value);
}
- public DateTime? RoundStartTime
- {
- get => _roundStartTime;
- set => SetProperty(ref _roundStartTime, value);
- }
-
public GameRoundStatus RoundStatus
{
get => _roundStatus;
diff --git a/SS14.Launcher/Models/ServerStatus/ServerStatusCache.cs b/SS14.Launcher/Models/ServerStatus/ServerStatusCache.cs
index 89e2d4a3..678d409f 100644
--- a/SS14.Launcher/Models/ServerStatus/ServerStatusCache.cs
+++ b/SS14.Launcher/Models/ServerStatus/ServerStatusCache.cs
@@ -128,23 +128,19 @@ public static void ApplyStatus(ServerStatusData data, ServerApi.ServerStatus sta
switch (status.RunLevel)
{
- case ServerApi.GameRunLevel.InRound:
- data.RoundStatus = GameRoundStatus.InRound;
+ case ServerApi.GameRunLevel.InRound when status.RoundStartTime is { } start:
+ var roundStartTime = DateTime.Parse(start, null, System.Globalization.DateTimeStyles.RoundtripKind);
+ data.RoundStatus = new InRound(roundStartTime);
break;
case ServerApi.GameRunLevel.PostRound:
case ServerApi.GameRunLevel.PreRoundLobby:
- data.RoundStatus = GameRoundStatus.InLobby;
+ data.RoundStatus = new InLobby();
break;
default:
- data.RoundStatus = GameRoundStatus.Unknown;
+ data.RoundStatus = new Unknown();
break;
}
- if (status.RoundStartTime != null)
- {
- data.RoundStartTime = DateTime.Parse(status.RoundStartTime, null, System.Globalization.DateTimeStyles.RoundtripKind);
- }
-
var baseTags = status.Tags ?? Array.Empty();
var inferredTags = ServerTagInfer.InferTags(status);
diff --git a/SS14.Launcher/Models/ServerStatus/ServerStatusCode.cs b/SS14.Launcher/Models/ServerStatus/ServerStatusCode.cs
index 02ace184..2df78027 100644
--- a/SS14.Launcher/Models/ServerStatus/ServerStatusCode.cs
+++ b/SS14.Launcher/Models/ServerStatus/ServerStatusCode.cs
@@ -1,3 +1,5 @@
+using System;
+
namespace SS14.Launcher.Models.ServerStatus;
public enum ServerStatusCode
@@ -15,9 +17,30 @@ public enum ServerStatusInfoCode
Fetched
}
-public enum GameRoundStatus
+public abstract record GameRoundStatus : IComparable
+{
+ public int CompareTo(GameRoundStatus? other)
+ => (this, other) switch
+ {
+ (InRound a, InRound b) => a.TimeElapsed.CompareTo(b.TimeElapsed),
+ ({ } a, { } b) => Ordering(a).CompareTo(Ordering(b)),
+ _ => 1,
+ };
+
+ private static int Ordering(GameRoundStatus status)
+ => status switch
+ {
+ Unknown => 0,
+ InLobby => 1,
+ InRound => 2,
+ _ => throw new ArgumentOutOfRangeException(nameof(status), status, "You should add an ordering value"),
+ };
+}
+
+public record Unknown : GameRoundStatus;
+public record InLobby : GameRoundStatus;
+
+public record InRound(DateTime RoundStartTime) : GameRoundStatus
{
- Unknown,
- InLobby,
- InRound,
+ public TimeSpan TimeElapsed => DateTime.UtcNow.Subtract(RoundStartTime);
}
diff --git a/SS14.Launcher/SS14.Launcher.csproj b/SS14.Launcher/SS14.Launcher.csproj
index 9800cf9d..0b437f76 100644
--- a/SS14.Launcher/SS14.Launcher.csproj
+++ b/SS14.Launcher/SS14.Launcher.csproj
@@ -40,6 +40,7 @@
+
diff --git a/SS14.Launcher/Theme/Theme.xaml b/SS14.Launcher/Theme/Theme.xaml
index 485a8657..b5836244 100644
--- a/SS14.Launcher/Theme/Theme.xaml
+++ b/SS14.Launcher/Theme/Theme.xaml
@@ -39,7 +39,7 @@
diff --git a/SS14.Launcher/Theme/ThemeResources.xaml b/SS14.Launcher/Theme/ThemeResources.xaml
index d3a85b84..12aca0a9 100644
--- a/SS14.Launcher/Theme/ThemeResources.xaml
+++ b/SS14.Launcher/Theme/ThemeResources.xaml
@@ -6,8 +6,12 @@
#202025
#EEEEEE
+ #1E1E22
+ #262626
+
#666
+ #2E2E35
#464966
#3E6C45
@@ -22,11 +26,14 @@
#AA575B7F
#00575B7F
+ #2E2E35
+
+
@@ -42,9 +49,9 @@
-
-
-
+
+
+
diff --git a/SS14.Launcher/Theme/ThemeServerList.axaml b/SS14.Launcher/Theme/ThemeServerList.axaml
index 96f21570..0f1443c9 100644
--- a/SS14.Launcher/Theme/ThemeServerList.axaml
+++ b/SS14.Launcher/Theme/ThemeServerList.axaml
@@ -1,103 +1,57 @@
-
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450">
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
diff --git a/SS14.Launcher/Theme/ThemeTimerTextCell.xaml b/SS14.Launcher/Theme/ThemeTimerTextCell.xaml
deleted file mode 100644
index a1462e4b..00000000
--- a/SS14.Launcher/Theme/ThemeTimerTextCell.xaml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
diff --git a/SS14.Launcher/ViewModels/MainWindowTabs/ServerEntryViewModel.cs b/SS14.Launcher/ViewModels/MainWindowTabs/ServerEntryViewModel.cs
index 343b46f8..156ad31a 100644
--- a/SS14.Launcher/ViewModels/MainWindowTabs/ServerEntryViewModel.cs
+++ b/SS14.Launcher/ViewModels/MainWindowTabs/ServerEntryViewModel.cs
@@ -1,5 +1,8 @@
using System;
+using System.Collections;
+using System.Collections.Generic;
using System.ComponentModel;
+using Avalonia.Threading;
using Microsoft.Toolkit.Mvvm.ComponentModel;
using Microsoft.Toolkit.Mvvm.Messaging;
using SS14.Launcher.Localization;
@@ -20,6 +23,22 @@ public sealed class ServerEntryViewModel : ObservableRecipient, IRecipient
+ /// Maps a sorting key to a comparer to use for column sorting.
+ ///
+ public static readonly Dictionary ComparerMapping = new()
+ {
+ { NameSortKey, StringComparer.InvariantCultureIgnoreCase },
+ { TimeSortKey, Comparer.Default },
+ { PlayersSortKey, Comparer.Default },
+ };
+
public ServerEntryViewModel(MainWindowViewModel windowVm, ServerStatusData cacheData, IServerSource serverSource,
DataManager cfg)
{
@@ -27,6 +46,11 @@ public ServerEntryViewModel(MainWindowViewModel windowVm, ServerStatusData cache
_windowVm = windowVm;
_cacheData = cacheData;
_serverSource = serverSource;
+
+ _cacheData.PropertyChanged += OnCacheDataOnPropertyChanged;
+
+ _refreshRoundStartTimer.Start();
+ _refreshRoundStartTimer.Tick += (_, _) => OnPropertyChanged(nameof(RoundStatusString));
}
public ServerEntryViewModel(
@@ -38,6 +62,8 @@ public ServerEntryViewModel(
: this(windowVm, cacheData, serverSource, cfg)
{
Favorite = favorite;
+
+ _cacheData.PropertyChanged += OnCacheDataOnPropertyChanged;
}
public ServerEntryViewModel(
@@ -50,11 +76,6 @@ public ServerEntryViewModel(
FallbackName = ssdfb.FallbackName ?? "";
}
- public void Tick()
- {
- OnPropertyChanged(nameof(RoundStartTime));
- }
-
public void ConnectPressed()
{
ConnectingViewModel.StartConnect(_windowVm, Address);
@@ -101,18 +122,25 @@ public string ServerStatusString
}
}
+ public int PlayerCount => _cacheData.PlayerCount;
+
// Give a ratio for servers with a defined player count, or just a current number for those without.
public string PlayerCountString =>
_loc.GetString("server-entry-player-count",
- ("players", _cacheData.PlayerCount), ("max", _cacheData.SoftMaxPlayerCount));
+ ("players", PlayerCount.ToString().PadLeft(3)),
+ ("max", _cacheData.SoftMaxPlayerCount.ToString().PadRight(3)));
- public DateTime? RoundStartTime => _cacheData.RoundStartTime;
+ public GameRoundStatus RoundStatus => _cacheData.RoundStatus;
- public string RoundStatusString =>
- _cacheData.RoundStatus == GameRoundStatus.InLobby
- ? _loc.GetString("server-entry-status-lobby")
- : "";
+ public string RoundStatusString
+ => _cacheData.RoundStatus switch
+ {
+ InLobby => _loc.GetString("server-entry-status-lobby"),
+ InRound r => _loc.GetString("server-entry-round-time", ("hours", Math.Floor(r.TimeElapsed.TotalHours)),
+ ("mins", r.TimeElapsed.Minutes.ToString().PadLeft(2, '0'))),
+ _ => "",
+ };
public string Description
{
@@ -237,10 +265,6 @@ private void OnCacheDataOnPropertyChanged(object? _, PropertyChangedEventArgs ar
OnPropertyChanged(nameof(PlayerCountString));
break;
- case nameof(IServerStatusData.RoundStartTime):
- OnPropertyChanged(nameof(RoundStartTime));
- break;
-
case nameof(IServerStatusData.RoundStatus):
OnPropertyChanged(nameof(RoundStatusString));
break;
diff --git a/SS14.Launcher/ViewModels/MainWindowTabs/ServerListTabViewModel.cs b/SS14.Launcher/ViewModels/MainWindowTabs/ServerListTabViewModel.cs
index bd50c08a..96ce3671 100644
--- a/SS14.Launcher/ViewModels/MainWindowTabs/ServerListTabViewModel.cs
+++ b/SS14.Launcher/ViewModels/MainWindowTabs/ServerListTabViewModel.cs
@@ -27,11 +27,13 @@ public class ServerListTabViewModel : MainWindowTabViewModel
public string? SearchString
{
get => _searchString;
- set => this.RaiseAndSetIfChanged(ref _searchString, value);
+ set
+ {
+ this.RaiseAndSetIfChanged(ref _searchString, value);
+ UpdateSearchedList();
+ }
}
- private const int throttleMs = 200;
-
public bool SpinnerVisible => _serverListCache.Status < RefreshListStatus.Updated;
public string ListText
@@ -88,11 +90,6 @@ public ServerListTabViewModel(MainWindowViewModel windowVm)
};
_loc.LanguageSwitched += () => Filters.UpdatePresentFilters(_serverListCache.AllServers);
-
- this.WhenAnyValue(x => x.SearchString)
- .Throttle(TimeSpan.FromMilliseconds(throttleMs), RxApp.MainThreadScheduler)
- .ObserveOn(RxApp.MainThreadScheduler)
- .Subscribe(_ => UpdateSearchedList());
}
private void FiltersOnFiltersUpdated()
diff --git a/SS14.Launcher/Views/MainWindowContent.xaml b/SS14.Launcher/Views/MainWindowContent.xaml
index 670c8e0e..31fe04de 100644
--- a/SS14.Launcher/Views/MainWindowContent.xaml
+++ b/SS14.Launcher/Views/MainWindowContent.xaml
@@ -53,7 +53,7 @@
+ SelectedIndex="{Binding SelectedIndex,Mode=TwoWay}">
diff --git a/SS14.Launcher/Views/MainWindowTabs/HomePageView.xaml b/SS14.Launcher/Views/MainWindowTabs/HomePageView.xaml
index 73e7e291..370bac62 100644
--- a/SS14.Launcher/Views/MainWindowTabs/HomePageView.xaml
+++ b/SS14.Launcher/Views/MainWindowTabs/HomePageView.xaml
@@ -14,7 +14,7 @@
-
+
-
-
+
-
+
+
diff --git a/SS14.Launcher/Views/MainWindowTabs/ServerEntryView.xaml b/SS14.Launcher/Views/MainWindowTabs/ServerEntryView.xaml
index d126e6ca..8d832622 100644
--- a/SS14.Launcher/Views/MainWindowTabs/ServerEntryView.xaml
+++ b/SS14.Launcher/Views/MainWindowTabs/ServerEntryView.xaml
@@ -1,14 +1,13 @@
+ 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:mainWindowTabs="clr-namespace:SS14.Launcher.ViewModels.MainWindowTabs"
+ xmlns:models="clr-namespace:SS14.Launcher.Models"
+ xmlns:views="clr-namespace:SS14.Launcher.Views"
+ xmlns:loc="clr-namespace:SS14.Launcher.Localization"
+ mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
+ x:Class="SS14.Launcher.Views.MainWindowTabs.ServerEntryView">
@@ -22,82 +21,49 @@
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
+
-
-
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
+
+
+
+
+
diff --git a/SS14.Launcher/Views/MainWindowTabs/ServerList.xaml b/SS14.Launcher/Views/MainWindowTabs/ServerList.xaml
new file mode 100644
index 00000000..a5a4b89f
--- /dev/null
+++ b/SS14.Launcher/Views/MainWindowTabs/ServerList.xaml
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SS14.Launcher/Views/MainWindowTabs/ServerList.xaml.cs b/SS14.Launcher/Views/MainWindowTabs/ServerList.xaml.cs
index fd611416..22fbdb8a 100644
--- a/SS14.Launcher/Views/MainWindowTabs/ServerList.xaml.cs
+++ b/SS14.Launcher/Views/MainWindowTabs/ServerList.xaml.cs
@@ -1,16 +1,66 @@
-using System;
+using System.Collections;
+using System.ComponentModel;
+using System.Linq;
using Avalonia;
-using Avalonia.Controls.Primitives;
-using System.Collections.Generic;
+using Avalonia.Collections;
using Avalonia.Controls;
-using Avalonia.Metadata;
-using Serilog;
using SS14.Launcher.ViewModels.MainWindowTabs;
+using static System.ComponentModel.ListSortDirection;
namespace SS14.Launcher.Views.MainWindowTabs;
-public sealed partial class ServerList : TemplatedControl
+public sealed partial class ServerList : UserControl
{
+ public ServerList()
+ {
+ InitializeComponent();
+
+ ServerGrid.SelectionChanged += (_, args) =>
+ {
+ foreach (ServerEntryViewModel rem in args.RemovedItems)
+ {
+ rem.IsExpanded = false;
+ }
+
+ foreach (ServerEntryViewModel add in args.AddedItems)
+ {
+ add.IsExpanded = true;
+ }
+ };
+
+ ServerGrid.Sorting += (_, args) =>
+ {
+ args.Handled = true; // Stop Avalonia from messing with our custom behavior
+
+ if (ServerGrid.ItemsSource is not DataGridCollectionView view)
+ return;
+
+ var currentSort = view.SortDescriptions.FirstOrDefault();
+ view.SortDescriptions.Clear(); // Start fresh
+
+ // This key/path corresponds to what the user wants to sort
+ var clickedKey = args.Column.SortMemberPath;
+
+ ListSortDirection? direction = currentSort switch
+ {
+ // No column is sorted: set clicked column to ascending
+ null => Ascending,
+ // Clicked column does not match currently sorted column: set clicked column to ascending
+ { PropertyPath: { } currentKey } when currentKey != clickedKey => Ascending,
+ // Cycle through ascending -> descending -> no sort -> ascending
+ { Direction: Ascending } => Descending,
+ { Direction: Descending } => null,
+ _ => Ascending,
+ };
+
+ if (direction is not { } d)
+ return; // Do not set any sorting
+
+ var comparer = ServerEntryViewModel.ComparerMapping[clickedKey];
+ view.SortDescriptions.Add(DataGridSortDescription.FromPath(clickedKey, d, comparer));
+ };
+ }
+
public static readonly DirectProperty ShowHeaderProperty =
AvaloniaProperty.RegisterDirect(
nameof(ShowHeader),
@@ -60,32 +110,18 @@ public bool SpinnerVisible
set => SetAndRaise(SpinnerVisibleProperty, ref _spinnerVisible, value);
}
- public static readonly DirectProperty> ListProperty =
- AvaloniaProperty.RegisterDirect>(
- nameof(List),
- o => o.List,
- (o, v) => o.List = v
- );
-
- private IReadOnlyCollection _serverList = Array.Empty();
-
- public IReadOnlyCollection List
- {
- get => _serverList;
- set => SetAndRaise(ListProperty, ref _serverList, value);
- }
-
- public static readonly StyledProperty