import { shouldOpenInMobileShellWebView } from './navigation'; export type MobileShellLoadFailureInput = | { type: 'native'; url: string; code?: number | null; description?: string | null; } | { type: 'http'; url: string; statusCode?: number | null; description?: string | null; }; export type MobileShellLoadFailure = { type: 'native' | 'http'; url: string; title: string; detail: string; retryLabel: string; }; function normalizeDescription(value: string | null | undefined) { const normalized = value?.replace(/\s+/g, ' ').trim(); if (!normalized) { return null; } return normalized.length > 96 ? `${normalized.slice(0, 96).trim()}...` : normalized; } function sameDocumentUrl( left: URL, right: string | null | undefined, allowedOrigin: string, ) { if (!right) { return true; } try { const current = new URL(right, allowedOrigin); return ( left.origin === current.origin && left.pathname === current.pathname && left.search === current.search ); } catch { return false; } } function shouldShowLoadFailure( rawUrl: string, allowedOrigin: string, currentPageUrl?: string | null, ) { if (!shouldOpenInMobileShellWebView(rawUrl, allowedOrigin)) { return false; } try { const url = new URL(rawUrl, allowedOrigin); return ( url.origin === allowedOrigin && url.pathname !== '/favicon.ico' && sameDocumentUrl(url, currentPageUrl, allowedOrigin) ); } catch { return false; } } export function normalizeMobileShellLoadFailure( input: MobileShellLoadFailureInput, allowedOrigin: string, currentPageUrl?: string | null, ): MobileShellLoadFailure | null { if (!shouldShowLoadFailure(input.url, allowedOrigin, currentPageUrl)) { return null; } const url = new URL(input.url, allowedOrigin).toString(); const description = normalizeDescription(input.description); if (input.type === 'http') { const statusCode = Number.isInteger(input.statusCode) && input.statusCode ? input.statusCode : null; return { type: 'http', url, title: statusCode ? `加载失败 ${statusCode}` : '加载失败', detail: description ?? '服务器暂时没有返回可用页面', retryLabel: '重试', }; } return { type: 'native', url, title: '网络不可用', detail: description ?? '当前页面没有加载成功', retryLabel: '重试', }; }