diff --git a/brand/LAUNCH-PROGRESS.md b/brand/LAUNCH-PROGRESS.md index 3f60bbf..72bf3a4 100644 --- a/brand/LAUNCH-PROGRESS.md +++ b/brand/LAUNCH-PROGRESS.md @@ -87,11 +87,14 @@ ## πŸ’‘ μΆœμ‹œ μ „ 닀듬기 후보 (λŒ€κΈ° μ‹œκ°„ ν™œμš©, 선택) μ‹ κ·œ(λΉˆμ†) μœ μ € κ²½ν—˜ μœ„μ£Ό β€” μ €μœ„ν—˜Β·κ³ νš¨μœ¨ 순: -1. **빈 μƒνƒœ β†’ 행동 μœ λ„** (첫 λ‚΄μ—­/κ³„μ’Œ μΆ”κ°€ CTA) ⭐ μž„νŒ©νŠΈ 高/λ…Έλ ₯ 低 -2. **μ˜€ν”„λΌμΈΒ·λ„€νŠΈμ›Œν¬ 였λ₯˜ UX 견고화** (폐쇄 ν…ŒμŠ€νŠΈ λŒ€λΉ„) -3. 첫 μ‹€ν–‰ μ˜¨λ³΄λ”©(μ‹œμž‘ν•˜κΈ° μΉ΄λ“œ) -4. Play 인앱 리뷰 μš”μ²­ -5. (선택) μ•± 잠금(PIN/생체) β€” λ§€λ‹ˆνŽ˜μŠ€νŠΈμ— USE_BIOMETRIC κΆŒν•œ 쑴재, κ΅¬ν˜„ μ—¬λΆ€ 미확인 +1. βœ… **빈 μƒνƒœ β†’ 행동 μœ λ„** (μ™„λ£Œ) β€” ν™ˆ 'μ‹œμž‘ν•˜κΈ°' μΉ΄λ“œ + 가계뢀내역/κ³„μ’Œ 빈 μƒνƒœ CTA. 데이터 0 κ³„μ •μ—μ„œλ§Œ λ…ΈμΆœ +2. βœ… **μ˜€ν”„λΌμΈΒ·λ„€νŠΈμ›Œν¬ 였λ₯˜ λ°°λ„ˆ** (μ™„λ£Œ) β€” http net:error 이벀트 + App.vue 상단 κ³ μ • λ°°λ„ˆ(μ˜€ν”„λΌμΈ/μ„œλ²„μ—°κ²°μ‹€νŒ¨, μƒˆλ‘œκ³ μΉ¨ λ²„νŠΌ) +3. βœ… **μ•± 잠금(PIN)** (μ™„λ£Œ) β€” 자체 κ΅¬ν˜„(ν•΄μ‹œ μ €μž₯, κΈ°λ³Έ OFF), μ‹œμž‘Β·λ³΅κ·€ μ‹œ 잠금, μ„€μ • ν† κΈ€+PINμ„€μ • λͺ¨λ‹¬, 'PIN λΆ„μ‹€β†’λ‘œκ·Έμ•„μ›ƒ' κ°‡νž˜ λ°©μ§€. μƒμ²΄λŠ” μΆ”ν›„(λ„€μ΄ν‹°λΈŒ ν”ŒλŸ¬κ·ΈμΈ ν•„μš”) +4. βœ… **μ „μ—­ μ—λŸ¬ 폴백** (μ™„λ£Œ) β€” errorHandler + onErrorCaptured β†’ 흰 ν™”λ©΄ λŒ€μ‹  '문제 λ°œμƒ + μƒˆλ‘œκ³ μΉ¨' +5. βœ… **μ•ˆλ“œλ‘œμ΄λ“œ λ’€λ‘œκ°€κΈ° κ°œμ„ ** (μ™„λ£Œ) β€” μ˜€λ²„λ ˆμ΄ λ‹«κΈ° μš°μ„  β†’ ν™”λ©΄ λ’€λ‘œ β†’ μ΅œμƒμœ„ 'ν•œ 번 더 λˆ„λ₯΄λ©΄ μ’…λ£Œ' ν† μŠ€νŠΈ +6. 첫 μ‹€ν–‰ μ˜¨λ³΄λ”©(1번과 쀑볡이라 보λ₯˜) / Play 인앱 리뷰(ν”ŒλŸ¬κ·ΈμΈ ν•„μš”, μΆœμ‹œ ν›„) / 생체인증(μΆœμ‹œ ν›„) + +> ⚠️ μ•± μž κΈˆμ€ μ‹œμž‘ 흐름을 κ°€λ‘œμ±„λŠ” κΈ°λŠ₯이라 **μ‹€κΈ°κΈ° 검증 ꢌμž₯**: μ„€μ •β†’μ•±μž κΈˆ ONβ†’PIN μ„€μ •β†’λ°±κ·ΈλΌμš΄λ“œ ν›„ λ³΅κ·€β†’μž κΈˆν™”λ©΄ 확인→PIN ν•΄μ œ. (ν˜„μž¬ μ„€μΉ˜ APKμ—” 미반영 β€” μž¬λΉŒλ“œΒ·μž¬μ„€μΉ˜ ν•„μš”) --- diff --git a/src/capacitor.js b/src/capacitor.js index 0605ad8..c01203c 100644 --- a/src/capacitor.js +++ b/src/capacitor.js @@ -1,37 +1,13 @@ // Capacitor λ„€μ΄ν‹°λΈŒ(μ•ˆλ“œλ‘œμ΄λ“œ) 톡합. μ›Ήμ—μ„œλŠ” no-op. import { Capacitor } from '@capacitor/core' import { App as CapApp } from '@capacitor/app' -import { useUiStore } from '@/stores/ui' -import { appLock } from '@/composables/appLock' +import { handleBack } from '@/composables/appBack' export function setupCapacitor(router) { if (!Capacitor.isNativePlatform()) return - const ui = useUiStore() - let exitArmed = false - let exitTimer = null - - // μ•ˆλ“œλ‘œμ΄λ“œ ν•˜λ“œμ›¨μ–΄ λ’€λ‘œκ°€κΈ° μš°μ„ μˆœμœ„: - // 1) 잠금 화면이면 우회 λΆˆκ°€ β†’ μ’…λ£Œ - // 2) μ—΄λ¦° μ „μ—­ μ˜€λ²„λ ˆμ΄(νšŒμ›κ°€μž…/둜그인/λΉ„λ²ˆ/μ‚¬μ΄λ“œλ°”) λ‹«κΈ° - // 3) ν™”λ©΄ λ’€λ‘œ - // 4) μ΅œμƒμœ„μ—μ„œ ν•œ 번 더 λˆ„λ₯΄λ©΄ μ’…λ£Œ(μ‹€μˆ˜ μ’…λ£Œ λ°©μ§€) - CapApp.addListener('backButton', ({ canGoBack }) => { - if (appLock.state.locked) { CapApp.exitApp(); return } - - if (ui.signupOpen) { ui.closeSignup(); return } - if (ui.loginOpen) { ui.closeLogin(); return } - if (ui.passwordOpen) { ui.closePassword(); return } - if (ui.sidebarOpen) { ui.closeSidebar(); return } - - if (canGoBack && window.history.length > 1) { router.back(); return } - - if (exitArmed) { CapApp.exitApp(); return } - exitArmed = true - window.dispatchEvent(new CustomEvent('app:toast', { detail: 'ν•œ 번 더 λˆ„λ₯΄λ©΄ μ’…λ£Œλ©λ‹ˆλ‹€' })) - clearTimeout(exitTimer) - exitTimer = setTimeout(() => { exitArmed = false }, 2000) - }) + // μ•ˆλ“œλ‘œμ΄λ“œ ν•˜λ“œμ›¨μ–΄ λ’€λ‘œκ°€κΈ° β†’ ν•˜λ‹¨ λ‚΄λΉ„ λ’€λ‘œ λ²„νŠΌκ³Ό λ™μΌν•œ 톡합 처리 + CapApp.addListener('backButton', () => handleBack(router)) // λ„€μ΄ν‹°λΈŒ ν‘œμ‹œμš© 클래슀 (safe-area λ“± μŠ€νƒ€μΌ λΆ„κΈ°) document.documentElement.classList.add('is-native') diff --git a/src/components/layout/AppBottomNav.vue b/src/components/layout/AppBottomNav.vue index b014907..862b685 100644 --- a/src/components/layout/AppBottomNav.vue +++ b/src/components/layout/AppBottomNav.vue @@ -1,6 +1,7 @@