Room names with non-ASCII characters (e.g. ò) were double URL-encoded
when appended as query parameters to websocket, conference-request, and
keepalive URLs. getBackendSafeRoomName() returns a percent-encoded string
which was then re-encoded by URLSearchParams.append() via appendURLParam().
Extract getNormalizedRoomName() that decodes, NFKC-normalizes, and
lowercases without percent-encoding, and use it in the appendURLParam
call sites. getBackendSafeRoomName() is refactored to call it internally,
preserving identical behavior for all other callers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a retry logic with a button. The problem is that some browsers (Safari) when window.open is not executed directly in the onClick handler, but on some underlying Promise will block the popup.
Chat and CC panels showed oldest messages at the top when opened because
scrollIntoView was called on hidden (display: none) elements where it
silently does nothing. Now we skip scrolling on mount for hidden tabs
and defer it to when each tab first becomes visible, while preserving
the user's scroll position on subsequent tab switches.
Add logger.debug calls throughout the PiP (Picture-in-Picture) feature
to make it easier to trace the PiP lifecycle when investigating issues.
Covers API event dispatching, action invocations with state snapshots,
requestPictureInPicture success/failure paths, and Electron namespace
mutations.
* feat(systemd): use native template units for prosody visitor instances
* fix: use /usr/lib path and wildcard restart for systemd units
* fix(systemd): use native template units
* squash: Drop loop and use one command to restart all.
---------
Co-authored-by: damencho <damencho@jitsi.org>
* fix(recording): show advanced options for local recording with transcription
* Fixed edge case when all recording service are disabled
* Modified css
* Added warning message
* Show transcription option when no recording service is present
* Addressed PR reviews
* squash: Hide recording advanced option when not rendering recording.
* squash: Show recording button when only transcriptions are enabled.
* squash: Make sure we do not call record when it is not rendered due to no permissions.
* squash: Allows those with just feature transcription to use async transcribe.
* squash: Show recording stop button when recording is running when only transcriptions feature is available.
---------
Co-authored-by: damencho <damencho@jitsi.org>
* Adding sq translation
* Adding sq to languages.json
* Updating sq translation
* Fixing missing commas and updating string changes
* Fixing unclosed quotes
* Updating sq translation
* Updating sq translation
* Typo fixing; removing and adding commas to make the .json file valid
* Another comma missing fix
* Sorting entries aphabetically
* More sorting…
* More entry sorting
* Adding a missing space
* Adding spaces
* Get rid of an extra period
* Update for sq locale
* Update main-sq.json
* Update main-sq.json
* Update main-sq.json
* Update main-sq.json
* Update main-sq.json
* Update for sq translation
* Adding missing separator
* Adding another missing separator
* Adding another separator
* Not tired of adding separators…
* Typo fixing
* Changing place for a string; translating a forgoten string
* Updating sq translation
* Deleting an extra space at the beggining of a string
* Update for sq translation
* Update for sq translation
* Update main-sq.json
* Update main-sq.json
* Update for sq translation
* Fixing a couple of missing commas
* Fixing commas to validate main-sq.json
* Fixing string order and extra spaces
* More string order fixing
* feat(transcription): allow custom transcriber languages via config
* fix(transcription): avoid duplicating default language json and document config
* feat(config): add support for custom transcription languages in configuration
* fix(config): satisfy lint and ts rules
* fix(video-layout) Fixes auto-pinning of SS in large calls.
In calls with 50+ participants, isTopPanelEnabled returns true. This causes isStageFilmstripAvailable(state) (called with no minimum participant count from getPinnedParticipant) to return true even when activeParticipants is empty. When getPinnedParticipant takes that stage filmstrip path, it reads from activeParticipants.find(p => p.pinned) — which is always
empty for an auto-pinned screenshare.
Added an explicit check in shouldDisplayTileView's auto-mode logic: when there are active screenshares AND the top panel is enabled AND auto-pin is active AND Follow Me isn't controlling the layout, exit tile view. The guards on getAutoPinSetting() and !isFollowMeActive(state) mirror the same conditions checked everywhere else before auto-pinning fires, ensuring
consistent behavior.
* squash: Fixes linter error
* fix(meeting_id): Depends on jitsi_session(uses session.user_region).
* feat(authentication): A static page that can be used with some auth providers like keycloak.
* fix(authentication): Implements inline authentication.
squash: Adds refresh token use when refresh token is needed on connection resuming.
squash: Fix bugs and move to PKCE flow.
* squash: Adds nonce verification.
* squash: Drops the closing logic.
* squash: Replace resuming event with CONNECTION_TOKEN_EXPIRED one.
* squash: Fixes comments.
* squash: Make sure we use tokenAuthUrl only when it is set and is not jaas.
* squash: Move CONNECTION_TOKEN_EXPIRED to web only middleware as it uses web only logic for now.
* squash: Fix comments.
Update the label's htmlFor and the Switch id from 'recording-switch-transcription' to 'recording-switch-audio-video' in StartRecordingDialogContent. This corrects the label-to-control association for the audio/video recording toggle, fixing an accessibility/mapping mismatch.
* i18n: update Persian (fa) translations
* fixed wrong new line at the end of file
* i18n: fix Persian (fa) translation for participants list heading
* fix: add missing newline at the end of main-fa.json
Fix waiting for transcription to be turned off. Re-enabling transcription was sometimes started before jigasi had left the room, resulting in a failure.
*Hang-up button is calling both appNavigate and conferenceWillLeave synchronously and something is interfering.
appNavigate is async and something is calling it again before conferenceWillLeave completes.
Adds touch-screen support for resizing filmstrip and chat panels to enable tablet and touch-laptop users to adjust panel widths. Previously, drag handles only worked with mouse hover, making panels non-resizable on touch devices.
Changes:
- Implement Pointer Events API for unified mouse/touch handling
- Add touch device detection with screen size threshold
- Make drag handles always visible on touch devices with padding for easier tapping
- Maintain identical visual layout between touch and non-touch versions
Touch devices with sufficiently large screens now have fully functional drag handles with appropriate hit targets while smaller devices remain disabled to preserve mobile UX.
* Update main-nl.json
Full update to latest state of main.json including Dutch translation updates.
Validated with JSONLint
* Fixes lint.
---------
Co-authored-by: Дамян Минков <damencho@jitsi.org>
When we minimize the meeting window on Mac OS via the yellow button, 2 requests for PiP are triggered one after another because of the blur and the visibilitychange handlers. If we implement in Electron to focus the meeting window on the pipLeft event this will lead to the first request to exit triggering the pipLeft event after the second request is triggered which will actually bring the window back because we focus on pipLeft event. This behaviour breaks the ability to minimize a window.
The current fix will prevent us for sending 2 requests for PiP one after another by skipping the second unnecessary request.
The panel will appear on the right side after the participant pane panel. Currently the panel is disabled by default and the components that are rendered in the panel are empty (null). The panel is easily customizable by adding some content in the CustomPanel component.
Before:
```
Error: element ("[data-testid="participant1-more-options-ba16a58a"]") still not existing after 1000ms
at async ParticipantsPane.openParticipantContextMenu (/tmp/tmp.bMVHEDmYin/jitsi-meet/tests/pageobjects/ParticipantsPane.ts:202:9)
at async BreakoutRooms.sendParticipantToBreakoutRoom (/tmp/tmp.bMVHEDmYin/jitsi-meet/tests/pageobjects/BreakoutRooms.ts:205:9)
```
After:
```
Error: element ("[data-testid="participant1-more-options-ecea6dd6"]") still not existing after 1000ms
at async ParticipantsPane.openParticipantContextMenu (/tmp/tmp.j8VkoO9abR/jitsi-meet/tests/pageobjects/ParticipantsPane.ts:202:9)
at async BreakoutRooms.sendParticipantToBreakoutRoom (/tmp/tmp.j8VkoO9abR/jitsi-meet/tests/pageobjects/BreakoutRooms.ts:205:9)
at async Context.<anonymous> (/tmp/tmp.j8VkoO9abR/jitsi-meet/tests/specs/misc/breakoutRooms.spec.ts:349:9)
```
In branding you can add now
"labels-translation-languages": {
"en": "/static/translation-overwritten-en.json"
}
This allows overwriting strings from the translation-languages namespace, till now it was possible only for the main one.
If you are in a private conversation with someone and that participant leaves, the selection of messages switches to Everyone but the private message notice stays.
* fix(groupchat-polls-permissions): Adds UI setting to show the option.
Make sure we do not show the setting when everyone is a moderator in the room.
* squash: Change text and default value.
* squash: Defaults to false.
* squash: Set it in metadata.
* squash: Whitelist the config.
* ci: try to fix android build by removing preinstalled stuff
The android SDK build anyway uses a docker image with react native and an android SDK inside, so remove android and haskell from the host runner
* More removals of preinstalled unused SDKs
dotnet is another 4GB, swift another 3GB
* Change stage view and use newly reducedUImainToolbarButtons config to show different custom buttons as main toolbar buttons for when web is in reduced UI.
This partially reverts commit 02787b1 to avoid looping between request subtitles and start recording which results not closing the start recording dialog.
Addresses multiple issues when enabling/disabling PiP dynamically:
1. External API: Replace dead config-overwrite event handler with
interception in executeCommand. This properly manages the intersection
observer and PiP state when pip config changes via overwriteConfig.
2. PiPVideoElement: Fix ref access pattern - access videoRef.current
inside useEffects instead of capturing at render time. The captured
value was null on first render, causing blur/focus listeners to never
be set up when component mounted into a stable conference.
3. useCanvasAvatar: Return streamRef object instead of refs.current.stream
so consumers can access .current inside their effects. The stream is
created in an effect and wasn't available at render time.
4. Add on-mount focus check with loadedmetadata wait to handle PiP enable
while app is in background, ensuring video source is ready before
attempting to enter PiP mode.
Implements Picture-in-Picture functionality for the Electron wrapper to maintain video engagement when users are not actively focused on the conference window. This feature addresses the need to keep users visually connected to the conference even when multitasking.
Key features:
- Automatic PiP mode activation and deactivation based on user interaction
- Displays large video participant's stream or renders their avatar on canvas when video unavailable
- Provides audio/video mute controls via MediaSession API directly in PiP window
- Adds API events (_pip-requested) for Electron wrapper integration
Implementation includes new pip feature module with Redux architecture, canvas-based avatar rendering with custom backgrounds support, and integration with existing mute/unmute logic. Depends on jitsi-meet-electron-sdk#479 for proper user gesture handling in Electron.
* Change toolbar background color from IFrame API #16468 fixed
* fix(toolbar #16468): implement toolbar background color via configOverwrite for web and mobile
* keep toolbarConfig defaults commented in config.js
* add trailing comma to commented toolbarConfig.backgroundColor
* fix: resolve linting errors
* feat(api): add toolbarVisibilityChanged event to IFrame API
* fix lint
* fix(recording): allow samesite iframe embeds to work with local recording
Skip capture handle validation when inside an iframe to ensure local
recording works. This only applies if the iframe is served from the
same domain.
* fix(recording): add missing line breaks for better readability in LocalRecordingManager
* test: Add iframe API expectation.
* test: Add expectations for recording and live streaming.
* test: Remove iframe references from jaas/.
* test: Add a transcription expectation.
Make sure we execute before prosody cleans it up from the list of room. If we try to look it up after that we will not find it. If we also add at 0 we cannot guarantee the order of hook execution.
* Change toolbar background color from IFrame API #16468 fixed
* fix(toolbar #16468): implement toolbar background color via configOverwrite for web and mobile
* keep toolbarConfig defaults commented in config.js
* add trailing comma to commented toolbarConfig.backgroundColor
* fix: resolve linting errors
Fixes#16468
* fix(tests): Avoids clicking UI buttons to avoid being blocked by notification.
In AV moderation tests sometimes clicking mute/unmute buttons is blocked by askedToUnmute notification.
* squash: fix waiting for button.
* squash: adds some docs.
In the `process_set_affiliation` function, an undefined `session` variable was used when revoking moderator privileges. This prevented the `jitsi_meet_context_features` from being cleared for the occupant.
Introduces a comprehensive disableChat config option that disables the entire chat feature including button visibility, notifications, sounds, private messages, and keyboard shortcuts. When disabled, the chat tab is hidden from the chat panel while allowing other tabs (polls, files, CC) to remain accessible.
Adds dedicated buttons for polls and file sharing in the toolbar overflow menu, following the pattern of the CC button. Both buttons open the chat panel with their respective tab selected when clicked.
When a user joins a very large call with SS, sometime SS is not auto-pinned to stage. This may happen when lot of participant joins are processed at the same time and therefore the state for remoteScreenShares may not get updated in time. Added extra logging to help debug if this issue reproduces.
- Fix missing Chinese translations in main-zh-CN.json and main-zh-TW.json
- Fix language selection not persisting for hyphenated locales (zh-CN, zh-TW, es-US, fr-CA, pt-BR)
- Update normalizeCurrentLanguage to check exact match before normalization
Moves the querySelector/querySelectorAll polyfill implementation from the local codebase to the @jitsi/js-utils package (v2.6.1) to reduce code duplication and make the polyfill available to other projects. This centralizes maintenance and ensures consistent behavior across the Jitsi ecosystem.
* fix(large-video)pin prev speaker on stage when local user is dominant speaker.
Also fix the case where the dominant speaker sometimes doesn't show up in the filmstrip when SS is pinned to stage.
* fix(test) Add more tests for activeSpeaker
* fix(test) Do not check for large-video if there is no remote video track.
* fix(filmstrip) Get updated display name for calc speaker order
To avoid trying to click too quickly while animations are still rendered. Avoids: Can't call elementClick on element with selector "//input[@name="lockKey"]" because element wasn't found
I suspect some intermittent test failures are caused by not waiting for
the codec change to complete. Might be exacerbated by
ensureThreeParticipants only waiting for 1 remote stream, which means
it the "ensureTwo(); ensureThree()" call may return before p2 sees p3.
Integrates file sharing into the chat interface so uploaded files appear as messages in the chat timeline alongside text
messages.
Changes:
- Created FileMessage component for inline file display in chat
- Extracted FileItem component for reusable file UI across chat and file sharing tab
- Show "A file was deleted" placeholder instead of removing message when file deleted
- Hide message menu (3-dot) when no actions are available for file messages
- Add button backgrounds in chat context to hide text on hover
- Fix timing: local participant only sees file message after upload completes (progress: 100%)
Technical implementation:
- Added fileMetadata field to IMessage interface
- Added isDeleted flag to IFileMetadata for soft-delete state
- Middleware dispatches addMessage when files uploaded (ADD_FILE action)
- Middleware uses editMessage when files deleted to preserve chat history
- Minimal state retention (only isDeleted flag) for deleted files
This provides a unified messaging experience where file sharing is part of the conversation flow.
This PR addresses a sporadic issue where cp would fail with a "directory not found" error during file operations. Replaced cp with ditto, which handles directory copying more reliably on macOS and resolves the random failures observed.
Large video was being updated through scheduleLargeVideoUpdate even when
the large video container was hidden via CSS. This occurred in multiple
layout modes: tile view, stage filmstrip (with 2+ participants), and
etherpad editing. These updates caused expensive operations including
setting video streams, managing track listeners, updating avatars, and
running show/hide animations - all wasted CPU cycles since the container
wasn't visible.
The fix introduces a centralized shouldHideLargeVideo() function that checks
all cases where the large video container is hidden. This function is used in
selectParticipantInLargeVideo() to guard to not update the participant id.
A state listener monitors transitions from hidden to visible states and ensures
the large video participant id is properly updated when the container becomes
visible again and set to undefined when large video is hidden.
This improves performance by eliminating unnecessary video element manipulation
and handler execution across all layout modes where large video is not displayed.
* fix(prosody): Avoid using stale room instances.
In very rare cases a participant can request a room and jicofo join there, but the participant don't show up (waiting for host) so jicofo leaves and in the mean time if someone tries to use the room instance just before and after the room is being destroyed, strange things can occur like web connected and joined to a stale room where nothing is received exchanged compared to the live meeting room.
* squash: Revert meeting-id one, will fix it in the problem place where there is an async call.
* squash: Change to a simple check.
* Add a sample "expectations" config.
* feat: Add configurable expectation for dial in.
* Add JaaS unauthenticatedJoins expectation.
* test: Move grantModerator to moderation/, add expectation.
* test: Move kick test to moderation/, fix p2p enabled case.
* test: Add a test case for non-moderator kick.
* ref: Move the jaas util out of specs/.
* ref: Extract a more generic joinMuc utility.
* ref: Rename joinMuc to joinJaasMuc.
* ref: Move tileView.spec.ts out of 2way, use joinMuc.
* ref: Enforce that "name" is p1, p2, p3, p4 using types.
* fix: Fix mute test filename.
* ref: Split the chat test into jaas and iframe tests.
* test: Add webhook verification to jaas visitor tests.
* ref: Remove the iframe/visitors test (ported to jaas).
* ref: Move the transcriptions test to jaas.
* ref: Make getEndpointId work from outside the iframe.
* ref: Remove TestProperties.useIFrameApi. Use the flag in IParticipantOptions instead.
* ref: Do not set a special tenant when the iFrame API is used, leave it to tests to determine.
* ref: Remove the jaas-specific tests from iframe/participantsPresnce (will be re-added under jaas/ later).
* ref: Move the dial in/out tests to jaas/.
* Add tests for jaas join/leave webhooks (port back from iframe/participantsPresence).
* config: Fallback to IFRAME_TENANT and JWT_* for jaas configuration.
* ref: Simplify boolean expression.
* ref: Remove the skipFirstModerator option (unused).
* ref: Do not override token if specified.
* fix: Do not generate token for alone/invite test.
* ref: Extract more dial-in utilities.
* test: Verify Invite UI in jaas.
* Do not generate token for dial in (case covered in jaas/).
* ref: Remove preferGenerateToken (unused).
* ref: Move mute utils in their own helper.
* fix: Fix setting the jaas enabled flag.
* Do not run alone/invite for jaas (temp fix).
* fix: Switch back to meeting window.
* Do not run alone/dialInAudio on jaas.
* Disable the SIP jibri test (broken).
When opening the connection to a new visitor node we send all the messages in current history to populate that new history and newly joined visitors will see the messages from the main room.
* feat(lang): Complete French and Canadian French translations
- Added 91 missing French translation keys to main-fr.json
- Updated Canadian French (main-fr-CA.json) with complete translation coverage
- Applied authentic Canadian French terminology (réunion vs conférence, É.-U. vs États-Unis)
- Removed 44 legacy keys from Canadian French to match English/French structure
- All files now have identical key coverage (1,469 keys each)
- Maintains regional linguistic preferences while ensuring 100% feature coverage
Fixes text truncation issue in participants pane footer context menu
items (the three-dot menu). Menu items now wrap naturally to multiple
lines instead of being truncated mid-word, improving readability for
languages with longer text strings like French.
The fix uses standard CSS properties (whiteSpace, wordBreak,
overflowWrap) without browser-specific prefixes. It is specific to
the footer context menu in the participants pane and does not affect
other context menus.
* feat(conference): Process unauthenticated access disabled error.
Shows notification with a button to login.
* squash: Fix texts.
* feat(visitors): Propagate and use allowUnauthenticatedAccess.
* squash: Avoids always sending a value, even when not set.
* squash: Rename error.
* squash: Fix comments.
* squash: Move check before log.
* feat(i18n): Complete Bulgarian translation with missing keys
- Added 587+ missing Bulgarian translations for all untranslated keys
- Achieved 100% translation coverage (1,469/1,469 keys)
- Maintained consistency with existing Bulgarian terminology and tone
- Removed 34 orphaned keys that weren't present in English version
- Applied proper 4-space indentation formatting
- Sorted all keys alphabetically to match project standards
- Created comprehensive professional Bulgarian localization
---------
Co-authored-by: Дамян Минков <damencho@jitsi.org>
Co-authored-by: bgrozev <boris@jitsi.org>
* squash: Renames module.
* squash: Loads polls component.
* squash: Attach needed logic when components/hosts load.
* squash: Moves to use component.
* squash: Uses json-message format with types.
* squash: Checks for polls support.
* squash: Fixes comments and moves validate polls to backend.
* squash: Fix debian build.
* fix(polls): Fixes polls in breakout rooms.
* squash: Further simplify types.
Separate type that needs to go into ljm and those used only for the UI part.
Simplify answer/voter type to be unified across operations which simplifies and its logic.
* squash: Change voters structure to be {id, name}.
* squash: Update react/features/conference/functions.any.ts
Co-authored-by: Saúl Ibarra Corretgé <saghul@jitsi.org>
* squash: Drops roomJid from messages. Uses the connection information as breakout does.
---------
Co-authored-by: Saúl Ibarra Corretgé <saghul@jitsi.org>
* feat(lobby) integrate login in lobby + configs
* fixed toolboxContainer styles, used HangupButton
* make hangup button visible by default
* use hangup button
* feat(prejoin): fixed indent, import extension
* squash: Restore back wait for owner dialog.
* squash: Drops not used state and functions.
---------
Co-authored-by: Calin-Teodor <calin.chitu@8x8.com>
Co-authored-by: damencho <damencho@jitsi.org>
* fix: Fix the tenant used for webhook proxy.
* squash: Linting, skip test if WH proxy is required but not configured.
* ref: Change visitorsLive to use the JaaS utils.
* ref: Move visitorsLive to the specs/jaas.
* squash: Fix import paths.
* fix: Use the iframe configured tenant for iframe tests.
Try to fix the error we see:
Error: waitUntil condition failed with the following reason: Command script.callFunction with id 116 (with the following parameter: {"functionDeclaration":"function anonymous(\n) {\nreturn (/* __wdio script__ */()=>typeof APP!==\"undefined\"&&APP.conference?.isJoined()/* __wdio script end__ */).apply(this, arguments);\n}","awaitPromise":true,"arguments":[],"target":{"context":"10352FFE685AC1D0503E1ECA3BFD33B2"}}) timed out
Seems like we do not wait for all checks to happen and start joining again in the middle of switching/checking.
* ref: Inline enterTileView.
* ref: Refactor tileView, remove tileView.LastN.
The "last n" cases are not related to tile view and are covered in lastN.spec.ts.
* ref: Remove redundant "skipInMeetingChecks: true".
skipInMeetingChecks is only used in ensureTwoParticipants, ensureThreeParticipants and ensureFourParticipants.
* ref: Move recording test to jaas/, more refactoring.
* ref: Rename and document switchToAPI() and switchInPage().
* ref: Move the tileView into 2way (temp).
The display name is used in messages when messages are coming from visitors or from the history. The display name is used only when the participant is not available in the meeting to get its name.
It is not available due to cross-origin or not able to start setCaptureHandleConfig in iframe.
error 1: Failed to execute 'showSaveFilePicker' on 'Window': Cross origin sub frames aren't allowed to show a file picker.
error 2: Failed to execute 'setCaptureHandleConfig' on 'MediaDevices': Can only be called from the top-level document.
* Once we started targeting SDK 35 on a device running Android 15 or higher, by default, we display edge-to-edge.
We can handle overlaps by using insets.
In cases like waiting-for-host lobby, jicofo can leave the room and rejoin later, without the room being destroyed. We need to make sure the metadata will reach jicofo on second attempt.
* fix: Fix example file.
* fix: Fix using webhook proxy with iframe and jaas tests.
* fix: Fixes detecting max users notification.
* ref: Clear _joinParticipant to not depend on participant names.
* ref: Use joinParticipant in jaas tests.
* ref: Drops JAAS_DOMAIN as BASE_URL is used.
* fix: Drops ctx from function parameters.
* ref: Drops not needed context members.
* ref: Drops extra function.
* ref: Participant.joinConference to use roomName from options.
* doc: Updates docs.
* fix: Adds roomName to joinOptions.
Make it possible to override the generated value.
Replaces hard-coded pixel values with relative rem units across UI components to improve typography responsiveness and maintainability.
Co-authored-by: Hristo Terezov <hristo@jitsi.org>
* ref: Don't use global context for local state.
* ref: Don't use global context to store the pin.
* feat: Add a test for setting passcode via settings provisioning.
* Use local state.
* Remove "data" from context.
* ref: Rename a function.
* test: Fail quick when join muc fails, assert specific errors (e.g. "token expired").
* test: Add tests for joining a JaaS MUC with different token options.
* ref: Refactor token generation and usage
* ref: Reduce usage of global context
* test: Add a maxOccupants jaas test.
Before the chat message context menu was appearing on the left if the private chat message was disabled. The fix makes the context menu appear on the left only for messages from the local partcipant which are the only messages rendered to the right (therefore the context menu have to appear on the left side). For all other messages the context menu should appear on the right side because the message is positioned on the left side.
The participant pane lost its scrolling capability when commit 2305ae85a removed the overflowY: 'auto' property from the container styles. This prevented users from scrolling through long lists of participants, breakout rooms, or visitors when the content exceeded the available height.
Additionally, context menus were being clipped on the left side due to the overflow constraints. This became apparent after the av-moderation feature added longer menu items like "Stop screen-sharing for everyone else".
Fix:
- Restore overflowY: 'auto' to enable vertical scrolling
- Add maxWidth constraint (285px) to context menus to prevent horizontal clipping
- Allow menu text to wrap to multiple lines instead of being cut off
- Add TODO comment for future portal-based implementation
This temporary solution provides both functional scrolling and fully readable context menus until a proper architectural change can be implemented to portal context menus outside the scrollable container.
- Move namespace declaration to correct location in build.gradle
- Remove deprecated package attribute from AndroidManifest.xml
- Update README with gradle plugin version requirement
- Fix Android namespace configuration for React Native SDK
These changes resolve installation and build errors when integrating
the Jitsi Meet React Native SDK into new projects.
Fixes: SDK installation failures on Android with newer Gradle versions
When a moderator joins or someone is granted moderation we update the whitelist for any media type for which moderation is enabled. The updated whitelist is sent to all the moderators including the newly joined or granted one.
Visitors with empty or undefined names now show the configured
defaultRemoteDisplayName or 'Fellow Jitster' as fallback, matching
the behavior of regular remote participants.
We were comparing if the number of waiting participants have changed with the wrong property from the state - the number of visitors. The result was that we won't update the state when the new waiting value matches the number of visitors already in the state. Most of the times this will be 0 and we would never go to 0.
Remove filtering on the receive side, because:
1. It's not applied to visitors, and should be for the "all" case
2. We don't want to strip stats-id from stanzas sent to jicofo
* JIT-14750 Do not show names to visitors
* apply review
* change name and email too
* fix: Fix filtering initial presence to vnodes.
* Also strip stats-id and identity.user.name.
* Move filtering logic to a util, filter all identity in main room
---------
Co-authored-by: Boris Grozev <boris@jitsi.org>
Adds .web suffixes to all web specific files to prevent beeing included in the native build. Before this it seems those files were included in the build but by some chance nothing was failing.
When we open a custom scheme URL before the window load event has been fired it seems that GUM prompt is not displayed after this due to Chrome bug. See more details here https://issues.chromium.org/issues/41398687.
The result in Jitsi Meet is the following:
If the user is joining a call for first time and haven't granted A/V permissions and lands on the deeplinking page we try to open the desktop app via redirect to a custom scheme URL. If the user chooses cancel and "Launch in web" we go to the prejoin screen and proceed with the initial GUM. At this point any GUM call won't display the permission prompt due to the browser bug and will go on forever making it impossible for the user to unmute camera or microphone.
* This is a huge update, mostly because we updated Gradle on the Android side, which includes a more strict bundle process for third party modules. On iOS, even though new architecture is disabled, we had to be explicit about it because of this react native update and because some updated dependencies have it enabled by default and are using turbo modules which are not available, YET, in our project.
When there is empty array cjson produces array: {} while prosody's json impl checks is it array and produces the correct value (array: []). Prosody impl is a little bit slower, but this is not a hot path and those are not huge json strings.
* Reusing existing translation string for virtual background error notification, instead of current hardcoded english value.
* Update VirtualBackgroundPreview.tsx
* Attempt to call a nil value (global 'get_visitors_room_metadata')
* make the linter happy
* more trailing whitespace + cleanup
* apply review
* use default false
Skip updating the transcribing state when the 'audio-recording-enabled'
property is not provided.
This fixes a race when a transcriber is already in the room, we'll see
it before properties are updated (sometimes) and without checking for
undefined we'd flip the local value to false.
For all intents and purposes 8x8 apps are integrating the SDK as a 3rd
party.
Yes, we are a 1st party of sorts, but that's ok because 8x8.vc allows
embedding.
We have observed terrible framerates due to the decoder getting
constantly restarted. Surprisingly, this only happens when using the
JVB, it does not happen when using P2P with Chromium as the other
endpoint.
We shall look into that from the bridge side.
At any rate, I'm disabling the HW video decoder for AV1, which means we
will be using dav1d, the software video decoder.
stale-issue-message:'This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.'
stale-pr-message:'This PR has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.'
- **Abstract Components** - Base classes for cross-platform components
- **Platform-Specific Components** - Separate implementations in `web/` and `native/` directories
- **Hook-based patterns** - Modern React patterns for component logic
### Testing Framework
- WebDriverIO for end-to-end testing
- Test files are located in `tests/specs/` and use page objects in `tests/pageobjects/`.
- Environment configuration via `.env` files
- Support for Chrome, Firefox, and grid testing
## Development Guidelines
### Adding New Features
1. Create feature directory under `react/features/[feature-name]/`
2. Follow the standard file structure (actionTypes, actions, reducer, etc.)
3. Register reducers and middleware using the registry pattern
4. Define TypeScript interfaces for state and props
5. Use platform-specific files for web/native differences
6. Add feature-specific logger for debugging
### Working with Existing Features
1. Check for existing `.any.ts`, `.web.ts`, `.native.ts` variants
2. Follow established action-reducer-middleware patterns
3. Use existing base utilities rather than creating new ones
4. Leverage abstract components for cross-platform logic
5. Maintain type safety across the entire state tree
### Testing
The project uses WebDriver (WebdriverIO) for end-to-end testing. Test files are located in `tests/specs/` and use page objects in `tests/pageobjects/`.
### Build System
- **Webpack** - Main build system for web bundles
- **Makefile** - Coordinates build process and asset deployment
- **Metro** - React Native bundler (configured in `metro.config.js`)
### Platform-Specific Notes
- Web builds exclude files matching `**/native/*`, `**/*.native.ts`, etc.
- Native builds exclude files matching `**/web/*`, `**/*.web.ts`, etc.
- Use `moduleSuffixes` in TypeScript config to handle platform-specific imports
- Check `tsconfig.web.json` and `tsconfig.native.json` for platform-specific exclusions
## Environment and Setup Requirements
### System Requirements
- **Node.js and npm** are required
- Development server runs at https://localhost:8080/
- Certificate errors in development are expected (self-signed certificates)
### Development Workflow
- Development server proxies to configurable target (default: https://alpha.jitsi.net)
- Hot module replacement enabled for development
- Bundle analysis available via `ANALYZE_BUNDLE=true` environment variable
- Circular dependency detection via `DETECT_CIRCULAR_DEPS=true`
## Code Quality Requirements
- All code must pass `npm run lint:ci` and `npm run tsc:ci` with 0 warnings before committing
- TypeScript strict mode enabled - avoid `any` type
- ESLint config extends `@jitsi/eslint-config`
- Prefer TypeScript for new features, convert existing JavaScript when possible
## Code Style and Standards
### Conventional Commits Format
Follow [Conventional Commits](https://www.conventionalcommits.org) with **mandatory scopes**:
```
feat(feature-name): description
fix(feature-name): description
docs(section): description
```
Available types: build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test
### Feature Layout Structure
When adding new features:
```
react/features/sample/
├── actionTypes.ts
├── actions.ts
├── components/
│ ├── AnotherComponent.tsx
│ └── OneComponent.tsx
├── middleware.ts
└── reducer.ts
```
### TypeScript Requirements
- All new features must be written in TypeScript
- Convert JavaScript to TypeScript when modifying existing code
- Import middleware in `react/features/app/middlewares.{any,native,web}.js`
- Import reducers in appropriate registry files
- Avoid `index` files
### Bundle Size Management
- Bundle size limits are enforced to prevent bloat
- For increases, analyze first: `npx webpack -p --analyze-bundle`
- Open analyzer: `npx webpack-bundle-analyzer build/app-stats.json`
- Justify any dependency additions that increase bundle size
## Testing and Quality Assurance
### Tests
- End-to-end tests are defined in the tests/
- Tests run automatically for project member PRs via Jenkins
- Tests cover peer-to-peer, invites, iOS, Android, and web platforms
- Beta testing available at https://beta.meet.jit.si/
### Manual Testing Checklist
- Test with 2 participants (P2P mode)
- Test with 3+ participants (JVB mode)
- Verify audio/video in both modes
- Test mobile apps if changes affect mobile
- Check that TLS certificate chain is complete for mobile app compatibility
## Common Issues and Debugging
### P2P vs JVB Problems
- **Works with 2 participants, fails with 3+**: JVB/firewall issue, check UDP 10000
- **Works on web, fails on mobile apps**: TLS certificate chain issue, need fullchain.pem
- Use the tests from tests/ directory to verify functionality across platforms
### Development Server Issues
- Certificate warnings are normal for development (self-signed)
- Use different backend with WEBPACK_DEV_SERVER_PROXY_TARGET environment variable
- Check firewall settings if local development fails
### Configuration and Customization
- Extensive configuration options documented in handbook
- See `config.js` for client-side options
- Options marked 🚫 are not overwritable through `configOverwrite`
- Reference [Configuration Guide](https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-configuration) for details
## Architecture Deep Dive
### Core Application Files
- **`./conference.js`** - Foundation for user-conference interactions (connection, joining, muting)
- **`./modules/external-api`** - External API for iframe integration and events
- **`./lang/`** - Translations in `main-[language].json` files
if ! grep -q -- '--"polls";' $PROSODY_HOST_CONFIG ;then
sed -i "s/\"polls\";/--\"polls\";/g" $PROSODY_HOST_CONFIG
PROSODY_CONFIG_PRESENT="false"
fi
# Old versions of jitsi-meet-prosody come with the extra plugin path commented out (https://github.com/jitsi/jitsi-meet/commit/e11d4d3101e5228bf956a69a9e8da73d0aee7949)
# Make sure it is uncommented, as it contains required modules.
"inProgress":"البث المباشر غير ممكّن على {{email}}. يرجى تمكين البث المباشر أو تسجيل الدخول إلى حساب مع تمكين البث المباشر.",
"invalidStreamKey":"يحتمل كون مفتاح البث الحي غير صحيح.",
"limitNotificationDescriptionNative":"سيقيَّد البث إلى {{limit}} د، ولكن إن أردت إجراء عملية بث غير محدودة، جرِّب {{app}}.",
"limitNotificationDescriptionWeb":"نظرًا للضغط الكبير، سيقيَّد البث إلى {{limit}} د، ولكن إن أردت إجراء عملية بث غير محدودة، جرِّب <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
"off":"أُوقِف البث الحي",
"offBy":"أوقف {{name}} البث الحي",
"on":"بث حي",
@@ -898,8 +896,6 @@
"highlightMomentSuccess":"تم تمييز اللحظة",
"highlightMomentSucessDescription":"ستتم إضافة اللحظة المميزة إلى ملخص المُلتقى.",
"inProgress":"التسجيل أو البث المباشر قيد التقدم",
"limitNotificationDescriptionNative":"نظرًا للضغط الكبير، سيقيَّد التسجيل إلى {{limit}} د، ولكن إن أردت التسجيل لمدة مفتوحة، جرِّب <3>{{app}}</3>.",
"limitNotificationDescriptionWeb":"نظرًا للضغط الكبير، سيقيَّد التسجيل إلى {{limit}} د، ولكن إن أردت التسجيل لمدة مفتوحة، جرِّب <a href={{url}} rel='noopener noreferrer' target='_blank'>{{app}}</a>.",
"linkGenerated":"لقد أنشأنا رابطًا لتسجيلك.",
"live":"مباشر",
"localRecordingNoNotificationWarning":"لن يتم الإعلان عن التسجيل للمشاركين الآخرين. ستحتاج إلى إخبارهم بأنه تم تسجيل الاجتماع.",
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.