diff --git a/package-lock.json b/package-lock.json index 9260183..d9768dd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -146,7 +146,6 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.6.tgz", "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==", "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/generator": "^7.28.6", @@ -512,7 +511,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" }, @@ -553,7 +551,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" } @@ -1057,7 +1054,6 @@ "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.22.12.tgz", "integrity": "sha512-xcmww1O/JFP2MrlGUMd3Q78S3Qu6W3mYTXYuIqFq33EorgYHV/HqymHfXy9GjiCJ7OI+7lWx6nYFOzU7M4rd1Q==", "license": "MIT", - "peer": true, "dependencies": { "@jimp/core": "^0.22.12" } @@ -1094,7 +1090,6 @@ "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-0.22.12.tgz", "integrity": "sha512-xslz2ZoFZOPLY8EZ4dC29m168BtDx95D6K80TzgUi8gqT7LY6CsajWO0FAxDwHz6h0eomHMfyGX0stspBrTKnQ==", "license": "MIT", - "peer": true, "dependencies": { "@jimp/utils": "^0.22.12" }, @@ -1107,7 +1102,6 @@ "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-0.22.12.tgz", "integrity": "sha512-S0vJADTuh1Q9F+cXAwFPlrKWzDj2F9t/9JAbUvaaDuivpyWuImEKXVz5PUZw2NbpuSHjwssbTpOZ8F13iJX4uw==", "license": "MIT", - "peer": true, "dependencies": { "@jimp/utils": "^0.22.12" }, @@ -1132,7 +1126,6 @@ "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-0.22.12.tgz", "integrity": "sha512-xImhTE5BpS8xa+mAN6j4sMRWaUgUDLoaGHhJhpC+r7SKKErYDR0WQV4yCE4gP+N0gozD0F3Ka1LUSaMXrn7ZIA==", "license": "MIT", - "peer": true, "dependencies": { "@jimp/utils": "^0.22.12", "tinycolor2": "^1.6.0" @@ -1176,7 +1169,6 @@ "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-0.22.12.tgz", "integrity": "sha512-FNuUN0OVzRCozx8XSgP9MyLGMxNHHJMFt+LJuFjn1mu3k0VQxrzqbN06yIl46TVejhyAhcq5gLzqmSCHvlcBVw==", "license": "MIT", - "peer": true, "dependencies": { "@jimp/utils": "^0.22.12" }, @@ -1300,7 +1292,6 @@ "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.22.12.tgz", "integrity": "sha512-3NyTPlPbTnGKDIbaBgQ3HbE6wXbAlFfxHVERmrbqAi8R3r6fQPxpCauA8UVDnieg5eo04D0T8nnnNIX//i/sXg==", "license": "MIT", - "peer": true, "dependencies": { "@jimp/utils": "^0.22.12" }, @@ -1313,7 +1304,6 @@ "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-0.22.12.tgz", "integrity": "sha512-9YNEt7BPAFfTls2FGfKBVgwwLUuKqy+E8bDGGEsOqHtbuhbshVGxN2WMZaD4gh5IDWvR+emmmPPWGgaYNYt1gA==", "license": "MIT", - "peer": true, "dependencies": { "@jimp/utils": "^0.22.12" }, @@ -1329,7 +1319,6 @@ "resolved": "https://registry.npmjs.org/@jimp/plugin-scale/-/plugin-scale-0.22.12.tgz", "integrity": "sha512-dghs92qM6MhHj0HrV2qAwKPMklQtjNpoYgAB94ysYpsXslhRTiPisueSIELRwZGEr0J0VUxpUY7HgJwlSIgGZw==", "license": "MIT", - "peer": true, "dependencies": { "@jimp/utils": "^0.22.12" }, @@ -3248,7 +3237,6 @@ "resolved": "https://registry.npmjs.org/@tanstack/react-router/-/react-router-1.157.16.tgz", "integrity": "sha512-xwFQa7S7dhBhm3aJYwU79cITEYgAKSrcL6wokaROIvl2JyIeazn8jueWqUPJzFjv+QF6Q8euKRlKUEyb5q2ymg==", "license": "MIT", - "peer": true, "dependencies": { "@tanstack/history": "1.154.14", "@tanstack/react-store": "^0.8.0", @@ -3418,7 +3406,6 @@ "resolved": "https://registry.npmjs.org/@tanstack/router-core/-/router-core-1.157.16.tgz", "integrity": "sha512-eJuVgM7KZYTTr4uPorbUzUflmljMVcaX2g6VvhITLnHmg9SBx9RAgtQ1HmT+72mzyIbRSlQ1q0fY/m+of/fosA==", "license": "MIT", - "peer": true, "dependencies": { "@tanstack/history": "1.154.14", "@tanstack/store": "^0.8.0", @@ -3731,7 +3718,6 @@ "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", @@ -3872,7 +3858,6 @@ "integrity": "sha512-MciR4AKGHWl7xwxkBa6xUGxQJ4VBOmPTF7sL+iGzuahOFaO0jHCsuEfS80pan1ef4gWId1oWOweIhrDEYLuaOw==", "devOptional": true, "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~6.21.0" } @@ -3892,7 +3877,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.10.tgz", "integrity": "sha512-WPigyYuGhgZ/cTPRXB2EwUw+XvsRA3GqHlsP4qteqrnnjDrApbS7MxcGr/hke5iUoeB7E/gQtrs9I37zAJ0Vjw==", "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -3902,7 +3886,6 @@ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", "license": "MIT", - "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } @@ -4366,7 +4349,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -4671,7 +4653,6 @@ "resolved": "https://registry.npmjs.org/crossws/-/crossws-0.4.4.tgz", "integrity": "sha512-w6c4OdpRNnudVmcgr7brb/+/HmYjMQvYToO/oTrprTwxRUiom3LYWU1PMWuD006okbUWpII1Ea9/+kwpUfmyRg==", "license": "MIT", - "peer": true, "peerDependencies": { "srvx": ">=0.7.1" }, @@ -4766,8 +4747,7 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/daisyui": { "version": "5.5.14", @@ -4808,7 +4788,6 @@ "resolved": "https://registry.npmjs.org/db0/-/db0-0.3.4.tgz", "integrity": "sha512-RiXXi4WaNzPTHEOu8UPQKMooIbqOEyqA1t7Z6MsdxSCeb8iUC9ko3LcmsLmeUt2SM5bctfArZKkRQggKZz7JNw==", "license": "MIT", - "peer": true, "peerDependencies": { "@electric-sql/pglite": "*", "@libsql/client": "*", @@ -6253,20 +6232,6 @@ } } }, - "node_modules/nitro/node_modules/readdirp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", - "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/nitro/node_modules/unstorage": { "version": "2.0.0-alpha.5", "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-2.0.0-alpha.5.tgz", @@ -6467,8 +6432,7 @@ "version": "2.0.0-alpha.3", "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-2.0.0-alpha.3.tgz", "integrity": "sha512-zpYTCs2byOuft65vI3z43Dd6iSdFbOZZLb9/d21aCpx2rGastVU9dOCv0lu4ykc1Ur1anAYjDi3SUvR0vq50JA==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/ohash": { "version": "2.0.11", @@ -6827,7 +6791,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -6948,7 +6911,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -6958,7 +6920,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -7133,7 +7094,6 @@ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.0.tgz", "integrity": "sha512-e5lPJi/aui4TO1LpAXIRLySmwXSE8k3b9zoGfd42p67wzxog4WHjiZF3M2uheQih4DGyc25QEV4yRBbpueNiUA==", "license": "MIT", - "peer": true, "dependencies": { "@types/estree": "1.0.8" }, @@ -7247,7 +7207,6 @@ "resolved": "https://registry.npmjs.org/seroval/-/seroval-1.5.0.tgz", "integrity": "sha512-OE4cvmJ1uSPrKorFIH9/w/Qwuvi/IMcGbv5RKgcJ/zjA/IohDLU6SVaxFN9FwajbP7nsX0dQqMDes1whk3y+yw==", "license": "MIT", - "peer": true, "engines": { "node": ">=10" } @@ -7322,7 +7281,6 @@ "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.9.11.tgz", "integrity": "sha512-WEJtcc5mkh/BnHA6Yrg4whlF8g6QwpmXXRg4P2ztPmcKeHHlH4+djYecBLhSpecZY2RRECXYUwIc/C2r3yzQ4Q==", "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.1.0", "seroval": "~1.5.0", @@ -7465,8 +7423,7 @@ "version": "4.1.18", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz", "integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/tapable": { "version": "2.3.0", @@ -7691,7 +7648,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -7806,7 +7762,6 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", diff --git a/src/hooks/useRemoteConnection.ts b/src/hooks/useRemoteConnection.ts index b04ebd4..4ab5c67 100644 --- a/src/hooks/useRemoteConnection.ts +++ b/src/hooks/useRemoteConnection.ts @@ -3,6 +3,9 @@ import { useState, useEffect, useCallback } from 'react'; export const useRemoteConnection = () => { const [ws, setWs] = useState(null); const [status, setStatus] = useState<'connecting' | 'connected' | 'disconnected'>('disconnected'); + const [isAuthenticated, setIsAuthenticated] = useState(false); + const [authRequired, setAuthRequired] = useState(false); + const [authError, setAuthError] = useState(false); useEffect(() => { const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; @@ -16,9 +19,38 @@ export const useRemoteConnection = () => { setStatus('connecting'); const socket = new WebSocket(wsUrl); - socket.onopen = () => setStatus('connected'); + socket.onopen = () => { + setStatus('connected'); + // Auth state is determined by the 'connected' message + }; + + socket.onmessage = (event) => { + try { + const msg = JSON.parse(event.data); + if (msg.type === 'connected') { + if (msg.authRequired) { + setAuthRequired(true); + setIsAuthenticated(false); + } else { + setIsAuthenticated(true); + setAuthRequired(false); + } + } else if (msg.type === 'auth-success') { + setIsAuthenticated(true); + setAuthError(false); + } else if (msg.type === 'auth-failed') { + setAuthError(true); + setIsAuthenticated(false); + } + } catch (e) { + console.error('WS Message Error', e); + } + }; + socket.onclose = () => { setStatus('disconnected'); + setIsAuthenticated(false); + setAuthRequired(false); reconnectTimer = setTimeout(connect, 3000); }; socket.onerror = (e) => { @@ -42,5 +74,11 @@ export const useRemoteConnection = () => { } }, [ws]); - return { status, send }; + const authenticate = useCallback((pin: string) => { + if (ws?.readyState === WebSocket.OPEN) { + ws.send(JSON.stringify({ type: 'authenticate', pin })); + } + }, [ws]); + + return { status, send, isAuthenticated, authRequired, authenticate, authError }; }; diff --git a/src/routes/settings.tsx b/src/routes/settings.tsx index dde409f..b078c83 100644 --- a/src/routes/settings.tsx +++ b/src/routes/settings.tsx @@ -13,6 +13,7 @@ function SettingsPage() { const [invertScroll, setInvertScroll] = useState(CONFIG.MOUSE_INVERT); const [sensitivity, setSensitivity] = useState(CONFIG.MOUSE_SENSITIVITY); const [qrData, setQrData] = useState(''); + const [pin, setPin] = useState(null); // Load initial state useEffect(() => { @@ -53,12 +54,24 @@ function SettingsPage() { socket.onopen = () => { console.log('Connected to local server for IP detection'); - socket.send(JSON.stringify({ type: 'get-ip' })); + // socket.send(JSON.stringify({ type: 'get-ip' })); // Not strictly needed as connected sends logic }; socket.onmessage = (event) => { try { const data = JSON.parse(event.data); + + if (data.type === 'connected') { + if (data.serverIp) { + console.log('Auto-detected IP:', data.serverIp); + setIp(data.serverIp); + } + if (data.pin) { + console.log('Received session PIN'); + setPin(data.pin); + } + } + if (data.type === 'server-ip' && data.ip) { console.log('Auto-detected IP:', data.ip); setIp(data.ip); @@ -84,6 +97,19 @@ function SettingsPage() {

Settings

+ {pin && ( +
+
+ +
+

Session PIN

+
Enter this PIN on your mobile device
+
+
+
{pin}
+
+ )} +