Compare commits

...

3 Commits

Author SHA1 Message Date
jared 8c711f5f4a feat(mobile): Saved Messages accessible from room header More Options menu
CI / Build & Quality Checks (push) Successful in 10m29s
CI / Trigger Desktop Build (push) Successful in 15s
On mobile, SidebarNav (which contains BookmarksTab) is hidden while
inside a room. Added a Saved Messages toggle to the RoomMenu (···More
Options) so users can open/close the bookmarks panel without leaving
the room. Works on all screen sizes; UNTESTED on device.

Also marks Remind Me Later as done in LOTUS_TODO — it was already
fully wired (RemindMeDialog + ReminderMonitor + Message.tsx trigger).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 15:18:38 -04:00
jared c4f00ed483 fix(mobile): apply useModalStyle to 7 more modal dialogs
ScheduleMessageModal, PollCreator, JoinAddressPrompt, JumpToTime,
EditHistoryModal, ForwardMessageDialog, RemindMeDialog — all now
render fullscreen on mobile (≤750px) and as a capped-width box on
desktop, consistent with the existing useModalStyle pattern.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 15:14:30 -04:00
jared f5c301d5c6 fix(mobile): useModalStyle on 3 more dialogs, GPU hint animated bg, document untested fixes
- DeviceVerification, InviteUserPrompt, LogoutDialog: apply useModalStyle for
  fullscreen on mobile, capped box on desktop
