From 2e576984be3b3c3f525ca24ade90308f74ca6d93 Mon Sep 17 00:00:00 2001 From: Ahreum02 <126854208+Ahreum02@users.noreply.github.com> Date: Sun, 3 May 2026 11:42:23 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=EC=8A=A4=EC=BA=94=20=EB=82=B4?= =?UTF-8?q?=EC=97=AD=20=ED=81=B4=EB=A6=AD=20=EC=8B=9C=20=EC=83=81=EC=84=B8?= =?UTF-8?q?=20=EB=B3=B4=EA=B3=A0=EC=84=9C=20=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Loading/hooks/useLoadingPage.ts | 13 ++++-- src/pages/QRScan/hooks/useQRScanPage.ts | 25 ++++++++--- src/pages/ScanList/ScanListPage.tsx | 26 +++++------ .../scan-session/scanClassification.test.ts | 26 +++++++++++ .../lib/scan-session/scanClassification.ts | 43 +++++++++++++++++++ src/shared/store/scanSessionStore.test.ts | 16 +++++++ src/shared/store/scanSessionStore.ts | 28 ++++++++---- 7 files changed, 143 insertions(+), 34 deletions(-) create mode 100644 src/shared/lib/scan-session/scanClassification.test.ts create mode 100644 src/shared/lib/scan-session/scanClassification.ts diff --git a/src/pages/Loading/hooks/useLoadingPage.ts b/src/pages/Loading/hooks/useLoadingPage.ts index df02e41..aab3336 100644 --- a/src/pages/Loading/hooks/useLoadingPage.ts +++ b/src/pages/Loading/hooks/useLoadingPage.ts @@ -7,6 +7,7 @@ import { pickString } from '@/shared/api/responseAccess/payloadAccess'; import { resolveResultToneFromSources } from '@/shared/api/risk/resolveResultTone'; import { mapSseStepId } from '@/shared/api/sse/sseStepMapper'; import { ensureScanDetail } from '@/shared/lib/scan-session/ensureScanDetail'; +import { isWebScanTarget } from '@/shared/lib/scan-session/scanClassification'; import { useScanSubscription } from '@/shared/lib/sse/useScanSubscription'; import { useGuestStore } from '@/shared/store/guestStore'; import { useScanProgressStore } from '@/shared/store/scanProgressStore'; @@ -32,10 +33,14 @@ const DEFAULT_LOADING_PAGE_DATA: LoadingPageData = { function openResultRouteForCurrentSession() { const session = getScanSessionSnapshot(); + const currentTargetUrl = session.decodedUrl ?? session.historySelection?.url ?? null; if ( - session.isUrl === false || - (session.schemeType && session.schemeType.trim().toUpperCase() !== 'WEB') + !isWebScanTarget({ + isUrl: session.isUrl, + schemeType: session.schemeType, + url: currentTargetUrl, + }) ) { window.location.assign('/result/non-url'); return; @@ -53,8 +58,8 @@ function openResultRouteForCurrentSession() { } as const; const route = routeByRiskLevel[riskLevel]; - if (session.decodedUrl) { - window.location.assign(`${route}?url=${encodeURIComponent(session.decodedUrl)}`); + if (currentTargetUrl) { + window.location.assign(`${route}?url=${encodeURIComponent(currentTargetUrl)}`); return; } diff --git a/src/pages/QRScan/hooks/useQRScanPage.ts b/src/pages/QRScan/hooks/useQRScanPage.ts index 21bc14f..2018025 100644 --- a/src/pages/QRScan/hooks/useQRScanPage.ts +++ b/src/pages/QRScan/hooks/useQRScanPage.ts @@ -5,6 +5,7 @@ import { App } from 'antd'; import { useCallback, useEffect, useRef, useState } from 'react'; import { showApiError } from '@/shared/lib/feedback/showApiError'; +import { isWebScanTarget } from '@/shared/lib/scan-session/scanClassification'; import { useScanProgressStore } from '@/shared/store/scanProgressStore'; import { useScanSessionStore } from '@/shared/store/scanSessionStore'; @@ -141,18 +142,30 @@ function isNonWebScanResponse(scanResponse: Record): boolean { typeof scanResponse.schemeType === 'string' ? scanResponse.schemeType : scanResponse.scheme_type; + const targetValue = + typeof scanResponse.typeInfo === 'string' + ? scanResponse.typeInfo + : typeof scanResponse.type_info === 'string' + ? scanResponse.type_info + : typeof scanResponse.decodedUrl === 'string' + ? scanResponse.decodedUrl + : typeof scanResponse.decoded_url === 'string' + ? scanResponse.decoded_url + : typeof scanResponse.url === 'string' + ? scanResponse.url + : null; const schemeType = typeof rawSchemeType === 'string' ? rawSchemeType.trim().toUpperCase() : ''; const rawIsUrl = scanResponse.isUrl !== undefined ? scanResponse.isUrl : scanResponse.is_url; - if (typeof rawIsUrl === 'boolean') { - return rawIsUrl === false; - } - - return schemeType.length > 0 && schemeType !== 'WEB'; + return !isWebScanTarget({ + isUrl: typeof rawIsUrl === 'boolean' ? rawIsUrl : null, + schemeType, + url: targetValue, + }); } function isWebHistoryItem(item: ScanHistoryItem): boolean { - return item.isUrl !== false && item.schemeType?.trim().toUpperCase() === 'WEB'; + return isWebScanTarget(item); } function openResultPage(route: ResultRoute, url: string) { diff --git a/src/pages/ScanList/ScanListPage.tsx b/src/pages/ScanList/ScanListPage.tsx index b5309ac..505141f 100644 --- a/src/pages/ScanList/ScanListPage.tsx +++ b/src/pages/ScanList/ScanListPage.tsx @@ -1,6 +1,7 @@ import { Link } from '@tanstack/react-router'; import { qrIconByTone } from '@/shared/icon/resultIcons'; +import { isWebScanTarget } from '@/shared/lib/scan-session/scanClassification'; import AppHeader from '@/shared/ui/app-header'; import { useScanListPage } from './hooks/useScanListPage'; @@ -8,15 +9,8 @@ import * as styles from './styles/scanListPage.css'; import type { ScanListStatus } from './types/scanListPage.types'; -type ResultRoute = '/result/critical' | '/result/non-url' | '/result/safe' | '/result/warning'; - const nonUrlResultRoute = '/result/non-url'; - -const resultRouteByStatus: Record = { - safe: '/result/safe', - warning: '/result/warning', - critical: '/result/critical', -}; +const reportRoute = '/report'; const statusLabelByTone: Record = { safe: '안전', @@ -91,8 +85,12 @@ function StatusBadgeIcon({ tone }: { tone: ScanListStatus }) { ); } -function isWebScanListItem(item: { isUrl: boolean | null; schemeType: string | null }): boolean { - return item.isUrl !== false && item.schemeType?.trim().toUpperCase() === 'WEB'; +function isWebScanListItem(item: { + isUrl: boolean | null; + schemeType: string | null; + url: string; +}): boolean { + return isWebScanTarget(item); } export default function ScanListPage() { @@ -115,9 +113,7 @@ export default function ScanListPage() { ) : (
    {scanListPageData.items.map((item) => { - const resultRoute = isWebScanListItem(item) - ? resultRouteByStatus[item.status] - : nonUrlResultRoute; + const nextRoute = isWebScanListItem(item) ? reportRoute : nonUrlResultRoute; return (
  • @@ -126,8 +122,8 @@ export default function ScanListPage() { onClick={() => { handleSelectScanResult(item); }} - search={resultRoute === nonUrlResultRoute ? {} : { url: item.url }} - to={resultRoute} + search={nextRoute === reportRoute ? { url: item.url } : {}} + to={nextRoute} >