-
Notifications
You must be signed in to change notification settings - Fork 14
feat(desktop): switch Windows shell to native Win11 frame and add cross-platform About modal #231
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
e087425
refactor(desktop): remove dead setTitlebar IPC chain
Astro-Han 7d948e6
feat(desktop): switch Windows to native Win11 frame
Astro-Han 80f8c42
chore(desktop): remove unused WINDOWS_TITLEBAR_OVERLAY_HEIGHT
Astro-Han ade5063
fix(app): scope desktop shell inset chrome to Linux only
Astro-Han f3a433c
test(app): update shell-frame contract for linux-only selector
Astro-Han 50bdd3c
feat(app): drop Windows-specific titlebar placeholder and drag region
Astro-Han 6b63ec1
feat(desktop): add per-platform menu templates and About IPC
Astro-Han d3cae35
test(desktop): cover macOS and Windows menu templates
Astro-Han f78c943
feat(desktop): hide menu bar on Windows loading window
Astro-Han f28cce8
feat(desktop): expose About info and open subscription via preload
Astro-Han 37347ca
feat(app): add About modal for non-macOS platforms
Astro-Han 485d1c9
feat(app): mount About modal in shell
Astro-Han f75ef44
ci: inject PAWWORK_BUILD_SHA into release build
Astro-Han File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| import { onCleanup, onMount } from "solid-js" | ||
| import { useDialog } from "@opencode-ai/ui/context/dialog" | ||
| import { Dialog } from "@opencode-ai/ui/dialog" | ||
|
|
||
| import { useLanguage } from "@/context/language" | ||
|
|
||
| export type AboutInfo = { | ||
| version: string | ||
| electronVersion: string | ||
| chromeVersion: string | ||
| buildSha: string | ||
| } | ||
|
|
||
| function AboutDialogBody(props: { info: AboutInfo }) { | ||
| const language = useLanguage() | ||
| return ( | ||
| <Dialog title={language.t("about.title")} class="w-full max-w-[400px] mx-auto"> | ||
| <dl class="text-sm space-y-1 p-6 pt-0"> | ||
| <div> | ||
| <dt class="inline">{language.t("about.version")}: </dt> | ||
| <dd class="inline">{props.info.version}</dd> | ||
| </div> | ||
| <div> | ||
| <dt class="inline">{language.t("about.build")}: </dt> | ||
| <dd class="inline">{props.info.buildSha}</dd> | ||
| </div> | ||
| <div> | ||
| <dt class="inline">{language.t("about.electron")}: </dt> | ||
| <dd class="inline">{props.info.electronVersion}</dd> | ||
| </div> | ||
| <div> | ||
| <dt class="inline">{language.t("about.chromium")}: </dt> | ||
| <dd class="inline">{props.info.chromeVersion}</dd> | ||
| </div> | ||
| </dl> | ||
| </Dialog> | ||
| ) | ||
| } | ||
|
|
||
| export function AboutModal() { | ||
| const dialog = useDialog() | ||
| let unsubscribe: (() => void) | undefined | ||
|
|
||
| onMount(() => { | ||
| unsubscribe = window.api?.onAboutOpen?.(async () => { | ||
| let info: AboutInfo | undefined | ||
| try { | ||
| info = await window.api?.getAboutInfo?.() | ||
| } catch (error) { | ||
| console.warn("[about] failed to fetch info", error) | ||
| return | ||
| } | ||
| if (!info) return | ||
| const data = info | ||
| dialog.show(() => <AboutDialogBody info={data} />) | ||
| }) | ||
| }) | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
|
||
| onCleanup(() => unsubscribe?.()) | ||
|
|
||
| return null | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| import { app, BrowserWindow, ipcMain } from "electron" | ||
|
|
||
| export type AboutInfo = { | ||
| version: string | ||
| electronVersion: string | ||
| chromeVersion: string | ||
| buildSha: string | ||
| } | ||
|
|
||
| function readBuildSha(): string { | ||
| const sha = import.meta.env.PAWWORK_BUILD_SHA | ||
| return sha && sha.length > 0 ? sha : "unknown" | ||
| } | ||
|
|
||
| export function registerAboutIpc() { | ||
| ipcMain.handle("about:get-info", (): AboutInfo => ({ | ||
| version: app.getVersion(), | ||
| electronVersion: process.versions.electron ?? "unknown", | ||
| chromeVersion: process.versions.chrome ?? "unknown", | ||
| buildSha: readBuildSha(), | ||
| })) | ||
| } | ||
|
|
||
| function isAppShellWindow(win: BrowserWindow): boolean { | ||
| // Loading window loads `loading.html`; the About bridge is only mounted in the main app renderer. | ||
| return !win.webContents.getURL().endsWith("loading.html") | ||
| } | ||
|
|
||
| export function triggerAbout(browserWindow?: BrowserWindow) { | ||
| const candidate = browserWindow && isAppShellWindow(browserWindow) ? browserWindow : undefined | ||
| const target = candidate ?? BrowserWindow.getAllWindows().find(isAppShellWindow) | ||
| target?.webContents.send("about:open") | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| import { expect, test } from "bun:test" | ||
| import { buildMacosMenuTemplate, buildWindowsMenuTemplate, type MenuTemplateDeps } from "./menu-template" | ||
|
|
||
| const stubDeps: MenuTemplateDeps = { | ||
| trigger: () => {}, | ||
| checkForUpdates: () => {}, | ||
| reload: () => {}, | ||
| relaunch: () => {}, | ||
| reportProblem: () => {}, | ||
| openExternal: () => {}, | ||
| newWindow: () => {}, | ||
| triggerAbout: () => {}, | ||
| } | ||
|
|
||
| const baseOptions = { | ||
| deps: stubDeps, | ||
| appName: "PawWork", | ||
| locale: "en" as const, | ||
| feedbackEnabled: true, | ||
| } | ||
|
|
||
| test("Windows template has 6 top-level menus: File / Edit / View / Go / Window / Help", () => { | ||
| const tpl = buildWindowsMenuTemplate(baseOptions) | ||
| expect(tpl).toHaveLength(6) | ||
| const labels = tpl.map((m) => m.label) | ||
| expect(labels).toEqual(["File", "Edit", "View", "Go", "Window", "Help"]) | ||
| }) | ||
|
|
||
| test("Windows Help submenu contains 'Check for Updates' and 'About PawWork'", () => { | ||
| const tpl = buildWindowsMenuTemplate(baseOptions) | ||
| const help = tpl.find((m) => m.label === "Help") | ||
| expect(help).toBeDefined() | ||
| const labels = (help?.submenu ?? []).map((s) => s.label) | ||
| expect(labels).toContain("Check for Updates...") | ||
| expect(labels).toContain("About PawWork") | ||
| }) | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
|
||
| test("Windows New Session accelerator matches macOS (CmdOrCtrl+Shift+S)", () => { | ||
| const tpl = buildWindowsMenuTemplate(baseOptions) | ||
| const file = tpl.find((m) => m.label === "File") | ||
| const newSession = (file?.submenu ?? []).find((s) => s.label === "New Session") | ||
| expect(newSession?.accelerator).toBe("CmdOrCtrl+Shift+S") | ||
| }) | ||
|
|
||
| test("Windows accelerators use CmdOrCtrl + Alt (no bare Cmd or Option)", () => { | ||
| const tpl = buildWindowsMenuTemplate(baseOptions) | ||
| const collect = (items: ReturnType<typeof buildWindowsMenuTemplate>): string[] => | ||
| items.flatMap((i) => [i.accelerator ?? "", ...collect(i.submenu ?? [])]) | ||
| const accels = collect(tpl).filter(Boolean) | ||
| for (const a of accels) { | ||
| expect(a).not.toMatch(/(^|\+)Cmd(\+|$)/) | ||
| expect(a).not.toMatch(/(^|\+)Option(\+|$)/) | ||
| } | ||
| expect(accels.some((a) => a === "CmdOrCtrl+Shift+S")).toBe(true) | ||
| }) | ||
|
|
||
| test("macOS template still has 7 top-level menus including PawWork app menu", () => { | ||
| const tpl = buildMacosMenuTemplate(baseOptions) | ||
| expect(tpl).toHaveLength(7) | ||
| expect(tpl[0].label).toBe("PawWork") | ||
| }) | ||
|
|
||
| test("macOS About menu item still uses role:about (system About panel)", () => { | ||
| const tpl = buildMacosMenuTemplate(baseOptions) | ||
| const appMenu = tpl[0] | ||
| const aboutItem = (appMenu.submenu ?? []).find((s) => s.role === "about") | ||
| expect(aboutItem).toBeTruthy() | ||
| }) | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.