107 lines
3.0 KiB
Vue
107 lines
3.0 KiB
Vue
<script setup lang="ts">
|
|
import { messageHandler } from '@/composable/message'
|
|
import router from '@/router'
|
|
import { ref, onMounted, onBeforeUnmount, nextTick, watch, type Ref } from 'vue'
|
|
|
|
const msg = messageHandler()
|
|
const newMessage = ref('')
|
|
const msgTimer = ref()
|
|
const scrollContainer = ref<null | HTMLElement>(null)
|
|
|
|
watch(msg.messages, async () => {
|
|
// To automatically scroll down when new message arrives
|
|
await nextTick()
|
|
const el = scrollContainer.value
|
|
if (!el) return
|
|
el.scrollTop = el.scrollHeight
|
|
})
|
|
|
|
const onSentMessage = () => {
|
|
if (newMessage.value.trim() === '') {
|
|
return
|
|
}
|
|
msg
|
|
.sendMessage(newMessage.value)
|
|
.then(() => {
|
|
newMessage.value = ''
|
|
})
|
|
.catch((error) => {
|
|
console.error('Error sending message:', error)
|
|
})
|
|
}
|
|
|
|
const handleKeyPress = (event: KeyboardEvent) => {
|
|
if (event.key === 'Enter' && event.shiftKey === false) {
|
|
onSentMessage()
|
|
}
|
|
}
|
|
|
|
// Instantiate polling for messages
|
|
// ToDo: Try using a WebSocket instea
|
|
onMounted(() => {
|
|
document.addEventListener('keypress', handleKeyPress)
|
|
msg.requestMessages()
|
|
msgTimer.value = setInterval(() => {
|
|
msg.requestMessages(msg.lastMsg()?.timestamp)
|
|
}, 3000) // 3s
|
|
})
|
|
|
|
// Clean up polling
|
|
onBeforeUnmount(() => {
|
|
clearInterval(msgTimer.value)
|
|
document.removeEventListener('keypress', handleKeyPress)
|
|
msgTimer.value = null
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<main>
|
|
<div class="grid grid-cols-1 grid-rows-10 boxed h-[75vh] max-w-128 min-w-100">
|
|
<h1 class="border-b-2">Chat</h1>
|
|
<div class="row-span-8 flex flex-col overflow-scroll" ref="scrollContainer">
|
|
<div v-if="msg" v-for="(message, id) in msg.messages.value" :key="message.id" class="mb-4">
|
|
<div
|
|
v-if="
|
|
!msg.previousMessage(id) ||
|
|
new Date(Number(message.timestamp) * 1000).toLocaleDateString() !==
|
|
new Date(Number(msg.previousMessage(id)?.timestamp) * 1000).toLocaleDateString()
|
|
"
|
|
class="text-center text-gray-500 my-2"
|
|
>
|
|
{{ new Date(Number(message.timestamp) * 1000).toLocaleDateString() }}
|
|
</div>
|
|
<p class="whitespace-pre-line">
|
|
<a class="italic mr-1">{{
|
|
new Date(Number(message.timestamp) * 1000).toLocaleTimeString([], {
|
|
hour: '2-digit',
|
|
minute: '2-digit',
|
|
hour12: false,
|
|
})
|
|
}}</a>
|
|
<a class="font-bold">{{ message.user }}</a
|
|
>: {{ message.content }}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="flex flex-row mt-auto">
|
|
<textarea
|
|
v-model="newMessage"
|
|
placeholder="Type your message here..."
|
|
class="w-full h-12 min-h-12 p-2 border rounded"
|
|
/>
|
|
<button
|
|
@click="
|
|
() =>
|
|
msg.sendMessage(newMessage).then(() => {
|
|
newMessage = ''
|
|
})
|
|
"
|
|
class="!w-min"
|
|
>
|
|
Send
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
</template>
|