Peace 1 week ago
parent 256b222d69
commit 036ed5441a
  1. 57
      every-jap-dict/App.tsx
  2. 10
      every-jap-dict/app.json
  3. 12
      every-jap-dict/components/AdBannerPlaceholder.tsx
  4. 1600
      every-jap-dict/components/ui/icon/index.tsx
  5. 1573
      every-jap-dict/components/ui/icon/index.web.tsx
  6. 10
      every-jap-dict/lib/providers/dictionaries.ts
  7. 27807
      every-jap-dict/package-lock.json
  8. 87
      every-jap-dict/package.json

@ -1,5 +1,5 @@
import { StatusBar } from 'expo-status-bar';
import { FlatList, Keyboard, Modal, Pressable, StyleSheet, View } from 'react-native';
import { FlatList, Keyboard, Modal, Pressable, ScrollView, StyleSheet, View } from 'react-native';
import { SafeAreaProvider, SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context';
import { GluestackUIProvider } from '@/components/ui/gluestack-ui-provider';
@ -10,11 +10,15 @@ import { useMemo, useState } from 'react';
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 { Button, ButtonIcon, ButtonText } from './components/ui/button';
import DictWebView from './components/DictWebView';
import AdBannerPlaceholder from './components/AdBannerPlaceholder';
import { Toast, ToastDescription, ToastTitle, useToast } from './components/ui/toast';
import mobileAds from 'react-native-google-mobile-ads';
import { Icon } from './components/ui/icon';
import { Bookmark, BookMarked, BookOpen, Search } from 'lucide-react-native';
function MainScreen() {
const [q, setQ] = useState('');
const [query, setQuery] = useState('');
@ -54,6 +58,7 @@ function MainScreen() {
add(q.trim(), pack.code);
toast.show({
id: 'onSave',
placement: 'top',
duration: 2000,
render: () => (
@ -82,29 +87,17 @@ function MainScreen() {
<View className="flex-1">
{/* 상단 검색창, 버튼 */}
<View className="p-4 gap-3">
{/* 액션 버튼 */}
{/* 검색창 */}
<HStack space="md" className="flex-row">
<Button
className="flex-1"
className="p-1"
onPress={() => setWordbookOpen(true)}
variant="outline"
action="secondary"
accessibilityLabel="단어장 보기"
>
<ButtonText> </ButtonText>
<Icon as={BookMarked} />
</Button>
<Button
className="flex-1"
onPress={onSave}
variant="outline"
action="secondary"
isDisabled={!canSearch}
>
<ButtonText> </ButtonText>
</Button>
</HStack>
{/* 검색창 */}
<HStack space="md" className="flex-row">
<Input className="flex-1">
<InputField
placeholder="검색어를 입력하세요"
@ -115,15 +108,29 @@ function MainScreen() {
onSubmitEditing={onSearch}
/>
</Input>
<Button
className="p-1"
onPress={onSave}
variant="outline"
action="secondary"
isDisabled={!canSearch}
accessibilityLabel="단어장 저장"
>
<Icon as={Bookmark} />
</Button>
<Button onPress={onSearch} isDisabled={!canSearch}>
<ButtonText></ButtonText>
</Button>
</HStack>
</View>
{/* 커스텀 탭 헤더 */}
{/* 커스텀 탭 헤더 (가로스크롤) */}
<View className="px-4 pb-2">
<HStack space="sm" className="flex-row">
<ScrollView
horizontal
showsHorizontalScrollIndicator={false}
contentContainerClassName="gap-1"
>
{providers.map((p) => {
const selected = activeId ? activeId === p.id : false;
return (
@ -138,7 +145,7 @@ function MainScreen() {
</Button>
);
})}
</HStack>
</ScrollView>
</View>
{/* 패널: WebView 모두 마운트 후 토글 */}
@ -186,7 +193,7 @@ function MainScreen() {
data={items}
keyExtractor={(x) => x.id}
renderItem={({ item }) => (
<View className="flex-row justify-between py-3 gap-4">
<View className="flex-row justify-between py-1">
<Pressable
onPress={() => onPickWord(item.text)}
style={{ flex: 1 }}
@ -208,6 +215,12 @@ function MainScreen() {
}
export default function App() {
// mobileAds()
// .initialize()
// .then(() => {
// // ready
// });
return (
<GluestackUIProvider mode="light">
<SafeAreaProvider>

@ -24,6 +24,14 @@
},
"web": {
"favicon": "./assets/favicon.png"
}
},
"plugins": [
[
"react-native-google-mobile-ads",
{
"androidAppId": "ca-app-pub-7854988771210967~3806885931"
}
]
]
}
}

@ -1,5 +1,15 @@
import { View } from 'react-native';
import { BannerAd, BannerAdSize, TestIds } from 'react-native-google-mobile-ads';
// const unitId = __DEV__ ? TestIds.BANNER : 'ca-app-pub-7854988771210967~3806885931';
export default function AdBannerPlaceholder() {
return <View className="w-full h-14" />;
return (
<View className="w-full h-14" />
// <BannerAd
// unitId={unitId}
// size={BannerAdSize.BANNER}
// requestOptions={{ requestNonPersonalizedAdsOnly: true }}
// />
);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -25,6 +25,16 @@ export const jaPack: LanguagePack = {
label: '다음',
buildUrl: (q) => `https://dic.daum.net/search.do?q=${encodeURIComponent(q)}&dic=jp`,
},
{
id: 'papago-ko-to-ja',
label: '파파고(한→일)',
buildUrl: (q) => `https://papago.naver.com/?sk=ko&tk=ja&hn=0&st=${encodeURIComponent(q)}`,
},
{
id: 'papago-ja-to-ko',
label: '파파고(일→한)',
buildUrl: (q) => `https://papago.naver.com/?sk=ja&tk=ko&st=${encodeURIComponent(q)}`,
},
{
id: 'weblio',
label: 'Weblio',

File diff suppressed because it is too large Load Diff

@ -1,42 +1,45 @@
{
"name": "every-jap-dict",
"version": "1.0.0",
"main": "index.ts",
"scripts": {
"start": "expo start --offline",
"android": "expo start --android --offline",
"ios": "expo start --ios --offline",
"web": "expo start --web --offline"
},
"dependencies": {
"@expo/html-elements": "^0.10.1",
"@gluestack-ui/core": "^3.0.0",
"@gluestack-ui/utils": "^3.0.0",
"@legendapp/motion": "^2.4.0",
"@react-native-async-storage/async-storage": "^2.2.0",
"babel-plugin-module-resolver": "^5.0.2",
"expo": "~53.0.22",
"expo-status-bar": "~2.2.3",
"install": "^0.13.0",
"nativewind": "^4.1.23",
"npm": "^11.6.0",
"react": "19.0.0",
"react-aria": "^3.33.0",
"react-dom": "^19.1.1",
"react-native": "0.79.6",
"react-native-reanimated": "^4.1.0",
"react-native-safe-area-context": "^5.6.1",
"react-native-svg": "^15.2.0",
"react-native-webview": "^13.16.0",
"react-native-worklets": "^0.5.0",
"react-stately": "^3.39.0",
"tailwind-variants": "^0.1.20",
"tailwindcss": "^3.4.17"
},
"devDependencies": {
"@babel/core": "^7.25.2",
"@types/react": "~19.0.10",
"typescript": "~5.8.3"
},
"private": true
}
{
"name": "every-jap-dict",
"version": "1.0.0",
"main": "index.ts",
"scripts": {
"start": "expo start --offline",
"android": "expo start --android --offline",
"ios": "expo start --ios --offline",
"web": "expo start --web --offline"
},
"dependencies": {
"@expo/html-elements": "^0.10.1",
"@gluestack-ui/core": "^3.0.0",
"@gluestack-ui/utils": "^3.0.0",
"@legendapp/motion": "^2.4.0",
"@react-native-async-storage/async-storage": "^2.2.0",
"babel-plugin-module-resolver": "^5.0.2",
"expo": "~53.0.22",
"expo-dev-client": "~5.2.4",
"expo-status-bar": "~2.2.3",
"install": "^0.13.0",
"lucide-react-native": "^0.543.0",
"nativewind": "^4.1.23",
"npm": "^11.6.0",
"react": "19.0.0",
"react-aria": "^3.33.0",
"react-dom": "^19.1.1",
"react-native": "0.79.6",
"react-native-google-mobile-ads": "^15.7.0",
"react-native-reanimated": "^4.1.0",
"react-native-safe-area-context": "^5.6.1",
"react-native-svg": "^15.12.0",
"react-native-webview": "^13.16.0",
"react-native-worklets": "^0.5.0",
"react-stately": "^3.39.0",
"tailwind-variants": "^0.1.20",
"tailwindcss": "^3.4.17"
},
"devDependencies": {
"@babel/core": "^7.25.2",
"@types/react": "~19.0.10",
"typescript": "~5.8.3"
},
"private": true
}

Loading…
Cancel
Save