♻️(frontend) move name update to AccountTab

User can now update their name in a dedicated Account tab,
inspired by Jitsi design. Removed the username dialog.

Account-related updates will be operated through the advanced
settings dialog, in this dedicated tab.
This commit is contained in:
lebaudantoine
2024-08-14 18:56:33 +02:00
committed by aleb_the_flash
parent 6a7ec95493
commit 12c27eedac
15 changed files with 100 additions and 102 deletions

View File

@@ -3,7 +3,6 @@ import { RiMore2Line } from '@remixicon/react'
import { Button, Menu } from '@/primitives'
import { useState } from 'react'
import { UsernameDialog } from '@/features/rooms/livekit/components/dialogs/UsernameDialog'
import { OptionsMenuItems } from '@/features/rooms/livekit/components/controls/Options/OptionsMenuItems'
import { SettingsDialogExtended } from '@/features/settings/components/SettingsDialogExtended'
@@ -25,10 +24,6 @@ export const OptionsButton = () => {
</Button>
<OptionsMenuItems onOpenDialog={setDialogOpen} />
</Menu>
<UsernameDialog
isOpen={dialogOpen === 'username'}
onOpenChange={(v) => !v && setDialogOpen(null)}
/>
<SettingsDialogExtended
isOpen={dialogOpen === 'settings'}
onOpenChange={(v) => !v && setDialogOpen(null)}

View File

@@ -3,26 +3,12 @@ import {
RiFeedbackLine,
RiQuestionLine,
RiSettings3Line,
RiUser5Line,
} from '@remixicon/react'
import { styled } from '@/styled-system/jsx'
import {
MenuItem,
Menu as RACMenu,
Separator as RACSeparator,
} from 'react-aria-components'
import { MenuItem, Menu as RACMenu } from 'react-aria-components'
import { useTranslation } from 'react-i18next'
import { Dispatch, SetStateAction } from 'react'
import { DialogState } from '@/features/rooms/livekit/components/controls/Options/OptionsButton'
const StyledSeparator = styled(RACSeparator, {
base: {
height: '1px',
background: 'gray.300',
margin: '4px 0',
},
})
// @todo try refactoring it to use MenuList component
export const OptionsMenuItems = ({
onOpenDialog,
@@ -38,14 +24,6 @@ export const OptionsMenuItems = ({
width: '300px',
}}
>
<MenuItem
className={menuItemRecipe({ icon: true })}
onAction={() => onOpenDialog('username')}
>
<RiUser5Line size={18} />
{t('options.items.username')}
</MenuItem>
<StyledSeparator />
<MenuItem
href="https://tchap.gouv.fr/#/room/!aGImQayAgBLjSBycpm:agent.dinum.tchap.gouv.fr?via=agent.dinum.tchap.gouv.fr"
target="_blank"

View File

@@ -1,44 +0,0 @@
import { useTranslation } from 'react-i18next'
import { Field, Form, Dialog, DialogProps } from '@/primitives'
import {
usePersistentUserChoices,
useRoomContext,
} from '@livekit/components-react'
export type UsernameDialogProps = Pick<DialogProps, 'isOpen' | 'onOpenChange'>
export const UsernameDialog = (props: UsernameDialogProps) => {
const { t } = useTranslation('rooms')
const { saveUsername } = usePersistentUserChoices()
const ctx = useRoomContext()
return (
<Dialog title={t('options.username.heading')} {...props}>
<Form
onSubmit={(data) => {
const { username } = data as { username: string }
ctx.localParticipant.setName(username)
saveUsername(username)
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

@@ -9,6 +9,7 @@ import {
RiSettings3Line,
RiSpeakerLine,
} from '@remixicon/react'
import { AccountTab } from './tabs/AccountTab'
const tabsStyle = css({
maxHeight: '40.625rem', // fixme size copied from meet settings modal
@@ -65,9 +66,7 @@ export const SettingsDialogExtended = (props: SettingsDialogExtended) => {
</TabList>
</div>
<div className={tabPanelContainerStyle}>
<TabPanel flex id="1">
There are your profile settings
</TabPanel>
<AccountTab id="1" onOpenChange={props.onOpenChange} />
<TabPanel flex id="2">
There are your audio settings
</TabPanel>

View File

@@ -0,0 +1,81 @@
import { A, Badge, Button, DialogProps, Field, H, P } from '@/primitives'
import { Trans, useTranslation } from 'react-i18next'
import {
usePersistentUserChoices,
useRoomContext,
} from '@livekit/components-react'
import { authUrl, logoutUrl, useUser } from '@/features/auth'
import { css } from '@/styled-system/css'
import { TabPanel, TabPanelProps } from '@/primitives/Tabs'
import { HStack } from '@/styled-system/jsx'
import { useState } from 'react'
export type AccountTabProps = Pick<DialogProps, 'onOpenChange'> &
Pick<TabPanelProps, 'id'>
export const AccountTab = ({ id, onOpenChange }: AccountTabProps) => {
const { t } = useTranslation('settings')
const { saveUsername } = usePersistentUserChoices()
const room = useRoomContext()
const { user, isLoggedIn } = useUser()
const [name, setName] = useState(room?.localParticipant.name || '')
const handleOnSubmit = () => {
if (room) room.localParticipant.setName(name)
saveUsername(name)
if (onOpenChange) onOpenChange(false)
}
const handleOnCancel = () => {
if (onOpenChange) onOpenChange(false)
}
return (
<TabPanel padding={'md'} flex id={id}>
<H lvl={2}>{t('account.heading')}</H>
<Field
type="text"
label={t('account.nameLabel')}
value={name}
onChange={setName}
validate={(value) => {
return !value ? <p>{'Votre Nom ne peut pas être vide'}</p> : null
}}
/>
<H lvl={2}>{t('account.authentication')}</H>
{isLoggedIn ? (
<>
<P>
<Trans
i18nKey="settings:account.currentlyLoggedAs"
values={{ user: user?.email }}
components={[<Badge />]}
/>
</P>
<P>
<A href={logoutUrl()}>{t('logout', { ns: 'global' })}</A>
</P>
</>
) : (
<>
<P>{t('account.youAreNotLoggedIn')}</P>
<P>
<A href={authUrl()}>{t('login', { ns: 'global' })}</A>
</P>
</>
)}
<HStack
className={css({
marginTop: 'auto',
marginLeft: 'auto',
})}
>
<Button onPress={handleOnCancel}>
{t('cancel', { ns: 'global' })}
</Button>
<Button variant={'primary'} onPress={handleOnSubmit}>
{t('submit', { ns: 'global' })}
</Button>
</HStack>
</TabPanel>
)
}

View File

@@ -16,5 +16,6 @@
"logout": "",
"notFound": {
"heading": ""
}
},
"submit": "OK"
}

View File

@@ -45,13 +45,6 @@
"support": "",
"settings": "",
"username": ""
},
"username": {
"heading": "",
"label": "",
"description": "",
"validationError": "",
"submitLabel": ""
}
},
"participants": {

View File

@@ -2,7 +2,9 @@
"account": {
"currentlyLoggedAs": "",
"heading": "",
"youAreNotLoggedIn": ""
"youAreNotLoggedIn": "",
"nameLabel": "",
"authentication": ""
},
"dialog": {
"heading": ""

View File

@@ -16,5 +16,6 @@
"logout": "Logout",
"notFound": {
"heading": "Page not found"
}
},
"submit": "OK"
}

View File

@@ -45,13 +45,6 @@
"support": "Get Help on Tchap",
"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"
}
},
"participants": {

View File

@@ -2,7 +2,9 @@
"account": {
"currentlyLoggedAs": "You are currently logged in as <0>{{user}}</0>",
"heading": "Account",
"youAreNotLoggedIn": "You are not logged in."
"youAreNotLoggedIn": "You are not logged in.",
"nameLabel": "Votre Nom",
"authentication": "Authentication"
},
"dialog": {
"heading": "Settings"

View File

@@ -16,5 +16,6 @@
"logout": "Se déconnecter",
"notFound": {
"heading": "Page introuvable"
}
},
"submit": "OK"
}

View File

@@ -45,13 +45,6 @@
"support": "Obtenir de l'aide sur Tchap",
"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"
}
},
"participants": {

View File

@@ -2,7 +2,9 @@
"account": {
"currentlyLoggedAs": "Vous êtes actuellement connecté en tant que <0>{{user}}</0>",
"heading": "Compte",
"youAreNotLoggedIn": "Vous n'êtes pas connecté."
"youAreNotLoggedIn": "Vous n'êtes pas connecté.",
"nameLabel": "Votre Nom",
"authentication": "Authentification"
},
"dialog": {
"heading": "Paramètres"

View File

@@ -162,6 +162,7 @@ const StyledTabPanel = styled(RACTabPanel, {
display: 'flex',
flexGrow: 1,
overflow: 'auto',
flexDirection: 'column', //fixme should be parameterizable
},
},
padding: {