fix: comprehensive P0 quality pass — audit findings resolved
- ReportRoomModal: use mx.reportRoom() SDK method, fix undefined CSS vars
(--mx-surface/border → folds color tokens), add role/aria-modal/aria-labelledby,
accessible select/input labels, per-error-code messages, auto-close on success
- About.tsx: clickable matrix_id + email_address links (Text as="a"), AbortController
cleanup, runtime JSON type guard, loading state, role display for all role values,
remove classList theming hack, use mx.getHomeserverUrl()
- RoomViewHeader: useLocalRoomName for header title, useReportRoomSupported gate,
hide Invite/Settings/Report for server notice rooms, isCreator guard on Report,
FocusTrap returnFocusOnDeactivate on topic overlay, Server Notice chip tooltip
- RoomInput: replace raw <div> with folds <Box> for server notice read-only message
- EditHistoryModal: isRawEditEvent type guard, handle next_batch truncation,
getVersionBody handles formatted_body (strips HTML for text display),
role/aria-modal/aria-labelledby accessibility, guard for undefined eventId,
use config.space tokens (remove var(--mx-spacing-*) strings)
- RoomNavItem: remove duplicate getExistingContent (use exported getLocalRoomNamesContent),
maxLength={255} on rename input, fix FocusTrap nesting (renameDialog state moved to
RoomNavItem_, RenameRoomDialog rendered outside menu, menu closes before dialog opens),
pencil icon opacity via config.opacity.P300
- useRoomMeta: export getLocalRoomNamesContent for reuse
- RoomIntro: useLocalRoomName, formatted topic viewer with Overlay/FocusTrap/RoomTopicViewer
- CallRoomName: useLocalRoomName for consistent rename display in call overlay
- General.tsx: fix #980000/#FF6B00 hardcoded hex → color tokens/CSS vars, URL Preview
capitalization, improved encrypted preview warning text + Warning chip, add
description to plain urlPreview setting
- sanitize.ts: fix hex color regex to support 3/4/6/8 digit hex (CSS4 #RGBA, #RRGGBBAA)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -61,7 +61,7 @@ import { getRoomPermissionsAPI, useRoomPermissions } from '../../hooks/useRoomPe
|
||||
import { InviteUserPrompt } from '../../components/invite-user-prompt';
|
||||
import {
|
||||
LOCAL_ROOM_NAMES_KEY,
|
||||
LocalRoomNamesContent,
|
||||
getLocalRoomNamesContent,
|
||||
useHasLocalRoomName,
|
||||
useLocalRoomName,
|
||||
} from '../../hooks/useRoomMeta';
|
||||
@@ -82,29 +82,15 @@ function RenameRoomDialog({ room, onClose }: RenameRoomDialogProps) {
|
||||
const mx = useMatrixClient();
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const getExistingContent = useCallback((): LocalRoomNamesContent => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const raw: unknown = (mx as any).getAccountData(LOCAL_ROOM_NAMES_KEY)?.getContent();
|
||||
if (
|
||||
raw &&
|
||||
typeof raw === 'object' &&
|
||||
'rooms' in raw &&
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
typeof (raw as any).rooms === 'object'
|
||||
) {
|
||||
return raw as LocalRoomNamesContent;
|
||||
}
|
||||
return { rooms: {} };
|
||||
}, [mx]);
|
||||
|
||||
const getCurrentLocalName = useCallback((): string => {
|
||||
const content = getExistingContent();
|
||||
const content = getLocalRoomNamesContent(mx);
|
||||
return content.rooms[room.roomId] ?? '';
|
||||
}, [getExistingContent, room.roomId]);
|
||||
}, [mx, room.roomId]);
|
||||
|
||||
const handleSave = useCallback(() => {
|
||||
const newName = inputRef.current?.value.trim() ?? '';
|
||||
const existing = getExistingContent();
|
||||
if (newName.length > 255) return;
|
||||
const existing = getLocalRoomNamesContent(mx);
|
||||
if (newName === '') {
|
||||
const { [room.roomId]: _removed, ...rest } = existing.rooms;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
@@ -116,15 +102,15 @@ function RenameRoomDialog({ room, onClose }: RenameRoomDialogProps) {
|
||||
});
|
||||
}
|
||||
onClose();
|
||||
}, [mx, room.roomId, getExistingContent, onClose]);
|
||||
}, [mx, room.roomId, onClose]);
|
||||
|
||||
const handleClear = useCallback(() => {
|
||||
const existing = getExistingContent();
|
||||
const existing = getLocalRoomNamesContent(mx);
|
||||
const { [room.roomId]: _removed, ...rest } = existing.rooms;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(mx as any).setAccountData(LOCAL_ROOM_NAMES_KEY, { rooms: rest });
|
||||
onClose();
|
||||
}, [mx, room.roomId, getExistingContent, onClose]);
|
||||
}, [mx, room.roomId, onClose]);
|
||||
|
||||
const handleKeyDown = (evt: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
if (evt.key === 'Enter') handleSave();
|
||||
@@ -169,6 +155,7 @@ function RenameRoomDialog({ room, onClose }: RenameRoomDialogProps) {
|
||||
placeholder={room.name}
|
||||
variant="Secondary"
|
||||
radii="300"
|
||||
maxLength={255}
|
||||
onKeyDown={handleKeyDown}
|
||||
autoFocus
|
||||
/>
|
||||
@@ -210,10 +197,11 @@ function RenameRoomDialog({ room, onClose }: RenameRoomDialogProps) {
|
||||
type RoomNavItemMenuProps = {
|
||||
room: Room;
|
||||
requestClose: () => void;
|
||||
onRenameClick: () => void;
|
||||
notificationMode?: RoomNotificationMode;
|
||||
};
|
||||
const RoomNavItemMenu = forwardRef<HTMLDivElement, RoomNavItemMenuProps>(
|
||||
({ room, requestClose, notificationMode }, ref) => {
|
||||
({ room, requestClose, onRenameClick, notificationMode }, ref) => {
|
||||
const mx = useMatrixClient();
|
||||
const [hideActivity] = useSetting(settingsAtom, 'hideActivity');
|
||||
const unread = useRoomUnread(room.roomId, roomToUnreadAtom);
|
||||
@@ -226,7 +214,6 @@ const RoomNavItemMenu = forwardRef<HTMLDivElement, RoomNavItemMenuProps>(
|
||||
const space = useSpaceOptionally();
|
||||
|
||||
const [invitePrompt, setInvitePrompt] = useState(false);
|
||||
const [renameDialog, setRenameDialog] = useState(false);
|
||||
|
||||
const handleMarkAsRead = () => {
|
||||
markAsRead(mx, room.roomId, hideActivity);
|
||||
@@ -260,15 +247,6 @@ const RoomNavItemMenu = forwardRef<HTMLDivElement, RoomNavItemMenuProps>(
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{renameDialog && (
|
||||
<RenameRoomDialog
|
||||
room={room}
|
||||
onClose={() => {
|
||||
setRenameDialog(false);
|
||||
requestClose();
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<Box direction="Column" gap="100" style={{ padding: config.space.S100 }}>
|
||||
<MenuItem
|
||||
onClick={handleMarkAsRead}
|
||||
@@ -330,11 +308,13 @@ const RoomNavItemMenu = forwardRef<HTMLDivElement, RoomNavItemMenuProps>(
|
||||
</Text>
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
onClick={() => setRenameDialog(true)}
|
||||
onClick={() => {
|
||||
requestClose();
|
||||
onRenameClick();
|
||||
}}
|
||||
size="300"
|
||||
after={<Icon size="100" src={Icons.Pencil} />}
|
||||
radii="300"
|
||||
aria-pressed={renameDialog}
|
||||
>
|
||||
<Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
|
||||
Rename for me…
|
||||
@@ -425,6 +405,7 @@ function RoomNavItem_({
|
||||
const { hoverProps } = useHover({ onHoverChange: setHover });
|
||||
const { focusWithinProps } = useFocusWithin({ onFocusWithinChange: setHover });
|
||||
const [menuAnchor, setMenuAnchor] = useState<RectCords>();
|
||||
const [renameDialog, setRenameDialog] = useState(false);
|
||||
const unread = useRoomUnread(room.roomId, roomToUnreadAtom);
|
||||
const typingMember = useRoomTypingMember(room.roomId).filter(
|
||||
(receipt) => receipt.userId !== mx.getUserId(),
|
||||
@@ -533,7 +514,7 @@ function RoomNavItem_({
|
||||
size="50"
|
||||
src={Icons.Pencil}
|
||||
aria-label="Custom local name"
|
||||
style={{ opacity: 0.6, flexShrink: 0 }}
|
||||
style={{ opacity: config.opacity.P300, flexShrink: 0 }}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
@@ -592,6 +573,7 @@ function RoomNavItem_({
|
||||
<RoomNavItemMenu
|
||||
room={room}
|
||||
requestClose={() => setMenuAnchor(undefined)}
|
||||
onRenameClick={() => setRenameDialog(true)}
|
||||
notificationMode={notificationMode}
|
||||
/>
|
||||
</FocusTrap>
|
||||
@@ -612,6 +594,9 @@ function RoomNavItem_({
|
||||
</PopOut>
|
||||
</NavItemOptions>
|
||||
)}
|
||||
{renameDialog && (
|
||||
<RenameRoomDialog room={room} onClose={() => setRenameDialog(false)} />
|
||||
)}
|
||||
</NavItem>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user