This commit is contained in:
Timothy Jaeryang Baek committed 2026-07-15 04:52:06 -04:00
1 parent 1760b073c7
commit 343eb1d659
22 files changed
+572 -308

No files matched your search

+17 -42
View File
@@ -47,7 +47,7 @@
import AccountPending from '$lib/components/layout/Overlay/AccountPending.svelte';
import UpdateInfoToast from '$lib/components/layout/UpdateInfoToast.svelte';
import Spinner from '$lib/components/common/Spinner.svelte';
import { Shortcut, shortcuts } from '$lib/shortcuts';
import { loadKeybindings, matchKeybinding, Shortcut } from '$lib/shortcuts';
const i18n = getContext('i18n');
@@ -105,6 +105,7 @@
if (userSettings?.ui) {
settings.set(userSettings.ui);
}
loadKeybindings(userSettings?.keybindings);
setTextScale($settings?.textScale ?? 1);
@@ -245,80 +246,54 @@
// Tool servers can be slow or unreachable; they are not needed to initialize chat.
setToolServers().catch((e) => console.error('Failed to load tool servers:', e));
// Helper function to check if the pressed keys match the shortcut definition
const isShortcutMatch = (event: KeyboardEvent, shortcut): boolean => {
const keys = shortcut?.keys || [];
const normalized = keys.map((k) => k.toLowerCase());
const needCtrl = normalized.includes('ctrl') || normalized.includes('mod');
const needShift = normalized.includes('shift');
const needAlt = normalized.includes('alt');
const mainKeys = normalized.filter((k) => !['ctrl', 'shift', 'alt', 'mod'].includes(k));
// Get the main key pressed
const keyPressed = event.key.toLowerCase();
// Check modifiers
if (needShift && !event.shiftKey) return false;
if (needCtrl && !(event.ctrlKey || event.metaKey)) return false;
if (!needCtrl && (event.ctrlKey || event.metaKey)) return false;
if (needAlt && !event.altKey) return false;
if (!needAlt && event.altKey) return false;
if (mainKeys.length && !mainKeys.includes(keyPressed)) return false;
return true;
};
const setupKeyboardShortcuts = () => {
document.addEventListener('keydown', async (event) => {
if (isShortcutMatch(event, shortcuts[Shortcut.SEARCH])) {
const shortcut = matchKeybinding(event);
if (shortcut === Shortcut.SEARCH) {
console.log('Shortcut triggered: SEARCH');
event.preventDefault();
showSearch.set(!$showSearch);
} else if (isShortcutMatch(event, shortcuts[Shortcut.NEW_CHAT])) {
} else if (shortcut === Shortcut.NEW_CHAT) {
console.log('Shortcut triggered: NEW_CHAT');
event.preventDefault();
document.getElementById('sidebar-new-chat-button')?.click();
} else if (isShortcutMatch(event, shortcuts[Shortcut.FOCUS_INPUT])) {
} else if (shortcut === Shortcut.FOCUS_INPUT) {
console.log('Shortcut triggered: FOCUS_INPUT');
event.preventDefault();
document.getElementById('chat-input')?.focus();
} else if (isShortcutMatch(event, shortcuts[Shortcut.COPY_LAST_CODE_BLOCK])) {
} else if (shortcut === Shortcut.COPY_LAST_CODE_BLOCK) {
console.log('Shortcut triggered: COPY_LAST_CODE_BLOCK');
event.preventDefault();
[...document.getElementsByClassName('copy-code-button')]?.at(-1)?.click();
} else if (isShortcutMatch(event, shortcuts[Shortcut.COPY_LAST_RESPONSE])) {
} else if (shortcut === Shortcut.COPY_LAST_RESPONSE) {
console.log('Shortcut triggered: COPY_LAST_RESPONSE');
event.preventDefault();
[...document.getElementsByClassName('copy-response-button')]?.at(-1)?.click();
} else if (isShortcutMatch(event, shortcuts[Shortcut.TOGGLE_SIDEBAR])) {
} else if (shortcut === Shortcut.TOGGLE_SIDEBAR) {
console.log('Shortcut triggered: TOGGLE_SIDEBAR');
event.preventDefault();
showSidebar.set(!$showSidebar);
} else if (isShortcutMatch(event, shortcuts[Shortcut.DELETE_CHAT])) {
} else if (shortcut === Shortcut.DELETE_CHAT) {
console.log('Shortcut triggered: DELETE_CHAT');
event.preventDefault();
document.getElementById('delete-chat-button')?.click();
} else if (isShortcutMatch(event, shortcuts[Shortcut.OPEN_SETTINGS])) {
} else if (shortcut === Shortcut.OPEN_SETTINGS) {
console.log('Shortcut triggered: OPEN_SETTINGS');
event.preventDefault();
showSettings.set(!$showSettings);
} else if (isShortcutMatch(event, shortcuts[Shortcut.SHOW_SHORTCUTS])) {
} else if (shortcut === Shortcut.SHOW_SHORTCUTS) {
console.log('Shortcut triggered: SHOW_SHORTCUTS');
event.preventDefault();
showSettings.set('shortcuts');
} else if (isShortcutMatch(event, shortcuts[Shortcut.CLOSE_MODAL])) {
} else if (shortcut === Shortcut.CLOSE_MODAL) {
console.log('Shortcut triggered: CLOSE_MODAL');
event.preventDefault();
showSettings.set(false);
} else if (isShortcutMatch(event, shortcuts[Shortcut.OPEN_MODEL_SELECTOR])) {
} else if (shortcut === Shortcut.OPEN_MODEL_SELECTOR) {
console.log('Shortcut triggered: OPEN_MODEL_SELECTOR');
event.preventDefault();
document.getElementById('model-selector-0-button')?.click();
} else if (isShortcutMatch(event, shortcuts[Shortcut.NEW_TEMPORARY_CHAT])) {
} else if (shortcut === Shortcut.NEW_TEMPORARY_CHAT) {
console.log('Shortcut triggered: NEW_TEMPORARY_CHAT');
event.preventDefault();
if ($user?.role !== 'admin' && $user?.permissions?.chat?.temporary_enforced) {
@@ -330,12 +305,12 @@
setTimeout(() => {
document.getElementById('new-chat-button')?.click();
}, 0);
} else if (isShortcutMatch(event, shortcuts[Shortcut.GENERATE_MESSAGE_PAIR])) {
} else if (shortcut === Shortcut.GENERATE_MESSAGE_PAIR) {
console.log('Shortcut triggered: GENERATE_MESSAGE_PAIR');
event.preventDefault();
document.getElementById('generate-message-pair-button')?.click();
} else if (
isShortcutMatch(event, shortcuts[Shortcut.REGENERATE_RESPONSE]) &&
shortcut === Shortcut.REGENERATE_RESPONSE &&
document.activeElement?.id === 'chat-input'
) {
console.log('Shortcut triggered: REGENERATE_RESPONSE');
@@ -1,5 +1,5 @@
<script>
import CreateKnowledgeBase from '$lib/components/workspace/Knowledge/CreateKnowledgeBase.svelte';
import Knowledge from '$lib/components/workspace/Knowledge.svelte';
</script>
<CreateKnowledgeBase />
<Knowledge showCreateOnMount={true} createModalCloseHref="/workspace/knowledge" />
@@ -1,79 +1,5 @@
<script lang="ts">
import { toast } from 'svelte-sonner';
import { goto } from '$app/navigation';
import { onMount, tick, getContext } from 'svelte';
const i18n = getContext('i18n');
import { createNewPrompt } from '$lib/apis/prompts';
import PromptEditor from '$lib/components/workspace/Prompts/PromptEditor.svelte';
let prompt: {
name: string;
command: string;
content: string;
tags: string[];
access_grants: any[];
} | null = null;
let clone = false;
const onSubmit = async (_prompt) => {
const res = await createNewPrompt(localStorage.token, _prompt).catch((error) => {
toast.error(`${error}`);
return null;
});
if (res) {
toast.success($i18n.t('Prompt created successfully'));
await goto('/workspace/prompts');
}
};
onMount(async () => {
window.addEventListener('message', async (event) => {
console.log(event);
if (
!['https://openwebui.com', 'https://www.openwebui.com', 'http://localhost:9999'].includes(
event.origin
)
)
return;
const _prompt = JSON.parse(event.data);
console.log('Received prompt via window message:', _prompt);
clone = true;
prompt = {
name: _prompt.name || _prompt.title || 'Prompt',
command: _prompt.command,
content: _prompt.content,
tags: _prompt.tags || [],
access_grants: _prompt.access_grants !== undefined ? _prompt.access_grants : []
};
});
if (window.opener ?? false) {
window.opener.postMessage('loaded', '*');
}
if (sessionStorage.prompt) {
const _prompt = JSON.parse(sessionStorage.prompt);
sessionStorage.removeItem('prompt');
console.log('Received prompt via sessionStorage:', _prompt);
clone = true;
prompt = {
name: _prompt.name || _prompt.title || 'Prompt',
command: _prompt.command,
content: _prompt.content,
tags: _prompt.tags || [],
access_grants: _prompt.access_grants !== undefined ? _prompt.access_grants : []
};
}
});
<script>
import Prompts from '$lib/components/workspace/Prompts.svelte';
</script>
{#key prompt}
<PromptEditor {prompt} {onSubmit} {clone} />
{/key}
<Prompts showCreateOnMount={true} createModalCloseHref="/workspace/prompts" />