Skip to content

fix(config): migrate favorites sidebar shortcut#334

Open
bnema wants to merge 1 commit into
mainfrom
fix/favorites-shortcuts-noop
Open

fix(config): migrate favorites sidebar shortcut#334
bnema wants to merge 1 commit into
mainfrom
fix/favorites-shortcuts-noop

Conversation

@bnema

@bnema bnema commented Jun 28, 2026

Copy link
Copy Markdown
Owner

Summary

  • detect the obsolete shipped toggle-favorites-systemview shortcut default with empty keys and migrate it to ctrl+b
  • add the missing toggle-current-page-favorite default shortcut as ctrl+d during migration/load
  • keep existing custom shortcut bindings intact and preserve normal shortcut propagation
  • keep the Ctrl+D favorite toggle success toast

Review

  • wrap-up review pass completed; fixed the minor helper-duplication finding
  • CodeRabbit pass completed; applied the valid migration/test-strengthening findings

Verification

  • go test ./internal/infrastructure/config -run 'TestManagerLoad_UpgradesObsoleteFavoritesShortcutDefaultInMemory|TestMigrator_ReportsAndMigratesObsoleteFavoritesShortcutDefault' -count=1 -v\n- go test ./internal/infrastructure/config ./internal/ui -count=1\n- make lint\n- make test\n- make check\n- git diff --check

Summary by CodeRabbit

  • New Features

    • Favorites-related shortcuts are now automatically updated to the current default bindings when older config values are detected.
  • Bug Fixes

    • Improved migration handling so existing favorite shortcut settings are corrected more reliably.
    • Favorite actions can now display a success message after toggling, when one is provided.

@coderabbitai

coderabbitai Bot commented Jun 28, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Extends the config migrator to detect and upgrade obsolete favorites shortcut bindings (empty keys, specific desc) to current defaults, using value-aware config parsing and new coercion helpers. Adds integration and in-memory loader tests. Also adds a conditional success toast in toggleCurrentPageFavoriteAction when the toggle returns a non-empty message.

Changes

Obsolete favorites shortcut migration and toggle toast

Layer / File(s) Summary
Obsolete action detection and merge logic
internal/infrastructure/config/migrate.go
CheckMigration switches to value-aware user-config parsing; detectMissingDefaultActions treats obsolete bindings as missing; mergeMissingDefaultActions overwrites obsolete entries with defaults; new helpers (isObsoleteDefaultAction, actionBindingFromAny, actionBindingFromMap, stringSliceFromAny) detect and coerce obsolete ActionBinding values.
Migration and loader tests
internal/infrastructure/config/migrate_test.go, internal/infrastructure/config/loader_actions_test.go
Integration test covers full migration cycle for obsolete favorites shortcut (check, detect, migrate, raw config, in-memory verify); in-memory loader test asserts loader upgrades keys/desc to defaults at load time.
Success toast on toggle action
internal/ui/browser_window_favorites_sidebar.go
toggleCurrentPageFavoriteAction captures FavoritesUC.Toggle result and displays a success toast when result.Message is non-empty.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

A rabbit hopped in, found old shortcuts astray,
With empty keys and a desc gone gray.
It migrated them swiftly, set defaults anew,
And toasted success when toggling too!
🐇✨ All favorites sidebar, good as new!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: migrating favorites-related config shortcuts.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/favorites-shortcuts-noop

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/infrastructure/config/migrate.go`:
- Around line 918-926: The sentinel in Migrator.isObsoleteDefaultAction should
not rely on an explicit empty Keys slice, because that is also a valid
user-unbound shortcut state. Update the logic so only the legacy shipped default
for "workspace.shortcuts.actions" / "toggle-favorites-systemview" is treated as
obsolete, using a more specific check than len(binding.Keys) == 0 and the legacy
Desc text; keep user-customized empty bindings from being rewritten during
Load() and Migrate().

In `@internal/ui/browser_window_favorites_sidebar.go`:
- Around line 130-138: The success toast in the Favorites sidebar is being
routed through showToastOnLastFocusedBrowserWindow, which can attach it to a
different window if focus changes during FavoritesUC.Toggle. Update the Toggle
success path in the browser window favorites sidebar flow to use the current
webview/browser window associated with the toggled page (for example via the
existing wv/browser-window context) instead of re-resolving the last focused
window, so the toast is shown on the same window that initiated the favorite
change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 70db8232-792b-430b-afba-17649a50be3b

📥 Commits

Reviewing files that changed from the base of the PR and between abd344b and 3721706.

📒 Files selected for processing (4)
  • internal/infrastructure/config/loader_actions_test.go
  • internal/infrastructure/config/migrate.go
  • internal/infrastructure/config/migrate_test.go
  • internal/ui/browser_window_favorites_sidebar.go

Comment on lines +918 to +926
func (m *Migrator) isObsoleteDefaultAction(actionMapKey, actionName string, actionValue any) bool {
if actionMapKey != "workspace.shortcuts.actions" || actionName != "toggle-favorites-systemview" {
return false
}
binding, ok := m.actionBindingFromAny(actionValue)
if !ok {
return false
}
return len(binding.Keys) == 0 && strings.TrimSpace(binding.Desc) == "Toggle Favorites in right split"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Don't use an explicit empty binding as the obsolete-default sentinel.

keys = [] is already a valid persisted shortcut state, so this heuristic cannot distinguish the old shipped default from a user intentionally unbinding ctrl+b. Any config that disables the shortcut but keeps the legacy description will now be rewritten back to ctrl+b during both Load() and Migrate(), which breaks the “preserve existing custom shortcut bindings” goal.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/infrastructure/config/migrate.go` around lines 918 - 926, The
sentinel in Migrator.isObsoleteDefaultAction should not rely on an explicit
empty Keys slice, because that is also a valid user-unbound shortcut state.
Update the logic so only the legacy shipped default for
"workspace.shortcuts.actions" / "toggle-favorites-systemview" is treated as
obsolete, using a more specific check than len(binding.Keys) == 0 and the legacy
Desc text; keep user-customized empty bindings from being rewritten during
Load() and Migrate().

