移除首页与工作台素材生成入口
Project CI / AI game creator shell Rust shard 1/4 (push) Successful in 4m58s
Project CI / AI game creator shell Rust shard 2/4 (push) Successful in 4m35s
Project CI / AI game creator shell Rust smoke (push) Successful in 1m31s
Project CI / AI game creator shell Rust shard 4/4 (push) Failing after 4m10s
Project CI / AI game creator shell Rust shard 3/4 (push) Successful in 4m29s
Project CI / AI game creator shell Rust crates (push) Successful in 2m9s
Project CI / Frontend tests (push) Successful in 4m5s
Project CI / Repository checks (push) Successful in 3m20s
Project CI / Native shell tests (push) Successful in 6m24s
Project CI / Backend tests (push) Successful in 7m40s
Project CI / AI game creator shell web tests (push) Successful in 3m18s
Project CI / AI game creator shell Rust shard 1/4 (push) Successful in 4m58s
Project CI / AI game creator shell Rust shard 2/4 (push) Successful in 4m35s
Project CI / AI game creator shell Rust smoke (push) Successful in 1m31s
Project CI / AI game creator shell Rust shard 4/4 (push) Failing after 4m10s
Project CI / AI game creator shell Rust shard 3/4 (push) Successful in 4m29s
Project CI / AI game creator shell Rust crates (push) Successful in 2m9s
Project CI / Frontend tests (push) Successful in 4m5s
Project CI / Repository checks (push) Successful in 3m20s
Project CI / Native shell tests (push) Successful in 6m24s
Project CI / Backend tests (push) Successful in 7m40s
Project CI / AI game creator shell web tests (push) Successful in 3m18s
首页只保留做游戏和做方案入口 移除项目工作台顶部生成素材按钮 同步相关测试与产品文档
This commit is contained in:
@@ -8,9 +8,9 @@ import { subscribeTauriEvent } from '../services/tauriEventSubscription';
|
||||
import { AppUpdateNotice } from './AppUpdateNotice';
|
||||
import {
|
||||
WINDOW_CHROME_DEFAULT_TITLE,
|
||||
type WindowChromeActiveProjectRuns,
|
||||
WindowChromeContext,
|
||||
type WindowChromeContextValue,
|
||||
type WindowChromeActiveProjectRuns,
|
||||
} from './windowChromeContext';
|
||||
|
||||
type WindowChromeProps = {
|
||||
|
||||
@@ -4,7 +4,6 @@ import {
|
||||
FolderKanban,
|
||||
FolderOpen,
|
||||
Gamepad2,
|
||||
Image,
|
||||
Loader2,
|
||||
type LucideIcon,
|
||||
Sparkles,
|
||||
@@ -50,13 +49,6 @@ const HOME_CREATION_TYPE_ITEMS: readonly HomeCreationTypeItem[] = [
|
||||
emptyPrompt: '请输入游戏灵感或上传参考素材',
|
||||
icon: Gamepad2,
|
||||
},
|
||||
{
|
||||
creationType: 'art',
|
||||
label: '做素材',
|
||||
placeholder: '今天想做什么样的美术素材',
|
||||
emptyPrompt: '请输入素材需求或上传参考图',
|
||||
icon: Image,
|
||||
},
|
||||
{
|
||||
creationType: 'doc',
|
||||
label: '做方案',
|
||||
@@ -66,7 +58,7 @@ const HOME_CREATION_TYPE_ITEMS: readonly HomeCreationTypeItem[] = [
|
||||
},
|
||||
];
|
||||
|
||||
// 首页只在做游戏与做方案之间分叉:做素材已被 master 并进直连构建,与做游戏同链,
|
||||
// 首页只保留做游戏与做方案两个入口;素材生成在项目内按实际工作流触发。
|
||||
export type HomeProjectRow = {
|
||||
path: string;
|
||||
name: string;
|
||||
@@ -149,13 +141,15 @@ export default function HomeView({
|
||||
const [planningCompletionEnabled, setPlanningCompletionEnabled] =
|
||||
useState(false);
|
||||
const homeCreationBusyRef = useRef(false);
|
||||
const effectiveCreationType =
|
||||
homeCreationType === 'art' ? 'game' : homeCreationType;
|
||||
const activeCreationType =
|
||||
HOME_CREATION_TYPE_ITEMS.find(
|
||||
(item) => item.creationType === homeCreationType,
|
||||
(item) => item.creationType === effectiveCreationType,
|
||||
) ?? HOME_CREATION_TYPE_ITEMS[0]!;
|
||||
// 做方案始终走立项策划链路;做游戏勾选“策划补全”时复用该链路,做素材保持直接开建。
|
||||
// 做方案始终走立项策划链路;做游戏勾选“策划补全”时复用该链路。
|
||||
const startMode = resolveHomeStartMode(
|
||||
homeCreationType,
|
||||
effectiveCreationType,
|
||||
planningCompletionEnabled,
|
||||
);
|
||||
|
||||
@@ -166,7 +160,7 @@ export default function HomeView({
|
||||
const referencedAttachments = richTextToAttachments(homeRichText);
|
||||
const prompt = richTextToPrompt(homeRichText);
|
||||
if (!prompt && referencedAttachments.length === 0) {
|
||||
if (homeCreationType !== 'doc') {
|
||||
if (effectiveCreationType !== 'doc') {
|
||||
onStatusChange(activeCreationType.emptyPrompt);
|
||||
}
|
||||
return;
|
||||
@@ -177,7 +171,7 @@ export default function HomeView({
|
||||
onStatusChange(
|
||||
await onCreateDraftAutomatically(
|
||||
{
|
||||
creationType: homeCreationType,
|
||||
creationType: effectiveCreationType,
|
||||
prompt,
|
||||
attachments: referencedAttachments,
|
||||
},
|
||||
@@ -274,7 +268,7 @@ export default function HomeView({
|
||||
<div className="grid grid-cols-[1fr_auto] items-center gap-2.5 text-[12px] text-(--platform-text-soft)">
|
||||
<div className="flex min-w-0 items-center gap-3">
|
||||
<UploadButton />
|
||||
{homeCreationType === 'game' ? (
|
||||
{effectiveCreationType === 'game' ? (
|
||||
<label className="inline-flex cursor-pointer items-center gap-1.5 whitespace-nowrap">
|
||||
<input
|
||||
type="checkbox"
|
||||
|
||||
@@ -156,7 +156,6 @@ import {
|
||||
resolveResourceCanvasFocusEscapeActive,
|
||||
} from '../../features/resource-canvas/resourceCanvasFocusModel';
|
||||
import {
|
||||
isResourceCanvasGenerationAvailable,
|
||||
type ResourceCanvasGenerationKind,
|
||||
resourceCanvasGenerationOption,
|
||||
resourceCanvasGenerationSourceId,
|
||||
@@ -7441,12 +7440,6 @@ export default function ProjectDevelopmentView({
|
||||
RESOURCE_CHARACTER_ANIMATION_RESOLUTION,
|
||||
RESOURCE_CHARACTER_ANIMATION_DURATION_SECONDS,
|
||||
);
|
||||
// 没有客户端 invoke 桥或项目还没就绪时不渲染生成入口,避免留下点了没反应的按钮。
|
||||
const resourceGenerationAvailable = isResourceCanvasGenerationAvailable({
|
||||
hasRuntimeInvoke: Boolean(window.__TAURI__?.core?.invoke),
|
||||
projectPath,
|
||||
projectId: manifest.projectId,
|
||||
});
|
||||
/**
|
||||
* 栏目画布底部工具栏的渲染判据:只在栏目页 `child` 且命中矩阵里的四个栏目时成立。
|
||||
*
|
||||
@@ -7680,27 +7673,9 @@ export default function ProjectDevelopmentView({
|
||||
<FolderTree size={15} aria-hidden="true" />
|
||||
资源面板
|
||||
</button>
|
||||
{resourceGenerationAvailable ? (
|
||||
<button
|
||||
type="button"
|
||||
className="game-workbench-resource-panel-button"
|
||||
aria-haspopup="dialog"
|
||||
aria-expanded={resourceGenerationOpen}
|
||||
onClick={() =>
|
||||
setResourceGenerationDraft({
|
||||
initialKind: 'video',
|
||||
kinds: ['video'],
|
||||
})
|
||||
}
|
||||
>
|
||||
<Sparkles size={15} aria-hidden="true" />
|
||||
生成素材
|
||||
</button>
|
||||
) : null}
|
||||
{/*
|
||||
{/*
|
||||
「整理画布」是一枚资源动作,不是第三种排列方式:它排在「生成素材」之后、
|
||||
「管理未完成编辑」之前,与其他资源动作同类相邻,并留在
|
||||
「整理画布」是一枚资源动作,不是第三种排列方式:它与其他资源动作相邻,
|
||||
并留在
|
||||
`game-workbench-view-actions` 动作区里——外观直接复用该容器既有的动作按钮
|
||||
样式(有边圆角 + secondary 填充),与分段 pill 的模式切换一眼可分;因此不
|
||||
新增任何 CSS。**不要放到这一行的行尾**:行尾会被读成“针对整个工具条”的动作。
|
||||
|
||||
@@ -1498,14 +1498,11 @@ export function registerHomeProjectCreationTests() {
|
||||
const gameType = within(creationTypes).getByRole('button', {
|
||||
name: '做游戏',
|
||||
});
|
||||
const artType = within(creationTypes).getByRole('button', {
|
||||
name: '做素材',
|
||||
});
|
||||
const documentType = within(creationTypes).getByRole('button', {
|
||||
name: '做方案',
|
||||
});
|
||||
expect(gameType.getAttribute('aria-pressed')).toBe('true');
|
||||
expect(artType.getAttribute('aria-pressed')).toBe('false');
|
||||
expect(within(creationTypes).queryByRole('button', { name: '做素材' })).toBeNull();
|
||||
expect(documentType.getAttribute('aria-pressed')).toBe('false');
|
||||
expect(screen.getByText('你的游戏创作管家')).not.toBeNull();
|
||||
expect(screen.getAllByText('今天想把什么灵感做成游戏')).toHaveLength(1);
|
||||
@@ -1519,11 +1516,10 @@ export function registerHomeProjectCreationTests() {
|
||||
expect(invoke).not.toHaveBeenCalledWith(
|
||||
'create_automatic_local_game_project',
|
||||
);
|
||||
fireEvent.click(artType);
|
||||
expect(gameType.getAttribute('aria-pressed')).toBe('false');
|
||||
expect(artType.getAttribute('aria-pressed')).toBe('true');
|
||||
fireEvent.click(gameType);
|
||||
expect(gameType.getAttribute('aria-pressed')).toBe('true');
|
||||
expect(screen.getByText('你的游戏创作管家')).not.toBeNull();
|
||||
expect(screen.getAllByText('今天想做什么样的美术素材')).toHaveLength(1);
|
||||
expect(screen.getAllByText('今天想把什么灵感做成游戏')).toHaveLength(1);
|
||||
|
||||
const promptInput = screen.getByLabelText('创作想法');
|
||||
nativeClipboardMock.text = '你好,今天多少号';
|
||||
@@ -1562,7 +1558,7 @@ export function registerHomeProjectCreationTests() {
|
||||
expect(invoke).toHaveBeenCalledWith('chat_with_game_creator_direct_codex', {
|
||||
projectPath: automaticProjectPath,
|
||||
prompt: '你好,今天多少号',
|
||||
creationType: 'art',
|
||||
creationType: 'game',
|
||||
clientTurnId: expect.any(String),
|
||||
userItem: {
|
||||
id: expect.stringMatching(/^direct-codex:[A-Za-z0-9-]+:user$/),
|
||||
|
||||
@@ -1109,49 +1109,11 @@ describe('project resource live canvas integration', () => {
|
||||
expect(readViewport()).not.toBe(viewportBefore);
|
||||
});
|
||||
|
||||
it('creates a brand new media asset from the canvas generation entry with a create-mode derive request', async () => {
|
||||
const { deriveCalls } = installTauri({ failFirstDerive: true });
|
||||
it('does not expose a top-level canvas generation entry', async () => {
|
||||
installTauri();
|
||||
render(<DerivedWorkbench />);
|
||||
|
||||
fireEvent.click(await screen.findByRole('button', { name: '生成素材' }));
|
||||
// 「生成素材」入口只保留视频:音频入口已由栏目画布底部工具栏承载。
|
||||
const panel = await screen.findByRole('dialog', { name: '生成视频' });
|
||||
fireEvent.change(within(panel).getByLabelText('生成提示词'), {
|
||||
target: { value: '一段片头动画,镜头缓慢推进' },
|
||||
});
|
||||
fireEvent.click(within(panel).getByRole('button', { name: '生成视频' }));
|
||||
expect(await within(panel).findByRole('alert')).not.toBeNull();
|
||||
fireEvent.click(
|
||||
within(panel).getByRole('button', { name: '使用原请求重试' }),
|
||||
);
|
||||
|
||||
await waitFor(() => expect(deriveCalls).toHaveLength(2));
|
||||
const operationId = String(deriveCalls[0]?.operationId);
|
||||
expect(deriveCalls[0]).toMatchObject({
|
||||
projectPath,
|
||||
expectedProjectId: 'live-canvas-project',
|
||||
editKind: 'video',
|
||||
generationMode: 'create',
|
||||
sourceResourceId: `create:${operationId}`,
|
||||
sourceAssetId: null,
|
||||
sourcePath: null,
|
||||
sourceMediaType: 'video/mp4',
|
||||
sourceSubtype: null,
|
||||
producerTaskId: null,
|
||||
sourceVersionId: null,
|
||||
prompt: '一段片头动画,镜头缓慢推进',
|
||||
assetName: '新视频',
|
||||
});
|
||||
expect(deriveCalls[0]).not.toHaveProperty('accessToken');
|
||||
expect(deriveCalls[1]?.operationId).toBe(operationId);
|
||||
expect(deriveCalls[1]?.idempotencyKey).toBe(deriveCalls[0]?.idempotencyKey);
|
||||
expect(screen.queryByRole('dialog', { name: '生成视频' })).toBeNull();
|
||||
// 产出物是新素材:画布定位并选中新卡片。
|
||||
expect(
|
||||
(await findResourceSelectButton(`${operationId}-rules.md`)).getAttribute(
|
||||
'aria-pressed',
|
||||
),
|
||||
).toBe('true');
|
||||
expect(screen.queryByRole('button', { name: '生成素材' })).toBeNull();
|
||||
});
|
||||
|
||||
it('keeps the search condition, offers an explicit clear-and-locate, then locates the new asset', async () => {
|
||||
|
||||
@@ -790,8 +790,7 @@ describe('资源画布手动重排口径', () => {
|
||||
const actionsRow = rederiveButton.closest('.game-workbench-view-actions');
|
||||
expect(actionsRow).not.toBeNull();
|
||||
|
||||
// 位置:不再是这一行的最后一个按钮(行尾会被读成"针对整个工具条"的动作),
|
||||
// 紧跟「生成素材」,并且在排序组左侧。
|
||||
// 位置:整理画布仍在排序组左侧,不会被读成排列方式的一部分。
|
||||
const rowButtons = Array.from(actionsRow!.querySelectorAll('button'));
|
||||
expect(rowButtons.at(-1)).not.toBe(rederiveButton);
|
||||
const rederiveIndex = rowButtons.indexOf(rederiveButton);
|
||||
@@ -801,9 +800,6 @@ describe('资源画布手动重排口径', () => {
|
||||
expect(rederiveIndex).toBeGreaterThanOrEqual(0);
|
||||
expect(sortGroupIndex).toBeGreaterThanOrEqual(0);
|
||||
expect(rederiveIndex).toBeLessThan(sortGroupIndex);
|
||||
expect(rederiveButton.previousElementSibling).toBe(
|
||||
screen.getByRole('button', { name: '生成素材' }),
|
||||
);
|
||||
|
||||
// 语义没变:可点性只跟布局就绪绑定,布局读完后它就是可点的。
|
||||
await waitFor(() =>
|
||||
|
||||
Reference in New Issue
Block a user