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
196f91d6
"...git@developer.sourcefind.cn:OpenDAS/torch-harmonics.git" did not exist on "b5c410c08661b87750d35a235ddd039097177810"
Commit
196f91d6
authored
Mar 31, 2024
by
Jun Siang Cheah
Browse files
feat: add frontend support for locally sharing chats
parent
bfbfdae1
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
433 additions
and
106 deletions
+433
-106
src/lib/apis/chats/index.ts
src/lib/apis/chats/index.ts
+96
-0
src/lib/components/chat/Messages.svelte
src/lib/components/chat/Messages.svelte
+3
-0
src/lib/components/chat/Messages/ResponseMessage.svelte
src/lib/components/chat/Messages/ResponseMessage.svelte
+82
-76
src/lib/components/chat/Messages/UserMessage.svelte
src/lib/components/chat/Messages/UserMessage.svelte
+26
-23
src/lib/components/chat/ShareChatModal.svelte
src/lib/components/chat/ShareChatModal.svelte
+12
-0
src/lib/components/layout/Navbar.svelte
src/lib/components/layout/Navbar.svelte
+25
-5
src/routes/(app)/+page.svelte
src/routes/(app)/+page.svelte
+1
-1
src/routes/(app)/c/[id]/+page.svelte
src/routes/(app)/c/[id]/+page.svelte
+1
-1
src/routes/(app)/s/[id]/+page.svelte
src/routes/(app)/s/[id]/+page.svelte
+187
-0
No files found.
src/lib/apis/chats/index.ts
View file @
196f91d6
...
@@ -218,6 +218,102 @@ export const getChatById = async (token: string, id: string) => {
...
@@ -218,6 +218,102 @@ export const getChatById = async (token: string, id: string) => {
return
res
;
return
res
;
};
};
export
const
getChatByShareId
=
async
(
token
:
string
,
share_id
:
string
)
=>
{
let
error
=
null
;
const
res
=
await
fetch
(
`
${
WEBUI_API_BASE_URL
}
/chats/share/
${
share_id
}
`
,
{
method
:
'
GET
'
,
headers
:
{
Accept
:
'
application/json
'
,
'
Content-Type
'
:
'
application/json
'
,
...(
token
&&
{
authorization
:
`Bearer
${
token
}
`
})
}
})
.
then
(
async
(
res
)
=>
{
if
(
!
res
.
ok
)
throw
await
res
.
json
();
return
res
.
json
();
})
.
then
((
json
)
=>
{
return
json
;
})
.
catch
((
err
)
=>
{
error
=
err
;
console
.
log
(
err
);
return
null
;
});
if
(
error
)
{
throw
error
;
}
return
res
;
};
export
const
shareChatById
=
async
(
token
:
string
,
id
:
string
)
=>
{
let
error
=
null
;
const
res
=
await
fetch
(
`
${
WEBUI_API_BASE_URL
}
/chats/
${
id
}
/share`
,
{
method
:
'
POST
'
,
headers
:
{
Accept
:
'
application/json
'
,
'
Content-Type
'
:
'
application/json
'
,
...(
token
&&
{
authorization
:
`Bearer
${
token
}
`
})
}
})
.
then
(
async
(
res
)
=>
{
if
(
!
res
.
ok
)
throw
await
res
.
json
();
return
res
.
json
();
})
.
then
((
json
)
=>
{
return
json
;
})
.
catch
((
err
)
=>
{
error
=
err
;
console
.
log
(
err
);
return
null
;
});
if
(
error
)
{
throw
error
;
}
return
res
;
};
export
const
deleteSharedChatById
=
async
(
token
:
string
,
id
:
string
)
=>
{
let
error
=
null
;
const
res
=
await
fetch
(
`
${
WEBUI_API_BASE_URL
}
/chats/
${
id
}
`
,
{
method
:
'
DELETE
'
,
headers
:
{
Accept
:
'
application/json
'
,
'
Content-Type
'
:
'
application/json
'
,
...(
token
&&
{
authorization
:
`Bearer
${
token
}
`
})
}
})
.
then
(
async
(
res
)
=>
{
if
(
!
res
.
ok
)
throw
await
res
.
json
();
return
res
.
json
();
})
.
then
((
json
)
=>
{
return
json
;
})
.
catch
((
err
)
=>
{
error
=
err
;
console
.
log
(
err
);
return
null
;
});
if
(
error
)
{
throw
error
;
}
return
res
;
};
export
const
updateChatById
=
async
(
token
:
string
,
id
:
string
,
chat
:
object
)
=>
{
export
const
updateChatById
=
async
(
token
:
string
,
id
:
string
,
chat
:
object
)
=>
{
let
error
=
null
;
let
error
=
null
;
...
...
src/lib/components/chat/Messages.svelte
View file @
196f91d6
...
@@ -16,6 +16,7 @@
...
@@ -16,6 +16,7 @@
const i18n = getContext('i18n');
const i18n = getContext('i18n');
export let chatId = '';
export let chatId = '';
export let readOnly = false;
export let sendPrompt: Function;
export let sendPrompt: Function;
export let continueGeneration: Function;
export let continueGeneration: Function;
export let regenerateResponse: Function;
export let regenerateResponse: Function;
...
@@ -317,6 +318,7 @@
...
@@ -317,6 +318,7 @@
<UserMessage
<UserMessage
on:delete={() => messageDeleteHandler(message.id)}
on:delete={() => messageDeleteHandler(message.id)}
user={$user}
user={$user}
{readOnly}
{message}
{message}
isFirstMessage={messageIdx === 0}
isFirstMessage={messageIdx === 0}
siblings={message.parentId !== null
siblings={message.parentId !== null
...
@@ -335,6 +337,7 @@
...
@@ -335,6 +337,7 @@
modelfiles={selectedModelfiles}
modelfiles={selectedModelfiles}
siblings={history.messages[message.parentId]?.childrenIds ?? []}
siblings={history.messages[message.parentId]?.childrenIds ?? []}
isLastMessage={messageIdx + 1 === messages.length}
isLastMessage={messageIdx + 1 === messages.length}
{readOnly}
{confirmEditResponseMessage}
{confirmEditResponseMessage}
{showPreviousMessage}
{showPreviousMessage}
{showNextMessage}
{showNextMessage}
...
...
src/lib/components/chat/Messages/ResponseMessage.svelte
View file @
196f91d6
...
@@ -33,6 +33,8 @@
...
@@ -33,6 +33,8 @@
export let isLastMessage = true;
export let isLastMessage = true;
export let readOnly = false;
export let confirmEditResponseMessage: Function;
export let confirmEditResponseMessage: Function;
export let showPreviousMessage: Function;
export let showPreviousMessage: Function;
export let showNextMessage: Function;
export let showNextMessage: Function;
...
@@ -469,31 +471,33 @@
...
@@ -469,31 +471,33 @@
</div>
</div>
{/if}
{/if}
<Tooltip content="Edit" placement="bottom">
{#if !readOnly}
<button
<Tooltip content="Edit" placement="bottom">
class="{isLastMessage
<button
? 'visible'
class="{isLastMessage
: 'invisible group-hover:visible'} p-1 rounded dark:hover:text-white hover:text-black transition"
? 'visible'
on:click={() => {
: 'invisible group-hover:visible'} p-1 rounded dark:hover:text-white hover:text-black transition"
editMessageHandler();
on:click={() => {
}}
editMessageHandler();
>
}}
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="2"
stroke="currentColor"
class="w-4 h-4"
>
>
<path
<svg
stroke-linecap="round"
xmlns="http://www.w3.org/2000/svg"
stroke-linejoin="round"
fill="none"
d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L6.832 19.82a4.5 4.5 0 01-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 011.13-1.897L16.863 4.487zm0 0L19.5 7.125"
viewBox="0 0 24 24"
/>
stroke-width="2"
</svg>
stroke="currentColor"
</button>
class="w-4 h-4"
</Tooltip>
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L6.832 19.82a4.5 4.5 0 01-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 011.13-1.897L16.863 4.487zm0 0L19.5 7.125"
/>
</svg>
</button>
</Tooltip>
{/if}
<Tooltip content="Copy" placement="bottom">
<Tooltip content="Copy" placement="bottom">
<button
<button
...
@@ -521,59 +525,61 @@
...
@@ -521,59 +525,61 @@
</button>
</button>
</Tooltip>
</Tooltip>
<Tooltip content="Good Response" placement="bottom">
{#if !readOnly}
<button
<Tooltip content="Good Response" placement="bottom">
class="{isLastMessage
<button
? 'visible'
class="{isLastMessage
: 'invisible group-hover:visible'} p-1 rounded {message.rating === 1
? 'visible'
? 'bg-gray-100 dark:bg-gray-800'
: 'invisible group-hover:visible'} p-1 rounded {message.rating === 1
: ''} dark:hover:text-white hover:text-black transition"
? 'bg-gray-100 dark:bg-gray-800'
on:click={() => {
: ''} dark:hover:text-white hover:text-black transition"
rateMessage(message.id, 1);
on:click={() => {
}}
rateMessage(message.id, 1);
>
}}
<svg
stroke="currentColor"
fill="none"
stroke-width="2"
viewBox="0 0 24 24"
stroke-linecap="round"
stroke-linejoin="round"
class="w-4 h-4"
xmlns="http://www.w3.org/2000/svg"
><path
d="M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3"
/></svg
>
>
</button>
<svg
</Tooltip>
stroke="currentColor"
fill="none"
stroke-width="2"
viewBox="0 0 24 24"
stroke-linecap="round"
stroke-linejoin="round"
class="w-4 h-4"
xmlns="http://www.w3.org/2000/svg"
><path
d="M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3"
/></svg
>
</button>
</Tooltip>
<Tooltip content="Bad Response" placement="bottom">
<Tooltip content="Bad Response" placement="bottom">
<button
<button
class="{isLastMessage
class="{isLastMessage
? 'visible'
? 'visible'
: 'invisible group-hover:visible'} p-1 rounded {message.rating === -1
: 'invisible group-hover:visible'} p-1 rounded {message.rating === -1
? 'bg-gray-100 dark:bg-gray-800'
? 'bg-gray-100 dark:bg-gray-800'
: ''} dark:hover:text-white hover:text-black transition"
: ''} dark:hover:text-white hover:text-black transition"
on:click={() => {
on:click={() => {
rateMessage(message.id, -1);
rateMessage(message.id, -1);
}}
}}
>
<svg
stroke="currentColor"
fill="none"
stroke-width="2"
viewBox="0 0 24 24"
stroke-linecap="round"
stroke-linejoin="round"
class="w-4 h-4"
xmlns="http://www.w3.org/2000/svg"
><path
d="M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17"
/></svg
>
>
</button>
<svg
</Tooltip>
stroke="currentColor"
fill="none"
stroke-width="2"
viewBox="0 0 24 24"
stroke-linecap="round"
stroke-linejoin="round"
class="w-4 h-4"
xmlns="http://www.w3.org/2000/svg"
><path
d="M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17"
/></svg
>
</button>
</Tooltip>
{/if}
<Tooltip content="Read Aloud" placement="bottom">
<Tooltip content="Read Aloud" placement="bottom">
<button
<button
...
@@ -656,7 +662,7 @@
...
@@ -656,7 +662,7 @@
</button>
</button>
</Tooltip>
</Tooltip>
{#if $config.images}
{#if $config.images
&& !readOnly
}
<Tooltip content="Generate Image" placement="bottom">
<Tooltip content="Generate Image" placement="bottom">
<button
<button
class="{isLastMessage
class="{isLastMessage
...
@@ -752,7 +758,7 @@
...
@@ -752,7 +758,7 @@
</Tooltip>
</Tooltip>
{/if}
{/if}
{#if isLastMessage}
{#if isLastMessage
&& !readOnly
}
<Tooltip content="Continue Response" placement="bottom">
<Tooltip content="Continue Response" placement="bottom">
<button
<button
type="button"
type="button"
...
...
src/lib/components/chat/Messages/UserMessage.svelte
View file @
196f91d6
...
@@ -15,6 +15,7 @@
...
@@ -15,6 +15,7 @@
export let message;
export let message;
export let siblings;
export let siblings;
export let isFirstMessage: boolean;
export let isFirstMessage: boolean;
export let readOnly: boolean;
export let confirmEditMessage: Function;
export let confirmEditMessage: Function;
export let showPreviousMessage: Function;
export let showPreviousMessage: Function;
...
@@ -250,29 +251,31 @@
...
@@ -250,29 +251,31 @@
</div>
</div>
{/if}
{/if}
<Tooltip content="Edit" placement="bottom">
{#if !readOnly}
<button
<Tooltip content="Edit" placement="bottom">
class="invisible group-hover:visible p-1 rounded dark:hover:text-white hover:text-black transition edit-user-message-button"
<button
on:click={() => {
class="invisible group-hover:visible p-1 rounded dark:hover:text-white hover:text-black transition edit-user-message-button"
editMessageHandler();
on:click={() => {
}}
editMessageHandler();
>
}}
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="2"
stroke="currentColor"
class="w-4 h-4"
>
>
<path
<svg
stroke-linecap="round"
xmlns="http://www.w3.org/2000/svg"
stroke-linejoin="round"
fill="none"
d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L6.832 19.82a4.5 4.5 0 01-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 011.13-1.897L16.863 4.487zm0 0L19.5 7.125"
viewBox="0 0 24 24"
/>
stroke-width="2"
</svg>
stroke="currentColor"
</button>
class="w-4 h-4"
</Tooltip>
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L6.832 19.82a4.5 4.5 0 01-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 011.13-1.897L16.863 4.487zm0 0L19.5 7.125"
/>
</svg>
</button>
</Tooltip>
{/if}
<Tooltip content="Copy" placement="bottom">
<Tooltip content="Copy" placement="bottom">
<button
<button
...
@@ -298,7 +301,7 @@
...
@@ -298,7 +301,7 @@
</button>
</button>
</Tooltip>
</Tooltip>
{#if !isFirstMessage}
{#if !isFirstMessage
&& !readOnly
}
<Tooltip content="Delete" placement="bottom">
<Tooltip content="Delete" placement="bottom">
<button
<button
class="invisible group-hover:visible p-1 rounded dark:hover:text-white hover:text-black transition"
class="invisible group-hover:visible p-1 rounded dark:hover:text-white hover:text-black transition"
...
...
src/lib/components/chat/ShareChatModal.svelte
View file @
196f91d6
...
@@ -6,6 +6,7 @@
...
@@ -6,6 +6,7 @@
export let downloadChat: Function;
export let downloadChat: Function;
export let shareChat: Function;
export let shareChat: Function;
export let shareLocalChat: Function;
export let show = false;
export let show = false;
</script>
</script>
...
@@ -23,6 +24,17 @@
...
@@ -23,6 +24,17 @@
{$i18n.t('Share to OpenWebUI Community')}
{$i18n.t('Share to OpenWebUI Community')}
</button>
</button>
<button
class=" self-center px-8 py-1.5 w-full rounded-full text-sm font-medium bg-blue-600 hover:bg-blue-500 text-white mt-1.5"
type="button"
on:click={() => {
shareLocalChat();
show = false;
}}
>
{$i18n.t('Create local share link')}
</button>
<div class="flex justify-center space-x-1 mt-1.5">
<div class="flex justify-center space-x-1 mt-1.5">
<div class=" self-center text-gray-400 text-xs font-medium">{$i18n.t('or')}</div>
<div class=" self-center text-gray-400 text-xs font-medium">{$i18n.t('or')}</div>
...
...
src/lib/components/layout/Navbar.svelte
View file @
196f91d6
...
@@ -5,7 +5,7 @@
...
@@ -5,7 +5,7 @@
const { saveAs } = fileSaver;
const { saveAs } = fileSaver;
import { Separator } from 'bits-ui';
import { Separator } from 'bits-ui';
import { getChatById } from '$lib/apis/chats';
import { getChatById
, shareChatById
} from '$lib/apis/chats';
import { WEBUI_NAME, chatId, modelfiles, settings, showSettings } from '$lib/stores';
import { WEBUI_NAME, chatId, modelfiles, settings, showSettings } from '$lib/stores';
import { slide } from 'svelte/transition';
import { slide } from 'svelte/transition';
...
@@ -19,6 +19,7 @@
...
@@ -19,6 +19,7 @@
import ChevronUpDown from '../icons/ChevronUpDown.svelte';
import ChevronUpDown from '../icons/ChevronUpDown.svelte';
import Menu from './Navbar/Menu.svelte';
import Menu from './Navbar/Menu.svelte';
import TagChatModal from '../chat/TagChatModal.svelte';
import TagChatModal from '../chat/TagChatModal.svelte';
import { copyToClipboard } from '$lib/utils';
const i18n = getContext('i18n');
const i18n = getContext('i18n');
...
@@ -32,7 +33,7 @@
...
@@ -32,7 +33,7 @@
export let addTag: Function;
export let addTag: Function;
export let deleteTag: Function;
export let deleteTag: Function;
export let showModelSelector =
fals
e;
export let showModelSelector =
tru
e;
let showShareChatModal = false;
let showShareChatModal = false;
let showTagChatModal = false;
let showTagChatModal = false;
...
@@ -64,6 +65,23 @@
...
@@ -64,6 +65,23 @@
);
);
};
};
const shareLocalChat = async () => {
const chat = await getChatById(localStorage.token, $chatId);
console.log('shareLocal', chat);
if (chat.share_id) {
const shareUrl = `${window.location.origin}/s/${chat.share_id}`;
toast.info(
$i18n.t('Chat is already shared at {{shareUrl}}, copied to clipboard', { shareUrl })
);
copyToClipboard(shareUrl);
} else {
const sharedChat = await shareChatById(localStorage.token, $chatId);
const shareUrl = `${window.location.origin}/s/${sharedChat.id}`;
toast.info($i18n.t('Chat is now shared at {{shareUrl}}, copied to clipboard', { shareUrl }));
copyToClipboard(shareUrl);
}
};
const downloadChat = async () => {
const downloadChat = async () => {
const chat = (await getChatById(localStorage.token, $chatId)).chat;
const chat = (await getChatById(localStorage.token, $chatId)).chat;
console.log('download', chat);
console.log('download', chat);
...
@@ -80,7 +98,7 @@
...
@@ -80,7 +98,7 @@
};
};
</script>
</script>
<ShareChatModal bind:show={showShareChatModal} {downloadChat} {shareChat} />
<ShareChatModal bind:show={showShareChatModal} {downloadChat} {shareChat}
{shareLocalChat}
/>
<!-- <TagChatModal bind:show={showTagChatModal} {tags} {deleteTag} {addTag} /> -->
<!-- <TagChatModal bind:show={showTagChatModal} {tags} {deleteTag} {addTag} /> -->
<nav id="nav" class=" sticky py-2.5 top-0 flex flex-row justify-center z-30">
<nav id="nav" class=" sticky py-2.5 top-0 flex flex-row justify-center z-30">
<div
<div
...
@@ -135,8 +153,10 @@
...
@@ -135,8 +153,10 @@
</div> -->
</div> -->
<div class="flex items-center w-full max-w-full">
<div class="flex items-center w-full max-w-full">
<div class="w-full flex-1 overflow-hidden max-w-full">
<div class="flex-1 overflow-hidden max-w-full">
<ModelSelector bind:selectedModels />
{#if showModelSelector}
<ModelSelector bind:selectedModels />
{/if}
</div>
</div>
<div class="self-start flex flex-none items-center">
<div class="self-start flex flex-none items-center">
...
...
src/routes/(app)/+page.svelte
View file @
196f91d6
...
@@ -48,7 +48,7 @@
...
@@ -48,7 +48,7 @@
let
messagesContainerElement
:
HTMLDivElement
;
let
messagesContainerElement
:
HTMLDivElement
;
let
currentRequestId
=
null
;
let
currentRequestId
=
null
;
let
showModelSelector
=
fals
e
;
let
showModelSelector
=
tru
e
;
let
selectedModels
=
[
''
];
let
selectedModels
=
[
''
];
let
selectedModelfile
=
null
;
let
selectedModelfile
=
null
;
...
...
src/routes/(app)/c/[id]/+page.svelte
View file @
196f91d6
...
@@ -56,7 +56,7 @@
...
@@ -56,7 +56,7 @@
let
currentRequestId
=
null
;
let
currentRequestId
=
null
;
//
let
chatId
=
$
page
.
params
.
id
;
//
let
chatId
=
$
page
.
params
.
id
;
let
showModelSelector
=
fals
e
;
let
showModelSelector
=
tru
e
;
let
selectedModels
=
[
''
];
let
selectedModels
=
[
''
];
let
selectedModelfile
=
null
;
let
selectedModelfile
=
null
;
...
...
src/routes/(app)/s/[id]/+page.svelte
0 → 100644
View file @
196f91d6
<script lang="ts">
import { onMount, tick, getContext } from 'svelte';
import { goto } from '$app/navigation';
import { page } from '$app/stores';
import { modelfiles, settings, chatId, WEBUI_NAME } from '$lib/stores';
import { convertMessagesToHistory } from '$lib/utils';
import { getChatByShareId } from '$lib/apis/chats';
import Messages from '$lib/components/chat/Messages.svelte';
import Navbar from '$lib/components/layout/Navbar.svelte';
const i18n = getContext('i18n');
let loaded = false;
let autoScroll = true;
let processing = '';
let messagesContainerElement: HTMLDivElement;
// let chatId = $page.params.id;
let showModelSelector = false;
let selectedModels = [''];
let selectedModelfiles = {};
$: selectedModelfiles = selectedModels.reduce((a, tagName, i, arr) => {
const modelfile =
$modelfiles.filter((modelfile) => modelfile.tagName === tagName)?.at(0) ?? undefined;
return {
...a,
...(modelfile && { [tagName]: modelfile })
};
}, {});
let chat = null;
let title = '';
let files = [];
let messages = [];
let history = {
messages: {},
currentId: null
};
$: if (history.currentId !== null) {
let _messages = [];
let currentMessage = history.messages[history.currentId];
while (currentMessage !== null) {
_messages.unshift({ ...currentMessage });
currentMessage =
currentMessage.parentId !== null ? history.messages[currentMessage.parentId] : null;
}
messages = _messages;
} else {
messages = [];
}
$: if ($page.params.id) {
(async () => {
if (await loadSharedChat()) {
await tick();
loaded = true;
window.setTimeout(() => scrollToBottom(), 0);
const chatInput = document.getElementById('chat-textarea');
chatInput?.focus();
} else {
await goto('/');
}
})();
}
//////////////////////////
// Web functions
//////////////////////////
const loadSharedChat = async () => {
await chatId.set($page.params.id);
chat = await getChatByShareId(localStorage.token, $chatId).catch(async (error) => {
await goto('/');
return null;
});
if (chat) {
const chatContent = chat.chat;
if (chatContent) {
console.log(chatContent);
selectedModels =
(chatContent?.models ?? undefined) !== undefined
? chatContent.models
: [chatContent.models ?? ''];
history =
(chatContent?.history ?? undefined) !== undefined
? chatContent.history
: convertMessagesToHistory(chatContent.messages);
title = chatContent.title;
let _settings = JSON.parse(localStorage.getItem('settings') ?? '{}');
await settings.set({
..._settings,
system: chatContent.system ?? _settings.system,
options: chatContent.options ?? _settings.options
});
autoScroll = true;
await tick();
if (messages.length > 0) {
history.messages[messages.at(-1).id].done = true;
}
await tick();
return true;
} else {
return null;
}
}
};
const scrollToBottom = () => {
if (messagesContainerElement) {
messagesContainerElement.scrollTop = messagesContainerElement.scrollHeight;
}
};
onMount(async () => {
if (!($settings.saveChatHistory ?? true)) {
await goto('/');
}
});
</script>
<svelte:head>
<title>
{title
? `${title.length > 30 ? `${title.slice(0, 30)}...` : title} | ${$WEBUI_NAME}`
: `${$WEBUI_NAME}`}
</title>
</svelte:head>
{#if loaded}
<div class="min-h-screen max-h-screen w-full flex flex-col">
<Navbar
{title}
bind:selectedModels
bind:showModelSelector
shareEnabled={false}
initNewChat={async () => {
goto('/');
}}
/>
<div class="flex flex-col flex-auto">
<div
class=" pb-2.5 flex flex-col justify-between w-full flex-auto overflow-auto h-0"
id="messages-container"
bind:this={messagesContainerElement}
on:scroll={(e) => {
autoScroll =
messagesContainerElement.scrollHeight - messagesContainerElement.scrollTop <=
messagesContainerElement.clientHeight + 5;
}}
>
<div class=" h-full w-full flex flex-col py-4">
<Messages
chatId={$chatId}
readOnly={true}
{selectedModels}
{selectedModelfiles}
{processing}
bind:history
bind:messages
bind:autoScroll
bottomPadding={files.length > 0}
sendPrompt={() => {}}
continueGeneration={() => {}}
regenerateResponse={() => {}}
/>
</div>
</div>
</div>
</div>
{/if}
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