Spaces:
Runtime error
Runtime error
| <script lang="ts"> | |
| import { PUBLIC_BACKEND_WS_URL } from '$env/static/public'; | |
| import { onMount } from 'svelte'; | |
| import { nanoid } from 'nanoid'; | |
| import { chatsStore, selectedChatId, loadingState } from '$lib/store'; | |
| import type { Message, Chat } from '$lib/types'; | |
| import { MessageType, Sender } from '$lib/types'; | |
| import ChatInput from '$lib/ChatInput.svelte'; | |
| import ChatMessage from '$lib/ChatMessage.svelte'; | |
| import ChatNewBtn from '$lib/ChatNewBtn.svelte'; | |
| $: isLoading = false; | |
| function clearStateMsg(t = 5000) { | |
| setTimeout(() => { | |
| $loadingState = ''; | |
| }, t); | |
| } | |
| onMount(() => { | |
| // generateImage(); | |
| }); | |
| $: chatData = $chatsStore.find((chat) => chat.id === $selectedChatId); | |
| $: messages = chatData?.messages || []; | |
| $: console.log($chatsStore); | |
| function newChat() { | |
| const chatId = nanoid(); | |
| const chat: Chat = { | |
| id: chatId, | |
| blurb: `New Chat - ${chatId}`, | |
| messages: [], | |
| timestamp: new Date().getTime() | |
| }; | |
| $chatsStore = [chat].concat($chatsStore); | |
| $selectedChatId = chat.id; | |
| } | |
| function submitMessage(event: CustomEvent) { | |
| const value = event.detail; | |
| const message: Message = { | |
| sender: Sender.USER, | |
| id: nanoid(), | |
| type: MessageType.TEXT, | |
| content: value, | |
| timestamp: new Date().getTime() | |
| }; | |
| $chatsStore = $chatsStore.map((chat) => { | |
| if (chat.id === $selectedChatId) { | |
| chat.messages.push(message); | |
| } | |
| return chat; | |
| }); | |
| } | |
| const timeFormater = new Intl.DateTimeFormat('en-US', { | |
| day: 'numeric', | |
| month: 'short', | |
| hour: 'numeric', | |
| minute: 'numeric' | |
| }).format; | |
| async function generateImage() { | |
| if (isLoading) return; | |
| $loadingState = 'Pending'; | |
| const sessionHash = crypto.randomUUID(); | |
| const hashpayload = { | |
| fn_index: 1, | |
| session_hash: sessionHash | |
| }; | |
| const image = ''; | |
| const datapayload = { | |
| data: [ | |
| 'make him wear shirts', // prompt | |
| 10.5, // text guidance | |
| 1.5, // image guidance | |
| image, | |
| 15, // steps | |
| '', // negative promtp, | |
| 512, // width | |
| 512, // height | |
| 0 // seed | |
| ] | |
| }; | |
| const websocket = new WebSocket(PUBLIC_BACKEND_WS_URL); | |
| // websocket.onopen = async function (event) { | |
| // websocket.send(JSON.stringify({ hash: sessionHash })); | |
| // }; | |
| websocket.onclose = (evt) => { | |
| if (!evt.wasClean) { | |
| $loadingState = 'Error'; | |
| } | |
| }; | |
| websocket.onmessage = async function (event) { | |
| try { | |
| const data = JSON.parse(event.data); | |
| $loadingState = ''; | |
| switch (data.msg) { | |
| case 'send_hash': | |
| websocket.send(JSON.stringify(hashpayload)); | |
| break; | |
| case 'send_data': | |
| $loadingState = 'Sending Data'; | |
| websocket.send(JSON.stringify({ ...hashpayload, ...datapayload })); | |
| break; | |
| case 'queue_full': | |
| $loadingState = 'Queue full'; | |
| websocket.close(); | |
| return; | |
| case 'estimation': | |
| const { rank, queue_size } = data; | |
| $loadingState = `On queue ${rank}/${queue_size}`; | |
| break; | |
| case 'process_generating': | |
| $loadingState = data.success ? 'Generating' : 'Error'; | |
| break; | |
| case 'process_completed': | |
| try { | |
| console.log(data); | |
| // const params = data.output.data[0] as { | |
| // is_nsfw: boolean; | |
| // image: { | |
| // url: string; | |
| // filename: string; | |
| // }; | |
| // }; | |
| // const isNSWF = params.is_nsfw; | |
| // if (isNSWF) { | |
| // throw new Error('NFSW'); | |
| // } | |
| // // const imgBlob = await base64ToBlob(imgBase64); | |
| // const promptImgParams = { | |
| // imgURL: params.image.filename | |
| // }; | |
| // // const imgURL = await uploadImage(imgBlob, promptImgParams); | |
| // // $promptImgStorage.set(imageKey, promptImgParams); | |
| // console.log(params.image.url); | |
| $loadingState = data.success ? 'Complete' : 'Error'; | |
| clearStateMsg(); | |
| } catch (err) { | |
| const tError = err as Error; | |
| $loadingState = tError?.message; | |
| clearStateMsg(10000); | |
| } | |
| websocket.close(); | |
| return; | |
| case 'process_starts': | |
| $loadingState = 'Processing'; | |
| break; | |
| } | |
| } catch (e) { | |
| console.error(e); | |
| $loadingState = 'Error'; | |
| } | |
| }; | |
| } | |
| </script> | |
| <div> | |
| <h1 class="text-2xl">CHATS</h1> | |
| <div class="grid min-h-[40rem] grid-cols-4"> | |
| <div class="col-span-1 flex flex-col border-r p-4"> | |
| <ChatNewBtn on:click={newChat} /> | |
| <div class="max-h-[40rem] flex flex-col gap-2 overflow-y-scroll"> | |
| {#if $chatsStore.length} | |
| {#each $chatsStore as chat} | |
| <button on:click={() => ($selectedChatId = chat.id)}> | |
| <div | |
| class="flex h-16 flex-col items-start justify-center rounded-xl bg-gray-100 px-4 text-gray-900 | |
| {chat.id === $selectedChatId ? 'bg-gray-400' : ''}" | |
| > | |
| <h3 class="w-full truncate font-semibold">{chat.blurb}</h3> | |
| <p class="w-full truncate text-sm text-gray-500"> | |
| {timeFormater(new Date(chat.timestamp))} | |
| </p> | |
| </div> | |
| </button> | |
| {/each} | |
| {:else} | |
| <div | |
| class="flex h-16 flex-col items-start justify-center rounded-xl bg-gray-100 px-4 text-gray-900" | |
| > | |
| <h3 class="w-full truncate font-semibold">No chats</h3> | |
| <p class="w-full truncate text-sm text-gray-500">Start a new Chat!</p> | |
| </div> | |
| {/if} | |
| </div> | |
| </div> | |
| <div class="col-span-3 flex flex-col"> | |
| {#each messages as message} | |
| <ChatMessage {message} /> | |
| {/each} | |
| <ChatInput on:submitMessage={submitMessage} /> | |
| </div> | |
| </div> | |
| </div> | |
| <style lang="postcss" scoped> | |
| </style> | |