diff --git a/LANCommander.Launcher/Assets/Localization/en-US.axaml b/LANCommander.Launcher/Assets/Localization/en-US.axaml index 964de468..48f6877a 100644 --- a/LANCommander.Launcher/Assets/Localization/en-US.axaml +++ b/LANCommander.Launcher/Assets/Localization/en-US.axaml @@ -121,6 +121,19 @@ Failed Queued + + None + {0} minutes + {0} hours + Never + Just now + {0} minute ago + {0} minutes ago + {0} hour ago + {0} hours ago + {0} day ago + {0} days ago + Singleplayer Genres diff --git a/LANCommander.Launcher/ViewModels/Components/GameActionBarViewModel.cs b/LANCommander.Launcher/ViewModels/Components/GameActionBarViewModel.cs index 8d2df120..e47c3713 100644 --- a/LANCommander.Launcher/ViewModels/Components/GameActionBarViewModel.cs +++ b/LANCommander.Launcher/ViewModels/Components/GameActionBarViewModel.cs @@ -88,10 +88,10 @@ public partial class GameActionBarViewModel : ViewModelBase // Stats [ObservableProperty] - private string _playTime = "None"; + private string _playTime = Localize("PlayStatNone"); [ObservableProperty] - private string _lastPlayed = "Never"; + private string _lastPlayed = Localize("LastPlayedNever"); // Status [ObservableProperty] @@ -172,6 +172,12 @@ public partial class GameActionBarViewModel : ViewModelBase // Timer for checking running state private System.Threading.Timer? _runningCheckTimer; + // Timer for refreshing the "Last Played" relative time text + private System.Threading.Timer? _lastPlayedTimer; + + // End time of the most recent play session, used to recompute the relative text + private DateTime? _lastSessionEnd; + // Events public event EventHandler? LibraryChanged; public event EventHandler? InstallRequested; @@ -245,8 +251,8 @@ public partial class GameActionBarViewModel : ViewModelBase IsInstalled = false; InstallDirectory = null; IsUpdateAvailable = false; - PlayTime = "None"; - LastPlayed = "Never"; + PlayTime = Localize("PlayStatNone"); + LastPlayed = Localize("LastPlayedNever"); Manuals.Clear(); HasManuals = false; } @@ -362,12 +368,22 @@ public partial class GameActionBarViewModel : ViewModelBase null, TimeSpan.Zero, TimeSpan.FromMilliseconds(500)); + + _lastPlayedTimer?.Dispose(); + _lastPlayedTimer = new System.Threading.Timer( + _ => Dispatcher.UIThread.Post(UpdateLastPlayedText), + null, + TimeSpan.FromMinutes(1), + TimeSpan.FromMinutes(1)); } public void StopRunningCheck() { _runningCheckTimer?.Dispose(); _runningCheckTimer = null; + + _lastPlayedTimer?.Dispose(); + _lastPlayedTimer = null; } private void CheckRunningState() @@ -443,35 +459,61 @@ public partial class GameActionBarViewModel : ViewModelBase .Sum(ts => ts.Ticks)); if (totalTime.TotalMinutes < 1) - PlayTime = "None"; + PlayTime = Localize("PlayStatNone"); else if (totalTime.TotalHours < 1) - PlayTime = $"{totalTime.TotalMinutes:0} minutes"; + PlayTime = Localize("PlayTimeMinutes", $"{totalTime.TotalMinutes:0}"); else - PlayTime = $"{totalTime.TotalHours:0.#} hours"; + PlayTime = Localize("PlayTimeHours", $"{totalTime.TotalHours:0.#}"); var lastSession = playSessions .OrderByDescending(ps => ps.End) .First(); - var elapsed = DateTime.Now - lastSession.End!.Value; - if (elapsed.TotalMinutes < 1) - LastPlayed = "Just now"; - else if (elapsed.TotalHours < 1) - LastPlayed = $"{elapsed.TotalMinutes:0} minutes ago"; - else if (elapsed.TotalDays < 1) - LastPlayed = $"{elapsed.TotalHours:0} hours ago"; - else if (elapsed.TotalDays < 7) - LastPlayed = $"{elapsed.TotalDays:0} days ago"; - else - LastPlayed = lastSession.End.Value.ToString("MMM d, yyyy"); + _lastSessionEnd = lastSession.End!.Value; + UpdateLastPlayedText(); } else { - PlayTime = "None"; - LastPlayed = "Never"; + PlayTime = Localize("PlayStatNone"); + _lastSessionEnd = null; + LastPlayed = Localize("LastPlayedNever"); } } + /// + /// Recomputes the relative "Last Played" text from the cached last session end time. + /// Called on load and periodically so the text stays current without re-querying. + /// + private void UpdateLastPlayedText() + { + if (_lastSessionEnd is not { } end) + { + LastPlayed = Localize("LastPlayedNever"); + return; + } + + var elapsed = DateTime.Now - end; + if (elapsed.TotalMinutes < 1) + LastPlayed = Localize("LastPlayedJustNow"); + else if (elapsed.TotalHours < 1) + { + var minutes = (int)elapsed.TotalMinutes; + LastPlayed = Localize(minutes == 1 ? "LastPlayedMinuteAgo" : "LastPlayedMinutesAgo", minutes); + } + else if (elapsed.TotalDays < 1) + { + var hours = (int)elapsed.TotalHours; + LastPlayed = Localize(hours == 1 ? "LastPlayedHourAgo" : "LastPlayedHoursAgo", hours); + } + else if (elapsed.TotalDays < 7) + { + var days = (int)elapsed.TotalDays; + LastPlayed = Localize(days == 1 ? "LastPlayedDayAgo" : "LastPlayedDaysAgo", days); + } + else + LastPlayed = end.ToString("MMM d, yyyy"); + } + /// /// Checks the server for available updates and updates local state if found. /// If no update is available, refreshes the on-disk manifest and scripts.