feat: Show loading spinner on landing page when in PWA mode (#96)
## Summary - Prevents the landing page from briefly flashing before redirecting to `/dashboard` when accessing from an installed PWA - Detects standalone mode synchronously via a `useState` initializer so the spinner renders on the very first paint - Shows a centered loading spinner instead of the full landing page while the redirect happens ## Test plan - [x] Open the app as an installed PWA and verify a spinner shows instead of the landing page before redirecting to dashboard - [x] Open the landing page in a regular browser and verify the full landing page renders normally with no spinner
This commit is contained in:
parent
28f9432af4
commit
21d36bb53b
|
|
@ -1,6 +1,7 @@
|
|||
import EncryptionVideoPlayer from '@/components/landing/encryption-video-player';
|
||||
import Header from '@/components/partials/header';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Spinner } from '@/components/ui/spinner';
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
|
|
@ -28,7 +29,7 @@ import {
|
|||
TrendingUpIcon,
|
||||
ZapIcon,
|
||||
} from 'lucide-react';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
|
||||
const LANDING_IMAGES = [
|
||||
{
|
||||
|
|
@ -160,13 +161,20 @@ export default function Welcome({
|
|||
const planEntries = Object.entries(pricing.plans);
|
||||
const visitTrackedRef = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
const isStandalone =
|
||||
const [isPwa] = useState(() => {
|
||||
if (typeof window === 'undefined') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
window.matchMedia('(display-mode: standalone)').matches ||
|
||||
('standalone' in navigator &&
|
||||
(navigator as Navigator & { standalone: boolean }).standalone);
|
||||
(navigator as Navigator & { standalone: boolean }).standalone)
|
||||
);
|
||||
});
|
||||
|
||||
if (isStandalone) {
|
||||
useEffect(() => {
|
||||
if (isPwa) {
|
||||
router.visit('/dashboard');
|
||||
return;
|
||||
}
|
||||
|
|
@ -178,7 +186,15 @@ export default function Welcome({
|
|||
trackEvent(LEAD_FUNNEL_EVENT_UUID, {
|
||||
step: 'Visit',
|
||||
});
|
||||
}, []);
|
||||
}, [isPwa]);
|
||||
|
||||
if (isPwa) {
|
||||
return (
|
||||
<div className="flex h-screen items-center justify-center">
|
||||
<Spinner className="size-8" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ abstract class TestCase extends BaseTestCase
|
|||
*/
|
||||
protected function setupEncryptionKey($page, ?string $key = null, bool $reload = true): void
|
||||
{
|
||||
$key = $key ?? $this->generateTestEncryptionKey();
|
||||
$key ??= $this->generateTestEncryptionKey();
|
||||
try {
|
||||
$page->script("localStorage.setItem('encryption_key', ".json_encode($key).')');
|
||||
} catch (\Exception) {
|
||||
|
|
@ -39,7 +39,7 @@ abstract class TestCase extends BaseTestCase
|
|||
}
|
||||
if ($reload) {
|
||||
$currentUrl = $page->url();
|
||||
$page->navigate($currentUrl)->wait(1);
|
||||
$page->navigate($currentUrl)->wait(1.5);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -48,7 +48,7 @@ abstract class TestCase extends BaseTestCase
|
|||
*/
|
||||
protected function visitWithEncryptionKey(string $url, ?string $key = null)
|
||||
{
|
||||
$key = $key ?? $this->generateTestEncryptionKey();
|
||||
$key ??= $this->generateTestEncryptionKey();
|
||||
$page = visit($url);
|
||||
$page->script("localStorage.setItem('encryption_key', ".json_encode($key).')');
|
||||
$page->navigate($url)->wait(1);
|
||||
|
|
|
|||
Loading…
Reference in New Issue