Skip to content
Closed
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
6 changes: 3 additions & 3 deletions app.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
"expo": {
"name": "모아동",
"slug": "moadong-app",
"version": "1.5.2",
"version": "1.6.0",
"orientation": "portrait",
"icon": "./assets/images/icon.png",
"scheme": "moadongapp",
"userInterfaceStyle": "light",
"newArchEnabled": true,
"ios": {
"supportsTablet": false,
"buildNumber": "15",
"buildNumber": "16",
"googleServicesFile": "./GoogleService-Info.plist",
"bundleIdentifier": "com.moadong.moadong",
"associatedDomains": [
Expand All @@ -26,7 +26,7 @@
},
"android": {
"jsEngine": "hermes",
"versionCode": 15,
"versionCode": 16,
"adaptiveIcon": {
"backgroundColor": "#E6F4FE",
"foregroundImage": "./assets/images/android-icon-foreground.png",
Expand Down
116 changes: 0 additions & 116 deletions app/(tabs)/_layout.tsx

This file was deleted.

3 changes: 0 additions & 3 deletions app/(tabs)/explore.tsx

This file was deleted.

3 changes: 0 additions & 3 deletions app/(tabs)/index.tsx.backup

This file was deleted.

165 changes: 0 additions & 165 deletions app/(tabs)/more.tsx

This file was deleted.

16 changes: 8 additions & 8 deletions app/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ SplashScreen.preventAutoHideAsync().catch(() => {
});

export const unstable_settings = {
anchor: '(tabs)',
anchor: 'index',
};

type BootstrapStatus = 'idle' | 'running' | 'success' | 'failed';
Expand All @@ -57,15 +57,15 @@ function RootLayoutContent() {
const [bootstrapResult, setBootstrapResult] = useState<BootstrapResult | null>(null);
const bootstrapStatusRef = useRef<BootstrapStatus>('idle');
const nativeSplashHiddenRef = useRef(false);
const { isSettled: homeWebViewPreloadSettled, status: homeWebViewPreloadStatus } =
const { isSettled: homeWebViewPreloadSettled } =
useHomeWebViewPreloadContext();

const initialPathnameRef = useRef(pathname);
const bootstrapSucceeded = bootstrapStatus === 'success';
const shouldWaitForHomeWebView = pathname === '/';
const shouldBlockSplash =
forceUpdateRequired ||
!bootstrapSucceeded ||
(shouldWaitForHomeWebView && !homeWebViewPreloadSettled);
(initialPathnameRef.current === '/' && !homeWebViewPreloadSettled);

Comment on lines 65 to 69

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

ATT 요청 순서가 루트 부트스트랩 계약과 다릅니다.

현재 ATT 요청은 스플래시 해제 이후에만 실행되어, access token/FCM/구독/Mixpanel 초기화보다 늦게 호출됩니다. ATT 단계를 runBootstrapSequence 이전으로 이동해 가이드 순서를 맞춰 주세요.

🔧 제안 수정 예시
-        // 2) Access Token -> FCM/구독 목록/Mixpanel 병렬 부트스트랩
-        await runBootstrapSequence();
+        // 2) iOS ATT 권한 요청
+        await requestTrackingPermissionAfterLaunch();
+        // 3) Access Token -> FCM/구독 목록/Mixpanel 초기화
+        await runBootstrapSequence();
-  useEffect(() => {
-    if (!bootstrapSucceeded || forceUpdateRequired || showSplash || Platform.OS !== 'ios') {
-      return;
-    }
-    ...
-  }, [bootstrapSucceeded, forceUpdateRequired, showSplash]);
+  // ATT는 prepare() 내부 순서에서 처리

As per coding guidelines, app/_layout.tsx must execute bootstrap in order: (1) Firebase Remote Config forced update check, (2) iOS ATT permission request, (3) access token retrieval/creation, (4) FCM token registration, (5) subscribed clubs list sync, (6) Mixpanel analytics initialization, and block UI until bootstrap completes.

Also applies to: 117-141, 177-195

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/_layout.tsx` around lines 65 - 69, The ATT permission request currently
runs after the splash is released; move the ATT step to run before
runBootstrapSequence so the bootstrap order becomes: (1) Firebase remote-config
forced update check, (2) iOS ATT permission request, (3) access token
retrieval/creation, (4) FCM token registration, (5) subscribed clubs sync, (6)
Mixpanel init; update the bootstrap flow invoked by runBootstrapSequence (and
any code gated by shouldBlockSplash/homeWebViewPreloadSettled) to perform the
ATT request as the second step and ensure the UI remains blocked until
runBootstrapSequence completes.

Source: Coding guidelines

// 강제 업데이트가 필요한 경우(또는 체크 전)에는 FCM 권한 프롬프트/핸들러 설정이 뜨지 않도록 비활성화
useFcm(forceUpdateChecked && !forceUpdateRequired && bootstrapSucceeded);
Expand Down Expand Up @@ -204,7 +204,7 @@ function RootLayoutContent() {
forceUpdateRequired,
bootstrapStatus,
pathname,
homeWebViewPreloadStatus,
homeWebViewPreloadSettled,
});
return;
}
Expand All @@ -213,7 +213,7 @@ function RootLayoutContent() {
forceUpdateRequired,
bootstrapStatus,
pathname,
homeWebViewPreloadStatus,
homeWebViewPreloadSettled,
shouldBlockSplash,
]);

Expand All @@ -236,7 +236,7 @@ function RootLayoutContent() {
bootstrapStatus,
forceUpdateRequired,
pathname,
homeWebViewPreloadStatus,
homeWebViewPreloadSettled,
});
}

Expand All @@ -252,7 +252,7 @@ function RootLayoutContent() {
<SubscribedClubsProvider initialClubIds={initialSubscribedClubIds}>
<ThemeProvider value={DefaultTheme}>
<Stack>
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
<Stack.Screen name="index" options={{ headerShown: false }} />
<Stack.Screen name="club/[id]" options={{ headerShown: false }} />
<Stack.Screen name="clubDetail/[id]" options={{ headerShown: false }} />
<Stack.Screen name="webview/[slug]" options={{ headerShown: false }} />
Expand Down
2 changes: 1 addition & 1 deletion app/(tabs)/index.tsx → app/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import React, { Suspense, lazy, useCallback, useState } from 'react';

const LazyHomeScreen = lazy(() => import('@/ui/home/home-screen'));

export default function HomeTab() {
export default function Home() {
const [webViewFailed, setWebViewFailed] = useState(false);
const { markFailed } = useHomeWebViewPreloadContext();

Expand Down
2 changes: 1 addition & 1 deletion app/webview/[slug].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,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 16 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 @@ -83,7 +83,7 @@
if (router.canGoBack()) {
router.back();
} else {
router.push("/(tabs)/more");
router.push("/");
}
};

Expand Down
Loading
Loading