From e3666ac0dc609ee37bec449a7bd6540f99d1902c Mon Sep 17 00:00:00 2001 From: Jung Sun A Date: Tue, 3 Nov 2026 15:25:23 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=EC=95=B1=20=EA=B3=B5=EC=9C=A0=20?= =?UTF-8?q?=EC=8B=9C=ED=8A=B8=20=EC=9C=84=EC=8B=9C=20=EA=B2=BD=EB=A1=9C=20?= =?UTF-8?q?/wish=20=EB=A1=9C=20=EA=B0=B1=EC=8B=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/app/app/+native-intent.ts | 2 +- apps/app/components/ShareBottomSheet.tsx | 4 ++-- apps/app/hooks/useShareIntent.ts | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/app/app/+native-intent.ts b/apps/app/app/+native-intent.ts index 18dcc41ac..e06041406 100644 --- a/apps/app/app/+native-intent.ts +++ b/apps/app/app/+native-intent.ts @@ -20,7 +20,7 @@ export function redirectSystemPath({ path }: { path: string; initial: boolean }) if (webFromUrl) return `/?web=${encodeURIComponent(webFromUrl)}`; try { - /** share extension → openHostApp(`/?web=${encodeURIComponent('/archive/wish')}`) */ + /** share extension → openHostApp(`/?web=${encodeURIComponent('/wish')}`) */ const url = new URL(path, 'piki://app'); const web = url.searchParams.get('web'); diff --git a/apps/app/components/ShareBottomSheet.tsx b/apps/app/components/ShareBottomSheet.tsx index 2320d289b..cd7998062 100644 --- a/apps/app/components/ShareBottomSheet.tsx +++ b/apps/app/components/ShareBottomSheet.tsx @@ -59,9 +59,9 @@ function ShareBottomSheetContent({ url, text }: ShareExtensionProps) { openHostApp(`/?web=${encodeURIComponent(webPath)}`); }; - const handleOpenWishlist = () => openHostAppAt('/archive/wish'); + const handleOpenWishlist = () => openHostAppAt('/wish'); const handleOpenLogin = () => openHostAppAt('/login'); - const handleOpenWishEdit = (wishId: number) => openHostAppAt(`/archive/wish/${wishId}`); + const handleOpenWishEdit = (wishId: number) => openHostAppAt(`/wish/${wishId}`); const handleClose = () => { abortRef.current?.abort(); diff --git a/apps/app/hooks/useShareIntent.ts b/apps/app/hooks/useShareIntent.ts index f563c61d0..f9e100860 100644 --- a/apps/app/hooks/useShareIntent.ts +++ b/apps/app/hooks/useShareIntent.ts @@ -5,7 +5,7 @@ import { useCallback, useEffect, useRef } from 'react'; import { toShareIntentPayload } from '@/utils/serializeShareIntent'; import { WebBridge } from '@/utils/webBridge'; -const WISHLIST_PATH = '/archive/wish'; +const WISHLIST_PATH = '/wish'; const isWishlistPath = (uri: URL) => uri.pathname === WISHLIST_PATH; @@ -40,13 +40,13 @@ export const useShareIntent = ({ onChangeWebviewUri, webviewUri }: Props) => { try { const nextUri = new URL(webviewUri); - /** 이미 아카이브 위시 탭: 즉시 전송 */ + /** 이미 위시 목록: 즉시 전송 */ if (isWishlistPath(nextUri)) { sendShareIntent(); return; } - /** 다른 페이지: payload 보관 후 아카이브 위시로 이동 → WEB_REQ_READY 수신 시 전송 */ + /** 다른 페이지: payload 보관 후 위시 목록으로 이동 → WEB_REQ_READY 수신 시 전송 */ nextUri.pathname = WISHLIST_PATH; nextUri.search = ''; nextUri.hash = ''; From d68f72b60fdeebd9b2580d60e81238288371bbcc Mon Sep 17 00:00:00 2001 From: Jung Sun A Date: Tue, 3 Nov 2026 15:25:24 +0900 Subject: [PATCH 2/2] =?UTF-8?q?chore:=20=EA=B3=B5=EC=9C=A0=20=EC=8B=9C?= =?UTF-8?q?=ED=8A=B8=20dev=20=ED=94=84=EB=A6=AC=EB=B7=B0=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/app/app/dev/share-sheet-preview.tsx | 162 ----------------------- apps/app/components/ShareBottomSheet.tsx | 5 +- 2 files changed, 2 insertions(+), 165 deletions(-) delete mode 100644 apps/app/app/dev/share-sheet-preview.tsx diff --git a/apps/app/app/dev/share-sheet-preview.tsx b/apps/app/app/dev/share-sheet-preview.tsx deleted file mode 100644 index ff097edb4..000000000 --- a/apps/app/app/dev/share-sheet-preview.tsx +++ /dev/null @@ -1,162 +0,0 @@ -import { Redirect } from 'expo-router'; -import { useState } from 'react'; -import { Alert, Pressable, ScrollView, StyleSheet, Text, View } from 'react-native'; -import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-context'; - -import { ShareBottomSheetView, type SheetStateT } from '@/components/ShareBottomSheet'; - -/** QA 케이스 매트릭스 — 상태 × 재시도 여부 조합을 전부 나열한다 */ -const PREVIEW_CASES: { label: string; state: SheetStateT; canRetry: boolean }[] = [ - { label: '로딩', state: { status: 'loading' }, canRetry: false }, - { - label: 'READY', - state: { - status: 'ready', - wishId: 1, - item: { - id: 1, - status: 'READY', - name: '힙노틱 벤트라 - 알파인스노우', - price: 849_000, - currency: 'KRW', - imageUrl: 'https://picsum.photos/seed/piki/200', - }, - }, - canRetry: false, - }, - { - label: 'READY (긴 상품명)', - state: { - status: 'ready', - wishId: 1, - item: { - id: 1, - status: 'READY', - name: '[제작/빅사이즈] 이블렛 케이닌 쿨링 리본 뷔스티에 미니원피스 제이스타일 여름 신상 특가', - price: 1_249_000, - currency: 'KRW', - imageUrl: 'https://picsum.photos/seed/piki2/200', - }, - }, - canRetry: false, - }, - { label: 'INCOMPLETE', state: { status: 'incomplete', wishId: 1 }, canRetry: false }, - { label: 'FAILED (파싱)', state: { status: 'failed', wishId: 1 }, canRetry: false }, - { label: '성공 폴백 (상세)', state: { status: 'success', wishId: 1 }, canRetry: false }, - { label: '성공 폴백 (목록)', state: { status: 'success' }, canRetry: false }, - { - label: '로그인 유도', - state: { status: 'error', reason: 'unauthenticated', retryable: false }, - canRetry: false, - }, - { - label: '세션 만료', - state: { status: 'error', reason: 'sessionExpired', retryable: false }, - canRetry: false, - }, - { - label: '네트워크 (재시도 가능)', - state: { status: 'error', reason: 'network', retryable: true }, - canRetry: true, - }, - { - label: '서버 오류 (재시도 소진)', - state: { status: 'error', reason: 'server', retryable: true }, - canRetry: false, - }, - { - label: '링크 없음 (재시도 불가)', - state: { status: 'error', reason: 'server', retryable: false }, - canRetry: false, - }, -]; - -/** 버튼 동작은 실제 이동 대신 목적지를 Alert 로 보여준다 */ -const notify = (action: string) => Alert.alert('dev preview', action); - -export default function ShareSheetPreview() { - if (!__DEV__) return ; - - return ( - - - - ); -} - -function ShareSheetPreviewContent() { - const { top } = useSafeAreaInsets(); - const [caseIndex, setCaseIndex] = useState(0); - const current = PREVIEW_CASES[caseIndex]; - - return ( - - - - {PREVIEW_CASES.map((previewCase, index) => ( - setCaseIndex(index)} - > - - {previewCase.label} - - - ))} - - - - notify('close()')} - onRetry={() => notify('다시 시도 (retryCount + 1)')} - onOpenLogin={() => notify('openHostApp → /login')} - onOpenWishlist={() => notify('openHostApp → /archive/wish (목록)')} - onOpenWishEdit={wishId => notify(`openHostApp → /archive/wish/${wishId} (상세)`)} - /> - - ); -} - -const styles = StyleSheet.create({ - screen: { - flex: 1, - /** 시트 뒤 딤과 구분되도록 시안 목업과 비슷한 밝은 배경 */ - backgroundColor: '#C7CAD1', - }, - picker: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - zIndex: 1, - }, - chips: { - gap: 8, - paddingHorizontal: 12, - paddingBottom: 8, - }, - chip: { - paddingHorizontal: 12, - paddingVertical: 8, - borderRadius: 16, - backgroundColor: '#FFFFFF', - }, - chipActive: { - backgroundColor: '#191B1F', - }, - chipText: { - fontSize: 13, - fontWeight: '600', - color: '#2D3037', - }, - chipTextActive: { - color: '#FFFFFF', - }, -}); diff --git a/apps/app/components/ShareBottomSheet.tsx b/apps/app/components/ShareBottomSheet.tsx index cd7998062..d5dec81e7 100644 --- a/apps/app/components/ShareBottomSheet.tsx +++ b/apps/app/components/ShareBottomSheet.tsx @@ -26,7 +26,7 @@ const LOGIN_REQUIRED_REASONS: ShareFailureReasonT[] = ['unauthenticated', 'sessi /** 재시도는 1회까지. 또 실패하면 확인 버튼만 남긴다. */ const MAX_RETRY_COUNT = 1; -export type SheetStateT = +type SheetStateT = /** POST 진행 중 + 파싱 대기(SSE) — 화면은 동일한 로딩 */ | { status: 'loading' } /** 파싱 결과를 못 받은 폴백 — 저장 성공은 POST 응답으로 이미 확정 */ @@ -199,8 +199,7 @@ type ShareBottomSheetViewProps = { onOpenWishEdit: (wishId: number) => void; }; -/** 상태별 렌더만 담당 — dev 프리뷰(dev/share-sheet-preview)에서 mock 상태로 재사용한다 */ -export function ShareBottomSheetView({ +function ShareBottomSheetView({ state: sheetState, canRetry, onClose,