Skip to content

Commit

Permalink
feat: user peer
Browse files Browse the repository at this point in the history
  • Loading branch information
thewh1teagle committed Nov 20, 2023
1 parent bb0e2a4 commit 5ea313f
Show file tree
Hide file tree
Showing 5 changed files with 343 additions and 175 deletions.
71 changes: 18 additions & 53 deletions desktop/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,53 +1,19 @@
import { invoke } from "@tauri-apps/api/tauri";
import { useLocalStorage } from "@uidotdev/usehooks";
import { DataConnection, Peer } from "peerjs";
import { useEffect, useRef, useState } from "react";
import { useEffect, useRef } from "react";
import { v4 as uuidv4 } from 'uuid';
import successSvg from "./assets/success.svg";
import { BASE_URL, PEERJS_OPTIONS } from "./config";
import { BASE_URL } from "./config";
import { createQR } from "./qr";


enum Action {
VOL_UP,
VOL_DN,
PG_UP,
PG_DN,
F5,
ESC
}

interface Message {
action: Action;
}

import { Action, usePeer } from "./usePeer";


function App() {
const [id, ] = useLocalStorage('id', uuidv4())
console.log('localstorage id => ', id)
const [loading, setLoading] = useState(true);
const [peer, ] = useState(new Peer(id, PEERJS_OPTIONS));
const [conn, setConn] = useState<DataConnection | null>(null);
const {message, status} = usePeer(id, true)
const qrDiv = useRef<HTMLDivElement>(null);

function onMessage(message: unknown) {
const data = JSON.parse(message as string) as Message;
invoke("press", { key: Action[data.action].toString() });
}

useEffect(() => {
conn?.on("data", onMessage);
}, [conn]);

function onConnect(connection: DataConnection) {
connection.on("iceStateChanged", (state) => {
if (state === "disconnected" || state == "closed") {
onDisconnect();
}
});
setConn(connection);
}


async function renderQR() {
const url = `${BASE_URL}?id=${id}`;
Expand All @@ -57,35 +23,34 @@ function App() {
const newQR = createQR(url);

const element = await newQR._getElement();
setLoading(false);
if (element) {
qrDiv.current?.appendChild(element);
}
}
async function onDisconnect() {
console.log("disconnected");
renderQR()

// qrRef?.current?.update({data: url})
setConn(null);
}

useEffect(() => {
peer.on("open", () => {
console.log('status => ', status)
if (status === 'READY') {
console.log("creating qr");
const url = `${BASE_URL}?id=${id}`;
console.log("url => ", url);
renderQR()
});
peer.on("connection", onConnect);
}, []);
}
}, [status])

useEffect(() => {
if (message) {
invoke("press", { key: Action[message.action].toString() });
}
}, [message])


function copyURL() {
const url = `${BASE_URL}?id=${id}`;
navigator.clipboard.writeText(url);
}

