mirror of
https://github.com/suitenumerique/meet.git
synced 2026-11-15 12:34:29 +00:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e7d47afb49 | |||
| c80e9ef3ef | |||
| e80dfc3305 | |||
| 2eea8e6c18 |
@@ -61,8 +61,6 @@ La Suite Meet is fully self-hostable and released under the MIT License, ensurin
|
||||
|
||||
We’re continuously adding new features to enhance your experience, with the latest updates coming soon!
|
||||
|
||||
⭐ **Find La Suite Meet useful?** Click the Star button at the top right of this page. It helps other people and public organisations discover the project.
|
||||
|
||||
### 🚀 Major roll out to all French public servants
|
||||
|
||||
On the 29th of January 2026, Prime Minister Sébastien Lecornu, announced the full deployment of Visio—the French government’s dedicated Meet platform—to all public servants. ([Source in English](https://www.nytimes.com/2026/01/29/world/europe/france-zoom-alternative-visio.html))
|
||||
|
||||
@@ -36,9 +36,6 @@ const config: Config = {
|
||||
jsxFramework: 'react',
|
||||
outdir: 'src/styled-system',
|
||||
globalFontface: {},
|
||||
globalVars: {
|
||||
'--global-font-body': 'var(--fonts-sans)',
|
||||
},
|
||||
theme: {
|
||||
...pandaPreset.theme,
|
||||
// media queries are defined in em so that zooming with text-only mode triggers breakpoints
|
||||
|
||||
@@ -7,11 +7,7 @@ import {
|
||||
} from 'react-aria-components'
|
||||
import { RiArrowDownSFill } from '@remixicon/react'
|
||||
import { css, cx } from '@/styled-system/css'
|
||||
import {
|
||||
DIAGNOSTIC_OUTPUT_LANG,
|
||||
getSummaryLang,
|
||||
type ConnectionTestStepResult,
|
||||
} from '../types'
|
||||
import type { ConnectionTestStepResult } from '../types'
|
||||
import { StepStatusIndicator } from './StepStatusIndicator'
|
||||
|
||||
/** Each step is its own bounded card, collapsed or not. */
|
||||
@@ -69,7 +65,7 @@ const labelClass = css({
|
||||
const valueClass = css({
|
||||
fontFamily: 'mono',
|
||||
textStyle: 'xs',
|
||||
color: 'greyscale.600',
|
||||
color: 'greyscale.500',
|
||||
overflowWrap: 'anywhere',
|
||||
})
|
||||
|
||||
@@ -114,11 +110,7 @@ const StepRowContent = ({ step }: { step: ConnectionTestStepResult }) => {
|
||||
<>
|
||||
<span className={identityClass}>
|
||||
<span className={labelClass}>{t(`steps.${step.id}`)}</span>
|
||||
{step.summary && (
|
||||
<span className={valueClass} lang={getSummaryLang(step)}>
|
||||
{step.summary}
|
||||
</span>
|
||||
)}
|
||||
{step.summary && <span className={valueClass}>{step.summary}</span>}
|
||||
</span>
|
||||
<StepStatusIndicator
|
||||
status={step.status}
|
||||
@@ -178,7 +170,7 @@ export const ConnectionTestStepRow = ({
|
||||
{/* Collapsed panels stay in the DOM for aria-controls, but the log
|
||||
lines themselves are only mounted when actually visible. */}
|
||||
{isExpanded && (
|
||||
<ul className={logListClass} lang={DIAGNOSTIC_OUTPUT_LANG}>
|
||||
<ul className={logListClass}>
|
||||
{step.logs?.map((log, index) => (
|
||||
<li key={`${log.level}-${index}`} className={logItemClass}>
|
||||
{log.message}
|
||||
|
||||
@@ -153,7 +153,7 @@ const counterValueClass = css({
|
||||
})
|
||||
|
||||
/** A zero count is context, not a result: it recedes instead of shouting. */
|
||||
const emptyCounterClass = css({ color: 'greyscale.600' })
|
||||
const emptyCounterClass = css({ color: 'greyscale.400' })
|
||||
const emptySquareClass = css({
|
||||
backgroundColor: 'transparent!',
|
||||
border: '1px solid {colors.greyscale.250}',
|
||||
|
||||
@@ -25,10 +25,10 @@ export const statusSquareClass: Record<ConnectionTestStepStatus, string> = {
|
||||
* failure and warning.
|
||||
*/
|
||||
export const statusTextClass: Record<ConnectionTestStepStatus, string> = {
|
||||
pending: css({ color: 'greyscale.600' }),
|
||||
pending: css({ color: 'greyscale.500' }),
|
||||
running: css({ color: 'greyscale.700' }),
|
||||
success: css({ color: 'greyscale.1000' }),
|
||||
warning: css({ color: 'warning', fontWeight: 'medium' }),
|
||||
failed: css({ color: 'danger.600', fontWeight: 'medium' }),
|
||||
skipped: css({ color: 'greyscale.600' }),
|
||||
skipped: css({ color: 'greyscale.500' }),
|
||||
}
|
||||
|
||||
@@ -136,16 +136,14 @@ const ConnectionTest = () => {
|
||||
<h2 className={sectionTitleClass}>
|
||||
{t(`groups.${group.id}`)}
|
||||
</h2>
|
||||
<ul className={rowsClass}>
|
||||
<div className={rowsClass}>
|
||||
{group.steps.map((id) => {
|
||||
const step = stepsById.get(id)
|
||||
return step ? (
|
||||
<li key={id}>
|
||||
<ConnectionTestStepRow step={step} />
|
||||
</li>
|
||||
<ConnectionTestStepRow key={id} step={step} />
|
||||
) : null
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
))}
|
||||
|
||||
|
||||
@@ -32,23 +32,6 @@ export type ConnectionTestStepResult = {
|
||||
data?: Record<string, unknown>
|
||||
}
|
||||
|
||||
export const DIAGNOSTIC_OUTPUT_LANG = 'en'
|
||||
|
||||
const LANGUAGE_NEUTRAL_STEPS: ReadonlySet<ConnectionTestStepId> = new Set([
|
||||
'browser',
|
||||
'microphone',
|
||||
'camera',
|
||||
'devices',
|
||||
])
|
||||
|
||||
export const getSummaryLang = ({
|
||||
id,
|
||||
status,
|
||||
}: Pick<ConnectionTestStepResult, 'id' | 'status'>) =>
|
||||
LANGUAGE_NEUTRAL_STEPS.has(id) && status === 'success'
|
||||
? undefined
|
||||
: DIAGNOSTIC_OUTPUT_LANG
|
||||
|
||||
export type ConnectionTestGroupId = 'local' | 'network'
|
||||
|
||||
/** Display order: everything local first, then everything that leaves the machine. */
|
||||
|
||||
@@ -41,23 +41,18 @@ const Image = styled('img', {
|
||||
const Dot = styled('div', {
|
||||
base: {
|
||||
borderRadius: '50%',
|
||||
borderStyle: 'solid',
|
||||
borderWidth: '1px',
|
||||
boxSizing: 'border-box',
|
||||
display: 'inline-block',
|
||||
height: '.5rem',
|
||||
height: '.375rem',
|
||||
margin: '0 .25rem',
|
||||
width: '.5rem',
|
||||
width: '.375rem',
|
||||
},
|
||||
variants: {
|
||||
selected: {
|
||||
true: {
|
||||
backgroundColor: 'primary.800',
|
||||
borderColor: 'primary.800',
|
||||
},
|
||||
false: {
|
||||
backgroundColor: 'primary.100',
|
||||
borderColor: 'primary.500',
|
||||
backgroundColor: 'primary.300',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Button, Div, Text } from '@/primitives'
|
||||
import { Button, Div, H, Text } from '@/primitives'
|
||||
|
||||
import { css } from '@/styled-system/css'
|
||||
import { useRoomId } from '@/features/rooms/livekit/hooks/useRoomId'
|
||||
@@ -189,9 +189,9 @@ export const ScreenRecordingSidePanel = () => {
|
||||
})}
|
||||
/>
|
||||
<VStack gap={0} marginBottom={15}>
|
||||
<Text as="h2" variant="h1" margin="sm" fullWidth>
|
||||
<H lvl={1} margin={'sm'} fullWidth>
|
||||
{t('heading')}
|
||||
</Text>
|
||||
</H>
|
||||
<LimitDescription
|
||||
keyPrefix={'screenRecording'}
|
||||
supportArticleLink={data?.support?.help_article_recording}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { A, Button, Div, Text } from '@/primitives'
|
||||
import { A, Button, Div, H, Text } from '@/primitives'
|
||||
|
||||
import { css } from '@/styled-system/css'
|
||||
import { useRoomId } from '@/features/rooms/livekit/hooks/useRoomId'
|
||||
@@ -203,9 +203,9 @@ export const TranscriptSidePanel = () => {
|
||||
})}
|
||||
/>
|
||||
<VStack gap={0} marginBottom={15}>
|
||||
<Text as="h2" variant="h1" margin="sm" fullWidth>
|
||||
<H lvl={1} margin={'sm'}>
|
||||
{t('heading')}
|
||||
</Text>
|
||||
</H>
|
||||
<LimitDescription
|
||||
keyPrefix={'transcript'}
|
||||
supportArticleLink={data?.support?.help_article_transcript}
|
||||
@@ -240,9 +240,6 @@ export const TranscriptSidePanel = () => {
|
||||
<Button
|
||||
variant="text"
|
||||
size="xs"
|
||||
aria-label={t('details.languageAriaLabel', {
|
||||
language: selectedLanguageLabel,
|
||||
})}
|
||||
onPress={() =>
|
||||
openSettingsDialog(SettingsDialogExtendedKey.TRANSCRIPTION)
|
||||
}
|
||||
|
||||
@@ -102,93 +102,46 @@ export const SettingsDialogExtended = (props: SettingsDialogExtended) => {
|
||||
</Heading>
|
||||
)}
|
||||
<TabList border={false}>
|
||||
<Tab
|
||||
icon
|
||||
highlight
|
||||
id={SettingsDialogExtendedKey.ACCOUNT}
|
||||
aria-label={t(`tabs.${SettingsDialogExtendedKey.ACCOUNT}`)}
|
||||
>
|
||||
<Tab icon highlight id={SettingsDialogExtendedKey.ACCOUNT}>
|
||||
<RiAccountCircleLine />
|
||||
{isWideScreen && t(`tabs.${SettingsDialogExtendedKey.ACCOUNT}`)}
|
||||
</Tab>
|
||||
<Tab
|
||||
icon
|
||||
highlight
|
||||
id={SettingsDialogExtendedKey.AUDIO}
|
||||
aria-label={t(`tabs.${SettingsDialogExtendedKey.AUDIO}`)}
|
||||
>
|
||||
<Tab icon highlight id={SettingsDialogExtendedKey.AUDIO}>
|
||||
<RiSpeakerLine />
|
||||
{isWideScreen && t(`tabs.${SettingsDialogExtendedKey.AUDIO}`)}
|
||||
</Tab>
|
||||
<Tab
|
||||
icon
|
||||
highlight
|
||||
id={SettingsDialogExtendedKey.VIDEO}
|
||||
aria-label={t(`tabs.${SettingsDialogExtendedKey.VIDEO}`)}
|
||||
>
|
||||
<Tab icon highlight id={SettingsDialogExtendedKey.VIDEO}>
|
||||
<RiVideoOnLine />
|
||||
{isWideScreen && t(`tabs.${SettingsDialogExtendedKey.VIDEO}`)}
|
||||
</Tab>
|
||||
<Tab
|
||||
icon
|
||||
highlight
|
||||
id={SettingsDialogExtendedKey.GENERAL}
|
||||
aria-label={t(`tabs.${SettingsDialogExtendedKey.GENERAL}`)}
|
||||
>
|
||||
<Tab icon highlight id={SettingsDialogExtendedKey.GENERAL}>
|
||||
<RiSettings3Line />
|
||||
{isWideScreen && t(`tabs.${SettingsDialogExtendedKey.GENERAL}`)}
|
||||
</Tab>
|
||||
<Tab
|
||||
icon
|
||||
highlight
|
||||
id={SettingsDialogExtendedKey.NOTIFICATIONS}
|
||||
aria-label={t(`tabs.${SettingsDialogExtendedKey.NOTIFICATIONS}`)}
|
||||
>
|
||||
<Tab icon highlight id={SettingsDialogExtendedKey.NOTIFICATIONS}>
|
||||
<RiNotification3Line />
|
||||
{isWideScreen &&
|
||||
t(`tabs.${SettingsDialogExtendedKey.NOTIFICATIONS}`)}
|
||||
</Tab>
|
||||
<Tab
|
||||
icon
|
||||
highlight
|
||||
id={SettingsDialogExtendedKey.SHORTCUTS}
|
||||
aria-label={t(`tabs.${SettingsDialogExtendedKey.SHORTCUTS}`)}
|
||||
>
|
||||
<Tab icon highlight id={SettingsDialogExtendedKey.SHORTCUTS}>
|
||||
<RiKeyboardBoxLine />
|
||||
{isWideScreen && t(`tabs.${SettingsDialogExtendedKey.SHORTCUTS}`)}
|
||||
</Tab>
|
||||
{isAdminOrOwner && (
|
||||
<Tab
|
||||
icon
|
||||
highlight
|
||||
id={SettingsDialogExtendedKey.TRANSCRIPTION}
|
||||
aria-label={t(
|
||||
`tabs.${SettingsDialogExtendedKey.TRANSCRIPTION}`
|
||||
)}
|
||||
>
|
||||
<Tab icon highlight id={SettingsDialogExtendedKey.TRANSCRIPTION}>
|
||||
<Icon name="speech_to_text" />
|
||||
{isWideScreen &&
|
||||
t(`tabs.${SettingsDialogExtendedKey.TRANSCRIPTION}`)}
|
||||
</Tab>
|
||||
)}
|
||||
{showRecordingTab && (
|
||||
<Tab
|
||||
icon
|
||||
highlight
|
||||
id={SettingsDialogExtendedKey.RECORDING}
|
||||
aria-label={t(`tabs.${SettingsDialogExtendedKey.RECORDING}`)}
|
||||
>
|
||||
<Tab icon highlight id={SettingsDialogExtendedKey.RECORDING}>
|
||||
<RiRecordCircleLine />
|
||||
{isWideScreen &&
|
||||
t(`tabs.${SettingsDialogExtendedKey.RECORDING}`)}
|
||||
</Tab>
|
||||
)}
|
||||
<Tab
|
||||
icon
|
||||
highlight
|
||||
id={SettingsDialogExtendedKey.ACCESSIBILITY}
|
||||
aria-label={t(`tabs.${SettingsDialogExtendedKey.ACCESSIBILITY}`)}
|
||||
>
|
||||
<Tab icon highlight id={SettingsDialogExtendedKey.ACCESSIBILITY}>
|
||||
<RiEyeLine />
|
||||
{isWideScreen &&
|
||||
t(`tabs.${SettingsDialogExtendedKey.ACCESSIBILITY}`)}
|
||||
|
||||
@@ -19,7 +19,6 @@ export const useLanguageLabels = () => {
|
||||
key: lang,
|
||||
value: lang,
|
||||
label: languageLabels[lang],
|
||||
lang,
|
||||
}))
|
||||
return {
|
||||
languagesList,
|
||||
|
||||
@@ -492,7 +492,6 @@
|
||||
"destination": "Ein neues Dokument wird erstellt auf",
|
||||
"destinationUnknown": "Ein neues Dokument wird erstellt",
|
||||
"language": "Meeting-Sprache:",
|
||||
"languageAriaLabel": "{{language}}, Meeting-Sprache ändern",
|
||||
"recording": "Auch eine Videoaufzeichnung starten"
|
||||
},
|
||||
"button": {
|
||||
|
||||
@@ -492,7 +492,6 @@
|
||||
"destination": "A new document will be created on",
|
||||
"destinationUnknown": "A new document will be created",
|
||||
"language": "Meeting language:",
|
||||
"languageAriaLabel": "{{language}}, change the meeting language",
|
||||
"recording": "Also start a video recording"
|
||||
},
|
||||
"button": {
|
||||
|
||||
@@ -491,7 +491,6 @@
|
||||
"destination": "Se creará un nuevo documento en",
|
||||
"destinationUnknown": "Se creará un nuevo documento",
|
||||
"language": "Idioma de la reunión:",
|
||||
"languageAriaLabel": "{{language}}, cambiar el idioma de la reunión",
|
||||
"recording": "Iniciar también una grabación de vídeo"
|
||||
},
|
||||
"button": {
|
||||
|
||||
@@ -492,7 +492,6 @@
|
||||
"destination": "Un nouveau document sera créé sur",
|
||||
"destinationUnknown": "Un nouveau document sera créé",
|
||||
"language": "Langue de la réunion :",
|
||||
"languageAriaLabel": "{{language}}, modifier la langue de la réunion",
|
||||
"recording": "Démarrer aussi un enregistrement vidéo"
|
||||
},
|
||||
"button": {
|
||||
|
||||
@@ -492,7 +492,6 @@
|
||||
"destination": "Er wordt een nieuw document aangemaakt op",
|
||||
"destinationUnknown": "Een nieuw document wordt aangemaakt",
|
||||
"language": "Vergadertalen:",
|
||||
"languageAriaLabel": "{{language}}, vergadertaal wijzigen",
|
||||
"recording": "Start ook een video-opname"
|
||||
},
|
||||
"button": {
|
||||
|
||||
@@ -492,7 +492,6 @@
|
||||
"destination": "Um novo documento será criado em",
|
||||
"destinationUnknown": "Um novo documento será criado",
|
||||
"language": "Idioma da reunião:",
|
||||
"languageAriaLabel": "{{language}}, alterar o idioma da reunião",
|
||||
"recording": "Também iniciar uma gravação"
|
||||
},
|
||||
"button": {
|
||||
|
||||
@@ -95,7 +95,7 @@ export type SelectProps<T> = Omit<
|
||||
> & {
|
||||
iconComponent?: RemixiconComponentType
|
||||
label: ReactNode
|
||||
items: Array<{ value: T; label: ReactNode; lang?: string }>
|
||||
items: Array<{ value: T; label: ReactNode }>
|
||||
errors?: ReactNode
|
||||
placement?: Placement
|
||||
variant?: 'light' | 'dark'
|
||||
@@ -150,11 +150,7 @@ export const Select = <T extends string | number>({
|
||||
>
|
||||
{({ isSelected }) => (
|
||||
<>
|
||||
{item.lang ? (
|
||||
<span lang={item.lang}>{item.label}</span>
|
||||
) : (
|
||||
item.label
|
||||
)}
|
||||
{item.label}
|
||||
{isSelected && (
|
||||
<VisuallyHidden>, {t('selected')}</VisuallyHidden>
|
||||
)}
|
||||
|
||||
@@ -6,13 +6,6 @@ body,
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* RGAA 10.5: every text color must be paired with a declared background
|
||||
color, so custom browser or system colors cannot make text unreadable. */
|
||||
body {
|
||||
background-color: var(--colors-default-bg);
|
||||
color: var(--colors-default-text);
|
||||
}
|
||||
|
||||
:root {
|
||||
--avatar-cap-height: 0.7;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user