Skip to content

fix(settings): prevent confirm dialog persisting after leaving settings#754

Merged
ErikBjare merged 1 commit intoActivityWatch:masterfrom
TimeToBuildBob:fix/categorization-navigation-guard
Feb 20, 2026
Merged

fix(settings): prevent confirm dialog persisting after leaving settings#754
ErikBjare merged 1 commit intoActivityWatch:masterfrom
TimeToBuildBob:fix/categorization-navigation-guard

Conversation

@TimeToBuildBob
Copy link
Copy Markdown
Contributor

@TimeToBuildBob TimeToBuildBob commented Feb 20, 2026

Summary

  • Move unsaved-changes navigation guard from global router.beforeEach to beforeRouteLeave on the parent Settings component

Problem

When modifying categories without saving and navigating away from the settings page, the "unsaved changes" confirmation dialog keeps appearing on every subsequent navigation, even when the user is no longer on the settings page.

Root Cause

CategorizationSettings.vue registered a global router.beforeEach guard that required manual cleanup in beforeDestroy. If the cleanup didn't execute in time during route transitions (race condition between next() completing and beforeDestroy firing), the guard persisted as a "zombie" — blocking all future navigations with the confirm dialog.

Fix

Replace the global router.beforeEach guard with beforeRouteLeave on the parent Settings.vue route component. beforeRouteLeave is:

  • Automatically managed by Vue Router (no manual cleanup needed)
  • Only fires when leaving the /settings route (not on every navigation)
  • Eliminated the zombie guard issue entirely

The window.beforeunload handler remains in CategorizationSettings.vue for browser tab/window close protection (separate concern).

Test plan

  • Go to Settings, modify a category (don't save)
  • Navigate to another page — confirm dialog should appear
  • Click "OK" to leave
  • Navigate to another page — no confirm dialog should appear
  • Repeat: go to Settings, modify, navigate away, click "Cancel" — should stay on settings

Fixes ActivityWatch/activitywatch#626


Important

Fixes persistent unsaved changes dialog by moving navigation guard to beforeRouteLeave in Settings.vue.

  • Behavior:
    • Moves unsaved-changes navigation guard from global router.beforeEach to beforeRouteLeave in Settings.vue.
    • Ensures confirmation dialog only appears when leaving /settings route.
    • Fixes issue of dialog persisting on every navigation after leaving settings.
  • Components:
    • Removes global router.beforeEach guard from CategorizationSettings.vue.
    • Adds beforeRouteLeave guard to Settings.vue to handle unsaved changes.
  • Misc:
    • Retains window.beforeunload handler in CategorizationSettings.vue for tab/window close protection.

This description was created by Ellipsis for b049dff. You can customize this summary. It will automatically update as commits are pushed.

Replace the global router.beforeEach guard in CategorizationSettings
with a beforeRouteLeave guard on the parent Settings component.

The global guard required manual cleanup in beforeDestroy, which could
fail to execute in time during route transitions, causing the unsaved
changes dialog to appear on every subsequent navigation even after
leaving the settings page.

beforeRouteLeave is automatically managed by Vue Router and only fires
when leaving the /settings route, eliminating the zombie guard issue.

The window.beforeunload handler remains in CategorizationSettings for
browser tab/window close protection.

Fixes ActivityWatch/activitywatch#626
Copy link
Copy Markdown
Contributor

@ellipsis-dev ellipsis-dev Bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed everything up to b049dff in 8 seconds. Click for details.
  • Reviewed 89 lines of code in 2 files
  • Skipped 0 files when reviewing.
  • Skipped posting 0 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.

Workflow ID: wflow_JMBcKALfoyXutpC0

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Feb 20, 2026

Greptile Summary

This PR fixes a critical bug where the unsaved changes confirmation dialog persisted on every navigation after leaving the settings page. The fix refactors the navigation guard from a global router.beforeEach (which required manual cleanup and was prone to race conditions) to beforeRouteLeave on the parent Settings.vue component.

Key Changes:

  • Removed global router.beforeEach guard from CategorizationSettings.vue
  • Removed routerGuardRemover data property and cleanup logic in beforeDestroy
  • Added beforeRouteLeave guard to Settings.vue that checks categoryStore.classes_unsaved_changes
  • Retained window.beforeunload handler for browser tab/window close protection

Benefits:

  • Automatically managed by Vue Router (no manual cleanup needed)
  • Only fires when leaving /settings route (not on every navigation)
  • Eliminates the "zombie guard" race condition entirely

The logic is sound and properly addresses the root cause described in ActivityWatch/activitywatch#626.

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk - it's a well-targeted bug fix with clear architectural improvement
  • The refactoring replaces a problematic pattern (manual guard cleanup) with Vue Router's built-in lifecycle management. The change is minimal, focused, and directly addresses the reported issue without introducing new complexity or side effects
  • No files require special attention

Important Files Changed

Filename Overview
src/views/settings/CategorizationSettings.vue Removed global router guard and cleanup logic, retaining only window.beforeunload handler for browser close protection
src/views/settings/Settings.vue Added beforeRouteLeave guard to handle unsaved category changes when navigating away from settings route

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[User navigates away from /settings] --> B{Is there unsaved category changes?}
    B -->|Yes| C[Show confirmation dialog]
    B -->|No| D[Allow navigation]
    C -->|User clicks OK| D
    C -->|User clicks Cancel| E[Stay on /settings]
    
    F[User closes/refreshes browser tab] --> G{Is there unsaved category changes?}
    G -->|Yes| H[Browser shows beforeunload warning]
    G -->|No| I[Allow close/refresh]
    
    style A fill:#e1f5ff
    style F fill:#e1f5ff
    style B fill:#fff4e1
    style G fill:#fff4e1
    style C fill:#ffe1e1
    style H fill:#ffe1e1
    style D fill:#e1ffe1
    style I fill:#e1ffe1
    style E fill:#ffe1e1
Loading

Last reviewed commit: b049dff

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

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

2 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

@codecov
Copy link
Copy Markdown

codecov Bot commented Feb 20, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 26.08%. Comparing base (64ed7a7) to head (b049dff).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master     #754   +/-   ##
=======================================
  Coverage   26.08%   26.08%           
=======================================
  Files          29       29           
  Lines        1698     1698           
  Branches      294      294           
=======================================
  Hits          443      443           
  Misses       1233     1233           
  Partials       22       22           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ErikBjare ErikBjare merged commit 5fe4025 into ActivityWatch:master Feb 20, 2026
8 checks passed
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.

More time reported than actual usage

2 participants