Merge branch 'dev' of https://github.com/open-webui/open-webui into feat/rtl-layout-chat-support

This commit is contained in:
Ido Henri Mamia
2024-05-17 01:22:23 +03:00
125 changed files with 8944 additions and 5917 deletions

View File

@@ -47,7 +47,7 @@
<div class="flex flex-col md:flex-row w-full px-6 pb-5 md:space-x-4">
<div
class="flex flex-col w-full dark:text-gray-200 overflow-y-scroll max-h-[22rem] scrollbar-none"
class="flex flex-col w-full dark:text-gray-200 overflow-y-scroll max-h-[22rem] scrollbar-hidden"
>
{#each mergedDocuments as document, documentIdx}
<div class="flex flex-col w-full">

View File

@@ -1,3 +1,3 @@
<div class=" self-center font-bold mb-0.5 capitalize line-clamp-1 contents">
<div class=" self-center font-bold mb-0.5 line-clamp-1 contents">
<slot />
</div>

View File

@@ -4,6 +4,6 @@
export let src = '/user.png';
</script>
<div class={$settings?.chatDirection === 'LTR' ? "mr-4" : "ml-4"}>
<img {src} class=" max-w-[28px] object-cover rounded-full" alt="profile" draggable="false" />
<div class={$settings?.chatDirection === 'LTR' ? "mr-3" : "ml-3"}>>
<img {src} class=" w-8 object-cover rounded-full" alt="profile" draggable="false" />
</div>

View File

@@ -39,9 +39,9 @@
let selectedReason = null;
let comment = '';
$: if (message.annotation.rating === 1) {
$: if (message?.annotation?.rating === 1) {
reasons = LIKE_REASONS;
} else if (message.annotation.rating === -1) {
} else if (message?.annotation?.rating === -1) {
reasons = DISLIKE_REASONS;
}

View File

@@ -65,8 +65,8 @@
let generatingImage = false;
let showRateComment = false;
let showCitationModal = false;
let selectedCitation = null;
$: tokens = marked.lexer(sanitizeResponseContent(message.content));
@@ -338,7 +338,7 @@
($i18n.language === 'dg-DG' ? `/doge.png` : `${WEBUI_BASE_URL}/static/favicon.png`)}
/>
<div class="w-full overflow-hidden">
<div class="w-full overflow-hidden pl-1">
<Name>
{#if message.model in modelfiles}
{modelfiles[message.model]?.title}
@@ -347,8 +347,10 @@
{/if}
{#if message.timestamp}
<span class=" invisible group-hover:visible text-gray-400 text-xs font-medium">
{dayjs(message.timestamp * 1000).format($i18n.t('DD/MM/YYYY HH:mm'))}
<span
class=" self-center invisible group-hover:visible text-gray-400 text-xs font-medium uppercase"
>
{dayjs(message.timestamp * 1000).format($i18n.t('h:mm a'))}
</span>
{/if}
</Name>
@@ -370,7 +372,7 @@
>
<div>
{#if edit === true}
<div class=" w-full">
<div class="w-full bg-gray-50 dark:bg-gray-800 rounded-3xl px-5 py-3 my-2">
<textarea
id="message-edit-{message.id}"
bind:this={editTextAreaElement}
@@ -382,24 +384,26 @@
}}
/>
<div class=" mt-2 mb-1 flex justify-center space-x-2 text-sm font-medium">
<div class=" mt-2 mb-1 flex justify-end space-x-1.5 text-sm font-medium">
<button
class="px-4 py-2 bg-emerald-700 hover:bg-emerald-800 text-gray-100 transition rounded-lg"
on:click={() => {
editMessageConfirmHandler();
}}
>
{$i18n.t('Save')}
</button>
<button
class=" px-4 py-2 hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-100 transition outline outline-1 outline-gray-200 dark:outline-gray-600 rounded-lg"
id="close-edit-message-button"
class=" px-4 py-2 bg-gray-900 hover:bg-gray-850 text-gray-100 transition rounded-3xl"
on:click={() => {
cancelEditMessage();
}}
>
{$i18n.t('Cancel')}
</button>
<button
id="save-edit-message-button"
class="px-4 py-2 bg-white hover:bg-gray-100 text-gray-800 transition rounded-3xl"
on:click={() => {
editMessageConfirmHandler();
}}
>
{$i18n.t('Save')}
</button>
</div>
</div>
{:else}
@@ -476,7 +480,7 @@
<div class="bg-white dark:bg-gray-700 rounded-full size-4">
{idx + 1}
</div>
<div class=" mx-2">
<div class="flex-1 mx-2 line-clamp-1">
{citation.source.name}
</div>
</button>
@@ -487,50 +491,56 @@
{#if message.done || siblings.length > 1}
<div
class=" flex justify-start space-x-1 overflow-x-auto buttons text-gray-700 dark:text-gray-500"
class=" flex justify-start overflow-x-auto buttons text-gray-600 dark:text-gray-500"
>
{#if siblings.length > 1}
<div class="flex self-center min-w-fit">
<div class="flex self-center">
<button
class="self-center dark:hover:text-white hover:text-black transition"
class="self-center p-1 hover:bg-black/5 dark:hover:bg-white/5 dark:hover:text-white hover:text-black rounded-md transition"
on:click={() => {
showPreviousMessage(message);
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
stroke-width="2.5"
class="size-3.5"
>
<path
fill-rule="evenodd"
d="M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z"
clip-rule="evenodd"
stroke-linecap="round"
stroke-linejoin="round"
d="M15.75 19.5 8.25 12l7.5-7.5"
/>
</svg>
</button>
<div class="text-xs font-bold self-center min-w-fit dark:text-gray-100">
{siblings.indexOf(message.id) + 1} / {siblings.length}
<div
class="text-sm tracking-widest font-semibold self-center dark:text-gray-100"
>
{siblings.indexOf(message.id) + 1}/{siblings.length}
</div>
<button
class="self-center dark:hover:text-white hover:text-black transition"
class="self-center p-1 hover:bg-black/5 dark:hover:bg-white/5 dark:hover:text-white hover:text-black rounded-md transition"
on:click={() => {
showNextMessage(message);
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
stroke-width="2.5"
class="size-3.5"
>
<path
fill-rule="evenodd"
d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z"
clip-rule="evenodd"
stroke-linecap="round"
stroke-linejoin="round"
d="m8.25 4.5 7.5 7.5-7.5 7.5"
/>
</svg>
</button>
@@ -543,7 +553,7 @@
<button
class="{isLastMessage
? 'visible'
: 'invisible group-hover:visible'} p-1 rounded dark:hover:text-white hover:text-black transition"
: 'invisible group-hover:visible'} p-1.5 hover:bg-black/5 dark:hover:bg-white/5 rounded-lg dark:hover:text-white hover:text-black transition"
on:click={() => {
editMessageHandler();
}}
@@ -552,7 +562,7 @@
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="2"
stroke-width="2.3"
stroke="currentColor"
class="w-4 h-4"
>
@@ -570,7 +580,7 @@
<button
class="{isLastMessage
? 'visible'
: 'invisible group-hover:visible'} p-1 rounded dark:hover:text-white hover:text-black transition copy-response-button"
: 'invisible group-hover:visible'} p-1.5 hover:bg-black/5 dark:hover:bg-white/5 rounded-lg dark:hover:text-white hover:text-black transition copy-response-button"
on:click={() => {
copyToClipboard(message.content);
}}
@@ -579,7 +589,7 @@
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="2"
stroke-width="2.3"
stroke="currentColor"
class="w-4 h-4"
>
@@ -592,83 +602,12 @@
</button>
</Tooltip>
{#if !readOnly}
<Tooltip content={$i18n.t('Good Response')} placement="bottom">
<button
class="{isLastMessage
? 'visible'
: 'invisible group-hover:visible'} p-1 rounded {message?.annotation
?.rating === 1
? 'bg-gray-100 dark:bg-gray-800'
: ''} dark:hover:text-white hover:text-black transition"
on:click={() => {
rateMessage(message.id, 1);
showRateComment = true;
window.setTimeout(() => {
document
.getElementById(`message-feedback-${message.id}`)
?.scrollIntoView();
}, 0);
}}
>
<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>
</Tooltip>
<Tooltip content={$i18n.t('Bad Response')} placement="bottom">
<button
class="{isLastMessage
? 'visible'
: 'invisible group-hover:visible'} p-1 rounded {message?.annotation
?.rating === -1
? 'bg-gray-100 dark:bg-gray-800'
: ''} dark:hover:text-white hover:text-black transition"
on:click={() => {
rateMessage(message.id, -1);
showRateComment = true;
window.setTimeout(() => {
document
.getElementById(`message-feedback-${message.id}`)
?.scrollIntoView();
}, 0);
}}
>
<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>
</Tooltip>
{/if}
<Tooltip content={$i18n.t('Read Aloud')} placement="bottom">
<button
id="speak-button-{message.id}"
class="{isLastMessage
? 'visible'
: 'invisible group-hover:visible'} p-1 rounded dark:hover:text-white hover:text-black transition"
: 'invisible group-hover:visible'} p-1.5 hover:bg-black/5 dark:hover:bg-white/5 rounded-lg dark:hover:text-white hover:text-black transition"
on:click={() => {
if (!loadingSpeech) {
toggleSpeakMessage(message);
@@ -715,7 +654,7 @@
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="2"
stroke-width="2.3"
stroke="currentColor"
class="w-4 h-4"
>
@@ -730,7 +669,7 @@
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="2"
stroke-width="2.3"
stroke="currentColor"
class="w-4 h-4"
>
@@ -749,7 +688,7 @@
<button
class="{isLastMessage
? 'visible'
: 'invisible group-hover:visible'} p-1 rounded dark:hover:text-white hover:text-black transition"
: 'invisible group-hover:visible'} p-1.5 hover:bg-black/5 dark:hover:bg-white/5 rounded-lg dark:hover:text-white hover:text-black transition"
on:click={() => {
if (!generatingImage) {
generateImage(message);
@@ -796,7 +735,7 @@
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="2"
stroke-width="2.3"
stroke="currentColor"
class="w-4 h-4"
>
@@ -816,7 +755,7 @@
<button
class=" {isLastMessage
? 'visible'
: 'invisible group-hover:visible'} p-1 rounded dark:hover:text-white hover:text-black transition whitespace-pre-wrap"
: 'invisible group-hover:visible'} p-1.5 hover:bg-black/5 dark:hover:bg-white/5 rounded-lg dark:hover:text-white hover:text-black transition whitespace-pre-wrap"
on:click={() => {
console.log(message);
}}
@@ -826,7 +765,7 @@
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="2"
stroke-width="2.3"
stroke="currentColor"
class="w-4 h-4"
>
@@ -840,13 +779,84 @@
</Tooltip>
{/if}
{#if !readOnly}
<Tooltip content={$i18n.t('Good Response')} placement="bottom">
<button
class="{isLastMessage
? 'visible'
: 'invisible group-hover:visible'} p-1.5 hover:bg-black/5 dark:hover:bg-white/5 rounded-lg {message
?.annotation?.rating === 1
? 'bg-gray-100 dark:bg-gray-800'
: ''} dark:hover:text-white hover:text-black transition"
on:click={() => {
rateMessage(message.id, 1);
showRateComment = true;
window.setTimeout(() => {
document
.getElementById(`message-feedback-${message.id}`)
?.scrollIntoView();
}, 0);
}}
>
<svg
stroke="currentColor"
fill="none"
stroke-width="2.3"
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={$i18n.t('Bad Response')} placement="bottom">
<button
class="{isLastMessage
? 'visible'
: 'invisible group-hover:visible'} p-1.5 hover:bg-black/5 dark:hover:bg-white/5 rounded-lg {message
?.annotation?.rating === -1
? 'bg-gray-100 dark:bg-gray-800'
: ''} dark:hover:text-white hover:text-black transition"
on:click={() => {
rateMessage(message.id, -1);
showRateComment = true;
window.setTimeout(() => {
document
.getElementById(`message-feedback-${message.id}`)
?.scrollIntoView();
}, 0);
}}
>
<svg
stroke="currentColor"
fill="none"
stroke-width="2.3"
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}
{#if isLastMessage && !readOnly}
<Tooltip content={$i18n.t('Continue Response')} placement="bottom">
<button
type="button"
class="{isLastMessage
? 'visible'
: 'invisible group-hover:visible'} p-1 rounded dark:hover:text-white hover:text-black transition regenerate-response-button"
: 'invisible group-hover:visible'} p-1.5 hover:bg-black/5 dark:hover:bg-white/5 rounded-lg dark:hover:text-white hover:text-black transition regenerate-response-button"
on:click={() => {
continueGeneration();
}}
@@ -855,7 +865,7 @@
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="2"
stroke-width="2.3"
stroke="currentColor"
class="w-4 h-4"
>
@@ -878,14 +888,14 @@
type="button"
class="{isLastMessage
? 'visible'
: 'invisible group-hover:visible'} p-1 rounded dark:hover:text-white hover:text-black transition regenerate-response-button"
: 'invisible group-hover:visible'} p-1.5 hover:bg-black/5 dark:hover:bg-white/5 rounded-lg dark:hover:text-white hover:text-black transition regenerate-response-button"
on:click={regenerateResponse}
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="2"
stroke-width="2.3"
stroke="currentColor"
class="w-4 h-4"
>
@@ -902,7 +912,7 @@
</div>
{/if}
{#if showRateComment}
{#if message.done && showRateComment}
<RateComment
messageId={message.id}
bind:show={showRateComment}

View File

@@ -54,49 +54,55 @@
};
</script>
<div class=" flex w-full" dir="{$settings.chatDirection}">
<ProfileImage
src={message.user
? $modelfiles.find((modelfile) => modelfile.tagName === message.user)?.imageUrl ?? '/user.png'
: user?.profile_image_url ?? '/user.png'}
/>
<div class=" flex w-full user-message" dir="{$settings.chatDirection}">
{#if !($settings?.chatBubble ?? true)}
<ProfileImage
src={message.user
? $modelfiles.find((modelfile) => modelfile.tagName === message.user)?.imageUrl ??
'/user.png'
: user?.profile_image_url ?? '/user.png'}
/>
{/if}
<div class="w-full overflow-hidden">
<div class="user-message">
<Name>
{#if message.user}
{#if $modelfiles.map((modelfile) => modelfile.tagName).includes(message.user)}
{$modelfiles.find((modelfile) => modelfile.tagName === message.user)?.title}
{#if !($settings?.chatBubble ?? true)}
<div>
<Name>
{#if message.user}
{#if $modelfiles.map((modelfile) => modelfile.tagName).includes(message.user)}
{$modelfiles.find((modelfile) => modelfile.tagName === message.user)?.title}
{:else}
{$i18n.t('You')}
<span class=" text-gray-500 text-sm font-medium">{message?.user ?? ''}</span>
{/if}
{:else if $settings.showUsername}
{user.name}
{:else}
{$i18n.t('You')}
<span class=" text-gray-500 text-sm font-medium">{message?.user ?? ''}</span>
{/if}
{:else if $settings.showUsername}
{user.name}
{:else}
{$i18n.t('You')}
{/if}
{#if message.timestamp}
<span class=" invisible group-hover:visible text-gray-400 text-xs font-medium">
{dayjs(message.timestamp * 1000).format($i18n.t('DD/MM/YYYY HH:mm'))}
</span>
{/if}
</Name>
</div>
{#if message.timestamp}
<span
class=" invisible group-hover:visible text-gray-400 text-xs font-medium uppercase"
>
{dayjs(message.timestamp * 1000).format($i18n.t('h:mm a'))}
</span>
{/if}
</Name>
</div>
{/if}
<div
class="prose chat-{message.role} w-full max-w-full dark:prose-invert prose-headings:my-0 prose-p:my-0 prose-p:-mb-4 prose-pre:my-0 prose-table:my-0 prose-blockquote:my-0 prose-img:my-0 prose-ul:-my-4 prose-ol:-my-4 prose-li:-my-3 prose-ul:-mb-6 prose-ol:-mb-6 prose-li:-mb-4 whitespace-pre-line"
class="prose chat-{message.role} w-full max-w-full flex flex-col justify-end dark:prose-invert prose-headings:my-0 prose-p:my-0 prose-p:-mb-4 prose-pre:my-0 prose-table:my-0 prose-blockquote:my-0 prose-img:my-0 prose-ul:-my-4 prose-ol:-my-4 prose-li:-my-3 prose-ul:-mb-6 prose-ol:-mb-6 prose-li:-mb-4 whitespace-pre-line"
>
{#if message.files}
<div class="my-2.5 w-full flex overflow-x-auto gap-2 flex-wrap">
<div class="mt-2.5 mb-1 w-full flex flex-col justify-end overflow-x-auto gap-1 flex-wrap">
{#each message.files as file}
<div>
<div class={$settings?.chatBubble ?? true ? 'self-end' : ''}>
{#if file.type === 'image'}
<img src={file.url} alt="input" class=" max-h-96 rounded-lg" draggable="false" />
{:else if file.type === 'doc'}
<button
class="h-16 w-[15rem] flex items-center space-x-3 px-2.5 dark:bg-gray-600 rounded-xl border border-gray-200 dark:border-none text-left"
class="h-16 w-72 flex items-center space-x-3 px-2.5 dark:bg-gray-850 rounded-xl border border-gray-200 dark:border-none text-left"
type="button"
on:click={() => {
if (file?.url) {
@@ -132,7 +138,7 @@
</button>
{:else if file.type === 'collection'}
<button
class="h-16 w-[15rem] flex items-center space-x-3 px-2.5 dark:bg-gray-600 rounded-xl border border-gray-200 dark:border-none text-left"
class="h-16 w-72 flex items-center space-x-3 px-2.5 dark:bg-gray-600 rounded-xl border border-gray-200 dark:border-none text-left"
type="button"
>
<div class="p-2.5 bg-red-400 text-white rounded-lg">
@@ -166,7 +172,7 @@
{/if}
{#if edit === true}
<div class=" w-full">
<div class=" w-full bg-gray-50 dark:bg-gray-800 rounded-3xl px-5 py-3 mb-2">
<textarea
id="message-edit-{message.id}"
bind:this={messageEditTextAreaElement}
@@ -190,85 +196,104 @@
}}
/>
<div class=" mt-2 mb-1 flex justify-center space-x-2 text-sm font-medium">
<button
id="save-edit-message-button"
class="px-4 py-2 bg-emerald-700 hover:bg-emerald-800 text-gray-100 transition rounded-lg"
on:click={() => {
editMessageConfirmHandler();
}}
>
{$i18n.t('Save & Submit')}
</button>
<div class=" mt-2 mb-1 flex justify-end space-x-1.5 text-sm font-medium">
<button
id="close-edit-message-button"
class=" px-4 py-2 hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-100 transition outline outline-1 outline-gray-200 dark:outline-gray-600 rounded-lg"
class=" px-4 py-2 bg-gray-900 hover:bg-gray-850 text-gray-100 transition rounded-3xl"
on:click={() => {
cancelEditMessage();
}}
>
{$i18n.t('Cancel')}
</button>
<button
id="save-edit-message-button"
class="px-4 py-2 bg-white hover:bg-gray-100 text-gray-800 transition rounded-3xl"
on:click={() => {
editMessageConfirmHandler();
}}
>
{$i18n.t('Send')}
</button>
</div>
</div>
{:else}
<div class="w-full">
<pre id="user-message">{message.content}</pre>
<div class="flex {$settings?.chatBubble ?? true ? 'justify-end' : ''} mb-2">
<div
class="rounded-3xl {$settings?.chatBubble ?? true
? `max-w-[90%] px-5 py-2 bg-gray-50 dark:bg-gray-850 ${
message.files ? 'rounded-tr-lg' : ''
}`
: ''} "
>
<pre id="user-message">{message.content}</pre>
</div>
</div>
<div class=" flex justify-start space-x-1 text-gray-700 dark:text-gray-500">
{#if siblings.length > 1}
<div class="flex self-center">
<button
class="self-center dark:hover:text-white hover:text-black transition"
on:click={() => {
showPreviousMessage(message);
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
<div
class=" flex {$settings?.chatBubble ?? true
? 'justify-end'
: ''} text-gray-600 dark:text-gray-500"
>
{#if !($settings?.chatBubble ?? true)}
{#if siblings.length > 1}
<div class="flex self-center">
<button
class="self-center p-1 hover:bg-black/5 dark:hover:bg-white/5 dark:hover:text-white hover:text-black rounded-md transition"
on:click={() => {
showPreviousMessage(message);
}}
>
<path
fill-rule="evenodd"
d="M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z"
clip-rule="evenodd"
/>
</svg>
</button>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
stroke-width="2.5"
class="size-3.5"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M15.75 19.5 8.25 12l7.5-7.5"
/>
</svg>
</button>
<div class="text-xs font-bold self-center dark:text-gray-100">
{siblings.indexOf(message.id) + 1} / {siblings.length}
<div class="text-sm tracking-widest font-semibold self-center dark:text-gray-100">
{siblings.indexOf(message.id) + 1}/{siblings.length}
</div>
<button
class="self-center p-1 hover:bg-black/5 dark:hover:bg-white/5 dark:hover:text-white hover:text-black rounded-md transition"
on:click={() => {
showNextMessage(message);
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
stroke-width="2.5"
class="size-3.5"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="m8.25 4.5 7.5 7.5-7.5 7.5"
/>
</svg>
</button>
</div>
<button
class="self-center dark:hover:text-white hover:text-black transition"
on:click={() => {
showNextMessage(message);
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
fill-rule="evenodd"
d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z"
clip-rule="evenodd"
/>
</svg>
</button>
</div>
{/if}
{/if}
{#if !readOnly}
<Tooltip content={$i18n.t('Edit')} placement="bottom">
<button
class="invisible group-hover:visible p-1 rounded dark:hover:text-white hover:text-black transition edit-user-message-button"
class="invisible group-hover:visible p-1.5 hover:bg-black/5 dark:hover:bg-white/5 rounded-lg dark:hover:text-white hover:text-black transition edit-user-message-button"
on:click={() => {
editMessageHandler();
}}
@@ -277,7 +302,7 @@
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="2"
stroke-width="2.3"
stroke="currentColor"
class="w-4 h-4"
>
@@ -293,7 +318,7 @@
<Tooltip content={$i18n.t('Copy')} placement="bottom">
<button
class="invisible group-hover:visible p-1 rounded dark:hover:text-white hover:text-black transition"
class="invisible group-hover:visible p-1.5 hover:bg-black/5 dark:hover:bg-white/5 rounded-lg dark:hover:text-white hover:text-black transition"
on:click={() => {
copyToClipboard(message.content);
}}
@@ -302,7 +327,7 @@
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="2"
stroke-width="2.3"
stroke="currentColor"
class="w-4 h-4"
>
@@ -340,6 +365,60 @@
</button>
</Tooltip>
{/if}
{#if $settings?.chatBubble ?? true}
{#if siblings.length > 1}
<div class="flex self-center">
<button
class="self-center p-1 hover:bg-black/5 dark:hover:bg-white/5 dark:hover:text-white hover:text-black rounded-md transition"
on:click={() => {
showPreviousMessage(message);
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
stroke-width="2.5"
class="size-3.5"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M15.75 19.5 8.25 12l7.5-7.5"
/>
</svg>
</button>
<div class="text-sm tracking-widest font-semibold self-center dark:text-gray-100">
{siblings.indexOf(message.id) + 1}/{siblings.length}
</div>
<button
class="self-center p-1 hover:bg-black/5 dark:hover:bg-white/5 dark:hover:text-white hover:text-black rounded-md transition"
on:click={() => {
showNextMessage(message);
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
stroke-width="2.5"
class="size-3.5"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="m8.25 4.5 7.5 7.5-7.5 7.5"
/>
</svg>
</button>
</div>
{/if}
{/if}
</div>
</div>
{/if}