Thomas G. Lopes
change outline
6ca8d92
raw
history blame
2.5 kB
<script lang="ts">
import { autofocus } from "$lib/attachments/autofocus.js";
import { TextareaAutosize } from "$lib/spells/textarea-autosize.svelte.js";
import { conversations } from "$lib/state/conversations.svelte";
import { cmdOrCtrl } from "$lib/utils/platform.js";
const multiple = $derived(conversations.active.length > 1);
const loading = $derived(conversations.generating);
let input = $state("");
async function onKeydown(event: KeyboardEvent) {
if (loading) return;
const ctrlOrMeta = event.ctrlKey || event.metaKey;
if (ctrlOrMeta && event.key === "Enter") {
sendMessage();
}
}
async function sendMessage() {
const c = conversations.active;
await Promise.all(c.map(c => c.addMessage({ role: "user", content: input })));
c.forEach(c => c.genNextMessage());
input = "";
}
const autosized = new TextareaAutosize();
</script>
<svelte:window onkeydown={onKeydown} />
<div class="mt-auto px-2">
<label
class="flex w-full items-end rounded-[32px] bg-gray-200 p-2 pl-6 outline-gray-400 focus-within:outline-2 dark:bg-gray-800"
>
<textarea
placeholder="Enter your message"
class="max-h-100 flex-1 resize-none self-center outline-none"
bind:value={input}
{@attach autosized.attachment}
{@attach autofocus()}
></textarea>
<button
onclick={() => {
if (loading) conversations.stopGenerating();
else sendMessage();
}}
type="button"
class={[
"flex items-center justify-center gap-2 rounded-full px-3.5 py-2.5 text-sm font-medium text-white focus:ring-4 focus:ring-gray-300 focus:outline-hidden dark:focus:ring-gray-700",
loading && "bg-red-900 hover:bg-red-800 dark:bg-red-600 dark:hover:bg-red-700",
!loading && "bg-black hover:bg-gray-900 dark:bg-blue-600 dark:hover:bg-blue-700",
]}
>
{#if loading}
<div class="flex flex-none items-center gap-[3px]">
<span class="mr-2">
{#if conversations.active.some(c => c.data.streaming)}
Stop
{:else}
Cancel
{/if}
</span>
{#each { length: 3 } as _, i}
<div
class="h-1 w-1 flex-none animate-bounce rounded-full bg-gray-200 dark:bg-gray-100"
style="animation-delay: {(i + 1) * 0.25}s;"
></div>
{/each}
</div>
{:else}
{multiple ? "Run all" : "Run"}
<span class="inline-flex gap-0.5 rounded-sm border border-white/20 bg-white/10 px-0.5 text-xs text-white/70">
{cmdOrCtrl}<span class="translate-y-px">↵</span>
</span>
{/if}
</button>
</label>
</div>