2f8753f597
- 契约层把 ProjectResourceCanvasPosition.section 加宽为 PersistedProjectResourceCanvasSection 并删除旧 ProjectResourceCanvasSection 联合 - 七个分区类型消费点改用 ProjectResourceCanvasCategory:投影、布局模型、布局 Hook、分区高度、依赖图层与画布历史 - RESOURCE_CANVAS_SECTION_ORDER 改为 PROJECT_RESOURCE_CANVAS_SECTIONS,删除 RESOURCE_CANVAS_VISIBLE_SECTION_ORDER - reconcileResourceCanvasLayout 接入读时归一化:旧栏目值按资源当前分区改写 section,坐标与手动标记原样保留 - 归并后的布局与原布局逐项不同,由既有协调路径判定 changed 并写回一次新分区,不引入迁移脚本 - 投影层五个资源入表点统一走 projectResourceCanvasCategory:项目版本独立成栏、Agent 回执归文档、其余按资产分类 - 新增 projectResourceDisplayKind 收敛 manifest 资产 subtype 即 kind 的显示类型口径,projectResourceTypeLabel 不再依赖旧栏目 - 卡片预览、编辑分流、媒体工具条、预览文案与画布历史快照改用显示类型与新分区,历史快照入栈时收窄到现行分区 - index.tsx 删除可见栏目导入与 visibleCategoryOrder,栏目标签由资源筛选唯一中文口径派生并补齐 7 栏 - index.tsx 补齐 7 栏默认视口与 7 个栏目图标(新增 LayoutGrid、Users、PackageOpen,移除已无用的 Code2) - index.tsx 删除 canvasResources 的 code 过滤:只登记游戏代码的项目现在落在待归类栏目并正常显示卡片 - 新增只登记游戏代码项目的 UI 回归用例,覆盖栏目大纲、默认落地栏目与代码卡片渲染 - 测试夹具按新分区轴迁移,新增旧栏目 sidecar 读时归并用例与栏目顺序用例 - 共享测试 harness 的资源卡查询正则允许栏目标签自带空格(UI 交互) - 同步 PRD 与共享记忆决策记录的栏目口径描述
123 lines
3.5 KiB
TypeScript
123 lines
3.5 KiB
TypeScript
import type {
|
|
ProjectResourceCanvasCategory,
|
|
ProjectResourceCanvasLayoutMode,
|
|
} from '../../../../../packages/shared/src/contracts/gameCreationApp';
|
|
import { RESOURCE_CANVAS_CARD_HEIGHT } from './resourceCanvasLayoutModel';
|
|
|
|
export const RESOURCE_SECTION_HEIGHT_STEP = 72;
|
|
export const RESOURCE_SECTION_MIN_HEIGHT = RESOURCE_CANVAS_CARD_HEIGHT + 88;
|
|
export const RESOURCE_SECTION_DEFAULT_HEIGHT = 340;
|
|
export const RESOURCE_SECTION_FALLBACK_MAX_HEIGHT = 640;
|
|
export const RESOURCE_CANVAS_VERTICAL_INSET = 24;
|
|
export const RESOURCE_SECTION_ZOOM_MIN = 0.5;
|
|
export const RESOURCE_SECTION_ZOOM_MAX = 2;
|
|
export const RESOURCE_SECTION_ZOOM_DEFAULT = 1;
|
|
export const RESOURCE_SECTION_ZOOM_STEP = 0.1;
|
|
|
|
export type ProjectResourceSectionHeightBounds = {
|
|
min: number;
|
|
max: number;
|
|
};
|
|
|
|
export type ProjectResourceSectionHeightAction =
|
|
| 'decrease'
|
|
| 'increase'
|
|
| 'reset';
|
|
|
|
export type ProjectResourceSectionZoomAction =
|
|
| 'decrease'
|
|
| 'increase'
|
|
| 'reset';
|
|
|
|
export function projectResourceSectionHeightKey(input: {
|
|
projectId: string;
|
|
mode: ProjectResourceCanvasLayoutMode;
|
|
section: ProjectResourceCanvasCategory;
|
|
}) {
|
|
return `${input.projectId}\n${input.mode}\n${input.section}`;
|
|
}
|
|
|
|
export function projectResourceSectionHeightBounds(
|
|
canvasClientHeight: number,
|
|
): ProjectResourceSectionHeightBounds {
|
|
const availableHeight =
|
|
Number.isFinite(canvasClientHeight) && canvasClientHeight > 0
|
|
? Math.floor(canvasClientHeight) - RESOURCE_CANVAS_VERTICAL_INSET
|
|
: RESOURCE_SECTION_FALLBACK_MAX_HEIGHT;
|
|
return {
|
|
min: RESOURCE_SECTION_MIN_HEIGHT,
|
|
max: Math.max(RESOURCE_SECTION_MIN_HEIGHT, availableHeight),
|
|
};
|
|
}
|
|
|
|
export function clampProjectResourceSectionHeight(
|
|
height: number,
|
|
bounds: ProjectResourceSectionHeightBounds,
|
|
) {
|
|
const normalized = Number.isFinite(height)
|
|
? Math.round(height)
|
|
: RESOURCE_SECTION_DEFAULT_HEIGHT;
|
|
return Math.min(bounds.max, Math.max(bounds.min, normalized));
|
|
}
|
|
|
|
export function defaultProjectResourceSectionHeight(
|
|
bounds: ProjectResourceSectionHeightBounds,
|
|
) {
|
|
return clampProjectResourceSectionHeight(
|
|
RESOURCE_SECTION_DEFAULT_HEIGHT,
|
|
bounds,
|
|
);
|
|
}
|
|
|
|
export function updateProjectResourceSectionHeight(
|
|
currentHeight: number,
|
|
action: ProjectResourceSectionHeightAction,
|
|
bounds: ProjectResourceSectionHeightBounds,
|
|
) {
|
|
if (action === 'reset') {
|
|
return defaultProjectResourceSectionHeight(bounds);
|
|
}
|
|
const delta =
|
|
action === 'increase'
|
|
? RESOURCE_SECTION_HEIGHT_STEP
|
|
: -RESOURCE_SECTION_HEIGHT_STEP;
|
|
return clampProjectResourceSectionHeight(currentHeight + delta, bounds);
|
|
}
|
|
|
|
export function clampProjectResourceSectionZoom(zoom: number) {
|
|
const normalized = Number.isFinite(zoom)
|
|
? Math.round(zoom * 100) / 100
|
|
: RESOURCE_SECTION_ZOOM_DEFAULT;
|
|
return Math.min(
|
|
RESOURCE_SECTION_ZOOM_MAX,
|
|
Math.max(RESOURCE_SECTION_ZOOM_MIN, normalized),
|
|
);
|
|
}
|
|
|
|
export function updateProjectResourceSectionZoom(
|
|
currentZoom: number,
|
|
action: ProjectResourceSectionZoomAction,
|
|
) {
|
|
if (action === 'reset') {
|
|
return RESOURCE_SECTION_ZOOM_DEFAULT;
|
|
}
|
|
return clampProjectResourceSectionZoom(
|
|
currentZoom +
|
|
(action === 'increase'
|
|
? RESOURCE_SECTION_ZOOM_STEP
|
|
: -RESOURCE_SECTION_ZOOM_STEP),
|
|
);
|
|
}
|
|
|
|
export function projectResourceSectionZoomFromWheel(
|
|
currentZoom: number,
|
|
deltaY: number,
|
|
) {
|
|
if (!Number.isFinite(deltaY) || deltaY === 0) {
|
|
return clampProjectResourceSectionZoom(currentZoom);
|
|
}
|
|
return clampProjectResourceSectionZoom(
|
|
currentZoom * Math.exp(-deltaY * 0.0025),
|
|
);
|
|
}
|