收起首页项目操作
首页最近项目卡片改为只读展示。 刷新、清空、显示和移除操作保留在项目页。 更新启动器项目操作回归测试。
This commit is contained in:
@@ -2301,16 +2301,6 @@ export function WorkspaceLauncher({
|
||||
<p className="launcher-project-status">{status}</p>
|
||||
</div>
|
||||
<div className="launcher-project-list-actions">
|
||||
<button
|
||||
type="button"
|
||||
disabled={recentWorkspaceRefreshing}
|
||||
onClick={handleRecentWorkspaceRefresh}
|
||||
>
|
||||
{recentWorkspaceRefreshing ? '刷新中' : '刷新'}
|
||||
</button>
|
||||
<button type="button" onClick={handleRecentWorkspaceClear}>
|
||||
清空
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setLauncherView('projects')}
|
||||
@@ -2325,38 +2315,13 @@ export function WorkspaceLauncher({
|
||||
className="launcher-project-card"
|
||||
key={project.path}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
<div
|
||||
className="launcher-project-card-main"
|
||||
disabled={!project.canOpen}
|
||||
onClick={() => {
|
||||
setProjectPath(project.path);
|
||||
void openProject(project.path, 'open');
|
||||
}}
|
||||
>
|
||||
<span>{project.name.slice(0, 2)}</span>
|
||||
<strong>{project.name}</strong>
|
||||
<small>{project.path}</small>
|
||||
<small>{project.status}</small>
|
||||
</button>
|
||||
<div className="launcher-project-card-actions">
|
||||
<button
|
||||
type="button"
|
||||
aria-label={`显示 ${project.path}`}
|
||||
disabled={!project.canReveal}
|
||||
onClick={() => {
|
||||
void handleRevealProjectDirectory(project.path);
|
||||
}}
|
||||
>
|
||||
显示
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
aria-label={`移除 ${project.path}`}
|
||||
onClick={() => handleRecentWorkspaceRemove(project.path)}
|
||||
>
|
||||
移除
|
||||
</button>
|
||||
</div>
|
||||
</article>
|
||||
))}
|
||||
@@ -2378,6 +2343,18 @@ export function WorkspaceLauncher({
|
||||
<h1>项目</h1>
|
||||
<p>{recentWorkspaceRefreshing ? '正在检查项目状态' : status}</p>
|
||||
</div>
|
||||
<div className="launcher-project-list-actions">
|
||||
<button
|
||||
type="button"
|
||||
disabled={recentWorkspaceRefreshing}
|
||||
onClick={handleRecentWorkspaceRefresh}
|
||||
>
|
||||
{recentWorkspaceRefreshing ? '刷新中' : '刷新'}
|
||||
</button>
|
||||
<button type="button" onClick={handleRecentWorkspaceClear}>
|
||||
清空
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
<form className="launcher-project-form" onSubmit={handleSubmit}>
|
||||
<label>
|
||||
|
||||
@@ -536,12 +536,10 @@ textarea {
|
||||
|
||||
.launcher-project-card {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.launcher-project-card > div,
|
||||
.launcher-project-card > button {
|
||||
.launcher-project-card > div {
|
||||
position: relative;
|
||||
height: 116px;
|
||||
overflow: hidden;
|
||||
@@ -550,15 +548,6 @@ textarea {
|
||||
background: #f7f7f7;
|
||||
}
|
||||
|
||||
.launcher-project-card > button {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.launcher-project-card > button:disabled {
|
||||
cursor: default;
|
||||
opacity: 0.62;
|
||||
}
|
||||
|
||||
.launcher-project-card-main {
|
||||
display: grid;
|
||||
align-content: start;
|
||||
@@ -599,27 +588,6 @@ textarea {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.launcher-project-card-actions {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.launcher-project-card-actions button {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
height: 28px;
|
||||
border: 1px solid #d8dde5;
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
color: #555;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.launcher-project-card-actions button:disabled {
|
||||
color: #aaa;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.launcher-project-create > button {
|
||||
display: grid;
|
||||
border-style: dashed;
|
||||
|
||||
@@ -1109,6 +1109,16 @@ describe('AI 游戏创作 App 界面边界', () => {
|
||||
expect(invoke).not.toHaveBeenCalledWith('inspect_local_project_directory', {
|
||||
projectPath: 'relative-game',
|
||||
});
|
||||
expect(
|
||||
screen.queryByRole('button', { name: '移除 /tmp/recent-one' }),
|
||||
).toBeNull();
|
||||
expect(
|
||||
screen.queryByRole('button', { name: '显示 /tmp/recent-one' }),
|
||||
).toBeNull();
|
||||
expect(screen.queryByRole('button', { name: '刷新' })).toBeNull();
|
||||
expect(screen.queryByRole('button', { name: '清空' })).toBeNull();
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '项目' }));
|
||||
fireEvent.click(
|
||||
screen.getByRole('button', { name: '移除 /tmp/recent-one' }),
|
||||
);
|
||||
@@ -1121,8 +1131,7 @@ describe('AI 游戏创作 App 界面边界', () => {
|
||||
);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '清空' }));
|
||||
expect(screen.queryByLabelText('最近项目')).toBeNull();
|
||||
expect(screen.getByText('欢迎使用 AI 游戏创作')).not.toBeNull();
|
||||
expect(screen.getByText('暂无项目')).not.toBeNull();
|
||||
expect(window.localStorage.length).toBe(0);
|
||||
});
|
||||
|
||||
@@ -1157,6 +1166,10 @@ describe('AI 游戏创作 App 界面边界', () => {
|
||||
renderLauncherAt('/?launcher');
|
||||
|
||||
expect(await screen.findByText('最近的项目')).not.toBeNull();
|
||||
expect(
|
||||
screen.queryByRole('button', { name: '显示 /tmp/recent-one' }),
|
||||
).toBeNull();
|
||||
fireEvent.click(screen.getByRole('button', { name: '项目' }));
|
||||
fireEvent.click(
|
||||
screen.getByRole('button', { name: '显示 /tmp/recent-one' }),
|
||||
);
|
||||
@@ -1298,6 +1311,16 @@ describe('AI 游戏创作 App 界面边界', () => {
|
||||
expect(screen.getByText('检查失败')).not.toBeNull();
|
||||
expect(screen.getByText('厨房突围')).not.toBeNull();
|
||||
expect(screen.getByText('run: done · preview-running')).not.toBeNull();
|
||||
expect(screen.getByText('missing-game').closest('button')).toBeNull();
|
||||
expect(
|
||||
screen.queryByRole('button', { name: '显示 /tmp/missing-game' }),
|
||||
).toBeNull();
|
||||
expect(
|
||||
screen.queryByRole('button', { name: '移除 /tmp/missing-game' }),
|
||||
).toBeNull();
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '项目' }));
|
||||
|
||||
const missingOpenButton = screen
|
||||
.getByText('missing-game')
|
||||
.closest('button') as HTMLButtonElement;
|
||||
@@ -1413,6 +1436,11 @@ describe('AI 游戏创作 App 界面边界', () => {
|
||||
renderLauncherAt('/?launcher');
|
||||
|
||||
expect(await screen.findByText('未找到')).not.toBeNull();
|
||||
expect(screen.queryByRole('button', { name: '刷新' })).toBeNull();
|
||||
expect(screen.getByText('refreshable-game').closest('button')).toBeNull();
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '项目' }));
|
||||
|
||||
expect(
|
||||
(
|
||||
screen
|
||||
@@ -1492,6 +1520,11 @@ describe('AI 游戏创作 App 界面边界', () => {
|
||||
renderLauncherAt('/?launcher');
|
||||
|
||||
expect(await screen.findByText('检查中')).not.toBeNull();
|
||||
expect(
|
||||
screen.queryByRole('button', { name: '移除 /tmp/slow-refresh-game' }),
|
||||
).toBeNull();
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '项目' }));
|
||||
fireEvent.click(
|
||||
screen.getByRole('button', { name: '移除 /tmp/slow-refresh-game' }),
|
||||
);
|
||||
@@ -1512,7 +1545,7 @@ describe('AI 游戏创作 App 界面边界', () => {
|
||||
expect(screen.queryByText('/tmp/slow-refresh-game')).toBeNull();
|
||||
expect(screen.queryByText('慢速刷新旧项目')).toBeNull();
|
||||
expect(screen.queryByText('run: done · late')).toBeNull();
|
||||
expect(screen.getByText('欢迎使用 AI 游戏创作')).not.toBeNull();
|
||||
expect(screen.getByText('暂无项目')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('keeps the typed project path when native directory picking is cancelled', async () => {
|
||||
|
||||
Reference in New Issue
Block a user