恢复新版创作主页与平台侧栏
恢复 /creation 新版创作工具主页及创作、项目公共侧栏。 将 creation-home 重新纳入 Vite、TypeScript、ESLint 与 Vitest 活动编译链。 恢复 /creation 的 Nginx 与 Pingora SPA 白名单并保留旧子路径下线边界。 补充路由、标题、CSS 过滤和网关 smoke 回归验证。
This commit is contained in:
@@ -127,7 +127,6 @@ module.exports = {
|
||||
'src/components/big-fish-result/**',
|
||||
'src/components/big-fish-runtime/**',
|
||||
'src/components/creation-agent/**',
|
||||
'src/components/creation-home/**',
|
||||
'src/components/creative-agent/**',
|
||||
'src/components/custom-world-agent/**',
|
||||
'src/components/custom-world-home/**',
|
||||
|
||||
@@ -141,7 +141,7 @@ http {
|
||||
try_files /index.html =404;
|
||||
}
|
||||
|
||||
location ~* "^/(?:editor/canvas|project)/?$" {
|
||||
location ~* "^/(?:creation|editor/canvas|project)/?$" {
|
||||
try_files $uri /index.html =404;
|
||||
}
|
||||
# END GENARRATIVE MAIN SPA ROUTES
|
||||
|
||||
@@ -190,7 +190,7 @@ server {
|
||||
try_files /index.html =404;
|
||||
}
|
||||
|
||||
location ~* "^/(?:editor/canvas|project)/?$" {
|
||||
location ~* "^/(?:creation|editor/canvas|project)/?$" {
|
||||
error_page 503 /maintenance.html;
|
||||
|
||||
if ($genarrative_maintenance) {
|
||||
|
||||
@@ -210,7 +210,7 @@ server {
|
||||
try_files /index.html =404;
|
||||
}
|
||||
|
||||
location ~* "^/(?:editor/canvas|project)/?$" {
|
||||
location ~* "^/(?:creation|editor/canvas|project)/?$" {
|
||||
error_page 503 /maintenance.html;
|
||||
|
||||
if ($genarrative_maintenance) {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# 旧创作模板业务退役方案
|
||||
|
||||
更新时间:`2026-07-17`
|
||||
更新时间:`2026-07-18`
|
||||
|
||||
## 目标
|
||||
|
||||
退役整个旧创作模板体系及其专属运行态,同时保留全部相关历史持久化表、迁移白名单和必要的兼容读取定义。历史数据不删除,持久化表及字段不删除、不改名、不重排、不改变类型。
|
||||
|
||||
本次执行口径是“数据壳保留,业务实现退役”:历史表继续以最小 schema 代码随 `spacetime-module` 编译和发布;创作入口、模板选择、生成、发布、公开业务详情、作品广场、排行榜和专属运行态不再进入正式编译链或运行路由。
|
||||
本次执行口径是“数据壳保留,业务实现退役”:历史表继续以最小 schema 代码随 `spacetime-module` 编译和发布;旧模板选择、生成、发布、公开业务详情、作品广场、排行榜和专属运行态不再进入正式编译链或运行路由。基于图片编辑器项目与公开素材的新版 `/creation` 创作工具主页及平台公共侧边栏继续作为现役能力保留。
|
||||
|
||||
## 范围
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
- `migration.rs` 中相关表的迁移白名单、表名兼容和字段目录。
|
||||
- 为历史审计、迁移、资产归属核对所必需的最小只读表定义;不得借兼容读取重新暴露旧创作、发布、公开详情或运行接口。
|
||||
- 编辑器、项目、账号、钱包、资产、HostBridge、运维和安全等平台公共能力。
|
||||
- 新版 `/creation` 创作工具主页、`creation-home` 展示组件与静态资产,以及桌面端“创作 / 项目”公共侧边栏;这些能力只读取编辑器项目和公开素材接口,不恢复旧模板入口。
|
||||
- 旧页面、测试、素材、handler、service、worker、生成 bindings 和纯业务 crate 的源码目录;它们仅用于历史追溯,不属于任何正式入口或编译目标。
|
||||
|
||||
## 编译边界
|
||||
@@ -32,11 +33,11 @@
|
||||
### 前端
|
||||
|
||||
- 主路由、Vite 入口和运行时动态 import 不得引用旧业务目录。
|
||||
- 正式应用入口使用 `active-main.tsx`、`ActiveApp.tsx`、`routing/activeAppRoutes.tsx`、`routing/activeAppPageRoutes.ts`、`services/activeAppTitle.ts`、`platform-entry/PlatformEntryActiveFlowShell.tsx` 和 `platformEntryActiveTypes.ts`;原同名非 active 文件保持历史源码原貌并退出 Vite、TypeScript、ESLint 和 Vitest。
|
||||
- 正式应用入口使用 `active-main.tsx`、`ActiveApp.tsx`、`routing/activeAppRoutes.tsx`、`routing/activeAppPageRoutes.ts`、`services/activeAppTitle.ts`、`platform-entry/PlatformEntryActiveFlowShell.tsx`、`platformEntryActiveTypes.ts` 和 `creation-home/`;原同名非 active 文件保持历史源码原貌并退出 Vite、TypeScript、ESLint 和 Vitest。
|
||||
- 旧业务源码与素材保留在仓库中;Vite 不得再引用入口或动态 import,TypeScript、ESLint、Vitest 必须明确排除旧目录和专属测试。退役源码只用于历史追溯,不允许从在运代码重新导入。
|
||||
- 原 `main.tsx`、`App.tsx`、旧路由、旧标题映射、`PlatformEntryFlowShellImpl.tsx` 与旧入口类型保持原样;正式链路由 `active-main.tsx`、`ActiveApp.tsx`、`activeApp*`、`PlatformEntryActiveFlowShell.tsx` 和 `platformEntryActiveTypes.ts` 承载,只包含项目、编辑器、账号、设置与钱包公共能力。`retired/legacy-creation-templates/frontend/original/` 另保留逐文件原样快照。
|
||||
- 原 `main.tsx`、`App.tsx`、旧路由、旧标题映射、`PlatformEntryFlowShellImpl.tsx` 与旧入口类型保持原样;正式链路由 `active-main.tsx`、`ActiveApp.tsx`、`activeApp*`、`PlatformEntryActiveFlowShell.tsx` 和 `platformEntryActiveTypes.ts` 承载,只包含新版创作主页、项目、编辑器、账号、设置与钱包公共能力。`retired/legacy-creation-templates/frontend/original/` 另保留逐文件原样快照。
|
||||
- 退役 CSS 的源码过滤必须在 Tailwind/Vite 转换前执行,产物过滤留在 `generateBundle`;禁止在 `post` transform 中把 Vite 已生成的 JavaScript 样式模块重新交给 PostCSS 解析。
|
||||
- 旧 URL 统一回落到当前平台公共首页,不再提供旧业务错误页、详情页或兼容壳。
|
||||
- `/creation` 保持新版创作工具主页;生产网关对旧子路径返回 404,客户端若收到未知旧路径则回落当前平台公共首页,不再提供旧业务详情页或兼容壳。
|
||||
|
||||
### Rust
|
||||
|
||||
@@ -50,6 +51,7 @@
|
||||
## 验收
|
||||
|
||||
- 旧 URL 不再命中旧页面或后端路由。
|
||||
- `/creation` 与 `/project` 显示公共侧边栏,新创作主页只调用编辑器项目和公开素材接口。
|
||||
- Vite 构建产物和依赖图不包含旧前端业务目录。
|
||||
- `cargo tree` 中不存在纯模板 crate 或专属运行态 crate。
|
||||
- `spacetime-module` 编译结果仍包含全部历史表,但不包含任何旧模板 reducer、procedure 和业务 view。
|
||||
|
||||
@@ -571,6 +571,17 @@ async function runSmokeCases(
|
||||
response.headers['cache-control'] === 'no-cache',
|
||||
},
|
||||
);
|
||||
await expectHttp(
|
||||
baseUrl,
|
||||
'/creation',
|
||||
200,
|
||||
'site-shell',
|
||||
'新创作主页深链回退 index.html',
|
||||
{
|
||||
validate: (response) =>
|
||||
response.headers['cache-control'] === 'no-cache',
|
||||
},
|
||||
);
|
||||
await expectHttp(
|
||||
baseUrl,
|
||||
'/project',
|
||||
|
||||
@@ -21,4 +21,25 @@ describe('retired creation template CSS plugin', () => {
|
||||
expect(plugin).toBeDefined();
|
||||
expect(plugin?.enforce).toBe('pre');
|
||||
});
|
||||
|
||||
it('keeps the active creation landing CSS while removing retired template CSS', async () => {
|
||||
const plugin = await resolveRetiredCssPlugin();
|
||||
const transform = plugin?.transform;
|
||||
|
||||
expect(typeof transform).toBe('function');
|
||||
if (typeof transform !== 'function') {
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await transform.call(
|
||||
{} as never,
|
||||
"@import 'tailwindcss';\n.creation-landing { color: red; }\n.puzzle-runtime { color: blue; }",
|
||||
'/workspace/src/index.css',
|
||||
);
|
||||
const code = typeof result === 'string' ? result : result?.code;
|
||||
|
||||
expect(code).toContain('.creation-landing');
|
||||
expect(code).not.toContain('.puzzle-runtime');
|
||||
expect(code).toContain('@source "./components/creation-home"');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -55,7 +55,7 @@ const SHADOW_PROBE_HEADER: &str = "x-genarrative-pingora-probe";
|
||||
const PAYLOAD_TOO_LARGE_CONTEXT: &str = "genarrative_payload_too_large";
|
||||
const PROTECTION_STATE_TTL: Duration = Duration::from_secs(600);
|
||||
const PROTECTION_CLEANUP_INTERVAL: Duration = Duration::from_secs(60);
|
||||
const MAIN_SPA_PATHS: &[&str] = &["/", "/editor/canvas", "/project"];
|
||||
const MAIN_SPA_PATHS: &[&str] = &["/", "/creation", "/editor/canvas", "/project"];
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct GatewayConfig {
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
import { FolderKanban, LogIn, Settings, UserRound } from 'lucide-react';
|
||||
import { lazy, Suspense, useCallback, useEffect, useState } from 'react';
|
||||
import {
|
||||
FolderKanban,
|
||||
LogIn,
|
||||
Palette,
|
||||
Settings,
|
||||
UserRound,
|
||||
} from 'lucide-react';
|
||||
import {
|
||||
type ComponentType,
|
||||
lazy,
|
||||
Suspense,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react';
|
||||
|
||||
import { PlatformMudPointWalletEntry } from '../../../packages/shared/src/components/PlatformMudPointWalletEntry';
|
||||
import type { ProfileDashboardSummary } from '../../../packages/shared/src/contracts/runtime';
|
||||
@@ -25,11 +38,87 @@ const ImageCanvasEditorView = lazy(async () => {
|
||||
return { default: module.ImageCanvasEditorView };
|
||||
});
|
||||
|
||||
const CreationLandingView = lazy(async () => {
|
||||
const module = await import('../creation-home/CreationLandingView');
|
||||
return { default: module.CreationLandingView };
|
||||
});
|
||||
|
||||
const ProjectGalleryView = lazy(async () => {
|
||||
const module = await import('../project/ProjectGalleryView');
|
||||
return { default: module.ProjectGalleryView };
|
||||
});
|
||||
|
||||
type ActiveRailButtonProps = {
|
||||
active: boolean;
|
||||
emphasized?: boolean;
|
||||
icon: ComponentType<{ className?: string }>;
|
||||
iconSrc: string;
|
||||
label: string;
|
||||
onClick: () => void;
|
||||
};
|
||||
|
||||
function ActiveRailButton({
|
||||
active,
|
||||
emphasized = false,
|
||||
icon: Icon,
|
||||
iconSrc,
|
||||
label,
|
||||
onClick,
|
||||
}: ActiveRailButtonProps) {
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
aria-current={active ? 'page' : undefined}
|
||||
aria-label={label}
|
||||
className={`platform-desktop-rail__button ${emphasized ? 'platform-desktop-rail__button--primary' : ''} ${active ? 'platform-desktop-rail__button--active' : ''}`}
|
||||
onClick={onClick}
|
||||
>
|
||||
<span className="platform-desktop-rail__icon-shell">
|
||||
<img
|
||||
src={iconSrc}
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
draggable={false}
|
||||
className="creation-home-nav-art"
|
||||
/>
|
||||
<Icon
|
||||
className="platform-desktop-rail__icon h-[1.1rem] w-[1.1rem]"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</span>
|
||||
<span className="platform-desktop-rail__label text-[11px] font-semibold">
|
||||
{label}
|
||||
</span>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
function ActivePlatformBrand() {
|
||||
return (
|
||||
<span
|
||||
className="creation-home-brand-lockup shrink-0"
|
||||
role="img"
|
||||
aria-label="陶泥儿 GENARRATIVE"
|
||||
>
|
||||
<span className="platform-brand-logo">
|
||||
<img
|
||||
src="/branding/taonier-product-ip.png"
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
draggable={false}
|
||||
className="platform-brand-logo__image"
|
||||
/>
|
||||
<span className="platform-brand-logo__copy">
|
||||
<span className="platform-brand-logo__title">
|
||||
陶泥<span className="platform-brand-logo__title-suffix">儿</span>
|
||||
</span>
|
||||
<span className="platform-brand-logo__subtitle">GENARRATIVE</span>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
function LoadingPanel({ label }: { label: string }) {
|
||||
return (
|
||||
<div className="flex h-full min-h-[12rem] items-center justify-center text-sm font-semibold text-[var(--platform-text-soft)]">
|
||||
@@ -76,18 +165,26 @@ export function PlatformEntryFlowShellImpl({
|
||||
currentUser: authUi?.user,
|
||||
});
|
||||
|
||||
const openCreation = useCallback(() => {
|
||||
pushAppHistoryPath('/creation');
|
||||
setSelectionStage('creation-home', { path: '/creation' });
|
||||
}, [setSelectionStage]);
|
||||
|
||||
const openProjects = useCallback(() => {
|
||||
pushAppHistoryPath('/project');
|
||||
setSelectionStage('project', { path: '/project' });
|
||||
}, [setSelectionStage]);
|
||||
|
||||
const openEditorProject = useCallback(
|
||||
(projectId: string, options?: { guide?: boolean }) => {
|
||||
(projectId: string, options?: { guide?: boolean; tool?: string }) => {
|
||||
const params = new URLSearchParams();
|
||||
params.set('projectid', projectId);
|
||||
if (options?.guide) {
|
||||
params.set('guide', 'toolbar');
|
||||
}
|
||||
if (options?.tool) {
|
||||
params.set('tool', options.tool);
|
||||
}
|
||||
const path = `/editor/canvas?${params.toString()}`;
|
||||
pushAppHistoryPath(path);
|
||||
setSelectionStage('image-editor', { path });
|
||||
@@ -118,76 +215,121 @@ export function PlatformEntryFlowShellImpl({
|
||||
profileCenter.rechargeCenter?.walletBalance ??
|
||||
dashboard?.walletBalance ??
|
||||
null;
|
||||
const isCreationStage =
|
||||
selectionStage === 'platform' || selectionStage === 'creation-home';
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex h-full min-h-0 min-w-0 flex-col overflow-hidden">
|
||||
<header className="flex min-h-16 shrink-0 items-center justify-between gap-3 border-b border-[var(--platform-subpanel-border)] px-4 sm:px-6">
|
||||
<button
|
||||
type="button"
|
||||
className="flex min-w-0 items-center gap-3 text-left"
|
||||
onClick={openProjects}
|
||||
>
|
||||
<span className="flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-[var(--platform-accent-strong)] text-white">
|
||||
<FolderKanban className="h-5 w-5" aria-hidden="true" />
|
||||
</span>
|
||||
<span className="truncate text-base font-black text-[var(--platform-text-strong)]">
|
||||
陶泥儿项目
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<div className="flex shrink-0 items-center gap-2">
|
||||
{isAuthenticated ? (
|
||||
<PlatformMudPointWalletEntry
|
||||
variant="desktop"
|
||||
balance={balance}
|
||||
breakdown={
|
||||
profileCenter.rechargeCenter?.mudPointBalance ?? null
|
||||
}
|
||||
isLoading={
|
||||
isLoadingDashboard || profileCenter.isLoadingRechargeCenter
|
||||
}
|
||||
error={profileCenter.rechargeError}
|
||||
onRequestDetails={profileCenter.loadRechargeCenter}
|
||||
onRecharge={() => {
|
||||
profileCenter.setIsRechargeOpen(true);
|
||||
profileCenter.loadRechargeCenter();
|
||||
}}
|
||||
onOpenLedger={profileCenter.openWalletLedgerPanel}
|
||||
/>
|
||||
) : (
|
||||
<PlatformActionButton
|
||||
size="xs"
|
||||
onClick={() => authUi?.openLoginModal()}
|
||||
<div
|
||||
className={`flex h-full min-h-0 min-w-0 flex-col overflow-hidden ${isCreationStage ? 'creation-home-stage--landing' : ''}`}
|
||||
>
|
||||
<div className="platform-desktop-shell platform-desktop-shell--workbench flex h-full min-h-0 flex-col">
|
||||
<div className="platform-desktop-layout flex min-h-0 flex-1">
|
||||
<aside className="platform-desktop-leftbar hidden shrink-0 flex-col lg:flex">
|
||||
<ActivePlatformBrand />
|
||||
<nav
|
||||
className="platform-desktop-rail flex shrink-0 flex-col gap-3"
|
||||
aria-label="平台导航"
|
||||
>
|
||||
<LogIn className="h-4 w-4" aria-hidden="true" />
|
||||
登录
|
||||
</PlatformActionButton>
|
||||
)}
|
||||
<PlatformIconButton
|
||||
label={isAuthenticated ? '账号' : '登录'}
|
||||
icon={<UserRound className="h-5 w-5" aria-hidden="true" />}
|
||||
onClick={() => {
|
||||
if (isAuthenticated) {
|
||||
authUi?.openAccountModal();
|
||||
return;
|
||||
}
|
||||
authUi?.openLoginModal();
|
||||
}}
|
||||
/>
|
||||
<PlatformIconButton
|
||||
label="设置"
|
||||
icon={<Settings className="h-5 w-5" aria-hidden="true" />}
|
||||
onClick={() => authUi?.openSettingsModal()}
|
||||
/>
|
||||
</div>
|
||||
</header>
|
||||
<ActiveRailButton
|
||||
active={isCreationStage}
|
||||
emphasized={isCreationStage}
|
||||
icon={Palette}
|
||||
iconSrc="/creation-home/nav-create.png"
|
||||
label="创作"
|
||||
onClick={openCreation}
|
||||
/>
|
||||
<ActiveRailButton
|
||||
active={selectionStage === 'project'}
|
||||
icon={FolderKanban}
|
||||
iconSrc="/creation-home/nav-projects.png"
|
||||
label="项目"
|
||||
onClick={openProjects}
|
||||
/>
|
||||
</nav>
|
||||
</aside>
|
||||
|
||||
<main className="min-h-0 min-w-0 flex-1 overflow-auto px-3 py-4 sm:px-6 sm:py-6">
|
||||
<Suspense fallback={<LoadingPanel label="正在加载项目..." />}>
|
||||
<ProjectGalleryView onOpenProject={openEditorProject} />
|
||||
</Suspense>
|
||||
</main>
|
||||
<div className="platform-desktop-main flex min-w-0 flex-1 flex-col">
|
||||
<header className="platform-desktop-topbar flex min-h-16 shrink-0 items-center justify-between gap-3 px-4 sm:px-6">
|
||||
<div className="min-w-0 lg:hidden">
|
||||
<ActivePlatformBrand />
|
||||
</div>
|
||||
<span className="hidden truncate text-base font-black text-[var(--platform-text-strong)] lg:block">
|
||||
{isCreationStage ? '创作工具' : '项目'}
|
||||
</span>
|
||||
|
||||
<div className="platform-desktop-topbar__actions flex shrink-0 items-center gap-2">
|
||||
{isAuthenticated ? (
|
||||
<PlatformMudPointWalletEntry
|
||||
variant="desktop"
|
||||
balance={balance}
|
||||
breakdown={
|
||||
profileCenter.rechargeCenter?.mudPointBalance ?? null
|
||||
}
|
||||
isLoading={
|
||||
isLoadingDashboard ||
|
||||
profileCenter.isLoadingRechargeCenter
|
||||
}
|
||||
error={profileCenter.rechargeError}
|
||||
onRequestDetails={profileCenter.loadRechargeCenter}
|
||||
onRecharge={() => {
|
||||
profileCenter.setIsRechargeOpen(true);
|
||||
profileCenter.loadRechargeCenter();
|
||||
}}
|
||||
onOpenLedger={profileCenter.openWalletLedgerPanel}
|
||||
/>
|
||||
) : (
|
||||
<PlatformActionButton
|
||||
size="xs"
|
||||
onClick={() => authUi?.openLoginModal()}
|
||||
>
|
||||
<LogIn className="h-4 w-4" aria-hidden="true" />
|
||||
登录
|
||||
</PlatformActionButton>
|
||||
)}
|
||||
<PlatformIconButton
|
||||
label={isAuthenticated ? '账号' : '登录'}
|
||||
icon={
|
||||
<UserRound className="h-5 w-5" aria-hidden="true" />
|
||||
}
|
||||
onClick={() => {
|
||||
if (isAuthenticated) {
|
||||
authUi?.openAccountModal();
|
||||
return;
|
||||
}
|
||||
authUi?.openLoginModal();
|
||||
}}
|
||||
/>
|
||||
<PlatformIconButton
|
||||
label="设置"
|
||||
icon={<Settings className="h-5 w-5" aria-hidden="true" />}
|
||||
onClick={() => authUi?.openSettingsModal()}
|
||||
/>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main
|
||||
id={isCreationStage ? 'platform-tab-panel-create' : undefined}
|
||||
className={`platform-tab-panel min-h-0 min-w-0 flex-1 overflow-auto ${isCreationStage ? '' : 'px-3 py-4 sm:px-6 sm:py-6'}`}
|
||||
>
|
||||
{isCreationStage ? (
|
||||
<Suspense
|
||||
fallback={<LoadingPanel label="正在加载创作主页..." />}
|
||||
>
|
||||
<CreationLandingView
|
||||
onOpenProject={openEditorProject}
|
||||
onOpenProjects={openProjects}
|
||||
/>
|
||||
</Suspense>
|
||||
) : (
|
||||
<Suspense fallback={<LoadingPanel label="正在加载项目..." />}>
|
||||
<ProjectGalleryView onOpenProject={openEditorProject} />
|
||||
</Suspense>
|
||||
)}
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{profileCenter.isRechargeOpen ? (
|
||||
|
||||
@@ -8,7 +8,7 @@ export type { PlatformEntryFlowShellProps, SelectionStage };
|
||||
|
||||
/**
|
||||
* 平台入口通用壳层。
|
||||
* 平台运行入口只承载项目、编辑器与账户公共能力。
|
||||
* 平台运行入口承载新创作主页、项目、编辑器与账户公共能力。
|
||||
*/
|
||||
export function PlatformEntryFlowShell(props: PlatformEntryFlowShellProps) {
|
||||
return <PlatformEntryFlowShellImpl {...props} />;
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
export type SelectionStage = 'platform' | 'project' | 'image-editor';
|
||||
export type SelectionStage =
|
||||
| 'platform'
|
||||
| 'creation-home'
|
||||
| 'project'
|
||||
| 'image-editor';
|
||||
|
||||
export type PlatformEntryFlowShellProps = {
|
||||
selectionStage: SelectionStage;
|
||||
|
||||
@@ -14,17 +14,19 @@ import {
|
||||
} from './activeAppPageRoutes';
|
||||
|
||||
describe('appPageRoutes', () => {
|
||||
it('only resolves public platform, project, and editor stages', () => {
|
||||
it('resolves the active creation, project, and editor stages', () => {
|
||||
expect(resolveSelectionStageFromPath('/')).toBe('platform');
|
||||
expect(resolveSelectionStageFromPath('/creation')).toBe('creation-home');
|
||||
expect(resolveSelectionStageFromPath('/project')).toBe('project');
|
||||
expect(resolveSelectionStageFromPath('/EDITOR/CANVAS/')).toBe(
|
||||
'image-editor',
|
||||
);
|
||||
expect(resolveSelectionStageFromPath('/creation')).toBe('platform');
|
||||
expect(resolveSelectionStageFromPath('/creation/rpg')).toBe('platform');
|
||||
expect(resolveSelectionStageFromPath('/runtime/puzzle')).toBe('platform');
|
||||
expect(isKnownMainAppPagePath('/creation')).toBe(true);
|
||||
expect(isKnownMainAppPagePath('/creation/rpg')).toBe(false);
|
||||
expect(isKnownMainAppPagePath('/runtime/puzzle')).toBe(false);
|
||||
expect(resolvePathForSelectionStage('creation-home')).toBe('/creation');
|
||||
expect(resolvePathForSelectionStage('project')).toBe('/project');
|
||||
});
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ export const EDITOR_CANVAS_PROJECT_ID_QUERY_PARAM = 'projectid';
|
||||
|
||||
const STAGE_ROUTE_ENTRIES = [
|
||||
['platform', '/'],
|
||||
['creation-home', '/creation'],
|
||||
['project', '/project'],
|
||||
['image-editor', '/editor/canvas'],
|
||||
] as const satisfies readonly (readonly [SelectionStage, string])[];
|
||||
|
||||
@@ -24,6 +24,9 @@ afterEach(() => {
|
||||
describe('activeAppTitle', () => {
|
||||
test('maps only active platform stages', () => {
|
||||
expect(resolveAppTitleForSelectionStage('platform')).toBe(APP_HOME_TITLE);
|
||||
expect(resolveAppTitleForSelectionStage('creation-home')).toBe(
|
||||
APP_HOME_TITLE,
|
||||
);
|
||||
expect(resolveAppTitleForSelectionStage('project')).toBe('项目 - 陶泥儿');
|
||||
expect(resolveAppTitleForSelectionStage('image-editor')).toBe(
|
||||
'美术编辑器 - 陶泥儿',
|
||||
|
||||
@@ -7,6 +7,7 @@ export const APP_HOME_TITLE =
|
||||
|
||||
const APP_TITLE_BY_SELECTION_STAGE: Record<SelectionStage, string> = {
|
||||
platform: APP_HOME_TITLE,
|
||||
'creation-home': APP_HOME_TITLE,
|
||||
project: '项目 - 陶泥儿',
|
||||
'image-editor': '美术编辑器 - 陶泥儿',
|
||||
};
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
"src/services/activeAppTitle.test.ts",
|
||||
"src/components/auth/**/*.test.ts",
|
||||
"src/components/auth/**/*.test.tsx",
|
||||
"src/components/creation-home/**/*.test.ts",
|
||||
"src/components/creation-home/**/*.test.tsx",
|
||||
"src/components/image-editor/**/*.test.ts",
|
||||
"src/components/image-editor/**/*.test.tsx",
|
||||
"src/components/project/**/*.test.ts",
|
||||
|
||||
+3
-4
@@ -7,7 +7,7 @@ import postcss from 'postcss';
|
||||
import { defineConfig, loadEnv, type Plugin } from 'vite';
|
||||
|
||||
const RETIRED_TEMPLATE_CSS_PATTERN =
|
||||
/(?:baby-object|bark-battle|big-fish|child-motion|creation-(?:agent|home|landing|work)|creative-agent|custom-world|jump-hop|match3d|platform-recommend|platform-work-detail|public-work|puzzle|rpg|square-hole|unified-creation|visual-novel|wooden-fish)/iu;
|
||||
/(?:baby-object|bark-battle|big-fish|child-motion|creation-(?:agent|work)|creative-agent|custom-world|jump-hop|match3d|platform-recommend|platform-work-detail|public-work|puzzle|rpg|square-hole|unified-creation|visual-novel|wooden-fish)/iu;
|
||||
|
||||
const ACTIVE_TAILWIND_SOURCES = `@import 'tailwindcss' source(none);
|
||||
@source "./active-main.tsx";
|
||||
@@ -15,6 +15,7 @@ const ACTIVE_TAILWIND_SOURCES = `@import 'tailwindcss' source(none);
|
||||
@source "./AuthenticatedApp.tsx";
|
||||
@source "./components/auth";
|
||||
@source "./components/common";
|
||||
@source "./components/creation-home";
|
||||
@source "./components/image-editor";
|
||||
@source "./components/project";
|
||||
@source "./components/platform-entry/PlatformEntryFlowShell.tsx";
|
||||
@@ -33,7 +34,6 @@ const RETIRED_PUBLIC_ASSET_PATHS = [
|
||||
'/bark-battle-assets',
|
||||
'/character',
|
||||
'/child-motion-demo',
|
||||
'/creation-home',
|
||||
'/creation-type-references',
|
||||
'/edutainment-baby-object',
|
||||
'/generated-character-drafts',
|
||||
@@ -165,7 +165,6 @@ export default defineConfig(({ mode }) => {
|
||||
'**/public/anthro-cat-illustrations/**',
|
||||
'**/public/bark-battle-assets/**',
|
||||
'**/public/character/**',
|
||||
'**/public/creation-home/**',
|
||||
'**/public/creation-type-references/**',
|
||||
'**/public/edutainment-baby-object/**',
|
||||
'**/public/match3d-background-references/**',
|
||||
@@ -177,7 +176,7 @@ export default defineConfig(({ mode }) => {
|
||||
'**/src/components/asset-studio/**',
|
||||
'**/src/components/bark-battle-creation/**',
|
||||
'**/src/components/big-fish-*/**',
|
||||
'**/src/components/creation-*/**',
|
||||
'**/src/components/creation-agent/**',
|
||||
'**/src/components/creative-agent/**',
|
||||
'**/src/components/custom-world-*/**',
|
||||
'**/src/components/edutainment-*/**',
|
||||
|
||||
@@ -26,6 +26,8 @@ export default defineConfig({
|
||||
'src/services/payment/**/*.test.ts',
|
||||
'src/components/auth/**/*.test.ts',
|
||||
'src/components/auth/**/*.test.tsx',
|
||||
'src/components/creation-home/**/*.test.ts',
|
||||
'src/components/creation-home/**/*.test.tsx',
|
||||
'src/components/image-editor/**/*.test.ts',
|
||||
'src/components/image-editor/**/*.test.tsx',
|
||||
'src/components/project/**/*.test.ts',
|
||||
|
||||
Reference in New Issue
Block a user