Skip to content

refactor(app): call each alerts hook where its block stood - #1769

Merged
devswha merged 1 commit into
mainfrom
refactor/app-alerts-hook-positions
Oct 23, 2026
Merged

devswha merged 1 commit into
mainfrom
refactor/app-alerts-hook-positions

Conversation

@devswha

@devswha devswha commented Oct 23, 2026

Copy link
Copy Markdown
Owner

A follow-up to PR #1768, wave 5 of the App.tsx split. The plan is .omo/plans/app-stores-split.md in the maintainer's workspace.

The plan's rule R1 says every contiguous block moved out of src/App.tsx becomes its own hook call, placed at that block's original line, so effect and listener order stay exactly as they were. PR #1768 broke that rule:

  • What it did: it gathered six separate blocks into one useAlerts call at the notifications line.
  • What changed as a result: three effects ran earlier in a commit than before:
    • the alert-sound player effect;
    • the sound-unlock effect;
    • the push re-registration effect, which also moved ahead of the event-stream effect.
  • Harm found: none. PR refactor(app): move the alerts and notification state into a hook #1768's body and the merge pass's review found no behaviour change from this.

This PR restores the exact order anyway, so no such argument is needed.

What changes

src/lib/useAlerts.ts now exports one hook per block. Each is called in App.tsx at its block's original line (the line numbers are from before PR #1768):

Block Hook Called where the block stood
alert prefs (alerts, alertsRef, alertsOn, alertsOnRef) useAlertPrefs({ settings }) right after useSettings()
notifications, pushOn, pushOnRef useNotificationState() after the connection chip
status and turn refs, in-app and sound switches useAlertRefs({ settings }) after lockedRef, before followFocusRef
dropIn, the sound player effect, chime, the sound-unlock effect, plus the three event-stream callbacks useAlertSignals({ … }) before the event-stream effect
enableNotifications, disableNotifications, the push re-registration effect useNotificationSwitch({ … }) after the event-stream effect and handleServerMessage
the bell, bellVisible, alertsOffDot (no hooks) plain alertsBell({ … }) where the bell was computed
  • Moved lines: none changes. Each hook's body is its block's lines from PR refactor(app): move the alerts and notification state into a hook #1768.
  • Effects and callbacks: every effect is back at its original line. The three event-stream callbacks (onRoster, onPaneStatus, onPaneExited) are useCallback([]) hooks without effects, so where they sit inside useAlertSignals changes no order.
  • Hook ceiling: unchanged at 144, because the same hook calls left App.

Checks

  • --color-moved: git diff --color-moved=plain --color-moved-ws=allow-indentation-change origin/main...HEAD shows only:

    • the single call replaced by six calls;
    • the import line;
    • useAlerts split into hook signatures, params interfaces, doc comments and returns.

    The block bodies show as moved, or as unchanged in place.

  • Moved blocks are exact: all six blocks match App.tsx before PR refactor(app): move the alerts and notification state into a hook #1768 (53b85127e) byte for byte, at lines 225-232, 496-500, 509-518, 604-647, 744-787 and 1317-1343.

  • Positions: the line before each new call is the line that came before its block on 53b85127e.

  • Typecheck: bun run typecheck passes.

  • Unit tests: 129 pass, 0 fail across 9 files, from:

    HERDR_TEST_MODE=unit bun test src/app-hooks.test.ts src/conventions.test.ts src/lib/notifications.test.ts src/lib/droplet.test.ts src/lib/alertTurns.test.ts src/lib/alertSound.test.ts src/lib/push.test.ts src/lib/notificationTarget.test.ts src/lib/i18n.test.ts

  • bun run check fast: passes (unit 6253 pass, 0 fail, 13 skip in 443 files, 8 at a time, 68.4s)

  • Alert browser scripts: each run with bun run check run --build bun scripts/<name>.ts: alert-sound-regression, droplet-regression, droplet-demo-regression, notification-startup-regression, notification-view-regression and push-settings-regression each exit 0.

No changelog fragment: users see no change.

PR #1768 moved six separate blocks of App.tsx into one useAlerts call at the
notifications line, which ran three effects earlier in a commit than before.
useAlerts.ts now exports one hook per block (useAlertPrefs, useNotificationState,
useAlertRefs, useAlertSignals, useNotificationSwitch) and a plain alertsBell, each
called at its block's original line, so effect and listener order match the code
before #1768. No moved line changes. Plan .omo/plans/app-stores-split.md rule R1.
@coderabbitai