Comment on lines +130 to +138
result, err := a.deps.FavoritesUC.Toggle(ctx, uri, wv.Title())
if err != nil {
return err
}
if result != nil && strings.TrimSpace(result.Message) != "" {
a.showToastOnLastFocusedBrowserWindow(ctx, result.Message, component.ToastSuccess,
component.WithDuration(component.ToastBriefDurationMs),
component.WithPosition(component.ToastPositionBottomRight),
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Bind the toast to the same browser window as the toggled page.

This success path re-resolves the focused window via showToastOnLastFocusedBrowserWindow(). If focus changes while FavoritesUC.Toggle runs, the toast can land in a different window than the webview whose favorite state was toggled.

Suggested fix
 func (a *App) toggleCurrentPageFavoriteAction(ctx context.Context) error {
 	if a == nil || a.deps == nil || a.deps.FavoritesUC == nil {
 		return fmt.Errorf("favorites unavailable: usecase not configured")
 	}
-	_, wv := a.activeWebViewForBrowserWindow(a.lastFocusedBrowserWindow())
+	bw := a.lastFocusedBrowserWindow()
+	_, wv := a.activeWebViewForBrowserWindow(bw)
 	if wv == nil {
 		return fmt.Errorf("favorites unavailable: no active webview")
 	}
 	uri := strings.TrimSpace(wv.URI())
 	if uri == "" {
@@
 	}
 	if result != nil && strings.TrimSpace(result.Message) != "" {
-		a.showToastOnLastFocusedBrowserWindow(ctx, result.Message, component.ToastSuccess,
+		a.showToastOnBrowserWindow(ctx, bw, result.Message, component.ToastSuccess,
 			component.WithDuration(component.ToastBriefDurationMs),
 			component.WithPosition(component.ToastPositionBottomRight),
 		)
 	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
result, err := a.deps.FavoritesUC.Toggle(ctx, uri, wv.Title())
if err != nil {
return err
}
if result != nil && strings.TrimSpace(result.Message) != "" {
a.showToastOnLastFocusedBrowserWindow(ctx, result.Message, component.ToastSuccess,
component.WithDuration(component.ToastBriefDurationMs),
component.WithPosition(component.ToastPositionBottomRight),
)
bw := a.lastFocusedBrowserWindow()
_, wv := a.activeWebViewForBrowserWindow(bw)
if wv == nil {
return fmt.Errorf("favorites unavailable: no active webview")
}
uri := strings.TrimSpace(wv.URI())
if uri == "" {
return fmt.Errorf("favorites unavailable: current page has no URI")
}
result, err := a.deps.FavoritesUC.Toggle(ctx, uri, wv.Title())
if err != nil {
return err
}
if result != nil && strings.TrimSpace(result.Message) != "" {
a.showToastOnBrowserWindow(ctx, bw, result.Message, component.ToastSuccess,
component.WithDuration(component.ToastBriefDurationMs),
component.WithPosition(component.ToastPositionBottomRight),
)
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/ui/browser_window_favorites_sidebar.go` around lines 130 - 138, The
success toast in the Favorites sidebar is being routed through
showToastOnLastFocusedBrowserWindow, which can attach it to a different window
if focus changes during FavoritesUC.Toggle. Update the Toggle success path in
the browser window favorites sidebar flow to use the current webview/browser
window associated with the toggled page (for example via the existing
wv/browser-window context) instead of re-resolving the last focused window, so
the toast is shown on the same window that initiated the favorite change.

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.

1 participant