Skip to content

Commit bd46e69

Browse files
sumi-0011sumi-exem
andauthored
웹뷰 앱 추가 (git-goods#334)
Co-authored-by: sumi-exem <sumi@ex-em.com>
1 parent 4a5e727 commit bd46e69

47 files changed

Lines changed: 25914 additions & 926 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/app/.gitignore

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files
2+
3+
# dependencies
4+
node_modules/
5+
6+
# Expo
7+
.expo/
8+
dist/
9+
web-build/
10+
expo-env.d.ts
11+
12+
# Native
13+
.kotlin/
14+
*.orig.*
15+
*.jks
16+
*.p8
17+
*.p12
18+
*.key
19+
*.mobileprovision
20+
21+
# Metro
22+
.metro-health-check*
23+
24+
# debug
25+
npm-debug.*
26+
yarn-debug.*
27+
yarn-error.*
28+
29+
# macOS
30+
.DS_Store
31+
*.pem
32+
33+
# local env files
34+
.env*.local
35+
36+
# typescript
37+
*.tsbuildinfo
38+
39+
app-example

apps/app/.vscode/settings.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"editor.codeActionsOnSave": {
3+
"source.fixAll": "explicit",
4+
"source.organizeImports": "explicit",
5+
"source.sortMembers": "explicit"
6+
}
7+
}

