From cc051a1a5e7aa1f7686824aabb376a5aa06c880f Mon Sep 17 00:00:00 2001 From: nimrodkra Date: Thu, 5 Feb 2026 08:03:17 +0000 Subject: [PATCH 1/3] feat(mobile): add delightful loading screen for mobile users Add MobileAppLoader component with floating logo animation and spinner for a more polished loading experience on mobile devices. The component displays during app initialization instead of showing a blank screen. Changes: - Create MobileAppLoader component with float-animation utility - Integrate into MainLayout for mobile-only loading state Co-Authored-By: Claude Opus 4.5 --- packages/shared/src/components/MainLayout.tsx | 5 ++++ .../shared/src/components/MobileAppLoader.tsx | 27 +++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 packages/shared/src/components/MobileAppLoader.tsx diff --git a/packages/shared/src/components/MainLayout.tsx b/packages/shared/src/components/MainLayout.tsx index 7c130bee0e..4db9ab7656 100644 --- a/packages/shared/src/components/MainLayout.tsx +++ b/packages/shared/src/components/MainLayout.tsx @@ -4,6 +4,7 @@ import classNames from 'classnames'; import { useRouter } from 'next/router'; import dynamic from 'next/dynamic'; import PromotionalBanner from './PromotionalBanner'; +import { MobileAppLoader } from './MobileAppLoader'; import useSidebarRendered from '../hooks/useSidebarRendered'; import { useLogContext } from '../contexts/LogContext'; import SettingsContext from '../contexts/SettingsContext'; @@ -91,6 +92,7 @@ function MainLayoutComponent({ const { isCustomFeed } = useFeedName({ feedName }); const { plusEntryAnnouncementBar } = usePlusEntry(); const isLaptopXL = useViewSize(ViewSize.LaptopXL); + const isMobile = useViewSize(ViewSize.MobileL); const { screenCenteredOnMobileLayout } = useFeedLayout(); const { isNotificationsReady, unreadCount } = useNotificationContext(); useAuthErrors(); @@ -165,6 +167,9 @@ function MainLayoutComponent({ (!isPageReady && isPageApplicableForOnboarding) || shouldRedirectOnboarding ) { + if (isMobile) { + return ; + } return null; } diff --git a/packages/shared/src/components/MobileAppLoader.tsx b/packages/shared/src/components/MobileAppLoader.tsx new file mode 100644 index 0000000000..9d14ee5de5 --- /dev/null +++ b/packages/shared/src/components/MobileAppLoader.tsx @@ -0,0 +1,27 @@ +import type { ReactElement } from 'react'; +import React from 'react'; +import classNames from 'classnames'; +import LogoIcon from '../svg/LogoIcon'; +import { Loader } from './Loader'; + +interface MobileAppLoaderProps { + className?: string; +} + +export function MobileAppLoader({ + className, +}: MobileAppLoaderProps): ReactElement { + return ( +
+
+ +
+ +
+ ); +} From c5fd48e60176f84e745af11a8d253298a50e051d Mon Sep 17 00:00:00 2001 From: Nimrod Kramer <41470823+nimrodkra@users.noreply.github.com> Date: Thu, 5 Feb 2026 10:26:23 +0200 Subject: [PATCH 2/3] refactor(mobile): show loading screen only in PWA with proper app icon - Change detection from viewport-based to isPWA() for PWA-only display - Use cloudinary app icon (cloudinaryAppIconMain) for consistent branding - Apply iOS-style rounded corners (22%) to the square icon Co-authored-by: Cursor --- packages/shared/src/components/MainLayout.tsx | 4 ++-- packages/shared/src/components/MobileAppLoader.tsx | 14 ++++++++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/shared/src/components/MainLayout.tsx b/packages/shared/src/components/MainLayout.tsx index 4db9ab7656..83bce434b9 100644 --- a/packages/shared/src/components/MainLayout.tsx +++ b/packages/shared/src/components/MainLayout.tsx @@ -28,6 +28,7 @@ import { useActiveFeedNameContext, } from '../contexts'; import { useFeedLayout, useViewSize, ViewSize } from '../hooks'; +import { isPWA } from '../lib/func'; import { BootPopups } from './modals/BootPopups'; import { useFeedName } from '../hooks/feed/useFeedName'; import { AuthTriggers } from '../lib/auth'; @@ -92,7 +93,6 @@ function MainLayoutComponent({ const { isCustomFeed } = useFeedName({ feedName }); const { plusEntryAnnouncementBar } = usePlusEntry(); const isLaptopXL = useViewSize(ViewSize.LaptopXL); - const isMobile = useViewSize(ViewSize.MobileL); const { screenCenteredOnMobileLayout } = useFeedLayout(); const { isNotificationsReady, unreadCount } = useNotificationContext(); useAuthErrors(); @@ -167,7 +167,7 @@ function MainLayoutComponent({ (!isPageReady && isPageApplicableForOnboarding) || shouldRedirectOnboarding ) { - if (isMobile) { + if (isPWA()) { return ; } return null; diff --git a/packages/shared/src/components/MobileAppLoader.tsx b/packages/shared/src/components/MobileAppLoader.tsx index 9d14ee5de5..e166cc4358 100644 --- a/packages/shared/src/components/MobileAppLoader.tsx +++ b/packages/shared/src/components/MobileAppLoader.tsx @@ -1,7 +1,7 @@ import type { ReactElement } from 'react'; import React from 'react'; import classNames from 'classnames'; -import LogoIcon from '../svg/LogoIcon'; +import { cloudinaryAppIconMain } from '../lib/image'; import { Loader } from './Loader'; interface MobileAppLoaderProps { @@ -14,14 +14,16 @@ export function MobileAppLoader({ return (
-
- -
- + daily.dev +
); } From 9ecda98f251e765b536cc8bb1d46d71000136c4e Mon Sep 17 00:00:00 2001 From: Nimrod Kramer <41470823+nimrodkra@users.noreply.github.com> Date: Thu, 5 Feb 2026 10:30:50 +0200 Subject: [PATCH 3/3] fix: add SSR guard for isPWA check Co-authored-by: Cursor --- packages/shared/src/components/MainLayout.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/shared/src/components/MainLayout.tsx b/packages/shared/src/components/MainLayout.tsx index 83bce434b9..7bc2fc438d 100644 --- a/packages/shared/src/components/MainLayout.tsx +++ b/packages/shared/src/components/MainLayout.tsx @@ -167,7 +167,7 @@ function MainLayoutComponent({ (!isPageReady && isPageApplicableForOnboarding) || shouldRedirectOnboarding ) { - if (isPWA()) { + if (typeof window !== 'undefined' && isPWA()) { return ; } return null;