mirror of
https://github.com/open-webui/open-webui.git
synced 2026-09-21 13:38:19 -05:00
refac
This commit is contained in:
@@ -168,6 +168,13 @@
|
||||
(history.currentId && history.messages[history.currentId]?.done != true) ||
|
||||
generating);
|
||||
$: canCompact = !!history?.currentId;
|
||||
$: canToggleTemporary =
|
||||
!embedded &&
|
||||
!chatId &&
|
||||
($_user?.role === 'admin' ||
|
||||
($_user?.role === 'user' &&
|
||||
($_user?.permissions?.chat?.temporary ?? true) &&
|
||||
!($_user?.permissions?.chat?.temporary_enforced ?? false)));
|
||||
|
||||
export let prompt = '';
|
||||
export let files = [];
|
||||
@@ -539,6 +546,26 @@
|
||||
chatInputElement?.replaceCommandWithText(text);
|
||||
};
|
||||
|
||||
const temporaryHandler = async () => {
|
||||
if (!canToggleTemporary) return;
|
||||
|
||||
if (($settings?.temporaryChatByDefault ?? false) && $temporaryChatEnabled) {
|
||||
await temporaryChatEnabled.set(null);
|
||||
} else {
|
||||
await temporaryChatEnabled.set(!$temporaryChatEnabled);
|
||||
}
|
||||
|
||||
if (location.pathname !== '/') {
|
||||
await goto('/');
|
||||
}
|
||||
|
||||
if ($temporaryChatEnabled) {
|
||||
window.history.replaceState(null, '', '?temporary-chat=true');
|
||||
} else {
|
||||
window.history.replaceState(null, '', location.pathname);
|
||||
}
|
||||
};
|
||||
|
||||
const insertTextAtCursor = async (text: string) => {
|
||||
const chatInput = document.getElementById('chat-input');
|
||||
if (!chatInput) return;
|
||||
@@ -1281,7 +1308,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
if (['compact', 'fork', 'status', 'model'].includes(props?.id)) {
|
||||
if (['compact', 'fork', 'status', 'model', 'settings', 'temporary'].includes(props?.id)) {
|
||||
editor.chain().focus().deleteRange(range).run();
|
||||
return;
|
||||
}
|
||||
@@ -1307,11 +1334,15 @@
|
||||
!!history?.currentId &&
|
||||
($_user?.role === 'admin' || ($_user?.permissions?.chat?.import ?? true)),
|
||||
forkDisabled: () => isActive,
|
||||
canTemporary: () => canToggleTemporary,
|
||||
temporaryEnabled: () => $temporaryChatEnabled === true,
|
||||
contextUsage: () => statusContextUsage,
|
||||
onCompact: compactHandler,
|
||||
onStatus: statusHandler,
|
||||
onFork: forkHandler,
|
||||
onModel: () => modelSelector?.open(),
|
||||
onSettings: () => showSettings.set(true),
|
||||
onTemporary: temporaryHandler,
|
||||
onSelect: (e) => {
|
||||
const { type, data } = e;
|
||||
|
||||
|
||||
@@ -21,12 +21,16 @@
|
||||
export let onStatus: () => void = () => {};
|
||||
export let onFork: () => void = () => {};
|
||||
export let onModel: () => void = () => {};
|
||||
export let onSettings: () => void = () => {};
|
||||
export let onTemporary: () => void = () => {};
|
||||
export let insertTextHandler: (text: string) => void = () => {};
|
||||
export let canCompact: boolean | (() => boolean) = false;
|
||||
export let compactDisabled: boolean | (() => boolean) = false;
|
||||
export let canStatus: boolean | (() => boolean) = false;
|
||||
export let canFork: boolean | (() => boolean) = false;
|
||||
export let forkDisabled: boolean | (() => boolean) = false;
|
||||
export let canTemporary: boolean | (() => boolean) = false;
|
||||
export let temporaryEnabled: boolean | (() => boolean) = false;
|
||||
export let contextUsage = null;
|
||||
|
||||
$: compactAvailable = typeof canCompact === 'function' ? canCompact() : canCompact;
|
||||
@@ -35,6 +39,9 @@
|
||||
$: statusAvailable = typeof canStatus === 'function' ? canStatus() : canStatus;
|
||||
$: forkAvailable = typeof canFork === 'function' ? canFork() : canFork;
|
||||
$: isForkDisabled = typeof forkDisabled === 'function' ? forkDisabled() : forkDisabled;
|
||||
$: temporaryAvailable = typeof canTemporary === 'function' ? canTemporary() : canTemporary;
|
||||
$: isTemporaryEnabled =
|
||||
typeof temporaryEnabled === 'function' ? temporaryEnabled() : temporaryEnabled;
|
||||
$: resolvedContextUsage = typeof contextUsage === 'function' ? contextUsage() : contextUsage;
|
||||
$: contextHasThreshold = Number(resolvedContextUsage?.threshold) > 0;
|
||||
$: contextPercent = contextHasThreshold
|
||||
@@ -93,6 +100,8 @@
|
||||
canStatus={statusAvailable}
|
||||
canFork={forkAvailable}
|
||||
forkDisabled={isForkDisabled}
|
||||
canTemporary={temporaryAvailable}
|
||||
temporaryEnabled={isTemporaryEnabled}
|
||||
{contextPercent}
|
||||
{contextHasThreshold}
|
||||
onSelect={(e) => {
|
||||
@@ -117,6 +126,12 @@
|
||||
} else if (type === 'command' && data.id === 'model') {
|
||||
command({ id: data.id, label: data.id });
|
||||
onModel();
|
||||
} else if (type === 'command' && data.id === 'settings') {
|
||||
command({ id: data.id, label: data.id });
|
||||
onSettings();
|
||||
} else if (type === 'command' && data.id === 'temporary') {
|
||||
command({ id: data.id, label: data.id });
|
||||
onTemporary();
|
||||
} else if (type === 'skill') {
|
||||
command({
|
||||
id: `${data.id}|${data.name}`,
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
import { getPrompts } from '$lib/apis/prompts';
|
||||
import { getSkillItems } from '$lib/apis/skills';
|
||||
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
||||
import ChatBubbleDotted from '$lib/components/icons/ChatBubbleDotted.svelte';
|
||||
import ChatBubbleDottedChecked from '$lib/components/icons/ChatBubbleDottedChecked.svelte';
|
||||
import Cube from '$lib/components/icons/Cube.svelte';
|
||||
import Knobs from '$lib/components/icons/Knobs.svelte';
|
||||
import Sparkles from '$lib/components/icons/Sparkles.svelte';
|
||||
|
||||
const i18n = getContext('i18n');
|
||||
@@ -15,6 +18,8 @@
|
||||
export let canStatus = false;
|
||||
export let canFork = false;
|
||||
export let forkDisabled = false;
|
||||
export let canTemporary = false;
|
||||
export let temporaryEnabled = false;
|
||||
export let contextPercent = 0;
|
||||
export let contextHasThreshold = false;
|
||||
|
||||
@@ -31,6 +36,9 @@
|
||||
$: contextCircleOffset = 50.27 * (1 - contextCirclePercent / 100);
|
||||
|
||||
$: commandItems = [
|
||||
...(canTemporary && 'temporary'.startsWith(query.toLowerCase())
|
||||
? [{ type: 'command', data: { id: 'temporary' } }]
|
||||
: []),
|
||||
...(canCompact && 'compact'.startsWith(query.toLowerCase())
|
||||
? [{ type: 'command', data: { id: 'compact' } }]
|
||||
: []),
|
||||
@@ -40,7 +48,12 @@
|
||||
...(canStatus && 'status'.startsWith(query.toLowerCase())
|
||||
? [{ type: 'command', data: { id: 'status' } }]
|
||||
: []),
|
||||
...('model'.startsWith(query.toLowerCase()) ? [{ type: 'command', data: { id: 'model' } }] : [])
|
||||
...('model'.startsWith(query.toLowerCase())
|
||||
? [{ type: 'command', data: { id: 'model' } }]
|
||||
: []),
|
||||
...('settings'.startsWith(query.toLowerCase())
|
||||
? [{ type: 'command', data: { id: 'settings' } }]
|
||||
: [])
|
||||
];
|
||||
|
||||
$: filteredPrompts = prompts
|
||||
@@ -128,7 +141,39 @@
|
||||
</div>
|
||||
|
||||
{#each commandItems as item, commandIdx}
|
||||
{#if item.data.id === 'compact'}
|
||||
{#if item.data.id === 'temporary'}
|
||||
<Tooltip content="Toggle temporary chat for this new chat." placement="top">
|
||||
<button
|
||||
type="button"
|
||||
aria-label="Temporary: toggle temporary chat for this new chat."
|
||||
class="slash-command-row flex items-center gap-2 w-full h-6 px-2 rounded-xl text-xs text-left transition-colors duration-75
|
||||
{commandIdx === selectedIdx ? 'app-interactive-active' : ''}"
|
||||
on:mousedown={(e) => e.preventDefault()}
|
||||
on:click={() => {
|
||||
onSelect(item);
|
||||
}}
|
||||
on:mouseenter={() => {
|
||||
selectedIdx = commandIdx;
|
||||
}}
|
||||
on:focus={() => {}}
|
||||
data-selected={commandIdx === selectedIdx}
|
||||
>
|
||||
<span class="app-icon-muted flex items-center justify-center w-4 shrink-0">
|
||||
{#if temporaryEnabled}
|
||||
<ChatBubbleDottedChecked className="size-3.5" strokeWidth="1.6" />
|
||||
{:else}
|
||||
<ChatBubbleDotted className="size-3.5" strokeWidth="1.6" />
|
||||
{/if}
|
||||
</span>
|
||||
<span class="flex-1 min-w-0 flex items-baseline gap-1.5 overflow-hidden">
|
||||
<span class="truncate">Temporary</span>
|
||||
<span class="app-muted text-[0.625rem] truncate shrink-0">
|
||||
{temporaryEnabled ? 'On' : 'Off'}
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
</Tooltip>
|
||||
{:else if item.data.id === 'compact'}
|
||||
<Tooltip content="Shorten older messages so this chat can keep going." placement="top">
|
||||
<button
|
||||
type="button"
|
||||
@@ -294,6 +339,32 @@
|
||||
</span>
|
||||
</button>
|
||||
</Tooltip>
|
||||
{:else if item.data.id === 'settings'}
|
||||
<Tooltip content="Open settings." placement="top">
|
||||
<button
|
||||
type="button"
|
||||
aria-label="Settings: open settings."
|
||||
class="slash-command-row flex items-center gap-2 w-full h-6 px-2 rounded-xl text-xs text-left transition-colors duration-75
|
||||
{commandIdx === selectedIdx ? 'app-interactive-active' : ''}"
|
||||
on:mousedown={(e) => e.preventDefault()}
|
||||
on:click={() => {
|
||||
onSelect(item);
|
||||
}}
|
||||
on:mouseenter={() => {
|
||||
selectedIdx = commandIdx;
|
||||
}}
|
||||
on:focus={() => {}}
|
||||
data-selected={commandIdx === selectedIdx}
|
||||
>
|
||||
<span class="app-icon-muted flex items-center justify-center w-4 shrink-0">
|
||||
<Knobs className="size-3.5" />
|
||||
</span>
|
||||
<span class="flex-1 min-w-0 flex items-baseline gap-1.5 overflow-hidden">
|
||||
<span class="truncate">Settings</span>
|
||||
<span class="app-muted text-[0.625rem] truncate shrink-0">/settings</span>
|
||||
</span>
|
||||
</button>
|
||||
</Tooltip>
|
||||
{/if}
|
||||
{/each}
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user