diff --git a/next.config.ts b/next.config.ts index 8439580..67fa43e 100644 --- a/next.config.ts +++ b/next.config.ts @@ -86,12 +86,20 @@ const nextConfig: NextConfig = { ], }, { - // Application HTML shell – App Shell + Stale-While-Revalidate pattern for instant WebView rendering + // Application HTML pages – must never serve stale HTML so hashed JS chunks match current deployment source: "/:path((?!api/|_next/|fonts/|assets/).*)", headers: [ { key: "Cache-Control", - value: "public, max-age=0, stale-while-revalidate=86400", + value: "no-store, no-cache, must-revalidate, max-age=0", + }, + { + key: "Pragma", + value: "no-cache", + }, + { + key: "Expires", + value: "0", }, ], }, diff --git a/src/app/globals.css b/src/app/globals.css index 4f8f63c..02514ce 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -265,6 +265,8 @@ a, label, [role="button"] { touch-action: manipulation; + -webkit-tap-highlight-color: transparent; + pointer-events: auto; } input, diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 2752b60..04c0a99 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -304,9 +304,10 @@ export default async function RootLayout({ document.cookie = 'habib_language=' + encodeURIComponent(String(code)) + '; Path=/; Max-Age=31536000; SameSite=Lax' + secure; root.lang = String(code); root.dir = (locale.isRTL || locale.isRtl || locale.is_rtl) ? 'rtl' : 'ltr'; + var knownLocales = ['fa', 'ar', 'en', 'ur', 'tr', 'ru', 'fr', 'es', 'de', 'id', 'bn', 'hi', 'pt', 'ha', 'sw', 'uz', 'az', 'tg', 'ks', 'zh', 'da', 'he', 'gu', 'ul']; var segments = window.location.pathname.split('/'); var currentCode = segments[1]; - if (currentCode && currentCode !== String(code)) { + if (currentCode && knownLocales.indexOf(currentCode) !== -1 && currentCode !== String(code)) { root.dataset.webBootstrap = 'pending'; segments[1] = String(code); window.location.replace(segments.join('/') + window.location.search + window.location.hash); @@ -317,6 +318,28 @@ export default async function RootLayout({ window.dispatchEvent(new CustomEvent('habib:bootstrap-ready', { detail: config })); } + // Global Error Forwarding to Flutter Native Log Channel + function forwardErrorToFlutter(type, err) { + try { + var message = '[WEB_ERROR] ' + type + ': ' + (err && (err.stack || err.message || String(err)) || 'Unknown error'); + console.error(message); + if (window.HabibApp && window.HabibApp.postMessage) { + window.HabibApp.postMessage(JSON.stringify({ + action: 'client_log', + message: message + })); + } + } catch (e) {} + } + + window.addEventListener('error', function(event) { + forwardErrorToFlutter('Runtime Error', event.error || event.message); + }); + + window.addEventListener('unhandledrejection', function(event) { + forwardErrorToFlutter('Unhandled Rejection', event.reason); + }); + if (window.__HABIB_BOOTSTRAP__) { apply(window.__HABIB_BOOTSTRAP__); } @@ -415,7 +438,7 @@ export default async function RootLayout({ var msg = '[WEB_DEEP_LIFECYCLE] [' + Date.now() + '] Event: ' + name + ' | visibility: ' + document.visibilityState + ' | hasFocus: ' + document.hasFocus() + ' | bodyBg: ' + bodyBg + ' | htmlBg: ' + htmlBg + (detail ? ' | ' + JSON.stringify(detail) : ''); console.log(msg); if (window.HabibApp && window.HabibApp.postMessage) { - window.HabibApp.postMessage(JSON.stringify({ action: 'debug_log', message: msg })); + window.HabibApp.postMessage(JSON.stringify({ action: 'client_log', message: msg })); } } catch (e) {} } diff --git a/src/app/request-accepted/request-accepted-client.tsx b/src/app/request-accepted/request-accepted-client.tsx index 4133fb2..dd1e423 100644 --- a/src/app/request-accepted/request-accepted-client.tsx +++ b/src/app/request-accepted/request-accepted-client.tsx @@ -972,25 +972,7 @@ export default function RequestAcceptedClient() { onGetAdvisor={openAdvisors} /> -
-
-
- lock -

- {t["Profile is locked"]} -

-
-
-