codexmobile-relay / client /src /PairingScreen.jsx
Codex
deploy: CodexMobile Relay
90f0300
Raw
History Blame Contribute Delete
1.8 kB
import { Check, Loader2, Monitor } from 'lucide-react';
import { useState } from 'react';
import { apiFetch, requestPersistentStorage, setToken } from './api.js';
export function PairingScreen({ onPaired }) {
const [code, setCode] = useState('');
const [error, setError] = useState('');
const [pairing, setPairing] = useState(false);
async function handlePair(event) {
event.preventDefault();
setPairing(true);
setError('');
try {
const result = await apiFetch('/api/pair', {
method: 'POST',
body: {
code,
deviceName: navigator.platform || 'iPhone'
}
});
setToken(result.token);
requestPersistentStorage();
onPaired();
} catch (err) {
setError(err.message);
} finally {
setPairing(false);
}
}
return (
<main className="pairing-screen">
<div className="pairing-mark">
<Monitor size={30} />
</div>
<h1>CodexMobile</h1>
<p>输入电脑端启动日志里的配对码。</p>
<form className="pairing-form" onSubmit={handlePair}>
<label className="sr-only" htmlFor="pairing-code">配对码</label>
<input
id="pairing-code"
name="pairingCode"
inputMode="numeric"
autoComplete="one-time-code"
maxLength={6}
placeholder="6 位配对码"
value={code}
onChange={(event) => setCode(event.target.value.replace(/\D/g, '').slice(0, 6))}
/>
<button type="submit" disabled={code.length !== 6 || pairing}>
{pairing ? <Loader2 className="spin" size={18} /> : <Check size={18} />}
连接
</button>
</form>
{error ? <div className="pairing-error" role="alert">{error}</div> : null}
</main>
);
}