Files
openchamber/packages/ui/src/apps/AppEffects.tsx
T

88 lines
2.7 KiB
TypeScript

import React from 'react';
import { useKeyboardShortcuts } from '@/hooks/useKeyboardShortcuts';
import { usePwaManifestSync } from '@/hooks/usePwaManifestSync';
import { useQueuedMessageAutoSend } from '@/hooks/useQueuedMessageAutoSend';
import { useSessionAutoCleanup } from '@/hooks/useSessionAutoCleanup';
import { useWindowControlsOverlayLayout } from '@/hooks/useWindowControlsOverlayLayout';
import { setOptimisticRefs } from '@/sync/session-actions';
import { markSessionViewed } from '@/sync/notification-store';
import { setExternallyViewedSession } from '@/sync/sync-context';
import { useSync } from '@/sync/use-sync';
const MINI_CHAT_PRESENCE_CHANNEL = 'openchamber:mini-chat-presence';
type MiniChatPresenceMessage = {
type?: string;
sessionId?: string;
directory?: string;
viewed?: boolean;
};
const SyncOptimisticBridge: React.FC = () => {
const sync = useSync();
const addRef = React.useRef(sync.optimistic.add);
const removeRef = React.useRef(sync.optimistic.remove);
const confirmRef = React.useRef(sync.optimistic.confirm);
addRef.current = sync.optimistic.add;
removeRef.current = sync.optimistic.remove;
confirmRef.current = sync.optimistic.confirm;
React.useEffect(() => {
setOptimisticRefs(
(input) => addRef.current(input),
(input) => removeRef.current(input),
(input) => confirmRef.current(input),
);
}, []);
return null;
};
const MiniChatPresenceBridge: React.FC = () => {
React.useEffect(() => {
if (typeof BroadcastChannel === 'undefined') return;
const channel = new BroadcastChannel(MINI_CHAT_PRESENCE_CHANNEL);
channel.onmessage = (event) => {
const data = event.data as MiniChatPresenceMessage | null;
if (data?.type !== 'mini-chat-session-presence' || !data.sessionId || !data.directory) {
return;
}
const viewed = data.viewed !== false;
setExternallyViewedSession(data.directory, data.sessionId, viewed);
if (viewed) {
markSessionViewed(data.sessionId);
}
};
return () => channel.close();
}, []);
return null;
};
export function SyncRuntimeEffects({ embeddedBackgroundWorkEnabled }: {
embeddedBackgroundWorkEnabled: boolean;
}) {
useSessionAutoCleanup(embeddedBackgroundWorkEnabled);
useQueuedMessageAutoSend(embeddedBackgroundWorkEnabled);
return <SyncOptimisticBridge />;
}
export function SyncAppEffects({ embeddedBackgroundWorkEnabled }: {
embeddedBackgroundWorkEnabled: boolean;
}) {
usePwaManifestSync();
useWindowControlsOverlayLayout();
useKeyboardShortcuts();
return (
<>
<SyncRuntimeEffects embeddedBackgroundWorkEnabled={embeddedBackgroundWorkEnabled} />
<MiniChatPresenceBridge />
</>
);
}