(frontend) improve meeting code input accessibility for touch devices

Enhance meeting code input to accept codes without hyphens and make input
case-insensitive. Addresses usability issue observed with touch screen and
virtual keyboard users who struggled with precise formatting. Improves
accessibility for users with pointing pens and limited input precision.

requested by @spaccoud
This commit is contained in:
lebaudantoine
2025-05-06 23:16:19 +02:00
committed by aleb_the_flash
parent 2e8407ac7c
commit 563f1e4c0f
4 changed files with 35 additions and 4 deletions

View File

@@ -1,5 +1,9 @@
export { Room as RoomRoute } from './routes/Room'
export { FeedbackRoute } from './routes/Feedback'
export { roomIdPattern, isRoomValid } from './utils/isRoomValid'
export {
roomIdPattern,
isRoomValid,
flexibleRoomIdPattern,
} from './utils/isRoomValid'
export { generateRoomId } from './utils/generateRoomId'
export { useCreateRoom } from './api/createRoom'

View File

@@ -3,13 +3,17 @@ import {
usePersistentUserChoices,
type LocalUserChoices as LocalUserChoicesLK,
} from '@livekit/components-react'
import { useParams } from 'wouter'
import { useLocation, useParams } from 'wouter'
import { ErrorScreen } from '@/components/ErrorScreen'
import { useUser, UserAware } from '@/features/auth'
import { Conference } from '../components/Conference'
import { Join } from '../components/Join'
import { useKeyboardShortcuts } from '@/features/shortcuts/useKeyboardShortcuts'
import { ProcessorSerialized } from '../livekit/components/blur'
import {
isRoomValid,
normalizeRoomId,
} from '@/features/rooms/utils/isRoomValid'
export type LocalUserChoices = LocalUserChoicesLK & {
processorSerialized?: ProcessorSerialized
@@ -21,6 +25,7 @@ export const Room = () => {
const [userConfig, setUserConfig] = useState<LocalUserChoices | null>(null)
const { roomId } = useParams()
const [location, setLocation] = useLocation()
const initialRoomData = history.state?.initialRoomData
const mode = isLoggedIn && history.state?.create ? 'create' : 'join'
const skipJoinScreen = isLoggedIn && mode === 'create'
@@ -40,6 +45,12 @@ export const Room = () => {
}
}, [])
useEffect(() => {
if (roomId && !isRoomValid(roomId)) {
setLocation(normalizeRoomId(roomId))
}
}, [roomId, setLocation, location])
if (!roomId) {
return <ErrorScreen />
}

View File

@@ -1,5 +1,17 @@
export const roomIdPattern = '[a-z]{3}-[a-z]{4}-[a-z]{3}'
// Case-insensitive and with optional hyphens
export const flexibleRoomIdPattern =
'(?:[a-zA-Z0-9]{3}-?[a-zA-Z0-9]{4}-?[a-zA-Z0-9]{3})'
export const isRoomValid = (roomIdOrUrl: string) =>
new RegExp(`^${roomIdPattern}$`).test(roomIdOrUrl) ||
new RegExp(`^${window.location.origin}/${roomIdPattern}$`).test(roomIdOrUrl)
export const normalizeRoomId = (roomId: string) => {
const cleanId = roomId.toLowerCase().replace(/-/g, '')
if (cleanId.length === 10) {
return `${cleanId.slice(0, 3)}-${cleanId.slice(3, 7)}-${cleanId.slice(7, 10)}`
}
return roomId
}

View File

@@ -1,4 +1,8 @@
import { FeedbackRoute, RoomRoute, roomIdPattern } from '@/features/rooms'
import {
FeedbackRoute,
RoomRoute,
flexibleRoomIdPattern,
} from '@/features/rooms'
import { HomeRoute } from '@/features/home'
import { LegalTermsRoute } from '@/features/legalsTerms/LegalTermsRoute'
import { AccessibilityRoute } from '@/features/legalsTerms/Accessibility'
@@ -32,8 +36,8 @@ export const routes: Record<
},
room: {
name: 'room',
path: new RegExp(`^[/](?<roomId>${roomIdPattern})$`),
to: (roomId: string) => `/${roomId.trim()}`,
path: new RegExp(`^[/](?<roomId>${flexibleRoomIdPattern})$`),
Component: RoomRoute,
},
feedback: {