coderabbitai Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
📥 Commits

Reviewing files that changed from the base of the PR and between d64e9ed and 8758731.

📒 Files selected for processing: 2
  • src/App.tsx
  • src/lib/useAlerts.ts

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 2 remain after this review.

📝 Summary

Summary by CodeRabbit

  • Refactor
    • Alert preferences, notification status, alert activity, notification controls, and bell presentation are now handled separately. Existing notification enablement, disablement, and bell status behavior are preserved.
    • No changes to user-facing features or behavior are indicated in this update.

The combined useAlerts hook is replaced by separate hooks for alert preferences, notification state, alert references, alert signals, notification controls, and bell presentation. App wires these helpers into alert handling and header rendering.

Changes: Alert hook refactor

Layer / File(s) Summary
Alert state and references
src/lib/useAlerts.ts, src/App.tsx
Alert preferences, notification state, and pane-level refs are exposed through separate hooks. App uses these helpers.
Alert signal handling
src/lib/useAlerts.ts, src/App.tsx
useAlertSignals receives alert preferences and refs, and returns event and pane handlers. App wires the helper to alert state and layout refs.
Notification controls and bell
src/lib/useAlerts.ts, src/App.tsx
Notification enable and disable actions are separated from bell presentation state. App uses the actions and derives bell state through alertsBell.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~12 minutes

Change: Refactor

Suggested reviewers: kratam

Merge Risk: ⚪ Minimal · up to 87587

No actionable alert behavior regression remains identified; the change is ready for normal merge checks.

Pre-merge checks: Passed 5
Check name Status Explanation
Title check Passed The title clearly describes the main change: splitting the alerts hook and calling each hook where its block originally stood.
Description check Passed The description explains the change and resulting behavior, then lists validation commands and results. It covers the template’s required Change and Validation information.
Docstring Coverage Passed Docstring coverage is 85.71% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 2 files.
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
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@devswha

devswha commented Oct 23, 2026

Copy link
Copy Markdown
Owner Author

Native Windows install failed in scripts/windows-plugin.test.ts, in the test "starts after its launcher exits, stops its owned tree and restarts on Windows": could not confirm Ovis stopped; its pid file was kept.

That test covers the Windows plugin launcher's process lifecycle on a GitHub-hosted Windows runner. This PR changes only src/App.tsx and src/lib/useAlerts.ts, which are browser client code that this job does not run. Main's CI, including this job, passed on d64e9ed7f, the base of this PR's merge commit.

I'm rerunning only the failed job once the run finishes.

@devswha

devswha commented Oct 23, 2026

Copy link
Copy Markdown
Owner Author

