Skip to content

feat(v3): add desktop-only "Start in fullscreen" system option - #938

Merged
byrongamatos merged 2 commits into
got-feedBack:mainfrom
gionnibgud:feat/v3-start-fullscreen
Jul 13, 2026
Merged

byrongamatos merged 2 commits into
got-feedBack:mainfrom
gionnibgud:feat/v3-start-fullscreen

Conversation

@gionnibgud

@gionnibgud gionnibgud commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

What

Adds a Start in fullscreen toggle to Settings → System (between App updates and Library folder path).

Addresses the desktop request in got-feedBack/feedBack-desktop#97 — users want the app to launch fullscreen without pressing the OS hotkey (⌃⌘F) every time.

How it stays desktop-only

The block ships hidden and is gated exactly like the existing App-updates block. setupWindowOptions() (in static/js/settings.js, called from loadSettings()) only unhides + wires it when the feedBack-desktop bridge exposes:

window.feedBackDesktop.window.{ getStartFullscreen, setStartFullscreen }
  • Web / Docker builds have no feedBackDesktop bridge → the function returns early → the section never appears.
  • It's a per-method capability check, so even on desktop it stays hidden until the bridge actually ships those methods — no half-wired toggle.

Persistence lives desktop-side because only the Electron main process can read the pref at window-creation time; core just proxies through the bridge (getter normalised via Promise.resolve to allow sync or async IPC).

Scope

Core UI + bridge proxy only. The desktop bridge (feedBackDesktop.window) and the actual launch-in-fullscreen behaviour land in a follow-up feedBack-desktop PR. Until then this is inert in every shipping build.

Testing

  • Web/Docker: #window-options-block is present in the DOM but display:none (no bridge) — nothing new renders. Manually classList.remove('hidden') in devtools confirms the row layout.
  • No new Tailwind utilities (all classes pre-existing), so no tailwind.min.css rebuild.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added a desktop-only Window options section in Settings.
    • Added a Start in fullscreen option that reflects and saves the selected preference.
    • The option stays hidden when desktop window controls aren’t available.

Adds a "Start in fullscreen" toggle to the Settings → System panel,
addressing the desktop request in feedBack-desktop#97: users want the
app to launch fullscreen without hitting the OS hotkey every time.

The block ships hidden and is gated exactly like the App-updates block:
setupWindowOptions() only unhides + wires it when the feedBack-desktop
bridge exposes window.feedBackDesktop.window.{getStartFullscreen,
setStartFullscreen}. Web/Docker builds have no such bridge, so the
section never appears there. Persistence lives desktop-side because
only the Electron main process can read the pref at window-creation
time — core just proxies through the bridge.

The desktop bridge + launch behaviour land in a follow-up
feedBack-desktop PR.

Signed-off-by: gionnibgud <gionnibgud@gmail.com>
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c97045fc-7643-485e-a9b8-13601dfe4c07

📥 Commits

Reviewing files that changed from the base of the PR and between f8012a8 and 3050c7b.

📒 Files selected for processing (1)
  • static/v3/index.html
🚧 Files skipped from review as they are similar to previous changes (1)
  • static/v3/index.html

📝 Walkthrough

Walkthrough

Adds a desktop-only “Window options” settings block with a “Start in fullscreen” checkbox. Settings initialization hydrates the checkbox through the desktop bridge and persists changes with capability checks, error handling, and idempotent listener wiring.

Changes

Window options

Layer / File(s) Summary
Window options settings UI
static/v3/index.html
Adds a hidden System-panel block containing the setting-start-fullscreen checkbox.
Desktop option initialization and persistence
static/app.js, static/js/settings.js
Imports and invokes setupWindowOptions(), which reveals supported desktop controls, loads the fullscreen state, and persists checkbox changes through the desktop bridge.

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

Sequence Diagram(s)

sequenceDiagram
  participant App
  participant Settings
  participant DOM
  participant DesktopBridge
  App->>Settings: loadSettings()
  Settings->>Settings: setupWindowOptions()
  Settings->>DOM: Reveal supported window options
  Settings->>DesktopBridge: getStartFullscreen()
  DesktopBridge-->>Settings: Return fullscreen state
  Settings->>DOM: Set checkbox state
  DOM->>Settings: Notify checkbox change
  Settings->>DesktopBridge: setStartFullscreen()
Loading

Possibly related PRs

  • got-feedBack/feedBack#920: Refactors settings initialization in static/js/settings.js and updates its import usage in static/app.js.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: a desktop-only fullscreen system option in v3 settings.
Description check ✅ Passed The description covers the purpose, behavior, scope, and testing, but it omits the template's checklist items.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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 unit tests (beta)
  • Create PR with unit tests

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 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 `@static/js/settings.js`:
- Around line 198-200: Update the getStartFullscreen hydration flow around cb so
an asynchronous result cannot overwrite a user toggle: either disable the
checkbox until the promise settles, or track user interaction and skip applying
the resolved value after a change. Preserve the existing unchecked fallback on
getter errors and ensure the control is usable once hydration completes.
- Line 103: Update setupWindowOptions to protect the synchronous
winApi.getStartFullscreen() getter invocation before wrapping its result in a
promise, ensuring bridge exceptions are caught within the settings hydration
flow. Preserve the existing handling for successful values and apply the same
protection to the corresponding logic around lines 196-200.

In `@static/v3/index.html`:
- Around line 760-766: Give the checkbox with id setting-start-fullscreen an
accessible name by associating the visible “Start in fullscreen” title via a
matching label for attribute, or by adding an equivalent aria-label to the
input; keep the existing switch styling and behavior unchanged.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e07d455d-7653-4525-b8c1-462ec60ef122

📥 Commits

