Skip to content

Commit 600a371

Browse files
committed
fix: skip stage screenshots when preview is hidden
1 parent 084ac0b commit 600a371

File tree

2 files changed

+23
-2
lines changed

2 files changed

+23
-2
lines changed

spx-gui/src/components/editor/preview/stage-viewer/StageViewer.vue

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,10 +471,17 @@ function handleWheel(e: KonvaEventObject<WheelEvent>) {
471471
472472
// TODO: implement a standalone screenshot taker which does not depend on StageViewer
473473
// See details in https://github.com/goplus/builder/issues/1807 .
474+
const canTakeScreenshot = computed(() => {
475+
const size = containerSizeRef.value
476+
return container.value != null && container.value.isConnected && size != null && size.width > 0 && size.height > 0
477+
})
478+
474479
async function takeScreenshot(name: string, signal?: AbortSignal) {
480+
if (!canTakeScreenshot.value) throw new Error('stage viewer is not renderable for screenshot')
475481
const stage = await untilNotNull(stageRef, signal)
476482
const nodeTransformer = await untilNotNull(nodeTransformerRef, signal)
477483
await until(() => !loading.value, signal)
484+
if (!canTakeScreenshot.value) throw new Error('stage viewer is not renderable for screenshot')
478485
// Omit transform control when taking screenshot
479486
const blob = await nodeTransformer.withHidden(
480487
() =>
@@ -488,6 +495,7 @@ async function takeScreenshot(name: string, signal?: AbortSignal) {
488495
}
489496
490497
watchEffect((onCleanup) => {
498+
if (!canTakeScreenshot.value) return
491499
const unbind = editorCtx.project.bindScreenshotTaker(takeScreenshot)
492500
onCleanup(unbind)
493501
})

spx-gui/src/models/spx/project.test.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ function mockFile(name = 'mocked') {
1313
return fromText(name, Math.random() + '')
1414
}
1515

16-
function makeProject() {
16+
function makeProject(screenshotTaker: (() => Promise<ReturnType<typeof mockFile>>) | null = async () => mockFile()) {
1717
const project = new SpxProject()
1818
const sound = new Sound('sound', mockFile())
1919
project.addSound(sound)
@@ -35,7 +35,7 @@ function makeProject() {
3535
const animation = Animation.create('default', animationCostumes)
3636
sprite.addAnimation(animation)
3737
project.addSprite(sprite)
38-
project.bindScreenshotTaker(async () => mockFile())
38+
if (screenshotTaker != null) project.bindScreenshotTaker(screenshotTaker)
3939
return project
4040
}
4141

@@ -99,6 +99,19 @@ describe('Project', () => {
9999
expect(hash).toBe(hash2)
100100
})
101101

102+
it('should export with existing thumbnail after screenshot taker unbound', async () => {
103+
const project = makeProject(null)
104+
const thumbnail = mockFile('thumbnail')
105+
const unbindScreenshotTaker = project.bindScreenshotTaker(async () => thumbnail)
106+
107+
project['updateThumbnail']()
108+
await project['updateThumbnail'].flush()
109+
unbindScreenshotTaker()
110+
111+
const { metadata } = await project.export()
112+
expect(metadata.thumbnail).toBe(thumbnail)
113+
})
114+
102115
it('should move sprites correctly', async () => {
103116
const project = new SpxProject()
104117
const sprite1 = new Sprite('sprite1')

0 commit comments

Comments
 (0)