Skip to content

Commit

Permalink
Release/v1.4.10
Browse files Browse the repository at this point in the history
Feature: 안드로이드 뒤로가기 버튼 개선, Footer 개선, splash screen 개선 (#679)
  • Loading branch information
dev-dong-su authored Apr 5, 2024
2 parents ad8a53b + ce374e7 commit 0183591
Show file tree
Hide file tree
Showing 16 changed files with 89 additions and 108 deletions.
2 changes: 0 additions & 2 deletions packages/app/src/components/MainNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { TransitionPresets, createStackNavigator } from '@react-navigation/stack
import React from 'react';

import OnBoarding from './OnBoarding';
import TabBarNavigator from './TabBarNavigator';
import WebViewContainer from './WebViewContainer';

import { useDidMount } from '@/hooks/useDidMount';
Expand All @@ -29,7 +28,6 @@ export default function MainNavigator() {
}}
>
<Stack.Screen name="OnBoarding" component={OnBoarding} />
<Stack.Screen name="BottomTab" component={TabBarNavigator} />
<Stack.Screen name="WebViewContainer" component={WebViewContainer} />
</Stack.Navigator>
</NavigationContainer>
Expand Down
22 changes: 17 additions & 5 deletions packages/app/src/components/OnBoarding.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import AsyncStorage from '@react-native-async-storage/async-storage';
import { useNavigation } from '@react-navigation/native';
import { StackNavigationProp } from '@react-navigation/stack';
import { useEffect, useRef, useState } from 'react';
import { Animated, Dimensions, Image, Text, TouchableOpacity, View } from 'react-native';
import { ExpandingDot } from 'react-native-animated-pagination-dots';
Expand Down Expand Up @@ -27,28 +28,36 @@ const imageDataList = [
];

export default function OnBoarding() {
const navigation = useNavigation();
const navigation = useNavigation<StackNavigationProp<any>>();
const [isPreloadingDone, setIsPreloadingDone] = useState(false);
const scrollX = useRef(new Animated.Value(0)).current;
const [pageIndex, setpageIndex] = useState(0);
const [lang, setlang] = useState(null);
const [lang, setlang] = useState<string | null>(null);

const preloading = async () => {
const isUserOnBoardSeen = await AsyncStorage.getItem('onBoarding');
if (!isUserOnBoardSeen) return;

navigation.replace('WebViewContainer', {
url: `${SOURCE_URL}`,
});

setIsPreloadingDone(true);
};

useEffect(() => {
const locales = RNLocalize.getLocales();
const languageCode = locales && locales.length > 0 ? locales[0].languageCode : 'en';
setlang(languageCode);
preloading();
setTimeout(() => {
SplashScreen.hide();
}, 500);
}, []);

useEffect(() => {
if (isPreloadingDone) {
SplashScreen.hide();
}
}, [isPreloadingDone]);

return (
<View
style={{
Expand Down Expand Up @@ -84,6 +93,7 @@ export default function OnBoarding() {
<View style={{ alignItems: 'center' }}>
{lang === 'ko' ? <Bubble1SVG /> : <Bubble1enSVG />}
<Image
alt="onboard-image1"
style={{
width: deviceWidth * 0.8,
height: deviceWidth * 0.8,
Expand All @@ -98,6 +108,7 @@ export default function OnBoarding() {
<View style={{ alignItems: 'center' }}>
{lang === 'ko' ? <Bubble2SVG /> : <Bubble2enSVG />}
<Image
alt="onboard-image2"
style={{
width: deviceWidth * 0.8,
height: deviceWidth * 0.8,
Expand All @@ -111,6 +122,7 @@ export default function OnBoarding() {
</View>
) : (
<Image
alt="onboard-image3"
style={{
width: deviceWidth * 0.7,
height: deviceWidth * 1.6,
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/components/TabBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const isKeyScreenIconName = (value: string) => value in ScreenIconName;
const getScreenIcon = (value: string) =>
isKeyScreenIconName(value) ? ScreenIconName[value as ScreenIconNameKey] : undefined;

function TabBar({ state, navigation, descriptors }: BottomTabBarProps) {
function TabBar({ state, navigation }: BottomTabBarProps) {
const onPress = useTabBarPress();
const renderTabBarButton = useCallback(
(name: string, index: number) => (
Expand Down
81 changes: 40 additions & 41 deletions packages/app/src/components/WebViewContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,55 @@
import AsyncStorage from '@react-native-async-storage/async-storage';
import messaging from '@react-native-firebase/messaging';
import { StackActions, useNavigation, useRoute } from '@react-navigation/native';
import { RouteProp, StackActions, useNavigation, useRoute } from '@react-navigation/native';
import React, { useEffect, useRef, useState } from 'react';
import { Alert, BackHandler, Dimensions, Linking, Platform } from 'react-native';
import RNRestart from 'react-native-restart'; // Import package from node modules
import RNRestart from 'react-native-restart';
import { SafeAreaView } from 'react-native-safe-area-context';
import WebView from 'react-native-webview';
import WebView, { WebViewMessageEvent, WebViewNavigation } from 'react-native-webview';

import Error from './Error';
import { SOURCE_URL } from '../config';
import { sendFCMTokenToWebView } from '../utils/sendFCMTokenToWebView';

import { useDidMount } from '@/hooks/useDidMount';
import useWebViewNavigationSetUp from '@/hooks/useWebViewNavigationSetUp';
import { getPermission } from '@/utils/getPermission';
import sendMessageToWebview from '@/utils/sendMessageToWebview';

const windowWidth = Dimensions.get('window').width;
const windowHeight = Dimensions.get('window').height;

type WebViewParams = {
url?: string;
edges?: any[];
title?: string;
};

export default function WebViewContainer() {
useWebViewNavigationSetUp();
const navigation = useNavigation();
const params = useRoute().params;
const webViewRef = useRef(null);
const params = useRoute<RouteProp<{ params: WebViewParams }, 'params'>>().params;
const webViewRef = useRef<WebView>(null);
const { isError, setIsError, onWebViewError } = useAppError();
const [canGoBackInWebView, setCanGoBackInWebView] = useState(false);
const url = params.url ?? SOURCE_URL;
const edges = params?.edges;

useDidMount(async () => {
/* 권한 요청 */
await sendFCMTokenToWebView(webViewRef);
await messaging().requestPermission();
});

/* 안드로이드 뒤로가기 */
useDidMount(() => {
// Android 뒤로가기 버튼 이벤트 처리
useEffect(() => {
if (Platform.OS !== 'android') return;

const handleAndroidBackPress = () => {
if (navigation.canGoBack()) navigation.goBack();
else {
console.log('back pushed ' + canGoBackInWebView);

if (canGoBackInWebView && webViewRef.current) {
webViewRef.current.goBack();
return true;
} else if (navigation.canGoBack()) {
navigation.goBack();
return true;
} else {
Alert.alert(
'Hold on!(잠시만요!)',
'Are you sure you want to quit the program?(앱을 종료하시겠습니까?)',
Expand All @@ -50,41 +61,35 @@ export default function WebViewContainer() {
{ text: 'Confirm(확인)', onPress: () => BackHandler.exitApp() },
]
);
}

if (webViewRef.current) {
webViewRef.current.goBack();
return true;
}
return false;
};

if (Platform.OS === 'android') {
BackHandler.addEventListener('hardwareBackPress', handleAndroidBackPress);
return () => {
BackHandler.removeEventListener('hardwareBackPress', handleAndroidBackPress);
};
}
});
BackHandler.addEventListener('hardwareBackPress', handleAndroidBackPress);
return () => {
BackHandler.removeEventListener('hardwareBackPress', handleAndroidBackPress);
};

/* (iOS)외부 페이지 이동 */
const onNavigationStateChange = (navState) => {
if (!navState.url.includes(SOURCE_URL)) {
Linking.openURL(navState.url).catch((err) => {});
return false;
}
/**
* addEventListener로 등록된 handleAndroidBackPress가 생성시의 클로저 환경을 유지하기 때문에
* canGoBackInWebView의 상태를 추적하기 위해 의존성 배열에 canGoBackInWebView와 navigation추가
*/
}, [canGoBackInWebView, navigation]);

const onNavigationStateChange = (navState: WebViewNavigation) => {
setCanGoBackInWebView(navState.canGoBack);
};

const onShouldStartLoadWithRequest = (navState) => {
if (!navState.url.includes(SOURCE_URL)) {
const onShouldStartLoadWithRequest = (navState: WebViewNavigation) => {
if (SOURCE_URL && !navState.url.includes(SOURCE_URL)) {
Linking.openURL(navState.url).catch((err) => {});
return false;
}
return true;
};

/* 페이지 이동 */
const requestOnMessage = async (event) => {
const requestOnMessage = async (event: WebViewMessageEvent) => {
const nativeEvent = JSON.parse(event.nativeEvent.data);
const { type, data } = nativeEvent;
switch (type) {
Expand All @@ -96,11 +101,6 @@ export default function WebViewContainer() {
url: `${SOURCE_URL}${path}`,
title,
edges: title ? ['bottom'] : [],
// right: () => { // 어디서 쓰는지 잘 모르겠는데 WARNING 떠서 주석처리
// webViewRef.current?.postMessage(
// JSON.stringify({type: 'NAVIGATION_TAPPED_RIGHT_BUTTON'}),
// );
// },
});
navigation.dispatch(pushAction);
break;
Expand Down Expand Up @@ -164,7 +164,6 @@ export default function WebViewContainer() {
pullToRefreshEnabled
thirdPartyCookiesEnabled={true}
sharedCookiesEnabled={true}
androidHardwareAccelerationDisabled
onNavigationStateChange={onNavigationStateChange}
onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
onMessage={requestOnMessage} // 웹뷰 -> 앱으로 통신
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 0183591

Please sign in to comment.