From 1c5310a0bc575d4caff084b1103da095590d76d3 Mon Sep 17 00:00:00 2001 From: kdletters Date: Sat, 27 Jun 2026 17:30:37 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=9F=E4=B8=80=E5=9B=BE=E6=A0=87=E7=94=9F?= =?UTF-8?q?=E6=88=90=E4=B8=AD=E5=8D=A0=E4=BD=8D=E5=8A=A8=E7=94=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 限制图标生成器装饰样式只作用于非生成中占位框 恢复图标生成中占位框的共享扫描动画和缩放样式 补充图标生成中动画级联回归测试 --- .../ImageCanvasWorldView.test.tsx | 23 +++++++++++++++ .../image-editor/ImageCanvasWorldView.tsx | 6 +++- src/index.css | 24 ++++++++++++---- src/index.test.ts | 28 +++++++++++++++++++ 4 files changed, 74 insertions(+), 7 deletions(-) diff --git a/src/components/image-editor/ImageCanvasWorldView.test.tsx b/src/components/image-editor/ImageCanvasWorldView.test.tsx index 59eed6cb9..815f6e2c1 100644 --- a/src/components/image-editor/ImageCanvasWorldView.test.tsx +++ b/src/components/image-editor/ImageCanvasWorldView.test.tsx @@ -757,6 +757,29 @@ describe('ImageCanvasWorldView', () => { ).toBe(''); }); + it('uses the shared generating icon scale for icon placeholders', () => { + const dialog = createGenerationDialog({ + id: 'dialog-icon-generating-scale', + mode: 'icon', + status: 'generating', + }); + + renderWorldView({ + viewport: { x: 0, y: 0, scale: 0.25 }, + canvasGenerationDialogs: [dialog], + generateDialog: dialog, + }); + + const frame = screen.getByRole('button', { name: '图标素材生成占位图' }); + const iconTile = frame.querySelector( + '.image-canvas-editor__generation-frame-icon', + ) as HTMLElement; + + expect( + iconTile.style.getPropertyValue('--image-canvas-editor-inverse-scale'), + ).toBe('4'); + }); + it('uses a plain information icon for metadata corner actions', () => { const layer = createLayer(); const { props } = renderWorldView({ layers: [layer] }); diff --git a/src/components/image-editor/ImageCanvasWorldView.tsx b/src/components/image-editor/ImageCanvasWorldView.tsx index 8efee1ae5..240d0c69f 100644 --- a/src/components/image-editor/ImageCanvasWorldView.tsx +++ b/src/components/image-editor/ImageCanvasWorldView.tsx @@ -1290,7 +1290,11 @@ export function ImageCanvasWorldView({ ) : null} {placeholderMeta.icon} diff --git a/src/index.css b/src/index.css index af2729776..dba208560 100644 --- a/src/index.css +++ b/src/index.css @@ -5801,7 +5801,9 @@ html[data-mobile-keyboard-open='true'] .platform-mobile-bottom-dock { } } -.image-canvas-editor__generation-frame--icon { +.image-canvas-editor__generation-frame--icon:not( + .image-canvas-editor__generation-frame--generating + ) { background: linear-gradient( 135deg, rgba(255, 255, 255, 0.72), @@ -5814,8 +5816,12 @@ html[data-mobile-keyboard-open='true'] .platform-mobile-bottom-dock { border-color: #10b981; } -.image-canvas-editor__generation-frame--icon::before, -.image-canvas-editor__generation-frame--icon::after { +.image-canvas-editor__generation-frame--icon:not( + .image-canvas-editor__generation-frame--generating + )::before, +.image-canvas-editor__generation-frame--icon:not( + .image-canvas-editor__generation-frame--generating + )::after { content: ''; position: absolute; width: 42%; @@ -5826,15 +5832,21 @@ html[data-mobile-keyboard-open='true'] .platform-mobile-bottom-dock { box-shadow: 0 12px 24px rgba(15, 118, 110, 0.12); } -.image-canvas-editor__generation-frame--icon::before { +.image-canvas-editor__generation-frame--icon:not( + .image-canvas-editor__generation-frame--generating + )::before { transform: translate(-20%, -8%) rotate(-8deg); } -.image-canvas-editor__generation-frame--icon::after { +.image-canvas-editor__generation-frame--icon:not( + .image-canvas-editor__generation-frame--generating + )::after { transform: translate(18%, 10%) rotate(7deg); } -.image-canvas-editor__generation-frame--icon +.image-canvas-editor__generation-frame--icon:not( + .image-canvas-editor__generation-frame--generating + ) .image-canvas-editor__generation-frame-icon { position: relative; z-index: 1; diff --git a/src/index.test.ts b/src/index.test.ts index 742eb0b39..7dfab151b 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -31,6 +31,34 @@ function getCssBlock(source: string, selector: string) { } describe('index stylesheet unread dots', () => { + it('keeps icon generator decoration from overriding the shared generating animation', () => { + const css = readIndexCss(); + const generatingBlock = getCssBlock( + css, + '.image-canvas-editor__generation-frame--generating', + ); + const generatingScanBlock = getCssBlock( + css, + '.image-canvas-editor__generation-frame--generating::before', + ); + const iconBlock = getCssBlock( + css, + '.image-canvas-editor__generation-frame--icon:not(\n .image-canvas-editor__generation-frame--generating\n )', + ); + const iconDecorationBlock = getCssBlock( + css, + '.image-canvas-editor__generation-frame--icon:not(\n .image-canvas-editor__generation-frame--generating\n )::before,\n.image-canvas-editor__generation-frame--icon:not(\n .image-canvas-editor__generation-frame--generating\n )::after', + ); + + expect(generatingBlock).toContain('cursor: progress;'); + expect(generatingScanBlock).toContain('animation: image-canvas-generation-scan'); + expect(iconBlock).toContain('background: linear-gradient('); + expect(iconDecorationBlock).toContain('width: 42%;'); + expect(css).not.toContain( + '.image-canvas-editor__generation-frame--icon::before,\n.image-canvas-editor__generation-frame--icon::after', + ); + }); + it('keeps image canvas loading shimmer clipped inside media frames', () => { const css = readIndexCss(); const loadingBlock = getCssBlock(