From 1ffeb1a65ffe999a6947fb96c08c81fe6362f55f Mon Sep 17 00:00:00 2001 From: Filipe Moreira Date: Mon, 28 Sep 2026 11:42:14 -0300 Subject: [PATCH 1/2] feat(updates): opt in to test versions (alpha/beta) from Settings - New BetaUpdates setting (off by default), in desktop and console Settings. - The update check offers pre-releases when opted in or when a pre-release is already installed (UpdateChannel, tested); turning it off never downgrades. - Turning it on shows a warning; strings in pt-BR, en-US and es-ES. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.en-US.md | 4 ++++ CHANGELOG.md | 4 ++++ src/ConsoleMode/Models/Models.cs | 2 ++ src/ConsoleMode/Resources/Strings.en-US.json | 3 +++ src/ConsoleMode/Resources/Strings.es-ES.json | 3 +++ src/ConsoleMode/Resources/Strings.pt-BR.json | 3 +++ src/ConsoleMode/Services/ConsoleEngine.cs | 1 + src/ConsoleMode/Services/LocalizationService.cs | 2 ++ src/ConsoleMode/Services/UpdateChannel.cs | 12 ++++++++++++ src/ConsoleMode/Services/UpdateService.cs | 6 +++--- .../ViewModels/MainViewModel.ConsoleUi.cs | 1 + .../ViewModels/MainViewModel.Updates.cs | 10 +++++++++- src/ConsoleMode/ViewModels/MainViewModel.cs | 2 ++ src/ConsoleMode/Views/ConsoleHomeView.xaml | 6 ++++++ src/ConsoleMode/Views/SettingsView.xaml | 7 +++++++ tests/ConsoleMode.Tests/ConsoleMode.Tests.csproj | 1 + tests/ConsoleMode.Tests/UpdateChannelTests.cs | 14 ++++++++++++++ 17 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 src/ConsoleMode/Services/UpdateChannel.cs create mode 100644 tests/ConsoleMode.Tests/UpdateChannelTests.cs diff --git a/CHANGELOG.en-US.md b/CHANGELOG.en-US.md index 708cb86..06c203e 100644 --- a/CHANGELOG.en-US.md +++ b/CHANGELOG.en-US.md @@ -2,6 +2,10 @@ English (US) release notes, mirroring CHANGELOG.md (Brazilian Portuguese). Before publishing a version, add a `## [VERSION]` section to **both** files: the workflow publishes the section matching the tag from each one and fails if either is missing. +## [Unreleased] +### What's new +- Settings → "Receive test versions (alpha and beta)": anyone can join the tests of upcoming versions from the app. Off by default; turning it on shows a warning that test versions can have bugs. + ## [1.6.0-alpha.2] ### Changes - 1.6 is all the project's own code: the option to go back to MultiMonitorTool / SoundVolumeView is gone too, and their old files in the `tools` folder are deleted when the app opens. (#91) diff --git a/CHANGELOG.md b/CHANGELOG.md index 307a93e..a17c01e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ Notas em português do Brasil; a versão em inglês (Estados Unidos) fica em `CHANGELOG.en-US.md`. Antes de publicar uma versão, adicione uma seção `## [VERSÃO]` com o changelog daquela versão **nos dois arquivos**. O workflow publica as duas seções correspondentes à tag na mesma release e falha se faltar alguma. +## [Unreleased] +### Novidades +- Ajustes → "Receber versões de teste (alpha e beta)": qualquer pessoa pode entrar nos testes das próximas versões pelo próprio app. Desligado por padrão; ao ligar, o app avisa que a versão pode ter bugs. + ## [1.6.0-alpha.2] ### Mudanças - A 1.6 é só código do projeto: saiu também a opção de voltar ao MultiMonitorTool / SoundVolumeView, e os arquivos antigos deles na pasta `tools` são apagados ao abrir o app. (#91) diff --git a/src/ConsoleMode/Models/Models.cs b/src/ConsoleMode/Models/Models.cs index ab0cb09..d4cfa46 100644 --- a/src/ConsoleMode/Models/Models.cs +++ b/src/ConsoleMode/Models/Models.cs @@ -38,6 +38,8 @@ public sealed class AppConfig /// Look for new GitHub releases on startup. public bool CheckUpdates { get; set; } = true; + /// Also offer alpha/beta releases (Settings → Receive test versions). + public bool BetaUpdates { get; set; } /// Holding the Xbox Guide (Home) button while in the tray enters console mode. public bool HomeButtonLaunch { get; set; } = true; diff --git a/src/ConsoleMode/Resources/Strings.en-US.json b/src/ConsoleMode/Resources/Strings.en-US.json index f9a652d..bd8e198 100644 --- a/src/ConsoleMode/Resources/Strings.en-US.json +++ b/src/ConsoleMode/Resources/Strings.en-US.json @@ -89,6 +89,9 @@ "CheckNow": "Check now", "NotifyUpdatesCard": "Notify me when a new version is available", "NotifyUpdatesDescription": "Checks GitHub releases when the app starts.", + "BetaUpdatesCard": "Receive test versions (alpha and beta)", + "BetaUpdatesDescription": "Get early versions before everyone else to help test them. They can have bugs. Turning this off doesn't go back to the stable version: you'll get the next stable one when it comes out.", + "BetaUpdatesWarning": "Test versions can fail on some setups. If something breaks, download the stable version from the releases page and tell us with the feedback button.", "HelpDataSection": "Shortcut, help, and data", "OtherAppsSection": "More apps from the developer", "WakeOnDescription": "Automation with Wake-on-LAN", diff --git a/src/ConsoleMode/Resources/Strings.es-ES.json b/src/ConsoleMode/Resources/Strings.es-ES.json index 53f3eb0..fd97117 100644 --- a/src/ConsoleMode/Resources/Strings.es-ES.json +++ b/src/ConsoleMode/Resources/Strings.es-ES.json @@ -89,6 +89,9 @@ "CheckNow": "Buscar ahora", "NotifyUpdatesCard": "Avisarme cuando haya una versión nueva", "NotifyUpdatesDescription": "Consulta las versiones de GitHub al abrir la aplicación.", + "BetaUpdatesCard": "Recibir versiones de prueba (alfa y beta)", + "BetaUpdatesDescription": "Recibe las versiones nuevas antes que nadie para ayudar a probarlas. Pueden tener errores. Desactivarlo no vuelve a la versión estable: recibirás la próxima estable cuando salga.", + "BetaUpdatesWarning": "Las versiones de prueba pueden fallar en algunas configuraciones. Si algo sale mal, descarga la versión estable en la página de versiones y cuéntanoslo con el botón de comentarios.", "HelpDataSection": "Acceso directo, ayuda y datos", "OtherAppsSection": "Más apps del desarrollador", "WakeOnDescription": "Automatización con Wake-on-LAN", diff --git a/src/ConsoleMode/Resources/Strings.pt-BR.json b/src/ConsoleMode/Resources/Strings.pt-BR.json index 7b8e612..dcabf5d 100644 --- a/src/ConsoleMode/Resources/Strings.pt-BR.json +++ b/src/ConsoleMode/Resources/Strings.pt-BR.json @@ -89,6 +89,9 @@ "CheckNow": "Procurar agora", "NotifyUpdatesCard": "Avisar quando sair versão nova", "NotifyUpdatesDescription": "Consulta as releases no GitHub ao abrir o app.", + "BetaUpdatesCard": "Receber versões de teste (alpha e beta)", + "BetaUpdatesDescription": "Recebe as versões novas antes de todo mundo para ajudar a testar. Elas podem ter bugs. Desligar não volta para a versão estável: você recebe a próxima estável quando ela sair.", + "BetaUpdatesWarning": "Versões de teste podem falhar em alguns setups. Se algo der errado, baixe a versão estável na página de releases e conte pelo botão de feedback.", "HelpDataSection": "Atalho, ajuda e dados", "OtherAppsSection": "Outros apps do desenvolvedor", "WakeOnDescription": "Automação com Wake-on-LAN", diff --git a/src/ConsoleMode/Services/ConsoleEngine.cs b/src/ConsoleMode/Services/ConsoleEngine.cs index 7e4a38e..18cdd0a 100644 --- a/src/ConsoleMode/Services/ConsoleEngine.cs +++ b/src/ConsoleMode/Services/ConsoleEngine.cs @@ -385,6 +385,7 @@ private AppConfig ResolveMonitorNames(AppConfig config) TourDone = config.TourDone, ConfirmedSetup = config.ConfirmedSetup, CheckUpdates = config.CheckUpdates, + BetaUpdates = config.BetaUpdates, SkippedUpdateVersion = config.SkippedUpdateVersion }; } diff --git a/src/ConsoleMode/Services/LocalizationService.cs b/src/ConsoleMode/Services/LocalizationService.cs index 9114be3..a4162c0 100644 --- a/src/ConsoleMode/Services/LocalizationService.cs +++ b/src/ConsoleMode/Services/LocalizationService.cs @@ -191,6 +191,8 @@ internal void NotifyAll() public string AutoStartControllerDescription => LocalizationService.Get(nameof(AutoStartControllerDescription)); public string NotifyUpdatesCard => LocalizationService.Get(nameof(NotifyUpdatesCard)); public string NotifyUpdatesDescription => LocalizationService.Get(nameof(NotifyUpdatesDescription)); + public string BetaUpdatesCard => LocalizationService.Get(nameof(BetaUpdatesCard)); + public string BetaUpdatesDescription => LocalizationService.Get(nameof(BetaUpdatesDescription)); public string HelpDataSection => LocalizationService.Get(nameof(HelpDataSection)); public string OtherAppsSection => LocalizationService.Get(nameof(OtherAppsSection)); public string WakeOnDescription => LocalizationService.Get(nameof(WakeOnDescription)); diff --git a/src/ConsoleMode/Services/UpdateChannel.cs b/src/ConsoleMode/Services/UpdateChannel.cs new file mode 100644 index 0000000..e0f1607 --- /dev/null +++ b/src/ConsoleMode/Services/UpdateChannel.cs @@ -0,0 +1,12 @@ +namespace ConsoleMode.Services; + +/// Which releases the update check offers. Pure, so it's tested. +public static class UpdateChannel +{ + /// + /// Test versions (alpha/beta) are offered when the user opted in, or when a test version is + /// already installed. Turning the option off never downgrades: a test build keeps getting test + /// builds until a newer stable one comes out. + /// + public static bool IncludePrereleases(bool currentIsPrerelease, bool optedIn) => currentIsPrerelease || optedIn; +} diff --git a/src/ConsoleMode/Services/UpdateService.cs b/src/ConsoleMode/Services/UpdateService.cs index 8358426..371e7c5 100644 --- a/src/ConsoleMode/Services/UpdateService.cs +++ b/src/ConsoleMode/Services/UpdateService.cs @@ -39,7 +39,7 @@ private static HttpClient CreateClient() } /// Newest published release above the running version, or null when up to date. - public static async Task CheckAsync(CancellationToken ct = default) + public static async Task CheckAsync(bool optedIntoPrereleases = false, CancellationToken ct = default) { using var timeout = CancellationTokenSource.CreateLinkedTokenSource(ct); timeout.CancelAfter(CheckTimeout); @@ -52,8 +52,8 @@ private static HttpClient CreateClient() using var doc = await JsonDocument.ParseAsync(stream, cancellationToken: ct); var current = SemVer.Parse(CurrentVersion); - // Betas see betas; stable builds only get stable releases. - var allowPrerelease = current.IsPrerelease; + // Test builds see test builds; stable builds only get them when the user opted in. + var allowPrerelease = UpdateChannel.IncludePrereleases(current.IsPrerelease, optedIntoPrereleases); UpdateInfo? best = null; SemVer? bestVersion = null; diff --git a/src/ConsoleMode/ViewModels/MainViewModel.ConsoleUi.cs b/src/ConsoleMode/ViewModels/MainViewModel.ConsoleUi.cs index b2d5812..99e1bb1 100644 --- a/src/ConsoleMode/ViewModels/MainViewModel.ConsoleUi.cs +++ b/src/ConsoleMode/ViewModels/MainViewModel.ConsoleUi.cs @@ -183,6 +183,7 @@ private void CycleSetting(string spec) case "autostart": AutoStartOnController = !AutoStartOnController; break; case "startup": StartWithWindows = !StartWithWindows; break; case "updates": CheckUpdates = !CheckUpdates; break; + case "betas": BetaUpdates = !BetaUpdates; break; } } diff --git a/src/ConsoleMode/ViewModels/MainViewModel.Updates.cs b/src/ConsoleMode/ViewModels/MainViewModel.Updates.cs index 452d55e..2eb80dc 100644 --- a/src/ConsoleMode/ViewModels/MainViewModel.Updates.cs +++ b/src/ConsoleMode/ViewModels/MainViewModel.Updates.cs @@ -16,6 +16,7 @@ public partial class MainViewModel private enum UpdateStatusKind { InstallKind, Searching, Latest, Available, Failed } [ObservableProperty] private bool _checkUpdates = true; + [ObservableProperty] private bool _betaUpdates; [ObservableProperty] private bool _homeButtonLaunch = true; [ObservableProperty] private bool _homeButtonShortPress; [ObservableProperty] private bool _autoStartOnController; @@ -80,6 +81,13 @@ partial void OnStartWithWindowsChanged(bool value) partial void OnCheckUpdatesChanged(bool value) => SaveQuietly(); + partial void OnBetaUpdatesChanged(bool value) + { + SaveQuietly(); + if (_applying || IsLoading) return; + if (value) SetStatus(LocalizationService.Get("BetaUpdatesWarning"), InfoBarSeverity.Warning); + } + partial void OnHomeButtonLaunchChanged(bool value) => SaveQuietly(); partial void OnAutoStartOnControllerChanged(bool value) => SaveQuietly(); @@ -129,7 +137,7 @@ private async Task CheckForUpdatesAsync(bool manual) } try { - var update = await UpdateService.CheckAsync(); + var update = await UpdateService.CheckAsync(BetaUpdates); if (update is null) { _updateStatusKind = UpdateStatusKind.Latest; diff --git a/src/ConsoleMode/ViewModels/MainViewModel.cs b/src/ConsoleMode/ViewModels/MainViewModel.cs index 26837b6..b2919d1 100644 --- a/src/ConsoleMode/ViewModels/MainViewModel.cs +++ b/src/ConsoleMode/ViewModels/MainViewModel.cs @@ -301,6 +301,7 @@ private void Apply(LoadResult data) HdrEnable = config.HdrEnable; VrrEnable = config.VrrEnable; CheckUpdates = config.CheckUpdates; + BetaUpdates = config.BetaUpdates; HomeButtonLaunch = config.HomeButtonLaunch; HomeButtonShortPress = config.HomeButtonShortPress; AutoStartOnController = config.AutoStartOnController; @@ -887,6 +888,7 @@ private AppConfig BuildConfig() TourDone = _loadedConfig.TourDone, ConfirmedSetup = _loadedConfig.ConfirmedSetup, CheckUpdates = CheckUpdates, + BetaUpdates = BetaUpdates, HomeButtonLaunch = HomeButtonLaunch, HomeButtonShortPress = HomeButtonShortPress, AutoStartOnController = AutoStartOnController, diff --git a/src/ConsoleMode/Views/ConsoleHomeView.xaml b/src/ConsoleMode/Views/ConsoleHomeView.xaml index 86c49d5..805d00b 100644 --- a/src/ConsoleMode/Views/ConsoleHomeView.xaml +++ b/src/ConsoleMode/Views/ConsoleHomeView.xaml @@ -412,6 +412,12 @@ +