feat(spx-gui): support project templates and adaptive editor layouts - #3480
qingqing-ux wants to merge 12 commits into
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
Review: template layout preview
This is a well-structured PR. The core model change — parameterizing viewportSize and deriving map size from the project's run config — is clean, backward-compatible, and well covered by the new project.test.ts cases (viewport/map independence, defensive copy, round-trip across aspect ratios). The CSS refactor to drive aspect ratio from viewportSize (community project.vue, SpxRunner.ce.vue, ProjectRunnerSurface.vue) is consistent. No security concerns: the loaded run.width/run.height are validated finite and positive before flowing into numeric CSS aspect-ratio, so there is no injection risk; the demo project is client-only and never persisted.
A few points worth a look are left as inline comments. None are blocking.
| Number.isFinite(runHeight) && | ||
| runHeight > 0 | ||
| ) { | ||
| this.viewportSize.width = runWidth |
There was a problem hiding this comment.
[P2] readonly viewportSize is mutated in place after construction
viewportSize is declared readonly with the JSDoc "Visible game canvas size. The map may grow beyond this size.", but loadFiles mutates its members in place (this.viewportSize.width = runWidth; this.viewportSize.height = runHeight, lines 468-469). readonly only forbids reassigning the reference, not mutating the object, so the field is silently re-derived from the run config on load. This is also inconsistent with the constructor, which defensively copies (this.viewportSize = { ...viewportSize }). Consider reassigning a fresh object (this.viewportSize = { width: runWidth, height: runHeight }) for symmetry, and/or documenting that the value is (re)derived from the project's run config during loadFiles.
| :class="{ 'stage-viewer-container-running': runnerState !== 'initial' }" | ||
| class="stage-viewer-container relative w-full flex items-center justify-center overflow-hidden rounded-sm bg-grey-200" | ||
| :class="{ | ||
| 'aspect-4/3': !fillContainer, |
There was a problem hiding this comment.
[P2] Standard editor preview stays hardcoded 4:3 while viewer fits real viewport
The preview container uses 'aspect-4/3': !fillContainer, so any project opened outside the new fillContainer demo layout forces a 4:3 preview box. stageViewerStyle fits the inner StageViewer to the project's actual viewportSize, so now that arbitrary viewports are loadable from run config, a non-4:3 project will be letterboxed inside a 4:3 container in the normal editor — while the community page and runner surface were updated to derive their aspect ratio from viewportSize. Worth confirming this is intentional, or deriving the container aspect from viewportSize here too for consistency.
|
|
||
| const previewSprite = await addDemoSprite(project) | ||
| for (let i = project.sprites.length; i < demoSpriteCount; i += 1) { | ||
| project.addSprite(sourceSprite.clone()) |
There was a problem hiding this comment.
[P3] Demo clones 18 sprites only to hide them
The loop clones the default sprite up to demoSpriteCount (20) via project.addSprite(sourceSprite.clone()), then the following forEach hides every sprite except previewSprite. Each clone() deep-copies costumes/animations and their backing files, so ~18 full clones are created purely to fill the Sprites panel and then hidden — wasteful and non-obvious. Low priority since this is a demo/docs route with a fixed small count, but a brief comment (or a smaller count) would clarify intent.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 31f8025f72
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if ( | ||
| typeof runWidth === 'number' && | ||
| Number.isFinite(runWidth) && | ||
| runWidth > 0 && | ||
| typeof runHeight === 'number' && | ||
| Number.isFinite(runHeight) && | ||
| runHeight > 0 |
There was a problem hiding this comment.
Preserve valid dimensions in partial run configs
When an imported SPX config supplies only one valid run dimension—which RawRunConfig explicitly permits—this all-or-nothing guard discards it, leaving the default size or, when loadFiles() reuses an instance during release checkout, a stale size from the previously loaded files. The next exportFiles() then writes those incorrect dimensions back and changes the project's canvas/runtime behavior; validate and apply each dimension independently with an explicit fallback.
Useful? React with 👍 / 👎.
关联 #3452、#3522。
改动
Console 滚动规则
设 H1 为内容自然高度,H2 为 Code 可视高度,H3 为 Console 高度。滚动容器总内容高度为 max(H2, H1 + H3):
横屏采用常见的 16:9 与 4:3;竖屏 620 × 900 参考 Kitten 的竖屏画布,作为第一版竖屏模板的产品参考,并非行业标准。
验证