Files
wordcloud-board/src/pages/PublicDisplayPage.tsx
T
broccoli 293e346f0a
Build, Push and Deploy / build (push) Successful in 7s
Build, Push and Deploy / deploy (push) Successful in 18s
Add product source job resolver
2026-09-13 18:00:35 +08:00

89 lines
2.7 KiB
TypeScript

import { useCallback, useEffect } from 'react';
import { CloudHeader } from '../components/CloudHeader';
import { FullscreenButton } from '../components/FullscreenButton';
import { QRPanel } from '../components/QRPanel';
import { WordCloudCanvas } from '../components/WordCloudCanvas';
import { CloudLoadingState } from '../components/CloudLoadingState';
import { CloudUnavailableState } from '../components/CloudUnavailableState';
import { useFocusQueue } from '../hooks/useFocusQueue';
import { useCloud } from '../hooks/useCloud';
import { useWordCloudChannel } from '../hooks/useWordCloudChannel';
import { useWordCloudFocus } from '../hooks/useWordCloudFocus';
import { TitleFrost } from '../components/TitleFrost';
import type { FocusEvent } from '../types/channel';
import styles from './PublicDisplayPage.module.css';
interface PublicDisplayPageProps {
productId: string;
}
export function PublicDisplayPage({ productId }: PublicDisplayPageProps) {
const cloudState = useCloud(productId);
const cloud = cloudState.cloud;
const queue = useFocusQueue();
const focus = useWordCloudFocus({
words: cloud?.words ?? [],
autoReturn: true,
onComplete: queue.advance,
});
const receiveMessage = useCallback(
(message: FocusEvent) => {
queue.enqueue(message);
},
[queue],
);
useWordCloudChannel(productId, receiveMessage);
useEffect(() => {
if (!queue.current || focus.phase !== 'idle' || !cloud) {
return;
}
const found = focus.focusName(queue.current.name, queue.current.targetIndex ?? 0);
if (!found) {
queue.advance();
}
}, [cloud, focus, queue]);
if (cloudState.status === 'loading') {
return <CloudLoadingState />;
}
if (!cloud) {
return <CloudUnavailableState />;
}
return (
<main className={styles.page} aria-label="大屏展示词云">
<WordCloudCanvas
words={cloud.words}
phase={focus.phase}
transform={focus.transform}
activeIds={focus.activeIds}
cloudRef={focus.cloudRef}
onPointerDown={focus.handlePointerDown}
onPointerMove={focus.handlePointerMove}
onPointerUp={focus.handlePointerUp}
onWheel={focus.handleWheel}
onKeyDown={focus.handleKeyDown}
sourceCanvas={cloud.sourceCanvas}
sourceSvg={cloud.sourceSvg}
viewport={focus.viewport}
/>
<TitleFrost />
<CloudHeader
eyebrow={cloud.eyebrow}
title={cloud.title}
subtitle={cloud.subtitle}
dimmed={focus.phase !== 'idle'}
layered
/>
<p className={styles.caption}>{cloud.caption}</p>
<QRPanel productId={productId} />
<FullscreenButton />
</main>
);
}