mirror of
https://github.com/open-webui/open-webui
synced 2025-01-19 09:16:44 +00:00
refac
This commit is contained in:
parent
9d39404e6c
commit
2840ff405b
@ -1,5 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { toast } from 'svelte-sonner';
|
||||
import { Pane, PaneGroup, PaneResizer } from 'paneforge';
|
||||
|
||||
import { onDestroy, onMount, tick } from 'svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
@ -9,6 +11,9 @@
|
||||
import Messages from './Messages.svelte';
|
||||
import MessageInput from './MessageInput.svelte';
|
||||
import Navbar from './Navbar.svelte';
|
||||
import Drawer from '../common/Drawer.svelte';
|
||||
import EllipsisVertical from '../icons/EllipsisVertical.svelte';
|
||||
import Thread from './Messages/Thread.svelte';
|
||||
|
||||
export let id = '';
|
||||
|
||||
@ -20,6 +25,8 @@
|
||||
let channel = null;
|
||||
let messages = null;
|
||||
|
||||
let threadId = null;
|
||||
|
||||
let typingUsers = [];
|
||||
let typingUsersTimeout = {};
|
||||
|
||||
@ -150,12 +157,28 @@
|
||||
});
|
||||
};
|
||||
|
||||
let mediaQuery;
|
||||
let largeScreen = false;
|
||||
|
||||
onMount(() => {
|
||||
if ($chatId) {
|
||||
chatId.set('');
|
||||
}
|
||||
|
||||
$socket?.on('channel-events', channelEventHandler);
|
||||
|
||||
mediaQuery = window.matchMedia('(min-width: 1024px)');
|
||||
|
||||
const handleMediaQuery = async (e) => {
|
||||
if (e.matches) {
|
||||
largeScreen = true;
|
||||
} else {
|
||||
largeScreen = false;
|
||||
}
|
||||
};
|
||||
|
||||
mediaQuery.addEventListener('change', handleMediaQuery);
|
||||
handleMediaQuery(mediaQuery);
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
@ -173,40 +196,98 @@
|
||||
: ''} w-full max-w-full flex flex-col"
|
||||
id="channel-container"
|
||||
>
|
||||
<Navbar {channel} />
|
||||
<PaneGroup direction="horizontal" class="w-full h-full">
|
||||
<Pane defaultSize={50} minSize={50} class="h-full flex flex-col w-full relative">
|
||||
<Navbar {channel} />
|
||||
|
||||
<div class="flex-1 overflow-y-auto">
|
||||
{#if channel}
|
||||
<div
|
||||
class=" pb-2.5 max-w-full z-10 scrollbar-hidden w-full h-full pt-6 flex-1 flex flex-col-reverse overflow-auto"
|
||||
id="messages-container"
|
||||
bind:this={messagesContainerElement}
|
||||
on:scroll={(e) => {
|
||||
scrollEnd = Math.abs(messagesContainerElement.scrollTop) <= 50;
|
||||
}}
|
||||
<div class="flex-1 overflow-y-auto">
|
||||
{#if channel}
|
||||
<div
|
||||
class=" pb-2.5 max-w-full z-10 scrollbar-hidden w-full h-full pt-6 flex-1 flex flex-col-reverse overflow-auto"
|
||||
id="messages-container"
|
||||
bind:this={messagesContainerElement}
|
||||
on:scroll={(e) => {
|
||||
scrollEnd = Math.abs(messagesContainerElement.scrollTop) <= 50;
|
||||
}}
|
||||
>
|
||||
{#key id}
|
||||
<Messages
|
||||
{channel}
|
||||
{messages}
|
||||
{top}
|
||||
onThread={(id) => {
|
||||
threadId = id;
|
||||
}}
|
||||
onLoad={async () => {
|
||||
const newMessages = await getChannelMessages(
|
||||
localStorage.token,
|
||||
id,
|
||||
messages.length
|
||||
);
|
||||
|
||||
messages = [...messages, ...newMessages];
|
||||
|
||||
if (newMessages.length < 50) {
|
||||
top = true;
|
||||
return;
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{/key}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class=" pb-[1rem]">
|
||||
<MessageInput
|
||||
{typingUsers}
|
||||
{onChange}
|
||||
onSubmit={submitHandler}
|
||||
{scrollToBottom}
|
||||
{scrollEnd}
|
||||
/>
|
||||
</div>
|
||||
</Pane>
|
||||
|
||||
{#if !largeScreen}
|
||||
{#if threadId !== null}
|
||||
<Drawer
|
||||
show={threadId !== null}
|
||||
on:close={() => {
|
||||
threadId = null;
|
||||
}}
|
||||
>
|
||||
<div class=" {threadId !== null ? ' h-screen w-screen' : 'px-6 py-4'} h-full">
|
||||
<Thread
|
||||
{threadId}
|
||||
{channel}
|
||||
onClose={() => {
|
||||
threadId = null;
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Drawer>
|
||||
{/if}
|
||||
{:else if threadId !== null}
|
||||
<PaneResizer
|
||||
class="relative flex w-[3px] items-center justify-center bg-background group bg-gray-50 dark:bg-gray-850"
|
||||
>
|
||||
{#key id}
|
||||
<Messages
|
||||
<div class="z-10 flex h-7 w-5 items-center justify-center rounded-sm">
|
||||
<EllipsisVertical className="size-4 invisible group-hover:visible" />
|
||||
</div>
|
||||
</PaneResizer>
|
||||
|
||||
<Pane defaultSize={50} minSize={20} class="h-full w-full">
|
||||
<div class="h-full w-full shadow-xl">
|
||||
<Thread
|
||||
{threadId}
|
||||
{channel}
|
||||
{messages}
|
||||
{top}
|
||||
onLoad={async () => {
|
||||
const newMessages = await getChannelMessages(localStorage.token, id, messages.length);
|
||||
|
||||
messages = [...messages, ...newMessages];
|
||||
|
||||
if (newMessages.length < 50) {
|
||||
top = true;
|
||||
return;
|
||||
}
|
||||
onClose={() => {
|
||||
threadId = null;
|
||||
}}
|
||||
/>
|
||||
{/key}
|
||||
</div>
|
||||
</div>
|
||||
</Pane>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class=" pb-[1rem]">
|
||||
<MessageInput {typingUsers} {onChange} onSubmit={submitHandler} {scrollToBottom} {scrollEnd} />
|
||||
</div>
|
||||
</PaneGroup>
|
||||
</div>
|
||||
|
@ -25,6 +25,7 @@
|
||||
export let top = false;
|
||||
|
||||
export let onLoad: Function = () => {};
|
||||
export let onThread: Function = () => {};
|
||||
|
||||
let messagesLoading = false;
|
||||
|
||||
@ -118,6 +119,9 @@
|
||||
return null;
|
||||
});
|
||||
}}
|
||||
onThread={(id) => {
|
||||
onThread(id);
|
||||
}}
|
||||
onReaction={(name) => {
|
||||
if (
|
||||
(message?.reactions ?? [])
|
||||
@ -127,7 +131,16 @@
|
||||
) {
|
||||
messages = messages.map((m) => {
|
||||
if (m.id === message.id) {
|
||||
m.reactions = m.reactions.filter((reaction) => reaction.name !== name);
|
||||
const reaction = m.reactions.find((reaction) => reaction.name === name);
|
||||
|
||||
if (reaction) {
|
||||
reaction.user_ids = reaction.user_ids.filter((id) => id !== $user.id);
|
||||
reaction.count = reaction.user_ids.length;
|
||||
|
||||
if (reaction.count === 0) {
|
||||
m.reactions = m.reactions.filter((r) => r.name !== name);
|
||||
}
|
||||
}
|
||||
}
|
||||
return m;
|
||||
});
|
||||
|
@ -35,6 +35,7 @@
|
||||
|
||||
export let onDelete: Function = () => {};
|
||||
export let onEdit: Function = () => {};
|
||||
export let onThread: Function = () => {};
|
||||
export let onReaction: Function = () => {};
|
||||
|
||||
let showButtons = false;
|
||||
@ -100,17 +101,18 @@
|
||||
</Tooltip>
|
||||
</ReactionPicker>
|
||||
|
||||
<Tooltip content={$i18n.t('Reply in Thread')}>
|
||||
<button
|
||||
class="hover:bg-gray-100 dark:hover:bg-gray-800 transition rounded-lg p-1"
|
||||
on:click={() => {
|
||||
edit = true;
|
||||
editedContent = message.content;
|
||||
}}
|
||||
>
|
||||
<ChatBubbleOvalEllipsis />
|
||||
</button>
|
||||
</Tooltip>
|
||||
{#if message?.parent_id === null}
|
||||
<Tooltip content={$i18n.t('Reply in Thread')}>
|
||||
<button
|
||||
class="hover:bg-gray-100 dark:hover:bg-gray-800 transition rounded-lg p-1"
|
||||
on:click={() => {
|
||||
onThread(message.id);
|
||||
}}
|
||||
>
|
||||
<ChatBubbleOvalEllipsis />
|
||||
</button>
|
||||
</Tooltip>
|
||||
{/if}
|
||||
|
||||
<Tooltip content={$i18n.t('Edit')}>
|
||||
<button
|
||||
@ -288,6 +290,7 @@
|
||||
].toLowerCase()}.svg"
|
||||
alt={reaction.name}
|
||||
class=" size-4"
|
||||
loading="lazy"
|
||||
/>
|
||||
{:else}
|
||||
<div>
|
||||
|
28
src/lib/components/channel/Messages/Thread.svelte
Normal file
28
src/lib/components/channel/Messages/Thread.svelte
Normal file
@ -0,0 +1,28 @@
|
||||
<script lang="ts">
|
||||
import XMark from '$lib/components/icons/XMark.svelte';
|
||||
|
||||
export let threadId = null;
|
||||
export let channel = null;
|
||||
|
||||
export let onClose = () => {};
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col w-full h-full bg-gray-50 dark:bg-gray-900 px-3.5 py-3">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class=" font-medium text-lg">Thread</div>
|
||||
|
||||
<div>
|
||||
<button
|
||||
class="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300 p-2"
|
||||
on:click={() => {
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
<XMark />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{threadId}
|
||||
|
||||
{channel}
|
||||
</div>
|
Loading…
Reference in New Issue
Block a user