Skip to content
Extraits de code Groupes Projets
chatbox.svelte 2,49 ko
Newer Older
  • Learn to ignore specific revisions
  • <script lang="ts">
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    	import type Session from '$lib/types/session';
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    	import { onDestroy, onMount } from 'svelte';
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    	import MessageC from './message.svelte';
    
    	import { get } from 'svelte/store';
    
    	import Writebox from './writebox.svelte';
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    	export let token: string;
    
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    	export let session: Session;
    
    	let messages = get(session.messages);
    
    	session.messages.subscribe((newMessages) => {
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    		let news = newMessages
    			.filter((m) => !messages.find((m2) => m2.message_id === m.message_id))
    			.at(-1);
    
    		messages = newMessages;
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    		if (!news) return;
    
    		if (document.hidden) {
    			new Notification(news.user.nickname, {
    				body: news.content,
    				icon: '/favicon.ico'
    			});
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    			new Audio('/notification.wav').play();
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    		}
    
    	let wsConnected = true;
    	let timeout: number;
    
    	session.wsConnected.subscribe((newConnected) => {
    
    		clearTimeout(timeout);
    
    		if (newConnected === wsConnected) return;
    		else if (newConnected) wsConnected = newConnected;
    		else {
    			timeout = setTimeout(() => {
    				wsConnected = newConnected;
    			}, 1000);
    		}
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    	$: isTyping = false;
    	let timeoutTyping: number;
    
    	session.lastTyping.subscribe((lastTyping) => {
    		clearTimeout(timeoutTyping);
    		if (!lastTyping) {
    			isTyping = false;
    			return;
    		}
    
    		const diff = new Date().getTime() - lastTyping.getTime();
    
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    		if (diff > 2000) {
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    			isTyping = false;
    		}
    
    		isTyping = true;
    		timeoutTyping = setTimeout(() => {
    			isTyping = false;
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    		}, 2000 - diff);
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    	});
    
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    	let presenceTimeout: number;
    
    	function presenceIndicator() {
    		clearInterval(presenceTimeout);
    
    		presenceTimeout = setInterval(() => {
    			session.sendPresence();
    		}, 5000);
    	}
    
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    	onMount(async () => {
    		await session.loadMessages();
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    		session.wsConnect(token);
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    		presenceIndicator();
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    		Notification.requestPermission(); // Should do something with denial ?
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    	});
    
    	onDestroy(() => {
    		clearInterval(presenceTimeout);
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    	});
    
    </script>
    
    
    <div class="flex flex-col w-full h-full border-x-2">
    
    	<div class="flex-grow h-48 overflow-auto flex-col-reverse px-4 flex mb-2">
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    		<div class:hidden={!isTyping}>
    			<span class="loading loading-dots loading-md"></span>
    		</div>
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    		{#each messages.sort((a, b) => b.created_at.getTime() - a.created_at.getTime()) as message (message.message_id)}
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    			<MessageC {message} />
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    		{/each}
    	</div>
    
    	{#if !wsConnected}
    		<div
    			class="bg-orange-400 h-10 text-center text-white font-bold flex justify-center items-center"
    		>
    			Real-time sync lost. You may need to refresh the page to see new messages.
    		</div>
    	{/if}
    
    	<div class="flex flex-row h-30">
    
    		<Writebox {session} />
    
    Brieuc Dubois's avatar
    Brieuc Dubois a validé
    	</div>
    
    </div>