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; } | { type: 'process'; url: string; description?: string | null; }; export type MobileShellLoadFailure = { type: 'native' | 'http' | 'process'; url: string; title: string; detail: string; retryLabel: string; }; 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; } } function sanitizeLoadFailureUrl(rawUrl: string, allowedOrigin: string) { const url = new URL(rawUrl, allowedOrigin); return `${url.origin}${url.pathname}`; } export function normalizeMobileShellLoadFailure( input: MobileShellLoadFailureInput, allowedOrigin: string, currentPageUrl?: string | null, ): MobileShellLoadFailure | null { if (!shouldShowLoadFailure(input.url, allowedOrigin, currentPageUrl)) { return null; } const url = sanitizeLoadFailureUrl(input.url, allowedOrigin); if (input.type === 'http') { const statusCode = Number.isInteger(input.statusCode) && input.statusCode ? input.statusCode : null; return { type: 'http', url, title: statusCode ? `加载失败 ${statusCode}` : '加载失败', detail: '服务器暂时没有返回可用页面', retryLabel: '重试', }; } if (input.type === 'process') { return { type: 'process', url, title: '页面已停止', detail: '当前页面连续恢复失败', retryLabel: '重试', }; } return { type: 'native', url, title: '网络不可用', detail: '当前页面没有加载成功', retryLabel: '重试', }; }