fix(mobile): make media gallery and members panel accessible on mobile
MediaGallery: fixed panel now goes full-width (100%) on mobile instead of the inaccessible 320px right sidebar. Added 'Media Gallery' MenuItem to RoomMenu (visible only on mobile) so users can open it from the More Options (···) button. MembersDrawer: removed ScreenSize.Desktop gate in Room.tsx so it now renders on mobile too. CSS media query (≤750px) makes it position:fixed inset:0 width:100% on mobile instead of the 266px desktop sidebar. Added 'Members' MenuItem to RoomMenu for mobile access. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -21,6 +21,7 @@ import { useMatrixClient } from '../../hooks/useMatrixClient';
|
||||
import { useMediaAuthentication } from '../../hooks/useMediaAuthentication';
|
||||
import { decryptFile, downloadEncryptedMedia, mxcUrlToHttp } from '../../utils/matrix';
|
||||
import { ContainerColor } from '../../styles/ContainerColor.css';
|
||||
import { ScreenSize, useScreenSizeContext } from '../../hooks/useScreenSize';
|
||||
|
||||
type GalleryTab = 'image' | 'video' | 'file';
|
||||
|
||||
@@ -531,6 +532,8 @@ type MediaGalleryProps = {
|
||||
export function MediaGallery({ room, onClose }: MediaGalleryProps) {
|
||||
const mx = useMatrixClient();
|
||||
const useAuthentication = useMediaAuthentication();
|
||||
const screenSize = useScreenSizeContext();
|
||||
const isMobile = screenSize === ScreenSize.Mobile;
|
||||
|
||||
const [tab, setTab] = useState<GalleryTab>('image');
|
||||
const [loading, setLoading] = useState(false);
|
||||
@@ -650,9 +653,9 @@ export function MediaGallery({ room, onClose }: MediaGalleryProps) {
|
||||
top: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
width: '320px',
|
||||
width: isMobile ? '100%' : '320px',
|
||||
zIndex: 500,
|
||||
borderLeft: `1px solid ${color.Surface.ContainerLine}`,
|
||||
borderLeft: isMobile ? 'none' : `1px solid ${color.Surface.ContainerLine}`,
|
||||
overflow: 'hidden',
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -3,6 +3,14 @@ import { config, toRem } from 'folds';
|
||||
|
||||
export const MembersDrawer = style({
|
||||
width: toRem(266),
|
||||
'@media': {
|
||||
'(max-width: 750px)': {
|
||||
position: 'fixed',
|
||||
inset: 0,
|
||||
width: '100%',
|
||||
zIndex: 500,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const MembersDrawerHeader = style({
|
||||
|
||||
@@ -78,9 +78,11 @@ export function Room() {
|
||||
<CallChatView />
|
||||
</>
|
||||
)}
|
||||
{!callView && screenSize === ScreenSize.Desktop && isDrawer && (
|
||||
{!callView && isDrawer && (
|
||||
<>
|
||||
<Line variant="Background" direction="Vertical" size="300" />
|
||||
{screenSize === ScreenSize.Desktop && (
|
||||
<Line variant="Background" direction="Vertical" size="300" />
|
||||
)}
|
||||
<MembersDrawer key={room.roomId} room={room} members={members} />
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -80,10 +80,14 @@ import { bookmarksPanelAtom } from '../../state/bookmarksPanel';
|
||||
type RoomMenuProps = {
|
||||
room: Room;
|
||||
requestClose: () => void;
|
||||
galleryOpen?: boolean;
|
||||
onToggleGallery?: () => void;
|
||||
};
|
||||
const RoomMenu = forwardRef<HTMLDivElement, RoomMenuProps>(({ room, requestClose }, ref) => {
|
||||
const RoomMenu = forwardRef<HTMLDivElement, RoomMenuProps>(
|
||||
({ room, requestClose, galleryOpen, onToggleGallery }, ref) => {
|
||||
const mx = useMatrixClient();
|
||||
const [hideActivity] = useSetting(settingsAtom, 'hideActivity');
|
||||
const screenSize = useScreenSizeContext();
|
||||
const unread = useRoomUnread(room.roomId, roomToUnreadAtom);
|
||||
const powerLevels = usePowerLevelsContext();
|
||||
const creators = useRoomCreators(room);
|
||||
@@ -99,6 +103,7 @@ const RoomMenu = forwardRef<HTMLDivElement, RoomMenuProps>(({ room, requestClose
|
||||
const [invitePrompt, setInvitePrompt] = useState(false);
|
||||
const [reportRoomOpen, setReportRoomOpen] = useState(false);
|
||||
const [bookmarksOpen, setBookmarksOpen] = useAtom(bookmarksPanelAtom);
|
||||
const [peopleDrawer, setPeopleDrawer] = useSetting(settingsAtom, 'isPeopleDrawer');
|
||||
|
||||
const handleMarkAsRead = () => {
|
||||
markAsRead(mx, room.roomId, hideActivity);
|
||||
@@ -186,6 +191,38 @@ const RoomMenu = forwardRef<HTMLDivElement, RoomMenuProps>(({ room, requestClose
|
||||
Saved Messages
|
||||
</Text>
|
||||
</MenuItem>
|
||||
{screenSize === ScreenSize.Mobile && (
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
setPeopleDrawer(!peopleDrawer);
|
||||
requestClose();
|
||||
}}
|
||||
size="300"
|
||||
after={<Icon size="100" src={Icons.User} filled={peopleDrawer} />}
|
||||
radii="300"
|
||||
aria-pressed={peopleDrawer}
|
||||
>
|
||||
<Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
|
||||
Members
|
||||
</Text>
|
||||
</MenuItem>
|
||||
)}
|
||||
{screenSize === ScreenSize.Mobile && onToggleGallery && (
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
onToggleGallery();
|
||||
requestClose();
|
||||
}}
|
||||
size="300"
|
||||
after={<Icon size="100" src={Icons.Photo} filled={galleryOpen} />}
|
||||
radii="300"
|
||||
aria-pressed={galleryOpen}
|
||||
>
|
||||
<Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
|
||||
Media Gallery
|
||||
</Text>
|
||||
</MenuItem>
|
||||
)}
|
||||
{!isServerNotice && (
|
||||
<MenuItem
|
||||
onClick={handleInvite}
|
||||
@@ -288,7 +325,8 @@ const RoomMenu = forwardRef<HTMLDivElement, RoomMenuProps>(({ room, requestClose
|
||||
</Box>
|
||||
</Menu>
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
type CallMenuProps = {
|
||||
onVoiceCall: () => void;
|
||||
@@ -783,7 +821,12 @@ export function RoomViewHeader({ callView }: { callView?: boolean }) {
|
||||
escapeDeactivates: stopPropagation,
|
||||
}}
|
||||
>
|
||||
<RoomMenu room={room} requestClose={() => setMenuAnchor(undefined)} />
|
||||
<RoomMenu
|
||||
room={room}
|
||||
requestClose={() => setMenuAnchor(undefined)}
|
||||
galleryOpen={galleryOpen}
|
||||
onToggleGallery={() => setGalleryOpen((v) => !v)}
|
||||
/>
|
||||
</FocusTrap>
|
||||
}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user