Skip to content

Commit e9294cb

Browse files
sumisumi
authored andcommitted
feat: webview, app logout 연동
1 parent 9440cda commit e9294cb

3 files changed

Lines changed: 89 additions & 12 deletions

File tree

apps/app/components/CustomWebView.tsx

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { useRef, useState, useEffect } from 'react';
22
import { StyleSheet, View, BackHandler, Platform, Linking, ActivityIndicator, Text } from 'react-native';
33
import { WebView, WebViewNavigation } from 'react-native-webview';
44
import { handleGithubLogin } from '../utils/github';
5+
import { useAuth } from '../hooks/useAuth';
56

67
interface CustomWebViewProps {
78
url: string;
@@ -76,6 +77,7 @@ const CustomWebView: React.FC<CustomWebViewProps> = ({ url, token }) => {
7677
const webViewRef = useRef<WebView>(null);
7778
const [loading, setLoading] = useState(true);
7879
const [canGoBack, setCanGoBack] = useState(false);
80+
const { logout } = useAuth();
7981

8082
const handleNavigationStateChange = (navState: WebViewNavigation) => {
8183
// 웹뷰 상태 업데이트
@@ -92,9 +94,9 @@ const CustomWebView: React.FC<CustomWebViewProps> = ({ url, token }) => {
9294

9395
useEffect(() => {
9496
if (Platform.OS === 'android') {
95-
BackHandler.addEventListener('hardwareBackPress', onAndroidBackPress);
97+
const subscription = BackHandler.addEventListener('hardwareBackPress', onAndroidBackPress);
9698
return () => {
97-
BackHandler.removeEventListener('hardwareBackPress', onAndroidBackPress);
99+
subscription.remove();
98100
};
99101
}
100102
}, [canGoBack]);
@@ -117,6 +119,10 @@ const CustomWebView: React.FC<CustomWebViewProps> = ({ url, token }) => {
117119
setCanGoBack(data.canGoBack);
118120
} else if (type === 'GITHUB_LOGIN') {
119121
await handleGithubLogin();
122+
} else if (type === 'LOGOUT') {
123+
console.log('[WebView Debug] Logout request received');
124+
await logout();
125+
console.log('[WebView Debug] Logout completed');
120126
}
121127
} catch (error) {
122128
console.log('[WebView Debug] Failed to parse webview message:', error);
@@ -126,13 +132,21 @@ const CustomWebView: React.FC<CustomWebViewProps> = ({ url, token }) => {
126132
const loginInjectedJavaScript = `
127133
(function() {
128134
// GitHub 로그인 버튼을 찾기 위한 선택자들을 추가
129-
const selectors = [
135+
const loginSelectors = [
130136
'[data-testid="github-login-button"]',
131137
'[data-testid="login-button"]',
132138
'button:contains("GitHub")',
133139
'a:contains("GitHub")'
134140
];
135141
142+
// Logout 버튼을 찾기 위한 선택자들
143+
const logoutSelectors = [
144+
'button:contains("logout")',
145+
'[data-testid="logout-button"]',
146+
'.logout-button',
147+
'#logout-button'
148+
];
149+
136150
function addLoginHandler(element) {
137151
element.addEventListener('click', function(e) {
138152
e.preventDefault();
@@ -142,20 +156,38 @@ const CustomWebView: React.FC<CustomWebViewProps> = ({ url, token }) => {
142156
});
143157
}
144158
145-
// 모든 선택자를 시도
146-
selectors.forEach(selector => {
147-
const elements = document.querySelectorAll(selector);
148-
elements.forEach(addLoginHandler);
149-
});
159+
function addLogoutHandler(element) {
160+
console.log('[WebView Debug] Adding logout handler to element:', element);
161+
element.addEventListener('click', function(e) {
162+
console.log('[WebView Debug] Logout button clicked');
163+
window.ReactNativeWebView.postMessage(JSON.stringify({
164+
type: 'LOGOUT'
165+
}));
166+
});
167+
}
168+
169+
function attachHandlers() {
170+
// 로그인 버튼 핸들러 추가
171+
loginSelectors.forEach(selector => {
172+
const elements = document.querySelectorAll(selector);
173+
elements.forEach(addLoginHandler);
174+
});
175+
176+
// 로그아웃 버튼 핸들러 추가
177+
logoutSelectors.forEach(selector => {
178+
const elements = document.querySelectorAll(selector);
179+
elements.forEach(addLogoutHandler);
180+
});
181+
}
182+
183+
// 초기 핸들러 연결
184+
attachHandlers();
150185
151186
// 동적으로 추가되는 버튼을 위한 MutationObserver
152187
const observer = new MutationObserver((mutations) => {
153188
mutations.forEach((mutation) => {
154189
if (mutation.addedNodes.length) {
155-
selectors.forEach(selector => {
156-
const elements = document.querySelectorAll(selector);
157-
elements.forEach(addLoginHandler);
158-
});
190+
attachHandlers();
159191
}
160192
});
161193
});

apps/webview/src/app/[locale]/(home)/page.tsx

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,25 @@ import CharacterView from './_components/CharacterView';
88
import { ProfileBoard } from './_components/ProfileBoard';
99

1010
export default function WebviewPage() {
11+
const handleLogout = () => {
12+
// React Native로 logout 메시지 전송
13+
if (window.ReactNativeWebView) {
14+
window.ReactNativeWebView.postMessage(
15+
JSON.stringify({
16+
type: 'LOGOUT',
17+
}),
18+
);
19+
} else {
20+
// 웹 브라우저에서의 경우 일반적인 로그아웃 처리
21+
console.log('Logout clicked in web browser');
22+
}
23+
};
24+
1125
return (
1226
<div className={containerStyle}>
27+
<button onClick={handleLogout} className={logoutButtonStyle}>
28+
logout
29+
</button>
1330
<ProfileBoard />
1431
<CharacterView />
1532
<div className={backgroundStyle}>
@@ -54,3 +71,21 @@ const backgroundStyle = css({
5471
objectPosition: 'bottom center',
5572
},
5673
});
74+
75+
const logoutButtonStyle = css({
76+
position: 'absolute',
77+
top: '20px',
78+
right: '20px',
79+
zIndex: 10,
80+
padding: '8px 16px',
81+
backgroundColor: '#ff4444',
82+
color: 'white',
83+
border: 'none',
84+
borderRadius: '4px',
85+
cursor: 'pointer',
86+
fontWeight: 'bold',
87+
88+
_hover: {
89+
backgroundColor: '#cc3333',
90+
},
91+
});

apps/webview/types/globals.d.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,13 @@ declare namespace NodeJS {
33
NEXT_PUBLIC_SLACK_ERROR_CHANNEL_WEBHOOK_URL: string;
44
}
55
}
6+
7+
declare global {
8+
interface Window {
9+
ReactNativeWebView?: {
10+
postMessage: (message: string) => void;
11+
};
12+
}
13+
}
14+
15+
export {};

0 commit comments

Comments
 (0)