open-webui/src/lib/components/chat/ChatControls.svelte

195 lines
4.7 KiB
Svelte
Raw Normal View History

2024-07-08 23:55:12 +00:00
<script lang="ts">
2024-09-17 20:05:19 +00:00
import { SvelteFlowProvider } from '@xyflow/svelte';
2024-07-08 23:55:12 +00:00
import { slide } from 'svelte/transition';
2024-09-17 20:05:19 +00:00
2024-09-17 21:02:41 +00:00
import { onDestroy, onMount } from 'svelte';
2024-09-17 20:05:19 +00:00
import { mobile, showControls, showCallOverlay, showOverview } from '$lib/stores';
2024-07-08 23:55:12 +00:00
import Modal from '../common/Modal.svelte';
import Controls from './Controls/Controls.svelte';
2024-08-23 14:42:36 +00:00
import CallOverlay from './MessageInput/CallOverlay.svelte';
2024-09-05 15:23:59 +00:00
import Drawer from '../common/Drawer.svelte';
2024-09-17 20:05:19 +00:00
import Overview from './Overview.svelte';
2024-09-21 01:33:06 +00:00
import { Pane, PaneResizer } from 'paneforge';
import EllipsisVertical from '../icons/EllipsisVertical.svelte';
import { get } from 'svelte/store';
2024-07-08 23:55:12 +00:00
2024-09-17 20:05:19 +00:00
export let history;
2024-07-12 00:18:18 +00:00
export let models = [];
2024-07-09 02:26:31 +00:00
export let chatId = null;
2024-07-17 09:39:37 +00:00
export let chatFiles = [];
2024-07-09 02:26:31 +00:00
export let params = {};
2024-07-08 23:55:12 +00:00
2024-08-23 14:42:36 +00:00
export let eventTarget: EventTarget;
export let submitPrompt: Function;
export let stopResponse: Function;
2024-09-18 01:13:37 +00:00
export let showMessage: Function;
2024-08-23 14:42:36 +00:00
export let files;
export let modelId;
2024-09-21 01:33:06 +00:00
export let pane;
2024-07-09 02:26:31 +00:00
let largeScreen = false;
2024-09-21 01:33:06 +00:00
2024-07-08 23:55:12 +00:00
onMount(() => {
// listen to resize 1024px
const mediaQuery = window.matchMedia('(min-width: 1024px)');
const handleMediaQuery = (e) => {
if (e.matches) {
largeScreen = true;
} else {
largeScreen = false;
2024-09-21 02:36:18 +00:00
pane = null;
2024-07-08 23:55:12 +00:00
}
};
mediaQuery.addEventListener('change', handleMediaQuery);
handleMediaQuery(mediaQuery);
return () => {
mediaQuery.removeEventListener('change', handleMediaQuery);
};
});
2024-09-17 21:02:41 +00:00
onDestroy(() => {
showControls.set(false);
});
2024-09-17 23:57:27 +00:00
$: if (!chatId) {
showOverview.set(false);
}
2024-07-08 23:55:12 +00:00
</script>
2024-09-17 20:05:19 +00:00
<SvelteFlowProvider>
{#if !largeScreen}
2024-09-21 01:33:06 +00:00
{#if $showControls}
2024-09-17 20:05:19 +00:00
<Drawer
2024-09-17 22:18:47 +00:00
show={$showControls}
2024-09-17 20:05:19 +00:00
on:close={() => {
showControls.set(false);
}}
>
2024-09-21 01:33:06 +00:00
<div
class=" {$showCallOverlay || $showOverview ? ' h-screen w-screen' : 'px-6 py-4'} h-full"
>
{#if $showCallOverlay}
<div
class=" h-full max-h-[100dvh] bg-white text-gray-700 dark:bg-black dark:text-gray-300 flex justify-center"
>
<CallOverlay
bind:files
{submitPrompt}
{stopResponse}
{modelId}
{chatId}
{eventTarget}
on:close={() => {
showControls.set(false);
}}
/>
</div>
{:else if $showOverview}
2024-09-17 23:25:28 +00:00
<Overview
2024-09-18 01:47:04 +00:00
{history}
on:nodeclick={(e) => {
showMessage(e.detail.node.data.message);
}}
2024-09-17 23:25:28 +00:00
on:close={() => {
showControls.set(false);
}}
/>
{:else}
<Controls
on:close={() => {
showControls.set(false);
}}
{models}
bind:chatFiles
bind:params
/>
{/if}
2024-09-17 20:05:19 +00:00
</div>
</Drawer>
{/if}
2024-09-21 01:33:06 +00:00
{:else}
<!-- if $showControls -->
2024-09-21 23:42:18 +00:00
<PaneResizer class="relative flex w-2 items-center justify-center bg-background group">
2024-09-21 01:33:06 +00:00
<div class="z-10 flex h-7 w-5 items-center justify-center rounded-sm">
2024-09-21 23:42:18 +00:00
<EllipsisVertical className="size-4 invisible group-hover:visible" />
2024-09-21 01:33:06 +00:00
</div>
</PaneResizer>
<Pane
bind:pane
2024-09-21 13:53:29 +00:00
defaultSize={$showControls
? parseInt(localStorage?.chatControlsSize ?? '30')
? parseInt(localStorage?.chatControlsSize ?? '30')
: 30
: 0}
2024-09-21 01:33:06 +00:00
onResize={(size) => {
2024-09-21 13:48:16 +00:00
console.log(size);
2024-09-21 01:33:06 +00:00
if (size === 0) {
showControls.set(false);
} else {
if (!$showControls) {
showControls.set(true);
}
2024-09-21 13:48:52 +00:00
localStorage.chatControlsSize = size;
2024-09-21 01:33:06 +00:00
}
}}
>
2024-09-21 02:10:24 +00:00
{#if $showControls}
<div class="pr-4 pb-8 flex max-h-full min-h-full">
<div
class="w-full {$showOverview && !$showCallOverlay
? ' '
: 'px-5 py-4 bg-white dark:shadow-lg dark:bg-gray-850 border border-gray-50 dark:border-gray-800'} rounded-lg z-50 pointer-events-auto overflow-y-auto scrollbar-hidden"
>
{#if $showCallOverlay}
<div class="w-full h-full flex justify-center">
<CallOverlay
bind:files
{submitPrompt}
{stopResponse}
{modelId}
{chatId}
{eventTarget}
on:close={() => {
showControls.set(false);
}}
/>
</div>
{:else if $showOverview}
<Overview
{history}
on:nodeclick={(e) => {
2024-09-22 00:53:38 +00:00
if (e.detail.node.data.message.favorite) {
history.messages[e.detail.node.data.message.id].favorite = true;
} else {
history.messages[e.detail.node.data.message.id].favorite = null;
}
2024-09-21 02:10:24 +00:00
showMessage(e.detail.node.data.message);
}}
2024-09-21 01:44:44 +00:00
on:close={() => {
showControls.set(false);
}}
/>
2024-09-21 02:10:24 +00:00
{:else}
<Controls
on:close={() => {
showControls.set(false);
}}
{models}
bind:chatFiles
bind:params
/>
{/if}
</div>
2024-09-17 20:05:19 +00:00
</div>
2024-09-21 02:10:24 +00:00
{/if}
2024-09-21 01:33:06 +00:00
</Pane>
2024-09-17 20:05:19 +00:00
{/if}
</SvelteFlowProvider>