if (conn) {
if (status === 'CONNECTED') {
return (
<div className="flex flex-col items-center justify-center w-full h-[100vh]">
<span className="text-3xl mb-5">CONNECTED</span>
Expand All @@ -98,7 +63,7 @@ function App() {
<div className="flex flex-col w-[100vw] h-[100vh] items-center justify-center">
<span className="text-3xl mb-5">Ready to connect</span>
<div ref={qrDiv} />
{loading && (
{status === 'INIT' && (
<div className="flex items-center justify-center w-[300px] h-[300px] rounded-xl bg-transparent shadow-xl">
<span className="loading loading-spinner loading-lg p-0"></span>
</div>
Expand Down
4 changes: 3 additions & 1 deletion desktop/src/config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import {PeerOptions} from 'peerjs'
export const BASE_URL = 'https://thewh1teagle.github.io/mobslide/'


export const BASE_URL = import.meta.env.MODE === 'development' ? 'http://localhost:5173/mobslide/' : 'https://thewh1teagle.github.io/mobslide/'
export const PEERJS_OPTIONS: PeerOptions = {
host: 'mobslide-signaling.fly.dev',
port: 443,
Expand Down
153 changes: 153 additions & 0 deletions desktop/src/usePeer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import { useRef, useState, useEffect } from "react";
import Peer, { DataConnection } from "peerjs";
import { PEERJS_OPTIONS } from "./config";

export enum Action {
VOL_UP,
VOL_DN,
PG_UP,
PG_DN,
F5,
ESC,
}
export interface Message {
action: Action;
}

type Status = "CONNECTING" | "CONNECTED" | "DISCONNECTED" | "INIT" | "READY";

export function usePeer(id?: string, listener?: boolean) {
const peerRef = useRef<Peer>();
const connRef = useRef<DataConnection>();
const addressRef = useRef<null | string>("");
const checkConnectionIntervalRef = useRef<number | null>(null);
const connectIntervalRef = useRef<number | null>(null);
const [message, setMessage] = useState<Message | null>()

const [status, setStatus] = useState<Status>("INIT");


function onMessage(message: unknown) {
const data = JSON.parse(message as string) as Message | null;
setMessage(data)
}

function reconnect() {
if (checkConnectionIntervalRef.current) {
clearInterval(checkConnectionIntervalRef.current);
}
if (connectIntervalRef.current) {
clearInterval(connectIntervalRef.current);
}
// reconnect
peerRef.current?.destroy();
connRef.current?.close();
connRef.current = undefined;
peerRef.current = undefined;
setStatus("CONNECTING");
if (checkConnectionIntervalRef.current) {
clearInterval(checkConnectionIntervalRef.current);
}
connectIntervalRef.current = setInterval(() => connect(), 5000);
}

function checkConnection() {
if (!connRef.current?.peerConnection) {
// reconnect
reconnect();
}
}

async function createConnection() {
setStatus("CONNECTING");
return new Promise<void>((resolve, reject) => {
console.log("connecting to ", addressRef.current);
if (id) {
peerRef.current = new Peer(id, PEERJS_OPTIONS);
} else {
peerRef.current = new Peer(PEERJS_OPTIONS);
}

peerRef.current.on("open", () => {
setStatus('READY')
if (addressRef.current) {
peerRef?.current?.on("error", (error) => reject(error));
connRef.current = peerRef.current?.connect(addressRef.current);
connRef.current?.on("open", () => resolve());
}
});

});
}

function listen() {
if (id) {
peerRef.current = new Peer(id, PEERJS_OPTIONS);
} else {
peerRef.current = new Peer(PEERJS_OPTIONS);
}

peerRef.current?.on("open", () => {
setStatus('READY')
});
peerRef.current.on('connection', conn => {
setStatus('CONNECTED')
connRef.current = conn
connRef.current?.on('data', onMessage)
connRef.current.on('iceStateChanged', (state) => {
if (state === 'disconnected' || state === 'closed') {
peerRef.current?.destroy();
connRef.current?.close();
connRef.current = undefined;
peerRef.current = undefined;
listen()
setStatus('DISCONNECTED')
return
}
})
})
}

if (listener) {
useEffect(() => {
listen()
}, [])
}

async function connect() {
try {
await createConnection();
connRef.current?.on('data', onMessage)
connRef.current?.once("iceStateChanged", (state) => {
if (
state === "disconnected" ||
state == "closed" ||
state == "failed"
) {
reconnect();
}
});
if (connectIntervalRef.current) {
clearInterval(connectIntervalRef.current!);
}
checkConnectionIntervalRef.current = setInterval(checkConnection, 1000);
setStatus("CONNECTED");
} catch (e) {
console.log(e);
}
}

function sendMessage(data: Message) {
console.log("sending => ", data);
navigator.vibrate(60);

connRef.current?.send(JSON.stringify(data));
}

function connectWrapper(address: string) {
addressRef.current = address;
reconnect();
}
return { connectWrapper, sendMessage, status, message };
}

Loading

0 comments on commit 5ea313f

Please sign in to comment.