Icon fonts were loading just in time, which is good for performance, but caused
a visible blink where fallback text appeared before the font loaded. I followed
the documentation introduced in PR 963 of the fontsource repository.
This introduces preloading for critical fonts, slightly increases initial load
time, and defines custom @font-face rules to control font-display and avoid
font swapping. This approach only works with Vite-based frameworks,
as noted in the documentation.
See the advanced installation section for material-symbols-outlined on
fontsource.org, and apply the same approach for Material Icons.
I manually built the preload headers based on a comment from issue #83.
This works well with Vite, which replaces the font URLs at build time.
Encapsulate icon and symbol rendering in a dedicated component that applies
aria-hidden and disables translation attributes.
This prevents browsers from translating icon names and breaking the UI, and
ensures screen readers do not announce decorative icons.
This is a first draft and can be extended with additional variants later.
Refactor the duplicateIdentity boolean URL parameter into an extensible string
reason parameter, making it easier to customize the disconnection message
shown to users.
Avoid passing this value via URL parameters, which are easy to manipulate.
Instead, use Wouter’s built-in navigation state to pass data across pages.
This was initially missed because navigateTo is a wrapper around Wouter’s
official navigation function, and its arguments were easy to overlook. This is
now fixed.
This prepares the ground for supporting additional disconnection reasons in
upcoming commits.
Hide non-essential icons and refine the labels to emphasize that one option
applies a stronger blur than the other. This should provide clearer cues for
screen reader users.
While this makes it slightly less explicit that clicking an already selected
option will disable the active effect, it improves accessibility by avoiding
automatic focus movement from the previously active option to a separate “none”
option. That focus shift could be misleading or hard to follow
for screen reader users.
Open to feedback on this decision.
Update the virtual background effects tooltip and ARIA label with more
descriptive and concise wording based on Sophie’s feedback. This helps all
users, especially those using assistive technologies, by improving how
each virtual background is vocalized.
Allow configuring whether a VAD model runs before calling an external ASR API.
Running VAD can save API calls (and costs) when no audible sound is detected,
but comes with the trade-off of additional computational overhead.
Subtitles were still visible when leaving and rejoining a meeting, even though
the backend API call to start them was not triggered again.
Introduce a hook that closes the subtitles layout on unmount, ensuring users
must explicitly click the button to restart subtitles when they rejoin a room.
Enhance the terms of service by adding detailed sections on
service availability, security, support management,
and monitoring of service use. This update aims to provide clearer
guidelines and responsibilities for users and the DINUM administration.
Based on a request from our European partners, introduce new languages for the
transcription feature. Dutch and German are now supported, which is a great
addition.
It closes#837.
WhisperX is expected to support both languages.
Simplify a broken conditional check that allowed users without
the required permissions to see the control menu. The `NoAccessView`
is now shown to any user who is neither an admin nor the meeting owner.
After upgrading Python to 3.13, not all development environments were
updated accordingly. This fixes the incorrect volume mount path
introduced by that upgrade.
Fix MinIO client configuration: I was incorrectly passing a full URL instead of
an endpoint, which caused errors in staging. Local development values did not
reflect the staging setup and were also out of sync with the backend.
Fix an unexpected behavior where filtering LiveKit webhook events sometimes
failed because the room name was not reliably extracted from the webhook data,
causing notifications to be ignored.
Configure the same filtering logic locally to avoid missing this kind of issue
in the future.
Pin egress to the production version, which uses a more recent release than the
default chart value (1.9.0).
Using the default could have led to issues; hopefully this change avoids them.
Instead of relying on the egress_started event—which fires when egress is
starting, not actually started—I now rely on egress_updated for more accurate
status updates. This is especially important for the active status, which
triggers after egress has truly joined the room. Using this avoids prematurely
stopping client-side listening to room.isRecording updates. A further
refactoring may remove reliance on room updates entirely.
The goal is to minimize handling metadata in the mediator class. egress_starting
is still used for simplicity, but egress_started could be considered in the
future.
Note: if the API to start egress hasn’t responded yet, the webhook may fail to
find the recording because it currently matches by worker ID. This is unstable.
A better approach would be to pass the database ID in the egress metadata and
recover the recording from it in the webhook.
Link recording statuses to the `isRecording` attribute from the room on the
client side.
After the refactor, the frontend relied only on recording statuses computed by
the backend. However, when egress is started and the backend is notified, the
recording is not actually active yet. It takes some time for the egress to join
the room and begin recording.
Enrich the frontend by combining backend statuses with the room recording state
to more accurately reflect when recording is truly active. This avoids missing
the first few seconds of audio at the beginning of a recording.
Only display transcription settings to room admins or owners. Showing these
controls to users without the required privileges would be misleading, since
they cannot actually configure or apply the settings.
Link the transcription document to its related recording by adding a short
header explaining that users can download the audio file via a dedicated link.
This was a highly requested feature, as many users need to keep their audio
files.
As part of a small refactor, remove the argument length check in the metadata
analytics class. The hardcoded argument count made code evolution harder and was
easy to forget updating. Argument unwrapping remains fragile and should be
redesigned later to be more robust.
The backend is responsible for generating the download link to ensure
consistency and reliability.
I tried adding a divider, but the Markdown-to-Yjs conversion is very lossy and
almost never handles it correctly. Only about one out of ten conversions works
as expected.
Specify distinct icons in the recording state toast for each mode to provide
clearer visual feedback on what is actually happening. Remove the pulse CSS
animation, as it did not improve visual clarity and accessibility.
Inspired by @ericboucher’s proposal, allow non-admin or non-owner participants
to request the start of a transcription or a recording.
All participants are notified of the request, but only the admin can actually
open the menu and start the recording.
This is a first simple and naive implementation and will be improved later.
Prefer opening the relevant recording menu for admins instead of offering a
direct quick action to start recording. With more options now tied to recording,
keeping the responsibility for starting it encapsulated within the side panel
felt cleaner.
This comes with some UX trade-offs, but it’s worth trying.
I also simplified the notification mechanism by disabling the action button for
the same duration as the notification, preventing duplicate triggers. This is
not perfect, since hovering the notification pauses its display, but it avoids
most accidental re-triggers.
Rework the visual hierarchy of the “no access” view to align it with other
presentation modes and ensure the title order is clear and understandable for
users.
Refactor literals in the recording status hook and introduce a new status.
Align the login prompt style with the newly introduced warning message, and
guide users by clearly indicating that the two modes are mutually exclusive.
Users are prompted to stop the other mode before starting a new one.
This situation should happen less often now that checkboxes allow users to start
transcription and recording together. Hopefully, the UX is clear enough.
The growing number of props passed to the controls buttons may become an issue
and will likely require refactoring later.