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
4e608a99
Unverified
Commit
4e608a99
authored
Nov 12, 2023
by
Timothy Jaeryang Baek
Committed by
GitHub
Nov 12, 2023
Browse files
Merge pull request #96 from ollama-webui/dev
feat: improved chat history support (response regeneration history)
parents
9cc206ca
5dff4744
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
418 additions
and
134 deletions
+418
-134
src/lib/components/chat/SettingsModal.svelte
src/lib/components/chat/SettingsModal.svelte
+1
-1
src/lib/constants.ts
src/lib/constants.ts
+1
-1
src/routes/+page.svelte
src/routes/+page.svelte
+416
-132
No files found.
src/lib/components/chat/SettingsModal.svelte
View file @
4e608a99
...
...
@@ -749,7 +749,7 @@
<div class=" space-y-3">
<div>
<div class=" py-1 flex w-full justify-between">
<div class=" self-center text-sm font-medium">
Speech
Auto-Send</div>
<div class=" self-center text-sm font-medium">
Voice Input
Auto-Send</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
...
...
src/lib/constants.ts
View file @
4e608a99
...
...
@@ -8,7 +8,7 @@ export const API_BASE_URL =
:
`http://localhost:11434/api`
:
PUBLIC_API_BASE_URL
;
export
const
WEB_UI_VERSION
=
'
v1.0.0-alpha.
2
'
;
export
const
WEB_UI_VERSION
=
'
v1.0.0-alpha.
3
'
;
// Source: https://kit.svelte.dev/docs/modules#$env-static-public
// This feature, akin to $env/static/private, exclusively incorporates environment variables
...
...
src/routes/+page.svelte
View file @
4e608a99
...
...
@@ -39,6 +39,22 @@
let
title
=
''
;
let
prompt
=
''
;
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
;
}
let
showSettings
=
false
;
let
stopResponseFlag
=
false
;
...
...
@@ -260,8 +276,13 @@
if
(
init
||
messages
.
length
>
0
)
{
chatId
=
uuidv4
();
autoScroll
=
true
;
messages
=
[];
title
=
''
;
messages
=
[];
history
=
{
messages
:
{},
currentId
:
null
};
settings
=
JSON
.
parse
(
localStorage
.
getItem
(
'
settings
'
)
??
JSON
.
stringify
(
settings
));
...
...
@@ -311,20 +332,59 @@
const
loadChat
=
async
(
id
)
=>
{
const
chat
=
await
db
.
get
(
'
chats
'
,
id
);
console
.
log
(
chat
);
if
(
chatId
!==
chat
.
id
)
{
if
(
chat
.
messages
.
length
>
0
)
{
chat
.
messages
.
at
(
-
1
).
done
=
true
;
if
(
'
history
'
in
chat
)
{
history
=
chat
.
history
;
}
else
{
let
_history
=
{
messages
:
{},
currentId
:
null
};
let
parentMessageId
=
null
;
let
messageId
=
null
;
for
(
const
message
of
chat
.
messages
)
{
messageId
=
uuidv4
();
if
(
parentMessageId
!==
null
)
{
_history
.
messages
[
parentMessageId
].
childrenIds
=
[
...
_history
.
messages
[
parentMessageId
].
childrenIds
,
messageId
];
}
_history
.
messages
[
messageId
]
=
{
...
message
,
id
:
messageId
,
parentId
:
parentMessageId
,
childrenIds
:
[]
};
parentMessageId
=
messageId
;
}
_history
.
currentId
=
messageId
;
history
=
_history
;
}
messages
=
chat
.
messages
;
console
.
log
(
history
);
title
=
chat
.
title
;
chatId
=
chat
.
id
;
selectedModel
=
chat
.
model
??
selectedModel
;
settings
.
system
=
chat
.
system
??
settings
.
system
;
settings
.
temperature
=
chat
.
temperature
??
settings
.
temperature
;
autoScroll
=
true
;
await
tick
();
renderLatex
();
if
(
messages
.
length
>
0
)
{
history
.
messages
[
messages
.
at
(
-
1
).
id
].
done
=
true
;
}
renderLatex
();
hljs
.
highlightAll
();
createCopyCodeBlockButton
();
}
...
...
@@ -368,7 +428,8 @@
options
:
chat
.
options
,
title
:
chat
.
title
,
timestamp
:
chat
.
timestamp
,
messages
:
chat
.
messages
messages
:
chat
.
messages
,
history
:
chat
.
history
});
}
chats
=
await
db
.
getAllFromIndex
(
'
chats
'
,
'
timestamp
'
);
...
...
@@ -386,35 +447,45 @@
showSettings
=
true
;
};
const
editMessage
=
async
(
messageIdx
)
=>
{
messages
=
messages
.
map
((
message
,
idx
)
=>
{
if
(
messageIdx
===
idx
)
{
message
.
edit
=
true
;
message
.
editedContent
=
message
.
content
;
}
return
message
;
});
const
editMessageHandler
=
async
(
messageId
)
=>
{
// let editMessage = history.messages[messageId];
history
.
messages
[
messageId
].
edit
=
true
;
history
.
messages
[
messageId
].
editedContent
=
history
.
messages
[
messageId
].
content
;
};
const
confirmEditMessage
=
async
(
messageId
x
)
=>
{
let
userPrompt
=
messages
.
at
(
messageId
x
)
.
edit
edContent
;
const
confirmEditMessage
=
async
(
messageId
)
=>
{
history
.
messages
[
messageId
]
.
edit
=
false
;
messages
.
splice
(
message
Idx
,
message
s
.
length
-
messageIdx
)
;
m
essage
s
=
messages
;
let
userPrompt
=
history
.
message
s
[
message
Id
].
editedContent
;
let
userM
essage
Id
=
uuidv4
()
;
await
submitPrompt
(
userPrompt
);
};
let
userMessage
=
{
id
:
userMessageId
,
parentId
:
history
.
messages
[
messageId
].
parentId
,
childrenIds
:
[],
role
:
'
user
'
,
content
:
userPrompt
};
const
cancelEditMessage
=
(
messageIdx
)
=>
{
messages
=
messages
.
map
((
message
,
idx
)
=>
{
if
(
messageIdx
===
idx
)
{
message
.
edit
=
undefined
;
message
.
editedContent
=
undefined
;
}
return
message
;
});
let
messageParentId
=
history
.
messages
[
messageId
].
parentId
;
console
.
log
(
messages
);
if
(
messageParentId
!==
null
)
{
history
.
messages
[
messageParentId
].
childrenIds
=
[
...
history
.
messages
[
messageParentId
].
childrenIds
,
userMessageId
];
}
history
.
messages
[
userMessageId
]
=
userMessage
;
history
.
currentId
=
userMessageId
;
await
tick
();
await
sendPrompt
(
userPrompt
,
userMessageId
);
};
const
cancelEditMessage
=
(
messageId
)
=>
{
history
.
messages
[
messageId
].
edit
=
false
;
history
.
messages
[
messageId
].
editedContent
=
undefined
;
};
const
rateMessage
=
async
(
messageIdx
,
rating
)
=>
{
...
...
@@ -434,12 +505,101 @@
temperature
:
settings
.
temperature
},
timestamp
:
Date
.
now
(),
messages
:
messages
messages
:
messages
,
history
:
history
});
console
.
log
(
messages
);
};
const
showPreviousMessage
=
async
(
message
)
=>
{
if
(
message
.
parentId
!==
null
)
{
let
messageId
=
history
.
messages
[
message
.
parentId
].
childrenIds
[
Math
.
max
(
history
.
messages
[
message
.
parentId
].
childrenIds
.
indexOf
(
message
.
id
)
-
1
,
0
)
];
if
(
message
.
id
!==
messageId
)
{
let
messageChildrenIds
=
history
.
messages
[
messageId
].
childrenIds
;
while
(
messageChildrenIds
.
length
!==
0
)
{
messageId
=
messageChildrenIds
.
at
(
-
1
);
messageChildrenIds
=
history
.
messages
[
messageId
].
childrenIds
;
}
history
.
currentId
=
messageId
;
}
}
else
{
let
childrenIds
=
Object
.
values
(
history
.
messages
)
.
filter
((
message
)
=>
message
.
parentId
===
null
)
.
map
((
message
)
=>
message
.
id
);
let
messageId
=
childrenIds
[
Math
.
max
(
childrenIds
.
indexOf
(
message
.
id
)
-
1
,
0
)];
if
(
message
.
id
!==
messageId
)
{
let
messageChildrenIds
=
history
.
messages
[
messageId
].
childrenIds
;
while
(
messageChildrenIds
.
length
!==
0
)
{
messageId
=
messageChildrenIds
.
at
(
-
1
);
messageChildrenIds
=
history
.
messages
[
messageId
].
childrenIds
;
}
history
.
currentId
=
messageId
;
}
}
await
tick
();
renderLatex
();
hljs
.
highlightAll
();
createCopyCodeBlockButton
();
};
const
showNextMessage
=
async
(
message
)
=>
{
if
(
message
.
parentId
!==
null
)
{
let
messageId
=
history
.
messages
[
message
.
parentId
].
childrenIds
[
Math
.
min
(
history
.
messages
[
message
.
parentId
].
childrenIds
.
indexOf
(
message
.
id
)
+
1
,
history
.
messages
[
message
.
parentId
].
childrenIds
.
length
-
1
)
];
if
(
message
.
id
!==
messageId
)
{
let
messageChildrenIds
=
history
.
messages
[
messageId
].
childrenIds
;
while
(
messageChildrenIds
.
length
!==
0
)
{
messageId
=
messageChildrenIds
.
at
(
-
1
);
messageChildrenIds
=
history
.
messages
[
messageId
].
childrenIds
;
}
history
.
currentId
=
messageId
;
}
}
else
{
let
childrenIds
=
Object
.
values
(
history
.
messages
)
.
filter
((
message
)
=>
message
.
parentId
===
null
)
.
map
((
message
)
=>
message
.
id
);
let
messageId
=
childrenIds
[
Math
.
min
(
childrenIds
.
indexOf
(
message
.
id
)
+
1
,
childrenIds
.
length
-
1
)];
if
(
message
.
id
!==
messageId
)
{
let
messageChildrenIds
=
history
.
messages
[
messageId
].
childrenIds
;
while
(
messageChildrenIds
.
length
!==
0
)
{
messageId
=
messageChildrenIds
.
at
(
-
1
);
messageChildrenIds
=
history
.
messages
[
messageId
].
childrenIds
;
}
history
.
currentId
=
messageId
;
}
}
await
tick
();
renderLatex
();
hljs
.
highlightAll
();
createCopyCodeBlockButton
();
};
//////////////////////////
// Ollama functions
//////////////////////////
...
...
@@ -507,21 +667,46 @@
}
};
const sendPrompt = async (userPrompt) => {
const sendPrompt = async (userPrompt, parentId) => {
// await Promise.all(
// selectedModels.map((model) => {
// if (selectedModel.includes('gpt-')) {
// await sendPromptOpenAI(userPrompt, parentId);
// } else {
// await sendPromptOllama(userPrompt, parentId);
// }
// })
// );
if (selectedModel.includes('gpt-')) {
await sendPromptOpenAI(userPrompt);
await sendPromptOpenAI(userPrompt
, parentId
);
} else {
await sendPromptOllama(userPrompt);
await sendPromptOllama(userPrompt
, parentId
);
}
console.log(history);
};
const sendPromptOllama = async (userPrompt) => {
const sendPromptOllama = async (userPrompt, parentId) => {
let responseMessageId = uuidv4();
let responseMessage = {
parentId: parentId,
id: responseMessageId,
childrenIds: [],
role: 'assistant',
content: ''
};
messages = [...messages, responseMessage];
history.messages[responseMessageId] = responseMessage;
history.currentId = responseMessageId;
if (parentId !== null) {
history.messages[parentId].childrenIds = [
...history.messages[parentId].childrenIds,
responseMessageId
];
}
window.scrollTo({ top: document.body.scrollHeight });
const res = await fetch(`
$
{
API_BASE_URL
}
/generate`,
{
...
...
@@ -542,8 +727,9 @@
},
format
:
settings
.
requestFormat
??
undefined
,
context
:
messages
.
length
>
3
&&
messages
.
at
(
-
3
).
context
!=
undefined
?
messages
.
at
(
-
3
).
context
history
.
messages
[
parentId
]
!==
null
&&
history
.
messages
[
parentId
].
parentId
in
history
.
messages
?
history
.
messages
[
history
.
messages
[
parentId
].
parentId
]?.
context
??
undefined
:
undefined
})
});
...
...
@@ -608,7 +794,8 @@
temperature
:
settings
.
temperature
},
timestamp
:
Date
.
now
(),
messages
:
messages
messages
:
messages
,
history
:
history
});
}
...
...
@@ -623,15 +810,28 @@
}
};
const
sendPromptOpenAI
=
async
(
userPrompt
)
=>
{
const
sendPromptOpenAI
=
async
(
userPrompt
,
parentId
)
=>
{
if
(
settings
.
OPENAI_API_KEY
)
{
if
(
models
)
{
let
responseMessageId
=
uuidv4
();
let
responseMessage
=
{
parentId
:
parentId
,
id
:
responseMessageId
,
childrenIds
:
[],
role
:
'
assistant
'
,
content
:
''
};
messages
=
[...
messages
,
responseMessage
];
history
.
messages
[
responseMessageId
]
=
responseMessage
;
history
.
currentId
=
responseMessageId
;
if
(
parentId
!==
null
)
{
history
.
messages
[
parentId
].
childrenIds
=
[
...
history
.
messages
[
parentId
].
childrenIds
,
responseMessageId
];
}
window
.
scrollTo
({
top
:
document
.
body
.
scrollHeight
});
const
res
=
await
fetch
(
`https://api.openai.com/v1/chat/completions`
,
{
...
...
@@ -653,7 +853,7 @@
...
messages
]
.
filter
((
message
)
=>
message
)
.
map
((
message
)
=>
({
...
message
,
d
on
e
:
undefined
})),
.
map
((
message
)
=>
({
role
:
message
.
role
,
c
on
tent
:
message
.
content
})),
temperature
:
settings
.
temperature
??
undefined
,
top_p
:
settings
.
top_p
??
undefined
,
frequency_penalty
:
settings
.
repeat_penalty
??
undefined
...
...
@@ -715,7 +915,8 @@
temperature
:
settings
.
temperature
},
timestamp
:
Date
.
now
(),
messages
:
messages
messages
:
messages
,
history
:
history
});
}
...
...
@@ -747,13 +948,22 @@
}
else
{
document
.
getElementById
(
'
chat-textarea
'
).
style
.
height
=
''
;
messages
=
[
...
messages
,
{
role
:
'
user
'
,
content
:
userPrompt
}
];
let
userMessageId
=
uuidv4
();
let
userMessage
=
{
id
:
userMessageId
,
parentId
:
messages
.
length
!==
0
?
messages
.
at
(
-
1
).
id
:
null
,
childrenIds
:
[],
role
:
'
user
'
,
content
:
userPrompt
};
if
(
messages
.
length
!==
0
)
{
history
.
messages
[
messages
.
at
(
-
1
).
id
].
childrenIds
.
push
(
userMessageId
);
}
history
.
messages
[
userMessageId
]
=
userMessage
;
history
.
currentId
=
userMessageId
;
prompt
=
''
;
...
...
@@ -767,7 +977,8 @@
},
title
:
'
New Chat
'
,
timestamp
:
Date
.
now
(),
messages
:
messages
messages
:
messages
,
history
:
history
});
chats
=
await
db
.
getAllFromIndex
(
'
chats
'
,
'
timestamp
'
);
}
...
...
@@ -776,7 +987,7 @@
window
.
scrollTo
({
top
:
document
.
body
.
scrollHeight
,
behavior
:
'
smooth
'
});
},
50
);
await
sendPrompt
(
userPrompt
);
await
sendPrompt
(
userPrompt
,
userMessageId
);
chats
=
await
db
.
getAllFromIndex
(
'
chats
'
,
'
timestamp
'
);
}
...
...
@@ -791,7 +1002,7 @@
let
userMessage
=
messages
.
at
(
-
1
);
let
userPrompt
=
userMessage
.
content
;
await
sendPrompt
(
userPrompt
);
await
sendPrompt
(
userPrompt
,
userMessage
.
id
);
chats
=
await
db
.
getAllFromIndex
(
'
chats
'
,
'
timestamp
'
);
}
...
...
@@ -1078,7 +1289,7 @@
<div
class=
" w-full"
>
<textarea
class=
" bg-transparent outline-none w-full resize-none"
bind:value=
{
message
.editedContent}
bind:value=
{
history.messages[message.id]
.editedContent}
on:input=
{(e)
=
>
{
e.target.style.height = '';
e.target.style.height = `${e.target.scrollHeight}px`;
...
...
@@ -1093,7 +1304,7 @@
<button
class=
"px-4 py-2.5 bg-emerald-600 hover:bg-emerald-700 text-gray-100 transition rounded-lg"
on:click=
{()
=
>
{
confirmEditMessage(message
Idx
);
confirmEditMessage(message
.id
);
}}
>
Save
&
Submit
...
...
@@ -1102,7 +1313,7 @@
<button
class=
" px-4 py-2.5 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"
on:click=
{()
=
>
{
cancelEditMessage(message
Idx
);
cancelEditMessage(message
.id
);
}}
>
Cancel
...
...
@@ -1113,90 +1324,113 @@
<div
class=
"w-full"
>
{message.content}
<!-- <div class=" flex justify-start space-x-1">
<div class="flex self-center">
<button
class="self-center"
on:click={() => {
message.selectedContentIdx = Math.max(
0,
message.selectedContentIdx - 1
);
messages = messages;
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
<div
class=
" flex justify-start space-x-1"
>
{#if message.parentId !== null
&&
message.parentId in history.messages
&&
(history.messages[message.parentId]?.childrenIds.length ?? 0) > 1}
<div
class=
"flex self-center"
>
<button
class=
"self-center"
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>
<div class="text-xs font-bold self-center">
{message.selectedContentIdx + 1} / {message.contents.length}
<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=
"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>
<div
class=
"text-xs font-bold self-center"
>
{history.messages[message.parentId].childrenIds.indexOf(
message.id
) + 1} / {history.messages[message.parentId].childrenIds
.length}
</div>
<button
class=
"self-center"
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>
<button
class="self-center"
on:click={() => {
message.selectedContentIdx = Math.min(
message.contents.length - 1,
message.selectedContentIdx + 1
);
messages = messages;
console.log(message);
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
{:else if message.parentId === null
&&
Object.values(history.messages).filter((message) => message.parentId === null).length > 1}
<div
class=
"flex self-center"
>
<button
class=
"self-center"
on:click=
{()
=
>
{
showPreviousMessage(message);
}}
>
<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>
<button
class="invisible group-hover:visible p-1 rounded dark:hover:bg-gray-800 transition"
on:click={() => {
editMessage(messageIdx);
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="w-4 h-4"
>
<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>
</div> -->
<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=
"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>
<div
class=
"text-xs font-bold self-center"
>
{Object.values(history.messages)
.filter((message) => message.parentId === null)
.map((message) => message.id)
.indexOf(message.id) + 1} / {Object.values(
history.messages
).filter((message) => message.parentId === null).length}
</div>
<button
class=
"self-center"
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}
<div
class=
" flex justify-start space-x-1"
>
<button
class=
"invisible group-hover:visible p-1 rounded dark:hover:bg-gray-800 transition"
on:click=
{()
=
>
{
editMessage(message
Idx
);
editMessage
Handler
(message
.id
);
}}
>
<svg
...
...
@@ -1223,6 +1457,56 @@
{#if message.done}
<div
class=
" flex justify-start space-x-1 -mt-2"
>
{#if message.parentId !== null
&&
message.parentId in history.messages
&&
(history.messages[message.parentId]?.childrenIds.length ?? 0) > 1}
<div
class=
"flex self-center"
>
<button
class=
"self-center"
on:click=
{()
=
>
{
showPreviousMessage(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=
"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>
<div
class=
"text-xs font-bold self-center"
>
{history.messages[message.parentId].childrenIds.indexOf(
message.id
) + 1} / {history.messages[message.parentId].childrenIds
.length}
</div>
<button
class=
"self-center"
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}
<button
class=
"{messageIdx + 1 === messages.length
? 'visible'
...
...
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