From 96ca6c0a5f15fd6c31dc71f7e972d76f47e115e2 Mon Sep 17 00:00:00 2001 From: Kuesung Park Date: Fri, 27 Oct 2023 23:17:09 +0900 Subject: [PATCH 01/36] =?UTF-8?q?feat=20:=20=EB=84=A4=EB=B9=84=EA=B2=8C?= =?UTF-8?q?=EC=9D=B4=EC=85=98=20=EB=AA=A8=EB=93=88=20=EC=84=A4=EC=B9=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit react-navigation/native --- package-lock.json | 144 +++++++++++++++++++++++++++++++++++++++++++++- package.json | 19 +++--- 2 files changed, 152 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index c077adb..c1fa9b4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "@react-native-firebase/app": "^18.5.0", "@react-native-firebase/messaging": "^18.5.0", "@react-native-masked-view/masked-view": "^0.2.9", + "@react-navigation/native": "^6.1.9", "react": "18.2.0", "react-native": "0.72.3", "react-native-animated-pagination-dots": "^0.1.73", @@ -4519,6 +4520,72 @@ "react-native": "*" } }, + "node_modules/@react-navigation/core": { + "version": "6.4.10", + "resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-6.4.10.tgz", + "integrity": "sha512-oYhqxETRHNHKsipm/BtGL0LI43Hs2VSFoWMbBdHK9OqgQPjTVUitslgLcPpo4zApCcmBWoOLX2qPxhsBda644A==", + "dependencies": { + "@react-navigation/routers": "^6.1.9", + "escape-string-regexp": "^4.0.0", + "nanoid": "^3.1.23", + "query-string": "^7.1.3", + "react-is": "^16.13.0", + "use-latest-callback": "^0.1.7" + }, + "peerDependencies": { + "react": "*" + } + }, + "node_modules/@react-navigation/core/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-navigation/core/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/@react-navigation/native": { + "version": "6.1.9", + "resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-6.1.9.tgz", + "integrity": "sha512-AMuJDpwXE7UlfyhIXaUCCynXmv69Kb8NzKgKJO7v0k0L+u6xUTbt6xvshmJ79vsvaFyaEH9Jg5FMzek5/S5qNw==", + "dependencies": { + "@react-navigation/core": "^6.4.10", + "escape-string-regexp": "^4.0.0", + "fast-deep-equal": "^3.1.3", + "nanoid": "^3.1.23" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/@react-navigation/native/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-navigation/routers": { + "version": "6.1.9", + "resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-6.1.9.tgz", + "integrity": "sha512-lTM8gSFHSfkJvQkxacGM6VJtBt61ip2XO54aNfswD+KMw6eeZ4oehl7m0me3CR9hnDE4+60iAZR8sAhvCiI3NA==", + "dependencies": { + "nanoid": "^3.1.23" + } + }, "node_modules/@sideway/address": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", @@ -6645,6 +6712,14 @@ "node": ">=0.10.0" } }, + "node_modules/decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "engines": { + "node": ">=0.10" + } + }, "node_modules/dedent": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", @@ -7686,8 +7761,7 @@ "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-diff": { "version": "1.3.0", @@ -7796,6 +7870,14 @@ "node": ">=8" } }, + "node_modules/filter-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", + "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/finalhandler": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", @@ -12122,6 +12204,23 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -12827,6 +12926,23 @@ } ] }, + "node_modules/query-string": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz", + "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==", + "dependencies": { + "decode-uri-component": "^0.2.2", + "filter-obj": "^1.1.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/queue": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", @@ -13890,6 +14006,14 @@ "source-map": "^0.6.0" } }, + "node_modules/split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", + "engines": { + "node": ">=6" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -13946,6 +14070,14 @@ "node": ">= 0.6" } }, + "node_modules/strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", + "engines": { + "node": ">=4" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -14660,6 +14792,14 @@ "punycode": "^2.1.0" } }, + "node_modules/use-latest-callback": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/use-latest-callback/-/use-latest-callback-0.1.7.tgz", + "integrity": "sha512-Hlrl0lskgZZpo2vIpZ4rA7qA/rAGn2PcDvDH1M47AogqMPB0qlGEdsa66AVkIUiEEDpfxA9/N6hY6MqtaNoqWA==", + "peerDependencies": { + "react": ">=16.8" + } + }, "node_modules/use-sync-external-store": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", diff --git a/package.json b/package.json index 6d7a4ec..5e3ade3 100644 --- a/package.json +++ b/package.json @@ -12,14 +12,21 @@ "lint:fix": "eslint '**/*.{js,jsx,ts,tsx}' --fix" }, "dependencies": { + "@notifee/react-native": "^7.8.0", "@react-native-async-storage/async-storage": "^1.19.3", + "@react-native-community/push-notification-ios": "^1.11.0", + "@react-native-firebase/analytics": "^18.5.0", + "@react-native-firebase/app": "^18.5.0", + "@react-native-firebase/messaging": "^18.5.0", "@react-native-masked-view/masked-view": "^0.2.9", + "@react-navigation/native": "^6.1.9", "react": "18.2.0", "react-native": "0.72.3", "react-native-animated-pagination-dots": "^0.1.73", "react-native-gesture-handler": "^2.12.1", "react-native-localize": "^3.0.2", "react-native-permissions": "^3.8.4", + "react-native-push-notification": "^8.1.1", "react-native-reanimated": "^3.4.1", "react-native-safe-area-context": "^4.7.1", "react-native-screens": "^3.23.0", @@ -27,12 +34,6 @@ "react-native-svg": "^13.13.0", "react-native-svg-transformer": "^1.1.0", "react-native-swiper-flatlist": "^3.2.3", - "@react-native-community/push-notification-ios": "^1.11.0", - "@react-native-firebase/analytics": "^18.5.0", - "@react-native-firebase/app": "^18.5.0", - "@react-native-firebase/messaging": "^18.5.0", - "@notifee/react-native": "^7.8.0", - "react-native-push-notification": "^8.1.1", "react-native-webview": "^13.6.2" }, "devDependencies": { @@ -43,16 +44,16 @@ "@react-native/metro-config": "^0.72.9", "@tsconfig/react-native": "^3.0.0", "@types/react": "^18.0.24", + "@types/react-native-push-notification": "^8.1.2", "@types/react-test-renderer": "^18.0.0", "babel-jest": "^29.2.1", "eslint": "^8.19.0", + "i": "^0.3.7", "jest": "^29.2.1", "metro-react-native-babel-preset": "0.76.7", "prettier": "^2.4.1", "react-test-renderer": "18.2.0", - "typescript": "4.8.4", - "@types/react-native-push-notification": "^8.1.2", - "i": "^0.3.7" + "typescript": "4.8.4" }, "engines": { "node": ">=16" From 4879075075faa9031f847c472a420da8b55bec3c Mon Sep 17 00:00:00 2001 From: Kuesung Park Date: Fri, 27 Oct 2023 23:17:25 +0900 Subject: [PATCH 02/36] =?UTF-8?q?feat=20:=20=EC=9B=B9=EB=B7=B0=20>=20?= =?UTF-8?q?=EC=95=B1=20=ED=86=B5=EC=8B=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App.js | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/App.js b/App.js index 02d5cdb..d0f1bc6 100644 --- a/App.js +++ b/App.js @@ -32,6 +32,8 @@ import Text2SVG from './image/text2.svg'; import Text2enSVG from './image/text2en.svg'; import messaging from '@react-native-firebase/messaging'; +import {StackActions} from '@react-navigation/native'; + // Firebase 알림 async function requestUserPermission() { const authStatus = await messaging().requestPermission(); @@ -52,7 +54,7 @@ const imageDataList = [ {no: 3, uri: require('./image/start.png')}, ]; -const SOURCE_URL = 'https://gloddy.vercel.app'; +const SOURCE_URL = 'http://localhost:3000'; export default function App() { const webViewRef = useRef(); @@ -166,13 +168,6 @@ export default function App() { } }, []); - const onMessageReceived = async event => { - if (event.nativeEvent.data === 'signout') { - await AsyncStorage.removeItem('token'); - setwebloading(true); - } - }; - const handlestart = async () => { await AsyncStorage.setItem('token', 'ok'); setwebloading(false); @@ -186,6 +181,20 @@ export default function App() { } }; + const requestOnMessage = async event => { + const nativeEvent = JSON.parse(event.nativeEvent.data); + if (nativeEvent === 'signout') { + await AsyncStorage.removeItem('token'); + setwebloading(true); + } + + if (nativeEvent.type === 'ROUTER_EVENT') { + const {path} = nativeEvent.data; + Alert.alert(path); + return; + } + }; + return ( sendweb()} - onMessage={onMessageReceived} + onMessage={requestOnMessage} // 웹뷰 로딩이 시작되거나 끝나면 호출하는 함수 navState로 url 감지 onNavigationStateChange={onNavigationStateChange} // 처음 호출한 URL에서 다시 Redirect하는 경우에, 사용하면 navState url 감지 From 8a2cff06a5326a8286bb43ad4b5be25e20ecc33e Mon Sep 17 00:00:00 2001 From: Kuesung Park Date: Fri, 27 Oct 2023 23:27:23 +0900 Subject: [PATCH 03/36] =?UTF-8?q?refactor=20:=20WebViewContainer=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .eslintrc.js | 3 ++ App.js | 65 ++--------------------------- components/WebViewContainer.jsx | 72 +++++++++++++++++++++++++++++++++ constants/index.js | 1 + 4 files changed, 79 insertions(+), 62 deletions(-) create mode 100644 components/WebViewContainer.jsx create mode 100644 constants/index.js diff --git a/.eslintrc.js b/.eslintrc.js index 187894b..84ce69b 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,4 +1,7 @@ module.exports = { root: true, extends: '@react-native', + rules: { + 'react/react-in-jsx-scope': 'off', + }, }; diff --git a/App.js b/App.js index d0f1bc6..bb5c337 100644 --- a/App.js +++ b/App.js @@ -33,6 +33,8 @@ import Text2enSVG from './image/text2en.svg'; import messaging from '@react-native-firebase/messaging'; import {StackActions} from '@react-navigation/native'; +import {SOURCE_URL} from './constants'; +import WebViewContainer from './components/WebViewContainer'; // Firebase 알림 async function requestUserPermission() { @@ -54,8 +56,6 @@ const imageDataList = [ {no: 3, uri: require('./image/start.png')}, ]; -const SOURCE_URL = 'http://localhost:3000'; - export default function App() { const webViewRef = useRef(); const [lang, setlang] = useState(null); @@ -79,28 +79,6 @@ export default function App() { AppRegistry.registerComponent('app', () => App); - const onShouldStartLoadWithRequest = event => { - if (!event.url.includes(SOURCE_URL)) { - Linking.openURL(event.url); - return false; - } - return true; - }; - - const sendweb = () => { - try { - const lang = RNLocalize.getLocales()[0].languageCode; - const payload = { - type: 'RNLocalize', - Platform: Platform.OS, - data: lang, - }; - webViewRef.current.postMessage(JSON.stringify(payload)); - } catch (error) { - console.log(error); - } - }; - // 뒤로 가기 control const [exit, setexit] = useState(false); const [swexit, setswexit] = useState(0); @@ -173,28 +151,6 @@ export default function App() { setwebloading(false); }; - const onNavigationStateChange = navState => { - webViewRef.canGoBack = navState.canGoBack; - if (!navState.url.includes(SOURCE_URL)) { - Linking.openURL(navState.url); - return false; - } - }; - - const requestOnMessage = async event => { - const nativeEvent = JSON.parse(event.nativeEvent.data); - if (nativeEvent === 'signout') { - await AsyncStorage.removeItem('token'); - setwebloading(true); - } - - if (nativeEvent.type === 'ROUTER_EVENT') { - const {path} = nativeEvent.data; - Alert.alert(path); - return; - } - }; - return ( ) : ( - sendweb()} - onMessage={requestOnMessage} - // 웹뷰 로딩이 시작되거나 끝나면 호출하는 함수 navState로 url 감지 - onNavigationStateChange={onNavigationStateChange} - // 처음 호출한 URL에서 다시 Redirect하는 경우에, 사용하면 navState url 감지 - onShouldStartLoadWithRequest={onShouldStartLoadWithRequest} - /> + )} diff --git a/components/WebViewContainer.jsx b/components/WebViewContainer.jsx new file mode 100644 index 0000000..03d0d7e --- /dev/null +++ b/components/WebViewContainer.jsx @@ -0,0 +1,72 @@ +import {useRef} from 'react'; +import WebView from 'react-native-webview'; +import {SOURCE_URL} from '../constants'; +import {Alert, Linking, Platform} from 'react-native'; +import * as RNLocalize from 'react-native-localize'; +import AsyncStorage from '@react-native-async-storage/async-storage'; + +export default function WebViewContainer() { + const webViewRef = useRef(); + + const sendweb = () => { + try { + const lang = RNLocalize.getLocales()[0].languageCode; + const payload = { + type: 'RNLocalize', + Platform: Platform.OS, + data: lang, + }; + webViewRef.current.postMessage(JSON.stringify(payload)); + } catch (error) { + console.log(error); + } + }; + + const onNavigationStateChange = navState => { + webViewRef.canGoBack = navState.canGoBack; + if (!navState.url.includes(SOURCE_URL)) { + Linking.openURL(navState.url); + return false; + } + }; + + const requestOnMessage = async event => { + const nativeEvent = JSON.parse(event.nativeEvent.data); + if (nativeEvent === 'signout') { + await AsyncStorage.removeItem('token'); + } + + if (nativeEvent.type === 'ROUTER_EVENT') { + const {path} = nativeEvent.data; + Alert.alert(path); + return; + } + }; + + const onShouldStartLoadWithRequest = event => { + if (!event.url.includes(SOURCE_URL)) { + Linking.openURL(event.url); + return false; + } + return true; + }; + + return ( + <> + sendweb()} + onMessage={requestOnMessage} // 웹뷰 -> 앱으로 통신 + onNavigationStateChange={onNavigationStateChange} // 웹뷰 로딩이 시작되거나 끝나면 호출하는 함수 navState로 url 감지 + onShouldStartLoadWithRequest={onShouldStartLoadWithRequest} // 처음 호출한 URL에서 다시 Redirect하는 경우에, 사용하면 navState url 감지 + /> + + ); +} diff --git a/constants/index.js b/constants/index.js new file mode 100644 index 0000000..504aab5 --- /dev/null +++ b/constants/index.js @@ -0,0 +1 @@ +export const SOURCE_URL = 'https://gloddy.vercel.app'; From 2eaaec90f5b3af7eca8f49fadd46fa00df9293a5 Mon Sep 17 00:00:00 2001 From: Kuesung Park Date: Sat, 28 Oct 2023 09:16:42 +0900 Subject: [PATCH 04/36] =?UTF-8?q?feat=20:=20NavigationItem=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 3 +- App.js | 8 ++-- components/WebViewContainer.jsx | 83 +++++++++++++++++++++++++++++++-- package-lock.json | 80 +++++++++++++++++++++++++++++++ package.json | 1 + 5 files changed, 165 insertions(+), 10 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 4f81299..99312c2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,4 @@ { - "java.configuration.updateBuildConfiguration": "automatic" + "java.configuration.updateBuildConfiguration": "automatic", + "java.compile.nullAnalysis.mode": "automatic" } diff --git a/App.js b/App.js index bb5c337..b54068a 100644 --- a/App.js +++ b/App.js @@ -87,6 +87,7 @@ export default function App() { setswexit(swexit => swexit + 1); return true; }; + useEffect(() => { let timer; if (exit === false) { @@ -100,9 +101,9 @@ export default function App() { BackHandler.exitApp(); } }, [swexit]); + useEffect(() => { BackHandler.addEventListener('hardwareBackPress', backAction); - return () => BackHandler.removeEventListener('hardwareBackPress', backAction); }, []); @@ -115,6 +116,7 @@ export default function App() { setwebloading(false); } }; + useEffect(() => { preloading(); setTimeout(() => { @@ -272,9 +274,7 @@ export default function App() { )} ) : ( - - - + )} + + + + + ); +} + +function WebviewItem({navigation, route}) { const webViewRef = useRef(); const sendweb = () => { @@ -38,7 +86,16 @@ export default function WebViewContainer() { if (nativeEvent.type === 'ROUTER_EVENT') { const {path} = nativeEvent.data; - Alert.alert(path); + if (path === 'back') { + const popAction = StackActions.pop(1); + navigation.dispatch(popAction); + } else { + const pushAction = StackActions.push('Details', { + url: 'http://localhost:3000/ko/grouping/create?step=main', + isStack: true, + }); + navigation.dispatch(pushAction); + } return; } }; @@ -52,9 +109,9 @@ export default function WebViewContainer() { }; return ( - <> + - + ); } + +const windowWidth = Dimensions.get('window').width; +const windowHeight = Dimensions.get('window').height; + +const styles = StyleSheet.create({ + container: { + flex: 1, + alignItems: 'center', + justifyContent: 'space-between', + }, + webview: { + flex: 1, + width: windowWidth, + height: windowHeight, + }, +}); diff --git a/package-lock.json b/package-lock.json index c1fa9b4..5fffa92 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "@react-native-firebase/messaging": "^18.5.0", "@react-native-masked-view/masked-view": "^0.2.9", "@react-navigation/native": "^6.1.9", + "@react-navigation/stack": "^6.3.20", "react": "18.2.0", "react-native": "0.72.3", "react-native-animated-pagination-dots": "^0.1.73", @@ -4552,6 +4553,17 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/@react-navigation/elements": { + "version": "1.3.21", + "resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.3.21.tgz", + "integrity": "sha512-eyS2C6McNR8ihUoYfc166O1D8VYVh9KIl0UQPI8/ZJVsStlfSTgeEEh+WXge6+7SFPnZ4ewzEJdSAHH+jzcEfg==", + "peerDependencies": { + "@react-navigation/native": "^6.0.0", + "react": "*", + "react-native": "*", + "react-native-safe-area-context": ">= 3.0.0" + } + }, "node_modules/@react-navigation/native": { "version": "6.1.9", "resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-6.1.9.tgz", @@ -4586,6 +4598,24 @@ "nanoid": "^3.1.23" } }, + "node_modules/@react-navigation/stack": { + "version": "6.3.20", + "resolved": "https://registry.npmjs.org/@react-navigation/stack/-/stack-6.3.20.tgz", + "integrity": "sha512-vE6mgZzOgoa5Uy7ayT97Cj+ZIK7DK+JBYVuKUViILlWZy6IWK7HFDuqoChSbZ1ajTIfAxj/acVGg1jkbAKsToA==", + "dependencies": { + "@react-navigation/elements": "^1.3.21", + "color": "^4.2.3", + "warn-once": "^0.1.0" + }, + "peerDependencies": { + "@react-navigation/native": "^6.0.0", + "react": "*", + "react-native": "*", + "react-native-gesture-handler": ">= 1.0.0", + "react-native-safe-area-context": ">= 3.0.0", + "react-native-screens": ">= 3.0.0" + } + }, "node_modules/@sideway/address": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", @@ -6328,6 +6358,18 @@ "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", "dev": true }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -6341,6 +6383,31 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/color/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, "node_modules/colorette": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", @@ -13945,6 +14012,19 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", diff --git a/package.json b/package.json index 5e3ade3..f9a85f2 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "@react-native-firebase/messaging": "^18.5.0", "@react-native-masked-view/masked-view": "^0.2.9", "@react-navigation/native": "^6.1.9", + "@react-navigation/stack": "^6.3.20", "react": "18.2.0", "react-native": "0.72.3", "react-native-animated-pagination-dots": "^0.1.73", From bd121e5873b8328892e1a632b4cb0a0ccae3be24 Mon Sep 17 00:00:00 2001 From: Kuesung Park Date: Sat, 28 Oct 2023 09:49:57 +0900 Subject: [PATCH 05/36] feat : StatusBar --- components/WebViewContainer.jsx | 34 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/components/WebViewContainer.jsx b/components/WebViewContainer.jsx index 0aa6930..593bc0b 100644 --- a/components/WebViewContainer.jsx +++ b/components/WebViewContainer.jsx @@ -1,4 +1,4 @@ -import {useRef} from 'react'; +import {useRef, useState} from 'react'; import WebView from 'react-native-webview'; import {SOURCE_URL} from '../constants'; import { @@ -7,7 +7,9 @@ import { Linking, Platform, SafeAreaView, + StatusBar, StyleSheet, + Text, View, } from 'react-native'; import * as RNLocalize from 'react-native-localize'; @@ -55,20 +57,7 @@ export default function WebViewContainer() { function WebviewItem({navigation, route}) { const webViewRef = useRef(); - - const sendweb = () => { - try { - const lang = RNLocalize.getLocales()[0].languageCode; - const payload = { - type: 'RNLocalize', - Platform: Platform.OS, - data: lang, - }; - webViewRef.current.postMessage(JSON.stringify(payload)); - } catch (error) { - console.log(error); - } - }; + const [isLoading, setIsLoading] = useState(true); const onNavigationStateChange = navState => { webViewRef.canGoBack = navState.canGoBack; @@ -91,7 +80,7 @@ function WebviewItem({navigation, route}) { navigation.dispatch(popAction); } else { const pushAction = StackActions.push('Details', { - url: 'http://localhost:3000/ko/grouping/create?step=main', + url: path, isStack: true, }); navigation.dispatch(pushAction); @@ -109,7 +98,7 @@ function WebviewItem({navigation, route}) { }; return ( - + sendweb()} onMessage={requestOnMessage} // 웹뷰 -> 앱으로 통신 onNavigationStateChange={onNavigationStateChange} // 웹뷰 로딩이 시작되거나 끝나면 호출하는 함수 navState로 url 감지 onShouldStartLoadWithRequest={onShouldStartLoadWithRequest} // 처음 호출한 URL에서 다시 Redirect하는 경우에, 사용하면 navState url 감지 + onLoad={() => setIsLoading(false)} + /> + ); } @@ -136,6 +133,7 @@ const styles = StyleSheet.create({ flex: 1, alignItems: 'center', justifyContent: 'space-between', + backgroundColor: 'white', }, webview: { flex: 1, From e400fd8d6534688b7cf2e76438a5c3738940de5a Mon Sep 17 00:00:00 2001 From: Kuesung Park Date: Sat, 28 Oct 2023 20:41:00 +0900 Subject: [PATCH 06/36] =?UTF-8?q?refactor=20:=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20>=20App=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=EC=97=90=EC=84=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .eslintrc.js | 7 + App.js | 183 +----------------- components/MainNavigator.jsx | 56 ++++++ components/OnBoarding.jsx | 166 ++++++++++++++++ components/WebViewContainer.jsx | 104 ++-------- constants/index.js | 2 +- .../xcshareddata/xcschemes/gloddy.xcscheme | 2 +- 7 files changed, 252 insertions(+), 268 deletions(-) create mode 100644 components/MainNavigator.jsx create mode 100644 components/OnBoarding.jsx diff --git a/.eslintrc.js b/.eslintrc.js index 84ce69b..dbd4b8a 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -3,5 +3,12 @@ module.exports = { extends: '@react-native', rules: { 'react/react-in-jsx-scope': 'off', + 'react-native/no-inline-styles': 0, + 'prettier/prettier': [ + 'error', + { + 'no-inline-styles': false, + }, + ], }, }; diff --git a/App.js b/App.js index b54068a..6b670b6 100644 --- a/App.js +++ b/App.js @@ -1,40 +1,17 @@ -import AsyncStorage from '@react-native-async-storage/async-storage'; +import messaging from '@react-native-firebase/messaging'; import React, {useEffect, useRef, useState} from 'react'; import { Alert, - Animated, AppRegistry, BackHandler, - Dimensions, - Image, - Linking, PermissionsAndroid, Platform, SafeAreaView, StatusBar, - Text, - TouchableOpacity, - View, } from 'react-native'; -import {ExpandingDot} from 'react-native-animated-pagination-dots'; -import * as RNLocalize from 'react-native-localize'; import {PERMISSIONS, request} from 'react-native-permissions'; -import SplashScreen from 'react-native-splash-screen'; -import {SwiperFlatList} from 'react-native-swiper-flatlist'; -import {WebView} from 'react-native-webview'; -import Bubble1SVG from './image/bubble1.svg'; -import Bubble1enSVG from './image/bubble1en.svg'; -import Bubble2SVG from './image/bubble2.svg'; -import Bubble2enSVG from './image/bubble2en.svg'; -import Text1SVG from './image/text1.svg'; -import Text1enSVG from './image/text1en.svg'; -import Text2SVG from './image/text2.svg'; -import Text2enSVG from './image/text2en.svg'; -import messaging from '@react-native-firebase/messaging'; -import {StackActions} from '@react-navigation/native'; -import {SOURCE_URL} from './constants'; -import WebViewContainer from './components/WebViewContainer'; +import MainNavigator from './components/MainNavigator'; // Firebase 알림 async function requestUserPermission() { @@ -48,20 +25,8 @@ async function requestUserPermission() { } } -const deviceWidth = Dimensions.get('window').width; - -const imageDataList = [ - {no: 1, uri: require('./image/character_edit.png')}, - {no: 2, uri: require('./image/character_edit2.png')}, - {no: 3, uri: require('./image/start.png')}, -]; - export default function App() { const webViewRef = useRef(); - const [lang, setlang] = useState(null); - const scrollX = useRef(new Animated.Value(0)).current; - const [webloading, setwebloading] = useState(true); - const [showindex, setshowindex] = useState(true); // 앱이 Foreground 인 상태에서 푸쉬알림 받는 코드 작성 useEffect(() => { @@ -108,25 +73,7 @@ export default function App() { BackHandler.removeEventListener('hardwareBackPress', backAction); }, []); - const preloading = async () => { - const lang = RNLocalize.getLocales()[0].languageCode; - setlang(lang); - const get = await AsyncStorage.getItem('token'); - if (get) { - setwebloading(false); - } - }; - - useEffect(() => { - preloading(); - setTimeout(() => { - SplashScreen.hide(); - }, 3000); - }, []); - - // 사진 라이브러리를 사용하기 전에 이 함수를 호출해야 합니다. // 권한설정 - useEffect(() => { if (Platform.OS === 'android') { const getper = async () => { @@ -148,135 +95,10 @@ export default function App() { } }, []); - const handlestart = async () => { - await AsyncStorage.setItem('token', 'ok'); - setwebloading(false); - }; - return ( - {webloading ? ( - - setshowindex(e.index)} - horizontal={true} - onScroll={Animated.event( - [{nativeEvent: {contentOffset: {x: scrollX}}}], - { - useNativeDriver: false, - }, - )} - onContentProcessDidTerminate={() => webViewRef.current.reload()} - data={imageDataList} - renderItem={({item, index}) => { - return ( - - {index === 0 ? ( - - {lang === 'ko' ? : } - - {lang === 'ko' ? : } - - ) : index === 1 ? ( - - {lang === 'ko' ? : } - - {lang === 'ko' ? : } - - ) : ( - - )} - - {index === 2 && ( - { - handlestart(); - }} - style={{ - width: deviceWidth * 0.9, - height: 60, - borderRadius: 10, - backgroundColor: 'rgb(75,133,247)', - justifyContent: 'center', - alignItems: 'center', - }}> - - {lang === 'ko' ? '시작하기' : 'START'} - - - )} - - ); - }} - keyExtractor={(item, index) => String(index)} - /> - {showindex !== 2 && ( - - )} - - ) : ( - - )} - ); } diff --git a/components/MainNavigator.jsx b/components/MainNavigator.jsx new file mode 100644 index 0000000..47e870d --- /dev/null +++ b/components/MainNavigator.jsx @@ -0,0 +1,56 @@ +import React, {useEffect, useState} from 'react'; + +import AsyncStorage from '@react-native-async-storage/async-storage'; +import {NavigationContainer} from '@react-navigation/native'; +import {createStackNavigator, TransitionPresets} from '@react-navigation/stack'; +import OnBoarding from './OnBoarding'; +import WebViewContainer from './WebViewContainer'; + +const Stack = createStackNavigator(); +export default function MainNavigator() { + const [firstView, setFirstView] = useState(''); + useEffect(() => { + const a = async () => { + const onBoarding = await AsyncStorage.getItem('onBoarding'); + if (onBoarding) { + setFirstView('WebViewContainer'); + } + }; + a(); + }, []); + + return ( + + + + + + + ); +} diff --git a/components/OnBoarding.jsx b/components/OnBoarding.jsx new file mode 100644 index 0000000..1efa901 --- /dev/null +++ b/components/OnBoarding.jsx @@ -0,0 +1,166 @@ +import AsyncStorage from '@react-native-async-storage/async-storage'; +import React, {useEffect, useRef, useState} from 'react'; +import { + Alert, + Animated, + Dimensions, + Image, + Text, + TouchableOpacity, + View, +} from 'react-native'; +import {ExpandingDot} from 'react-native-animated-pagination-dots'; +import SplashScreen from 'react-native-splash-screen'; +import {SwiperFlatList} from 'react-native-swiper-flatlist'; +import Bubble1SVG from '../image/bubble1.svg'; +import Bubble1enSVG from '../image/bubble1en.svg'; +import Bubble2SVG from '../image/bubble2.svg'; +import Bubble2enSVG from '../image/bubble2en.svg'; +import Text1SVG from '../image/text1.svg'; +import Text1enSVG from '../image/text1en.svg'; +import Text2SVG from '../image/text2.svg'; +import Text2enSVG from '../image/text2en.svg'; + +const deviceWidth = Dimensions.get('window').width; + +const imageDataList = [ + {no: 1, uri: require('../image/character_edit.png')}, + {no: 2, uri: require('../image/character_edit2.png')}, + {no: 3, uri: require('../image/start.png')}, +]; + +export default function OnBoarding({navigation}) { + const lang = 'ko'; + const scrollX = useRef(new Animated.Value(0)).current; + const [pageIndex, setpageIndex] = useState(0); + const preloading = async () => { + const get = await AsyncStorage.getItem('token'); + if (get) { + navigation.replace('WebViewContainer'); + } + }; + useEffect(() => { + preloading(); + setTimeout(() => { + SplashScreen.hide(); + }, 3000); + }, []); + + return ( + + setpageIndex(e.index)} + horizontal={true} + onScroll={Animated.event( + [{nativeEvent: {contentOffset: {x: scrollX}}}], + { + useNativeDriver: false, + }, + )} + data={imageDataList} + renderItem={({item, index}) => { + return ( + + {index === 0 ? ( + + {lang === 'ko' ? : } + + {lang === 'ko' ? : } + + ) : index === 1 ? ( + + {lang === 'ko' ? : } + + {lang === 'ko' ? : } + + ) : ( + + )} + + {index === 2 && ( + { + await AsyncStorage.setItem('onBoarding', 'true'); + navigation.replace('WebViewContainer'); + }} + style={{ + width: deviceWidth * 0.9, + height: 60, + borderRadius: 10, + backgroundColor: 'rgb(75,133,247)', + justifyContent: 'center', + alignItems: 'center', + }}> + + {lang === 'ko' ? '시작하기' : 'START'} + + + )} + + ); + }} + keyExtractor={(item, index) => String(index)} + /> + {pageIndex < 2 && ( + + )} + + ); +} diff --git a/components/WebViewContainer.jsx b/components/WebViewContainer.jsx index 593bc0b..98f040d 100644 --- a/components/WebViewContainer.jsx +++ b/components/WebViewContainer.jsx @@ -1,63 +1,12 @@ -import {useRef, useState} from 'react'; +import AsyncStorage from '@react-native-async-storage/async-storage'; +import {StackActions} from '@react-navigation/native'; +import {useRef} from 'react'; +import {Dimensions, Linking, StyleSheet} from 'react-native'; import WebView from 'react-native-webview'; import {SOURCE_URL} from '../constants'; -import { - Alert, - Dimensions, - Linking, - Platform, - SafeAreaView, - StatusBar, - StyleSheet, - Text, - View, -} from 'react-native'; -import * as RNLocalize from 'react-native-localize'; -import AsyncStorage from '@react-native-async-storage/async-storage'; -import {NavigationContainer, StackActions} from '@react-navigation/native'; -import {createStackNavigator, TransitionPresets} from '@react-navigation/stack'; - -const Stack = createStackNavigator(); -export default function WebViewContainer() { - return ( - - - - - - ); -} - -function WebviewItem({navigation, route}) { +export default function WebViewContainer({navigation, route}) { const webViewRef = useRef(); - const [isLoading, setIsLoading] = useState(true); const onNavigationStateChange = navState => { webViewRef.canGoBack = navState.canGoBack; @@ -98,30 +47,19 @@ function WebviewItem({navigation, route}) { }; return ( - - 앱으로 통신 - onNavigationStateChange={onNavigationStateChange} // 웹뷰 로딩이 시작되거나 끝나면 호출하는 함수 navState로 url 감지 - onShouldStartLoadWithRequest={onShouldStartLoadWithRequest} // 처음 호출한 URL에서 다시 Redirect하는 경우에, 사용하면 navState url 감지 - onLoad={() => setIsLoading(false)} - /> - + 앱으로 통신 + onNavigationStateChange={onNavigationStateChange} // 웹뷰 로딩이 시작되거나 끝나면 호출하는 함수 navState로 url 감지 + onShouldStartLoadWithRequest={onShouldStartLoadWithRequest} // 처음 호출한 URL에서 다시 Redirect하는 경우에, 사용하면 navState url 감지 + /> ); } @@ -129,12 +67,6 @@ const windowWidth = Dimensions.get('window').width; const windowHeight = Dimensions.get('window').height; const styles = StyleSheet.create({ - container: { - flex: 1, - alignItems: 'center', - justifyContent: 'space-between', - backgroundColor: 'white', - }, webview: { flex: 1, width: windowWidth, diff --git a/constants/index.js b/constants/index.js index 504aab5..b2098fc 100644 --- a/constants/index.js +++ b/constants/index.js @@ -1 +1 @@ -export const SOURCE_URL = 'https://gloddy.vercel.app'; +export const SOURCE_URL = 'http://localhost:3000'; diff --git a/ios/gloddy.xcodeproj/xcshareddata/xcschemes/gloddy.xcscheme b/ios/gloddy.xcodeproj/xcshareddata/xcschemes/gloddy.xcscheme index 6853112..d997c3a 100644 --- a/ios/gloddy.xcodeproj/xcshareddata/xcschemes/gloddy.xcscheme +++ b/ios/gloddy.xcodeproj/xcshareddata/xcschemes/gloddy.xcscheme @@ -41,7 +41,7 @@ Date: Sat, 28 Oct 2023 20:51:43 +0900 Subject: [PATCH 07/36] =?UTF-8?q?refactor=20:=20SafeArea=20WebViewContaine?= =?UTF-8?q?r=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App.js | 113 ++-------------------------- components/MainNavigator.jsx | 23 +----- components/OnBoarding.jsx | 8 +- components/WebViewContainer.jsx | 127 +++++++++++++++++++++++++++----- 4 files changed, 126 insertions(+), 145 deletions(-) diff --git a/App.js b/App.js index 6b670b6..c378b45 100644 --- a/App.js +++ b/App.js @@ -1,112 +1,15 @@ -import messaging from '@react-native-firebase/messaging'; -import React, {useEffect, useRef, useState} from 'react'; -import { - Alert, - AppRegistry, - BackHandler, - PermissionsAndroid, - Platform, - SafeAreaView, - StatusBar, -} from 'react-native'; -import {PERMISSIONS, request} from 'react-native-permissions'; +import React from 'react'; +import {StatusBar, View} from 'react-native'; import MainNavigator from './components/MainNavigator'; -// Firebase 알림 -async function requestUserPermission() { - const authStatus = await messaging().requestPermission(); - const enabled = - authStatus === messaging.AuthorizationStatus.AUTHORIZED || - authStatus === messaging.AuthorizationStatus.PROVISIONAL; - - if (enabled) { - console.log('Authorization status:', authStatus); - } -} - export default function App() { - const webViewRef = useRef(); - - // 앱이 Foreground 인 상태에서 푸쉬알림 받는 코드 작성 - useEffect(() => { - const unsubscribe = messaging().onMessage(async remoteMessage => { - Alert.alert('A new FCM message arrived!', JSON.stringify(remoteMessage)); - }); - - return unsubscribe; - }, []); - - // 앱이 Background 이거나 꺼진 상태에서 푸쉬알림 받는 코드 작성 - messaging().setBackgroundMessageHandler(async remoteMessage => { - console.log('Message handled in the background!', remoteMessage); - }); - - AppRegistry.registerComponent('app', () => App); - - // 뒤로 가기 control - const [exit, setexit] = useState(false); - const [swexit, setswexit] = useState(0); - const backAction = () => { - // 500(0.5초) 안에 back 버튼을 한번 더 클릭 할 경우 앱 종료 - setswexit(swexit => swexit + 1); - return true; - }; - - useEffect(() => { - let timer; - if (exit === false) { - webViewRef?.current?.goBack(); - setexit(true); - timer = setTimeout(function () { - setexit(false); - }, 500); - } else { - clearTimeout(timer); - BackHandler.exitApp(); - } - }, [swexit]); - - useEffect(() => { - BackHandler.addEventListener('hardwareBackPress', backAction); - return () => - BackHandler.removeEventListener('hardwareBackPress', backAction); - }, []); - - // 권한설정 - useEffect(() => { - if (Platform.OS === 'android') { - const getper = async () => { - await PermissionsAndroid.request( - PermissionsAndroid.PERMISSIONS.ACCESS_MEDIA_LOCATION, - ); - await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.CAMERA); - }; - getper(); - } - if (Platform.OS === 'ios') { - const requestPhotoLibraryPermission = async () => { - await request(PERMISSIONS.IOS.CAMERA); - await request(PERMISSIONS.IOS.MICROPHONE); - await request(PERMISSIONS.IOS.PHOTO_LIBRARY); - await requestUserPermission(); - }; - requestPhotoLibraryPermission(); - } - }, []); - return ( - - + <> + + + + + ); } diff --git a/components/MainNavigator.jsx b/components/MainNavigator.jsx index 47e870d..6de12f9 100644 --- a/components/MainNavigator.jsx +++ b/components/MainNavigator.jsx @@ -28,28 +28,7 @@ export default function MainNavigator() { headerShown: false, }}> - + ); diff --git a/components/OnBoarding.jsx b/components/OnBoarding.jsx index 1efa901..5490a4a 100644 --- a/components/OnBoarding.jsx +++ b/components/OnBoarding.jsx @@ -47,7 +47,13 @@ export default function OnBoarding({navigation}) { }, []); return ( - + { + const unsubscribe = messaging().onMessage(async remoteMessage => { + Alert.alert('A new FCM message arrived!', JSON.stringify(remoteMessage)); + }); + + return unsubscribe; + }, []); + + // 앱이 Background 이거나 꺼진 상태에서 푸쉬알림 받는 코드 작성 + messaging().setBackgroundMessageHandler(async remoteMessage => { + console.log('Message handled in the background!', remoteMessage); + }); + + // 뒤로 가기 control + const [exit, setexit] = useState(false); + const [swexit, setswexit] = useState(0); + const backAction = () => { + // 500(0.5초) 안에 back 버튼을 한번 더 클릭 할 경우 앱 종료 + setswexit(swexit => swexit + 1); + return true; + }; + + useEffect(() => { + let timer; + if (exit === false) { + webViewRef?.current?.goBack(); + setexit(true); + timer = setTimeout(function () { + setexit(false); + }, 500); + } else { + clearTimeout(timer); + BackHandler.exitApp(); + } + }, [swexit]); + + useEffect(() => { + BackHandler.addEventListener('hardwareBackPress', backAction); + return () => + BackHandler.removeEventListener('hardwareBackPress', backAction); + }, []); + + // 권한설정 + useEffect(() => { + if (Platform.OS === 'android') { + const getper = async () => { + await PermissionsAndroid.request( + PermissionsAndroid.PERMISSIONS.ACCESS_MEDIA_LOCATION, + ); + await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.CAMERA); + }; + getper(); + } + if (Platform.OS === 'ios') { + const requestPhotoLibraryPermission = async () => { + await request(PERMISSIONS.IOS.CAMERA); + await request(PERMISSIONS.IOS.MICROPHONE); + await request(PERMISSIONS.IOS.PHOTO_LIBRARY); + await requestUserPermission(); + }; + requestPhotoLibraryPermission(); + } + }, []); + const onNavigationStateChange = navState => { webViewRef.canGoBack = navState.canGoBack; if (!navState.url.includes(SOURCE_URL)) { @@ -28,8 +117,8 @@ export default function WebViewContainer({navigation, route}) { const popAction = StackActions.pop(1); navigation.dispatch(popAction); } else { - const pushAction = StackActions.push('Details', { - url: path, + const pushAction = StackActions.push('WebViewContainer', { + url: 'https://www.naver.com', isStack: true, }); navigation.dispatch(pushAction); @@ -47,19 +136,23 @@ export default function WebViewContainer({navigation, route}) { }; return ( - 앱으로 통신 - onNavigationStateChange={onNavigationStateChange} // 웹뷰 로딩이 시작되거나 끝나면 호출하는 함수 navState로 url 감지 - onShouldStartLoadWithRequest={onShouldStartLoadWithRequest} // 처음 호출한 URL에서 다시 Redirect하는 경우에, 사용하면 navState url 감지 - /> + <> + + 앱으로 통신 + onNavigationStateChange={onNavigationStateChange} // 웹뷰 로딩이 시작되거나 끝나면 호출하는 함수 navState로 url 감지 + onShouldStartLoadWithRequest={onShouldStartLoadWithRequest} // 처음 호출한 URL에서 다시 Redirect하는 경우에, 사용하면 navState url 감지 + /> + + ); } From 48c1d624d3fb5710ef7f4dff7986f3223d43c54a Mon Sep 17 00:00:00 2001 From: Kuesung Park Date: Sat, 28 Oct 2023 20:59:33 +0900 Subject: [PATCH 08/36] =?UTF-8?q?feat=20:=20=EC=97=90=EB=9F=AC=ED=95=B8?= =?UTF-8?q?=EB=93=A4=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/Error.tsx | 44 +++++++++++++++++++++++++++++++++ components/WebViewContainer.jsx | 27 +++++++++++++++++++- src/styles/theme.ts | 17 +++++++++++++ tsconfig.json | 10 +++++++- 4 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 components/Error.tsx create mode 100644 src/styles/theme.ts diff --git a/components/Error.tsx b/components/Error.tsx new file mode 100644 index 0000000..cc1e008 --- /dev/null +++ b/components/Error.tsx @@ -0,0 +1,44 @@ +import {Button, Text, View} from 'react-native'; +import theme from '../src/styles/theme'; + +interface Props { + reload: () => void; +} + +const Error = ({reload}: Props) => { + return ( + + + + 알 수 없는 에러가 발생했어요. + + + 네트워크 상태가 올바른지 확인해주세요. + + + 문제가 지속된다면 ahmatda.app@gmail.com으로 문의해주세요. + + + +