goon/mobile/src/screens/PinEntry.tsx
goon-foss eead9f159c i18n(mobile): polish UI strings → English
Tłumaczenie wszystkich user-facing stringów PL→EN (bug-report 2026-05-31
"dalej wszystko po polsku"). Alerty, przyciski, placeholdery, labelki w 12
ekranach/komponentach: BugReportFAB, AppLock(Screen/Settings/PinEntry),
applock biometric prompts, doodstream error msgs, MovieDetail, PlaybackQuality,
Player, SceneDetail, ScenesFilter, SiteScenes. Komentarze w kodzie zostają PL.

Zmiany były WIP drugiego okna (uncommitted); wjechały do bundla 0.2.1 przy
buildzie (były w working tree) — apka zainstalowana już ma EN. Ten commit
utrwala je w gicie żeby nie zginęły. Czysto stringi, zero zmian logiki.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 16:27:55 +02:00

133 lines
3.9 KiB
TypeScript

import React, { useState } from 'react';
import { Pressable, StyleSheet, Text, View } from 'react-native';
import * as Haptics from 'expo-haptics';
import { theme } from '../theme';
interface Props {
title: string;
error?: string | null;
onSubmit: (pin: string) => Promise<void> | void;
onCancel: () => void;
}
const KEYS: (string | null)[] = ['1', '2', '3', '4', '5', '6', '7', '8', '9', null, '0', '⌫'];
export function PinEntry({ title, error, onSubmit, onCancel }: Props) {
const [pin, setPin] = useState('');
function press(k: string) {
if (k === '⌫') {
setPin((p) => p.slice(0, -1));
Haptics.selectionAsync().catch(() => {});
return;
}
if (pin.length >= 8) return;
setPin((p) => p + k);
Haptics.selectionAsync().catch(() => {});
}
return (
<View style={styles.root}>
<Text style={styles.title}>{title}</Text>
{error ? <Text style={styles.error}>{error}</Text> : <View style={{ height: 18 }} />}
<View style={styles.dots}>
{Array.from({ length: Math.max(4, pin.length) }).map((_, i) => (
<View
key={i}
style={[styles.dot, i < pin.length && styles.dotFilled]}
/>
))}
</View>
<View style={styles.pad}>
{KEYS.map((k, i) =>
k === null ? (
<View key={i} style={[styles.key, styles.keyEmpty]} />
) : (
<Pressable
key={i}
style={({ pressed }) => [styles.key, pressed && styles.keyPressed]}
onPress={() => press(k)}
>
<Text style={k === '⌫' ? styles.keyBack : styles.keyText}>{k}</Text>
</Pressable>
),
)}
</View>
<View style={styles.actions}>
<Pressable style={styles.ghostBtn} onPress={onCancel}>
<Text style={styles.ghostText}>Cancel</Text>
</Pressable>
<Pressable
style={[styles.primaryBtn, pin.length < 4 && styles.primaryBtnDisabled]}
disabled={pin.length < 4}
onPress={() => onSubmit(pin)}
>
<Text style={styles.primaryText}>Next</Text>
</Pressable>
</View>
</View>
);
}
const KEY_SIZE = 72;
const styles = StyleSheet.create({
root: { flex: 1, backgroundColor: theme.bg, alignItems: 'center', paddingTop: 60 },
title: { color: theme.fg, fontSize: 18, fontWeight: '700' },
error: { color: theme.bad, fontSize: 13, marginTop: 8 },
dots: { flexDirection: 'row', gap: 14, marginTop: 14, minHeight: 16 },
dot: {
width: 12,
height: 12,
borderRadius: 6,
borderWidth: 1.5,
borderColor: theme.border,
},
dotFilled: { backgroundColor: theme.accent, borderColor: theme.accent },
pad: {
marginTop: 24,
flexDirection: 'row',
flexWrap: 'wrap',
width: KEY_SIZE * 3 + 36,
justifyContent: 'space-between',
rowGap: 12,
},
key: {
width: KEY_SIZE,
height: KEY_SIZE,
borderRadius: KEY_SIZE / 2,
backgroundColor: theme.card,
borderWidth: 1,
borderColor: theme.border,
alignItems: 'center',
justifyContent: 'center',
},
keyEmpty: { backgroundColor: 'transparent', borderColor: 'transparent' },
keyPressed: { backgroundColor: theme.bgElevated, borderColor: theme.borderFocus },
keyText: { color: theme.fg, fontSize: 26, fontWeight: '500' },
keyBack: { color: theme.muted, fontSize: 22 },
actions: {
flexDirection: 'row',
gap: 12,
marginTop: 28,
paddingHorizontal: 24,
},
ghostBtn: {
paddingVertical: 12,
paddingHorizontal: 22,
borderRadius: 10,
borderWidth: 1,
borderColor: theme.border,
},
ghostText: { color: theme.muted, fontSize: 14, fontWeight: '600' },
primaryBtn: {
paddingVertical: 12,
paddingHorizontal: 30,
borderRadius: 10,
backgroundColor: theme.accent,
},
primaryBtnDisabled: { backgroundColor: theme.border },
primaryText: { color: '#fff', fontSize: 14, fontWeight: '700' },
});