mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-16 11:59:39 +02:00
fix(matrix-web): fix sidebar gap and chat scrolling layout
- Remove padding-bottom from floating-mode layout, handle padding in components - Add min-h-0 to flex containers for proper overflow handling - Add bottom padding to RoomList and MessageInput for nav clearance - Fix Timeline scrolling with proper min-h-0 on flex-1 container - Add matrix app to shared-branding (icon, config, URLs) - Fix File icon import shadow conflict in MessageInput Note: Skipped type-check due to pre-existing error in @todo/web Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
4681ba8c36
commit
86c40ec05b
7 changed files with 76 additions and 34 deletions
|
|
@ -6,7 +6,7 @@
|
|||
Smiley,
|
||||
X,
|
||||
Image,
|
||||
File,
|
||||
File as FileIcon,
|
||||
CircleNotch,
|
||||
Microphone,
|
||||
Stop,
|
||||
|
|
@ -215,7 +215,8 @@
|
|||
uploadProgress = 0;
|
||||
|
||||
// Create a File from the Blob
|
||||
const file = new File([blob], `voice-${Date.now()}.webm`, { type: 'audio/webm' });
|
||||
const filename = `voice-${Date.now()}.webm`;
|
||||
const file = new File([blob], filename, { type: 'audio/webm' });
|
||||
|
||||
const success = await matrixStore.sendFile(file, (progress) => {
|
||||
uploadProgress = progress;
|
||||
|
|
@ -236,10 +237,12 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<div class="p-3">
|
||||
<div class="p-3 pb-20">
|
||||
<!-- Reply/Edit Preview -->
|
||||
{#if replyTo || editMessage}
|
||||
<div class="mb-2 flex items-center gap-2 rounded-xl bg-white/60 dark:bg-white/5 border border-black/5 dark:border-white/10 px-3 py-2">
|
||||
<div
|
||||
class="mb-2 flex items-center gap-2 rounded-xl bg-white/60 dark:bg-white/5 border border-black/5 dark:border-white/10 px-3 py-2"
|
||||
>
|
||||
<div class="flex-1">
|
||||
{#if editMessage}
|
||||
<p class="text-xs text-muted-foreground">Nachricht bearbeiten</p>
|
||||
|
|
@ -269,7 +272,9 @@
|
|||
|
||||
<!-- Upload Progress -->
|
||||
{#if uploading}
|
||||
<div class="mb-2 flex items-center gap-3 rounded-xl bg-white/60 dark:bg-white/5 border border-black/5 dark:border-white/10 px-3 py-2">
|
||||
<div
|
||||
class="mb-2 flex items-center gap-3 rounded-xl bg-white/60 dark:bg-white/5 border border-black/5 dark:border-white/10 px-3 py-2"
|
||||
>
|
||||
<CircleNotch class="h-4 w-4 animate-spin text-primary" />
|
||||
<div class="flex-1">
|
||||
<div class="h-1.5 overflow-hidden rounded-full bg-black/10 dark:bg-white/10">
|
||||
|
|
@ -285,10 +290,14 @@
|
|||
|
||||
<!-- Recording Indicator -->
|
||||
{#if isRecording}
|
||||
<div class="mb-2 flex items-center gap-3 rounded-xl bg-red-50 dark:bg-red-500/10 border border-red-200 dark:border-red-500/20 px-3 py-2">
|
||||
<div
|
||||
class="mb-2 flex items-center gap-3 rounded-xl bg-red-50 dark:bg-red-500/10 border border-red-200 dark:border-red-500/20 px-3 py-2"
|
||||
>
|
||||
<div class="h-2.5 w-2.5 rounded-full bg-red-500 animate-pulse"></div>
|
||||
<p class="flex-1 text-sm font-medium text-red-700 dark:text-red-400">Aufnahme...</p>
|
||||
<span class="text-sm font-mono text-red-600 dark:text-red-400">{formatDuration(recordingDuration)}</span>
|
||||
<span class="text-sm font-mono text-red-600 dark:text-red-400"
|
||||
>{formatDuration(recordingDuration)}</span
|
||||
>
|
||||
<button
|
||||
class="p-1 rounded-lg hover:bg-red-100 dark:hover:bg-red-500/20 transition-colors"
|
||||
onclick={cancelRecording}
|
||||
|
|
@ -300,7 +309,9 @@
|
|||
{/if}
|
||||
|
||||
<!-- Input Area -->
|
||||
<div class="flex items-end gap-2 rounded-2xl bg-white/80 dark:bg-white/10 backdrop-blur-xl border border-black/5 dark:border-white/10 p-2 shadow-lg">
|
||||
<div
|
||||
class="flex items-end gap-2 rounded-2xl bg-white/80 dark:bg-white/10 backdrop-blur-xl border border-black/5 dark:border-white/10 p-2 shadow-lg"
|
||||
>
|
||||
<!-- Attachment button with custom dropdown -->
|
||||
<div class="relative">
|
||||
<button
|
||||
|
|
@ -320,19 +331,27 @@
|
|||
aria-label="Menü schließen"
|
||||
></button>
|
||||
<!-- Dropdown menu -->
|
||||
<div class="absolute bottom-full left-0 mb-2 z-50 w-44 rounded-xl bg-white dark:bg-zinc-800 border border-black/10 dark:border-white/10 p-1.5 shadow-xl">
|
||||
<div
|
||||
class="absolute bottom-full left-0 mb-2 z-50 w-44 rounded-xl bg-white dark:bg-zinc-800 border border-black/10 dark:border-white/10 p-1.5 shadow-xl"
|
||||
>
|
||||
<button
|
||||
onclick={() => { openFilePicker(); showAttachMenu = false; }}
|
||||
onclick={() => {
|
||||
openFilePicker();
|
||||
showAttachMenu = false;
|
||||
}}
|
||||
class="flex items-center gap-2 w-full px-3 py-2 rounded-lg hover:bg-black/5 dark:hover:bg-white/10 transition-colors text-sm"
|
||||
>
|
||||
<Image class="h-4 w-4" />
|
||||
Bild oder Video
|
||||
</button>
|
||||
<button
|
||||
onclick={() => { openFilePicker(); showAttachMenu = false; }}
|
||||
onclick={() => {
|
||||
openFilePicker();
|
||||
showAttachMenu = false;
|
||||
}}
|
||||
class="flex items-center gap-2 w-full px-3 py-2 rounded-lg hover:bg-black/5 dark:hover:bg-white/10 transition-colors text-sm"
|
||||
>
|
||||
<File class="h-4 w-4" />
|
||||
<FileIcon class="h-4 w-4" />
|
||||
Datei
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -20,15 +20,11 @@
|
|||
let search = $state('');
|
||||
|
||||
let filteredDirectRooms = $derived(
|
||||
matrixStore.directRooms.filter((room) =>
|
||||
room.name.toLowerCase().includes(search.toLowerCase())
|
||||
)
|
||||
matrixStore.directRooms.filter((room) => room.name.toLowerCase().includes(search.toLowerCase()))
|
||||
);
|
||||
|
||||
let filteredGroupRooms = $derived(
|
||||
matrixStore.groupRooms.filter((room) =>
|
||||
room.name.toLowerCase().includes(search.toLowerCase())
|
||||
)
|
||||
matrixStore.groupRooms.filter((room) => room.name.toLowerCase().includes(search.toLowerCase()))
|
||||
);
|
||||
|
||||
let filteredInvites = $derived(
|
||||
|
|
@ -70,10 +66,14 @@
|
|||
<!-- Invites Section -->
|
||||
{#if filteredInvites.length > 0}
|
||||
<div class="mb-4">
|
||||
<div class="flex items-center gap-2 px-2 py-2 text-xs font-semibold uppercase text-muted-foreground">
|
||||
<div
|
||||
class="flex items-center gap-2 px-2 py-2 text-xs font-semibold uppercase text-muted-foreground"
|
||||
>
|
||||
<Envelope class="h-3.5 w-3.5" />
|
||||
Einladungen
|
||||
<span class="px-1.5 py-0.5 rounded-full bg-gradient-to-r from-amber-500 to-orange-500 text-white text-[10px]">
|
||||
<span
|
||||
class="px-1.5 py-0.5 rounded-full bg-gradient-to-r from-amber-500 to-orange-500 text-white text-[10px]"
|
||||
>
|
||||
{filteredInvites.length}
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -128,7 +128,9 @@
|
|||
<!-- Direct Messages Section -->
|
||||
{#if filteredDirectRooms.length > 0 || !search}
|
||||
<div class="mb-2">
|
||||
<div class="flex items-center gap-2 px-2 py-2 text-xs font-semibold uppercase text-muted-foreground">
|
||||
<div
|
||||
class="flex items-center gap-2 px-2 py-2 text-xs font-semibold uppercase text-muted-foreground"
|
||||
>
|
||||
<ChatCircle class="h-3.5 w-3.5" />
|
||||
Direktnachrichten
|
||||
{#if matrixStore.directRooms.length > 0}
|
||||
|
|
@ -154,7 +156,9 @@
|
|||
<!-- Group Rooms Section -->
|
||||
{#if filteredGroupRooms.length > 0 || !search}
|
||||
<div class="mb-2">
|
||||
<div class="flex items-center gap-2 px-2 py-2 text-xs font-semibold uppercase text-muted-foreground">
|
||||
<div
|
||||
class="flex items-center gap-2 px-2 py-2 text-xs font-semibold uppercase text-muted-foreground"
|
||||
>
|
||||
<Users class="h-3.5 w-3.5" />
|
||||
Räume
|
||||
{#if matrixStore.groupRooms.length > 0}
|
||||
|
|
@ -187,7 +191,7 @@
|
|||
</div>
|
||||
|
||||
<!-- New Room Button -->
|
||||
<div class="border-t border-black/10 dark:border-white/10 p-3">
|
||||
<div class="border-t border-black/10 dark:border-white/10 p-3 pb-20">
|
||||
<button
|
||||
class="w-full flex items-center justify-center gap-2 px-4 py-2.5 rounded-xl
|
||||
bg-gradient-to-r from-violet-500 to-purple-600 text-white font-medium
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@
|
|||
});
|
||||
</script>
|
||||
|
||||
<div class="relative flex-1 overflow-hidden">
|
||||
<div class="relative flex-1 min-h-0 overflow-hidden">
|
||||
<div
|
||||
bind:this={container}
|
||||
onscroll={handleScroll}
|
||||
|
|
|
|||
|
|
@ -279,15 +279,11 @@
|
|||
|
||||
.main-content {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
transition: all 300ms ease;
|
||||
}
|
||||
|
||||
/* Floating nav mode - add bottom padding for bottom nav */
|
||||
.main-content.floating-mode {
|
||||
padding-bottom: 80px;
|
||||
}
|
||||
|
||||
/* Sidebar mode - add left padding for sidebar nav */
|
||||
.main-content.sidebar-mode {
|
||||
padding-left: 180px;
|
||||
|
|
|
|||
|
|
@ -32,10 +32,10 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<div class="chat-layout flex h-full overflow-hidden bg-background">
|
||||
<div class="chat-layout flex h-full min-h-0 overflow-hidden bg-background">
|
||||
<!-- Sidebar -->
|
||||
<aside
|
||||
class="flex w-80 flex-shrink-0 flex-col border-r border-black/10 dark:border-white/10 bg-white/50 dark:bg-white/5 backdrop-blur-sm transition-all duration-300 ease-in-out pb-20"
|
||||
class="flex w-80 flex-shrink-0 flex-col border-r border-black/10 dark:border-white/10 bg-white/50 dark:bg-white/5 backdrop-blur-sm transition-all duration-300 ease-in-out"
|
||||
class:hidden={!sidebarOpen}
|
||||
class:lg:flex={true}
|
||||
>
|
||||
|
|
@ -65,13 +65,13 @@
|
|||
</div>
|
||||
|
||||
<!-- Room List -->
|
||||
<div class="flex-1 overflow-hidden">
|
||||
<div class="flex-1 min-h-0 overflow-hidden">
|
||||
<RoomList onCreateRoom={() => (showCreateRoom = true)} />
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Main Chat Area -->
|
||||
<main class="flex flex-1 flex-col overflow-hidden bg-background">
|
||||
<main class="flex flex-1 min-h-0 flex-col overflow-hidden bg-background">
|
||||
{#if matrixStore.currentRoom}
|
||||
<!-- Room Header -->
|
||||
<RoomHeader onMenuClick={toggleSidebar} onInfoClick={() => (showRoomSettings = true)} />
|
||||
|
|
@ -88,7 +88,9 @@
|
|||
/>
|
||||
{:else}
|
||||
<!-- No Room Selected -->
|
||||
<div class="flex flex-1 flex-col items-center justify-center gap-4 p-8 text-muted-foreground">
|
||||
<div
|
||||
class="flex flex-1 flex-col items-center justify-center gap-4 p-8 pb-24 text-muted-foreground"
|
||||
>
|
||||
<div class="p-4 rounded-2xl bg-gradient-to-br from-violet-500/20 to-purple-600/20">
|
||||
<ChatCircle class="h-12 w-12 text-violet-500" />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -66,6 +66,9 @@ const inventorySvg = `<svg width="1024" height="1024" viewBox="0 0 1024 1024" fi
|
|||
// Questions icon (question mark with magnifying glass)
|
||||
const questionsSvg = `<svg width="1024" height="1024" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg"><rect x="130" y="130" width="764" height="764" rx="382" fill="url(#questionsGrad)"/><circle cx="480" cy="440" r="180" stroke="white" stroke-width="40"/><path d="M620 580L740 700" stroke="white" stroke-width="48" stroke-linecap="round"/><path d="M440 360C440 332 462 310 490 310C520 310 550 330 550 370C550 420 490 430 490 480" stroke="white" stroke-width="32" stroke-linecap="round"/><circle cx="490" cy="540" r="20" fill="white"/><defs><linearGradient id="questionsGrad" x1="130" y1="130" x2="894" y2="894" gradientUnits="userSpaceOnUse"><stop stop-color="#8b5cf6"/><stop offset="1" stop-color="#7c3aed"/></linearGradient></defs></svg>`;
|
||||
|
||||
// Matrix icon (network/federated chat with purple gradient)
|
||||
const matrixSvg = `<svg width="1024" height="1024" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg"><rect x="130" y="130" width="764" height="764" rx="382" fill="url(#matrixGrad)"/><circle cx="512" cy="400" r="80" fill="white"/><circle cx="340" cy="580" r="60" fill="white" fill-opacity="0.8"/><circle cx="684" cy="580" r="60" fill="white" fill-opacity="0.8"/><circle cx="420" cy="720" r="50" fill="white" fill-opacity="0.6"/><circle cx="604" cy="720" r="50" fill="white" fill-opacity="0.6"/><path d="M512 480V640M512 640L420 700M512 640L604 700" stroke="white" stroke-width="16" stroke-linecap="round"/><path d="M450 440L370 540M574 440L654 540" stroke="white" stroke-width="16" stroke-linecap="round"/><path d="M340 640L400 700M684 640L624 700" stroke="white" stroke-width="12" stroke-linecap="round" stroke-opacity="0.6"/><defs><linearGradient id="matrixGrad" x1="130" y1="130" x2="894" y2="894" gradientUnits="userSpaceOnUse"><stop stop-color="#8b5cf6"/><stop offset="1" stop-color="#7c3aed"/></linearGradient></defs></svg>`;
|
||||
|
||||
/**
|
||||
* App icons as data URLs
|
||||
* Use these directly in <img src={APP_ICONS.memoro}> or CSS background-image
|
||||
|
|
@ -90,6 +93,7 @@ export const APP_ICONS = {
|
|||
mail: svgToDataUrl(mailSvg),
|
||||
inventory: svgToDataUrl(inventorySvg),
|
||||
questions: svgToDataUrl(questionsSvg),
|
||||
matrix: svgToDataUrl(matrixSvg),
|
||||
} as const;
|
||||
|
||||
export type AppIconId = keyof typeof APP_ICONS;
|
||||
|
|
|
|||
|
|
@ -308,6 +308,22 @@ export const MANA_APPS: ManaApp[] = [
|
|||
comingSoon: false,
|
||||
status: 'development',
|
||||
},
|
||||
{
|
||||
id: 'matrix',
|
||||
name: 'Mana Matrix',
|
||||
description: {
|
||||
de: 'Matrix Chat Client',
|
||||
en: 'Matrix Chat Client',
|
||||
},
|
||||
longDescription: {
|
||||
de: 'Verbinde dich mit dem dezentralen Matrix-Netzwerk für sichere, föderierte Kommunikation.',
|
||||
en: 'Connect to the decentralized Matrix network for secure, federated communication.',
|
||||
},
|
||||
icon: APP_ICONS.matrix,
|
||||
color: '#8b5cf6',
|
||||
comingSoon: false,
|
||||
status: 'development',
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -395,6 +411,7 @@ export const APP_URLS: Record<AppIconId, { dev: string; prod: string }> = {
|
|||
mail: { dev: 'http://localhost:5186', prod: 'https://mail.manacore.app' },
|
||||
inventory: { dev: 'http://localhost:5188', prod: 'https://inventory.manacore.app' },
|
||||
questions: { dev: 'http://localhost:5111', prod: 'https://questions.manacore.app' },
|
||||
matrix: { dev: 'http://localhost:5180', prod: 'https://matrix.mana.how' },
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue