import { getHostRuntime, navigateHostNativePage, } from './host-bridge/hostBridge'; const SUBSCRIBE_RESULT_HASH_KEY = 'wx_subscribe_result'; const MINI_PROGRAM_SUBSCRIBE_MESSAGE_PAGE_URL = '/pages/subscribe-message/index'; const SUBSCRIBE_RESULT_TIMEOUT_MS = 2_500; const SUBSCRIBE_RESULT_RETURN_FALLBACK_MS = 800; function clearSubscribeResultHash() { const rawHash = window.location.hash.replace(/^#/, ''); if (!rawHash.includes(`${SUBSCRIBE_RESULT_HASH_KEY}=`)) { return; } const params = new URLSearchParams(rawHash); params.delete(SUBSCRIBE_RESULT_HASH_KEY); const nextHash = params.toString(); window.history.replaceState( null, '', `${window.location.pathname}${window.location.search}${nextHash ? `#${nextHash}` : ''}`, ); } function readSubscribeResultFromHash() { const value = new URLSearchParams(window.location.hash.replace(/^#/, '')).get( SUBSCRIBE_RESULT_HASH_KEY, ); if (!value) { return null; } clearSubscribeResultHash(); return value; } function waitSubscribeResultFromHash(timeoutMs = SUBSCRIBE_RESULT_TIMEOUT_MS) { const immediateResult = readSubscribeResultFromHash(); if (immediateResult) { return Promise.resolve(immediateResult); } return new Promise((resolve) => { let timer: number | null = null; let resumeFallbackTimer: number | null = null; const cleanup = () => { window.removeEventListener('hashchange', handleHashChange); window.removeEventListener('focus', handleResume); window.removeEventListener('pageshow', handleResume); document.removeEventListener('visibilitychange', handleResume); if (timer !== null) { window.clearTimeout(timer); } if (resumeFallbackTimer !== null) { window.clearTimeout(resumeFallbackTimer); } }; const finish = (result: string | null) => { cleanup(); resolve(result); }; const consume = () => { const result = readSubscribeResultFromHash(); if (result) { finish(result); return true; } return false; }; const handleHashChange = () => { consume(); }; const handleResume = () => { if ( typeof document !== 'undefined' && document.visibilityState === 'hidden' ) { return; } if (consume()) { return; } // 中文注释:订阅授权只影响后续通知,不应阻断生成;原生页返回但没有 hash // 回灌时,按已返回处理,让原本的生成提交流程继续执行。 if (resumeFallbackTimer === null) { resumeFallbackTimer = window.setTimeout( () => finish('returned'), SUBSCRIBE_RESULT_RETURN_FALLBACK_MS, ); } }; window.addEventListener('hashchange', handleHashChange); window.addEventListener('focus', handleResume); window.addEventListener('pageshow', handleResume); document.addEventListener('visibilitychange', handleResume); timer = window.setTimeout(() => finish(null), timeoutMs); }); } export async function requestGenerationResultSubscribePermission() { if ( getHostRuntime().kind !== 'wechat_mini_program' || typeof window === 'undefined' ) { return false; } const requestId = `subscribe_generation_result_${Date.now()}`; let resultPromise: Promise | null = null; try { const navigated = await navigateHostNativePage( `${MINI_PROGRAM_SUBSCRIBE_MESSAGE_PAGE_URL}?requestId=${encodeURIComponent(requestId)}&scene=generation-result`, { errorMessage: 'wechat_js_sdk_unavailable', beforeNavigate() { resultPromise = waitSubscribeResultFromHash(); }, }, ); if (!navigated) { return false; } } catch { return false; } const result = await (resultPromise ?? Promise.resolve(null)); return Boolean(result); }