Created
August 17, 2024 14:26
-
-
Save Romejanic/beba08c95ddbc2bdb4cd969df67b26eb to your computer and use it in GitHub Desktop.
WebRTC Chat Room
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Built using Svelte and peerjs | |
<script lang="ts"> | |
import Peer from "peerjs"; | |
import type { DataConnection } from "peerjs"; | |
import { onMount } from "svelte"; | |
type Optional<T> = T | null; | |
interface Message { | |
id?: string; | |
text: string; | |
sender: string; | |
} | |
let peer: Optional<Peer> = null; | |
let conn: Optional<DataConnection> = null; | |
let clients: DataConnection[] = []; | |
let connected = false; | |
let peerID = ""; | |
let connectID = ""; | |
let messageText = ""; | |
let messages: Message[] = []; | |
onMount(() => { | |
if(peer) return; | |
peer = new Peer(); | |
peer.on("open", id => { | |
peerID = id; | |
}); | |
peer.on("error", console.error); | |
peer.on("connection", (conn) => { | |
conn.on("open", () => { | |
clients = [...clients, conn]; | |
sendMessage({ | |
text: `${conn.connectionId} connected`, | |
sender: "System" | |
}); | |
}); | |
conn.on("close", () => { | |
clients = clients.filter(val => val != conn); | |
sendMessage({ | |
text: `${conn.connectionId} left`, | |
sender: "System" | |
}); | |
}); | |
conn.on("data", data => { | |
sendMessage(parseMessage(data), conn); | |
}); | |
}); | |
return () => peer?.destroy(); | |
}); | |
function connect() { | |
if(!peer || connected) return; | |
connectID = connectID.trim(); | |
if(connectID.length == 0) { | |
return alert("You must enter an ID to connect to!"); | |
} | |
conn = peer.connect(connectID, { reliable: true }); | |
conn.on("open", () => connected = true); | |
conn.on("close", () => { | |
connected = false; | |
conn = null; | |
}); | |
conn.on("data", data => onMessageRecieved(parseMessage(data))); | |
} | |
function disconnect() { | |
if(conn) { | |
conn.close(); | |
conn = null; | |
connected = false; | |
} | |
} | |
function sendMsg() { | |
sendMessage({ | |
text: messageText, | |
sender: peerID | |
}); | |
messageText = ""; | |
} | |
function parseMessage(data: unknown) { | |
return JSON.parse(String(data)) as Message; | |
} | |
function sendMessage(msg: Message, except?: DataConnection) { | |
onMessageRecieved(msg); | |
if(clients.length == 0 && !conn) return; | |
let targetConns = clients; | |
if(targetConns.length == 0 && conn) | |
targetConns = [conn]; | |
targetConns.forEach(conn => { | |
if(conn == except) return; | |
conn.send(JSON.stringify(msg)); | |
}); | |
} | |
function onMessageRecieved(msg: Message) { | |
msg.id = crypto.randomUUID(); | |
messages = [...messages, msg]; | |
} | |
</script> | |
<h1>ligma chat</h1> | |
{#if peer} | |
<h3>Peer ID: {peerID}</h3> | |
{#if !connected} | |
<form on:submit|preventDefault={connect}> | |
<input type="text" name="id" placeholder="ID to connect to" bind:value={connectID} /> | |
<input type="submit" /> | |
</form> | |
{:else} | |
<span>Connected to {connectID}</span> | |
<button on:click={disconnect}>Disconnect</button> | |
{/if} | |
<div class="messages"> | |
{#each messages as msg (msg.id)} | |
<span>{msg.sender.substring(0, 6)}: {msg.text}</span> | |
{/each} | |
</div> | |
<form on:submit|preventDefault={sendMsg}> | |
<input type="text" name="msg" placeholder="Message" bind:value={messageText} /> | |
<input type="submit" /> | |
</form> | |
{:else} | |
<p>Peer is not established</p> | |
{/if} | |
<style> | |
.messages { | |
display: flex; | |
flex-direction: column; | |
width: 500px; | |
height: 500px; | |
overflow-y: scroll; | |
border: 1px solid gray; | |
} | |
</style> | |
<svelte:head> | |
<title>Test</title> | |
</svelte:head> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment