Peace 1 week ago
parent ce50e78fb1
commit f78b3f2c16
  1. 162
      every-jap-dict/App.tsx

@ -1,50 +1,186 @@
import { StatusBar } from 'expo-status-bar';
import { SafeAreaView, StyleSheet, View } from 'react-native';
import { FlatList, Modal, Pressable, StyleSheet, View } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { GluestackUIProvider } from '@/components/ui/gluestack-ui-provider';
import '@/global.css';
import { useWordbook, WordbookProvider } from './lib/wordbook/context';
import { Text } from './components/ui/text';
import { useMemo, useState } from 'react';
import { languages } from './lib/providers/dictionaries';
import { jaPack, languages } from './lib/providers/dictionaries';
import { Input, InputField } from './components/ui/input';
import { HStack } from './components/ui/hstack';
import { Button, ButtonText } from './components/ui/button';
import DictWebView from './components/DictWebView';
import AdBannerPlaceholder from './components/AdBannerPlaceholder';
function MainScreen() {
const [q, setQ] = useState('');
const [langIdx, setLangIdx] = useState(0);
const [query, setQuery] = useState('');
const [activeId, setActiveId] = useState<string>('');
const [wordbookOpen, setWordbookOpen] = useState(false);
const pack = languages[langIdx];
const pack = jaPack;
const providers = pack.providers;
const canSearch = q.trim().length > 0;
const hasQuery = query.trim().length > 0;
const { add, items, remove, clear, loading } = useWordbook();
const urls = useMemo(
() =>
providers.reduce<Record<string, string>>((acc, p) => {
acc[p.id] = canSearch ? p.buildUrl(q.trim()) : '';
acc[p.id] = hasQuery ? p.buildUrl(query.trim()) : '';
return acc;
}, {}),
[providers, q, canSearch],
[providers, query, hasQuery],
);
const onSearch = () => {
if (!canSearch) return;
setQuery(q.trim());
setActiveId(providers[0]?.id ?? '');
};
const onSave = () => {
if (!canSearch) return;
add(q.trim(), pack.code);
};
const onPickWord = (word: string) => {
const t = word.trim();
setWordbookOpen(false);
setQ(t);
setQuery(t);
setActiveId(providers[0]?.id ?? '');
};
return (
<SafeAreaView className="flex-1 bg-white">
<View className="flex-1">
{/* 상단 검색창, 버튼 */}
<View className="p-4 gap-3">
<Text>Hello</Text>
{/* 액션 버튼 */}
<HStack space="md" className="flex-row">
<Button className="flex-1" onPress={() => setWordbookOpen(true)} action="secondary">
<ButtonText> </ButtonText>
</Button>
<Button className="flex-1" onPress={onSave} action="secondary" isDisabled={!canSearch}>
<ButtonText> </ButtonText>
</Button>
</HStack>
{/* 검색창 */}
<HStack space="md" className="flex-row">
<Input className="flex-1">
<InputField
placeholder="검색어를 입력하세요"
value={q}
onChangeText={setQ}
returnKeyType="search"
onSubmitEditing={onSearch}
/>
</Input>
<Button onPress={onSearch} isDisabled={!canSearch}>
<ButtonText></ButtonText>
</Button>
</HStack>
</View>
{/* 커스텀 탭 헤더 */}
<View className="px-4 pb-2">
<HStack space="sm" className="flex-row">
{providers.map((p) => {
const selected = activeId ? activeId === p.id : false;
return (
<Button
className="flex-1"
key={p.id}
variant={selected ? 'solid' : 'outline'}
onPress={() => setActiveId(p.id)}
isDisabled={!canSearch}
>
<ButtonText>{p.label}</ButtonText>
</Button>
);
})}
</HStack>
</View>
</SafeAreaView>
{/* 패널: WebView 모두 마운트 후 토글 */}
<View className="flex-1">
{!canSearch ? (
<View className="flex-1 items-center justify-center">
<Text> [] </Text>
</View>
) : activeId ? (
<DictWebView url={urls[activeId]} />
) : (
<View className="flex-1 items-center justify-center">
<Text> </Text>
</View>
)}
</View>
<AdBannerPlaceholder />
<Modal
visible={wordbookOpen}
animationType="slide"
onRequestClose={() => setWordbookOpen(false)}
>
<View className="flex-1 p-4 gap-3">
<View className="flex-row justify-between items-center">
<Text className="text-lg font-semibold"></Text>
<HStack space="md" className="flex-row">
<Button action="negative" onPress={clear}>
<ButtonText></ButtonText>
</Button>
<Button onPress={() => setWordbookOpen(false)}>
<ButtonText></ButtonText>
</Button>
</HStack>
</View>
{loading ? (
<View className="flex-1 items-center justify-center">
<Text> ...</Text>
</View>
) : (
<FlatList
className="flex-1"
data={items}
keyExtractor={(x) => x.id}
renderItem={({ item }) => (
<View className="flex-row justify-between py-3 gap-4">
<Pressable
onPress={() => onPickWord(item.text)}
style={{ flex: 1 }}
className="justify-center items-center"
>
<Text className="text-lg">{item.text}</Text>
</Pressable>
<Button action="secondary" onPress={() => remove(item.id)}>
<ButtonText></ButtonText>
</Button>
</View>
)}
/>
)}
</View>
</Modal>
</View>
);
}
export default function App() {
return (
<GluestackUIProvider mode="light">
<StatusBar style="auto" />
<WordbookProvider>
<MainScreen />
</WordbookProvider>
<SafeAreaView style={{ flex: 1 }}>
<StatusBar style="auto" />
<WordbookProvider>
<MainScreen />
</WordbookProvider>
</SafeAreaView>
</GluestackUIProvider>
);
}

Loading…
Cancel
Save