mirror of
https://github.com/AeThex-Corporation/AeThex-OS.git
synced 2026-04-18 06:17:21 +00:00
The boot screen was rendering as a black screen on web because useNativeFeatures() called Capacitor's Network.getStatus() without checking if the app was running on a native platform. This crashed the entire AeThexOS component during mount. Additionally, tablet testing code in use-platform-layout.ts was mixing viewport width checks (responsive design) with native platform detection, causing layout confusion between web and mobile builds. Changes: - Add isMobile() guards to all Capacitor plugin calls in useNativeFeatures - Remove tablet viewport-width branch from usePlatformLayout (platform detection should not check window.innerWidth) - Rename isMobileDevice() to isSmallViewport() in embed-utils to clarify it's a responsive check, not a platform check - Rename local isMobile state to isNarrowViewport in os.tsx DesktopWidgets to prevent shadowing the platform.ts isMobile() import - Remove dead PlatformAdaptiveExample.tsx (not imported anywhere) - Fix watchLocation TypeScript error (watchId is Promise<string>) - Add web fallbacks for clipboard and browser in useNativeFeatures Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
105 lines
2.9 KiB
TypeScript
105 lines
2.9 KiB
TypeScript
import { useMemo } from 'react';
|
|
import { isMobile, isDesktop, isWeb } from '@/lib/platform';
|
|
|
|
interface LayoutConfig {
|
|
isMobile: boolean;
|
|
isDesktop: boolean;
|
|
isWeb: boolean;
|
|
containerClass: string;
|
|
cardClass: string;
|
|
navClass: string;
|
|
spacing: string;
|
|
fontSize: string;
|
|
}
|
|
|
|
/**
|
|
* Hook to get platform-specific layout configuration
|
|
* Use this to conditionally render or style components based on platform
|
|
*/
|
|
export function usePlatformLayout(): LayoutConfig {
|
|
// Call detection functions once and cache
|
|
const platformCheck = useMemo(() => {
|
|
const mobile = isMobile();
|
|
const desktop = isDesktop();
|
|
const web = isWeb();
|
|
return { isMobile: mobile, isDesktop: desktop, isWeb: web };
|
|
}, []); // Empty array - only check once on mount
|
|
|
|
const config = useMemo((): LayoutConfig => {
|
|
if (platformCheck.isMobile) {
|
|
return {
|
|
...platformCheck,
|
|
// Native mobile app styling (Capacitor/Flutter/Cordova)
|
|
containerClass: 'px-4 py-3 max-w-full',
|
|
cardClass: 'rounded-lg shadow-sm border p-4',
|
|
navClass: 'fixed bottom-0 left-0 right-0 bg-background border-t',
|
|
spacing: 'space-y-3',
|
|
fontSize: 'text-base',
|
|
};
|
|
}
|
|
|
|
if (platformCheck.isDesktop) {
|
|
return {
|
|
...platformCheck,
|
|
// Desktop app styling
|
|
containerClass: 'px-8 py-6 max-w-7xl mx-auto',
|
|
cardClass: 'rounded-xl shadow-lg border p-6',
|
|
navClass: 'fixed top-0 left-0 right-0 bg-background border-b',
|
|
spacing: 'space-y-6',
|
|
fontSize: 'text-sm',
|
|
};
|
|
}
|
|
|
|
// Web browser styling (default)
|
|
return {
|
|
...platformCheck,
|
|
containerClass: 'px-6 py-4 max-w-6xl mx-auto',
|
|
cardClass: 'rounded-xl shadow-md border p-6',
|
|
navClass: 'sticky top-0 bg-background/95 backdrop-blur border-b z-50',
|
|
spacing: 'space-y-4',
|
|
fontSize: 'text-sm',
|
|
};
|
|
}, [platformCheck]);
|
|
|
|
return config;
|
|
}
|
|
|
|
/**
|
|
* Get platform-specific class names
|
|
*/
|
|
export function usePlatformClasses() {
|
|
const layout = usePlatformLayout();
|
|
|
|
return {
|
|
container: layout.containerClass,
|
|
card: layout.cardClass,
|
|
nav: layout.navClass,
|
|
spacing: layout.spacing,
|
|
fontSize: layout.fontSize,
|
|
// Additional utility classes
|
|
button: layout.isMobile ? 'h-12 text-base' : 'h-10 text-sm',
|
|
input: layout.isMobile ? 'h-12 text-base' : 'h-10 text-sm',
|
|
heading: layout.isMobile ? 'text-2xl' : 'text-3xl',
|
|
subheading: layout.isMobile ? 'text-lg' : 'text-xl',
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Conditional rendering based on platform
|
|
*/
|
|
export function PlatformSwitch({
|
|
mobile,
|
|
desktop,
|
|
web,
|
|
fallback
|
|
}: {
|
|
mobile?: React.ReactNode;
|
|
desktop?: React.ReactNode;
|
|
web?: React.ReactNode;
|
|
fallback?: React.ReactNode;
|
|
}) {
|
|
if (isMobile() && mobile) return mobile as React.ReactElement;
|
|
if (isDesktop() && desktop) return desktop as React.ReactElement;
|
|
if (isWeb() && web) return web as React.ReactElement;
|
|
return (fallback || null) as React.ReactElement;
|
|
}
|