Reviewing files that changed from the base of the PR and between 99b974a and f8012a8.

📒 Files selected for processing (3)
  • static/app.js
  • static/js/settings.js
  • static/v3/index.html

Comment thread static/js/settings.js
// failed fetch below still leaves the desktop updater wired up.
// setupAppUpdates() is idempotent via _appUpdatesWired.
setupAppUpdates();
setupWindowOptions();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Protect settings hydration from a synchronous getter throw.

Promise.resolve(winApi.getStartFullscreen()) evaluates the getter before creating the promise. A synchronous bridge exception therefore escapes setupWindowOptions(). Since loadSettings() calls it at Line 103, the outer catch in static/app.js only logs the error and skips the remaining settings hydration.

Proposed fix
-    Promise.resolve(winApi.getStartFullscreen()).then(function (on) {
+    Promise.resolve().then(function () {
+        return winApi.getStartFullscreen();
+    }).then(function (on) {
         cb.checked = !!on;
     }).catch(function () { /* leave unchecked on error */ });

Also applies to: 196-200

🤖 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 `@static/js/settings.js` at line 103, Update setupWindowOptions to protect the
synchronous winApi.getStartFullscreen() getter invocation before wrapping its
result in a promise, ensuring bridge exceptions are caught within the settings
hydration flow. Preserve the existing handling for successful values and apply
the same protection to the corresponding logic around lines 196-200.

Comment thread static/js/settings.js
Comment on lines +198 to +200
Promise.resolve(winApi.getStartFullscreen()).then(function (on) {
cb.checked = !!on;
}).catch(function () { /* leave unchecked on error */ });

Copy link
Copy Markdown
Contributor

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

Prevent late hydration from overwriting a user toggle.

When the getter is asynchronous, the checkbox is enabled immediately. A user can change it before the getter resolves, after which cb.checked = !!on silently replaces the user’s choice. Disable the control until hydration completes or skip applying the result after a user change.

🤖 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 `@static/js/settings.js` around lines 198 - 200, Update the getStartFullscreen
hydration flow around cb so an asynchronous result cannot overwrite a user
toggle: either disable the checkbox until the promise settles, or track user
interaction and skip applying the resolved value after a change. Preserve the
existing unchecked fallback on getter errors and ensure the control is usable
once hydration completes.

Comment thread static/v3/index.html Outdated
Comment on lines +760 to +766
<div class="fb-srow-title">Start in fullscreen</div>
<div class="fb-srow-desc">Launch the desktop app in fullscreen every time.</div>
</div>
<div class="fb-srow-control">
<label class="fb-switch">
<input type="checkbox" id="setting-start-fullscreen">
<span class="fb-switch-track"></span>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Give the checkbox an accessible name.

The visible title is a sibling of the <label>, while the label contains only the switch track. Screen readers therefore may announce an unnamed checkbox. Associate the title with the input using for/id, or add aria-label="Start in fullscreen" (and optionally aria-describedby for the description).

🤖 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 `@static/v3/index.html` around lines 760 - 766, Give the checkbox with id
setting-start-fullscreen an accessible name by associating the visible “Start in
fullscreen” title via a matching label for attribute, or by adding an equivalent
aria-label to the input; keep the existing switch styling and behavior
unchanged.

Retitle the toggle "Fullscreen" (from "Start in fullscreen") and reword
the description to "Run fee[dB]ack in fullscreen mode. On macOS, changes
take effect on the next launch."

The macOS note is honest about a native-fullscreen limitation: AppKit
drops the first programmatic fullscreen-enter on a window created
windowed, so on macOS the desktop side applies the pref at next launch
rather than live. Windows/Linux apply it live on the first toggle. The
note is self-scoping text (no platform-detection code needed).

Signed-off-by: gionnibgud <gionnibgud@gmail.com>
@gionnibgud

Copy link
Copy Markdown
Contributor Author

Companion desktop PR: got-feedBack/feedBack-desktop#105 — adds the feedBackDesktop.window bridge, persists the pref, and applies fullscreen: true at window creation. This core PR is the UI/settings half; #105 is the Electron half. Both are needed for the feature to function end-to-end.

@gionnibgud

Copy link
Copy Markdown
Contributor Author

Thanks @coderabbitai — evaluated all three; skipping each, with rationale:

1. Sync getter throw (Promise.resolve(winApi.getStartFullscreen()), settings.js) — skip. This mirrors the existing update-bridge hydration in the same file (Promise.resolve(updateApi.getStatus()).then(...)). getStartFullscreen is an ipcRenderer.invoke call, which returns a Promise and doesn't throw synchronously, and the capability check already guarantees it's a function. Changing only this row would make it inconsistent with the sibling bridge code for a case that can't occur here.

2. Late hydration overwriting a user toggle — skip. The race window is a single IPC round-trip on Settings entry, and the toggle is its own sole writer — the change handler already persists and live-applies the user's choice via setStartFullscreen, so a stale read would at most briefly mis-show the checkbox and self-heals on next entry. Same hydrate-on-entry pattern as the update block; not worth the added interaction-tracking state.

3. Checkbox accessible name — valid, but out of scope here. The finding is correct, but it's a page-wide pattern: every sibling toggle in Settings (setting-lefty, setting-confirm-exit, setting-show-upnext, …) uses the identical fb-switch structure with the title as a sibling of the <label>, so they all share this gap. Fixing only this one row would be inconsistent, and reworking the switch/label a11y pattern across the whole settings page (or app) is a design decision for a dedicated pass, not this feature PR. Flagging it for the maintainers to tackle page-wide.

Net: this PR stays consistent with the established settings patterns; no changes from this review.

@byrongamatos
byrongamatos merged commit 8b6829a into got-feedBack:main Jul 13, 2026
6 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.

2 participants