Merge pass: follow-up to #1768. A gate reviewer on a different model than the author's approved it.

  • Order restored. The reviewer substituted each hook's body, and alertsBell's, back into App and compared with App.tsx at 5e44913 (before refactor(app): move the alerts and notification state into a hook #1768). The component body matches.
    • All 34 effects are back at their original positions.
    • The only addition is the three [] event-stream callbacks inside useAlertSignals. They have no effects.
  • No other changes found.
    • alertsBell calls no hooks.
    • No hook argument is used before it is declared (no TDZ).
    • Counted on the TypeScript AST, App still has 144 hook calls.
  • Tests at this head. 76 unit tests pass (app-hooks, conventions, droplet, notifications, alertTurns, alertSound), and the typecheck passes.

Native Windows install first failed on the known flaky stop/restart test (windows-plugin.test.ts:180, "could not confirm Ovis stopped"), which this PR doesn't touch. It passed on the re-run.

All required checks are green and no review thread is open.

@devswha
devswha merged commit 41189ee into main Oct 23, 2026
16 of 17 checks passed
@devswha
devswha deleted the refactor/app-alerts-hook-positions branch October 23, 2026 16:15
devswha added a commit that referenced this pull request Oct 23, 2026
…ks (#1770)

Wave 6 of the App.tsx split. The plan is
`.omo/plans/app-stores-split.md` in the maintainer's workspace, and
plan-reviewer approved it. It follows PR #1768 and PR #1769.

This wave moves the state behind the dialogs, the file panels, the
command palette and the pane-coverage check out of `src/App.tsx`. That
is seven blocks, into five new files.

Following the plan's rule R1:
- Each contiguous block becomes one hook, called at that block's own
line.
- The new-session area has three separate blocks, so its file exports
three hooks.

Effect and listener registration order stay identical. That includes the
`popstate` listeners that `useFileViewer` and `useRepoDiffViewer`
register, and the coverage MutationObserver.

## What moves

| File | Hook | Block (App.tsx on `41189ee36`) | Contents |
|---|---|---|---|
| `src/lib/useMachineDialog.ts` | `useMachineDialog()` | 246-255 |
`machineDialog`, `addPcFocusReturn`, `closeMachineDialog` |
| `src/lib/useNewSessionDialog.ts` | `useNewSessionMachine()` | 256 |
`newSessionMachineId` |
| `src/lib/useCommandPalette.ts` | `useCommandPalette()` | 395-397 |
`paletteOpen`, `paletteQuery`, `openPalette` |
| `src/lib/useFilePanels.ts` | `useFilePanels({ settings,
filePanelAvailable, selectedPaneId, selectedMachineId })` | 405-463 |
`filesOpen`; the `useFileViewer`, `useRepoDiffViewer` and
`useFocusReturn` calls; `presentation`, `fileDocked` and both
docked-close effects; `webPage` and `openWebPage`; `collapsing` and its
effect; `presentFile`, `reportFileKind`, `toggleFilePresentation`,
`viewFile` |
| `src/lib/useNewSessionDialog.ts` | `useNewSessionState({ initialLink
})` | 465-475 | `newSessionOpen`, `newPrefill`, `newFields`,
`pendingCreate`, `newTab`, `sessionHistory` |
| `src/lib/usePaneCoverage.ts` | `usePaneCoverage({ contentKey })` |
866-879 | `dialogCover`, `contentReady`, the MutationObserver effect |
| `src/lib/useNewSessionDialog.ts` | `useSessionHistoryList({ … })` |
1352-1367 | `closeNewSession`, `closeSessionHistory`,
`useRecentResumes`, the away-PC probe effect, `sessionHistoryWorkspace`
and its effect |

- **What stays in App, as the plan says:**
  - the `pendingCreate` effect, whose deps include `actions`;
  - `contentKey`;
  - `paneInFront`;
  - every call site.
- **Dependency lists and returned refs:** every `useCallback`/`useMemo`
dependency list is unchanged. `openWebPage` and `viewFile` are context
values, and keep their exact deps. Refs (`addPcFocusReturn`,
`pendingCreate`, `collapsing`) are returned as the same objects.
- **Imports:** App drops the imports only the moved code used.
- **Hook ceiling:** `APP_HOOK_CEILING` drops from 144 to 113, after
moving 31 builtin hook calls.

## Checks

- **`--color-moved`:** `git diff --color-moved=plain
--color-moved-ws=allow-indentation-change origin/main...HEAD` shows 228
lines as moved. The other 99 lines are:
  - App's narrowed imports, the five new imports and the seven calls;
  - the ceiling;
  - the new files' imports, params types, signatures and returns.
- **Moved blocks are exact:** all seven blocks appear byte for byte in
their hooks.
- **Positions:** the line before and after each call is the line that
surrounded its block on `41189ee36`.
- **Typecheck:** `bun run typecheck` passes.
- **Unit tests:** `HERDR_TEST_MODE=unit bun test src/app-hooks.test.ts
src/conventions.test.ts src/lib/i18n.test.ts
src/lib/filePresentation.test.ts src/lib/webPanel.test.ts
src/lib/paletteSeed.test.ts`: 42 pass, 0 fail.
- **Ceiling test:** adding `const zz = useState(false);` to App.tsx
makes `src/app-hooks.test.ts` fail.
- `bun run check fast`: passes (unit 6253 pass, 0 fail, 13 skip in 443
files, 8 at a time, 57.9s)
- **`bun run check integration browser`:** the browser lane exits 0
(every browser script passed, 1815 s), including the file viewer, repo
diff, files prompt, palette, machine dialog, session history,
new-session, recent folders, deep link and sidebar activity scripts. The
integration lane's only failure is `server/api.contract.test.ts`
"creates, edits, searches, inspects, and closes an owned workspace"
(line 1540), which fails the same way on unchanged `origin/main` on this
PC; CI runs that lane in its own environment.

## Outside PRs that touch the same files

No other maintainer PR touches these files. One outside contributor's PR
touches `src/App.tsx`: #1427. It already conflicts with main, and needs
a rebase either way.

Move-only: moved blocks plus imports, hook signatures and returns, seven
calls and the lowered ceiling. No changelog fragment: users see no
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