import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import './styles/index.css'; import App from './App.tsx'; const isTauri = 'window' in globalThis && '__TAURI_INTERNALS__' in window; if (isTauri) { // WebView safe-area fallbacks: Android doesn't support CSS env(), and // Linux WebKitGTK chokes on env() inside var(). Set explicit values via JS. if (navigator.userAgent.includes('Android')) { document.documentElement.style.setProperty('--safe-top', '1.5rem'); document.documentElement.style.setProperty('--safe-bottom', '0.75rem'); document.documentElement.style.setProperty('--safe-left', '0px'); document.documentElement.style.setProperty('--safe-right', '0px'); } else { // Linux / macOS Tauri — no notch, but body has default padding already document.documentElement.style.setProperty('--safe-top', '0px'); document.documentElement.style.setProperty('--safe-bottom', '0px'); document.documentElement.style.setProperty('--safe-left', '0px'); document.documentElement.style.setProperty('--safe-right', '0px'); } const TARGET = 'https://dumpster.dustin.coffee'; const WS_TARGET = 'wss://dumpster.dustin.coffee'; let sessionToken = localStorage.getItem('dumpster_session_token') || ''; const originalFetch = window.fetch; window.fetch = async (input, init) => { let url = typeof input === 'string' ? input : input.toString(); if (url.startsWith('/')) { url = TARGET + url; } let newInit = init ? { ...init } : {}; if (sessionToken) { newInit.headers = { ...newInit.headers, 'Authorization': 'Bearer ' + sessionToken }; } const response = await originalFetch(url, newInit); const token = response.headers.get('X-Session-Token'); if (token) { sessionToken = token; localStorage.setItem('dumpster_session_token', token); } if (url.endsWith('/auth/logout') && response.ok) { sessionToken = ''; localStorage.removeItem('dumpster_session_token'); } return response; }; const OriginalWebSocket = window.WebSocket; window.WebSocket = function(url: string | URL, protocols?: string | string[]) { let urlStr = typeof url === 'string' ? url : url.toString(); if (urlStr.includes('tauri.localhost') || urlStr.includes('tauri://localhost')) { urlStr = urlStr.replace(/^(wss?|https?|tauri):\/\/tauri\.localhost/, WS_TARGET); urlStr = urlStr.replace(/^tauri:\/\/localhost/, WS_TARGET); } else if (urlStr.startsWith('ws://localhost') && isTauri) { urlStr = urlStr.replace('ws://localhost', WS_TARGET); } else if (urlStr.startsWith('/')) { urlStr = WS_TARGET + urlStr; } const ws = new OriginalWebSocket(urlStr, protocols); if (sessionToken && urlStr.includes('/ws') && !urlStr.includes('/ws/bot')) { const originalOnOpen = ws.onopen; ws.onopen = function(ev) { ws.send(JSON.stringify({ token: sessionToken })); if (originalOnOpen) originalOnOpen.call(ws, ev); }; } return ws; } as unknown as typeof WebSocket; // ponytail: WebKitGTK may have read-only prototype — guard against throw try { window.WebSocket.prototype = OriginalWebSocket.prototype; } catch { /* readonly, fine */ } } createRoot(document.getElementById('root')!).render( , );