(frontend) allow local participant to update her name

The user name is initially set by the backend when generating the LiveKit access
token. By default, if the frontend has not provided a username, the backend uses
the user's email address. This approach isn't ideal, as some users prefer using
their first name.

This update allows local participant to change their username in real-time
during a session. However, these changes are not yet persisted for
future meetings. This persistence feature will be added in upcoming commits.
This commit is contained in:
lebaudantoine
2024-08-07 11:36:07 +02:00
committed by aleb_the_flash
parent fe8ed43aae
commit 37eea16a50
5 changed files with 91 additions and 7 deletions

View File

@@ -3,6 +3,7 @@ import {
RiFeedbackLine,
RiQuestionLine,
RiSettings3Line,
RiUser5Line,
} from '@remixicon/react'
import { useState } from 'react'
import { styled } from '@/styled-system/jsx'
@@ -10,8 +11,10 @@ import {
Menu as RACMenu,
MenuItem as RACMenuItem,
Popover as RACPopover,
Separator as RACSeparator,
} from 'react-aria-components'
import { SettingsDialog } from '@/features/settings'
import { UsernameDialog } from '../../dialogs/UsernameDialog'
// Styled components to be refactored
const StyledMenu = styled(RACMenu, {
@@ -60,13 +63,28 @@ const StyledPopover = styled(RACPopover, {
},
})
const StyledSeparator = styled(RACSeparator, {
base: {
height: '1px',
background: '#9ca3af',
margin: '2px 4px',
},
})
type DialogState = 'username' | 'settings' | null
export const OptionsMenu = () => {
const { t } = useTranslation('rooms')
const [isSettingsDialogOpen, setIsSettingsDialogOpen] = useState(false)
const [dialogOpen, setDialogOpen] = useState<DialogState>(null)
return (
<>
<StyledPopover>
<StyledMenu>
<StyledMenuItem onAction={() => setDialogOpen('username')}>
<RiUser5Line size={18} />
{t('options.items.username')}
</StyledMenuItem>
<StyledSeparator />
<StyledMenuItem
href="https://tchap.gouv.fr/#/room/!aGImQayAgBLjSBycpm:agent.dinum.tchap.gouv.fr?via=agent.dinum.tchap.gouv.fr"
target="_blank"
@@ -81,15 +99,19 @@ export const OptionsMenu = () => {
<RiFeedbackLine size={18} />
{t('options.items.feedbacks')}
</StyledMenuItem>
<StyledMenuItem onAction={() => setIsSettingsDialogOpen(true)}>
<StyledMenuItem onAction={() => setDialogOpen('settings')}>
<RiSettings3Line size={18} />
{t('options.items.settings')}
</StyledMenuItem>
</StyledMenu>
</StyledPopover>
<UsernameDialog
isOpen={dialogOpen === 'username'}
onOpenChange={(v) => !v && setDialogOpen(null)}
/>
<SettingsDialog
isOpen={isSettingsDialogOpen}
onOpenChange={(v) => setIsSettingsDialogOpen(v)}
isOpen={dialogOpen === 'settings'}
onOpenChange={(v) => !v && setDialogOpen(null)}
/>
</>
)

View File

@@ -0,0 +1,38 @@
import { useTranslation } from 'react-i18next'
import { Field, Form, Dialog, DialogProps } from '@/primitives'
import { useRoomContext } from '@livekit/components-react'
export type UsernameDialogProps = Pick<DialogProps, 'isOpen' | 'onOpenChange'>
export const UsernameDialog = (props: UsernameDialogProps) => {
const { t } = useTranslation('rooms')
const ctx = useRoomContext()
return (
<Dialog title={t('options.username.heading')} {...props}>
<Form
onSubmit={(data) => {
ctx.localParticipant.setName(data.username as string)
const { onOpenChange } = props
if (onOpenChange) {
onOpenChange(false)
}
}}
submitLabel={t('options.username.submitLabel')}
>
<Field
type="text"
name="username"
label={t('options.username.label')}
description={t('options.username.description')}
defaultValue={ctx.localParticipant.name}
validate={(value) => {
return !value ? (
<p>{t('options.username.validationError')}</p>
) : null
}}
/>
</Form>
</Dialog>
)
}

View File

@@ -36,7 +36,15 @@
"items": {
"feedbacks": "",
"support": "",
"settings": ""
"settings": "",
"username": ""
},
"username": {
"heading": "",
"label": "",
"description": "",
"validationError": "",
"submitLabel": ""
}
}
}

View File

@@ -36,7 +36,15 @@
"items": {
"feedbacks": "Give us feedbacks",
"support": "Get Help on Tchap",
"settings": "Settings"
"settings": "Settings",
"username": "Update Your Name"
},
"username": {
"heading": "Update Your Name",
"label": "Your Name",
"description": "All other participants will see this name.",
"validationError": "Name cannot be empty.",
"submitLabel": "Save"
}
}
}

View File

@@ -36,7 +36,15 @@
"items": {
"feedbacks": "Partager votre avis",
"support": "Obtenir de l'aide sur Tchap",
"settings": "Paramètres"
"settings": "Paramètres",
"username": "Choisir votre nom"
},
"username": {
"heading": "Choisir votre nom",
"label": "Votre Nom",
"description": "Tous les autres participants verront ce nom.",
"validationError": "Le nom ne peut pas être vide.",
"submitLabel": "Enregistrer"
}
}
}