Skip to content

Commit 9111ec1

Browse files
committed
remigrate and adjust animations
1 parent 1154fd0 commit 9111ec1

28 files changed

+551
-426
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,6 @@ expo-env.d.ts
4141
# @end expo-cli
4242

4343
scripts/data
44+
45+
# ignore ios
46+
ios/

.yarn/install-state.gz

17.1 KB
Binary file not shown.

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ This is a mobile application built with Expo and React Native that helps users p
1515
- [ ] Add more questions
1616
- [ ] Add practice test mode
1717
- [ ] Add listening questions mode
18+
- [ ] Add category filtering
19+
- [ ] Add question sets (enable importing and selection of which sets are being used to pull questions from)
1820

1921
## Installation
2022

app.json

+9-12
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"expo": {
3-
"name": "jlpt-practice-v2",
4-
"slug": "jlpt-practice-v2",
5-
"version": "1.0.0",
3+
"name": "Jellip",
4+
"slug": "jlpt-practice",
5+
"version": "1.0.1",
66
"orientation": "portrait",
77
"icon": "./assets/images/icon.png",
88
"scheme": "myapp",
@@ -12,12 +12,13 @@
1212
"resizeMode": "contain",
1313
"backgroundColor": "#ffffff"
1414
},
15-
"assetBundlePatterns": [
16-
"**/*"
17-
],
15+
"assetBundlePatterns": ["**/*"],
1816
"ios": {
1917
"supportsTablet": true,
20-
"bundleIdentifier": "dev.mmtf.jlpt-practice"
18+
"bundleIdentifier": "dev.mmtf.jlpt-practice",
19+
"infoPlist": {
20+
"LSApplicationQueriesSchemes": ["shirabelookup"]
21+
}
2122
},
2223
"android": {
2324
"adaptiveIcon": {
@@ -30,11 +31,7 @@
3031
"output": "static",
3132
"favicon": "./assets/images/favicon.png"
3233
},
33-
"plugins": [
34-
"expo-router",
35-
"expo-build-properties",
36-
"expo-font"
37-
],
34+
"plugins": ["expo-router", "expo-build-properties", "expo-font"],
3835
"experiments": {
3936
"typedRoutes": true
4037
}

app/(tabs)/index.tsx

+9-10
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
import { Linking } from "react-native";
2-
import { Paragraph, View } from "tamagui";
1+
import { Link } from "expo-router";
2+
import { Heading, Paragraph, YStack } from "tamagui";
33

44
export default function Home() {
55
return (
6-
<View>
7-
<Paragraph>Home</Paragraph>
8-
<Paragraph onPress={() => Linking.openURL("https://expo.dev")}>
9-
Learn more about Expo
6+
<YStack gap="$4" padding="$8">
7+
<Heading>Welcome</Heading>
8+
<Paragraph>
9+
Welcome to Jellip - a JLPT practice tool. Start grinding away by going
10+
to the
11+
<Link href="/question"> question tab</Link>.
1012
</Paragraph>
11-
<Paragraph onPress={() => Linking.openURL("https://reactnavigation.org")}>
12-
Learn more about React Navigation
13-
</Paragraph>
14-
</View>
13+
</YStack>
1514
);
1615
}

app/(tabs)/question.tsx

+29-118
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,13 @@
1-
import {
2-
YStack,
3-
XStack,
4-
AnimatePresence,
5-
View,
6-
ScrollView,
7-
Button,
8-
} from "tamagui";
1+
import { AnimatePresence, View } from "tamagui";
92
import { useCallback, useEffect, useState } from "react";
103
import {
114
getRandomQuestion,
125
QuestionWithAnswers,
136
submitAnswer,
14-
} from "../../services/questions";
7+
} from "@/services/questions";
158
import { useToastController } from "@tamagui/toast";
169
import * as zod from "zod";
17-
import { AnswerButton } from "../../components/AnswerButton";
18-
import { QuestionContent } from "../../components/QuestionContent";
19-
import {
20-
BookOpen,
21-
JapaneseYen,
22-
Search,
23-
SearchCheck,
24-
SearchCode,
25-
SearchX,
26-
} from "@tamagui/lucide-icons";
27-
import { Linking } from "react-native";
28-
import * as WebBrowser from "expo-web-browser";
29-
import { SearchBar } from "react-native-screens";
10+
import { QuestionView } from "@/components/QuestionView";
3011

