Skip to content

Handle runtime auto-update interval changes and UI-thread OCR toasts - #131

Merged
dimitar-radenkov merged 3 commits into
fix/auto-update-tray-notification-intervalfrom
copilot/fix-null-pointer-exception
Jun 28, 2026
Merged

dimitar-radenkov merged 3 commits into
fix/auto-update-tray-notification-intervalfrom
copilot/fix-null-pointer-exception

Conversation

Copilot AI commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Update notifications were only evaluated against the auto-update interval captured at service startup, so changing the interval to Never did not stop the periodic loop until the original timer elapsed. The PR also addresses the cross-thread OCR toast dismissal path that could crash the WPF test host.

  • Auto-update scheduling

    • Replace the single long PeriodicTimer wait with a settings-aware wait loop that re-reads AutoUpdateCheckInterval while waiting.
    • Stop the loop promptly when the interval becomes Never.
    • Recompute the next wait when the interval changes at runtime instead of waiting out the stale schedule.
  • Regression coverage

    • Replace the timing-dependent test with deterministic coverage that waits for the hosted service task to complete after switching the setting to Never.
    • Keep the assertion focused on the intended contract: one startup check, no further periodic checks.
  • WPF dispatcher safety

    • Marshal OCR toast display/dismissal back to the window dispatcher.
    • Guard toast updates during shutdown so delayed UI work does not touch dispatcher-owned controls after teardown.
while (!stoppingToken.IsCancellationRequested)
{
    var interval = _userSettings.Current.AutoUpdateCheckInterval;
    if (interval == UpdateCheckInterval.Never)
    {
        return false;
    }

    var remaining = GetTimerInterval(interval);
    while (remaining > TimeSpan.Zero)
    {
        var delay = TimeSpan.FromTicks(Math.Min(remaining.Ticks, _settingsPollInterval.Ticks));
        await Task.Delay(delay, stoppingToken);

        var currentInterval = _userSettings.Current.AutoUpdateCheckInterval;
        if (currentInterval == UpdateCheckInterval.Never) return false;
        if (currentInterval != interval) break;

        remaining -= delay;
    }

    if (remaining <= TimeSpan.Zero) return true;
}

@dimitar-radenkov
dimitar-radenkov marked this pull request as ready for review June 28, 2026 19:23
Copilot AI review requested due to automatic review settings June 28, 2026 19:23
@dimitar-radenkov
dimitar-radenkov merged commit 846b75c into fix/auto-update-tray-notification-interval Jun 28, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves runtime correctness and test reliability by making auto-update scheduling responsive to live settings changes, and by ensuring OCR toast UI updates are marshaled safely to the WPF UI thread (including during shutdown).

Changes:

  • Replace the long PeriodicTimer wait with a settings-aware wait loop that re-reads AutoUpdateCheckInterval and stops promptly when set to Never.
  • Update auto-update tests to deterministically verify the periodic loop terminates after switching the interval to Never.
  • Marshal OCR toast show/hide work to the window dispatcher and add shutdown guards to avoid cross-thread/access-after-teardown crashes.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
Pointframe/Views/OverlayWindow.xaml.cs Adds dispatcher marshalling and shutdown guards for OCR toast display/dismissal.
Pointframe/Services/Update/AutoUpdateService.cs Reworks periodic scheduling to react to runtime interval changes via a poll-based wait loop.
Pointframe.Tests/Services/AutoUpdateServiceTests.cs Replaces timing-dependent coverage with a deterministic “stop promptly after switching to Never” test.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

_messageBox = messageBox;
_logger = logger;
_telemetry = telemetry;
_settingsPollInterval = settingsPollInterval.GetValueOrDefault(DefaultSettingsPollInterval);
Comment on lines +493 to +497
if (!Dispatcher.CheckAccess())
{
await Dispatcher.InvokeAsync(() => ShowOcrToast(message));
return;
}
return;
}

await Dispatcher.InvokeAsync(() => OcrToast.Visibility = Visibility.Collapsed, DispatcherPriority.Normal);
@dimitar-radenkov
dimitar-radenkov deleted the copilot/fix-null-pointer-exception branch June 30, 2026 08:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants