Skip to content

feat(midscene-studio): scaffold native shell app#2329

Draft
quanru wants to merge 9 commits intomainfrom
feat/electron-playground-shell
Draft

feat(midscene-studio): scaffold native shell app#2329
quanru wants to merge 9 commits intomainfrom
feat/electron-playground-shell

Conversation

@quanru
Copy link
Copy Markdown
Collaborator

@quanru quanru commented Apr 10, 2026

Summary

  • Scaffold a new Electron + Rsbuild desktop shell under apps/midscene-studio
    with three rsbuild environments (renderer, main, preload), a typed IPC
    bridge, and a light-themed two-pane layout.
  • Vendor shell assets locally (apps/midscene-studio/assets) and sync them
    into dist/assets via scripts/sync-static-assets.mjs, so the runtime no
    longer depends on remote design-export URLs.
  • Apply review feedback: tighten wait-for-electron-build freshness check,
    drop the process.cwd() fallback in getAppIconPath, cache the nativeImage,
    deduplicate midscene-icon.png, and add JSDoc to the ElectronShellApi
    contract.

This is phase 1 of Midscene Studio — pure shell scaffolding, no device or
agent runtime yet. Phase 2 will plug in real device discovery and agent
hosting from the main process without reorganizing the layering.

Test plan

  • `pnpm --filter midscene-studio build`
  • `pnpm run lint`
  • Manual smoke: `pnpm --filter midscene-studio dev` on macOS, verify the
    window opens, title bar controls (minimize / maximize / close) work, and
    the Playground / Sidebar / MainContent render with local assets

quanru added 2 commits April 10, 2026 14:19
…s review feedback

Rename the shell app apps/electron-playground -> apps/midscene-studio
(package name, HTML title, dev env var, docs/plan path) and apply the
review follow-ups:

- wait-for-electron-build: drop the freshnessWindowMs bypass so only
  strictly newer mtimes count as a fresh build
- main: remove the process.cwd() fallback in getAppIconPath and cache
  the nativeImage
- renderer: point the Playground component at the single app-level
  midscene-icon.png and delete the duplicate renderer copy
- electron-contract: add JSDoc to ElectronShellApi and IPC_CHANNELS
- sync-static-assets: rm the target dir before cp so stale files
  are not left behind

Validated with pnpm --filter midscene-studio build and pnpm run lint.
Rename the shell app apps/midscene-studio -> apps/studio (package name,
docs/plan filename and contents) and flatten the renderer component tree
by removing the incut-area-all-in-one directory layer so every shell
component lives directly under src/renderer/components.

- Move IncutAreaAllInOne, MainContent, Playground, Sidebar, globals.css
  up into src/renderer/components and drop the redundant barrel index.ts
- Rename the asset helper to asset-urls.ts to avoid a file-vs-directory
  collision with the sibling assets/ folder
- Update App.tsx and IncutAreaAllInOne.tsx imports to the new sibling
  paths, and tighten the midscene-icon.png relative path in asset-urls
- Refresh docs/plan to reference apps/studio and pnpm --filter studio

Validated with pnpm --filter studio build and pnpm run lint.
@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages bot commented Apr 10, 2026

Deploying midscene with  Cloudflare Pages  Cloudflare Pages

Latest commit: 0746a5f
Status: ✅  Deploy successful!
Preview URL: https://ec8d452a.midscene.pages.dev
Branch Preview URL: https://feat-electron-playground-she.midscene.pages.dev

View logs

quanru added 6 commits April 10, 2026 16:53
Strip the incut-export naming from the shell app so the component and
asset map names reflect their actual role instead of the design-tool
provenance.

- Rename the root layout component IncutAreaAllInOne -> ShellLayout
  (directory, default export, barrel re-export, App.tsx usage)
- Rename the asset URL map incutAssetUrls -> assetUrls and update all
  three importers (MainContent, Playground, Sidebar)
- Drop the data-incut-root attribute left behind by the design export

Validated with pnpm --filter studio build, pnpm --filter studio test,
and pnpm run lint.
…ents

These attributes were left behind by the design-export pipeline and are
never read by any runtime or test. Remove them now so the renderer tree
reads cleanly during review.
A round of "fix it while we are here" cleanup surfaced by PR review.

- Sidebar: drop dead referenceId/id/iconId fields left over from the
  design export (types, mock data, SectionHeader props, DeviceRow)
- ShellLayout: remove orphan globals.css; tailwind and the base reset
  are already owned by App.css, so this file only duplicated them
- main: simplify toggleMaximizeWindow handler to a flat if/else
- wait-for-electron-build: narrow readMtimeMs catch to ENOENT so real
  IO errors no longer get swallowed into a stale-build state
- rsbuild.config: extract the renderer dev port into a named constant
  with a note pointing at the matching package.json dev script

Validated with pnpm --filter studio build, pnpm --filter studio test,
and pnpm run lint.
Three targeted fixes from the self-review pass on 7ceead9:

- Collapse the renderer dev port to a single source of truth.
  scripts/renderer-dev-config.mjs now owns host/port/URL and is
  imported by rsbuild.config.ts, wait-for-electron-build.mjs and a
  new launch-electron-dev.mjs launcher that injects the env var for
  electron. The dev script in package.json no longer hardcodes the
  URL, so the port lives in exactly one place.
- Wrap the non-ENOENT throw in readMtimeMs with a contextual Error
  (file path + original message via cause), so unexpected IO failures
  during the dev gate point directly at the offending file.
- Add a regression test that createFreshBuildChecker propagates a
  non-ENOENT reader error instead of treating it as a missing file,
  locking in the narrowed catch behavior.

Validated with pnpm --filter studio build, pnpm --filter studio test,
and pnpm run lint.
@chenshuichao
Copy link
Copy Markdown

why not tauri 2.0?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants