From f9c03d5e334bc4a8686b9656ecbdaa8249bc9ae7 Mon Sep 17 00:00:00 2001 From: Jared Vititoe Date: Tue, 7 Jul 2026 20:58:10 -0400 Subject: [PATCH] fix(inputs): cap room-name / display-name length client-side (H10) The room-name (settings + create-room) and display-name inputs had no client-side length guard, so an over-long value only failed after a server round-trip. Add maxLength={255} (matching the existing inline-rename cap in RoomNavItem; under Synapse's 256 max_displayname_length). Also clamp the emoji-picker prepend in the two room-name fields, since programmatic setState isn't constrained by the DOM maxLength and could otherwise push past the cap. Co-Authored-By: Claude Opus 4.8 --- src/app/features/common-settings/general/RoomProfile.tsx | 5 ++++- src/app/features/create-room/CreateRoom.tsx | 5 ++++- src/app/features/settings/account/Profile.tsx | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/app/features/common-settings/general/RoomProfile.tsx b/src/app/features/common-settings/general/RoomProfile.tsx index 71cd53827..96dcb8157 100644 --- a/src/app/features/common-settings/general/RoomProfile.tsx +++ b/src/app/features/common-settings/general/RoomProfile.tsx @@ -122,7 +122,9 @@ export function RoomProfileEdit({ const [emojiAnchor, setEmojiAnchor] = useState(); const handleEmojiSelect = useCallback((unicode: string) => { - setNameValue((prev) => unicode + prev); + // Clamp to the same cap as the input's maxLength — programmatic setState isn't + // constrained by the DOM maxLength, so the picker could otherwise exceed it. + setNameValue((prev) => (unicode + prev).slice(0, 255)); setEmojiAnchor(undefined); }, []); @@ -309,6 +311,7 @@ export function RoomProfileEdit({ onChange={(e: React.ChangeEvent) => setNameValue(e.target.value)} variant="Secondary" radii="300" + maxLength={255} readOnly={!canEditName || submitting} style={{ width: '100%' }} /> diff --git a/src/app/features/create-room/CreateRoom.tsx b/src/app/features/create-room/CreateRoom.tsx index f844ae799..82340f4d2 100644 --- a/src/app/features/create-room/CreateRoom.tsx +++ b/src/app/features/create-room/CreateRoom.tsx @@ -102,7 +102,9 @@ export function CreateRoomForm({ const [emojiAnchor, setEmojiAnchor] = useState(); const handleEmojiSelect = useCallback((unicode: string) => { - setNameValue((prev) => unicode + prev); + // Clamp to the same cap as the input's maxLength — programmatic setState isn't + // constrained by the DOM maxLength, so the picker could otherwise exceed it. + setNameValue((prev) => (unicode + prev).slice(0, 255)); setEmojiAnchor(undefined); }, []); @@ -240,6 +242,7 @@ export function CreateRoomForm({ disabled={disabled} value={nameValue} onChange={(e: React.ChangeEvent) => setNameValue(e.target.value)} + maxLength={255} style={{ width: '100%' }} /> diff --git a/src/app/features/settings/account/Profile.tsx b/src/app/features/settings/account/Profile.tsx index a72b22154..c6ce2c0ff 100644 --- a/src/app/features/settings/account/Profile.tsx +++ b/src/app/features/settings/account/Profile.tsx @@ -285,6 +285,7 @@ function ProfileDisplayName({ profile, userId }: ProfileProps) { onChange={handleChange} variant="Secondary" radii="300" + maxLength={255} style={{ paddingRight: config.space.S200 }} readOnly={changingDisplayName || disableSetDisplayname} after={