You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
200 lines
7.1 KiB
200 lines
7.1 KiB
import type { Metadata } from "next";
|
|
import { Amiri } from "next/font/google";
|
|
import localFont from "next/font/local";
|
|
import Providers from "./providers";
|
|
import "./globals.css";
|
|
import DevClickToComponent from "@/components/dev/dev-click-to-component";
|
|
|
|
const faminela = localFont({
|
|
src: "../../public/fonts/Faminela/Faminela.otf",
|
|
variable: "--font-faminela-local",
|
|
display: "swap",
|
|
preload: true,
|
|
fallback: ["Arial", "sans-serif"],
|
|
});
|
|
|
|
const amiri = Amiri({
|
|
weight: ["400", "700"],
|
|
subsets: ["arabic"],
|
|
variable: "--font-amiri",
|
|
display: "swap",
|
|
preload: true,
|
|
fallback: ["Arial", "sans-serif"],
|
|
});
|
|
|
|
export const metadata: Metadata = {
|
|
title: "Habib Marriage",
|
|
description: "Islamic Marriage Platform",
|
|
viewport: {
|
|
width: "device-width",
|
|
initialScale: 1,
|
|
maximumScale: 1,
|
|
},
|
|
themeColor: "#ffffff",
|
|
};
|
|
|
|
export default function RootLayout({
|
|
children,
|
|
}: Readonly<{
|
|
children: React.ReactNode;
|
|
}>) {
|
|
return (
|
|
<html lang="en">
|
|
<head>
|
|
<link rel="preconnect" href="https://habibapp.com" />
|
|
<link rel="dns-prefetch" href="https://habibapp.com" />
|
|
<script
|
|
dangerouslySetInnerHTML={{
|
|
__html: `
|
|
if (typeof window !== 'undefined') {
|
|
var flutterResponseListeners = window.__flutterResponseListeners || [];
|
|
window.__flutterResponseListeners = flutterResponseListeners;
|
|
|
|
window.addFlutterResponseListener = window.addFlutterResponseListener || function(listener) {
|
|
flutterResponseListeners.push(listener);
|
|
|
|
return function() {
|
|
var index = flutterResponseListeners.indexOf(listener);
|
|
if (index >= 0) {
|
|
flutterResponseListeners.splice(index, 1);
|
|
}
|
|
};
|
|
};
|
|
|
|
window.onFlutterResponse = function(event) {
|
|
flutterResponseListeners.slice().forEach(function(listener) {
|
|
try {
|
|
listener(event);
|
|
} catch (error) {
|
|
console.error('Flutter response listener failed', error);
|
|
}
|
|
});
|
|
};
|
|
|
|
var HABIB_TOKEN_COOKIE = 'HABIB_TOKEN';
|
|
var HABIB_COINS_COOKIE = 'HABIB_COINS';
|
|
var HABIB_COOKIE_MAX_AGE = 60 * 60 * 24 * 30;
|
|
|
|
function writeCookie(name, value) {
|
|
if (value === undefined || value === null || value === '') return;
|
|
|
|
var secure = window.location.protocol === 'https:';
|
|
var cookie = name + '=' + encodeURIComponent(String(value)) + '; Path=/; Max-Age=' + HABIB_COOKIE_MAX_AGE + '; SameSite=Lax';
|
|
|
|
if (secure) {
|
|
cookie += '; Secure';
|
|
}
|
|
|
|
document.cookie = cookie;
|
|
}
|
|
|
|
function readCookie(name) {
|
|
var cookies = document.cookie ? document.cookie.split('; ') : [];
|
|
|
|
for (var i = 0; i < cookies.length; i += 1) {
|
|
var parts = cookies[i].split('=');
|
|
if (parts[0] === name) {
|
|
return decodeURIComponent(parts.slice(1).join('='));
|
|
}
|
|
}
|
|
|
|
return '';
|
|
}
|
|
|
|
if (!Object.getOwnPropertyDescriptor(window, 'HABIB_TOKEN')) {
|
|
Object.defineProperty(window, 'HABIB_TOKEN', {
|
|
configurable: true,
|
|
set: function(value) {
|
|
this._habib_token = value;
|
|
if (value) {
|
|
writeCookie(HABIB_TOKEN_COOKIE, value);
|
|
sessionStorage.setItem(HABIB_TOKEN_COOKIE, value);
|
|
}
|
|
},
|
|
get: function() {
|
|
return this._habib_token || readCookie(HABIB_TOKEN_COOKIE) || sessionStorage.getItem(HABIB_TOKEN_COOKIE);
|
|
}
|
|
});
|
|
}
|
|
|
|
if (!Object.getOwnPropertyDescriptor(window, 'HABIB_COINS')) {
|
|
Object.defineProperty(window, 'HABIB_COINS', {
|
|
configurable: true,
|
|
set: function(value) {
|
|
this._habib_coins = value;
|
|
if (value !== undefined && value !== null && value !== '') {
|
|
writeCookie(HABIB_COINS_COOKIE, value);
|
|
sessionStorage.setItem(HABIB_COINS_COOKIE, String(value));
|
|
}
|
|
},
|
|
get: function() {
|
|
var cookieValue = readCookie(HABIB_COINS_COOKIE);
|
|
return this._habib_coins || parseInt(cookieValue || sessionStorage.getItem(HABIB_COINS_COOKIE) || '0');
|
|
}
|
|
});
|
|
}
|
|
|
|
// Performance monitoring
|
|
window.addEventListener('load', function() {
|
|
var perfData = performance.getEntriesByType('navigation')[0];
|
|
console.log('⏱️ Load time:', Math.round(perfData.loadEventEnd - perfData.fetchStart), 'ms');
|
|
});
|
|
}
|
|
`,
|
|
}}
|
|
/>
|
|
<script
|
|
dangerouslySetInnerHTML={{
|
|
__html: `
|
|
if (typeof window !== 'undefined') {
|
|
var REDIRECT_SESSION_KEY = 'redirect';
|
|
|
|
function renderRedirectDebug() {
|
|
var badge = document.getElementById('redirect-debug-badge');
|
|
if (!badge) {
|
|
return;
|
|
}
|
|
|
|
var redirectValue = window.sessionStorage.getItem(REDIRECT_SESSION_KEY);
|
|
badge.textContent =
|
|
redirectValue === null
|
|
? 'redirect: missing'
|
|
: 'redirect: ' + redirectValue;
|
|
}
|
|
|
|
var originalSetItem = window.sessionStorage.setItem.bind(window.sessionStorage);
|
|
var originalRemoveItem = window.sessionStorage.removeItem.bind(window.sessionStorage);
|
|
|
|
window.sessionStorage.setItem = function(key, value) {
|
|
originalSetItem(key, value);
|
|
renderRedirectDebug();
|
|
};
|
|
|
|
window.sessionStorage.removeItem = function(key) {
|
|
originalRemoveItem(key);
|
|
renderRedirectDebug();
|
|
};
|
|
|
|
window.addEventListener('load', renderRedirectDebug);
|
|
window.addEventListener('pageshow', renderRedirectDebug);
|
|
window.setTimeout(renderRedirectDebug, 0);
|
|
}
|
|
`,
|
|
}}
|
|
/>
|
|
</head>
|
|
<body className={`${faminela.variable} ${amiri.variable}`}>
|
|
<Providers>
|
|
<div className="app-shell">{children}</div>
|
|
</Providers>
|
|
<div
|
|
id="redirect-debug-badge"
|
|
className="fixed bottom-3 right-3 z-[9999] rounded bg-black/75 px-2 py-1 text-xs text-white"
|
|
/>
|
|
{process.env.NODE_ENV === "development" ? (
|
|
<DevClickToComponent />
|
|
) : null}
|
|
</body>
|
|
</html>
|
|
);
|
|
}
|