feat(P4B.T6): composer 'Whiteboard' button creates board + sends bubble
This commit is contained in:
@@ -42,7 +42,13 @@ import type { DecryptedMessage } from '@chat-app/shared/chat';
|
||||
import { useAuth } from '../context/AuthContext';
|
||||
import { useCall } from '../context/CallContext';
|
||||
import { useConversationsContext } from '../context/ConversationsContext';
|
||||
import { collectConversationAttachments, createPollPayload } from '../lib/conversationFeatures';
|
||||
import {
|
||||
collectConversationAttachments,
|
||||
createPollPayload,
|
||||
createWhiteboardPayload,
|
||||
} from '../lib/conversationFeatures';
|
||||
import { WhiteboardModal } from '../components/WhiteboardModal';
|
||||
import { createWhiteboard } from '@chat-app/shared/chat';
|
||||
import { compressImages } from '../lib/imageCompress';
|
||||
import { ensureInstallId } from '../lib/installId';
|
||||
import { searchCachedMessages } from '../lib/messageCache';
|
||||
@@ -161,6 +167,8 @@ export function ConversationPage() {
|
||||
const [mediaDrawerOpen, setMediaDrawerOpen] = useState(false);
|
||||
const [pollDialogOpen, setPollDialogOpen] = useState(false);
|
||||
const [pollSending, setPollSending] = useState(false);
|
||||
const [openWhiteboardId, setOpenWhiteboardId] = useState<string | null>(null);
|
||||
const [creatingWhiteboard, setCreatingWhiteboard] = useState(false);
|
||||
const [pollError, setPollError] = useState<string | null>(null);
|
||||
const [replyTo, setReplyTo] = useState<DecryptedMessage | null>(null);
|
||||
const [forwardTarget, setForwardTarget] = useState<DecryptedMessage | null>(null);
|
||||
@@ -588,6 +596,23 @@ export function ConversationPage() {
|
||||
[send, replyTo?.id, notifyStopTyping],
|
||||
);
|
||||
|
||||
const handleCreateWhiteboard = useCallback(async () => {
|
||||
if (!id || creatingWhiteboard) return;
|
||||
setCreatingWhiteboard(true);
|
||||
try {
|
||||
const board = await createWhiteboard(supabase, id);
|
||||
const payload = createWhiteboardPayload(board.id);
|
||||
await send(payload, [], replyTo?.id ?? null);
|
||||
setReplyTo(null);
|
||||
setStickToBottom(true);
|
||||
setOpenWhiteboardId(board.id);
|
||||
} catch (err: unknown) {
|
||||
setSendError(err instanceof Error ? err.message : 'Whiteboard konnte nicht angelegt werden');
|
||||
} finally {
|
||||
setCreatingWhiteboard(false);
|
||||
}
|
||||
}, [id, creatingWhiteboard, send, replyTo?.id]);
|
||||
|
||||
async function ingestFiles(files: File[]) {
|
||||
const compressed = await compressImages(files);
|
||||
const next: File[] = [];
|
||||
@@ -981,6 +1006,16 @@ export function ConversationPage() {
|
||||
>
|
||||
<PollIcon className="h-4 w-4" />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => void handleCreateWhiteboard()}
|
||||
disabled={creatingWhiteboard}
|
||||
title={t('app:composer.whiteboard', { defaultValue: 'Whiteboard' })}
|
||||
aria-label={t('app:composer.whiteboard', { defaultValue: 'Whiteboard' })}
|
||||
className="inline-flex h-10 w-10 shrink-0 cursor-pointer items-center justify-center rounded-lg text-fg-muted transition hover:bg-surface-3 hover:text-fg focus:outline-none focus-visible:ring-2 focus-visible:ring-accent/50 disabled:cursor-not-allowed disabled:opacity-50 dark:hover:bg-[#313338]"
|
||||
>
|
||||
<WhiteboardIcon className="h-4 w-4" />
|
||||
</button>
|
||||
<div className="relative">
|
||||
<button
|
||||
type="button"
|
||||
@@ -1180,6 +1215,13 @@ export function ConversationPage() {
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{openWhiteboardId && (
|
||||
<WhiteboardModal
|
||||
whiteboardId={openWhiteboardId}
|
||||
onClose={() => setOpenWhiteboardId(null)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1459,3 +1501,13 @@ function AttachmentPreview({
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function WhiteboardIcon(props: React.SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2}
|
||||
strokeLinecap="round" strokeLinejoin="round" {...props}>
|
||||
<rect x="3" y="4" width="18" height="13" rx="2" />
|
||||
<path d="M8 21h8M12 17v4" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user