Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/app/components/page/Page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Box, Header, Line, Scroll, Text, as } from 'folds';
import classNames from 'classnames';
import { ContainerColor } from '$styles/ContainerColor.css';
import { ScreenSize, useScreenSizeContext } from '$hooks/useScreenSize';
import { mobileOrTabletLayout } from '$utils/user-agent';
import * as css from './style.css';

type PageRootProps = {
Expand All @@ -16,7 +17,7 @@ export function PageRoot({ nav, children }: PageRootProps) {
return (
<Box grow="Yes" className={ContainerColor({ variant: 'Background' })}>
{nav}
{screenSize !== ScreenSize.Mobile && (
{screenSize !== ScreenSize.Mobile && !mobileOrTabletLayout() && (
<Line variant="Background" size="300" direction="Vertical" />
)}
{children}
Expand Down
5 changes: 3 additions & 2 deletions src/app/pages/MobileFriendly.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { ReactNode } from 'react';
import { useMatch } from 'react-router-dom';
import { ScreenSize, useScreenSizeContext } from '$hooks/useScreenSize';
import { mobileOrTabletLayout } from '$utils/user-agent';
import { DIRECT_PATH, EXPLORE_PATH, HOME_PATH, INBOX_PATH, SPACE_PATH } from './paths';

type MobileFriendlyClientNavProps = {
Expand All @@ -15,7 +16,7 @@ export function MobileFriendlyClientNav({ children }: MobileFriendlyClientNavPro
const inboxMatch = useMatch({ path: INBOX_PATH, caseSensitive: true, end: true });

if (
screenSize === ScreenSize.Mobile &&
(screenSize === ScreenSize.Mobile || mobileOrTabletLayout()) &&
!(homeMatch || directMatch || spaceMatch || exploreMatch || inboxMatch)
) {
return null;
Expand All @@ -36,7 +37,7 @@ export function MobileFriendlyPageNav({ path, children }: MobileFriendlyPageNavP
end: true,
});

if (screenSize === ScreenSize.Mobile && !exactPath) {
if ((screenSize === ScreenSize.Mobile || mobileOrTabletLayout()) && !exactPath) {
return null;
}

Expand Down
3 changes: 2 additions & 1 deletion src/app/pages/Router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { Room } from '$features/room';
import { Lobby } from '$features/lobby';
import { PageRoot } from '$components/page';
import { ScreenSize } from '$hooks/useScreenSize';
import { mobileOrTabletLayout } from '$utils/user-agent';
import { ReceiveSelfDeviceVerification } from '$components/DeviceVerification';
import { AutoRestoreBackupOnVerification } from '$components/BackupRestore';
import { RoomSettingsRenderer } from '$features/room-settings';
Expand Down Expand Up @@ -101,7 +102,7 @@ const getFirstSession = () => {

export const createRouter = (clientConfig: ClientConfig, screenSize: ScreenSize) => {
const { hashRouter } = clientConfig;
const mobile = screenSize === ScreenSize.Mobile;
const mobile = screenSize === ScreenSize.Mobile || mobileOrTabletLayout();

const routes = createRoutesFromElements(
<Route>
Expand Down
6 changes: 3 additions & 3 deletions src/app/pages/client/direct/Direct.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ import {
import { useDirectCreateSelected } from '$hooks/router/useDirectSelected';
import { useDirectRooms } from './useDirectRooms';
import { SidebarResizer } from '$pages/client/sidebar/SidebarResizer';
import { mobileOrTablet } from '$utils/user-agent';
import { mobileOrTabletLayout } from '$utils/user-agent';
import { useScreenSizeContext, ScreenSize } from '$hooks/useScreenSize';

type DirectMenuProps = {
Expand Down Expand Up @@ -254,7 +254,7 @@ export function Direct() {
);

const screenSize = useScreenSizeContext();
const isMobile = mobileOrTablet() || screenSize === ScreenSize.Mobile;
const isMobile = mobileOrTabletLayout() || screenSize === ScreenSize.Mobile;
const hideText = curWidth <= 80 && !isMobile;

return (
Expand Down Expand Up @@ -364,7 +364,7 @@ export function Direct() {
</PageNavContent>
)}
</PageNav>
{!mobileOrTablet() && (
{!mobileOrTabletLayout() && (
<SidebarResizer
setCurWidth={setCurWidth}
sidebarWidth={roomSidebarWidth}
Expand Down
6 changes: 3 additions & 3 deletions src/app/pages/client/explore/Explore.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import { stopPropagation } from '$utils/keyboard';
import { SidebarResizer } from '$pages/client/sidebar/SidebarResizer';
import { settingsAtom } from '$state/settings';
import { useSetting } from '$state/hooks/settings';
import { mobileOrTablet } from '$utils/user-agent';
import { mobileOrTabletLayout } from '$utils/user-agent';
import { getMxIdServer } from '$utils/mxIdHelper';
import { useScreenSizeContext, ScreenSize } from '$hooks/useScreenSize';

Expand Down Expand Up @@ -178,7 +178,7 @@ export function Explore() {
setCurWidth(roomSidebarWidth);
}, [roomSidebarWidth]);
const screenSize = useScreenSizeContext();
const isMobile = mobileOrTablet() || screenSize === ScreenSize.Mobile;
const isMobile = mobileOrTabletLayout() || screenSize === ScreenSize.Mobile;
const hideText = curWidth <= 80 && !isMobile;

return (
Expand Down Expand Up @@ -312,7 +312,7 @@ export function Explore() {
</Box>
</PageNavContent>
</PageNav>
{!mobileOrTablet() && (
{!mobileOrTabletLayout() && (
<SidebarResizer
setCurWidth={setCurWidth}
sidebarWidth={roomSidebarWidth}
Expand Down
6 changes: 3 additions & 3 deletions src/app/pages/client/home/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ import { UseStateProvider } from '$components/UseStateProvider';
import { JoinAddressPrompt } from '$components/join-address-prompt';
import { useHomeRooms } from './useHomeRooms';
import { SidebarResizer } from '$pages/client/sidebar/SidebarResizer';
import { mobileOrTablet } from '$utils/user-agent';
import { mobileOrTabletLayout } from '$utils/user-agent';
import { ScreenSize, useScreenSizeContext } from '$hooks/useScreenSize';

type HomeMenuProps = {
Expand Down Expand Up @@ -262,7 +262,7 @@ export function Home() {
);

const screenSize = useScreenSizeContext();
const isMobile = mobileOrTablet() || screenSize === ScreenSize.Mobile;
const isMobile = mobileOrTabletLayout() || screenSize === ScreenSize.Mobile;
const hideText = curWidth <= 80 && !isMobile;

return (
Expand Down Expand Up @@ -452,7 +452,7 @@ export function Home() {
</PageNavContent>
)}
</PageNav>
{!mobileOrTablet() && (
{!mobileOrTabletLayout() && (
<SidebarResizer
setCurWidth={setCurWidth}
sidebarWidth={roomSidebarWidth}
Expand Down
6 changes: 3 additions & 3 deletions src/app/pages/client/inbox/Inbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { SidebarResizer } from '$pages/client/sidebar/SidebarResizer';
import { useSetting } from '$state/hooks/settings';
import { settingsAtom } from '$state/settings';
import { useEffect, useState } from 'react';
import { mobileOrTablet } from '$utils/user-agent';
import { mobileOrTabletLayout } from '$utils/user-agent';
import { ScreenSize, useScreenSizeContext } from '$hooks/useScreenSize';

function InvitesNavItem({ hideText }: { hideText?: boolean }) {
Expand Down Expand Up @@ -62,7 +62,7 @@ export function Inbox() {
setCurWidth(roomSidebarWidth);
}, [roomSidebarWidth]);
const screenSize = useScreenSizeContext();
const isMobile = mobileOrTablet() || screenSize === ScreenSize.Mobile;
const isMobile = mobileOrTabletLayout() || screenSize === ScreenSize.Mobile;
const hideText = curWidth <= 80 && !isMobile;

return (
Expand Down Expand Up @@ -118,7 +118,7 @@ export function Inbox() {
</Box>
</PageNavContent>
</PageNav>
{!mobileOrTablet() && (
{!mobileOrTabletLayout() && (
<SidebarResizer
setCurWidth={setCurWidth}
sidebarWidth={roomSidebarWidth}
Expand Down
6 changes: 3 additions & 3 deletions src/app/pages/client/space/Space.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ import { ContainerColor } from '$styles/ContainerColor.css';
import { AsyncStatus, useAsyncCallback } from '$hooks/useAsyncCallback';
import { BreakWord } from '$styles/Text.css';
import { InviteUserPrompt } from '$components/invite-user-prompt';
import { mobileOrTablet } from '$utils/user-agent';
import { mobileOrTablet, mobileOrTabletLayout } from '$utils/user-agent';
import { lastVisitedRoomIdAtom } from '$state/room/lastRoom';
import { SwipeableOverlayWrapper } from '$components/SwipeableOverlayWrapper';
import { useCallEmbed } from '$hooks/useCallEmbed';
Expand Down Expand Up @@ -804,7 +804,7 @@ export function Space() {
}, [lastRoomId, spaceIdOrAlias, mx, navigate]);

const screenSize = useScreenSizeContext();
const isMobile = mobileOrTablet() || screenSize === ScreenSize.Mobile;
const isMobile = mobileOrTabletLayout() || screenSize === ScreenSize.Mobile;
const hideText = curWidth <= 80 && !isMobile;
return (
<Box
Expand Down Expand Up @@ -994,7 +994,7 @@ export function Space() {
</PageNavContent>
</SwipeableOverlayWrapper>
</PageNav>
{!mobileOrTablet() && (
{!mobileOrTabletLayout() && (
<SidebarResizer
setCurWidth={setCurWidth}
sidebarWidth={roomSidebarWidth}
Expand Down
17 changes: 17 additions & 0 deletions src/app/utils/user-agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ const isMobileOrTablet = (() => {
const { os, device } = result;
if (device.type === 'mobile' || device.type === 'tablet') return true;
if (os.name === 'Android' || os.name === 'iOS') return true;
// iPad on iOS 13+ sends a macOS Safari user agent by default ("Request Desktop Website").
// ua-parser-js therefore reports os.name === 'Mac OS' with no device.type.
// Real Macs never have maxTouchPoints > 1 (Magic Trackpad reports 1 at most in browsers),
// so this safely identifies iPads masquerading as desktop Safari.
if (os.name === 'Mac OS' && navigator.maxTouchPoints > 1) return true;
return false;
})();

Expand All @@ -15,11 +20,23 @@ const normalizeMacName = (os?: string) => {
return os;
};

// True only for phone-form-factor devices for layout/nav decisions.
// Tablets (native iPadOS UA or "Request Desktop Website") always get the desktop
// two-panel layout; only phones collapse to the single-panel mobile layout.
const isMobileOrTabletLayout = result.device.type === 'mobile';

const isMac = result.os.name === 'Mac OS';

export const ua = () => result;
export const isMacOS = () => isMac;
export const mobileOrTablet = () => isMobileOrTablet;
/**
* True only for phones. Use this for layout/nav decisions (sidebars, route registration).
* Tablets — whether using native iPadOS UA or iPad "Request Desktop Website" — return false,
* so they always get the full desktop two-panel layout.
* Use `mobileOrTablet` for touch/keyboard/scroll-lock behaviour instead.
*/
export const mobileOrTabletLayout = () => isMobileOrTabletLayout;

export const deviceDisplayName = (): string => {
const browser = result.browser.name;
Expand Down
Loading