apps/app/README.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Welcome to your Expo app 👋
2+
3+
This is an [Expo](https://expo.dev) project created with [`create-expo-app`](https://www.npmjs.com/package/create-expo-app).
4+
5+
## Get started
6+
7+
1. Install dependencies
8+
9+
```bash
10+
npm install
11+
```
12+
13+
2. Start the app
14+
15+
```bash
16+
npx expo start
17+
```
18+
19+
In the output, you'll find options to open the app in a
20+
21+
- [development build](https://docs.expo.dev/develop/development-builds/introduction/)
22+
- [Android emulator](https://docs.expo.dev/workflow/android-studio-emulator/)
23+
- [iOS simulator](https://docs.expo.dev/workflow/ios-simulator/)
24+
- [Expo Go](https://expo.dev/go), a limited sandbox for trying out app development with Expo
25+
26+
You can start developing by editing the files inside the **app** directory. This project uses [file-based routing](https://docs.expo.dev/router/introduction).
27+
28+
## Get a fresh project
29+
30+
When you're ready, run:
31+
32+
```bash
33+
npm run reset-project
34+
```
35+
36+
This command will move the starter code to the **app-example** directory and create a blank **app** directory where you can start developing.
37+
38+
## Learn more
39+
40+
To learn more about developing your project with Expo, look at the following resources:
41+
42+
- [Expo documentation](https://docs.expo.dev/): Learn fundamentals, or go into advanced topics with our [guides](https://docs.expo.dev/guides).
43+
- [Learn Expo tutorial](https://docs.expo.dev/tutorial/introduction/): Follow a step-by-step tutorial where you'll create a project that runs on Android, iOS, and the web.
44+
45+
## Join the community
46+
47+
Join our community of developers creating universal apps.
48+
49+
- [Expo on GitHub](https://github.com/expo/expo): View our open source platform and contribute.
50+
- [Discord community](https://chat.expo.dev): Chat with Expo users and ask questions.

apps/app/app.json

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
{
2+
"expo": {
3+
"name": "my-app",
4+
"slug": "my-app",
5+
"version": "1.0.0",
6+
"orientation": "portrait",
7+
"icon": "./assets/images/icon.png",
8+
"scheme": "gitanimals",
9+
"userInterfaceStyle": "automatic",
10+
"newArchEnabled": true,
11+
"ios": {
12+
"bundleIdentifier": "org.gitanimals.app",
13+
"supportsTablet": true,
14+
"usesAppleSignIn": true
15+
},
16+
"android": {
17+
"package": "org.gitanimals.app",
18+
"adaptiveIcon": {
19+
"foregroundImage": "./assets/adaptive-icon.png",
20+
"backgroundColor": "#ffffff"
21+
}
22+
},
23+
"web": {
24+
"bundler": "metro",
25+
"output": "static",
26+
"favicon": "./assets/images/favicon.png"
27+
},
28+
"plugins": [
29+
"expo-router",
30+
[
31+
"expo-splash-screen",
32+
{
33+
"image": "./assets/images/splash-icon.png",
34+
"imageWidth": 200,
35+
"resizeMode": "contain",
36+
"backgroundColor": "#ffffff"
37+
}
38+
],
39+
"expo-secure-store",
40+
"expo-apple-authentication"
41+
],
42+
"experiments": {
43+
"typedRoutes": true
44+
}
45+
}
46+
}

apps/app/app/(tabs)/_layout.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Stack } from 'expo-router';
2+
import React from 'react';
3+
4+
export default function Layout() {
5+
return (
6+
<Stack
7+
screenOptions={{
8+
headerShown: false,
9+
}}
10+
>
11+
<Stack.Screen
12+
name="index"
13+
options={{
14+
title: 'GitAnimals',
15+
}}
16+
/>
17+
</Stack>
18+
);
19+
}

apps/app/app/(tabs)/index.tsx

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import { useEffect, useRef } from 'react';
2+
import { View, Text, StyleSheet, TouchableOpacity, SafeAreaView, Platform, StatusBar } from 'react-native';
3+
import { router, useRouter } from 'expo-router';
4+
import CustomWebView from '../../components/CustomWebView';
5+
import { useAuth } from '../../hooks/useAuth';
6+
import { IconSymbol } from '@/components/ui/IconSymbol';
7+
8+
export default function TabOneScreen() {
9+
const { isAuthenticated, logout, token } = useAuth();
10+
const router = useRouter();
11+
const isFirstRender = useRef(true);
12+
13+
useEffect(() => {
14+
// 첫 렌더링에서는 리다이렉트 스킵
15+
if (isFirstRender.current) {
16+
isFirstRender.current = false;
17+
return;
18+
}
19+
20+
// 이후 렌더링에서만 리다이렉트 수행
21+
if (!isAuthenticated) {
22+
router.replace('/auth/login');
23+
}
24+
}, [isAuthenticated]);
25+
26+
const onPressLogout = async () => {
27+
try {
28+
await logout();
29+
router.replace('/auth/login');
30+
} catch (error) {
31+
console.error('로그아웃 실패:', error);
32+
}
33+
};
34+
35+
if (!isAuthenticated) {
36+
return null;
37+
}
38+
39+
return (
40+
<View style={styles.container}>
41+
<StatusBar barStyle="dark-content" backgroundColor="#f8f9fa" />
42+
<View style={styles.webViewContainer}>
43+
<CustomWebView url="https://www.gitanimals.org/" token={token} />
44+
</View>
45+
</View>
46+
);
47+
}
48+
49+
const styles = StyleSheet.create({
50+
container: {
51+
flex: 1,
52+
backgroundColor: '#fff',
53+
},
54+
safeArea: {
55+
backgroundColor: '#f8f9fa',
56+
},
57+
header: {
58+
backgroundColor: '#f8f9fa',
59+
borderBottomWidth: 1,
60+
borderBottomColor: '#e9ecef',
61+
...Platform.select({
62+
ios: {
63+
shadowColor: '#000',
64+
shadowOffset: { width: 0, height: 1 },
65+
shadowOpacity: 0.1,
66+
shadowRadius: 3,
67+
},
68+
android: {
69+
elevation: 3,
70+
},
71+
}),
72+
},
73+
headerContent: {
74+
flexDirection: 'row',
75+
justifyContent: 'space-between',
76+
alignItems: 'center',
77+
paddingHorizontal: 16,
78+
paddingVertical: 12,
79+
},
80+
titleContainer: {
81+
flexDirection: 'row',
82+
alignItems: 'center',
83+
},
84+
welcomeText: {
85+
fontSize: 18,
86+
fontWeight: '600',
87+
color: '#24292e',
88+
marginLeft: 8,
89+
},
90+
logoutButton: {
91+
backgroundColor: '#dc3545',
92+
paddingVertical: 8,
93+
paddingHorizontal: 16,
94+
borderRadius: 8,
95+
},
96+
buttonText: {
97+
color: '#fff',
98+
fontSize: 14,
99+
fontWeight: '500',
100+
},
101+
webViewContainer: {
102+
flex: 1,
103+
},
104+
});

apps/app/app/+not-found.tsx

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import React from 'react';
2+
import { Link, Stack } from 'expo-router';
3+
import { StyleSheet } from 'react-native';
4+
5+
import { ThemedText } from '@/components/ThemedText';
6+
import { ThemedView } from '@/components/ThemedView';
7+
8+
export default function NotFoundScreen() {
9+
return (
10+
<>
11+
<Stack.Screen options={{ title: 'Oops!' }} />
12+
<ThemedView style={styles.container}>
13+
<ThemedText type="title">This screen doesn't exist.</ThemedText>
14+
<Link href="/" style={styles.link}>
15+
<ThemedText type="link">Go to home screen!</ThemedText>
16+
</Link>
17+
</ThemedView>
18+
</>
19+
);
20+
}
21+
22+
const styles = StyleSheet.create({
23+
container: {
24+
flex: 1,
25+
alignItems: 'center',
26+
justifyContent: 'center',
27+
padding: 20,
28+
},
29+
link: {
30+
marginTop: 15,
31+
paddingVertical: 15,
32+
},
33+
});

apps/app/app/_layout.tsx

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';
2+
import { useFonts } from 'expo-font';
3+
import { Stack } from 'expo-router';
4+
import * as SplashScreen from 'expo-splash-screen';
5+
import { StatusBar } from 'expo-status-bar';
6+
import React, { useEffect } from 'react';
7+
import 'react-native-reanimated';
8+
import DebugPath from '../components/DebugPath';
9+
import { SafeAreaView, View } from 'react-native';
10+
11+
import { useColorScheme } from '@/hooks/useColorScheme';
12+
import { useAuth } from '../hooks/useAuth'; // 인증 상태 관리 훅
13+
14+
// Prevent the splash screen from auto-hiding before asset loading is complete.
15+
SplashScreen.preventAutoHideAsync();
16+
17+
export default function RootLayout() {
18+
const colorScheme = useColorScheme();
19+
const [loaded] = useFonts({
20+
SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'),
21+
});
22+
23+
const { isAuthenticated, isLoading } = useAuth();
24+
25+
useEffect(() => {
26+
if (loaded) {
27+
SplashScreen.hideAsync();
28+
}
29+
}, [loaded]);
30+
31+
if (!loaded) {
32+
return null;
33+
}
34+
35+
if (isLoading) {
36+
return null; // 또는 로딩 화면
37+
}
38+
39+
return (
40+
<View style={{ flex: 1 }}>
41+
<SafeAreaView>
42+
<DebugPath />
43+
</SafeAreaView>
44+
<ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
45+
<Stack
46+
initialRouteName={isAuthenticated ? '(tabs)' : 'auth/login'}
47+
screenOptions={{
48+
headerShown: false,
49+
}}
50+
>
51+
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
52+
<Stack.Screen
53+
name="auth/login"
54+
options={{
55+
headerShown: false,
56+
presentation: 'modal',
57+
}}
58+
/>
59+
<Stack.Screen name="auth/success" options={{ title: '로그인 완료' }} />
60+
61+
{/* test/auth-web?token= */}
62+
<Stack.Screen name="test/auth-web" options={{ title: '로그인 완료' }} />
63+
</Stack>
64+
<StatusBar style="auto" />
65+
</ThemeProvider>
66+
</View>
67+
);
68+
}

0 commit comments

Comments
 (0)