3112
const questionSchema = zod.object({
3213
id: zod.number(),
@@ -37,12 +18,10 @@ const questionSchema = zod.object({
3718
correctAnswer: zod.number().lte(3).gte(0),
3819
});
3920

40-
export default function TabOneScreen() {
21+
function QuestionManager() {
4122
const [answer, setAnswer] = useState<null | number>(null);
42-
4323
const [question, setQuestion] = useState<QuestionWithAnswers | null>(null);
4424
const [loading, setLoading] = useState(false);
45-
4625
const toast = useToastController();
4726

4827
const fetchQuestion = useCallback(
@@ -72,10 +51,12 @@ export default function TabOneScreen() {
7251
setLoading(false);
7352
}
7453
},
75-
[setQuestion]
54+
[setQuestion],
7655
);
7756

7857
useEffect(() => {
58+
if (question) return;
59+
setAnswer(null);
7960
fetchQuestion();
8061
}, []);
8162

@@ -91,100 +72,30 @@ export default function TabOneScreen() {
9172
setAnswer(answerId);
9273
};
9374

94-
const [layout, setLayout] = useState({
95-
questionY: 0,
96-
containerY: 0,
97-
paragraphHeight: 0,
98-
});
99-
10075
return (
101-
<YStack
102-
onLayout={(e) => {
103-
const y = e.nativeEvent.layout.y;
104-
setLayout((l) => ({ ...l, containerY: y }));
105-
}}
106-
height="100%"
107-
paddingHorizontal="$8"
108-
alignItems="center"
109-
justifyContent="flex-end"
110-
gap="$4"
111-
>
112-
<AnimatePresence>
113-
<View
114-
overflow="visible"
115-
width="100%"
116-
animation="fast"
117-
key={question?.question.toString()}
118-
exitStyle={{ transform: [{ translateX: 200 }], opacity: 0 }}
119-
enterStyle={{ transform: [{ translateX: -200 }], opacity: 0 }}
120-
onLayout={(e) => {
121-
const y = e.nativeEvent.layout.y;
122-
setLayout((l) => ({ ...l, questionY: y }));
123-
}}
124-
transform={[{ translateX: 0 }]}
125-
>
126-
<ScrollView
127-
bottom={0}
128-
left={0}
129-
right={0}
130-
position="absolute"
131-
width="100%"
132-
onContentSizeChange={(_, h) => {
133-
setLayout((l) => ({ ...l, paragraphHeight: h }));
134-
}}
135-
contentContainerStyle={{ flexGrow: 1 }}
136-
height={layout.questionY - layout.containerY}
137-
scrollEnabled={layout.paragraphHeight > layout.questionY}
138-
>
139-
<QuestionContent question={question} />
140-
</ScrollView>
141-
</View>
142-
</AnimatePresence>
143-
<XStack gap="$2" flexWrap="wrap">
144-
{question?.answers.map((answerText, idx) => (
145-
<AnswerButton
146-
key={idx}
147-
answerText={answerText}
148-
isCorrect={idx === question!.correctAnswer}
149-
selected={answer === null ? answer : idx === answer}
150-
onPress={() => handleAnswer(idx)}
151-
/>
152-
))}
153-
</XStack>
154-
<XStack
155-
justifyContent="space-between"
156-
width="100%"
157-
marginTop="$-2"
158-
gap="$2"
159-
pointerEvents={answer !== null ? "auto" : "none"}
160-
opacity={answer !== null ? 1 : 0}
161-
animation="medium"
162-
theme="alt2"
76+
<AnimatePresence>
77+
<View
78+
position="absolute"
79+
top={0}
80+
left={0}
81+
right={0}
82+
bottom={0}
83+
animation="fast"
84+
key={question?.question.toString()}
85+
exitStyle={{ transform: [{ translateX: 200 }], opacity: 0 }}
86+
enterStyle={{ transform: [{ translateX: -200 }], opacity: 0 }}
87+
transform={[{ translateX: 0 }]}
16388
>
164-
<Button
165-
circular
166-
icon={BookOpen}
167-
onPress={() => {
168-
WebBrowser.openBrowserAsync(
169-
`https://jisho.org/search/${encodeURIComponent(
170-
(question?.question || "") + (question?.answers.join(" ") || "")
171-
)}`
172-
);
173-
}}
174-
/>
175-
<Button
176-
circular
177-
icon={Search}
178-
onPress={() => {
179-
WebBrowser.openBrowserAsync(
180-
`https://www.google.com/search?q=${encodeURIComponent(
181-
(question?.answers[question.correctAnswer] || "") + " 文法"
182-
)}`
183-
);
184-
}}
89+
<QuestionView
90+
question={question}
91+
answer={answer}
92+
handleAnswer={handleAnswer}
18593
/>
186-
</XStack>
187-
<View marginBottom="40%" />
188-
</YStack>
94+
</View>
95+
</AnimatePresence>
18996
);
19097
}
98+
99+
export default function TabOneScreen() {
100+
return <QuestionManager />;
101+
}

assets/images/icon.png

448 KB
Loading

components/AnswerButton.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { useState } from "react";
12
import { Button, Theme, ThemeName } from "tamagui";
23

34
export const AnswerButton = ({
@@ -23,9 +24,9 @@ export const AnswerButton = ({
2324
return (
2425
<Theme name="blue">
2526
<Button
26-
animation={{ theme: "fast" }}
27+
animation="superfastTransform"
2728
minWidth="40%"
28-
pressStyle={{ scale: 0.95 }}
29+
pressStyle={{ scale: 0.9 }}
2930
flex={1}
3031
theme={theme}
3132
size={"$5"}

components/MigrationProvider.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useMigrations } from "drizzle-orm/expo-sqlite/migrator";
1+
import { migrate, useMigrations } from "drizzle-orm/expo-sqlite/migrator";
22
import migrations from "../drizzle/migrations";
33
import { View, Text } from "react-native";
44
import React from "react";

components/QuestionView.1.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

0 commit comments

Comments
 (0)