- chatBackground: inject willChange + contain:paint on animated variants to
  promote compositor layer and prevent descendant repaint flickering (Bug #2)
- LOTUS_BUGS.md: mark #7-#10 FIXED/UNTESTED, #2 FIXED/UNTESTED, chatBackground
  backgroundColor values as PATTERN CONTENT EXCEPTION

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 14:51:28 -04:00
14 changed files with 75 additions and 40 deletions
+16 -19
View File
@@ -19,10 +19,10 @@ This document tracks identified bugs, edge cases, and architectural discrepancie
### 2. Chat Background Animation Flickering
- **File:** `cinny/src/app/features/lotus/chatBackground.ts`
- **Status:** **OPEN**
- **Status:** **FIXED ⚠️ UNTESTED** — needs verification on a real device with an animated background active
- **Issue:** Animated background properties cause visible flickering on message text and the composer area, particularly on browsers/GPUs susceptible to repaint-induced artifacts.
- **Root Cause:** Animation triggers excessive repaints or layout recalculations on descendant elements, likely due to animating non-GPU accelerated properties on parent containers without proper rendering context isolation.
- **Proposed Fix:** Promote background container to a compositor layer using `will-change: transform`, strictly limit animations to `transform` and `opacity` properties, and utilize `contain: paint;` to isolate the background rendering context.
- **Fix Applied:** `getChatBg()` now injects `willChange: 'background-position'` and `contain: 'paint'` for any animated variant. This promotes the element to its own compositor layer and isolates repaints from descendants. Background-position animation is already GPU-hinted on modern browsers; `contain: paint` prevents descendant elements from being invalidated during each frame.
### 3. Avatar Decorations in Element Call
@@ -60,7 +60,7 @@ This document tracks identified bugs, edge cases, and architectural discrepancie
### 6. Exclusive Background vs. Seasonal Choice
- **File:** `cinny/src/app/state/settings.ts`
- **Status:** **FIXED**
- **Status:** **FIXED ⚠️ UNTESTED** — needs verification: (a) pick a background, confirm seasonal theme auto-clears; (b) pick a seasonal theme, confirm background auto-clears; (c) set both via old localStorage data and reload, confirm SeasonalEffect guard suppresses the overlay
- **Issue:** Concurrent application of both Chat Backgrounds and Seasonal Themes causes visual clutter and high GPU usage.
- **Root Cause:** These are currently handled as independent settings in the `settingsAtom` and applied simultaneously without mutual exclusion.
- **Fix Applied:** Mutual exclusion enforced at two layers: (1) `General.tsx` — ChatBgGrid clears seasonalThemeOverride→'off' when any non-'none' background is picked; SeasonalBgGrid clears chatBackground→'none' when any real seasonal theme is selected. (2) `SeasonalEffect.tsx` — runtime guard returns null if `chatBackground !== 'none'`, protecting against legacy persisted state.
@@ -68,34 +68,31 @@ This document tracks identified bugs, edge cases, and architectural discrepancie
### 7. Tiny Touch Targets in Composer Toolbar
- **File:** `cinny/src/app/features/room/RoomInput.tsx`
- **Status:** **OPEN**
- **Status:** **FIXED ⚠️ UNTESTED** — needs verification on a real mobile device: open composer, confirm all toolbar buttons are tappable without mis-taps
- **Issue:** Toolbar buttons have hit areas smaller than the WCAG-recommended 44x44px for touch, hindering mobile accessibility.
- **Root Cause:** The `IconButton` component does not explicitly enforce a 44x44px touch target, and the default size is too small for mobile touch precision.
- **Proposed Fix:** Apply CSS `min-width: 44px; min-height: 44px;` to all toolbar icons, potentially via a dedicated `MobileTouchTarget` style wrapper or by overriding the `IconButton` component's style for mobile viewports using media queries.
- **Fix Applied:** Added `touchTarget = { minWidth: '44px', minHeight: '44px' }` computed from `mobileOrTablet()` and applied as `style={touchTarget}` to all 8 composer toolbar `IconButton` elements (attach, format, sticker, emoji, GIF, location, poll, schedule, send).
### 8. Horizontal Overflow in Room Settings
- **File:** `cinny/src/app/features/room-settings/RoomSettings.tsx`
- **Status:** **OPEN**
- **File:** `cinny/src/app/components/page/style.css.ts`
- **Status:** **FIXED ⚠️ UNTESTED** — needs verification: open Room Settings on a narrow mobile screen, confirm nav panel fills full width and no horizontal scrollbar appears
- **Issue:** Wide tables and input elements in room settings cause horizontal overflow on mobile viewports.
- **Root Cause:** A fixed-width constraint applied to the `PageNav` component in `cinny/src/app/components/page/style.css.ts` overrides responsive layout attempts on smaller screens.
- **Proposed Fix:** Update the `PageNav` style definition to be responsive, setting its width to `100%` on mobile viewports using CSS media queries, and ensure all child containers in `RoomSettings` use `flex-wrap: wrap` or similar overflow-handling layouts.
- **Fix Applied:** Added `@media (max-width: 750px) { width: '100%' }` to both `'400'` and `'300'` size variants of the `PageNav` vanilla-extract recipe in `style.css.ts`.
### 9. Modal Float-Style Responsiveness
- **File:** `cinny/src/app/components/modal/Modal.tsx`
- **Status:** **OPEN**
- **File:** Multiple modal files
- **Status:** **PARTIALLY FIXED ⚠️ UNTESTED** — applied to 7 modals; ~13 remaining modal files still need the hook applied
- **Issue:** Modals appear as floating boxes on mobile, creating navigation and readability challenges.
- **Root Cause:** Missing viewport-dependent styling in the base modal component.
- **Proposed Fix:** Implement media-query-based responsiveness in the base `Modal` wrapper. For viewports below a certain threshold, override floating styles with full-screen layout: `width: 100vw; height: 100vh; border-radius: 0;`.
- **Fix Applied:** Created `useModalStyle(desktopMaxWidth)` hook (`src/app/hooks/useModalStyle.ts`) that returns fullscreen styles on mobile (no border-radius, no max-width, `height: 100%`) and desktop box styles otherwise. Applied to: `LeaveRoomPrompt`, `LeaveSpacePrompt`, `ReportRoomModal`, `ReportUserModal`, `DeviceVerification`, `InviteUserPrompt`, `LogoutDialog`.
- **Remaining:** Apply `useModalStyle` to: `DeviceVerificationSetup`, `UIAFlowOverlay`, `JoinAddressPrompt`, `JoinRulesSwitcher`, `RoomNotificationSwitcher`, and others that render floating dialogs.
### 10. Composer Keyboard Obscurity
- **File:** `cinny/src/app/features/room/RoomInput.tsx`
- **Status:** **OPEN**
- **File:** `src/index.css`
- **Status:** **FIXED ⚠️ UNTESTED** — needs verification on iOS Safari specifically (the worst offender); on Android Chrome `100dvh` has been standard since Chrome 108
- **Issue:** The chat composer is often partially or fully obscured by the virtual keyboard on mobile.
- **Root Cause:** Use of `vh` units for container height does not adapt when the virtual keyboard appears, pushing the `RoomInput` container off-screen.
- **Proposed Fix:** Adopt modern viewport units (`100svh`) for main layout containers to ensure the height adapts dynamically. Optionally, use `scrollIntoView` on the `RoomInput` container when it receives focus.
- **Fix Applied:** Added `height: 100dvh` (dynamic viewport height) to `html` alongside the existing `height: 100%` fallback. `dvh` updates when the software keyboard appears, ensuring the layout shrinks correctly and the composer stays visible.
### 11. Inline Jotai atom creation
@@ -151,7 +148,7 @@ This document tracks identified bugs, edge cases, and architectural discrepancie
| Hardcoded inline style `cursor: 'pointer'` | `cinny/src/app/plugins/react-custom-html-parser.tsx` |
| Hardcoded color `#00D4FF`, `#FFB300`**VERIFIED COMPLIANT** | `cinny/src/app/components/event-readers/EventReaders.tsx` |
| Hardcoded color `#EE1D52`, `#9146ff`, `#ff4500`, `#cb3837`, `#f48024` ⚠️ **BRAND EXCEPTION** | `cinny/src/app/components/url-preview/UrlPreviewCard.tsx` + `UrlPreview.css.tsx` — official third-party brand colors in SVG logos and site badge backgrounds; cannot convert to CSS variables without inventing new tokens (violates TDS rule 3) |
| Massive number of hardcoded `backgroundColor` values | `cinny/src/app/features/lotus/chatBackground.ts` |
| Massive number of hardcoded `backgroundColor` values ⚠️ **PATTERN CONTENT EXCEPTION** | `cinny/src/app/features/lotus/chatBackground.ts` — each background's base color is aesthetic content that defines the pattern identity; converting requires inventing 40+ CSS variables (violates TDS rule 3) or using CSS4 `relative-color-syntax` in inline styles (insufficient browser support); these are visual content, not UI chrome |
| Hardcoded colors `#00FF88`, `#FF6B00`**VERIFIED COMPLIANT** | `cinny/src/app/features/call/CallControls.tsx` |
| Hardcoded fallback hexes in toast colors ✅ **FIXED** | `cinny/src/app/features/toast/LotusToastContainer.tsx` |
+7 -8
View File
@@ -436,14 +436,13 @@ Themes:
## 🚀 Features to Add
- [ ] **Mobile Audit:** Comprehensive audit of all features in LOTUS_FEATURES.md for mobile PWA usability and layout responsiveness.
- [ ] **Remind Me Later:** Slack-style reminders for messages (ping user at a set time, add to bookmarks).
- **Root Cause:** Feature does not exist. Reminders require persistence in Matrix account data and a background worker to trigger notifications.
- **Approach:** Expand `useReminders.ts` to include `removeReminder`. Add a "Remind me" menu item to `Message.tsx` that triggers a `DatePicker`/`TimePicker` modal (reusing logic from `JumpToTime.tsx`). Implement a `ReminderMonitor` in `ClientNonUIFeatures.tsx` that polls active reminders from `io.lotus.reminders` and pushes to `toastQueueAtom` in `state/toast.ts` when due.
- **Complexity:** Medium.
- [ ] **Mobile Bookmarks:** Fix visibility issue where bookmarks do not show up when selected via PWA on mobile.
- **Root Cause:** `ClientLayout.tsx` explicitly restricts `BookmarksPanel` rendering to `ScreenSize.Desktop` (lines 51-56).
- **Approach:** Update `ClientLayout.tsx` to remove the `ScreenSize.Desktop` restriction. Pass `isMobile={screenSize !== ScreenSize.Desktop}` to `BookmarksPanel`. `BookmarksPanel.tsx` already supports this prop (line 127) to enable full-screen absolute positioning and reactive layout.
- **Complexity:** Low.
- [x] **Remind Me Later:** Slack-style reminders for messages — fully implemented ⚠️ UNTESTED end-to-end
- **Storage:** `useReminders.ts` — persists to `io.lotus.reminders` account data with `addReminder` / `removeReminder` / `getReminders`
- **UI:** `RemindMeDialog.tsx` — 4 presets (20 min, 1 hr, 3 hr, tomorrow 9am); wired into `Message.tsx` context menu via `remindOpen` state; `useModalStyle(320)` for mobile fullscreen
- **Monitor:** `ReminderMonitor` in `ClientNonUIFeatures.tsx` — polls every 30s + on tab visibility; fires Lotus toast when due and calls `removeReminder`
- [x] **Mobile Bookmarks:** Fixed ⚠️ UNTESTED — bookmarks now accessible from within any room on mobile
- **Root Cause:** `BookmarksPanel` renders correctly on mobile but `BookmarksTab` lives in `SidebarNav`, which is hidden when inside a room on mobile (`MobileFriendlyClientNav` returns `null`). No trigger existed.
- **Fix:** Added "Saved Messages" `MenuItem` to the `RoomMenu` (···More Options) in `RoomViewHeader.tsx`. Toggles `bookmarksPanelAtom` and closes the menu. Works on all screen sizes — desktop users see it as a duplicate of the sidebar star, mobile users now have their only in-room access point.
---
+3 -1
View File
@@ -30,6 +30,7 @@ import {
} from '../hooks/useVerificationRequest';
import { AsyncStatus, useAsyncCallback } from '../hooks/useAsyncCallback';
import { ContainerColor } from '../styles/ContainerColor.css';
import { useModalStyle } from '../hooks/useModalStyle';
const DialogHeaderStyles: CSSProperties = {
padding: `0 ${config.space.S200} 0 ${config.space.S400}`,
@@ -232,6 +233,7 @@ type DeviceVerificationProps = {
};
export function DeviceVerification({ request, onExit }: DeviceVerificationProps) {
const phase = useVerificationRequestPhase(request);
const modalStyle = useModalStyle(480);
const handleCancel = useCallback(() => {
if (request.phase !== VerificationPhase.Done && request.phase !== VerificationPhase.Cancelled) {
@@ -255,7 +257,7 @@ export function DeviceVerification({ request, onExit }: DeviceVerificationProps)
escapeDeactivates: false,
}}
>
<Dialog variant="Surface">
<Dialog variant="Surface" style={modalStyle}>
<Header style={DialogHeaderStyles} variant="Surface" size="500">
<Box grow="Yes">
<Text as="h2" size="H4">
+3 -1
View File
@@ -3,6 +3,7 @@ import { Dialog, Header, config, Box, Text, Button, Spinner, color } from 'folds
import { AsyncStatus, useAsyncCallback } from '../hooks/useAsyncCallback';
import { logoutClient } from '../../client/initMatrix';
import { useMatrixClient } from '../hooks/useMatrixClient';
import { useModalStyle } from '../hooks/useModalStyle';
import { useCrossSigningActive } from '../hooks/useCrossSigning';
import { InfoCard } from './info-card';
import {
@@ -16,6 +17,7 @@ type LogoutDialogProps = {
export const LogoutDialog = forwardRef<HTMLDivElement, LogoutDialogProps>(
({ handleClose }, ref) => {
const mx = useMatrixClient();
const modalStyle = useModalStyle(480);
const hasEncryptedRoom = !!mx.getRooms().find((room) => room.hasEncryptionStateEvent());
const crossSigningActive = useCrossSigningActive();
const verificationStatus = useDeviceVerificationStatus(
@@ -33,7 +35,7 @@ export const LogoutDialog = forwardRef<HTMLDivElement, LogoutDialogProps>(
const ongoingLogout = logoutState.status === AsyncStatus.Loading;
return (
<Dialog variant="Surface" ref={ref}>
<Dialog variant="Surface" ref={ref} style={modalStyle}>
<Header
style={{
padding: `0 ${config.space.S200} 0 ${config.space.S400}`,
@@ -51,6 +51,7 @@ import { useAlive } from '../../hooks/useAlive';
import { copyToClipboard } from '../../utils/dom';
import { getMatrixToRoom } from '../../plugins/matrix-to';
import { getViaServers } from '../../plugins/via-servers';
import { useModalStyle } from '../../hooks/useModalStyle';
const SEARCH_OPTIONS: UseAsyncSearchOptions = {
limit: 1000,
@@ -66,6 +67,7 @@ type InviteUserProps = {
};
export function InviteUserPrompt({ room, requestClose }: InviteUserProps) {
const mx = useMatrixClient();
const modalStyle = useModalStyle(560);
const alive = useAlive();
const [linkCopied, setLinkCopied] = useState(false);
const [showQr, setShowQr] = useState(false);
@@ -184,7 +186,7 @@ export function InviteUserPrompt({ room, requestClose }: InviteUserProps) {
escapeDeactivates: stopPropagation,
}}
>
<Dialog>
<Dialog style={modalStyle}>
<Box grow="Yes" direction="Column">
<Header
size="500"
@@ -18,6 +18,7 @@ import {
} from 'folds';
import { stopPropagation } from '../../utils/keyboard';
import { isRoomAlias, isRoomId } from '../../utils/matrix';
import { useModalStyle } from '../../hooks/useModalStyle';
import { parseMatrixToRoom, parseMatrixToRoomEvent, testMatrixTo } from '../../plugins/matrix-to';
import { tryDecodeURIComponent } from '../../utils/dom';
@@ -26,6 +27,7 @@ type JoinAddressProps = {
onCancel: () => void;
};
export function JoinAddressPrompt({ onOpen, onCancel }: JoinAddressProps) {
const modalStyle = useModalStyle(480);
const [invalid, setInvalid] = useState(false);
const handleSubmit: FormEventHandler<HTMLFormElement> = (evt) => {
@@ -71,7 +73,7 @@ export function JoinAddressPrompt({ onOpen, onCancel }: JoinAddressProps) {
escapeDeactivates: stopPropagation,
}}
>
<Dialog variant="Surface">
<Dialog variant="Surface" style={modalStyle}>
<Header
style={{
padding: `0 ${config.space.S200} 0 ${config.space.S400}`,
+5
View File
@@ -493,5 +493,10 @@ export const getChatBg = (
const { animation: _anim, ...rest } = style;
return rest;
}
// For animated backgrounds, promote the element to its own compositor layer so
// background-position keyframes don't trigger repaints on descendant elements.
if (style.animation) {
return { ...style, willChange: 'background-position', contain: 'paint' };
}
return style;
};
+3 -3
View File
@@ -19,6 +19,7 @@ import {
import { Room } from 'matrix-js-sdk';
import { useMatrixClient } from '../../hooks/useMatrixClient';
import { stopPropagation } from '../../utils/keyboard';
import { useModalStyle } from '../../hooks/useModalStyle';
interface PollCreatorProps {
roomId: string;
@@ -28,6 +29,7 @@ interface PollCreatorProps {
export function PollCreator({ roomId, onClose }: PollCreatorProps) {
const mx = useMatrixClient();
const modalStyle = useModalStyle(440);
const [question, setQuestion] = useState('');
const [options, setOptions] = useState<string[]>(['', '']);
const [isMultiple, setIsMultiple] = useState(false);
@@ -109,9 +111,7 @@ export function PollCreator({ roomId, onClose }: PollCreatorProps) {
background: color.Surface.Container,
borderRadius: config.radii.R400,
boxShadow: color.Other.Shadow,
width: '100vw',
maxWidth: 440,
overflow: 'hidden',
...modalStyle,
}}
>
{/* Header */}
+17
View File
@@ -74,6 +74,8 @@ import { useLivekitSupport } from '../../hooks/useLivekitSupport';
import { webRTCSupported } from '../../utils/rtc';
import { MediaGallery } from './MediaGallery';
import { usePendingKnocks } from '../../hooks/usePendingKnocks';
import { useAtom } from 'jotai';
import { bookmarksPanelAtom } from '../../state/bookmarksPanel';
type RoomMenuProps = {
room: Room;
@@ -96,6 +98,7 @@ const RoomMenu = forwardRef<HTMLDivElement, RoomMenuProps>(({ room, requestClose
const [invitePrompt, setInvitePrompt] = useState(false);
const [reportRoomOpen, setReportRoomOpen] = useState(false);
const [bookmarksOpen, setBookmarksOpen] = useAtom(bookmarksPanelAtom);
const handleMarkAsRead = () => {
markAsRead(mx, room.roomId, hideActivity);
@@ -169,6 +172,20 @@ const RoomMenu = forwardRef<HTMLDivElement, RoomMenuProps>(({ room, requestClose
</Box>
<Line variant="Surface" size="300" />
<Box direction="Column" gap="100" style={{ padding: config.space.S100 }}>
<MenuItem
onClick={() => {
setBookmarksOpen((v) => !v);
requestClose();
}}
size="300"
after={<Icon size="100" src={Icons.Star} filled={bookmarksOpen} />}
radii="300"
aria-pressed={bookmarksOpen}
>
<Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
Saved Messages
</Text>
</MenuItem>
{!isServerNotice && (
<MenuItem
onClick={handleInvite}
@@ -19,6 +19,7 @@ import { IContent } from 'matrix-js-sdk';
import { useMatrixClient } from '../../hooks/useMatrixClient';
import { stopPropagation } from '../../utils/keyboard';
import { scheduleMessage } from '../../utils/scheduledMessages';
import { useModalStyle } from '../../hooks/useModalStyle';
interface ScheduleMessageModalProps {
roomId: string;
@@ -89,6 +90,7 @@ export function ScheduleMessageModal({
onScheduled,
onClose,
}: ScheduleMessageModalProps) {
const modalStyle = useModalStyle(400);
const mx = useMatrixClient();
const [messageText, setMessageText] = useState(initialBody ?? '');
const [submitting, setSubmitting] = useState(false);
@@ -186,9 +188,7 @@ export function ScheduleMessageModal({
background: color.Surface.Container,
borderRadius: config.radii.R400,
boxShadow: color.Other.Shadow,
width: '100vw',
maxWidth: 400,
overflow: 'hidden',
...modalStyle,
}}
>
{/* Header */}
@@ -31,6 +31,7 @@ import { getToday, getYesterday, timeDayMonthYear, timeHourMinute } from '../../
import { DatePicker, TimePicker } from '../../../components/time-date';
import { useSetting } from '../../../state/hooks/settings';
import { settingsAtom } from '../../../state/settings';
import { useModalStyle } from '../../../hooks/useModalStyle';
type JumpToTimeProps = {
onCancel: () => void;
@@ -38,6 +39,7 @@ type JumpToTimeProps = {
};
export function JumpToTime({ onCancel, onSubmit }: JumpToTimeProps) {
const mx = useMatrixClient();
const modalStyle = useModalStyle(480);
const room = useRoom();
const alive = useAlive();
const createStateEvent = useStateEvent(room, StateEvent.RoomCreate);
@@ -96,7 +98,7 @@ export function JumpToTime({ onCancel, onSubmit }: JumpToTimeProps) {
escapeDeactivates: stopPropagation,
}}
>
<Dialog variant="Surface">
<Dialog variant="Surface" style={modalStyle}>
<Header
style={{
padding: `0 ${config.space.S200} 0 ${config.space.S400}`,
@@ -20,6 +20,7 @@ import {
import { MatrixEvent, Room } from 'matrix-js-sdk';
import { useMatrixClient } from '../../../hooks/useMatrixClient';
import { stopPropagation } from '../../../utils/keyboard';
import { useModalStyle } from '../../../hooks/useModalStyle';
import { sanitizeCustomHtml } from '../../../utils/sanitize';
import { LINKIFY_OPTS } from '../../../plugins/react-custom-html-parser';
import { AsyncStatus, useAsyncCallback } from '../../../hooks/useAsyncCallback';
@@ -92,6 +93,7 @@ function getVersionContent(evt: MatrixEvent): ReactNode {
export function EditHistoryModal({ room, mEvent, onClose }: EditHistoryModalProps) {
const mx = useMatrixClient();
const modalStyle = useModalStyle(560);
const [hour24Clock] = useSetting(settingsAtom, 'hour24Clock');
const [dateFormatString] = useSetting(settingsAtom, 'dateFormatString');
@@ -167,6 +169,7 @@ export function EditHistoryModal({ room, mEvent, onClose }: EditHistoryModalProp
role="dialog"
aria-modal="true"
aria-labelledby="edit-history-title"
style={modalStyle}
>
<Header
variant="Surface"
@@ -19,6 +19,7 @@ import { MatrixEvent, Room } from 'matrix-js-sdk';
import { useAtomValue } from 'jotai';
import { useMatrixClient } from '../../../hooks/useMatrixClient';
import { stopPropagation } from '../../../utils/keyboard';
import { useModalStyle } from '../../../hooks/useModalStyle';
import { mDirectAtom } from '../../../state/mDirectList';
import { useMediaAuthentication } from '../../../hooks/useMediaAuthentication';
import { mxcUrlToHttp } from '../../../utils/matrix';
@@ -78,6 +79,7 @@ type Props = {
export function ForwardMessageDialog({ mEvent, onClose }: Props) {
const mx = useMatrixClient();
const modalStyle = useModalStyle(400);
const directs = useAtomValue(mDirectAtom);
const useAuthentication = useMediaAuthentication();
const [query, setQuery] = useState('');
@@ -129,6 +131,7 @@ export function ForwardMessageDialog({ mEvent, onClose }: Props) {
borderRadius: config.radii.R500,
display: 'flex',
flexDirection: 'column',
...modalStyle,
}}
>
<Box
@@ -17,6 +17,7 @@ import {
} from 'folds';
import { stopPropagation } from '../../../utils/keyboard';
import { useReminders } from '../../../hooks/useReminders';
import { useModalStyle } from '../../../hooks/useModalStyle';
type RemindMeDialogProps = {
roomId: string;
@@ -39,6 +40,7 @@ function getPresets(): Array<{ label: string; ms: number }> {
}
export function RemindMeDialog({ roomId, eventId, previewText, onClose }: RemindMeDialogProps) {
const modalStyle = useModalStyle(320);
const { addReminder } = useReminders();
// eslint-disable-next-line react-hooks/exhaustive-deps
const presets = useMemo(() => getPresets(), []);
@@ -73,8 +75,7 @@ export function RemindMeDialog({ roomId, eventId, previewText, onClose }: Remind
background: color.Surface.Container,
borderRadius: config.radii.R400,
boxShadow: color.Other.Shadow,
width: '100vw',
maxWidth: 280,
...modalStyle,
overflow: 'hidden',
}}
>