Fix/统一修复modal样式失效 (#122)
Project CI / Repository checks (push) Successful in 48s
Project CI / Frontend tests (push) Successful in 3m21s
Project CI / Backend tests (push) Successful in 3m53s
Project CI / Native shell tests (push) Successful in 11m16s

之前遇到几次弹窗的样式不生效,bug 现在在画布agent的删除对话弹窗又出现了,
这个pr把类似的修改集中到最下层的UnifiedModal,适用于所有的modal,
一些特殊的modal有特殊处理.

画布agent的删除对话弹窗
![shotmd-1785399342.jpg](/attachments/d63d7dc6-bf7e-4f13-bfe8-bc4716cd798f)

---------

Co-authored-by: 段舒康 <kdletters@qq.com>
Reviewed-on: http://192.168.35.82/git/GenarrativeAI/Genarrative/pulls/122
Reviewed-by: 段舒康 <kdletters@qq.com>
Co-authored-by: 王德宇 <kvtodev@outlook.com>
Co-committed-by: 王德宇 <kvtodev@outlook.com>
This commit was merged in pull request #122.
This commit is contained in:
2026-08-03 17:55:47 +08:00
committed by 段舒康
parent 3c58e76a71
commit e6b3199490
35 changed files with 486 additions and 169 deletions
@@ -338,9 +338,7 @@ describe('EditorAgentConversationPanelView', () => {
expect(
screen.getByText('一二三四五六七八九十甲乙丙丁戊己庚辛壬癸子丑寅卯'),
).toBeTruthy();
expect(
screen.getByRole('option', { name: '角色参考' }),
).toBeTruthy();
expect(screen.getByRole('option', { name: '角色参考' })).toBeTruthy();
expect(screen.getByRole('option', { name: '新对话' })).toBeTruthy();
fireEvent.change(screen.getByLabelText('发送给画布 Agent'), {
@@ -530,9 +528,9 @@ describe('EditorAgentConversationPanelView', () => {
(screen.getByLabelText('发送给画布 Agent') as HTMLTextAreaElement).value,
).toBe('需要保留的草稿');
expect(screen.getByText('已经看到画布内容')).toBeTruthy();
expect(
(screen.getByLabelText('当前对话') as HTMLSelectElement).value,
).toBe('conversation-1');
expect((screen.getByLabelText('当前对话') as HTMLSelectElement).value).toBe(
'conversation-1',
);
});
it('preserves newer draft edits while creating a conversation', async () => {
@@ -1989,6 +1987,14 @@ describe('EditorAgentConversationPanelView', () => {
fireEvent.click(screen.getByRole('button', { name: '删除当前对话' }));
const confirmDialog = screen.getByRole('dialog', { name: '删除对话' });
expect(confirmDialog.parentElement?.className).toContain(
'platform-theme--light',
);
expect(confirmDialog.parentElement?.className).toContain('z-[140]');
expect(confirmDialog.className).toContain('platform-remap-surface');
expect(
within(confirmDialog).getByText('确认删除这个对话吗?'),
).toBeTruthy();
fireEvent.click(
within(confirmDialog).getByRole('button', { name: '确认删除' }),
);
@@ -391,7 +391,9 @@ export function EditorAgentConversationPanelView({
setDeleteConfirmOpen(false),
);
}}
/>
>
确认删除这个对话吗?
</PlatformDangerConfirmDialog>
</>
);
}
@@ -118,9 +118,11 @@ describe('MessageBubble', () => {
clientX: 30,
clientY: 40,
});
const menu = screen.getByRole('menu', { name: '消息右键菜单' });
expect(menu.style.zIndex).toBe('60');
expect(
screen.getByRole('menu', { name: '消息右键菜单' }).style.zIndex,
).toBe('60');
menu.closest('.image-canvas-editor__portal-theme')?.className,
).toContain('platform-theme--light');
fireEvent.click(screen.getByRole('menuitem', { name: '复制文本' }));
await waitFor(() =>
@@ -1,8 +1,8 @@
import { useEffect, useLayoutEffect, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import type { ImageCanvasActionResult } from '@/src/components/image-editor/ImageCanvasActionsContext.ts';
import { ImageCanvasEditorPortal } from '../ImageCanvasEditorPortal.tsx';
import {
contextAssetMediaSrc,
type EditorAgentContextAsset,
@@ -158,110 +158,115 @@ export function MessageBubbleRightClickMenu({
};
}, [onClose]);
if (typeof document === 'undefined') {
return null;
}
return createPortal(
<div
ref={menuRef}
className="image-canvas-editor__context-menu"
role="menu"
aria-label={target.kind === 'text' ? '消息右键菜单' : '消息素材右键菜单'}
style={{
left: position?.x ?? x,
top: position?.y ?? y,
zIndex: 60,
}}
onContextMenu={(event) => event.preventDefault()}
>
{target.kind === 'text' ? (
<button
type="button"
role="menuitem"
disabled={pendingAction !== null}
onClick={() => onAction(EditorAgentRightClickAction.CopyText)}
>
{actionLabel({
action: EditorAgentRightClickAction.CopyText,
idleLabel: '复制文本',
pendingAction,
resultAction,
result,
})}
</button>
) : (
<>
{target.asset.kind === 'generated_media' &&
target.asset.resourceId?.trim() ? (
<button
type="button"
role="menuitem"
disabled={pendingAction !== null}
onClick={() => onAction(EditorAgentRightClickAction.FocusCanvas)}
>
{actionLabel({
action: EditorAgentRightClickAction.FocusCanvas,
idleLabel: '在画布中定位',
pendingAction,
resultAction,
result,
})}
</button>
) : null}
{target.asset.mediaType === 'image' ? (
<>
{contextAssetMediaSrc(target.asset).trim() ? (
<button
type="button"
role="menuitem"
disabled={pendingAction !== null}
onClick={() =>
onAction(EditorAgentRightClickAction.ReferenceImage)
}
>
{actionLabel({
action: EditorAgentRightClickAction.ReferenceImage,
idleLabel: '引用',
pendingAction,
resultAction,
result,
})}
</button>
) : null}
<button
type="button"
role="menuitem"
disabled={pendingAction !== null}
onClick={() => onAction(EditorAgentRightClickAction.CopyImage)}
>
{actionLabel({
action: EditorAgentRightClickAction.CopyImage,
idleLabel: '复制图片',
pendingAction,
resultAction,
result,
})}
</button>
</>
) : null}
return (
<ImageCanvasEditorPortal>
<div
ref={menuRef}
className="image-canvas-editor__context-menu"
role="menu"
aria-label={
target.kind === 'text' ? '消息右键菜单' : '消息素材右键菜单'
}
style={{
left: position?.x ?? x,
top: position?.y ?? y,
zIndex: 60,
}}
onContextMenu={(event) => event.preventDefault()}
>
{target.kind === 'text' ? (
<button
type="button"
role="menuitem"
disabled={pendingAction !== null}
onClick={() => onAction(EditorAgentRightClickAction.DownloadAsset)}
onClick={() => onAction(EditorAgentRightClickAction.CopyText)}
>
{actionLabel({
action: EditorAgentRightClickAction.DownloadAsset,
idleLabel: assetDownloadLabel(target.asset),
action: EditorAgentRightClickAction.CopyText,
idleLabel: '复制文本',
pendingAction,
resultAction,
result,
})}
</button>
</>
)}
</div>,
document.body,
) : (
<>
{target.asset.kind === 'generated_media' &&
target.asset.resourceId?.trim() ? (
<button
type="button"
role="menuitem"
disabled={pendingAction !== null}
onClick={() =>
onAction(EditorAgentRightClickAction.FocusCanvas)
}
>
{actionLabel({
action: EditorAgentRightClickAction.FocusCanvas,
idleLabel: '在画布中定位',
pendingAction,
resultAction,
result,
})}
</button>
) : null}
{target.asset.mediaType === 'image' ? (
<>
{contextAssetMediaSrc(target.asset).trim() ? (
<button
type="button"
role="menuitem"
disabled={pendingAction !== null}
onClick={() =>
onAction(EditorAgentRightClickAction.ReferenceImage)
}
>
{actionLabel({
action: EditorAgentRightClickAction.ReferenceImage,
idleLabel: '引用',
pendingAction,
resultAction,
result,
})}
</button>
) : null}
<button
type="button"
role="menuitem"
disabled={pendingAction !== null}
onClick={() =>
onAction(EditorAgentRightClickAction.CopyImage)
}
>
{actionLabel({
action: EditorAgentRightClickAction.CopyImage,
idleLabel: '复制图片',
pendingAction,
resultAction,
result,
})}
</button>
</>
) : null}
<button
type="button"
role="menuitem"
disabled={pendingAction !== null}
onClick={() =>
onAction(EditorAgentRightClickAction.DownloadAsset)
}
>
{actionLabel({
action: EditorAgentRightClickAction.DownloadAsset,
idleLabel: assetDownloadLabel(target.asset),
pendingAction,
resultAction,
result,
})}
</button>
</>
)}
</div>
</ImageCanvasEditorPortal>
);
}