fix(mobile/login): one-tap public pairing, manual URL/key behind Advanced
Pairing is automatic (App.tsx auto-connects to the public instance when no creds are stored); the login screen only appears after an explicit Sign out. It defaulted to localhost + empty key, forcing manual entry that no longer reflects how pairing works. Now it prefills the public backend + shipped key (one-tap 'Connect to public instance') and tucks the URL/API-key fields under an 'Advanced · self-hosted backend' toggle for power users. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
bb5a97e288
commit
7981ba3408
1 changed files with 71 additions and 33 deletions
|
|
@ -12,6 +12,7 @@ import {
|
|||
} from 'react-native';
|
||||
import { GoonClient } from '../api';
|
||||
import { GoonMark, GoonWordmark } from '../components/GoonWordmark';
|
||||
import { DEFAULT_API_KEY, DEFAULT_BACKEND_URL } from '../lib/backend';
|
||||
import { saveCredentials } from '../storage';
|
||||
import { theme } from '../theme';
|
||||
|
||||
|
|
@ -20,9 +21,14 @@ interface Props {
|
|||
}
|
||||
|
||||
export function LoginScreen({ onAuthenticated }: Props) {
|
||||
const [baseUrl, setBaseUrl] = useState('http://localhost:8000');
|
||||
const [apiKey, setApiKey] = useState('');
|
||||
// Pairing jest domyślnie automatyczny (App.tsx auto-connectuje do publicznej instancji
|
||||
// gdy brak zapisanych creds). Ten ekran pojawia się tylko po explicit "Sign out" —
|
||||
// prefillujemy publiczne defaulty, więc reconnect to JEDEN tap, bez wpisywania URL/klucza.
|
||||
// Ręczne pola są pod "Advanced" dla self-hosterów.
|
||||
const [baseUrl, setBaseUrl] = useState(DEFAULT_BACKEND_URL);
|
||||
const [apiKey, setApiKey] = useState(DEFAULT_API_KEY);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [advanced, setAdvanced] = useState(false);
|
||||
const [urlFocused, setUrlFocused] = useState(false);
|
||||
const [keyFocused, setKeyFocused] = useState(false);
|
||||
|
||||
|
|
@ -67,10 +73,13 @@ export function LoginScreen({ onAuthenticated }: Props) {
|
|||
<View style={styles.card}>
|
||||
<Text style={styles.cardLabel}>Connect</Text>
|
||||
<Text style={styles.cardHint}>
|
||||
Pair this device with your backend. Credentials are stored encrypted in
|
||||
secure-storage on this device only.
|
||||
{advanced
|
||||
? 'Point the app at your own self-hosted backend. Credentials are stored encrypted in secure-storage on this device only.'
|
||||
: 'Connects to the public goon instance — no setup needed.'}
|
||||
</Text>
|
||||
|
||||
{advanced && (
|
||||
<>
|
||||
<Text style={styles.label}>Backend URL</Text>
|
||||
<TextInput
|
||||
style={[styles.input, urlFocused && styles.inputFocused]}
|
||||
|
|
@ -80,7 +89,7 @@ export function LoginScreen({ onAuthenticated }: Props) {
|
|||
onBlur={() => setUrlFocused(false)}
|
||||
autoCapitalize="none"
|
||||
keyboardType="url"
|
||||
placeholder="http://localhost:8000"
|
||||
placeholder={DEFAULT_BACKEND_URL}
|
||||
placeholderTextColor={theme.mutedDim}
|
||||
/>
|
||||
|
||||
|
|
@ -96,6 +105,8 @@ export function LoginScreen({ onAuthenticated }: Props) {
|
|||
placeholder="paste your X-API-Key"
|
||||
placeholderTextColor={theme.mutedDim}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
<Pressable
|
||||
style={({ pressed }) => [
|
||||
|
|
@ -107,15 +118,34 @@ export function LoginScreen({ onAuthenticated }: Props) {
|
|||
disabled={loading}
|
||||
>
|
||||
<Text style={styles.buttonText}>
|
||||
{loading ? 'Connecting…' : 'Connect'}
|
||||
{loading ? 'Connecting…' : advanced ? 'Connect' : 'Connect to public instance'}
|
||||
</Text>
|
||||
</Pressable>
|
||||
|
||||
<Pressable
|
||||
onPress={() => {
|
||||
if (advanced) {
|
||||
// Powrót do publicznej instancji — reset pól do defaultów.
|
||||
setBaseUrl(DEFAULT_BACKEND_URL);
|
||||
setApiKey(DEFAULT_API_KEY);
|
||||
}
|
||||
setAdvanced((v) => !v);
|
||||
}}
|
||||
hitSlop={8}
|
||||
style={styles.advancedToggle}
|
||||
>
|
||||
<Text style={styles.advancedToggleText}>
|
||||
{advanced ? '← Use public instance' : 'Advanced · self-hosted backend'}
|
||||
</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
|
||||
{advanced && (
|
||||
<Text style={styles.footer}>
|
||||
Need help? Check the <Text style={styles.footerEm}>X-API-Key</Text> in your
|
||||
backend .env file.
|
||||
</Text>
|
||||
)}
|
||||
</ScrollView>
|
||||
</KeyboardAvoidingView>
|
||||
);
|
||||
|
|
@ -231,4 +261,12 @@ const styles = StyleSheet.create({
|
|||
lineHeight: 18,
|
||||
},
|
||||
footerEm: { color: theme.muted, fontWeight: '700' },
|
||||
|
||||
advancedToggle: { marginTop: 16, alignItems: 'center' },
|
||||
advancedToggleText: {
|
||||
color: theme.muted,
|
||||
fontSize: 12,
|
||||
fontWeight: '600',
|
||||
letterSpacing: 0.3,
|
||||
},
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue