import { useCallback, useEffect, useRef } from 'react';
import MobileAppBridge from 'app/libs/MobileAppBridge';
import { closeKakaoInAppBrowser } from 'app/libs/snsUtils';
import useSsrUserAgent from 'app/hook/common/useSsrUserAgent';
const closerOptions = {
browser: {
onNotClosed: undefined,
},
};
export function useUniversalCloser(options = closerOptions) {
const ua = useSsrUserAgent();
const {
isApp, isAndroid, isKakao,
} = ua();
const { browser } = useRef(options).current;
const prevCheckTimer = useRef(null);
useEffect(() => {
const onPrevCheck = () => (clearTimeout(prevCheckTimer.current));
window.addEventListener('pageshow', onPrevCheck, { capture: true });
window.addEventListener('pagehide', onPrevCheck, { capture: true });
window.addEventListener('beforeunload', onPrevCheck, { capture: true });
window.addEventListener('popstate', onPrevCheck, { capture: true });
return () => {
clearTimeout(prevCheckTimer.current);
window.removeEventListener('pageshow', onPrevCheck, { capture: true });
window.removeEventListener('pagehide', onPrevCheck, { capture: true });
window.removeEventListener('beforeunload', onPrevCheck, { capture: true });
window.removeEventListener('popstate', onPrevCheck, { capture: true });
};
}, []);
const handleAppClose = useCallback(() => {
if (isApp) {
if (isAndroid) {
MobileAppBridge().destroyNativeWindow();
} else {
window.close();
}
}
}, [isAndroid, isApp]);
const handleKakaoClose = useCallback(() => {
if (isKakao) {
closeKakaoInAppBrowser();
}
}, [isKakao]);
const handleBrowserClose = useCallback(() => {
if (isApp || isKakao) {
return;
}
const { onNotClosed } = browser;
window.close();
if (onNotClosed) {
setTimeout(() => {
onNotClosed();
}, 1000);
}
}, [browser, isApp, isKakao]);
const handleCheckPrevPageClose = useCallback(() => {
const { onNotClosed } = browser;
const windowType = isApp && 'isApp' || isKakao && 'isKakao' || 'close';
const windowCloseMethod = {
isApp: MobileAppBridge().destroyWebView,
isKakao: closeKakaoInAppBrowser,
close: window.close,
}[windowType];
// ios 사파리는 length 2이하로 해야댈듯?
if (window.history.length === 1) {
windowCloseMethod();
return;
}
window.history.back();
prevCheckTimer.current = setTimeout(() => {
windowCloseMethod();
if (onNotClosed) {
onNotClosed();
}
}, 1000);
}, [isApp, isKakao, browser]);
const handleUniversalClose = useCallback(() => {
handleAppClose();
handleKakaoClose();
handleBrowserClose();
}, [handleAppClose, handleBrowserClose, handleKakaoClose]);
return {
handleAppClose,
handleKakaoClose,
handleBrowserClose,
handleUniversalClose,
handleCheckPrevPageClose,
};
}
export default null;
카카오 종료 스크립트
export const closeKakaoInAppBrowser = () => {
const {
navigator: { userAgent },
location,
} = window;
location.href = (/iPad|iPhone|iPod/.test(userAgent))
? 'kakaoweb://closeBrowser'
: 'kakaotalk://inappbrowser/close';
};
최신 정리
import { useCallback, useEffect, useRef } from 'react';
import MobileAppBridge from 'app/libs/MobileAppBridge';
import { closeKakaoInAppBrowser } from 'app/libs/snsUtils';
import useSsrUserAgent from 'app/hook/common/useSsrUserAgent';
const closerOptions = {
browser: {
onNotClosed: undefined,
},
};
export function useUniversalCloser(options = closerOptions) {
const ua = useSsrUserAgent();
const {
isApp,
isAndroid,
isKakao,
} = ua();
const { browser } = useRef(options).current;
const prevCheckTimer = useRef(null);
useEffect(() => {
const onPrevCheck = () => (clearTimeout(prevCheckTimer.current));
window.addEventListener('pageshow', onPrevCheck, { capture: true });
window.addEventListener('pagehide', onPrevCheck, { capture: true });
window.addEventListener('beforeunload', onPrevCheck, { capture: true });
window.addEventListener('popstate', onPrevCheck, { capture: true });
return () => {
clearTimeout(prevCheckTimer.current);
window.removeEventListener('pageshow', onPrevCheck, { capture: true });
window.removeEventListener('pagehide', onPrevCheck, { capture: true });
window.removeEventListener('beforeunload', onPrevCheck, { capture: true });
window.removeEventListener('popstate', onPrevCheck, { capture: true });
};
}, []);
// 카카오톡 인앱, 자사앱, 브라우저 윈도우 닫기
const closeCrossPlatform = useCallback(() => {
if (isServer) {
return;
}
if (isKakao) {
window.location.href = isIOS
? 'kakaoweb://closeBrowser'
: 'kakaotalk://inappbrowser/close';
return;
}
if (isApp) {
appBridge().closeWebview();
return;
}
window.close();
}, []);
const goBackOrClose = useCallback(() => {
if (isServer) {
return;
}
const { onNotClosed } = browser;
const windowType = isApp && 'isApp' || isKakao && 'isKakao' || 'close';
const windowCloseMethod = {
isApp: MobileAppBridge().destroyWebView,
isKakao: closeKakaoInAppBrowser,
close: window.close,
}[windowType];
// ios 사파리는 length 2이하로 해야댈듯?
const historyLength = window.history.length;
const shouldCloseHistoryLength = isIOS && isSafari ? 2 : 1;
if (historyLength === shouldCloseHistoryLength) {
windowCloseMethod();
return;
}
window.history.back();
prevCheckTimer.current = setTimeout(closeCrossPlatform, 600);
}, [isApp, isKakao, browser]);
return {
closeCrossPlatform,
goBackOrClose,
};
}