feat: publish admin sticker releases (TASK-WP5-05)
Dada P0-A isolated Windows CI / validate-and-package (push) Failing after 30s

This commit is contained in:
suyx
2026-08-03 19:43:10 +08:00
parent f1bebab611
commit c92a91a127
21 changed files with 1755 additions and 18 deletions
+20 -7
View File
@@ -49,7 +49,7 @@ import {
type DynamicTemplateId,
} from "./dynamic-provider.js";
import { dynamicFontOptionsFor } from "./dynamic-render-models.js";
import { P0A_STATIC_STICKER_CATALOG, P0A_STATIC_STICKER_COUNT, stickerWindow } from "./static-sticker-catalog.js";
import { P0A_STATIC_STICKER_CATALOG, stickerWindow, type StaticStickerCatalogItem } from "./static-sticker-catalog.js";
import {
createColorCardElement,
extractPaletteFromImage,
@@ -136,6 +136,7 @@ export function EditorPage({ projectId }: { projectId: string }) {
const [notice, setNotice] = useState("");
const [activePanel, setActivePanel] = useState<EditorAssetPanel>("background");
const [stickerScrollTop, setStickerScrollTop] = useState(0);
const [stickerCatalog, setStickerCatalog] = useState<StaticStickerCatalogItem[]>(P0A_STATIC_STICKER_CATALOG);
const [selectedIds, setSelectedIds] = useState<string[]>([]);
const [guides, setGuides] = useState<string[]>([]);
const [multiMode, setMultiMode] = useState(false);
@@ -187,6 +188,18 @@ export function EditorPage({ projectId }: { projectId: string }) {
return () => { active = false; };
}, [session?.user.user_id]);
useEffect(() => {
let active = true;
readEditorJson<{ items: StaticStickerCatalogItem[] }>("/api/v1/static-stickers/current")
.then((response) => {
if (!active) return;
const uploaded = response.items.filter((item) => item.enabled && item.origin === "admin_uploaded");
setStickerCatalog([...P0A_STATIC_STICKER_CATALOG, ...uploaded].sort((left, right) => left.part - right.part || left.order - right.order || left.stable_id.localeCompare(right.stable_id)));
})
.catch(() => { if (active) setStickerCatalog(P0A_STATIC_STICKER_CATALOG); });
return () => { active = false; };
}, []);
useEffect(() => {
if (!project || !session || !canvasState) return undefined;
const queue = new ProjectAutoSaveQueue({
@@ -343,15 +356,15 @@ export function EditorPage({ projectId }: { projectId: string }) {
setNotice(message);
}
function addSticker(assetId: string) {
function addSticker(sticker: StaticStickerCatalogItem) {
const controller = controllerForCurrent();
if (!controller || !canvasState) return;
try {
controller.add(createStaticStickerElement({
assetId,
assetId: sticker.stable_id,
identity: newElementIdentity(),
position: { x: 0.5, y: 0.5 },
resourceVersion: "fixture-v1",
resourceVersion: sticker.resource_version,
zIndex: canvasState.elements.length,
}));
commitElementOperation(controller, "贴纸已加入画布");
@@ -832,11 +845,11 @@ export function EditorPage({ projectId }: { projectId: string }) {
{...(templateCategory ? { category: templateCategory } : {})}
/> : null}
{activePanel === "stickers" ? (() => {
const visibleStickers = stickerWindow(P0A_STATIC_STICKER_CATALOG, stickerScrollTop, 280);
return <section><h2></h2><p aria-live="polite" className="editor-sticker-count"> {P0A_STATIC_STICKER_COUNT.toLocaleString("zh-CN")} </p><div className="editor-sticker-virtual-list" data-testid="static-sticker-list" onScroll={(event) => setStickerScrollTop(event.currentTarget.scrollTop)} role="list">
const visibleStickers = stickerWindow(stickerCatalog, stickerScrollTop, 280);
return <section><h2></h2><p aria-live="polite" className="editor-sticker-count"> {stickerCatalog.length.toLocaleString("zh-CN")} </p><div className="editor-sticker-virtual-list" data-testid="static-sticker-list" onScroll={(event) => setStickerScrollTop(event.currentTarget.scrollTop)} role="list">
<div style={{ paddingTop: visibleStickers.top_spacer_px, paddingBottom: visibleStickers.bottom_spacer_px }}>
<div className="editor-sticker-grid">
{visibleStickers.items.map((sticker) => <button aria-label={`添加贴纸 ${sticker.stable_id}`} data-sticker-id={sticker.stable_id} disabled={!canEdit || canvasState.elements.length >= 50} key={sticker.stable_id} onClick={() => addSticker(sticker.stable_id)} type="button"><img alt="" className="editor-sticker-preview" decoding="async" loading="lazy" src={sticker.thumbnail_reference.url} /><strong>{sticker.stable_id}</strong><span>part{sticker.part} · {sticker.order}</span></button>)}
{visibleStickers.items.map((sticker) => <button aria-label={`添加贴纸 ${sticker.stable_id}`} data-sticker-id={sticker.stable_id} disabled={!canEdit || canvasState.elements.length >= 50} key={sticker.stable_id} onClick={() => addSticker(sticker)} type="button"><img alt="" className="editor-sticker-preview" decoding="async" loading="lazy" src={sticker.thumbnail_reference.url} /><strong>{sticker.stable_id}</strong><span>part{sticker.part} · {sticker.order}</span></button>)}
</div>
</div>
</div>{canvasState.elements.length >= 50 ? <p className="editor-limit" role="status"> 50 </p> : null}</section>;