Skip to content

feat: open the extension in a 400x600 popup with an open-full-page action - #23

Merged
ttncode merged 3 commits into
mainfrom
feat/extension-popup
Oct 12, 2026
Merged

ttncode merged 3 commits into
mainfrom
feat/extension-popup

Conversation

@ttncode

@ttncode ttncode commented Oct 12, 2026

Copy link
Copy Markdown
Owner

Summary

The extension's toolbar button now opens the app in a popup, with a way to open the full page.

Popup size: 400 × 600

Chrome caps extension popups at 800 × 600 and the app switches to its phone layout below 820 px, so any popup uses the phone layout. 400 wide matches the ~390 px phone width the layout was designed at (the bottom nav gets 376 px); 600 is the tallest Chrome allows. At that size the stock phone layout was 774 px tall with Start Focus hidden behind the bottom nav, so the popup gets a compact variant (popup: Tailwind variant, data-view="popup" on popup.html):

  • timer artwork 160 px instead of 256, top padding 3rem instead of 4rem, desktop nav clearance → the idle and running timer both fit in exactly 600 px with no scrollbar;
  • the floating menu button (which covered Pause while running) moves into the top bar and opens downward.

Open full page

⤢ button in the popup's top bar and a new Alt+Enter shortcut ("Open full page (extension popup)", rebindable) ask the background worker to focus the existing app tab or open one, then close the popup.

The timer survives the popup closing

A popup is destroyed whenever it loses focus. Previously a reopened app restored a running session as paused, and its end notification never fired.

  • While a focus session or break runs, the app records { kind, sessionId, endAt, totalMs, goal } (extension only) and the background worker sets a chrome.alarms alarm for endAt.
  • Reopening continues the countdown; if endAt has passed it marks the session complete at its real end time and shows the completion state.
  • The background worker raises the "Focus session complete" / "Break is over" notification when the alarm fires (fresh id each time) and opens the app on click. Pages in the extension no longer notify themselves, so there are no duplicates.
  • Pause, Done, End and Reset clear the record and cancel the alarm. Manifest gains the alarms permission and default_popup: popup.html.
  • The web app is unchanged.

Testing

  • Lint, typecheck, unit tests and build pass.
  • Built extension served under the MV3 policy (script-src 'self') at 400 × 600 with a stubbed chrome.runtime:
    • idle: artwork 160 px, Start Focus 414–462 px and Switch to Break above the nav (514 px); no scrollbar;
    • running: page exactly 600 px, Pause/Done/Reset clear of the menu (now top-right);
    • Start → schedule-end at +120 s; Pause → cancel-end; Resume → schedule-end at +119 s;
    • reload while running (= reopening the popup) continues at 00:57 instead of pausing;
    • reload after endAt → "Session complete!", session saved as completed at endAt, record cleared;
    • ⤢ and Alt+Enter → open-app and the popup closes.
  • Not run: a real Chrome with the unpacked extension (this machine's Chrome ignores command-line extension loading), so the background alarm and notification were reviewed, not executed.

…tion

## Summary
The extension's toolbar button now opens the app in a popup, with a way to open the full page.

### Popup size: 400 × 600
Chrome caps extension popups at 800 × 600 and the app switches to its phone layout below 820 px, so any popup uses the phone layout. 400 wide matches the ~390 px phone width the layout was designed at (the bottom nav gets 376 px); 600 is the tallest Chrome allows. At that size the stock phone layout was 774 px tall with **Start Focus hidden behind the bottom nav**, so the popup gets a compact variant (`popup:` Tailwind variant, `data-view="popup"` on popup.html):
- timer artwork 160 px instead of 256, top padding 3rem instead of 4rem, desktop nav clearance → the idle and running timer both fit in exactly 600 px with no scrollbar;
- the floating menu button (which covered Pause while running) moves into the top bar and opens downward.

### Open full page
⤢ button in the popup's top bar and a new **Alt+Enter** shortcut ("Open full page (extension popup)", rebindable) ask the background worker to focus the existing app tab or open one, then close the popup.

### The timer survives the popup closing
A popup is destroyed whenever it loses focus. Previously a reopened app restored a running session as **paused**, and its end notification never fired.
- While a focus session or break runs, the app records `{ kind, sessionId, endAt, totalMs, goal }` (extension only) and the background worker sets a `chrome.alarms` alarm for `endAt`.
- Reopening continues the countdown; if `endAt` has passed it marks the session complete at its real end time and shows the completion state.
- The background worker raises the "Focus session complete" / "Break is over" notification when the alarm fires (fresh id each time) and opens the app on click. Pages in the extension no longer notify themselves, so there are no duplicates.
- Pause, Done, End and Reset clear the record and cancel the alarm. Manifest gains the `alarms` permission and `default_popup: popup.html`.
- The web app is unchanged.

## Testing
- Lint, typecheck, unit tests and build pass.
- Built extension served under the MV3 policy (`script-src 'self'`) at 400 × 600 with a stubbed `chrome.runtime`:
  - idle: artwork 160 px, Start Focus 414–462 px and Switch to Break above the nav (514 px); no scrollbar;
  - running: page exactly 600 px, Pause/Done/Reset clear of the menu (now top-right);
  - Start → `schedule-end` at +120 s; Pause → `cancel-end`; Resume → `schedule-end` at +119 s;
  - reload while running (= reopening the popup) continues at 00:57 instead of pausing;
  - reload after `endAt` → "Session complete!", session saved as completed at `endAt`, record cleared;
  - ⤢ and Alt+Enter → `open-app` and the popup closes.
- Not run: a real Chrome with the unpacked extension (this machine's Chrome ignores command-line extension loading), so the background alarm and notification were reviewed, not executed.
Larger, brighter ⤢ button with a hover state, and an 'Open full page' entry (with its shortcut) at the top of the popup's menu. The popup now closes only after the background worker has received the request, so the tab always opens.
Remove the top-bar button so the popup's main screen stays clean. 'Open full page' lives at the top of the popup menu with lucide's Expand (four outward arrows) icon and its Alt+Enter shortcut, which is now registered by the menu.
@ttncode
ttncode merged commit cac87fc into main Oct 12, 2026
2 checks passed
@ttncode
ttncode deleted the feat/extension-popup branch October 12, 2026 03:40
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