feat: integrate Matrix chat (Option 2 - credentials stored in Supabase)

- Add matrix-js-sdk, marked, highlight.js, twemoji, @tanstack/svelte-virtual deps
- Copy Matrix core layer: /matrix/, /stores/matrix.ts, /cache/, /services/
- Copy Matrix components: matrix/, message/, chat-layout/, chat-settings/
- Copy UI components: EmojiPicker, Twemoji, ImagePreviewModal, VirtualList
- Copy utils: emojiData, twemoji, twemojiGlobal
- Replace lucide-svelte with Material Symbols in SyncRecoveryBanner
- Extend Avatar with xs size and status indicator prop
- Fix ui.ts store conflict: re-export toasts from toast.svelte.ts
- Add migration 020_matrix_credentials for storing Matrix tokens per user/org
- Add /api/matrix-credentials endpoint (GET/POST/DELETE)
- Create [orgSlug]/chat page with Matrix login form + full chat UI
- Add Chat to sidebar navigation
This commit is contained in:
AlacrisDevs
2026-02-07 01:44:06 +02:00
parent e55881b38b
commit d1ce5d0951
62 changed files with 11432 additions and 41 deletions

View File

@@ -0,0 +1,63 @@
<script lang="ts">
interface Props {
src: string;
alt?: string;
onClose: () => void;
}
let { src, alt = "", onClose }: Props = $props();
function handleKeyDown(e: KeyboardEvent) {
if (e.key === "Escape") {
onClose();
}
}
function handleBackdropClick(e: MouseEvent) {
if (e.target === e.currentTarget) {
onClose();
}
}
</script>
<svelte:window onkeydown={handleKeyDown} />
<!-- svelte-ignore a11y_no_static_element_interactions -->
<div
class="fixed inset-0 z-[200] flex items-center justify-center bg-black/90 backdrop-blur-sm"
onclick={handleBackdropClick}
>
<!-- Close button -->
<button
class="absolute top-4 right-4 w-10 h-10 flex items-center justify-center rounded-full bg-light/10 hover:bg-light/20 transition-colors text-light"
onclick={onClose}
>
<svg class="w-6 h-6" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M18 6L6 18M6 6l12 12" />
</svg>
</button>
<!-- Image container -->
<div class="max-w-[90vw] max-h-[90vh] flex items-center justify-center">
<img
{src}
{alt}
class="max-w-full max-h-[90vh] object-contain rounded-lg shadow-2xl"
/>
</div>
<!-- Open in new tab button -->
<a
href={src}
target="_blank"
rel="noopener noreferrer"
class="absolute bottom-4 right-4 px-4 py-2 rounded-lg bg-light/10 hover:bg-light/20 transition-colors text-light text-sm flex items-center gap-2"
>
<svg class="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" />
<polyline points="15 3 21 3 21 9" />
<line x1="10" y1="14" x2="21" y2="3" />
</svg>
Open Original
</a>
</div>