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>
This commit is contained in:
2026-06-18 14:51:28 -04:00
parent c395f7d16e
commit f5c301d5c6
5 changed files with 30 additions and 22 deletions
+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"
+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;
};