mirror of
https://github.com/Stone-Red-Code/EchoHub.git
synced 2026-09-04 00:56:05 +02:00
feat: implement background update check and add version notification in AppOrchestrator
This commit is contained in:
@@ -414,6 +414,18 @@ public sealed class AppOrchestrator : IDisposable
|
|||||||
|
|
||||||
FetchAndUpdateOnlineUsers();
|
FetchAndUpdateOnlineUsers();
|
||||||
SaveServerToConfig(result);
|
SaveServerToConfig(result);
|
||||||
|
|
||||||
|
// Check for newer version in the background
|
||||||
|
_ = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
var newVersion = await UpdateChecker.CheckForUpdateAsync();
|
||||||
|
if (newVersion is not null)
|
||||||
|
{
|
||||||
|
InvokeUI(() => _mainWindow.AddSystemMessage(
|
||||||
|
HubConstants.DefaultChannel,
|
||||||
|
$"A new version of EchoHub is available: v{newVersion} (current: v{MainWindow.AppVersion}). Visit https://github.com/HueByte/EchoHub/releases"));
|
||||||
|
}
|
||||||
|
});
|
||||||
}, "Connection failed", "Connect");
|
}, "Connection failed", "Connect");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
using System.Net.Http.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace EchoHub.Client.Services;
|
||||||
|
|
||||||
|
public static class UpdateChecker
|
||||||
|
{
|
||||||
|
private static readonly Uri ReleaseUrl =
|
||||||
|
new("https://api.github.com/repos/HueByte/EchoHub/releases/latest");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks GitHub for a newer release. Returns the new version string if one exists, or null.
|
||||||
|
/// Never throws — all errors are silently swallowed.
|
||||||
|
/// </summary>
|
||||||
|
public static async Task<string?> CheckForUpdateAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(5) };
|
||||||
|
http.DefaultRequestHeaders.UserAgent.ParseAdd("EchoHub-Client");
|
||||||
|
|
||||||
|
var release = await http.GetFromJsonAsync<GitHubRelease>(ReleaseUrl);
|
||||||
|
if (release?.TagName is null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var tag = release.TagName.TrimStart('v', 'V');
|
||||||
|
if (!Version.TryParse(tag, out var latest))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var currentStr = typeof(UpdateChecker).Assembly.GetName().Version?.ToString(3);
|
||||||
|
if (currentStr is null || !Version.TryParse(currentStr, out var current))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return latest > current ? tag : null;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class GitHubRelease
|
||||||
|
{
|
||||||
|
[JsonPropertyName("tag_name")]
|
||||||
|
public string? TagName { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,7 +34,7 @@ public sealed class MainWindow : Runnable
|
|||||||
private const int UsersPanelWidth = 22;
|
private const int UsersPanelWidth = 22;
|
||||||
private static readonly Key F2Key = Key.F2;
|
private static readonly Key F2Key = Key.F2;
|
||||||
|
|
||||||
private static readonly string AppVersion =
|
internal static readonly string AppVersion =
|
||||||
typeof(MainWindow).Assembly.GetName().Version?.ToString(3) ?? "?";
|
typeof(MainWindow).Assembly.GetName().Version?.ToString(3) ?? "?";
|
||||||
|
|
||||||
// Cached Key constants — compare via .KeyCode to avoid Key.Equals (which also checks Handled)
|
// Cached Key constants — compare via .KeyCode to avoid Key.Equals (which also checks Handled)
|
||||||
@@ -479,19 +479,33 @@ public sealed class MainWindow : Runnable
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void AddSystemMessage(string channelName, string text)
|
public void AddSystemMessage(string channelName, string text)
|
||||||
{
|
{
|
||||||
var time = DateTimeOffset.Now.ToString("HH:mm");
|
|
||||||
var segments = new List<ChatSegment>
|
|
||||||
{
|
|
||||||
new($"[{time}] ", ChatColors.TimestampAttr),
|
|
||||||
new($"** {text}", ChatColors.SystemAttr)
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!_channelMessages.TryGetValue(channelName, out var messages))
|
if (!_channelMessages.TryGetValue(channelName, out var messages))
|
||||||
{
|
{
|
||||||
messages = [];
|
messages = [];
|
||||||
_channelMessages[channelName] = messages;
|
_channelMessages[channelName] = messages;
|
||||||
}
|
}
|
||||||
messages.Add(new ChatLine(segments));
|
|
||||||
|
var time = DateTimeOffset.Now.ToString("HH:mm");
|
||||||
|
var textLines = text.Split('\n');
|
||||||
|
|
||||||
|
// First line gets timestamp prefix
|
||||||
|
messages.Add(new ChatLine(
|
||||||
|
[
|
||||||
|
new($"[{time}] ", ChatColors.TimestampAttr),
|
||||||
|
new($"** {textLines[0].TrimEnd('\r')}", ChatColors.SystemAttr)
|
||||||
|
]));
|
||||||
|
|
||||||
|
// Continuation lines are indented to align
|
||||||
|
var indent = new string(' ', $"[{time}] ** ".Length);
|
||||||
|
for (int i = 1; i < textLines.Length; i++)
|
||||||
|
{
|
||||||
|
var line = textLines[i].TrimEnd('\r');
|
||||||
|
if (string.IsNullOrWhiteSpace(line)) continue;
|
||||||
|
messages.Add(new ChatLine(
|
||||||
|
[
|
||||||
|
new($"{indent}{line}", ChatColors.SystemAttr)
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
if (channelName == _currentChannel)
|
if (channelName == _currentChannel)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user