import React, { useState, useEffect, useRef } from 'react' import login from './login.png'; import { Input, Button } from 'antd'; import { UserOutlined, LockOutlined } from '@ant-design/icons'; import 'antd/dist/antd.css'; var base64 = require('base-64'); const FETCH_TIMEOUT = 15000; function checkResponse(response) { if(response.status >= 400 && response.status < 600) { throw new Error(response.url + " failed"); } } async function fetchWithTimeout(url, options) { return Promise.race([ fetch(url, options).catch(err => { throw new Error(url + ' failed'); }), new Promise((_, reject) => setTimeout(() => reject(new Error(url + ' timeout')), FETCH_TIMEOUT)) ]); } async function getAvailable() { let available = await fetchWithTimeout("/account/available", { method: 'GET', timeout: FETCH_TIMEOUT }) checkResponse(available) return await available.json() } async function getUsername(name: string) { let available = await fetchWithTimeout('/account/username?name=' + encodeURIComponent(name), { method: 'GET', timeout: FETCH_TIMEOUT }) checkResponse(available) return await available.json() } async function setLogin(username: string, password: string) { let headers = new Headers() headers.append('Authorization', 'Basic ' + base64.encode(username + ":" + password)); let app = { Name: "indicom", Description: "decentralized communication" } let login = await fetchWithTimeout('/account/apps', { method: 'POST', timeout: FETCH_TIMEOUT, body: JSON.stringify(app), headers: headers }) checkResponse(login) return await login.json() } async function createAccount(username: string, password: string) { let headers = new Headers() headers.append('Credentials', 'Basic ' + base64.encode(username + ":" + password)); let profile = await fetchWithTimeout("/account/profile", { method: 'POST', timeout: FETCH_TIMEOUT, headers: headers }) checkResponse(profile); return await profile.json() } function App() { const [available, setAvailable] = useState(false) const [username, setUsername] = useState('') const [password, setPassword] = useState('') const [confirmed, setConfirmed] = useState('') const [mode, setMode] = useState('') const [creatable, setCreatable] = useState(false) const [conflict, setConflict] = useState('') const [token, setToken] = useState('') const debounce = useRef(null) const ws = useRef(null) useEffect(() => { let access = localStorage.getItem("access") console.log("ACCESS", access) if (access == null) { setMode('login') getAvailable().then(a => { setAvailable(a > 0) }).catch(err => { console.log(err) }) } else { setMode('logout') connectStatus(access) } }, []) const usernameSet = (name) => { setCreatable(false) setUsername(name) clearTimeout(debounce.current) debounce.current = setTimeout(async () => { let valid = await getUsername(name) setCreatable(valid) if (!valid) { setConflict('not available') } else { setConflict('') } setCreatable(await getUsername(name)) }, 500) } const connectStatus = (access: string) => { ws.current = new WebSocket("wss://" + window.location.host + "/status"); ws.current.onmessage = (ev) => { console.log(ev) } ws.current.onclose = () => { console.log('ws close') setTimeout(() => { if (ws.current != null) { ws.current.onmessage = () => {} ws.current.onclose = () => {} ws.current.onopen = () => {} ws.current.onerror = () => {} connectStatus(access) } }, 2000) } ws.current.onopen = () => { ws.current.send(JSON.stringify({ AppToken: access })) } ws.current.error = () => { console.log('ws error') } localStorage.setItem("access", access) } const Logout = () => { if (mode === 'logout') { return } return <> } const Link = () => { if (mode === 'create') { return } if (mode === 'login') { return } return <> } const canLogin = () => { return username !== '' && password !== '' } const canCreate = () => { return username !== '' && password !== '' && confirmed === password && creatable } const onLogin = async () => { try { let access = await setLogin(username, password) connectStatus(access) setMode('logout') console.log(access) } catch(err) { window.alert("failed to sign into account") } } const onCreate = async () => { try { let profile = await createAccount(username, password) setMode('created') try { let access = await setLogin(username, password) connectStatus(access) setMode('logout') console.log(access) } catch(err) { window.alert("failed to sign into account") } } catch(err) { window.alert("failed to create account") } } const onLogout = () => { ws.current.onclose = () => {} ws.current.close(1000, "bye") ws.current = null localStorage.removeItem("access") setMode('login') } if (mode === 'login') { return (
indicom
Communication for the Decentralized Web
usernameSet(e.target.value)} value={username} placeholder="username" prefix={} style={{ marginTop: '16px' }} /> setPassword(e.target.value)} value={password} placeholder="password" prefix={} style={{ marginTop: '16px' }} />
) } if (mode === 'create') { return (
indicom
Communication for the Decentralized Web
usernameSet(e.target.value)} value={username} placeholder="username" prefix={} style={{ marginTop: '16px' }} /> setPassword(e.target.value)} value={password} placeholder="password" prefix={} style={{ marginTop: '16px' }} /> setConfirmed(e.target.value)} value={confirmed} placeholder="confirm password" prefix={} style={{ marginTop: '16px' }} />
) } if (mode === 'logout') { return (
indicom
Communication for the Decentralized Web
) } else { return (
) } return <> } export default App;