Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion app/webview/[slug].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import { ActivityIndicator, TouchableOpacity } from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
import { WebView } from "react-native-webview";
import styled from "styled-components/native";

Check warning on line 17 in app/webview/[slug].tsx

View workflow job for this annotation

GitHub Actions / android-check

Using exported name 'styled' as identifier for default import

const webviewUrl =
process.env.EXPO_PUBLIC_WEBVIEW_URL || "https://develop.moadong.com";
Expand Down Expand Up @@ -76,7 +76,14 @@
? (config.url ?? (config.path ? `${webviewUrl}${config.path}` : ""))
: "";

const url = useMemo(() => appendSessionId(baseUrl, sessionId), [baseUrl, sessionId]);
/**
* session_id 는 웹 Mixpanel 의 distinct_id 라 모아동 밖으로 나가면 안 된다.
* 이 화면은 slug=external 로 임의 외부 URL 도 로드하므로 오리진을 확인하고 붙인다.
*/
const url = useMemo(
() => (isWebViewOrigin(baseUrl) ? appendSessionId(baseUrl, sessionId) : baseUrl),
[baseUrl, sessionId],
);

/**
* 우체통은 앱이 주입한 학생 토큰을 먼저 쓴다(웹 studentFetch). 주입이 없으면 웹이
Expand Down
12 changes: 9 additions & 3 deletions ui/home/home-webview-screen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useHomeWebViewPreloadContext } from '@/contexts/home-webview-preload-co
import { useMixpanelContext } from '@/contexts/mixpanel-context';
import { useSubscribedClubsContext } from '@/contexts/subscribed-clubs-context';
import { ensureAccessToken } from '@/services/auth-token.service';
import { appendSessionId, buildStudentTokenInjection, getWebViewUserAgent } from '@/utils/webview';
import { appendSessionId, buildStudentTokenInjection, getWebViewUserAgent, isWebViewOrigin } from '@/utils/webview';
import Constants from 'expo-constants';
import { useRouter } from 'expo-router';
import * as WebBrowser from 'expo-web-browser';
Expand Down Expand Up @@ -174,8 +174,10 @@ export function HomeWebViewScreen({ onError }: HomeWebViewScreenProps) {

const handleShouldStartLoadWithRequest = useCallback(
(request: ShouldStartLoadRequest) => {
const baseOrigin = (process.env.EXPO_PUBLIC_WEBVIEW_URL ?? 'https://moadong.com').replace(/\/$/, '');
if (request.url.startsWith('http') && !request.url.startsWith(baseOrigin)) {
// origin 을 문자열 prefix 로 판정하면 moadong.com.evil.com 이 내부로 통과한다.
// 그 페이지가 이 웹뷰에 뜨면 window.ReactNativeWebView.postMessage 로 브리지를
// 그대로 쓸 수 있다(SUBSCRIBE_TOGGLE, OPEN_EXTERNAL_URL 등). 파싱해서 비교한다.
if (request.url.startsWith('http') && !isWebViewOrigin(request.url)) {
// iOS: navigationType === 'click' 은 사용자가 직접 링크를 탭한 경우만 해당
// 초기 로드·서버 리다이렉트는 'other' 이므로 인터셉트하지 않음
// Android: navigationType이 항상 'other'이므로 loaded 상태로 구분
Expand Down Expand Up @@ -230,6 +232,10 @@ export function HomeWebViewScreen({ onError }: HomeWebViewScreenProps) {
onHttpError={handleError}
javaScriptEnabled
domStorageEnabled
// Android 기본값(true)이면 target=_blank 가 onCreateWindow 로 가는데,
// onOpenWindow 핸들러가 없으면 화면에 붙지 않는 WebView 로 빨려들어가 링크가 죽는다.
// false 로 두면 같은 요청이 onShouldStartLoadWithRequest 를 타 iOS 와 같은 경로가 된다.
setSupportMultipleWindows={false}
pullToRefreshEnabled
allowsBackForwardNavigationGestures
/>
Expand Down
Loading