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> | |