From 506dd9241f910e0ef68c61bdf0e66f38398b1661 Mon Sep 17 00:00:00 2001 From: Stone_Red <56473591+Stone-Red-Code@users.noreply.github.com> Date: Tue, 3 Nov 2026 21:37:52 +0100 Subject: [PATCH 1/2] fix: save refreshed tokens for server URLs with a trailing slash --- src/EchoHub.Client/AppOrchestrator.cs | 3 +- src/EchoHub.Client/Config/ClientConfig.cs | 8 +++++ .../Services/ConnectionManager.cs | 8 ++--- src/EchoHub.Tests/ClientConfigTests.cs | 30 +++++++++++++++++++ 4 files changed, 41 insertions(+), 8 deletions(-) create mode 100644 src/EchoHub.Tests/ClientConfigTests.cs diff --git a/src/EchoHub.Client/AppOrchestrator.cs b/src/EchoHub.Client/AppOrchestrator.cs index 7769d0a..20d5e9e 100644 --- a/src/EchoHub.Client/AppOrchestrator.cs +++ b/src/EchoHub.Client/AppOrchestrator.cs @@ -2232,8 +2232,7 @@ public sealed class AppOrchestrator : IDisposable if (url is null) return; var config = ConfigManager.Load(); - var server = config.SavedServers.FirstOrDefault(s => - string.Equals(s.Url, url, StringComparison.OrdinalIgnoreCase)); + var server = config.FindServer(url); if (server is null) return; mutate(server); diff --git a/src/EchoHub.Client/Config/ClientConfig.cs b/src/EchoHub.Client/Config/ClientConfig.cs index 6fa2d91..0a69ab9 100644 --- a/src/EchoHub.Client/Config/ClientConfig.cs +++ b/src/EchoHub.Client/Config/ClientConfig.cs @@ -18,6 +18,14 @@ public class ClientConfig /// Applies to copy-paste/drag-drop attachments, which have no per-file size flag. /// public string DefaultAsciiSize { get; set; } = "m"; + + /// + /// Finds a saved server by URL. A trailing slash is ignored: entries keep the URL as the + /// user typed it, while has the slash removed. + /// + public SavedServer? FindServer(string url) => + SavedServers.FirstOrDefault(s => + string.Equals(s.Url.TrimEnd('/'), url.TrimEnd('/'), StringComparison.OrdinalIgnoreCase)); } public class NotificationConfig diff --git a/src/EchoHub.Client/Services/ConnectionManager.cs b/src/EchoHub.Client/Services/ConnectionManager.cs index 40cd701..b4f5004 100644 --- a/src/EchoHub.Client/Services/ConnectionManager.cs +++ b/src/EchoHub.Client/Services/ConnectionManager.cs @@ -152,7 +152,7 @@ internal sealed class ConnectionManager : IAsyncDisposable // all of them, not just channels opened this session. Channels the user left // with /leave stay out until rejoined; protected channels we can't enter // silently (no cached membership) are skipped, never prompted for. - var leftChannels = FindServer(ConfigManager.Load(), info.ServerUrl)?.LeftChannels ?? []; + var leftChannels = ConfigManager.Load().FindServer(info.ServerUrl)?.LeftChannels ?? []; foreach (var channel in channels) { if (channel.Name.Equals(HubConstants.DefaultChannel, StringComparison.OrdinalIgnoreCase)) @@ -332,7 +332,7 @@ internal sealed class ConnectionManager : IAsyncDisposable { if (_apiClient?.RefreshToken is null) return; var config = ConfigManager.Load(); - var server = FindServer(config, _apiClient.BaseUrl); + var server = config.FindServer(_apiClient.BaseUrl); if (server is not null && server.RememberMe) { server.RefreshToken = _apiClient.RefreshToken; @@ -340,10 +340,6 @@ internal sealed class ConnectionManager : IAsyncDisposable } } - private static SavedServer? FindServer(ClientConfig config, string url) => - config.SavedServers.FirstOrDefault(s => - string.Equals(s.Url, url, StringComparison.OrdinalIgnoreCase)); - // ── Dispose ─────────────────────────────────────────────────────────── public async ValueTask DisposeAsync() diff --git a/src/EchoHub.Tests/ClientConfigTests.cs b/src/EchoHub.Tests/ClientConfigTests.cs new file mode 100644 index 0000000..a3bac43 --- /dev/null +++ b/src/EchoHub.Tests/ClientConfigTests.cs @@ -0,0 +1,30 @@ +using EchoHub.Client.Config; +using Xunit; + +namespace EchoHub.Tests; + +public class ClientConfigTests +{ + [Theory] + [InlineData("https://echo.example.com/", "https://echo.example.com")] + [InlineData("https://echo.example.com", "https://echo.example.com/")] + [InlineData("https://echo.example.com", "https://echo.example.com")] + [InlineData("https://ECHO.example.com/", "https://echo.example.com")] + public void FindServer_IgnoresTrailingSlashAndCase(string savedUrl, string lookupUrl) + { + var config = new ClientConfig(); + var server = new SavedServer { Name = "echo", Url = savedUrl }; + config.SavedServers.Add(server); + + Assert.Same(server, config.FindServer(lookupUrl)); + } + + [Fact] + public void FindServer_OtherServer_ReturnsNull() + { + var config = new ClientConfig(); + config.SavedServers.Add(new SavedServer { Name = "echo", Url = "https://echo.example.com/" }); + + Assert.Null(config.FindServer("https://other.example.com")); + } +} From 89dba31185bd44451378f2dd56e3ae5608d58a99 Mon Sep 17 00:00:00 2001 From: Stone_Red <56473591+Stone-Red-Code@users.noreply.github.com> Date: Tue, 3 Nov 2026 21:50:55 +0100 Subject: [PATCH 2/2] chore: add changelog --- docs/changelog/index.md | 2 +- docs/changelog/v0.2.18.md | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/changelog/index.md b/docs/changelog/index.md index 9b29bd7..a98c483 100644 --- a/docs/changelog/index.md +++ b/docs/changelog/index.md @@ -4,7 +4,7 @@ Release history for EchoHub. ## Releases -- [v0.2.18](v0.2.18.md) - IRCv3 Capabilities & Native OS Notifications +- [v0.2.18](v0.2.18.md) - IRCv3 Capabilities, Native OS Notifications & Saved Session Fix - [v0.2.17](v0.2.17.md) - Server Version Reporting & IRC Multi-Line Fix - [v0.2.16](v0.2.16.md) - Periodic Server-Stats Report, Upload & Moderation Logging & Quieter Connection Logs - [v0.2.15](v0.2.15.md) - Invite Codes, Data Export & Deletion, /me, /banner, Replies, Open Images In Browser & IRC Image Links diff --git a/docs/changelog/v0.2.18.md b/docs/changelog/v0.2.18.md index 6a031a2..ca52018 100644 --- a/docs/changelog/v0.2.18.md +++ b/docs/changelog/v0.2.18.md @@ -4,3 +4,7 @@ - **IRCv3 capabilities** — `server-time`, `message-tags`, `echo-message`, `batch` and `draft/multiline` are now advertised and fully supported in the IRC gateway. CAP LS 302 requests receive capability values. Clients can enable caps via CAP REQ and disable them with CAP REQ -cap. - **Native OS notifications** — EchoHub now supports native notifications on Windows, macOS and Linux. Notifications are sent for mentions or replies. + +## Bug Fixes + +- **Saved sessions lost after a token refresh** — refreshed tokens are now saved for servers whose saved URL ends in a slash. Previously the lookup compared the URL without the slash, so the new token was never written and the next launch failed with the old, already revoked one, logging the user out.