InboxZone: a PixiJS Container positioned at (-500,-500) with a
dashed border and "Inbox" label. Auto-synced media slides in with spring animations and random offset/rotation for a natural look. MattermostImport: modal dialog for pulling images from a MM thread URL and managing linked channels for auto-sync. Uses the existing dark modal styling pattern from ShortcutsHelp. Editor wiring: toolbar button for MM import, InboxZone added to viewport on init, socket listener for board:media-arrived events that routes assets into the InboxZone with a toast notification.
This commit is contained in:
@@ -21,6 +21,8 @@ import UserCursors from '../components/UserCursors';
|
||||
import ContextMenu from '../components/ContextMenu';
|
||||
import LayerPanel from '../components/LayerPanel';
|
||||
import ShortcutsHelp from '../components/ShortcutsHelp';
|
||||
import MattermostImport from '../components/MattermostImport';
|
||||
import { InboxZone } from '../canvas/InboxZone';
|
||||
|
||||
// Pre-sort shortcuts by specificity (most modifiers first) for correct matching
|
||||
const sortedShortcuts = sortBySpecificity(shortcutDefs);
|
||||
@@ -82,9 +84,11 @@ export default function Editor({ isPublicView }: EditorProps) {
|
||||
const [showLayers, setShowLayers] = useState(false);
|
||||
const [showGrid, setShowGrid] = useState(false);
|
||||
const [showHelp, setShowHelp] = useState(false);
|
||||
const [showMmImport, setShowMmImport] = useState(false);
|
||||
const [layerList, setLayerList] = useState<any[]>([]);
|
||||
const [selectedLayerIds, setSelectedLayerIds] = useState<string[]>([]);
|
||||
const clipboardRef = useRef<SceneItem[]>([]);
|
||||
const inboxZoneRef = useRef<InboxZone | null>(null);
|
||||
|
||||
const resolvedBoardId = boardId || boardData?.board?.id;
|
||||
|
||||
@@ -238,6 +242,11 @@ export default function Editor({ isPublicView }: EditorProps) {
|
||||
// Create UndoManager
|
||||
undoRef.current = new UndoManager(scene);
|
||||
|
||||
// Create InboxZone and add to viewport
|
||||
const inboxZone = new InboxZone(scene.textures, scene.springs);
|
||||
viewport.addChild(inboxZone);
|
||||
inboxZoneRef.current = inboxZone;
|
||||
|
||||
if (user) {
|
||||
const socket = connectSocket();
|
||||
|
||||
@@ -270,6 +279,15 @@ export default function Editor({ isPublicView }: EditorProps) {
|
||||
}
|
||||
});
|
||||
|
||||
// Listen for auto-synced media arriving via socket
|
||||
socket.on('board:media-arrived', (data: any) => {
|
||||
const assets = data?.assets;
|
||||
if (Array.isArray(assets) && assets.length > 0 && inboxZoneRef.current) {
|
||||
inboxZoneRef.current.addMedia(assets);
|
||||
showToast(`${assets.length} image${assets.length !== 1 ? 's' : ''} arrived in Inbox`);
|
||||
}
|
||||
});
|
||||
|
||||
// Cursor tracking: listen on viewport for pointermove
|
||||
const onPointerMove = (e: any) => {
|
||||
const world = viewport.toWorld(e.global.x, e.global.y);
|
||||
@@ -317,6 +335,11 @@ export default function Editor({ isPublicView }: EditorProps) {
|
||||
clearTimeout(timer);
|
||||
selectionRef.current?.destroy();
|
||||
selectionRef.current = null;
|
||||
if (inboxZoneRef.current) {
|
||||
inboxZoneRef.current.clear();
|
||||
inboxZoneRef.current.destroy({ children: true });
|
||||
inboxZoneRef.current = null;
|
||||
}
|
||||
syncCleanupRef.current?.();
|
||||
dropCleanupRef.current?.();
|
||||
pasteCleanupRef.current?.();
|
||||
@@ -896,6 +919,7 @@ export default function Editor({ isPublicView }: EditorProps) {
|
||||
onToggleLayers={() => setShowLayers((v) => !v)}
|
||||
showLayers={showLayers}
|
||||
onToggleHelp={() => setShowHelp((v) => !v)}
|
||||
onMmImport={() => setShowMmImport(true)}
|
||||
boardName={board?.name}
|
||||
/>
|
||||
|
||||
@@ -1063,6 +1087,19 @@ export default function Editor({ isPublicView }: EditorProps) {
|
||||
{showHelp && (
|
||||
<ShortcutsHelp shortcuts={shortcutDefs} onClose={() => setShowHelp(false)} />
|
||||
)}
|
||||
|
||||
{/* Mattermost import modal */}
|
||||
{showMmImport && resolvedBoardId && (
|
||||
<MattermostImport
|
||||
boardId={resolvedBoardId}
|
||||
onClose={() => setShowMmImport(false)}
|
||||
onMediaArrived={(assets) => {
|
||||
if (inboxZoneRef.current) {
|
||||
inboxZoneRef.current.addMedia(assets);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user