PWA detect. Fixes #887

This commit is contained in:
Enrico Ros
2025-11-23 18:46:12 -08:00
parent fc047087ce
commit ffef0ef31d
4 changed files with 77 additions and 4 deletions
@@ -17,7 +17,6 @@ import { createDMessageFromFragments, createDMessageTextContent, DMessage, DMess
import { createTextContentFragment, DMessageFragment, DMessageFragmentId } from '~/common/stores/chat/chat.fragments';
import { openFileForAttaching } from '~/common/components/ButtonAttachFiles';
import { optimaOpenPreferences } from '~/common/layout/optima/useOptima';
import { useBrowserTranslationWarning } from '~/common/components/useIsBrowserTranslating';
import { useCapabilityElevenLabs } from '~/common/components/useCapabilities';
import { useChatOverlayStore } from '~/common/chat-overlay/store-perchat_vanilla';
import { useChatStore } from '~/common/stores/chat/store-chats';
@@ -65,7 +64,6 @@ export function ChatMessageList(props: {
const { notifyBooting } = useScrollToBottom();
const danger_experimentalHtmlWebUi = useChatAutoSuggestHTMLUI();
const [showSystemMessages] = useChatShowSystemMessages();
const optionalTranslationWarning = useBrowserTranslationWarning();
const { conversationMessages, historyTokenCount } = useChatStore(useShallow(({ conversations }) => {
const conversation = conversations.find(conversation => conversation.id === props.conversationId);
return {
@@ -326,8 +324,6 @@ export function ChatMessageList(props: {
return (
<List role='chat-messages-list' sx={listSx}>
{optionalTranslationWarning}
{props.isMessageSelectionMode && (
<MessagesSelectionHeader
hasSelected={selectedMessages.size > 0}
@@ -0,0 +1,66 @@
import * as React from 'react';
import { Alert, IconButton } from '@mui/joy';
import CloseRoundedIcon from '@mui/icons-material/CloseRounded';
import WarningRoundedIcon from '@mui/icons-material/WarningRounded';
import { Is, isBrowser, isPwa } from '~/common/util/pwaUtils';
import { useUICounter } from '~/common/stores/store-ui';
/**
* Detects if a mobile PWA is running in Desktop Mode (which causes layout issues).
* This happens when Chrome's "Request Desktop Site" is enabled on mobile devices.
*
* Shows a dismissible warning when:
* - App is running as a PWA (standalone mode)
* - Device OS is mobile (iOS or Android)
* - Viewport width is >= 900px (indicating desktop mode override)
*/
export function usePWADesktopModeWarning() {
// state
const [hideWarning, setHideWarning] = React.useState(false);
// external state
const { novel: lessThanFive, touch } = useUICounter('acknowledge-pwa-desktop-mode-warning', 5);
// detect PWA in desktop mode
const isInDesktopMode = React.useMemo(() => {
if (!isBrowser) return false;
// if PWA
const isInPwaMode = isPwa();
if (!isInPwaMode) return false;
// if OS is mobile
const isMobileOS = Is.OS.iOS || Is.OS.Android;
if (!isMobileOS) return false;
// Check if viewport width suggests desktop mode (>= 900px)
// This matches the mobile breakpoint used in useMatchMedia.ts
return window.matchMedia('(min-width: 900px)').matches;
}, []);
const showWarning = isInDesktopMode && !hideWarning && lessThanFive;
return React.useMemo(() => showWarning ? (
<Alert
size='lg'
variant='soft'
color='warning'
startDecorator={<WarningRoundedIcon />}
endDecorator={
<IconButton color='warning'>
<CloseRoundedIcon onClick={() => {
setHideWarning(true);
touch();
}} />
</IconButton>
}
>
This Browser is running in Desktop Mode, which may cause layout issues.<br />
To fix: Close this app, open Chrome, visit this site, disable &quot;Desktop site&quot; in the menu, then reopen the app.
</Alert>
) : null, [showWarning, touch]);
}
+10
View File
@@ -5,8 +5,10 @@ import { PanelGroup } from 'react-resizable-panels';
import { GlobalDragOverlay } from '~/common/components/dnd-dt/GlobalDragOverlay';
import { Is } from '~/common/util/pwaUtils';
import { checkVisibleNav, navItems } from '~/common/app.nav';
import { useBrowserTranslationWarning } from '~/common/components/useIsBrowserTranslating';
import { useGlobalShortcuts } from '~/common/components/shortcuts/useGlobalShortcuts';
import { useIsMobile } from '~/common/components/useMatchMedia';
import { usePWADesktopModeWarning } from '~/common/components/useIsBrowserInPWADesktop';
import { useUIPreferencesStore } from '~/common/stores/store-ui';
import { ScratchClip } from './scratchclip/ScratchClip';
@@ -61,6 +63,10 @@ export function OptimaLayout(props: { suspendAutoModelsSetup?: boolean, children
// derived state
const currentApp = navItems.apps.find(item => item.route === route);
// global warnings
const translationWarning = useBrowserTranslationWarning();
const pwaDesktopModeWarning = usePWADesktopModeWarning();
// global shortcuts for Optima
useGlobalShortcuts('OptimaApp', React.useMemo(() => [
// Preferences & Model dialogs
@@ -78,6 +84,10 @@ export function OptimaLayout(props: { suspendAutoModelsSetup?: boolean, children
return <>
{/* Global Warnings */}
{translationWarning}
{pwaDesktopModeWarning}
<PanelGroup direction='horizontal' id='root-layout' style={isMobile ? undoPanelGroupSx : undefined}>
+1
View File
@@ -245,6 +245,7 @@ export function uiSetPanelGroupCollapsed(key: string, collapsed: boolean): void
// 'export-share' // used the export function
// 'share-chat-link' // not shared a Chat Link yet
type KnownKeys =
| 'acknowledge-pwa-desktop-mode-warning' // displayed if mobile PWA is in desktop mode (layout issues)
| 'acknowledge-translation-warning' // displayed if Chrome is translating the page (may crash)
| 'beam-wizard' // first Beam
| 'call-wizard' // first Call