diff --git a/CursorLang.Core.Tests/Models/AppSettingsTests.cs b/CursorLang.Core.Tests/Models/AppSettingsTests.cs index 9b50559..e8a3422 100644 --- a/CursorLang.Core.Tests/Models/AppSettingsTests.cs +++ b/CursorLang.Core.Tests/Models/AppSettingsTests.cs @@ -137,10 +137,6 @@ public sealed class AppSettingsTests bool flag => !flag, Color color => Color.FromArgb((byte)(color.R + 1), color.G, color.B), Enum value => NextEnumValue(value), - DateTimeOffset moment => moment.AddDays(1), - - // A setting never set yet: the app has not checked for updates once - null when property.PropertyType == typeof(DateTimeOffset?) => DateTimeOffset.UnixEpoch, _ => throw new NotSupportedException($"Unknown kind of setting: {property.PropertyType}"), }; diff --git a/CursorLang.Core.Tests/Services/UpdateOptionsTests.cs b/CursorLang.Core.Tests/Services/UpdateOptionsTests.cs index f3e0ba6..218c368 100644 --- a/CursorLang.Core.Tests/Services/UpdateOptionsTests.cs +++ b/CursorLang.Core.Tests/Services/UpdateOptionsTests.cs @@ -29,10 +29,4 @@ public sealed class UpdateOptionsTests Assert.Equal("git.example.com", options.ServiceUri.Host); Assert.Equal("team/app", options.Project); } - - [Fact] - public void The_app_asks_about_releases_no_more_than_once_a_day() - { - Assert.Equal(TimeSpan.FromDays(1), new UpdateOptions().CheckInterval); - } } diff --git a/CursorLang.Core/Models/AppSettings.cs b/CursorLang.Core/Models/AppSettings.cs index 6ca77e8..64fb55d 100644 --- a/CursorLang.Core/Models/AppSettings.cs +++ b/CursorLang.Core/Models/AppSettings.cs @@ -87,20 +87,6 @@ public sealed partial class AppSettings : ObservableObject [ObservableProperty] private double _capsLockHoldMilliseconds = 300; - /// - /// Ask the repository about new versions on startup. A check can always be - /// started by hand — this setting turns off only the automatic one. - /// - [ObservableProperty] - private bool _checkForUpdates = true; - - /// - /// When the application last asked about new versions successfully. - /// Stored so as not to go to the network on every startup. - /// - [ObservableProperty] - private DateTimeOffset? _lastUpdateCheck; - /// The fill of the popup. The opacity is set by . [ObservableProperty] private Color _backgroundColor = Color.FromArgb(0xFF, 0x20, 0x20, 0x20); @@ -142,8 +128,6 @@ public sealed partial class AppSettings : ObservableObject DurationMilliseconds = other.DurationMilliseconds; UseCapsLockHotkey = other.UseCapsLockHotkey; CapsLockHoldMilliseconds = other.CapsLockHoldMilliseconds; - CheckForUpdates = other.CheckForUpdates; - LastUpdateCheck = other.LastUpdateCheck; BackgroundColor = other.BackgroundColor; ForegroundColor = other.ForegroundColor; } diff --git a/CursorLang.Core/Resources/Strings.resx b/CursorLang.Core/Resources/Strings.resx index 497a8ab..c2a22be 100644 --- a/CursorLang.Core/Resources/Strings.resx +++ b/CursorLang.Core/Resources/Strings.resx @@ -85,8 +85,8 @@ Dark - - Placement + + Layout popup Mode @@ -151,9 +151,6 @@ Margin from screen edge - - Appearance - Font size @@ -214,8 +211,8 @@ Check for updates - - Check for updates + + Updates have not been checked yet. Checking for updates… diff --git a/CursorLang.Core/Resources/Strings.ru.resx b/CursorLang.Core/Resources/Strings.ru.resx index 8e2e20a..551da8f 100644 --- a/CursorLang.Core/Resources/Strings.ru.resx +++ b/CursorLang.Core/Resources/Strings.ru.resx @@ -85,8 +85,8 @@ Тёмная - - Расположение + + Подсказка о раскладке Режим @@ -151,9 +151,6 @@ Отступ от края экрана - - Внешний вид - Размер шрифта @@ -214,8 +211,8 @@ Проверить обновления - - Проверять обновления + + Обновления ещё не проверялись. Идёт проверка обновлений… diff --git a/CursorLang.Core/Services/UpdateOptions.cs b/CursorLang.Core/Services/UpdateOptions.cs index 4a4a8a9..f386214 100644 --- a/CursorLang.Core/Services/UpdateOptions.cs +++ b/CursorLang.Core/Services/UpdateOptions.cs @@ -21,9 +21,6 @@ public sealed class UpdateOptions /// The project: owner/repository. public string Project { get; init; } = "alrakis/cursor-lang"; - /// How often the application checks the releases on its own. - public TimeSpan CheckInterval { get; init; } = TimeSpan.FromDays(1); - /// /// An access token for a private repository. /// diff --git a/CursorLang.Settings.Tests/Infrastructure/SettingsFakes.cs b/CursorLang.Settings.Tests/Infrastructure/SettingsFakes.cs index 29148b0..e3c653f 100644 --- a/CursorLang.Settings.Tests/Infrastructure/SettingsFakes.cs +++ b/CursorLang.Settings.Tests/Infrastructure/SettingsFakes.cs @@ -1,5 +1,4 @@ using CursorLang.Core.Models; -using CursorLang.Core.Services; using CursorLang.Settings.Services; using CursorLang.Settings.ViewModels; using CursorLang.Tests.Shared; @@ -12,7 +11,7 @@ namespace CursorLang.Settings.Tests.Infrastructure; internal static class Fake { internal static UpdateViewModel Updates() => - new(new FakeUpdateService(), new FakeLocalizationService(), new AppSettings(), new UpdateOptions()); + new(new FakeUpdateService(), new FakeLocalizationService()); } /// diff --git a/CursorLang.Settings.Tests/ViewModels/UpdateViewModelTests.cs b/CursorLang.Settings.Tests/ViewModels/UpdateViewModelTests.cs index 165505e..5566929 100644 --- a/CursorLang.Settings.Tests/ViewModels/UpdateViewModelTests.cs +++ b/CursorLang.Settings.Tests/ViewModels/UpdateViewModelTests.cs @@ -13,13 +13,15 @@ namespace CursorLang.Settings.Tests.ViewModels; /// public sealed class UpdateViewModelTests { + // The section has something to say at every moment, the one before the first + // answer included: the status line is never an empty spot in the window [Fact] - public void Before_the_first_check_the_section_says_nothing() + public void Before_the_first_check_the_section_says_so() { using UpdateViewModel viewModel = Create(new FakeUpdateService()); Assert.Equal(UpdateStatus.Idle, viewModel.Status); - Assert.False(viewModel.HasStatus); + Assert.Equal("en:UpdateNotChecked", viewModel.StatusText); Assert.False(viewModel.IsDownloadOffered); Assert.False(viewModel.IsInstallOffered); Assert.True(viewModel.CanCheck); @@ -62,96 +64,36 @@ public sealed class UpdateViewModelTests await viewModel.CheckCommand.ExecuteAsync(null); Assert.Equal(UpdateStatus.Failed, viewModel.Status); - Assert.True(viewModel.HasStatus); + Assert.Equal("en:UpdateFailed", viewModel.StatusText); } - // The app does not always start with a live network, and the user who never - // asked about updates has no use for the complaint + // The window is opened by hand, and the answer is what the section is there + // for: a dead network is part of the answer rather than a reason to say nothing [Fact] - public async Task A_check_at_startup_keeps_a_failure_to_itself() + public async Task A_check_when_the_window_opens_says_when_it_did_not_work_out() { var updates = new FakeUpdateService { Failure = new HttpRequestException("no network") }; using UpdateViewModel viewModel = Create(updates); await viewModel.StartAsync(); - Assert.Equal(UpdateStatus.Idle, viewModel.Status); - Assert.False(viewModel.HasStatus); + Assert.Equal(UpdateStatus.Failed, viewModel.Status); + Assert.Equal("en:UpdateFailed", viewModel.StatusText); } + // Nothing is remembered between openings: an answer from yesterday is worth + // less than today's, and the request costs nothing at this rate [Fact] - public async Task A_successful_check_is_remembered_in_the_settings() + public async Task Every_opening_of_the_window_asks_anew() { - var settings = new AppSettings(); - var updates = new FakeUpdateService { Release = Release("2.0.0.0") }; - using UpdateViewModel viewModel = Create(updates, settings); - - await viewModel.CheckCommand.ExecuteAsync(null); - - Assert.NotNull(settings.LastUpdateCheck); - } - - [Fact] - public async Task A_check_that_did_not_work_out_is_not_remembered() - { - var settings = new AppSettings(); - var updates = new FakeUpdateService { Failure = new HttpRequestException("no network") }; - using UpdateViewModel viewModel = Create(updates, settings); - - await viewModel.CheckCommand.ExecuteAsync(null); - - Assert.Null(settings.LastUpdateCheck); - } - - [Fact] - public async Task A_recent_check_is_not_repeated_at_startup() - { - var settings = new AppSettings { LastUpdateCheck = DateTimeOffset.UtcNow }; var updates = new FakeUpdateService(); - using UpdateViewModel viewModel = Create(updates, settings); + using UpdateViewModel viewModel = Create(updates); await viewModel.StartAsync(); - - Assert.Equal(0, updates.CheckCalls); - } - - [Fact] - public async Task A_check_of_yesterday_is_repeated_at_startup() - { - var settings = new AppSettings { LastUpdateCheck = DateTimeOffset.UtcNow - TimeSpan.FromDays(2) }; - var updates = new FakeUpdateService(); - using UpdateViewModel viewModel = Create(updates, settings); - - await viewModel.StartAsync(); - Assert.Equal(1, updates.CheckCalls); - } - - [Fact] - public async Task A_ban_on_checking_by_itself_is_obeyed() - { - var settings = new AppSettings { CheckForUpdates = false }; - var updates = new FakeUpdateService(); - using UpdateViewModel viewModel = Create(updates, settings); await viewModel.StartAsync(); - - Assert.Equal(0, updates.CheckCalls); - - // The button still works: the setting is about the app doing it on its own - await viewModel.CheckCommand.ExecuteAsync(null); - Assert.Equal(1, updates.CheckCalls); - } - - [Fact] - public void The_ban_on_checking_travels_to_the_settings() - { - var settings = new AppSettings { CheckForUpdates = true }; - using UpdateViewModel viewModel = Create(new FakeUpdateService(), settings); - - viewModel.CheckAutomatically = false; - - Assert.False(settings.CheckForUpdates); + Assert.Equal(2, updates.CheckCalls); } [Fact] @@ -283,10 +225,6 @@ public sealed class UpdateViewModelTests private static UpdateViewModel Create( IUpdateService updates, - AppSettings? settings = null, ILocalizationService? localization = null) => - new(updates, - localization ?? new FakeLocalizationService(), - settings ?? new AppSettings(), - new UpdateOptions()); + new(updates, localization ?? new FakeLocalizationService()); } diff --git a/CursorLang.Settings.Tests/Views/MainWindowTests.cs b/CursorLang.Settings.Tests/Views/MainWindowTests.cs index bfe6ba5..72eaf29 100644 --- a/CursorLang.Settings.Tests/Views/MainWindowTests.cs +++ b/CursorLang.Settings.Tests/Views/MainWindowTests.cs @@ -353,7 +353,7 @@ public sealed class MainWindowTests } private static UpdateViewModel CreateUpdates(IUpdateService updates) => - new(updates, new FakeLocalizationService(), new AppSettings(), new UpdateOptions()); + new(updates, new FakeLocalizationService()); private static IEnumerable