Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
chenpangpang
open-webui
Commits
a7bb692a
Unverified
Commit
a7bb692a
authored
Feb 15, 2024
by
Timothy Jaeryang Baek
Committed by
GitHub
Feb 15, 2024
Browse files
Merge pull request #751 from ollama-webui/styling
feat: fullscreen mode
parents
7e2508e4
dc322084
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
256 additions
and
219 deletions
+256
-219
src/lib/components/chat/MessageInput.svelte
src/lib/components/chat/MessageInput.svelte
+15
-8
src/lib/components/chat/MessageInput/Documents.svelte
src/lib/components/chat/MessageInput/Documents.svelte
+1
-1
src/lib/components/chat/MessageInput/Models.svelte
src/lib/components/chat/MessageInput/Models.svelte
+1
-1
src/lib/components/chat/MessageInput/PromptCommands.svelte
src/lib/components/chat/MessageInput/PromptCommands.svelte
+1
-1
src/lib/components/chat/Messages.svelte
src/lib/components/chat/Messages.svelte
+99
-89
src/lib/components/chat/Messages/Placeholder.svelte
src/lib/components/chat/Messages/Placeholder.svelte
+1
-1
src/lib/components/chat/Messages/ResponseMessage.svelte
src/lib/components/chat/Messages/ResponseMessage.svelte
+3
-5
src/lib/components/chat/Settings/Models.svelte
src/lib/components/chat/Settings/Models.svelte
+2
-2
src/lib/components/layout/Navbar.svelte
src/lib/components/layout/Navbar.svelte
+1
-1
src/lib/components/layout/Sidebar.svelte
src/lib/components/layout/Sidebar.svelte
+6
-2
src/routes/(app)/+page.svelte
src/routes/(app)/+page.svelte
+55
-46
src/routes/(app)/c/[id]/+page.svelte
src/routes/(app)/c/[id]/+page.svelte
+69
-61
src/routes/error/+page.svelte
src/routes/error/+page.svelte
+2
-1
No files found.
src/lib/components/chat/MessageInput.svelte
View file @
a7bb692a
...
...
@@ -55,6 +55,11 @@
let isRecording = false;
const MIN_DECIBELS = -45;
const scrollToBottom = () => {
const element = document.getElementById('messages-container');
element.scrollTop = element.scrollHeight;
};
const startRecording = async () => {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
mediaRecorder = new MediaRecorder(stream);
...
...
@@ -371,17 +376,17 @@
</div>
{/if}
<div class="
fixed bottom-0
w-full">
<div class="px-2.5
pt-2.5
-mb-0.5 mx-auto inset-x-0 bg-transparent flex justify-center">
<div class="w-full">
<div class="px-2.5 -mb-0.5 mx-auto inset-x-0 bg-transparent flex justify-center">
<div class="flex flex-col max-w-3xl w-full">
<div>
<div
class="relative"
>
{#if autoScroll === false && messages.length > 0}
<div class=" flex justify-center
mb-4
">
<div class="
absolute -top-12 left-0 right-0
flex justify-center">
<button
class=" bg-white border border-gray-100 dark:border-none dark:bg-white/20 p-1.5 rounded-full"
on:click={() => {
autoScroll = true;
window.
scrollTo
({ top: document.body.scrollHeight, behavior: 'smooth' }
);
scrollTo
Bottom(
);
}}
>
<svg
...
...
@@ -401,7 +406,7 @@
{/if}
</div>
<div class="w-full">
<div class="w-full
relative
">
{#if prompt.charAt(0) === '/'}
<Prompts bind:this={promptsElement} bind:prompt />
{:else if prompt.charAt(0) === '#'}
...
...
@@ -432,14 +437,16 @@
bind:chatInputPlaceholder
{messages}
/>
{:else if messages.length == 0 && suggestionPrompts.length !== 0}
{/if}
{#if messages.length == 0 && suggestionPrompts.length !== 0}
<Suggestions {suggestionPrompts} {submitPrompt} />
{/if}
</div>
</div>
</div>
<div class="bg-white dark:bg-gray-900">
<div class="max-w-3xl px-2.5
-mb-0.5
mx-auto inset-x-0">
<div class="max-w-3xl px-2.5 mx-auto inset-x-0">
<div class=" pb-2">
<input
bind:this={filesInputElement}
...
...
src/lib/components/chat/MessageInput/Documents.svelte
View file @
a7bb692a
...
...
@@ -88,7 +88,7 @@
</script>
{#if filteredItems.length > 0 || prompt.split(' ')?.at(0)?.substring(1).startsWith('http')}
<div class="md:px-2 mb-3 text-left w-full">
<div class="md:px-2 mb-3 text-left w-full
absolute bottom-0 left-0 right-0
">
<div class="flex w-full rounded-lg border border-gray-100 dark:border-gray-700">
<div class=" bg-gray-100 dark:bg-gray-700 w-10 rounded-l-lg text-center">
<div class=" text-lg font-semibold mt-2">#</div>
...
...
src/lib/components/chat/MessageInput/Models.svelte
View file @
a7bb692a
...
...
@@ -120,7 +120,7 @@
</script>
{#if filteredModels.length > 0}
<div class="md:px-2 mb-3 text-left w-full">
<div class="md:px-2 mb-3 text-left w-full
absolute bottom-0 left-0 right-0
">
<div class="flex w-full rounded-lg border border-gray-100 dark:border-gray-700">
<div class=" bg-gray-100 dark:bg-gray-700 w-10 rounded-l-lg text-center">
<div class=" text-lg font-semibold mt-2">@</div>
...
...
src/lib/components/chat/MessageInput/PromptCommands.svelte
View file @
a7bb692a
...
...
@@ -47,7 +47,7 @@
</script>
{#if filteredPromptCommands.length > 0}
<div class="md:px-2 mb-3 text-left w-full">
<div class="md:px-2 mb-3 text-left w-full
absolute bottom-0 left-0 right-0
">
<div class="flex w-full rounded-lg border border-gray-100 dark:border-gray-700">
<div class=" bg-gray-100 dark:bg-gray-700 w-10 rounded-l-lg text-center">
<div class=" text-lg font-semibold mt-2">/</div>
...
...
src/lib/components/chat/Messages.svelte
View file @
a7bb692a
...
...
@@ -29,10 +29,15 @@
$: if (autoScroll && bottomPadding) {
(async () => {
await tick();
window.
scrollTo
({ top: document.body.scrollHeight, behavior: 'smooth' }
);
scrollTo
Bottom(
);
})();
}
const scrollToBottom = () => {
const element = document.getElementById('messages-container');
element.scrollTop = element.scrollHeight;
};
const copyToClipboard = (text) => {
if (!navigator.clipboard) {
var textArea = document.createElement('textarea');
...
...
@@ -160,10 +165,11 @@
await tick();
autoScroll = window.innerHeight + window.scrollY >= document.body.offsetHeight - 40;
const element = document.getElementById('messages-container');
autoScroll = element.scrollHeight - element.scrollTop <= element.clientHeight + 50;
setTimeout(() => {
window.
scrollTo
({ top: document.body.scrollHeight, behavior: 'smooth' }
);
scrollTo
Bottom(
);
}, 100);
};
...
...
@@ -208,9 +214,11 @@
await tick();
autoScroll = window.innerHeight + window.scrollY >= document.body.offsetHeight - 40;
const element = document.getElementById('messages-container');
autoScroll = element.scrollHeight - element.scrollTop <= element.clientHeight + 50;
setTimeout(() => {
window.
scrollTo
({ top: document.body.scrollHeight, behavior: 'smooth' }
);
scrollTo
Bottom(
);
}, 100);
};
</script>
...
...
@@ -218,95 +226,97 @@
{#if messages.length == 0}
<Placeholder models={selectedModels} modelfiles={selectedModelfiles} />
{:else}
{#key chatId}
{#each messages as message, messageIdx}
<div class=" w-full">
<div
class="flex flex-col justify-between px-5 mb-3 {$settings?.fullScreenMode ?? null
? 'max-w-full'
: 'max-w-3xl'} mx-auto rounded-lg group"
>
{#if message.role === 'user'}
<UserMessage
user={$user}
{message}
siblings={message.parentId !== null
? history.messages[message.parentId]?.childrenIds ?? []
: Object.values(history.messages)
.filter((message) => message.parentId === null)
.map((message) => message.id) ?? []}
{confirmEditMessage}
{showPreviousMessage}
{showNextMessage}
{copyToClipboard}
/>
{#if messages.length - 1 === messageIdx && processing !== ''}
<div class="flex my-2.5 ml-12 items-center w-fit space-x-2.5">
<div class=" dark:text-blue-100">
<svg
class=" w-4 h-4 translate-y-[0.5px]"
fill="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
><style>
.spinner_qM83 {
animation: spinner_8HQG 1.05s infinite;
}
.spinner_oXPr {
animation-delay: 0.1s;
}
.spinner_ZTLf {
animation-delay: 0.2s;
}
@keyframes spinner_8HQG {
0%,
57.14% {
animation-timing-function: cubic-bezier(0.33, 0.66, 0.66, 1);
transform: translate(0);
<div class=" pb-10">
{#key chatId}
{#each messages as message, messageIdx}
<div class=" w-full">
<div
class="flex flex-col justify-between px-5 mb-3 {$settings?.fullScreenMode ?? null
? 'max-w-full'
: 'max-w-3xl'} mx-auto rounded-lg group"
>
{#if message.role === 'user'}
<UserMessage
user={$user}
{message}
siblings={message.parentId !== null
? history.messages[message.parentId]?.childrenIds ?? []
: Object.values(history.messages)
.filter((message) => message.parentId === null)
.map((message) => message.id) ?? []}
{confirmEditMessage}
{showPreviousMessage}
{showNextMessage}
{copyToClipboard}
/>
{#if messages.length - 1 === messageIdx && processing !== ''}
<div class="flex my-2.5 ml-12 items-center w-fit space-x-2.5">
<div class=" dark:text-blue-100">
<svg
class=" w-4 h-4 translate-y-[0.5px]"
fill="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
><style>
.spinner_qM83 {
animation: spinner_8HQG 1.05s infinite;
}
28.57% {
animation-timing-function: cubic-bezier(0.33, 0, 0.66, 0.33);
transform: translateY(-6px);
.spinner_oXPr {
animation-delay: 0.1s;
}
100%
{
transform: translate(0)
;
.spinner_ZTLf
{
animation-delay: 0.2s
;
}
}
</style><circle class="spinner_qM83" cx="4" cy="12" r="2.5" /><circle
class="spinner_qM83 spinner_oXPr"
cx="12"
cy="12"
r="2.5"
/><circle class="spinner_qM83 spinner_ZTLf" cx="20" cy="12" r="2.5" /></svg
>
</div>
<div class=" text-sm font-medium">
{processing}
@keyframes spinner_8HQG {
0%,
57.14% {
animation-timing-function: cubic-bezier(0.33, 0.66, 0.66, 1);
transform: translate(0);
}
28.57% {
animation-timing-function: cubic-bezier(0.33, 0, 0.66, 0.33);
transform: translateY(-6px);
}
100% {
transform: translate(0);
}
}
</style><circle class="spinner_qM83" cx="4" cy="12" r="2.5" /><circle
class="spinner_qM83 spinner_oXPr"
cx="12"
cy="12"
r="2.5"
/><circle class="spinner_qM83 spinner_ZTLf" cx="20" cy="12" r="2.5" /></svg
>
</div>
<div class=" text-sm font-medium">
{processing}
</div>
</div>
</div>
{/if}
{:else}
<ResponseMessage
{message}
modelfiles={selectedModelfiles}
siblings={history.messages[message.parentId]?.childrenIds ?? []}
isLastMessage={messageIdx + 1 === messages.length}
{confirmEditResponseMessage}
{showPreviousMessage}
{showNextMessage}
{rateMessage}
{copyToClipboard}
{continueGeneration}
{regenerateResponse}
/>
{/if}
{:else}
<ResponseMessage
{message}
modelfiles={selectedModelfiles}
siblings={history.messages[message.parentId]?.childrenIds ?? []}
isLastMessage={messageIdx + 1 === messages.length}
{confirmEditResponseMessage}
{showPreviousMessage}
{showNextMessage}
{rateMessage}
{copyToClipboard}
{continueGeneration}
{regenerateResponse}
/>
{/if}
</div>
</div>
</div>
{/each}
{/each}
{#if bottomPadding}
<div class=" mb-10" />
{/if}
{/key}
{#if bottomPadding}
<div class=" mb-10" />
{/if}
{/key}
</div>
{/if}
src/lib/components/chat/Messages/Placeholder.svelte
View file @
a7bb692a
...
...
@@ -16,7 +16,7 @@
</script>
{#if models.length > 0}
<div class="m-auto text-center max-w-md
pb-56
px-2">
<div class="m-auto text-center max-w-md px-2">
<div class="flex justify-center mt-8">
<div class="flex -space-x-4 mb-1">
{#each models as model, modelIdx}
...
...
src/lib/components/chat/Messages/ResponseMessage.svelte
View file @
a7bb692a
...
...
@@ -270,9 +270,7 @@
{#if message.model in modelfiles}
{modelfiles[message.model]?.title}
{:else}
Ollama <span class=" text-gray-500 text-sm font-medium"
>{message.model ? ` ${message.model}` : ''}</span
>
{message.model ? ` ${message.model}` : ''}
{/if}
{#if message.timestamp}
...
...
@@ -365,7 +363,7 @@
{#if message.done}
<div class=" flex justify-start space-x-1 -mt-2 overflow-x-auto buttons">
{#if siblings.length > 1}
<div class="flex self-center">
<div class="flex self-center
min-w-fit
">
<button
class="self-center"
on:click={() => {
...
...
@@ -386,7 +384,7 @@
</svg>
</button>
<div class="text-xs font-bold self-center">
<div class="text-xs font-bold self-center
min-w-fit
">
{siblings.indexOf(message.id) + 1} / {siblings.length}
</div>
...
...
src/lib/components/chat/Settings/Models.svelte
View file @
a7bb692a
...
...
@@ -3,7 +3,7 @@
import toast from 'svelte-french-toast';
import { createModel, deleteModel, pullModel } from '$lib/apis/ollama';
import { WEBUI_API_BASE_URL } from '$lib/constants';
import { WEBUI_API_BASE_URL
, WEBUI_NAME
} from '$lib/constants';
import { models, user } from '$lib/stores';
import { splitStream } from '$lib/utils';
...
...
@@ -59,7 +59,7 @@
} else {
toast.success(`Model '${modelName}' has been successfully downloaded.`);
const notification = new Notification(
`Ollama`
, {
const notification = new Notification(
WEBUI_NAME
, {
body: `Model '${modelName}' has been successfully downloaded.`,
icon: '/favicon.png'
});
...
...
src/lib/components/layout/Navbar.svelte
View file @
a7bb692a
...
...
@@ -69,7 +69,7 @@
<ShareChatModal bind:show={showShareChatModal} {downloadChat} {shareChat} />
<nav
id="nav"
class="
fixed
py-2.5 top-0 flex flex-row justify-center bg-white/95 dark:bg-gray-900/90 dark:text-gray-200 backdrop-blur-xl
w-screen
z-30"
class="
sticky
py-2.5 top-0 flex flex-row justify-center bg-white/95 dark:bg-gray-900/90 dark:text-gray-200 backdrop-blur-xl z-30"
>
<div
class=" flex {$settings?.fullScreenMode ?? null
...
...
src/lib/components/layout/Sidebar.svelte
View file @
a7bb692a
...
...
@@ -89,10 +89,14 @@
bind:this={navElement}
class="h-screen {show
? ''
: '-translate-x-[260px]'} w-[260px]
fixed top-0 left-0 z-40 transition
bg-black text-gray-200 shadow-2xl text-sm
: '-translate-x-[260px]
w-[0px]
'} w-[260px]
min-w[260px]
bg-black text-gray-200 shadow-2xl text-sm
transition z-40 fixed top-0 left-0 lg:relative
"
>
<div class="py-2.5 my-auto flex flex-col justify-between h-screen">
<div
class="py-2.5 my-auto flex flex-col justify-between h-screen w-[260px] {show
? ''
: 'invisible'}"
>
<div class="px-2.5 flex justify-center space-x-2">
<button
id="sidebar-new-chat-button"
...
...
src/routes/(app)/+page.svelte
View file @
a7bb692a
...
...
@@ -137,6 +137,11 @@
});
};
const scrollToBottom = () => {
const element = document.getElementById('messages-container');
element.scrollTop = element.scrollHeight;
};
//////////////////////////
// Ollama functions
//////////////////////////
...
...
@@ -316,7 +321,7 @@
await tick();
// Scroll down
window.
scrollTo
({ top: document.body.scrollHeight }
);
scrollTo
Bottom(
);
const messagesBody = [
$settings.system
...
...
@@ -440,7 +445,7 @@
selectedModelfile.title.charAt(0).toUpperCase() +
selectedModelfile.title.slice(1)
}`
: `
Ollama -
${model}`,
: `${model}`,
{
body: responseMessage.content,
icon: selectedModelfile?.imageUrl ?? '/favicon.png'
...
...
@@ -469,7 +474,7 @@
}
if (autoScroll) {
window.
scrollTo
({ top: document.body.scrollHeight }
);
scrollTo
Bottom(
);
}
}
...
...
@@ -508,7 +513,7 @@
await tick();
if (autoScroll) {
window.
scrollTo
({ top: document.body.scrollHeight }
);
scrollTo
Bottom(
);
}
if (messages.length == 2 && messages.at(1).content !== '') {
...
...
@@ -519,8 +524,7 @@
const sendPromptOpenAI = async (model, userPrompt, responseMessageId, _chatId) => {
const responseMessage = history.messages[responseMessageId];
window.scrollTo({ top: document.body.scrollHeight });
scrollToBottom();
const res = await generateOpenAIChatCompletion(localStorage.token, {
model: model,
...
...
@@ -628,7 +632,7 @@
}
if (autoScroll) {
window.
scrollTo
({ top: document.body.scrollHeight }
);
scrollTo
Bottom(
);
}
}
...
...
@@ -672,7 +676,7 @@
await tick();
if (autoScroll) {
window.
scrollTo
({ top: document.body.scrollHeight }
);
scrollTo
Bottom(
);
}
if (messages.length == 2) {
...
...
@@ -783,47 +787,52 @@
};
</script>
<svelte:window
on:scroll={(e) => {
autoScroll = window.innerHeight + window.scrollY >= document.body.offsetHeight - 40;
}}
/>
<Navbar {title} shareEnabled={messages.length > 0} {initNewChat} {tags} {addTag} {deleteTag} />
<div class="min-h-screen w-full flex justify-center">
<div class=" py-2.5 flex flex-col justify-between w-full">
<div class="min-h-screen max-h-screen w-full flex flex-col">
<Navbar {title} shareEnabled={messages.length > 0} {initNewChat} {tags} {addTag} {deleteTag} />
<div class="flex flex-col flex-auto">
<div
class="{$settings?.fullScreenMode ?? null
? 'max-w-full'
: 'max-w-2xl md:px-0'} mx-auto w-full px-4 mt-10"
class=" pb-2.5 flex flex-col justify-between w-full flex-auto overflow-auto h-0"
id="messages-container"
on:scroll={(e) => {
autoScroll = e.target.scrollHeight - e.target.scrollTop <= e.target.clientHeight + 50;
}}
>
<ModelSelector bind:selectedModels disabled={messages.length > 0} />
<div
class="{$settings?.fullScreenMode ?? null
? 'max-w-full'
: 'max-w-2xl md:px-0'} mx-auto w-full px-4"
>
<ModelSelector
bind:selectedModels
disabled={messages.length > 0 && !selectedModels.includes('')}
/>
</div>
<div class=" h-full w-full flex flex-col py-8">
<Messages
chatId={$chatId}
{selectedModels}
{selectedModelfiles}
{processing}
bind:history
bind:messages
bind:autoScroll
bottomPadding={files.length > 0}
{sendPrompt}
{continueGeneration}
{regenerateResponse}
/>
</div>
</div>
<div class=" h-full mt-10 mb-32 w-full flex flex-col">
<Messages
chatId={$chatId}
{selectedModels}
{selectedModelfiles}
{processing}
bind:history
bind:messages
bind:autoScroll
bottomPadding={files.length > 0}
{sendPrompt}
{continueGeneration}
{regenerateResponse}
/>
</div>
<MessageInput
bind:files
bind:prompt
bind:autoScroll
suggestionPrompts={selectedModelfile?.suggestionPrompts ?? $config.default_prompt_suggestions}
{messages}
{submitPrompt}
{stopResponse}
/>
</div>
<MessageInput
bind:files
bind:prompt
bind:autoScroll
suggestionPrompts={selectedModelfile?.suggestionPrompts ?? $config.default_prompt_suggestions}
{messages}
{submitPrompt}
{stopResponse}
/>
</div>
src/routes/(app)/c/[id]/+page.svelte
View file @
a7bb692a
...
...
@@ -153,6 +153,11 @@
}
};
const scrollToBottom = () => {
const element = document.getElementById('messages-container');
element.scrollTop = element.scrollHeight;
};
//////////////////////////
// Ollama functions
//////////////////////////
...
...
@@ -330,7 +335,7 @@
await tick();
// Scroll down
window.
scrollTo
({ top: document.body.scrollHeight }
);
scrollTo
Bottom(
);
const messagesBody = [
$settings.system
...
...
@@ -454,7 +459,7 @@
selectedModelfile.title.charAt(0).toUpperCase() +
selectedModelfile.title.slice(1)
}`
: `
Ollama -
${model}`,
: `${model}`,
{
body: responseMessage.content,
icon: selectedModelfile?.imageUrl ?? '/favicon.png'
...
...
@@ -483,7 +488,7 @@
}
if (autoScroll) {
window.
scrollTo
({ top: document.body.scrollHeight }
);
scrollTo
Bottom(
);
}
}
...
...
@@ -522,7 +527,7 @@
await tick();
if (autoScroll) {
window.
scrollTo
({ top: document.body.scrollHeight }
);
scrollTo
Bottom(
);
}
if (messages.length == 2 && messages.at(1).content !== '') {
...
...
@@ -534,7 +539,7 @@
const sendPromptOpenAI = async (model, userPrompt, responseMessageId, _chatId) => {
const responseMessage = history.messages[responseMessageId];
window.
scrollTo
({ top: document.body.scrollHeight }
);
scrollTo
Bottom(
);
const res = await generateOpenAIChatCompletion(localStorage.token, {
model: model,
...
...
@@ -642,7 +647,7 @@
}
if (autoScroll) {
window.
scrollTo
({ top: document.body.scrollHeight }
);
scrollTo
Bottom(
);
}
}
...
...
@@ -686,7 +691,7 @@
await tick();
if (autoScroll) {
window.
scrollTo
({ top: document.body.scrollHeight }
);
scrollTo
Bottom(
);
}
if (messages.length == 2) {
...
...
@@ -797,66 +802,69 @@
});
</script>
<svelte:window
on:scroll={(e) => {
autoScroll = window.innerHeight + window.scrollY >= document.body.offsetHeight - 40;
}}
/>
{#if loaded}
<Navbar
{title}
shareEnabled={messages.length > 0}
initNewChat={async () => {
if (currentRequestId !== null) {
await cancelChatCompletion(localStorage.token, currentRequestId);
currentRequestId = null;
}
<div class="min-h-screen max-h-screen w-full flex flex-col">
<Navbar
{title}
shareEnabled={messages.length > 0}
initNewChat={async () => {
if (currentRequestId !== null) {
await cancelChatCompletion(localStorage.token, currentRequestId);
currentRequestId = null;
}
goto('/');
}}
{tags}
{addTag}
{deleteTag}
/>
<div class="min-h-screen w-full flex justify-center">
<div class=" py-2.5 flex flex-col justify-between w-full">
goto('/');
}}
{tags}
{addTag}
{deleteTag}
/>
<div class="flex flex-col flex-auto">
<div
class="{$settings?.fullScreenMode ?? null
? 'max-w-full'
: 'max-w-2xl md:px-0'} mx-auto w-full px-4 mt-10"
class=" pb-2.5 flex flex-col justify-between w-full flex-auto overflow-auto h-0"
id="messages-container"
on:scroll={(e) => {
autoScroll = e.target.scrollHeight - e.target.scrollTop <= e.target.clientHeight + 50;
}}
>
<ModelSelector
bind:selectedModels
disabled={messages.length > 0 && !selectedModels.includes('')}
/>
<div
class="{$settings?.fullScreenMode ?? null
? 'max-w-full'
: 'max-w-2xl md:px-0'} mx-auto w-full px-4"
>
<ModelSelector
bind:selectedModels
disabled={messages.length > 0 && !selectedModels.includes('')}
/>
</div>
<div class=" h-full w-full flex flex-col py-8">
<Messages
chatId={$chatId}
{selectedModels}
{selectedModelfiles}
{processing}
bind:history
bind:messages
bind:autoScroll
bottomPadding={files.length > 0}
{sendPrompt}
{continueGeneration}
{regenerateResponse}
/>
</div>
</div>
<div class=" h-full mt-10 mb-32 w-full flex flex-col">
<Messages
chatId={$chatId}
{selectedModels}
{selectedModelfiles}
{processing}
bind:history
bind:messages
bind:autoScroll
bottomPadding={files.length > 0}
{sendPrompt}
{continueGeneration}
{regenerateResponse}
/>
</div>
<MessageInput
bind:files
bind:prompt
bind:autoScroll
suggestionPrompts={selectedModelfile?.suggestionPrompts ??
$config.default_prompt_suggestions}
{messages}
{submitPrompt}
{stopResponse}
/>
</div>
<MessageInput
bind:files
bind:prompt
bind:autoScroll
suggestionPrompts={selectedModelfile?.suggestionPrompts ?? $config.default_prompt_suggestions}
{messages}
{submitPrompt}
{stopResponse}
/>
</div>
{/if}
src/routes/error/+page.svelte
View file @
a7bb692a
<script>
import { goto } from '$app/navigation';
import { WEBUI_NAME } from '$lib/constants';
import { config } from '$lib/stores';
import { onMount } from 'svelte';
...
...
@@ -19,7 +20,7 @@
<div class="absolute rounded-xl w-full h-full backdrop-blur flex justify-center">
<div class="m-auto pb-44 flex flex-col justify-center">
<div class="max-w-md">
<div class="text-center text-2xl font-medium z-50">
Ollama WebUI
Backend Required</div>
<div class="text-center text-2xl font-medium z-50">
{WEBUI_NAME}
Backend Required</div>
<div class=" mt-4 text-center text-sm w-full">
Oops! You're using an unsupported method (frontend only). Please serve the WebUI from
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment