Compare commits

...

36 Commits

Author SHA1 Message Date
Naman Jain
fe1f858ef9 fix(docs) update contributing 2025-03-23 10:15:03 +01:00
damencho
dd7b953a92 fix(tests): When checking audio levels make sure testMode and debugAudioLevels are present. 2025-03-21 13:31:27 -05:00
damencho
1f2aaa8dc0 fix(tests): Adds some debug prints for a case reporting failure to leave. 2025-03-21 13:31:27 -05:00
damencho
80bf228a65 fix(tests): Make sure we give time dialog to submit password.
Give time for the dialog to disappear before entering the new password when retrying or checking for wrong password.
2025-03-21 13:31:27 -05:00
damencho
62e0f09f98 fix(tests): Wait for the join button to disappear if it was there. 2025-03-21 13:31:27 -05:00
Mihaela Dumitru
6654feacee fix(recordings) skip consent for jibri participant (#15825) 2025-03-21 13:40:30 +02:00
Saúl Ibarra Corretgé
3d4defd799 feat(lint) update to eslint-config-jitsi v6 2025-03-20 17:17:41 +01:00
damencho
e15bf2d4dd fix(tests): Avoid error after tests.
In newer versions of wdio this is handled, but now in case of error at this level the test is missing from the result xmls.
2025-03-20 11:08:44 -05:00
Naman Jain
6de935b372 fix(welcome) open external links in a new tab 2025-03-20 16:16:46 +01:00
Saúl Ibarra Corretgé
3397b9cbc9 fix(deps) remove xmldom override
The dependency is now gone from strophe.js so we don't need to override
it.
2025-03-20 13:01:30 +01:00
Horatiu Muresan
45626a0d23 feat(groupchat-polls-permissions) Implement groupchat and polls creation for web (#15806) 2025-03-19 22:02:32 -05:00
Jaya Allamsetty
b7bccb0801 chore(deps) lib-jitsi-meet@latest
https://github.com/jitsi/lib-jitsi-meet/compare/v1926.0.0+c661fdee...v1928.0.0+763b2c8f
2025-03-19 14:59:23 -04:00
damencho
475ec6d427 fix: Adds an option to set jicofo as owner of rooms.
This is needed for prosody 13.0 only.
2025-03-18 17:33:23 -05:00
damencho
a28b155c41 fix: Fixes creating users when using latest prosody. 2025-03-18 17:33:23 -05:00
Calinteodor
5f44c7580d feat(base/ui): update tokens (#15688)
* Make createColorTokens generate values based on jitsiTokens and tokens
2025-03-18 18:00:54 +02:00
Saúl Ibarra Corretgé
3d1eb5282c feat(ios) migrate remaining helper classes to Swift 2025-03-18 10:31:00 +01:00
Saúl Ibarra Corretgé
10935ec692 feat(ios) rewrite AppDelegate in Swift 2025-03-18 10:31:00 +01:00
Saúl Ibarra Corretgé
95a0a8418f feat(ios) rewrite ViewController in Swift 2025-03-18 10:31:00 +01:00
Saúl Ibarra Corretgé
0a5e914862 feat(ios) allow importing SDK in Swift modules in another target 2025-03-18 10:31:00 +01:00
Saúl Ibarra Corretgé
02ff359de2 feat(ios) drop use of storyboard
We only have a single view, so we can simlify.
2025-03-18 10:31:00 +01:00
Joshua Irmer
fecac0322e fix(prejoin): polite name error message
Signed-off-by: Joshua Irmer <irmer@gonicus.de>
2025-03-17 22:37:17 +01:00
damencho
bd1c3332ea fix(test): Fixes failing to hangup a participant.
This is caused by the redirect we do during hangup.

fix(test): Fixes a FF case with not receiving video from p2.
2025-03-17 16:28:38 -05:00
Jaya Allamsetty
5ee0738e45 chore(deps) lib-jitsi-meet@latest
https://github.com/jitsi/lib-jitsi-meet/compare/v1922.0.0+25031534...v1926.0.0+c661fdee
2025-03-17 15:30:26 -05:00
Saúl Ibarra Corretgé
c3518208e1 fix(ci) fix action branch name 2025-03-17 16:29:45 +01:00
Saúl Ibarra Corretgé
21116c09f4 fix(ci) update tj-actions/changed-files action
Use our own fork, currently synced with upstream.
2025-03-17 16:01:09 +01:00
damencho
875a9cbaf3 feat(prosody): New impl of is_admin. 2025-03-17 08:43:37 -05:00
damencho
5fd050b77f feat(prosody): Moves is_admin to util. 2025-03-17 08:43:37 -05:00
Shevilll
fee6ecc82d Fixed unrelated changes 2025-03-17 12:53:50 +02:00
Calin-Teodor
2ba57730cd fix(base/config): apply disableProfile check only for web buttons 2025-03-17 12:49:58 +02:00
Ahmad Faraz
78c304cba8 Annotate with type (#15782) 2025-03-15 12:13:29 +02:00
Saúl Ibarra Corretgé
b082354773 fix(ios) patch SocketRocket to support WebSocket with TLS 1.3
Upstream PR: https://github.com/facebookincubator/SocketRocket/pull/701
2025-03-14 08:40:13 +01:00
Saúl Ibarra Corretgé
8bd377098d fix(test): use filmstrip to audio mute in av moderation (#15785)
Avoids a race in the participants pane.

Co-authored-by: Дамян Минков <damencho@jitsi.org>
2025-03-13 11:42:15 -05:00
Дамян Минков
7d6990b3f8 feat(logging): Let ljm handle its logging to rtcStats.
* feat(logging): Let ljm handle its logging to rtcStats.

* chore(deps) lib-jitsi-meet@latest

https://github.com/jitsi/lib-jitsi-meet/compare/v1919.0.0+d4a47d0e...v1922.0.0+25031534

* squash: Small gap between stopping screenshare and turning on video.

We see some FF failures and not sending video in p2p mode after enabling video back one shortly after switching off screenshare.
2025-03-13 10:49:38 -05:00
Joshua Irmer
a51e97f318 fix(settings): notification tab restructure
Signed-off-by: Joshua Irmer <irmer@gonicus.de>
2025-03-13 16:25:40 +02:00
Calin-Teodor
bc65d21ce4 feat(android): fix case where actions have no data 2025-03-13 14:46:27 +02:00
Lakshay
e9236fd9ff fix: Disable lobby chat emoji reactions
* fixed lobby chat emoji react

* disabled the chat reaction

* removed previous changes

* fixed lint errors
2025-03-12 15:06:59 -05:00
93 changed files with 989 additions and 1396 deletions

View File

@@ -17,3 +17,8 @@ react/features/face-landmarks/resources/*
# Not worth it.
actionTypes.ts
# It's not complete until all files are copied at build time.
react-native-sdk/
*.d.ts

View File

@@ -1,6 +1,5 @@
module.exports = {
'extends': [
extends: [
'@jitsi/eslint-config'
],
'ignorePatterns': [ '*.d.ts' ]
]
};

View File

@@ -18,7 +18,7 @@ jobs:
npm -v
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v41
uses: jitsi/changed-files@main
- name: Get changed lang files
id: lang-files
run: echo "all=$(echo "${{ steps.changed-files.outputs.all_changed_files }}" | grep -oE 'lang\/\S+' | tr '\n' ' ')" >> "$GITHUB_OUTPUT"

View File

@@ -1,14 +1,20 @@
# Follow Our Updated Guide to See How You Can Contribute
Hello there! 👋
**Hello there! 👋**
We're thrilled that you're eager to contribute to Jitsi Meet! ❤️
We're thrilled that you're eager to contribute to **Jitsi Meet! ❤️**
Your interest in improving our platform means a lot to us. To ensure your contributions align seamlessly with our goals and processes, we've recently updated our guide. This guide will provide you with clear instructions on how to get involved effectively.
Ready to get started? Head over to our [Jitsi Meet Handbook](https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-contributing/) and let's make Jitsi Meet even better together!
### 📖 Get Started
Ready to get started? Head over to our [Jitsi Meet Handbook](https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-contributing/) and let's make **Jitsi Meet** even better together!
### 💬 Join the Discussion
Have questions or need help? Join our community discussions on the [Jitsi Forum](https://community.jitsi.org/) where contributors and maintainers can assist you.
### ❗Additional Note
Before sending us your code, double-check that it meets our coding standards. You can do this by running a command: `npm run lint`. If there are any issues, don't worry! You can fix them by running: `npm run lint-fix`. Once your code passes these checks, feel free to submit your pull request.
Happy coding!
**Happy coding!**

View File

@@ -32,7 +32,13 @@ public class BroadcastReceiver extends android.content.BroadcastReceiver {
BroadcastAction action = new BroadcastAction(intent);
String actionName = action.getType().getAction();
Bundle data = action.getData();
ReactInstanceManagerHolder.emitEvent(actionName, Arguments.fromBundle(data));
// For actions without data bundle (like hangup), we create an empty map
// instead of attempting to convert a null bundle to avoid crashes.
if (data != null) {
ReactInstanceManagerHolder.emitEvent(actionName, Arguments.fromBundle(data));
} else {
ReactInstanceManagerHolder.emitEvent(actionName, Arguments.createMap());
}
}
}

26
app.js
View File

@@ -10,6 +10,32 @@ import '@matrix-org/olm';
import 'focus-visible';
/*
* Safari polyfill for createImageBitmap
* https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/createImageBitmap
*
* Support source image types: Canvas.
*/
if (!('createImageBitmap' in window)) {
window.createImageBitmap = function(data) {
return new Promise((resolve, reject) => {
let dataURL;
if (data instanceof HTMLCanvasElement) {
dataURL = data.toDataURL();
} else {
reject(new Error('createImageBitmap does not handle the provided image source type'));
}
const img = document.createElement('img');
img.addEventListener('load', () => {
resolve(img);
});
img.src = dataURL;
});
};
}
// We need to setup the jitsi-local-storage as early as possible so that we can start using it.
// NOTE: If jitsi-local-storage is used before the initial setup is performed this will break the use case when we use
// the local storage from the parent page when the localStorage is disabled. Also the setup is relying that

View File

@@ -601,7 +601,7 @@ export default {
const { tryCreateLocalTracks, errors } = this.createInitialLocalTracks(initialOptions, true);
tryCreateLocalTracks.then(async tr => {
tryCreateLocalTracks.then(tr => {
const createLocalTracksEnd = window.performance.now();
connectionTimes['conference.init.createLocalTracks.end'] = createLocalTracksEnd;

View File

@@ -1378,8 +1378,12 @@ var config = {
The config file should be in JSON.
None of the fields are mandatory and the response must have the shape:
{
// Whether participant can only send group chat message if `send-groupchat` feature is enabled in jwt.
groupChatRequiresPermission: false,
// Whether participant can only create polls if `create-polls` feature is enabled in jwt.
pollCreationRequiresPermission: false,
// The domain url to apply (will replace the domain in the sharing conference link/embed section)
inviteDomain: 'example-company.org,
inviteDomain: 'example-company.org',
// The hex value for the colour used as background
backgroundColor: '#fff',
// The url for the image used as background

View File

@@ -53,7 +53,10 @@
}
.welcome-footer-row-block {
display: block;
display: flex;
flex-direction: column;
gap:12px;
align-items: center;
}
}
}

View File

@@ -349,6 +349,6 @@ body.welcome-page {
.welcome-footer-row-1-text {
max-width: 200px;
margin-right: 16px;
text-align: center;
}
}

View File

@@ -131,16 +131,6 @@ case "$1" in
fi
fi
if [ "$PROSODY_CREATE_JICOFO_USER" = "true" ]; then
# create 'focus@auth.domain' prosody user
prosodyctl register $JICOFO_AUTH_USER $JICOFO_AUTH_DOMAIN $JICOFO_AUTH_PASSWORD
# trigger a restart
PROSODY_CONFIG_PRESENT="false"
fi
# creates the user if it does not exist
echo -e "$JVB_SECRET\n$JVB_SECRET" | prosodyctl adduser jvb@$JICOFO_AUTH_DOMAIN > /dev/null || true
# Check whether prosody config has the internal muc, if not add it,
# as we are migrating configs
if [ -f $PROSODY_HOST_CONFIG ] && ! grep -q "internal.$JICOFO_AUTH_DOMAIN" $PROSODY_HOST_CONFIG; then
@@ -184,6 +174,12 @@ case "$1" in
PROSODY_CONFIG_PRESENT="false"
fi
# Since prosody 13 admins are not automatically room owners and we expect that for jicofo
if ! grep -q -- 'component_admins_as_room_owners = ' $PROSODY_HOST_CONFIG ;then
sed -i "1s/^/component_admins_as_room_owners = true\n/" $PROSODY_HOST_CONFIG
PROSODY_CONFIG_PRESENT="false"
fi
JAAS_HOST_CONFIG="/etc/prosody/conf.avail/jaas.cfg.lua"
if [ "${JAAS_INPUT}" = "true" ] && [ ! -f $JAAS_HOST_CONFIG ]; then
sed -i "s/enabled = false -- Jitsi meet components/enabled = true -- Jitsi meet components/g" $PROSODY_HOST_CONFIG
@@ -207,9 +203,6 @@ case "$1" in
fi
fi
# Make sure the focus@auth user's roster includes the proxy component (this is idempotent)
prosodyctl mod_roster_command subscribe focus.$JVB_HOSTNAME $JICOFO_AUTH_USER@$JICOFO_AUTH_DOMAIN
if [ ! -f /var/lib/prosody/$JVB_HOSTNAME.crt ]; then
# prosodyctl takes care for the permissions
# echo for using all default values
@@ -252,6 +245,29 @@ case "$1" in
if [ "$PROSODY_CONFIG_PRESENT" = "false" ]; then
invoke-rc.d prosody restart || true
# give it some time to warm up
sleep 10
if [ "$PROSODY_CREATE_JICOFO_USER" = "true" ]; then
# create 'focus@auth.domain' prosody user
echo -e "$JICOFO_AUTH_PASSWORD\n$JICOFO_AUTH_PASSWORD" | prosodyctl adduser $JICOFO_AUTH_USER@$JICOFO_AUTH_DOMAIN > /dev/null || true
# trigger a restart
PROSODY_CONFIG_PRESENT="false"
fi
# creates the user if it does not exist
echo -e "$JVB_SECRET\n$JVB_SECRET" | prosodyctl adduser jvb@$JICOFO_AUTH_DOMAIN > /dev/null || true
# Make sure the focus@auth user's roster includes the proxy component (this is idempotent)
prosodyctl mod_roster_command subscribe focus.$JVB_HOSTNAME $JICOFO_AUTH_USER@$JICOFO_AUTH_DOMAIN
# To make sure the roster command is loaded
# Once we have https://issues.prosody.im/1908 we can start using prosodyctl shell roster subscribe
# and drop the wait and the prosody restart
sleep 1
invoke-rc.d prosody restart || true
# In case we had updated the certificates and restarted prosody, let's restart and the bridge and jicofo if possible
if [ -d /run/systemd/system ] && [ "$CERT_ADDED_TO_TRUST" = "true" ]; then
systemctl restart jitsi-videobridge2.service >/dev/null || true

View File

@@ -1,3 +1,6 @@
-- We need this for prosody 13.0
component_admins_as_room_owners = true
plugin_paths = { "/usr/share/jitsi-meet/prosody-plugins/" }
-- domain mapper options, must at least have domain base set to use the mapper

View File

@@ -97,4 +97,7 @@ post_install do |installer|
config.build_settings['OTHER_SWIFT_FLAGS'] = '$(inherited) -no-verify-emitted-module-interface'
end
end
# Patch SocketRocket to support TLS 1.3
%x(patch Pods/SocketRocket/SocketRocket/SRSecurityPolicy.m -N < patches/ws-tls13.diff)
end

View File

@@ -2209,6 +2209,6 @@ SPEC CHECKSUMS:
SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d
Yoga: 1dd9dabb9df8fe08f12cd522eae04a2da0e252eb
PODFILE CHECKSUM: 8a3e5d019861b37d4159f2d178cc534be3ac528c
PODFILE CHECKSUM: 4f6abcf3cec0d9e8e1d5f5d81a35d99adde9ae45
COCOAPODS: 1.16.2

View File

@@ -7,8 +7,6 @@
objects = {
/* Begin PBXBuildFile section */
0B412F1F1EDEE6E800B1A0A6 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B412F1E1EDEE6E800B1A0A6 /* ViewController.m */; };
0B412F211EDEE95300B1A0A6 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0B412F201EDEE95300B1A0A6 /* Main.storyboard */; };
0B5418471F7C5D8C00A2DD86 /* MeetingRowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B5418461F7C5D8C00A2DD86 /* MeetingRowController.swift */; };
0B7001701F7C51CC005944F4 /* InCallController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B70016F1F7C51CC005944F4 /* InCallController.swift */; };
0BEA5C291F7B8F73000D0AB4 /* Interface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0BEA5C271F7B8F73000D0AB4 /* Interface.storyboard */; };
@@ -19,10 +17,8 @@
0BEA5C3B1F7B8F73000D0AB4 /* ComplicationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BEA5C3A1F7B8F73000D0AB4 /* ComplicationController.swift */; };
0BEA5C3D1F7B8F73000D0AB4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0BEA5C3C1F7B8F73000D0AB4 /* Assets.xcassets */; };
0BEA5C411F7B8F73000D0AB4 /* JitsiMeetCompanion.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = 0BEA5C251F7B8F73000D0AB4 /* JitsiMeetCompanion.app */; };
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
2681BB562C7A0B42CFBA6719 /* libPods-JitsiMeet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D6152FF9E9F7B0E86F70A21D /* libPods-JitsiMeet.a */; };
361974E2A13624D7735D619D /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 5C1BE20ECD5DEEB48FED90B5 /* PrivacyInfo.xcprivacy */; };
4341A9062CF0D63200940D93 /* hermes.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4341A9052CF0D63200940D93 /* hermes.xcframework */; };
@@ -34,7 +30,8 @@
4EB0603C260E09D000F524C5 /* SocketConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB06039260E09D000F524C5 /* SocketConnection.swift */; };
4EB0603D260E09D000F524C5 /* DarwinNotificationCenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB0603A260E09D000F524C5 /* DarwinNotificationCenter.swift */; };
4EB0603E260E09D000F524C5 /* SampleUploader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB0603B260E09D000F524C5 /* SampleUploader.swift */; };
DE4C456121DE1E4E00EA0709 /* FIRUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = DE4C455F21DE1E4E00EA0709 /* FIRUtilities.m */; };
DEA0B7122D7EF16E0062A9F6 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEA0B7112D7EF16E0062A9F6 /* ViewController.swift */; };
DEA0B7142D7EF7590062A9F6 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEA0B7132D7EF7590062A9F6 /* AppDelegate.swift */; };
DEA9F289258A6EA800D4CD74 /* JitsiMeetSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DEA9F288258A6EA800D4CD74 /* JitsiMeetSDK.framework */; };
DEA9F28A258A6EA800D4CD74 /* JitsiMeetSDK.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DEA9F288258A6EA800D4CD74 /* JitsiMeetSDK.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
DED016F128ECBC9D009D5E8D /* WebRTC.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = DED016F028ECBC9D009D5E8D /* WebRTC.xcframework */; };
@@ -121,12 +118,8 @@
/* Begin PBXFileReference section */
0B26BE6D1EC5BC3C00EEFB41 /* JitsiMeet.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = JitsiMeet.framework; sourceTree = BUILT_PRODUCTS_DIR; };
0B412F1D1EDEE6E800B1A0A6 /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
0B412F1E1EDEE6E800B1A0A6 /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
0B412F201EDEE95300B1A0A6 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = Main.storyboard; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
0B5418461F7C5D8C00A2DD86 /* MeetingRowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeetingRowController.swift; sourceTree = "<group>"; };
0B70016F1F7C51CC005944F4 /* InCallController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InCallController.swift; sourceTree = "<group>"; };
0BBD021F212EB69D00CCB19F /* Types.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Types.h; sourceTree = "<group>"; };
0BD6B4361EF82A6B00D1F4CD /* WebRTC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebRTC.framework; path = "../../node_modules/react-native-webrtc/ios/WebRTC.framework"; sourceTree = "<group>"; };
0BEA5C251F7B8F73000D0AB4 /* JitsiMeetCompanion.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JitsiMeetCompanion.app; sourceTree = BUILT_PRODUCTS_DIR; };
0BEA5C281F7B8F73000D0AB4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Interface.storyboard; sourceTree = "<group>"; };
@@ -139,12 +132,9 @@
0BEA5C3C1F7B8F73000D0AB4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
0BEA5C3E1F7B8F73000D0AB4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
13B07F961A680F5B00A75B9A /* jitsi-meet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "jitsi-meet.app"; sourceTree = BUILT_PRODUCTS_DIR; };
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
3E0F4ED943C0B12BE77F6B45 /* Pods-JitsiMeet.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JitsiMeet.release.xcconfig"; path = "Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet.release.xcconfig"; sourceTree = "<group>"; };
4341A9052CF0D63200940D93 /* hermes.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = hermes.xcframework; path = "../Pods/hermes-engine/destroot/Library/Frameworks/universal/hermes.xcframework"; sourceTree = "<group>"; };
4E90F93F2632D1AB001102D4 /* Atomic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Atomic.swift; sourceTree = "<group>"; };
@@ -161,8 +151,8 @@
B3B083EB1D4955FF0069CEE7 /* app.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = app.entitlements; sourceTree = "<group>"; };
D6152FF9E9F7B0E86F70A21D /* libPods-JitsiMeet.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-JitsiMeet.a"; sourceTree = BUILT_PRODUCTS_DIR; };
DE050388256E904600DEE3A5 /* WebRTC.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = WebRTC.xcframework; path = "../../node_modules/react-native-webrtc/apple/WebRTC.xcframework"; sourceTree = "<group>"; };
DE4C455F21DE1E4E00EA0709 /* FIRUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FIRUtilities.m; sourceTree = "<group>"; };
DE4C456021DE1E4E00EA0709 /* FIRUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FIRUtilities.h; sourceTree = "<group>"; };
DEA0B7112D7EF16E0062A9F6 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
DEA0B7132D7EF7590062A9F6 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
DEA9F288258A6EA800D4CD74 /* JitsiMeetSDK.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = JitsiMeetSDK.framework; sourceTree = BUILT_PRODUCTS_DIR; };
DED016F028ECBC9D009D5E8D /* WebRTC.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = WebRTC.xcframework; path = ../Pods/JitsiWebRTC/WebRTC.xcframework; sourceTree = "<group>"; };
DEFDBBDB25656E3B00344B23 /* WebRTC.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = WebRTC.xcframework; path = "../../node_modules/react-native-webrtc/ios/WebRTC.xcframework"; sourceTree = "<group>"; };
@@ -257,18 +247,11 @@
13B07FAE1A68108700A75B9A /* src */ = {
isa = PBXGroup;
children = (
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
13B07FB01A68108700A75B9A /* AppDelegate.m */,
DE4C456021DE1E4E00EA0709 /* FIRUtilities.h */,
DE4C455F21DE1E4E00EA0709 /* FIRUtilities.m */,
DEA0B7132D7EF7590062A9F6 /* AppDelegate.swift */,
13B07FB51A68108700A75B9A /* Images.xcassets */,
13B07FB61A68108700A75B9A /* Info.plist */,
13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
13B07FB71A68108700A75B9A /* main.m */,
0B412F201EDEE95300B1A0A6 /* Main.storyboard */,
0BBD021F212EB69D00CCB19F /* Types.h */,
0B412F1D1EDEE6E800B1A0A6 /* ViewController.h */,
0B412F1E1EDEE6E800B1A0A6 /* ViewController.m */,
DEA0B7112D7EF16E0062A9F6 /* ViewController.swift */,
);
path = src;
sourceTree = "<group>";
@@ -433,6 +416,7 @@
ProvisioningStyle = Automatic;
};
13B07F861A680F5B00A75B9A = {
LastSwiftMigration = 1620;
SystemCapabilities = {
com.apple.SafariKeychain = {
enabled = 1;
@@ -490,7 +474,6 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0B412F211EDEE95300B1A0A6 /* Main.storyboard in Resources */,
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,
361974E2A13624D7735D619D /* PrivacyInfo.xcprivacy in Resources */,
@@ -658,10 +641,8 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0B412F1F1EDEE6E800B1A0A6 /* ViewController.m in Sources */,
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
DE4C456121DE1E4E00EA0709 /* FIRUtilities.m in Sources */,
13B07FC11A68108700A75B9A /* main.m in Sources */,
DEA0B7122D7EF16E0062A9F6 /* ViewController.swift in Sources */,
DEA0B7142D7EF7590062A9F6 /* AppDelegate.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -867,6 +848,7 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIconDebug;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = app.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
@@ -891,6 +873,8 @@
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
@@ -901,6 +885,7 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIconRelease;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = app.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
@@ -924,6 +909,7 @@
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;

View File

@@ -1,23 +0,0 @@
/*
* Copyright @ 2017-present Atlassian Pty Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (nonatomic, strong) UIWindow *window;
@end

View File

@@ -1,139 +0,0 @@
/*
* Copyright @ 2018-present 8x8, Inc.
* Copyright @ 2017-2018 Atlassian Pty Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "AppDelegate.h"
#import "FIRUtilities.h"
#import "Types.h"
#import "ViewController.h"
@import Firebase;
@import JitsiMeetSDK;
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
JitsiMeet *jitsiMeet = [JitsiMeet sharedInstance];
#if 0
jitsiMeet.webRtcLoggingSeverity = WebRTCLoggingSeverityVerbose;
#endif
jitsiMeet.conferenceActivityType = JitsiMeetConferenceActivityType;
jitsiMeet.customUrlScheme = @"org.jitsi.meet";
jitsiMeet.universalLinkDomains = @[@"meet.jit.si", @"alpha.jitsi.net", @"beta.meet.jit.si"];
jitsiMeet.defaultConferenceOptions = [JitsiMeetConferenceOptions fromBuilder:^(JitsiMeetConferenceOptionsBuilder *builder) {
// For testing configOverrides a room needs to be set
// builder.room = @"https://meet.jit.si/test0988test";
[builder setFeatureFlag:@"welcomepage.enabled" withBoolean:YES];
[builder setFeatureFlag:@"ios.screensharing.enabled" withBoolean:YES];
[builder setFeatureFlag:@"ios.recording.enabled" withBoolean:YES];
}];
[jitsiMeet application:application didFinishLaunchingWithOptions:launchOptions];
// Initialize Crashlytics and Firebase if a valid GoogleService-Info.plist file was provided.
if ([FIRUtilities appContainsRealServiceInfoPlist]) {
NSLog(@"Enabling Firebase");
[FIRApp configure];
// Crashlytics defaults to disabled with the FirebaseCrashlyticsCollectionEnabled Info.plist key.
[[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:![jitsiMeet isCrashReportingDisabled]];
}
ViewController *rootController = (ViewController *)self.window.rootViewController;
[jitsiMeet showSplashScreen:rootController.view];
return YES;
}
- (void) applicationWillTerminate:(UIApplication *)application {
NSLog(@"Application will terminate!");
// Try to leave the current meeting graceefully.
ViewController *rootController = (ViewController *)self.window.rootViewController;
[rootController terminate];
}
#pragma mark Linking delegate methods
- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> *restorableObjects))restorationHandler {
if ([FIRUtilities appContainsRealServiceInfoPlist]) {
// 1. Attempt to handle Universal Links through Firebase in order to support
// its Dynamic Links (which we utilize for the purposes of deferred deep
// linking).
BOOL handled
= [[FIRDynamicLinks dynamicLinks]
handleUniversalLink:userActivity.webpageURL
completion:^(FIRDynamicLink * _Nullable dynamicLink, NSError * _Nullable error) {
NSURL *firebaseUrl = [FIRUtilities extractURL:dynamicLink];
if (firebaseUrl != nil) {
userActivity.webpageURL = firebaseUrl;
[[JitsiMeet sharedInstance] application:application
continueUserActivity:userActivity
restorationHandler:restorationHandler];
}
}];
if (handled) {
return handled;
}
}
// 2. Default to plain old, non-Firebase-assisted Universal Links.
return [[JitsiMeet sharedInstance] application:application
continueUserActivity:userActivity
restorationHandler:restorationHandler];
}
- (BOOL)application:(UIApplication *)app
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
// This shows up during a reload in development, skip it.
// https://github.com/firebase/firebase-ios-sdk/issues/233
if ([[url absoluteString] containsString:@"google/link/?dismiss=1&is_weak_match=1"]) {
return NO;
}
NSURL *openUrl = url;
if ([FIRUtilities appContainsRealServiceInfoPlist]) {
// Process Firebase Dynamic Links
FIRDynamicLink *dynamicLink = [[FIRDynamicLinks dynamicLinks] dynamicLinkFromCustomSchemeURL:url];
NSURL *firebaseUrl = [FIRUtilities extractURL:dynamicLink];
if (firebaseUrl != nil) {
openUrl = firebaseUrl;
}
}
return [[JitsiMeet sharedInstance] application:app
openURL:openUrl
options:options];
}
- (UIInterfaceOrientationMask)application:(UIApplication *)application
supportedInterfaceOrientationsForWindow:(UIWindow *)window {
return [[JitsiMeet sharedInstance] application:application
supportedInterfaceOrientationsForWindow:window];
}
@end

View File

@@ -0,0 +1,109 @@
import UIKit
import Firebase
import JitsiMeetSDK
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
self.window = UIWindow(frame: UIScreen.main.bounds)
let jitsiMeet = JitsiMeet.sharedInstance()
// jitsiMeet.webRtcLoggingSeverity = .verbose
jitsiMeet.conferenceActivityType = "org.jitsi.JitsiMeet.ios.conference" // Must match the one defined in Info.plist{}
jitsiMeet.customUrlScheme = "org.jitsi.meet"
jitsiMeet.universalLinkDomains = ["meet.jit.si", "alpha.jitsi.net", "beta.meet.jit.si"]
jitsiMeet.defaultConferenceOptions = JitsiMeetConferenceOptions.fromBuilder { builder in
// For testing configOverrides a room needs to be set
// builder.room = "https://meet.jit.si/test0988test"
builder.setFeatureFlag("welcomepage.enabled", withBoolean: true)
builder.setFeatureFlag("ios.screensharing.enabled", withBoolean: true)
builder.setFeatureFlag("ios.recording.enabled", withBoolean: true)
}
jitsiMeet.application(application, didFinishLaunchingWithOptions: launchOptions ?? [:])
if self.appContainsRealServiceInfoPlist() {
print("Enabling Firebase")
FirebaseApp.configure()
Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(!jitsiMeet.isCrashReportingDisabled())
}
let vc = ViewController()
self.window?.rootViewController = vc
jitsiMeet.showSplashScreen(vc.view)
self.window?.makeKeyAndVisible()
return true
}
func applicationWillTerminate(_ application: UIApplication) {
print("Application will terminate!")
if let rootController = self.window?.rootViewController as? ViewController {
rootController.terminate()
}
}
// MARK: Linking delegate methods
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
if self.appContainsRealServiceInfoPlist() {
let handled = DynamicLinks.dynamicLinks().handleUniversalLink(userActivity.webpageURL!) { dynamicLink, error in
if let firebaseUrl = self.extractURL(from: dynamicLink) {
userActivity.webpageURL = firebaseUrl
JitsiMeet.sharedInstance().application(application, continue: userActivity, restorationHandler: restorationHandler)
}
}
if handled {
return handled
}
}
return JitsiMeet.sharedInstance().application(application, continue: userActivity, restorationHandler: restorationHandler)
}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
if url.absoluteString.contains("google/link/?dismiss=1&is_weak_match=1") {
return false
}
var openUrl = url
if self.appContainsRealServiceInfoPlist() {
if let dynamicLink = DynamicLinks.dynamicLinks().dynamicLink(fromCustomSchemeURL: url),
let firebaseUrl = self.extractURL(from: dynamicLink) {
openUrl = firebaseUrl
}
}
return JitsiMeet.sharedInstance().application(app, open: openUrl, options: options)
}
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
return JitsiMeet.sharedInstance().application(application, supportedInterfaceOrientationsFor: window)
}
}
// Firebase utilities
extension AppDelegate {
func appContainsRealServiceInfoPlist() -> Bool {
return InfoPlistUtil.containsRealServiceInfoPlist(in: Bundle.main)
}
func extractURL(from dynamicLink: DynamicLink?) -> URL? {
guard let dynamicLink = dynamicLink,
let dynamicLinkURL = dynamicLink.url,
dynamicLink.matchType == .unique || dynamicLink.matchType == .default else {
return nil
}
return dynamicLinkURL
}
}

View File

@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7702" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES">
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina6_12" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7701"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>

View File

@@ -1,30 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12120" systemVersion="16F73" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="u7g-vg-A8m">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12088"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="xSm-U5-Hdu">
<objects>
<viewController id="u7g-vg-A8m" customClass="ViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="d40-fc-Y8P"/>
<viewControllerLayoutGuide type="bottom" id="1KD-Ho-g0H"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="QpR-jB-WOw" customClass="JitsiMeetView">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="ZIj-K3-jVH" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="28" y="138"/>
</scene>
</scenes>
</document>

View File

@@ -1,27 +0,0 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
@import Firebase;
@interface FIRUtilities : NSObject
+ (BOOL)appContainsRealServiceInfoPlist;
+ (NSURL *_Nullable)extractURL: (FIRDynamicLink* _Nullable)dynamicLink;
@end

View File

@@ -1,48 +0,0 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRUtilities.h"
@import JitsiMeetSDK;
@implementation FIRUtilities
+ (BOOL)appContainsRealServiceInfoPlist {
static BOOL containsRealServiceInfoPlist = NO;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSBundle *bundle = [NSBundle mainBundle];
containsRealServiceInfoPlist = [InfoPlistUtil containsRealServiceInfoPlistInBundle:bundle];
});
return containsRealServiceInfoPlist;
}
+ (NSURL *)extractURL: (FIRDynamicLink*)dynamicLink {
NSURL *url = nil;
if (dynamicLink != nil) {
NSURL *dynamicLinkURL = dynamicLink.url;
if (dynamicLinkURL != nil
&& (dynamicLink.matchType == FIRDLMatchTypeUnique
|| dynamicLink.matchType == FIRDLMatchTypeDefault)) {
// Strong match, process it.
url = dynamicLinkURL;
}
}
return url;
}
@end

View File

@@ -88,8 +88,6 @@
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>

View File

@@ -1,7 +0,0 @@
#import <Foundation/Foundation.h>
// This must match what's defined in the NSUserActivityTypes array in the
// Info.plist file.
static NSString *const JitsiMeetConferenceActivityType
= @"org.jitsi.JitsiMeet.ios.conference";

View File

@@ -1,24 +0,0 @@
/*
* Copyright @ 2017-present Atlassian Pty Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@import UIKit;
@import JitsiMeetSDK;
@interface ViewController : UIViewController<JitsiMeetViewDelegate>
- (void)terminate;
@end

View File

@@ -1,157 +0,0 @@
/*
* Copyright @ 2017-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@import CoreSpotlight;
@import MobileCoreServices;
@import Intents; // Needed for NSUserActivity suggestedInvocationPhrase
@import JitsiMeetSDK;
#import "Types.h"
#import "ViewController.h"
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
JitsiMeetView *view = (JitsiMeetView *) self.view;
view.delegate = self;
[view join:[[JitsiMeet sharedInstance] getInitialConferenceOptions]];
}
// JitsiMeetViewDelegate
- (void)_onJitsiMeetViewDelegateEvent:(NSString *)name
withData:(NSDictionary *)data {
NSLog(
@"[%s:%d] JitsiMeetViewDelegate %@ %@",
__FILE__, __LINE__, name, data);
#if DEBUG
NSAssert(
[NSThread isMainThread],
@"JitsiMeetViewDelegate %@ method invoked on a non-main thread",
name);
#endif
}
- (void)conferenceJoined:(NSDictionary *)data {
[self _onJitsiMeetViewDelegateEvent:@"CONFERENCE_JOINED" withData:data];
// Register a NSUserActivity for this conference so it can be invoked as a
// Siri shortcut.
NSUserActivity *userActivity
= [[NSUserActivity alloc] initWithActivityType:JitsiMeetConferenceActivityType];
NSString *urlStr = data[@"url"];
NSURL *url = [NSURL URLWithString:urlStr];
NSString *conference = [url.pathComponents lastObject];
userActivity.title = [NSString stringWithFormat:@"Join %@", conference];
userActivity.suggestedInvocationPhrase = @"Join my Jitsi meeting";
userActivity.userInfo = @{@"url": urlStr};
[userActivity setEligibleForSearch:YES];
[userActivity setEligibleForPrediction:YES];
[userActivity setPersistentIdentifier:urlStr];
// Subtitle
CSSearchableItemAttributeSet *attributes
= [[CSSearchableItemAttributeSet alloc] initWithItemContentType:(NSString *)kUTTypeItem];
attributes.contentDescription = urlStr;
userActivity.contentAttributeSet = attributes;
self.userActivity = userActivity;
[userActivity becomeCurrent];
}
- (void)conferenceTerminated:(NSDictionary *)data {
[self _onJitsiMeetViewDelegateEvent:@"CONFERENCE_TERMINATED" withData:data];
}
// - (void)conferenceUniqueIdSet:(NSDictionary *)data {
// [self _onJitsiMeetViewDelegateEvent:@"CONFERENCE_UNIQUE_ID_SET" withData:data];
// }
- (void)conferenceWillJoin:(NSDictionary *)data {
[self _onJitsiMeetViewDelegateEvent:@"CONFERENCE_WILL_JOIN" withData:data];
}
// - (void)customButtonPressed:(NSDictionary *)data {
// [self _onJitsiMeetViewDelegateEvent:@"CUSTOM_BUTTON_PRESSED" withData:data];
// }
#if 0
- (void)enterPictureInPicture:(NSDictionary *)data {
[self _onJitsiMeetViewDelegateEvent:@"ENTER_PICTURE_IN_PICTURE" withData:data];
}
#endif
- (void)readyToClose:(NSDictionary *)data {
[self _onJitsiMeetViewDelegateEvent:@"READY_TO_CLOSE" withData:data];
}
// - (void)recordingStatusChanged:(NSDictionary *)data {
// [self _onJitsiMeetViewDelegateEvent:@"RECORDING_STATUS_CHANGED" withData:data];
// }
// - (void)transcriptionChunkReceived:(NSDictionary *)data {
// [self _onJitsiMeetViewDelegateEvent:@"TRANSCRIPTION_CHUNK_RECEIVED" withData:data];
// }
- (void)participantJoined:(NSDictionary *)data {
NSLog(@"%@%@", @"Participant joined: ", data[@"participantId"]);
}
- (void)participantLeft:(NSDictionary *)data {
NSLog(@"%@%@", @"Participant left: ", data[@"participantId"]);
}
- (void)audioMutedChanged:(NSDictionary *)data {
NSLog(@"%@%@", @"Audio muted changed: ", data[@"muted"]);
}
- (void)endpointTextMessageReceived:(NSDictionary *)data {
NSLog(@"%@%@", @"Endpoint text message received: ", data);
}
- (void)screenShareToggled:(NSDictionary *)data {
NSLog(@"%@%@", @"Screen share toggled: ", data);
}
- (void)chatMessageReceived:(NSDictionary *)data {
NSLog(@"%@%@", @"Chat message received: ", data);
}
- (void)chatToggled:(NSDictionary *)data {
NSLog(@"%@%@", @"Chat toggled: ", data);
}
- (void)videoMutedChanged:(NSDictionary *)data {
NSLog(@"%@%@", @"Video muted changed: ", data[@"muted"]);
}
#pragma mark - Helpers
- (void)terminate {
JitsiMeetView *view = (JitsiMeetView *) self.view;
[view leave];
}
@end

View File

@@ -0,0 +1,94 @@
/*
* Copyright @ 2025-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import CoreSpotlight
import Intents
import MobileCoreServices
import UIKit
import JitsiMeetSDK
@objcMembers
class ViewController: UIViewController {
override func loadView() {
let jitsiView = JitsiMeetView(frame: UIScreen.main.bounds)
self.view = jitsiView
}
override func viewDidLoad() {
super.viewDidLoad()
guard let view = self.view as? JitsiMeetView else { return }
view.delegate = self
view.join(JitsiMeet.sharedInstance().getInitialConferenceOptions())
}
// MARK: - Helper Methods
func terminate() {
guard let view = self.view as? JitsiMeetView else { return }
view.leave()
}
}
extension ViewController: @preconcurrency JitsiMeetViewDelegate {
// MARK: - Private Helper Methods
private func onJitsiMeetViewDelegateEvent(_ name: String, withData data: [AnyHashable: Any]?) {
NSLog("[%@:%d] JitsiMeetViewDelegate %@ %@", #file, #line, name, data ?? [:])
#if DEBUG
assert(Thread.isMainThread, "JitsiMeetViewDelegate \(name) method invoked on a non-main thread")
#endif
}
// MARK: - JitsiMeetViewDelegate
func conferenceJoined(_ data: [AnyHashable: Any]) {
onJitsiMeetViewDelegateEvent("CONFERENCE_JOINED", withData: data)
// Register a NSUserActivity for this conference so it can be invoked as a Siri shortcut.
// Must match the one defined in Info.plist
let userActivity = NSUserActivity(activityType: "org.jitsi.JitsiMeet.ios.conference")
if let urlStr = data["url"] as? String,
let url = URL(string: urlStr),
let conference = url.pathComponents.last {
userActivity.title = "Join \(conference)"
userActivity.suggestedInvocationPhrase = "Join my Jitsi meeting"
userActivity.userInfo = ["url": urlStr]
userActivity.isEligibleForSearch = true
userActivity.isEligibleForPrediction = true
userActivity.persistentIdentifier = urlStr
// Subtitle
let attributes = CSSearchableItemAttributeSet(contentType: UTType.item)
attributes.contentDescription = urlStr
userActivity.contentAttributeSet = attributes
self.userActivity = userActivity
userActivity.becomeCurrent()
}
}
func ready(toClose data: [AnyHashable: Any]) {
onJitsiMeetViewDelegateEvent("READY_TO_CLOSE", withData: data)
}
}

View File

@@ -1,28 +0,0 @@
/*
* Copyright @ 2017-present Atlassian Pty Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(
argc, argv,
nil,
NSStringFromClass([AppDelegate class]));
}
}

15
ios/patches/ws-tls13.diff Normal file
View File

@@ -0,0 +1,15 @@
diff --git a/SocketRocket/SRSecurityPolicy.m b/SocketRocket/SRSecurityPolicy.m
index 3759d26e..271477e8 100644
--- a/SocketRocket/SRSecurityPolicy.m
+++ b/SocketRocket/SRSecurityPolicy.m
@@ -56,8 +56,8 @@ - (instancetype)init
- (void)updateSecurityOptionsInStream:(NSStream *)stream
{
- // Enforce TLS 1.2
- [stream setProperty:(__bridge id)CFSTR("kCFStreamSocketSecurityLevelTLSv1_2") forKey:(__bridge id)kCFStreamPropertySocketSecurityLevel];
+ // Enforce TLS >= 1.2
+ [stream setProperty:(__bridge id)kCFStreamSocketSecurityLevelNegotiatedSSL forKey:(__bridge id)kCFStreamPropertySocketSecurityLevel];
// Validate certificate chain for this stream if enabled.
NSDictionary<NSString *, id> *sslOptions = @{ (__bridge NSString *)kCFStreamSSLValidatesCertificateChain : @(self.certificateChainValidationEnabled) };

View File

@@ -869,6 +869,7 @@
baseConfigurationReference = 09A78016288AF50ACD28A10D /* Pods-JitsiMeetSDK.debug.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
@@ -892,8 +893,6 @@
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_INSTALL_OBJC_HEADER = NO;
SWIFT_OBJC_INTERFACE_HEADER_NAME = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
@@ -905,6 +904,7 @@
baseConfigurationReference = 891FE43DAD30BC8976683100 /* Pods-JitsiMeetSDK.release.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
@@ -928,8 +928,6 @@
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_INSTALL_OBJC_HEADER = NO;
SWIFT_OBJC_INTERFACE_HEADER_NAME = "";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
@@ -940,6 +938,7 @@
baseConfigurationReference = 8F48C340DE0D91D1012976C5 /* Pods-JitsiMeetSDKLite.debug.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
@@ -968,8 +967,6 @@
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_INSTALL_OBJC_HEADER = NO;
SWIFT_OBJC_INTERFACE_HEADER_NAME = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
@@ -981,6 +978,7 @@
baseConfigurationReference = 86389F55993FAAF6AEB3FA3E /* Pods-JitsiMeetSDKLite.release.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
@@ -1009,8 +1007,6 @@
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_INSTALL_OBJC_HEADER = NO;
SWIFT_OBJC_INTERFACE_HEADER_NAME = "";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};

View File

@@ -82,7 +82,7 @@ typedef NS_ENUM(NSInteger, WebRTCLoggingSeverity) {
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *_Nonnull)options;
- (UIInterfaceOrientationMask)application:(UIApplication *_Nonnull)application
supportedInterfaceOrientationsForWindow:(UIWindow *_Nonnull)window;
supportedInterfaceOrientationsForWindow:(UIWindow *_Nullable)window;
#pragma mark - Utility methods

View File

@@ -676,7 +676,7 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
*
* @returns {Object} Rooms info.
*/
async getRoomsInfo() {
getRoomsInfo() {
return this._transport.sendRequest({
name: 'rooms-info'
});
@@ -687,7 +687,7 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
*
* @returns {Object} Rooms info.
*/
async getSharedDocumentUrl() {
getSharedDocumentUrl() {
return this._transport.sendRequest({
name: 'get-shared-document-url'
});

567
package-lock.json generated
View File

@@ -62,7 +62,7 @@
"js-md5": "0.6.1",
"js-sha512": "0.8.0",
"jwt-decode": "2.2.0",
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1919.0.0+d4a47d0e/lib-jitsi-meet.tgz",
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1928.0.0+763b2c8f/lib-jitsi-meet.tgz",
"lodash-es": "4.17.21",
"moment": "2.29.4",
"moment-duration-format": "2.2.2",
@@ -123,13 +123,11 @@
},
"devDependencies": {
"@babel/core": "7.25.9",
"@babel/eslint-parser": "7.25.9",
"@babel/plugin-transform-private-methods": "7.25.9",
"@babel/preset-env": "7.25.9",
"@babel/preset-react": "7.25.9",
"@jitsi/eslint-config": "5.0.9",
"@jitsi/eslint-config": "6.0.1",
"@react-native/metro-config": "0.75.5",
"@stylistic/eslint-plugin": "2.12.1",
"@types/amplitude-js": "8.16.5",
"@types/audioworklet": "0.0.29",
"@types/dom-screen-wake-lock": "1.0.1",
@@ -155,8 +153,6 @@
"@types/w3c-image-capture": "1.0.6",
"@types/w3c-web-hid": "1.0.3",
"@types/zxcvbn": "4.4.1",
"@typescript-eslint/eslint-plugin": "8.19.1",
"@typescript-eslint/parser": "8.19.1",
"@wdio/allure-reporter": "9.4.3",
"@wdio/cli": "9.4.3",
"@wdio/globals": "9.4.3",
@@ -4152,14 +4148,20 @@
}
},
"node_modules/@jitsi/eslint-config": {
"version": "5.0.9",
"resolved": "https://registry.npmjs.org/@jitsi/eslint-config/-/eslint-config-5.0.9.tgz",
"integrity": "sha512-Xs44+Q8dU3dYvHuDYbcYWUwEwsGIWFD8tAX2WdtTihtaTkmzYBt74Piiyqe3qQSp1CYIfr85wl30BFf5oTZtXg==",
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/@jitsi/eslint-config/-/eslint-config-6.0.1.tgz",
"integrity": "sha512-Y7Bkcx7NK4ctYKVX57zS51Z7Ak2jtoYctr/Xso5Gh1E/Gl32KipTkF5Fg142qo1x2KH/ossk/P1emdqTHBnAWQ==",
"dev": true,
"license": "Apache-2.0",
"peerDependencies": {
"@babel/eslint-parser": ">= 7",
"eslint": ">= 8"
"dependencies": {
"@babel/eslint-parser": "^7.25.9",
"@stylistic/eslint-plugin": "^2.12.1",
"@typescript-eslint/eslint-plugin": "^8.19.1",
"@typescript-eslint/parser": "^8.19.1",
"eslint": "^8.57.0",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-jsdoc": "^50.6.1",
"eslint-plugin-typescript-sort-keys": "^3.3.0"
}
},
"node_modules/@jitsi/excalidraw": {
@@ -8803,7 +8805,8 @@
"node_modules/@yarnpkg/lockfile": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz",
"integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ=="
"integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==",
"dev": true
},
"node_modules/@zip.js/zip.js": {
"version": "2.7.54",
@@ -9617,14 +9620,6 @@
"integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==",
"license": "MIT"
},
"node_modules/at-least-node": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
"integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
"engines": {
"node": ">= 4.0.0"
}
},
"node_modules/available-typed-arrays": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
@@ -9969,6 +9964,7 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
"dev": true,
"engines": {
"node": ">=8"
}
@@ -10519,6 +10515,7 @@
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
"dev": true,
"dependencies": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
@@ -10542,6 +10539,7 @@
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
"dependencies": {
"is-glob": "^4.0.1"
},
@@ -11435,11 +11433,6 @@
"integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==",
"license": "MIT"
},
"node_modules/debounce": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz",
"integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug=="
},
"node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -13837,6 +13830,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz",
"integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==",
"dev": true,
"dependencies": {
"micromatch": "^4.0.2"
}
@@ -15191,6 +15185,7 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"dev": true,
"dependencies": {
"binary-extensions": "^2.0.0"
},
@@ -15246,6 +15241,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz",
"integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==",
"dev": true,
"dependencies": {
"ci-info": "^2.0.0"
},
@@ -16788,21 +16784,6 @@
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-2.2.0.tgz",
"integrity": "sha1-fYa9VmefWM5qhHBKZX3TkruoGnk="
},
"node_modules/karma-rollup-preprocessor": {
"version": "7.0.8",
"resolved": "https://registry.npmjs.org/karma-rollup-preprocessor/-/karma-rollup-preprocessor-7.0.8.tgz",
"integrity": "sha512-WiuBCS9qsatJuR17dghiTARBZ7LF+ml+eb7qJXhw7IbsdY0lTWELDRQC/93J9i6636CsAXVBL3VJF4WtaFLZzA==",
"dependencies": {
"chokidar": "^3.3.1",
"debounce": "^1.2.0"
},
"engines": {
"node": ">= 8.0.0"
},
"peerDependencies": {
"rollup": ">= 1.0.0"
}
},
"node_modules/kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
@@ -16815,6 +16796,7 @@
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz",
"integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==",
"dev": true,
"dependencies": {
"graceful-fs": "^4.1.11"
}
@@ -16909,9 +16891,8 @@
},
"node_modules/lib-jitsi-meet": {
"version": "0.0.0",
"resolved": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1919.0.0+d4a47d0e/lib-jitsi-meet.tgz",
"integrity": "sha512-0/rTgoaaXwKs4J2+MY4HYh/VbZg3gjNHInhAz+smZGlWsJB8H2qkSNVU0HcTI7WG5LzrzkX4c/eTVpkq8ljLJw==",
"hasInstallScript": true,
"resolved": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1928.0.0+763b2c8f/lib-jitsi-meet.tgz",
"integrity": "sha512-gjJfU1Ll4sYIpPM3vE5nFnPQgun2D/8RoYCsOmk+P1V/OZWx1E+v3iZiK6OyzgGnZlIPlF83rcUMUYy8WIFFCA==",
"license": "Apache-2.0",
"dependencies": {
"@jitsi/js-utils": "2.2.1",
@@ -16924,11 +16905,8 @@
"current-executing-script": "0.1.3",
"jquery": "3.6.1",
"lodash-es": "4.17.21",
"patch-package": "6.5.1",
"sdp-transform": "2.3.0",
"strophe.js": "1.5.0",
"strophejs-plugin-disco": "0.0.2",
"strophejs-plugin-stream-management": "git+https://github.com/jitsi/strophejs-plugin-stream-management#679be5902097ed612fb5062b5549f3f32b6f5f47",
"strophe.js": "https://github.com/jitsi/strophejs/releases/download/v1.5-jitsi-3/strophe.js-1.5.0.tgz",
"uuid": "8.1.0",
"webrtc-adapter": "8.1.1"
}
@@ -16952,197 +16930,11 @@
"uuid": "dist/bin/uuid"
}
},
"node_modules/lib-jitsi-meet/node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dependencies": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/lib-jitsi-meet/node_modules/base64-js": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
"integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
},
"node_modules/lib-jitsi-meet/node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/lib-jitsi-meet/node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/lib-jitsi-meet/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"node_modules/lib-jitsi-meet/node_modules/cross-spawn": {
"version": "6.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz",
"integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==",
"dependencies": {
"nice-try": "^1.0.4",
"path-key": "^2.0.1",
"semver": "^5.5.0",
"shebang-command": "^1.2.0",
"which": "^1.2.9"
},
"engines": {
"node": ">=4.8"
}
},
"node_modules/lib-jitsi-meet/node_modules/fs-extra": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
"integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
"dependencies": {
"at-least-node": "^1.0.0",
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^2.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/lib-jitsi-meet/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"engines": {
"node": ">=8"
}
},
"node_modules/lib-jitsi-meet/node_modules/jsonfile": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
"dependencies": {
"universalify": "^2.0.0"
},
"optionalDependencies": {
"graceful-fs": "^4.1.6"
}
},
"node_modules/lib-jitsi-meet/node_modules/patch-package": {
"version": "6.5.1",
"resolved": "https://registry.npmjs.org/patch-package/-/patch-package-6.5.1.tgz",
"integrity": "sha512-I/4Zsalfhc6bphmJTlrLoOcAF87jcxko4q0qsv4bGcurbr8IskEOtdnt9iCmsQVGL1B+iUhSQqweyTLJfCF9rA==",
"dependencies": {
"@yarnpkg/lockfile": "^1.1.0",
"chalk": "^4.1.2",
"cross-spawn": "^6.0.5",
"find-yarn-workspace-root": "^2.0.0",
"fs-extra": "^9.0.0",
"is-ci": "^2.0.0",
"klaw-sync": "^6.0.0",
"minimist": "^1.2.6",
"open": "^7.4.2",
"rimraf": "^2.6.3",
"semver": "^5.6.0",
"slash": "^2.0.0",
"tmp": "^0.0.33",
"yaml": "^1.10.2"
},
"bin": {
"patch-package": "index.js"
},
"engines": {
"node": ">=10",
"npm": ">5"
}
},
"node_modules/lib-jitsi-meet/node_modules/path-key": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
"integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==",
"engines": {
"node": ">=4"
}
},
"node_modules/lib-jitsi-meet/node_modules/rimraf": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
"dependencies": {
"glob": "^7.1.3"
},
"bin": {
"rimraf": "bin.js"
}
},
"node_modules/lib-jitsi-meet/node_modules/semver": {
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"bin": {
"semver": "bin/semver"
}
},
"node_modules/lib-jitsi-meet/node_modules/shebang-command": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
"integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==",
"dependencies": {
"shebang-regex": "^1.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/lib-jitsi-meet/node_modules/shebang-regex": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
"integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/lib-jitsi-meet/node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dependencies": {
"has-flag": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/lib-jitsi-meet/node_modules/universalify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
"engines": {
"node": ">= 10.0.0"
}
},
"node_modules/lib-jitsi-meet/node_modules/uuid": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.1.0.tgz",
@@ -17151,17 +16943,6 @@
"uuid": "dist/bin/uuid"
}
},
"node_modules/lib-jitsi-meet/node_modules/which": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
"dependencies": {
"isexe": "^2.0.0"
},
"bin": {
"which": "bin/which"
}
},
"node_modules/lie": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
@@ -18798,7 +18579,8 @@
"node_modules/nice-try": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
"dev": true
},
"node_modules/no-case": {
"version": "3.0.4",
@@ -19325,6 +19107,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -21859,6 +21642,7 @@
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
"dev": true,
"dependencies": {
"picomatch": "^2.2.1"
},
@@ -22875,6 +22659,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
"integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
"dev": true,
"engines": {
"node": ">=6"
}
@@ -23458,54 +23243,9 @@
},
"node_modules/strophe.js": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/strophe.js/-/strophe.js-1.5.0.tgz",
"integrity": "sha512-H5tE/tZxPR5xP3jhXyQwsjnMSwQMf7vrn9r1OkufTApyGHYe8WjzhsfxtL3AFhVu7vFjXPPZBrmUOTm1ccYgOA==",
"dependencies": {
"abab": "^2.0.3",
"karma-rollup-preprocessor": "^7.0.8"
},
"optionalDependencies": {
"@xmldom/xmldom": "0.8.2",
"ws": "^8.5.0"
}
},
"node_modules/strophe.js/node_modules/ws": {
"version": "8.18.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
"integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
"optional": true,
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/strophejs-plugin-disco": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/strophejs-plugin-disco/-/strophejs-plugin-disco-0.0.2.tgz",
"integrity": "sha512-T9pJFzn1ZUqZ/we9+OvI5pFdrjeb4IBMbEjK+ZWEZV036wEl8l8GOtF8AJ3sIqOMtdIiFLdFu99JiGWd7yapAQ==",
"peerDependencies": {
"strophe.js": "^1.2.12"
}
},
"node_modules/strophejs-plugin-stream-management": {
"version": "1.0.0",
"resolved": "git+ssh://git@github.com/jitsi/strophejs-plugin-stream-management.git#679be5902097ed612fb5062b5549f3f32b6f5f47",
"integrity": "sha512-pQUT174bznpLEVNAnJT2Q7lyoSaoIoo8LaVyglRx5rWwxpdHUcS+8NjfLYDlqM+rLcsO1uAKt/fMZ7j3clj9qg==",
"license": "MIT",
"peerDependencies": {
"strophe.js": ">=1.3.4"
}
"resolved": "https://github.com/jitsi/strophejs/releases/download/v1.5-jitsi-3/strophe.js-1.5.0.tgz",
"integrity": "sha512-LNtsu2qioXofCESHqEmLF12DuIK7itMMjxe9aSeQOENz8rCXBY/khV8OKO2xaWBy0QxpQs7nyb7RHefVu9ZlfA==",
"license": "MIT"
},
"node_modules/style-loader": {
"version": "3.3.1",
@@ -23867,6 +23607,7 @@
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
"dev": true,
"dependencies": {
"os-tmpdir": "~1.0.2"
},
@@ -28591,10 +28332,20 @@
}
},
"@jitsi/eslint-config": {
"version": "5.0.9",
"resolved": "https://registry.npmjs.org/@jitsi/eslint-config/-/eslint-config-5.0.9.tgz",
"integrity": "sha512-Xs44+Q8dU3dYvHuDYbcYWUwEwsGIWFD8tAX2WdtTihtaTkmzYBt74Piiyqe3qQSp1CYIfr85wl30BFf5oTZtXg==",
"dev": true
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/@jitsi/eslint-config/-/eslint-config-6.0.1.tgz",
"integrity": "sha512-Y7Bkcx7NK4ctYKVX57zS51Z7Ak2jtoYctr/Xso5Gh1E/Gl32KipTkF5Fg142qo1x2KH/ossk/P1emdqTHBnAWQ==",
"dev": true,
"requires": {
"@babel/eslint-parser": "^7.25.9",
"@stylistic/eslint-plugin": "^2.12.1",
"@typescript-eslint/eslint-plugin": "^8.19.1",
"@typescript-eslint/parser": "^8.19.1",
"eslint": "^8.57.0",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-jsdoc": "^50.6.1",
"eslint-plugin-typescript-sort-keys": "^3.3.0"
}
},
"@jitsi/excalidraw": {
"version": "https://github.com/jitsi/excalidraw/releases/download/v0.0.19/jitsi-excalidraw-0.0.19.tgz",
@@ -31860,7 +31611,8 @@
"@yarnpkg/lockfile": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz",
"integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ=="
"integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==",
"dev": true
},
"@zip.js/zip.js": {
"version": "2.7.54",
@@ -32425,11 +32177,6 @@
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
"integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="
},
"at-least-node": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
"integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg=="
},
"available-typed-arrays": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
@@ -32698,7 +32445,8 @@
"binary-extensions": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA=="
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
"dev": true
},
"bl": {
"version": "4.1.0",
@@ -33083,6 +32831,7 @@
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
"dev": true,
"requires": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
@@ -33098,6 +32847,7 @@
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
"requires": {
"is-glob": "^4.0.1"
}
@@ -33750,11 +33500,6 @@
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
"integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg=="
},
"debounce": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz",
"integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug=="
},
"debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -35471,6 +35216,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz",
"integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==",
"dev": true,
"requires": {
"micromatch": "^4.0.2"
}
@@ -36428,6 +36174,7 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"dev": true,
"requires": {
"binary-extensions": "^2.0.0"
}
@@ -36465,6 +36212,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz",
"integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==",
"dev": true,
"requires": {
"ci-info": "^2.0.0"
}
@@ -37543,15 +37291,6 @@
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-2.2.0.tgz",
"integrity": "sha1-fYa9VmefWM5qhHBKZX3TkruoGnk="
},
"karma-rollup-preprocessor": {
"version": "7.0.8",
"resolved": "https://registry.npmjs.org/karma-rollup-preprocessor/-/karma-rollup-preprocessor-7.0.8.tgz",
"integrity": "sha512-WiuBCS9qsatJuR17dghiTARBZ7LF+ml+eb7qJXhw7IbsdY0lTWELDRQC/93J9i6636CsAXVBL3VJF4WtaFLZzA==",
"requires": {
"chokidar": "^3.3.1",
"debounce": "^1.2.0"
}
},
"kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
@@ -37561,6 +37300,7 @@
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz",
"integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==",
"dev": true,
"requires": {
"graceful-fs": "^4.1.11"
}
@@ -37637,8 +37377,8 @@
}
},
"lib-jitsi-meet": {
"version": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1919.0.0+d4a47d0e/lib-jitsi-meet.tgz",
"integrity": "sha512-0/rTgoaaXwKs4J2+MY4HYh/VbZg3gjNHInhAz+smZGlWsJB8H2qkSNVU0HcTI7WG5LzrzkX4c/eTVpkq8ljLJw==",
"version": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1928.0.0+763b2c8f/lib-jitsi-meet.tgz",
"integrity": "sha512-gjJfU1Ll4sYIpPM3vE5nFnPQgun2D/8RoYCsOmk+P1V/OZWx1E+v3iZiK6OyzgGnZlIPlF83rcUMUYy8WIFFCA==",
"requires": {
"@jitsi/js-utils": "2.2.1",
"@jitsi/logger": "2.0.2",
@@ -37650,11 +37390,8 @@
"current-executing-script": "0.1.3",
"jquery": "3.6.1",
"lodash-es": "4.17.21",
"patch-package": "6.5.1",
"sdp-transform": "2.3.0",
"strophe.js": "1.5.0",
"strophejs-plugin-disco": "0.0.2",
"strophejs-plugin-stream-management": "git+https://github.com/jitsi/strophejs-plugin-stream-management#679be5902097ed612fb5062b5549f3f32b6f5f47",
"strophe.js": "https://github.com/jitsi/strophejs/releases/download/v1.5-jitsi-3/strophe.js-1.5.0.tgz",
"uuid": "8.1.0",
"webrtc-adapter": "8.1.1"
},
@@ -37677,155 +37414,15 @@
}
}
},
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"requires": {
"color-convert": "^2.0.1"
}
},
"base64-js": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
"integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
},
"chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"cross-spawn": {
"version": "6.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz",
"integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==",
"requires": {
"nice-try": "^1.0.4",
"path-key": "^2.0.1",
"semver": "^5.5.0",
"shebang-command": "^1.2.0",
"which": "^1.2.9"
}
},
"fs-extra": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
"integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
"requires": {
"at-least-node": "^1.0.0",
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^2.0.0"
}
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
},
"jsonfile": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
"requires": {
"graceful-fs": "^4.1.6",
"universalify": "^2.0.0"
}
},
"patch-package": {
"version": "6.5.1",
"resolved": "https://registry.npmjs.org/patch-package/-/patch-package-6.5.1.tgz",
"integrity": "sha512-I/4Zsalfhc6bphmJTlrLoOcAF87jcxko4q0qsv4bGcurbr8IskEOtdnt9iCmsQVGL1B+iUhSQqweyTLJfCF9rA==",
"requires": {
"@yarnpkg/lockfile": "^1.1.0",
"chalk": "^4.1.2",
"cross-spawn": "^6.0.5",
"find-yarn-workspace-root": "^2.0.0",
"fs-extra": "^9.0.0",
"is-ci": "^2.0.0",
"klaw-sync": "^6.0.0",
"minimist": "^1.2.6",
"open": "^7.4.2",
"rimraf": "^2.6.3",
"semver": "^5.6.0",
"slash": "^2.0.0",
"tmp": "^0.0.33",
"yaml": "^1.10.2"
}
},
"path-key": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
"integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw=="
},
"rimraf": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
"requires": {
"glob": "^7.1.3"
}
},
"semver": {
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="
},
"shebang-command": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
"integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==",
"requires": {
"shebang-regex": "^1.0.0"
}
},
"shebang-regex": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
"integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ=="
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"requires": {
"has-flag": "^4.0.0"
}
},
"universalify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ=="
},
"uuid": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.1.0.tgz",
"integrity": "sha512-CI18flHDznR0lq54xBycOVmphdCYnQLKn8abKn7PXUiKUGdEd+/l9LWNJmugXel4hXq7S+RMNl34ecyC9TntWg=="
},
"which": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
"requires": {
"isexe": "^2.0.0"
}
}
}
},
@@ -39047,7 +38644,8 @@
"nice-try": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
"dev": true
},
"no-case": {
"version": "3.0.4",
@@ -39388,7 +38986,8 @@
"os-tmpdir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
"dev": true
},
"own-keys": {
"version": "1.0.1",
@@ -41068,6 +40667,7 @@
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
"dev": true,
"requires": {
"picomatch": "^2.2.1"
}
@@ -41836,7 +41436,8 @@
"slash": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
"integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A=="
"integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
"dev": true
},
"slashes": {
"version": "3.0.12",
@@ -42275,33 +41876,8 @@
"integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA=="
},
"strophe.js": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/strophe.js/-/strophe.js-1.5.0.tgz",
"integrity": "sha512-H5tE/tZxPR5xP3jhXyQwsjnMSwQMf7vrn9r1OkufTApyGHYe8WjzhsfxtL3AFhVu7vFjXPPZBrmUOTm1ccYgOA==",
"requires": {
"@xmldom/xmldom": "0.8.7",
"abab": "^2.0.3",
"karma-rollup-preprocessor": "^7.0.8",
"ws": "^8.5.0"
},
"dependencies": {
"ws": {
"version": "8.18.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
"integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
"optional": true
}
}
},
"strophejs-plugin-disco": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/strophejs-plugin-disco/-/strophejs-plugin-disco-0.0.2.tgz",
"integrity": "sha512-T9pJFzn1ZUqZ/we9+OvI5pFdrjeb4IBMbEjK+ZWEZV036wEl8l8GOtF8AJ3sIqOMtdIiFLdFu99JiGWd7yapAQ=="
},
"strophejs-plugin-stream-management": {
"version": "git+ssh://git@github.com/jitsi/strophejs-plugin-stream-management.git#679be5902097ed612fb5062b5549f3f32b6f5f47",
"integrity": "sha512-pQUT174bznpLEVNAnJT2Q7lyoSaoIoo8LaVyglRx5rWwxpdHUcS+8NjfLYDlqM+rLcsO1uAKt/fMZ7j3clj9qg==",
"from": "strophejs-plugin-stream-management@git+https://github.com/jitsi/strophejs-plugin-stream-management#679be5902097ed612fb5062b5549f3f32b6f5f47"
"version": "https://github.com/jitsi/strophejs/releases/download/v1.5-jitsi-3/strophe.js-1.5.0.tgz",
"integrity": "sha512-LNtsu2qioXofCESHqEmLF12DuIK7itMMjxe9aSeQOENz8rCXBY/khV8OKO2xaWBy0QxpQs7nyb7RHefVu9ZlfA=="
},
"style-loader": {
"version": "3.3.1",
@@ -42559,6 +42135,7 @@
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
"dev": true,
"requires": {
"os-tmpdir": "~1.0.2"
}

View File

@@ -68,7 +68,7 @@
"js-md5": "0.6.1",
"js-sha512": "0.8.0",
"jwt-decode": "2.2.0",
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1919.0.0+d4a47d0e/lib-jitsi-meet.tgz",
"lib-jitsi-meet": "https://github.com/jitsi/lib-jitsi-meet/releases/download/v1928.0.0+763b2c8f/lib-jitsi-meet.tgz",
"lodash-es": "4.17.21",
"moment": "2.29.4",
"moment-duration-format": "2.2.2",
@@ -129,13 +129,11 @@
},
"devDependencies": {
"@babel/core": "7.25.9",
"@babel/eslint-parser": "7.25.9",
"@babel/plugin-transform-private-methods": "7.25.9",
"@babel/preset-env": "7.25.9",
"@babel/preset-react": "7.25.9",
"@jitsi/eslint-config": "5.0.9",
"@jitsi/eslint-config": "6.0.1",
"@react-native/metro-config": "0.75.5",
"@stylistic/eslint-plugin": "2.12.1",
"@types/amplitude-js": "8.16.5",
"@types/audioworklet": "0.0.29",
"@types/dom-screen-wake-lock": "1.0.1",
@@ -161,8 +159,6 @@
"@types/w3c-image-capture": "1.0.6",
"@types/w3c-web-hid": "1.0.3",
"@types/zxcvbn": "4.4.1",
"@typescript-eslint/eslint-plugin": "8.19.1",
"@typescript-eslint/parser": "8.19.1",
"@wdio/allure-reporter": "9.4.3",
"@wdio/cli": "9.4.3",
"@wdio/globals": "9.4.3",
@@ -199,9 +195,6 @@
"webpack-cli": "5.1.4",
"webpack-dev-server": "5.1.0"
},
"overrides": {
"@xmldom/xmldom": "0.8.7"
},
"engines": {
"node": ">=22.0.0",
"npm": ">=10.0.0"

View File

@@ -87,9 +87,6 @@
"react-native-webrtc": "0.0.0",
"react-native-webview": "0.0.0"
},
"overrides": {
"@xmldom/xmldom": "0.0.0"
},
"scripts": {
"postinstall": "node sdk_instructions.js",
"prepare": "node prepare_sdk.js"

View File

@@ -1,4 +1,4 @@
/* eslint-disable guard-for-in, no-continue */
/* eslint-disable guard-for-in */
/* global __dirname */
const fs = require('fs');

View File

@@ -1,12 +1,11 @@
module.exports = {
'plugins': [
plugins: [
'react-native'
],
'rules': {
rules: {
'react-native/no-color-literals': 2,
'react-native/no-inline-styles': 2,
'react-native/no-unused-styles': 2,
'react-native/split-platform-components': 2
}
};

View File

@@ -1,29 +1,27 @@
module.exports = {
'extends': [
extends: [
'../.eslintrc.js',
'@jitsi/eslint-config/jsdoc',
'@jitsi/eslint-config/react',
'.eslintrc-react-native.js'
],
'overrides': [
overrides: [
{
'files': [ '*.ts', '*.tsx' ],
files: [ '*.ts', '*.tsx' ],
extends: [ '@jitsi/eslint-config/typescript' ],
parserOptions: {
sourceType: 'module',
project: [ './tsconfig.web.json', './tsconfig.native.json' ]
},
rules: {
// TODO: Remove these and fix the warnings
'@typescript-eslint/no-unsafe-function-type': 0,
'@typescript-eslint/no-wrapper-object-types': 0,
'@typescript-eslint/no-require-imports': 0
}
}
],
'settings': {
'react': {
settings: {
react: {
'version': 'detect'
}
}

View File

@@ -572,9 +572,12 @@ function _translateLegacyConfig(oldValue: IConfig) {
};
}
if (oldValue.disableProfile) {
newValue.toolbarButtons = (newValue.toolbarButtons || TOOLBAR_BUTTONS)
.filter((button: ToolbarButton) => button !== 'profile');
// Profile button is not available on mobile
if (navigator.product !== 'ReactNative') {
if (oldValue.disableProfile) {
newValue.toolbarButtons = (newValue.toolbarButtons || TOOLBAR_BUTTONS)
.filter((button: ToolbarButton) => button !== 'profile');
}
}
_setDeeplinkingDefaults(newValue.deeplinking as IDeeplinkingConfig);

View File

@@ -1,9 +1,12 @@
import { ParticipantFeaturesKey } from '../participants/types';
/**
* The list of supported meeting features to enable/disable through jwt.
*/
export const MEET_FEATURES = {
export const MEET_FEATURES: Record<string, ParticipantFeaturesKey> = {
BRANDING: 'branding',
CALENDAR: 'calendar',
CREATE_POLLS: 'create-polls',
FLIP: 'flip',
INBOUND_CALL: 'inbound-call',
LIVESTREAMING: 'livestreaming',
@@ -13,6 +16,7 @@ export const MEET_FEATURES = {
RECORDING: 'recording',
ROOM: 'room',
SCREEN_SHARING: 'screen-sharing',
SEND_GROUPCHAT: 'send-groupchat',
SIP_INBOUND_CALL: 'sip-inbound-call',
SIP_OUTBOUND_CALL: 'sip-outbound-call',
TRANSCRIPTION: 'transcription'

View File

@@ -4,7 +4,7 @@ import jwtDecode from 'jwt-decode';
import { IReduxState } from '../../app/types';
import { isVpaasMeeting } from '../../jaas/functions';
import { getLocalParticipant } from '../participants/functions';
import { IParticipantFeatures } from '../participants/types';
import { IParticipantFeatures, ParticipantFeaturesKey } from '../participants/types';
import { parseURLParams } from '../util/parseURLParams';
import { JWT_VALIDATION_ERRORS, MEET_FEATURES } from './constants';
@@ -49,7 +49,12 @@ export function getJwtName(state: IReduxState) {
* @param {boolean} ifNotInFeatures - Default value if features prop exists but does not have the {@code feature}.
* @returns {boolean}
*/
export function isJwtFeatureEnabled(state: IReduxState, feature: string, ifNoToken: boolean, ifNotInFeatures: boolean) {
export function isJwtFeatureEnabled(
state: IReduxState,
feature: ParticipantFeaturesKey,
ifNoToken: boolean,
ifNotInFeatures: boolean
) {
const { jwt } = state['features/base/jwt'];
let { features } = getLocalParticipant(state) || {};
@@ -68,7 +73,7 @@ export function isJwtFeatureEnabled(state: IReduxState, feature: string, ifNoTok
}
interface IIsJwtFeatureEnabledStatelessParams {
feature: string;
feature: ParticipantFeaturesKey;
ifNoToken: boolean;
ifNotInFeatures: boolean;
jwt?: string;
@@ -101,11 +106,11 @@ export function isJwtFeatureEnabledStateless({
return ifNoToken;
}
if (typeof features[feature as keyof typeof features] === 'undefined') {
if (typeof features[feature] === 'undefined') {
return ifNotInFeatures;
}
return String(features[feature as keyof typeof features]) === 'true';
return String(features[feature]) === 'true';
}
/**
@@ -202,7 +207,7 @@ export function validateJwt(jwt: string) {
const { features } = context;
const meetFeatures = Object.values(MEET_FEATURES);
Object.keys(features).forEach(feature => {
(Object.keys(features) as ParticipantFeaturesKey[]).forEach(feature => {
if (meetFeatures.includes(feature)) {
const featureValue = features[feature];

View File

@@ -165,7 +165,6 @@ function _initLogging({ dispatch, getState }: IStore,
}
Logger.addGlobalTransport(_logCollector);
JitsiMeetJS.addGlobalLogTransport(_logCollector);
dispatch(setLogCollector(_logCollector));
// The JitsiMeetInMemoryLogStorage can not be accessed on mobile through

View File

@@ -57,6 +57,7 @@ export interface ILocalParticipant extends IParticipant {
export interface IParticipantFeatures {
'branding'?: boolean | string;
'calendar'?: boolean | string;
'create-polls'?: boolean | string;
'flip'?: boolean | string;
'inbound-call'?: boolean | string;
'livestreaming'?: boolean | string;
@@ -66,6 +67,7 @@ export interface IParticipantFeatures {
'recording'?: boolean | string;
'room'?: boolean | string;
'screen-sharing'?: boolean | string;
'send-groupchat'?: boolean | string;
'sip-inbound-call'?: boolean | string;
'sip-outbound-call'?: boolean | string;
'transcription'?: boolean | string;
@@ -84,3 +86,5 @@ export interface IJitsiParticipant {
getSources: () => Map<string, Map<string, ISourceInfo>>;
isHidden: () => boolean;
}
export type ParticipantFeaturesKey = keyof IParticipantFeatures;

View File

@@ -1,49 +1,3 @@
// Default color palette
export const colors = {
error03: '#7A141F',
error04: '#A21B29',
error05: '#CB2233',
error06: '#D83848',
error08: '#F24D5F',
primary01: '#00112D',
primary02: '#00225A',
primary03: '#003486',
primary04: '#0045B3',
primary05: '#0056E0',
primary06: '#246FE5',
primary07: '#4687ED',
primary08: '#99BBF3',
primary09: '#CCDDF9',
surface01: '#040404',
surface02: '#141414',
surface03: '#292929',
surface04: '#3D3D3D',
surface05: '#525252',
surface06: '#666',
surface07: '#858585',
surface08: '#A3A3A3',
surface09: '#C2C2C2',
surface10: '#E0E0E0',
surface11: '#FFF',
success04: '#189B55',
success05: '#1EC26A',
warning05: '#F8AE1A',
warning06: '#FFD600',
support01: '#FF9B42',
support02: '#F96E57',
support03: '#DF486F',
support04: '#B23683',
support05: '#73348C',
support06: '#6A50D3',
support07: '#4380E2',
support08: '#00A8B3',
support09: '#2AA076'
};
// Mapping between the token used and the color
export const colorMap = {
@@ -57,108 +11,110 @@ export const colorMap = {
// Container backgrounds
ui01: 'surface02',
ui02: 'surface03',
ui03: 'surface04',
ui03: 'ui02',
ui04: 'surface05',
ui05: 'surface06',
ui06: 'surface07',
ui05: 'ui01',
ui06: 'ui03',
ui07: 'surface08',
ui08: 'surface09',
ui09: 'surface10',
ui10: 'surface11',
ui08: 'ui21',
ui09: 'ui08',
ui10: 'ui04',
// ----- Actions -----
// Primary
action01: 'primary06',
action01Hover: 'primary07',
action01Active: 'primary04',
action01: 'action01',
action01Hover: 'hover01',
action01Active: 'active01',
// Secondary
action02: 'surface10',
action02Hover: 'surface11',
action02Active: 'surface09',
action02: 'action02',
action02Hover: 'hover02',
action02Active: 'active02',
// Destructive
actionDanger: 'error05',
actionDangerHover: 'error06',
actionDangerActive: 'error04',
actionDanger: 'action03',
actionDangerHover: 'hover03',
actionDangerActive: 'active03',
// Tertiary
action03: 'transparent',
action03Hover: 'surface04',
action03Hover: 'hover05',
action03Active: 'surface03',
// Disabled
disabled01: 'surface09',
disabled01: 'disabled01',
// Focus
focus01: 'primary07',
focus01: 'focus01',
// ----- Links -----
link01: 'primary07',
link01Hover: 'primary08',
link01Active: 'primary06',
link01: 'action01',
link01Hover: 'hover07',
link01Active: 'action04',
// ----- Text -----
// Primary
text01: 'surface11',
text01: 'textColor01',
// Secondary
text02: 'surface09',
text02: 'textColor02',
// Tertiary
text03: 'surface07',
text03: 'ui03',
// High-contrast
text04: 'surface01',
// Error
textError: 'error08',
textError: 'alertRed',
// ----- Icons -----
// Primary
icon01: 'surface11',
icon01: 'icon01',
// Secondary
icon02: 'surface09',
icon02: 'ui21',
// Tertiary
icon03: 'surface07',
icon03: 'icon07',
// High-contrast
icon04: 'surface01',
// Error
iconError: 'error06',
iconError: 'action03',
// Normal
iconNormal: 'action04',
// Success
iconSuccess: 'alertGreen',
// Warning
iconWarning: 'warning01',
// ----- Forms -----
field01: 'surface04',
field01: 'ui02',
// ----- Feedback -----
// Success
success01: 'success05',
success02: 'success04',
success02: 'success01',
// Warning
warning01: 'warning05',
warning01: 'warning01',
warning02: 'warning06',
// ----- Support -----
support01: 'support01',
support02: 'support02',
support03: 'support03',
support04: 'support04',
support05: 'support05',
support06: 'support06',
support07: 'support07',
support08: 'support08',
support09: 'support09'
support06: 'support06'
};
@@ -177,19 +133,9 @@ export const spacing
= [ 0, 4, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 128 ];
export const typography = {
labelRegular: {
fontSize: 12,
lineHeight: 16,
fontWeight: font.weightRegular,
letterSpacing: 0.16
},
labelRegular: 'label01',
labelBold: {
fontSize: 12,
lineHeight: 16,
fontWeight: font.weightSemiBold,
letterSpacing: 0.16
},
labelBold: 'labelBold01',
bodyShortRegularSmall: {
fontSize: 10,
@@ -254,19 +200,9 @@ export const typography = {
letterSpacing: 0
},
heading1: {
fontSize: 54,
lineHeight: 64,
fontWeight: font.weightSemiBold,
letterSpacing: 0
},
heading1: 'heading01',
heading2: {
fontSize: 42,
lineHeight: 50,
fontWeight: font.weightSemiBold,
letterSpacing: 0
},
heading2: 'heading02',
heading3: {
fontSize: 32,

View File

@@ -1,11 +1,10 @@
import { colorMap, colors, font, shape, spacing, typography } from '../Tokens';
import { colorMap, font, shape, spacing, typography } from '../Tokens';
import { createNativeTheme } from '../functions.native';
import updateTheme from './updateTheme.native';
export default createNativeTheme(updateTheme({
font,
colors,
colorMap,
spacing,
shape,

View File

@@ -1,9 +1,8 @@
import { breakpoints, colorMap, colors, font, shape, spacing, typography } from '../Tokens';
import { breakpoints, colorMap, font, shape, spacing, typography } from '../Tokens';
import { createWebTheme } from '../functions.web';
export default createWebTheme({
font,
colors,
colorMap,
spacing,
shape,

View File

@@ -8,10 +8,10 @@ import { createColorTokens } from './utils';
* @param {Object} arg - The ui tokens.
* @returns {Object}
*/
export function createNativeTheme({ font, colors, colorMap, shape, spacing, typography }: any): any {
export function createNativeTheme({ font, colorMap, shape, spacing, typography }: any): any {
return {
...DefaultTheme,
palette: createColorTokens(colorMap, colors),
palette: createColorTokens(colorMap),
shape,
spacing,
typography: {

View File

@@ -16,7 +16,6 @@ declare module '@mui/material/styles' {
interface ThemeProps {
breakpoints: Object;
colorMap: Object;
colors: Object;
font: Object;
shape: Object;
spacing: Array<number>;
@@ -29,10 +28,10 @@ interface ThemeProps {
* @param {Object} arg - The ui tokens.
* @returns {Object}
*/
export function createWebTheme({ font, colors, colorMap, shape, spacing, typography, breakpoints }: ThemeProps) {
export function createWebTheme({ font, colorMap, shape, spacing, typography, breakpoints }: ThemeProps) {
return createTheme(adaptV4Theme({
spacing,
palette: createColorTokens(colorMap, colors),
palette: createColorTokens(colorMap),
shape,
typography: {
// @ts-ignore

View File

@@ -0,0 +1,14 @@
{
"success05": "#1EC26A",
"support05": "#73348C",
"support06": "#6A50D3",
"surface01": "#040404",
"surface02": "#141414",
"surface03": "#292929",
"surface05": "#525252",
"surface08": "#A3A3A3",
"warning06": "#FFD600"
}

View File

@@ -0,0 +1,211 @@
{
"action01": "#4687ED",
"action02": "#E0E0E0",
"action03": "#D83848",
"action04": "#246FE5",
"action05": "#4687ED",
"action06": "#0056E0",
"action07": "#D7E3F9",
"action08": "#99BBF3",
"action09": "#4687ED",
"active01": "#0056E0",
"active02": "#C2C2C2",
"active03": "#CB2233",
"active04": "#189B55",
"active05": "#666666",
"active07": "#0056E0",
"active08": "#525252",
"active09": "#3D3D3D",
"active10": "#3D3D3D",
"active11": "#CCDDF9",
"active12": "#666666",
"alertGreen": "#189B55",
"alertRed": "#F24D5F",
"alertYellow": "#F8AE1A",
"body01": {
"fontFamily": "Inter, sans-serif",
"fontSize": "0.875rem",
"lineHeight": "1.25rem",
"fontWeight": 400,
"letterSpacing": "-0.006rem"
},
"body02": {
"fontFamily": "Inter, sans-serif",
"fontSize": "1rem",
"lineHeight": "1.5rem",
"fontWeight": 400,
"letterSpacing": "-0.011rem"
},
"bodyBold01": {
"fontFamily": "Inter, sans-serif",
"fontSize": "0.875rem",
"lineHeight": "1.25rem",
"fontWeight": 600,
"letterSpacing": "-0.006rem"
},
"bodyBold02": {
"fontFamily": "Inter, sans-serif",
"fontSize": "1rem",
"lineHeight": "1.5rem",
"fontWeight": 600,
"letterSpacing": "-0.011rem"
},
"brand01": "#FFFFFF",
"bulletList01": {
"fontFamily": "Inter, sans-serif",
"fontSize": "0.875rem",
"lineHeight": "1.5rem",
"fontWeight": 400,
"letterSpacing": "-0.006rem"
},
"data01": "#C15C97",
"data02": "#4079D3",
"data03": "#A276B2",
"data04": "#4CAC9C",
"data05": "#E76782",
"data06": "#8CA7D1",
"data07": "#B23683",
"data08": "#FFA95E",
"data09": "#8B559F",
"data10": "#009B89",
"data11": "#858585",
"dataText01": "#292929",
"dataText02": "#292929",
"dataText03": "#292929",
"dataText04": "#000000",
"dataText05": "#000000",
"dataText06": "#000000",
"dataText07": "#FFFFFF",
"dataText08": "#000000",
"dataText09": "#FFFFFF",
"dataText10": "#FFFFFF",
"dataText11": "#000000",
"disabled01": "#C2C2C2",
"disabled02": "#666666",
"disabled03": "#C2C2C2",
"disabled04": "#858585",
"error01": "#F24D5F",
"focus01": "#D7E3F9",
"heading01": {
"fontFamily": "Inter, sans-serif",
"fontSize": "1.25rem",
"lineHeight": "1.75rem",
"fontWeight": 600,
"letterSpacing": "-0.017rem"
},
"heading02": {
"fontFamily": "Inter, sans-serif",
"fontSize": "1.75rem",
"lineHeight": "2.5rem",
"fontWeight": 600,
"letterSpacing": "-0.020rem"
},
"highlight01": "#F8AE1A",
"hover01": "#4687ED",
"hover02": "#F1F1F1",
"hover03": "#F24D5F",
"hover04": "#4BCE88",
"hover05": "#3D3D3D",
"hover06": "#666666",
"hover07": "#99BBF3",
"hover08": "#2F2E32",
"hover09": "#666666",
"hover10": "#292929",
"hover11": "#99BBF3",
"hover12": "#3D3D3D",
"hover13": "#525252",
"icon01": "#FFFFFF",
"icon02": "#FFFFFF",
"icon03": "#666666",
"icon04": "#0056E0",
"icon05": "#292929",
"icon06": "#666666",
"icon07": "#858585",
"icon08": "#292929",
"info01": "#666666",
"label01": {
"fontFamily": "Inter, sans-serif",
"fontSize": "0.75rem",
"lineHeight": "1rem",
"fontWeight": 400,
"letterSpacing": "normal"
},
"labelBold01": {
"fontFamily": "Inter, sans-serif",
"fontSize": "0.75rem",
"lineHeight": "1rem",
"fontWeight": 600,
"letterSpacing": "normal"
},
"overlay01": "#292929BF",
"shadow01": "#141414",
"shadowHigh": "0px 2px 20px 9px #141414",
"shadowLow": "0px 1px 2px 1px #141414",
"shadowMedium": "0px 2px 8px 2px #141414",
"statusAvailable01": "#189B55",
"statusAway01": "#DD7011",
"statusBusy01": "#F24D5F",
"statusOffline01": "#666666",
"statusWrapup01": "#8B559F",
"success01": "#189B55",
"textColor01": "#FFFFFF",
"textColor02": "#C2C2C2",
"textColor04": "#292929",
"textColor05": "#C2C2C2",
"textColor06": "#FFFFFF",
"textColor07": "#292929",
"textColor08": "#FFFFFF",
"textColor09": "#000000",
"textColor10": "#E7E3FF",
"ui01": "#666666",
"ui02": "#3D3D3D",
"ui03": "#858585",
"ui04": "#FFFFFF",
"ui05": "#2F2E32",
"ui06": "#171719",
"ui07": "#F1F1F1",
"ui08": "#E0E0E0",
"ui09": "#CCDDF9",
"ui10": "#666666",
"ui11": "#0C0C0D",
"ui12": "#212124",
"ui13": "#003486",
"ui14": "#127440",
"ui15": "#00225A",
"ui16": "#F5D3D6",
"ui17": "#FEEFD1",
"ui18": "#D2F3E1",
"ui19": "#E0E0E0",
"ui20": "#E8DCEC",
"ui21": "#C2C2C2",
"ui22": "#CCDDF9",
"ui23": "#3C2F8E",
"ui24": "#5F50BE",
"ui25": "#171719",
"warning01": "#F8AE1A",
"warning02": "#F8AE1A",
"warning03": "#9F701C"
}

View File

@@ -1,13 +1,21 @@
import { merge } from 'lodash';
import * as jitsiTokens from './jitsiTokens.json';
import * as tokens from './tokens.json';
/**
* Creates the color tokens based on the color theme and the association map.
* If a key is not found in the association map it defaults to the current value.
*
* @param {Object} colorMap - A map between the token name and the actual color value.
* @param {Object} colors - An object containing all the theme colors.
* @returns {Object}
*/
export function createColorTokens(colorMap: Object, colors: Object): any {
export function createColorTokens(colorMap: Object): any {
const allTokens = merge({}, tokens, jitsiTokens);
return Object.entries(colorMap)
.reduce((result, [ token, value ]: [any, keyof Object]) =>
Object.assign(result, { [token]: colors[value] || value }), {});
.reduce((result, [ token, value ]: [any, string]) => {
const color = allTokens[value as keyof typeof allTokens];
return Object.assign(result, { [token]: color });
}, {});
}

View File

@@ -8,7 +8,7 @@ import { translate } from '../../../base/i18n/functions';
import { IconFaceSmile, IconSend } from '../../../base/icons/svg';
import Button from '../../../base/ui/components/web/Button';
import Input from '../../../base/ui/components/web/Input';
import { areSmileysDisabled } from '../../functions';
import { areSmileysDisabled, isSendGroupChatDisabled } from '../../functions';
import SmileysPanel from './SmileysPanel';
@@ -22,6 +22,8 @@ interface IProps extends WithTranslation {
*/
_areSmileysDisabled: boolean;
_isSendGroupChatDisabled: boolean;
/**
* The id of the message recipient, if any.
*/
@@ -145,7 +147,8 @@ class ChatInput extends Component<IProps, IState> {
value = { this.state.message } />
<Button
accessibilityLabel = { this.props.t('chat.sendButton') }
disabled = { !this.state.message.trim() }
disabled = { !this.state.message.trim()
|| (this.props._isSendGroupChatDisabled && !this.props._privateMessageRecipientId) }
icon = { IconSend }
onClick = { this._onSubmitMessage }
size = { isMobileBrowser() ? 'large' : 'medium' } />
@@ -170,10 +173,20 @@ class ChatInput extends Component<IProps, IState> {
* @returns {void}
*/
_onSubmitMessage() {
const {
_isSendGroupChatDisabled,
_privateMessageRecipientId,
onSend
} = this.props;
if (_isSendGroupChatDisabled && !_privateMessageRecipientId) {
return;
}
const trimmed = this.state.message.trim();
if (trimmed) {
this.props.onSend(trimmed);
onSend(trimmed);
this.setState({ message: '' });
@@ -276,10 +289,12 @@ class ChatInput extends Component<IProps, IState> {
*/
const mapStateToProps = (state: IReduxState) => {
const { privateMessageRecipient } = state['features/chat'];
const isGroupChatDisabled = isSendGroupChatDisabled(state);
return {
_areSmileysDisabled: areSmileysDisabled(state),
_privateMessageRecipientId: privateMessageRecipient?.id
_privateMessageRecipientId: privateMessageRecipient?.id,
_isSendGroupChatDisabled: isGroupChatDisabled
};
};

View File

@@ -381,7 +381,7 @@ const ChatMessage = ({
</div>
{shouldDisplayChatMessageMenu && (
<div className = { classes.sideBySideContainer }>
{!message.privateMessage && <div>
{!message.privateMessage && !message.lobbyChat && <div>
<div className = { classes.optionsButtonContainer }>
{isHovered && <ReactButton
messageId = { message.messageId }

View File

@@ -7,6 +7,7 @@ import emojiAsciiAliases from 'react-emoji-render/data/asciiAliases';
import { IReduxState } from '../app/types';
import { getLocalizedDateFormatter } from '../base/i18n/dateUtil';
import i18next from '../base/i18n/i18next';
import { isJwtFeatureEnabled } from '../base/jwt/functions';
import { getParticipantById } from '../base/participants/functions';
import { escapeRegexp } from '../base/util/helpers';
@@ -70,7 +71,7 @@ const SLACK_EMOJI_REGEXP_ARRAY: Array<[RegExp, string]> = [];
* @param {string} message - The message to parse and replace.
* @returns {string}
*/
export function replaceNonUnicodeEmojis(message: string) {
export function replaceNonUnicodeEmojis(message: string): string {
let replacedMessage = message;
for (const [ regexp, replaceValue ] of SLACK_EMOJI_REGEXP_ARRAY) {
@@ -99,7 +100,7 @@ export function getUnreadCount(state: IReduxState) {
}
let reactionMessages = 0;
let lastReadIndex;
let lastReadIndex: number;
if (navigator.product === 'ReactNative') {
// React native stores the messages in a reversed order.
@@ -190,3 +191,20 @@ export function getPrivateNoticeMessage(message: IMessage) {
recipient: message.messageType === MESSAGE_TYPE_LOCAL ? message.recipient : i18next.t('chat.you')
});
}
/**
* Check if participant is not allowed to send group messages.
*
* @param {IReduxState} state - The redux state.
* @returns {boolean} - Returns true if the participant is not allowed to send group messages.
*/
export function isSendGroupChatDisabled(state: IReduxState) {
const { groupChatRequiresPermission } = state['features/dynamic-branding'];
if (!groupChatRequiresPermission) {
return false;
}
return !isJwtFeatureEnabled(state, 'send-groupchat', false, false);
}

View File

@@ -42,7 +42,7 @@ import {
SEND_REACTION,
SET_IS_POLL_TAB_FOCUSED
} from './actionTypes';
import { addMessage, addMessageReaction, clearMessages, closeChat } from './actions.any';
import { addMessage, addMessageReaction, clearMessages, closeChat, setPrivateMessageRecipient } from './actions.any';
import { ChatPrivacyDialog } from './components';
import {
INCOMING_MSG_SOUND_ID,
@@ -52,7 +52,7 @@ import {
MESSAGE_TYPE_REMOTE,
MESSAGE_TYPE_SYSTEM
} from './constants';
import { getUnreadCount } from './functions';
import { getUnreadCount, isSendGroupChatDisabled } from './functions';
import { INCOMING_MSG_SOUND_FILE } from './sounds';
/**
@@ -161,13 +161,29 @@ MiddlewareRegistry.register(store => next => action => {
break;
}
case OPEN_CHAT:
case OPEN_CHAT: {
unreadCount = 0;
if (typeof APP !== 'undefined') {
APP.API.notifyChatUpdated(unreadCount, true);
}
const { privateMessageRecipient } = store.getState()['features/chat'];
if (
isSendGroupChatDisabled(store.getState())
&& privateMessageRecipient
&& !action.participant
) {
const participant = getParticipantById(store.getState(), privateMessageRecipient.id);
if (participant) {
action.participant = participant;
}
}
break;
}
case SET_IS_POLL_TAB_FOCUSED: {
dispatch(resetNbUnreadPollsMessages());
@@ -307,6 +323,12 @@ function _addChatMsgListener(conference: IJitsiConference, store: IStore) {
isGuest,
messageId,
privateMessage: false });
if (isSendGroupChatDisabled(store.getState()) && participantId) {
const participant = getParticipantById(store, participantId);
store.dispatch(setPrivateMessageRecipient(participant));
}
}
);

View File

@@ -1,7 +1,7 @@
import { Theme } from '@mui/material';
import { adaptV4Theme, createTheme } from '@mui/material/styles';
import { breakpoints, colorMap, colors, font, shape, spacing, typography } from '../base/ui/Tokens';
import { breakpoints, colorMap, font, shape, spacing, typography } from '../base/ui/Tokens';
import { createColorTokens } from '../base/ui/utils';
/**
@@ -19,7 +19,7 @@ export function createMuiBrandingTheme(customTheme: Theme) {
spacing: customSpacing
} = customTheme;
const newPalette = createColorTokens(colorMap, colors);
const newPalette = createColorTokens(colorMap);
if (customPalette) {
overwriteRecurrsive(newPalette, customPalette);

View File

@@ -76,6 +76,15 @@ const DEFAULT_STATE = {
*/
didPageUrl: '',
/**
* Whether participant can only send group chat message if `send-groupchat`
* feature is enabled in jwt.
*
* @public
* @type {boolean}
*/
groupChatRequiresPermission: false,
/**
* The custom invite domain.
*
@@ -117,6 +126,14 @@ const DEFAULT_STATE = {
*/
muiBrandedTheme: undefined,
/**
* Whether participant can only create polls if `create-polls` feature is enabled in jwt.
*
* @public
* @type {boolean}
*/
pollCreationRequiresPermission: false,
/**
* The lobby/prejoin background.
*
@@ -152,11 +169,13 @@ export interface IDynamicBrandingState {
defaultBranding: boolean;
defaultTranscriptionLanguage?: boolean;
didPageUrl: string;
groupChatRequiresPermission: boolean;
inviteDomain: string;
labels: Object | null;
logoClickUrl: string;
logoImageUrl: string;
muiBrandedTheme?: boolean;
pollCreationRequiresPermission: boolean;
premeetingBackground: string;
requireRecordingConsent?: boolean;
sharedVideoAllowedURLDomains?: Array<string>;
@@ -179,11 +198,13 @@ ReducerRegistry.register<IDynamicBrandingState>(STORE_NAME, (state = DEFAULT_STA
brandedIcons,
defaultBranding,
didPageUrl,
groupChatRequiresPermission,
inviteDomain,
labels,
logoClickUrl,
logoImageUrl,
muiBrandedTheme,
pollCreationRequiresPermission,
premeetingBackground,
sharedVideoAllowedURLDomains,
showGiphyIntegration,
@@ -199,11 +220,13 @@ ReducerRegistry.register<IDynamicBrandingState>(STORE_NAME, (state = DEFAULT_STA
brandedIcons,
defaultBranding,
didPageUrl,
groupChatRequiresPermission,
inviteDomain,
labels,
logoClickUrl,
logoImageUrl,
muiBrandedTheme,
pollCreationRequiresPermission,
premeetingBackground,
sharedVideoAllowedURLDomains,
showGiphyIntegration,

View File

@@ -1,5 +1,4 @@
import 'image-capture';
import './createImageBitmap';
import { IStore } from '../app/types';
import { isMobileBrowser } from '../base/environment/utils';
import { getLocalVideoTrack } from '../base/tracks/functions';

View File

@@ -1,5 +1,4 @@
import 'image-capture';
import './createImageBitmap';
import { AnyAction } from 'redux';
import {

View File

@@ -1,31 +0,0 @@
/*
* Safari < 15 polyfill for createImageBitmap
* https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/createImageBitmap
*
* Support source image types: Canvas.
*/
// @ts-nocheck
if (!('createImageBitmap' in window)) {
window.createImageBitmap = async function(data) {
return new Promise((resolve, reject) => {
let dataURL;
if (data instanceof HTMLCanvasElement) {
dataURL = data.toDataURL();
} else {
reject(new Error('createImageBitmap does not handle the provided image source type'));
}
const img = document.createElement('img');
img.close = () => {
// empty
};
img.addEventListener('load', () => {
resolve(img);
});
img.src = dataURL;
});
};
}

View File

@@ -1,5 +1,6 @@
import { IStore } from '../app/types';
import { openDialog } from '../base/dialog/actions';
import { ParticipantFeaturesKey } from '../base/participants/types';
import PremiumFeatureDialog from './components/web/PremiumFeatureDialog';
import { isFeatureDisabled } from './functions';
@@ -7,11 +8,11 @@ import { isFeatureDisabled } from './functions';
/**
* Shows a dialog prompting users to upgrade, if requested feature is disabled.
*
* @param {string} feature - The feature to check availability for.
* @param {ParticipantFeaturesKey} feature - The feature to check availability for.
*
* @returns {Function}
*/
export function maybeShowPremiumFeatureDialog(feature: string) {
export function maybeShowPremiumFeatureDialog(feature: ParticipantFeaturesKey) {
return function(dispatch: IStore['dispatch'], getState: IStore['getState']) {
if (isFeatureDisabled(getState(), feature)) {
dispatch(openDialog(PremiumFeatureDialog));

View File

@@ -1,5 +1,6 @@
import { IReduxState } from '../app/types';
import { IJitsiConference } from '../base/conference/reducer';
import { ParticipantFeaturesKey } from '../base/participants/types';
import { VPAAS_TENANT_PREFIX } from './constants';
import logger from './logger';
@@ -105,10 +106,10 @@ export async function sendGetDetailsRequest({ appId, baseUrl }: {
* Returns the billing id for vpaas meetings.
*
* @param {IReduxState} state - The state of the app.
* @param {string} feature - Feature to be looked up for disable state.
* @param {ParticipantFeaturesKey} feature - Feature to be looked up for disable state.
* @returns {boolean}
*/
export function isFeatureDisabled(state: IReduxState, feature: string) {
export function isFeatureDisabled(state: IReduxState, feature: ParticipantFeaturesKey) {
return state['features/jaas'].disabledFeatures.includes(feature);
}

View File

@@ -176,7 +176,6 @@ class AudioRoutePickerDialog extends Component<IProps, IState> {
// Skip devices with unknown type.
if (!infoMap) {
// eslint-disable-next-line no-continue
continue;
}

View File

@@ -9,7 +9,6 @@ import {
IconUsers,
IconWarning
} from '../../../base/icons/svg';
import { colors } from '../../../base/ui/Tokens';
import BaseTheme from '../../../base/ui/components/BaseTheme.native';
import Button from '../../../base/ui/components/native/Button';
import IconButton from '../../../base/ui/components/native/IconButton';
@@ -30,10 +29,10 @@ import styles from './styles';
*/
const ICON_COLOR = {
error: colors.error06,
normal: colors.primary06,
success: colors.success05,
warning: colors.warning05
error: BaseTheme.palette.iconError,
normal: BaseTheme.palette.iconNormal,
success: BaseTheme.palette.iconSuccess,
warning: BaseTheme.palette.iconWarning
};

View File

@@ -1,5 +1,8 @@
import React, { ComponentType, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useSelector } from 'react-redux';
import { isCreatePollDisabled } from '../functions';
/*
* Props that will be passed by the AbstractPollsPane to its
@@ -7,6 +10,7 @@ import { useTranslation } from 'react-i18next';
**/
export type AbstractProps = {
createMode: boolean;
isCreatePollsDisabled: boolean;
onCreate: () => void;
setCreateMode: (mode: boolean) => void;
t: Function;
@@ -21,6 +25,7 @@ export type AbstractProps = {
*/
const AbstractPollsPane = (Component: ComponentType<AbstractProps>) => () => {
const isCreatePollsDisabled = useSelector(isCreatePollDisabled);
const [ createMode, setCreateMode ] = useState(false);
const onCreate = () => {
@@ -31,6 +36,7 @@ const AbstractPollsPane = (Component: ComponentType<AbstractProps>) => () => {
return (<Component
createMode = { createMode }
isCreatePollsDisabled = { isCreatePollsDisabled }
/* eslint-disable react/jsx-no-bind */
onCreate = { onCreate }
setCreateMode = { setCreateMode }

View File

@@ -28,7 +28,7 @@ const useStyles = makeStyles()(() => {
};
});
const PollsPane = ({ createMode, onCreate, setCreateMode, t }: AbstractProps) => {
const PollsPane = ({ createMode, isCreatePollsDisabled, onCreate, setCreateMode, t }: AbstractProps) => {
const { classes } = useStyles();
return createMode
@@ -40,6 +40,7 @@ const PollsPane = ({ createMode, onCreate, setCreateMode, t }: AbstractProps) =>
<div className = { classes.footer }>
<Button
accessibilityLabel = { t('polls.create.create') }
disabled = { isCreatePollsDisabled }
fullWidth = { true }
labelKey = { 'polls.create.create' }
onClick = { onCreate } />

View File

@@ -1,4 +1,5 @@
import { IReduxState } from '../app/types';
import { isJwtFeatureEnabled } from '../base/jwt/functions';
import { IAnswerData } from './types';
@@ -62,3 +63,19 @@ export function hasIdenticalAnswers(currentAnswers: Array<IAnswerData>): boolean
return currentAnswersSet.size !== nonEmptyCurrentAnswers.length;
}
/**
* Check if participant is not allowed to create polls.
*
* @param {IReduxState} state - The redux state.
* @returns {boolean} - Returns true if the participant is not allowed to create polls.
*/
export function isCreatePollDisabled(state: IReduxState) {
const { pollCreationRequiresPermission } = state['features/dynamic-branding'];
if (!pollCreationRequiresPermission) {
return false;
}
return !isJwtFeatureEnabled(state, 'create-polls', false, false);
}

View File

@@ -438,7 +438,11 @@ const Prejoin = ({
{showErrorOnField && <div
className = { classes.error }
data-testid = 'prejoin.errorMessage'>{t('prejoin.errorMissingName')}</div>}
data-testid = 'prejoin.errorMessage'>
<p aria-live = 'polite' >
{t('prejoin.errorMissingName')}
</p>
</div>}
<div className = { classes.dropdownContainer }>
<Popover

View File

@@ -448,6 +448,11 @@ export function isLiveStreamingButtonVisible({
export function shouldRequireRecordingConsent(recorderSession: any, state: IReduxState) {
const { requireRecordingConsent } = state['features/dynamic-branding'] || {};
const { requireConsent } = state['features/base/config'].recordings || {};
const { iAmRecorder } = state['features/base/config'];
if (iAmRecorder) {
return false;
}
if (!requireConsent && !requireRecordingConsent) {
return false;

View File

@@ -1,5 +1,4 @@
import 'image-capture';
import './createImageBitmap';
import { createScreensharingCaptureTakenEvent } from '../analytics/AnalyticsEvents';
import { sendAnalytics } from '../analytics/functions';

View File

@@ -1,25 +0,0 @@
/*
* Safari polyfill for createImageBitmap
* https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/createImageBitmap
*
* Support source image types: Canvas.
*/
if (!('createImageBitmap' in window)) {
window.createImageBitmap = async function(data) {
return new Promise((resolve, reject) => {
let dataURL;
if (data instanceof HTMLCanvasElement) {
dataURL = data.toDataURL();
} else {
reject(new Error('createImageBitmap does not handle the provided image source type'));
}
const img = document.createElement('img');
img.addEventListener('load', () => {
resolve(img);
});
img.src = dataURL;
});
};
}

View File

@@ -6,5 +6,5 @@
* @returns {Promise<void>}
*/
export async function processScreenshot(imageBlob, options) { // eslint-disable-line no-unused-vars
return;
return await Promise.resolve();
}

View File

@@ -190,14 +190,14 @@ class NotificationsTab extends AbstractDialogTab<IProps, any> {
const classes = withStyles.getClasses(this.props);
return (
<div
<form
className = { classes.container }
key = 'sounds'>
{showSoundsSettings && (
<div className = { classes.column }>
<h2 className = { classes.title }>
<fieldset className = { classes.column }>
<legend className = { classes.title }>
{t('settings.playSounds')}
</h2>
</legend>
{enableReactions && <Checkbox
checked = { soundsReactions && !disabledSounds.includes('REACTION_SOUND') }
className = { classes.checkbox }
@@ -244,13 +244,13 @@ class NotificationsTab extends AbstractDialogTab<IProps, any> {
label = { t('settings.participantKnocking') }
name = 'soundsParticipantKnocking'
onChange = { this._onChange } />
</div>
</fieldset>
)}
{showNotificationsSettings && (
<div className = { classes.column }>
<h2 className = { classes.title }>
<fieldset className = { classes.column }>
<legend className = { classes.title }>
{t('notify.displayNotifications')}
</h2>
</legend>
{
Object.keys(enabledNotifications).map(key => (
<Checkbox
@@ -264,9 +264,9 @@ class NotificationsTab extends AbstractDialogTab<IProps, any> {
onChange = { e => this._onEnabledNotificationsChanged(e, key) } />
))
}
</div>
</fieldset>
)}
</div>
</form>
);
}
}

View File

@@ -56,7 +56,6 @@ const checkToolboxOverlap = (clientHeight: number, store: IStore) => {
const indicatorsRect = tile?.querySelector('.bottom-indicators')?.getBoundingClientRect();
if (!indicatorsRect) {
// eslint-disable-next-line no-continue
continue;
}

View File

@@ -382,21 +382,27 @@ class WelcomePage extends AbstractWelcomePage<IProps> {
<div className = 'welcome-footer-row-1-text'>{t('welcomepage.jitsiOnMobile')}</div>
<a
className = 'welcome-badge'
href = { iosDownloadLink }>
href = { iosDownloadLink }
rel = 'noopener noreferrer'
target = '_blank'>
<img
alt = { t('welcomepage.mobileDownLoadLinkIos') }
src = './images/app-store-badge.png' />
</a>
<a
className = 'welcome-badge'
href = { androidDownloadLink }>
href = { androidDownloadLink }
rel = 'noopener noreferrer'
target = '_blank'>
<img
alt = { t('welcomepage.mobileDownLoadLinkAndroid') }
src = './images/google-play-badge.png' />
</a>
<a
className = 'welcome-badge'
href = { fDroidUrl }>
href = { fDroidUrl }
rel = 'noopener noreferrer'
target = '_blank'>
<img
alt = { t('welcomepage.mobileDownLoadLinkFDroid') }
src = './images/f-droid-badge.png' />

View File

@@ -5,6 +5,7 @@ local jid = require "util.jid";
local token_util = module:require "token/util".new(module);
local util = module:require 'util';
local is_admin = util.is_admin;
local room_jid_match_rewrite = util.room_jid_match_rewrite;
local is_feature_allowed = util.is_feature_allowed;
local is_sip_jigasi = util.is_sip_jigasi;
@@ -38,11 +39,6 @@ local is_visitor_prosody = main_domain ~= nil;
-- this is the main virtual host of this vnode
local local_domain = module:get_option_string('muc_mapper_domain_base');
local um_is_admin = require 'core.usermanager'.is_admin;
local function is_admin(jid)
return um_is_admin(jid, module.host);
end
-- The maximum number of simultaneous calls,
-- and also the maximum number of new calls per minute that a session is allowed to create.
local limit_outgoing_calls;

View File

@@ -18,6 +18,7 @@ local array = require 'util.array';
local set = require 'util.set';
local util = module:require 'util';
local is_admin = util.is_admin;
local ends_with = util.ends_with;
local is_vpaas = util.is_vpaas;
local room_jid_match_rewrite = util.room_jid_match_rewrite;
@@ -63,11 +64,6 @@ local sent_iq_cache = require 'util.cache'.new(200);
local sessions = prosody.full_sessions;
local um_is_admin = require 'core.usermanager'.is_admin;
local function is_admin(jid)
return um_is_admin(jid, module.host);
end
local function send_transcriptions_update(room)
-- let's notify main prosody
local lang_array = array();

View File

@@ -3,8 +3,8 @@ local jid = require "util.jid";
local jid_bare = require "util.jid".bare;
local jid_host = require "util.jid".host;
local st = require "util.stanza";
local um_is_admin = require "core.usermanager".is_admin;
local util = module:require "util";
local is_admin = util.is_admin;
local is_healthcheck_room = util.is_healthcheck_room;
local is_moderated = util.is_moderated;
local get_room_from_jid = util.get_room_from_jid;
@@ -18,10 +18,6 @@ local function load_config()
end
load_config();
local function is_admin(_jid)
return um_is_admin(_jid, module.host);
end
-- List of the bare_jids of all occupants that are currently joining (went through pre-join) and will be promoted
-- as moderators. As pre-join (where added) and joined event (where removed) happen one after another this list should
-- have length of 1

View File

@@ -4,9 +4,9 @@
-- Copyright (C) 2023-present 8x8, Inc.
local oss_util = module:require "util";
local is_admin = oss_util.is_admin;
local is_healthcheck_room = oss_util.is_healthcheck_room;
local process_host_module = oss_util.process_host_module;
local um_is_admin = require "core.usermanager".is_admin;
local inspect = require('inspect');
local jid_bare = require "util.jid".bare;
local jid = require "util.jid";
@@ -21,10 +21,6 @@ if lobby_muc_component_config == nil then
return ;
end
local function is_admin(occupant_jid)
return um_is_admin(occupant_jid, module.host);
end
local function remove_flip_tag(stanza)
stanza:maptags(function(tag)
if tag and tag.name == "flip_device" then

View File

@@ -3,17 +3,13 @@ local json = require 'cjson.safe';
local queue = require "util.queue";
local uuid_gen = require "util.uuid".generate;
local main_util = module:require "util";
local is_admin = main_util.is_admin;
local ends_with = main_util.ends_with;
local get_room_from_jid = main_util.get_room_from_jid;
local is_healthcheck_room = main_util.is_healthcheck_room;
local internal_room_jid_match_rewrite = main_util.internal_room_jid_match_rewrite;
local presence_check_status = main_util.presence_check_status;
local um_is_admin = require 'core.usermanager'.is_admin;
local function is_admin(jid)
return um_is_admin(jid, module.host);
end
local QUEUE_MAX_SIZE = 500;
-- Common module for all logic that can be loaded under the conference muc component.

View File

@@ -6,9 +6,9 @@
-- the guest domain which is anonymous.
-- The module has the option to set participants to moderators when connected via token/when they are authenticated
-- This module depends on mod_persistent_lobby.
local um_is_admin = require 'core.usermanager'.is_admin;
local jid = require 'util.jid';
local util = module:require "util";
local is_admin = util.is_admin;
local is_healthcheck_room = util.is_healthcheck_room;
local is_moderated = util.is_moderated;
local process_host_module = util.process_host_module;
@@ -43,10 +43,6 @@ if not disable_auto_owners then
end, 2);
end
local function is_admin(jid)
return um_is_admin(jid, module.host);
end
-- if not authenticated user is trying to join the room we enable lobby in it
-- and wait for the moderator to join
module:hook('muc-occupant-pre-join', function (event)

View File

@@ -1,4 +1,5 @@
local util = module:require "util";
local is_admin = util.is_admin;
local get_room_from_jid = util.get_room_from_jid;
local room_jid_match_rewrite = util.room_jid_match_rewrite;
local is_jibri = util.is_jibri;
@@ -9,7 +10,6 @@ local jid_resource = require "util.jid".resource;
local st = require "util.stanza";
local socket = require "socket";
local json = require 'cjson.safe';
local um_is_admin = require "core.usermanager".is_admin;
local jid_split = require 'util.jid'.split;
-- we use async to detect Prosody 0.10 and earlier
@@ -32,10 +32,6 @@ module:log("info", "Starting speakerstats for %s", muc_component_host);
local main_muc_service;
local function is_admin(jid)
return um_is_admin(jid, module.host);
end
-- Searches all rooms in the main muc component that holds a breakout room
-- caches it if found so we don't search it again
-- we should not cache objects in _data as this is being serialized when calling room:save()

View File

@@ -4,19 +4,17 @@
local log = module._log;
local host = module.host;
local st = require "util.stanza";
local um_is_admin = require "core.usermanager".is_admin;
local jid_split = require 'util.jid'.split;
local jid_bare = require 'util.jid'.bare;
local util = module:require 'util';
local is_admin = util.is_admin;
local DEBUG = false;
local measure_success = module:measure('success', 'counter');
local measure_fail = module:measure('fail', 'counter');
local function is_admin(jid)
return um_is_admin(jid, host);
end
local parentHostName = string.gmatch(tostring(host), "%w+.(%w.+)")();
if parentHostName == nil then
module:log("error", "Failed to start - unable to get parent hostname");

View File

@@ -12,15 +12,11 @@ local st = require 'util.stanza';
local jid = require 'util.jid';
local new_id = require 'util.id'.medium;
local util = module:require 'util';
local is_admin = util.is_admin;
local presence_check_status = util.presence_check_status;
local process_host_module = util.process_host_module;
local is_transcriber_jigasi = util.is_transcriber_jigasi;
local um_is_admin = require 'core.usermanager'.is_admin;
local function is_admin(jid)
return um_is_admin(jid, module.host);
end
local MUC_NS = 'http://jabber.org/protocol/muc';
-- required parameter for custom muc component prefix, defaults to 'conference'

View File

@@ -5,6 +5,7 @@ local http = require 'net.http';
local jid = require 'util.jid';
local st = require 'util.stanza';
local util = module:require 'util';
local is_admin = util.is_admin;
local is_healthcheck_room = util.is_healthcheck_room;
local is_sip_jigasi = util.is_sip_jigasi;
local room_jid_match_rewrite = util.room_jid_match_rewrite;
@@ -18,7 +19,6 @@ local process_host_module = util.process_host_module;
local respond_iq_result = util.respond_iq_result;
local split_string = util.split_string;
local new_id = require 'util.id'.medium;
local um_is_admin = require 'core.usermanager'.is_admin;
local json = require 'cjson.safe';
local inspect = require 'inspect';
@@ -50,10 +50,6 @@ local http_headers = {
["Accept"] = "application/json"
};
local function is_admin(jid)
return um_is_admin(jid, module.host);
end
-- This is a map to keep data for room and the jids that were allowed to join after visitor mode is enabled
-- automatically allowed or allowed by a moderator
local visitors_promotion_map = {};

View File

@@ -6,6 +6,10 @@ local http = require "net.http";
local cache = require "util.cache";
local array = require "util.array";
local is_set = require 'util.set'.is_set;
local usermanager = require 'core.usermanager';
local config_global_admin_jids = module:context('*'):get_option_set('admins', {}) / jid.prep;
local config_admin_jids = module:get_option_inherited_set('admins', {}) / jid.prep;
local http_timeout = 30;
local have_async, async = pcall(require, "util.async");
@@ -626,11 +630,24 @@ function get_ip(session)
return request and request.ip or session.ip;
end
-- Checks whether the provided jid is in the list of admins
-- we are not using the new permissions and roles api as we have few global modules which need to be
-- refactored into host modules, as that api needs to be executed in host context
local function is_admin(_jid)
local bare_jid = jid.bare(_jid);
if config_global_admin_jids:contains(bare_jid) or config_admin_jids:contains(bare_jid) then
return true;
end
return false;
end
return {
OUTBOUND_SIP_JIBRI_PREFIXES = OUTBOUND_SIP_JIBRI_PREFIXES;
INBOUND_SIP_JIBRI_PREFIXES = INBOUND_SIP_JIBRI_PREFIXES;
RECORDER_PREFIXES = RECORDER_PREFIXES;
extract_subdomain = extract_subdomain;
is_admin = is_admin;
is_feature_allowed = is_feature_allowed;
is_jibri = is_jibri;
is_healthcheck_room = is_healthcheck_room;

View File

@@ -617,14 +617,24 @@ export class Participant {
// let's give it some time to leave the muc, we redirect after hangup so we should wait for the
// change of url
await this.driver.waitUntil(
async () => current !== await this.driver.getUrl(),
async () => {
const u = await this.driver.getUrl();
// trying to debug some failures of reporting not leaving, where we see the close page in screenshot
console.log(`initialUrl: ${current} currentUrl: ${u}`);
return current !== u;
},
{
timeout: 8000,
timeoutMsg: `${this.name} did not leave the muc in 8s`
timeoutMsg: `${this.name} did not leave the muc in 8s initialUrl: ${current}`
}
);
await this.driver.url('/base.html');
await this.driver.url('/base.html')
// This was fixed in wdio v9.9.1, we can drop once we update to that version
.catch(_ => {}); // eslint-disable-line @typescript-eslint/no-empty-function
}
/**

View File

@@ -31,6 +31,9 @@ describe('Lock Room', () => {
await p2PasswordDialog.waitForDialog();
await p2PasswordDialog.submitPassword(`${ctx.roomKey}1234`);
// give sometime to the password prompt to disappear and send the password
await p2.driver.pause(500);
// wait for password prompt
await p2PasswordDialog.waitForDialog();
await p2PasswordDialog.submitPassword(ctx.roomKey);
@@ -105,6 +108,9 @@ describe('Lock Room', () => {
await p2PasswordDialog.waitForDialog();
await p2PasswordDialog.submitPassword(`${ctx.roomKey}1234`);
// give sometime to the password prompt to disappear and send the password
await p2.driver.pause(500);
// wait for password prompt
await p2PasswordDialog.waitForDialog();

View File

@@ -173,7 +173,7 @@ describe('AVModeration', () => {
await unmuteByModerator(p1, p2, true, false);
// p1 mute audio on p2 and check
await p1.getParticipantsPane().muteAudio(p2);
await p1.getFilmstrip().muteAudio(p2);
await p1.getFilmstrip().assertAudioMuteIconIsDisplayed(p2);
await p2.getFilmstrip().assertAudioMuteIconIsDisplayed(p2);
@@ -213,7 +213,7 @@ describe('AVModeration', () => {
await unmuteByModerator(p1, p2, false, false);
// mute and check
await p1.getParticipantsPane().muteAudio(p2);
await p1.getFilmstrip().muteAudio(p2);
await p1.getFilmstrip().assertAudioMuteIconIsDisplayed(p2);
await p2.getFilmstrip().assertAudioMuteIconIsDisplayed(p2);

View File

@@ -479,8 +479,12 @@ async function enterLobby(participant: Participant, enterDisplayName = false, us
await screen.waitToJoinLobby();
// check no join button
expect(!await joinButton.isExisting() || !await joinButton.isDisplayed() || !await joinButton.isEnabled())
.toBe(true);
await p3.driver.waitUntil(
async () => !await joinButton.isExisting() || !await joinButton.isDisplayed() || !await joinButton.isEnabled(),
{
timeout: 2_000,
timeoutMsg: 'Join button is still available for p3'
});
// new screen, is password button shown
const passwordButton = screen.getPasswordButton();

View File

@@ -9,7 +9,16 @@ import {
describe('StartMuted', () => {
it('checkboxes test', async () => {
const options = { configOverwrite: { p2p: { enabled: true } } };
const options = {
configOverwrite: {
p2p: {
enabled: true
},
testing: {
testMode: true,
debugAudioLevels: true
}
} };
await ensureOneParticipant(ctx, options);
@@ -162,7 +171,11 @@ describe('StartMuted', () => {
const options = {
configOverwrite: {
startWithAudioMuted: true
startWithAudioMuted: true,
testing: {
testMode: true,
debugAudioLevels: true
}
}
};
@@ -191,6 +204,10 @@ describe('StartMuted', () => {
await ensureOneParticipant(ctx, options);
await joinSecondParticipant(ctx, {
configOverwrite: {
testing: {
testMode: true,
debugAudioLevels: true
},
p2p: {
enabled: true
}

View File

@@ -221,11 +221,8 @@ export const config: WebdriverIO.MultiremoteConfig = {
after() {
const { ctx }: any = global;
if (ctx?.webhooksProxy) {
ctx.webhooksProxy.disconnect();
}
ctx.keepAlive?.forEach(clearInterval);
ctx?.webhooksProxy?.disconnect();
ctx?.keepAlive?.forEach(clearInterval);
},
beforeSession(c, capabilities, specs, cid) {

View File

@@ -280,7 +280,7 @@ module.exports = (_env, argv) => {
};
return [
Object.assign({}, config, {
{ ...config,
entry: {
'app.bundle': './app.js'
},
@@ -301,10 +301,8 @@ module.exports = (_env, argv) => {
})
],
performance: getPerformanceHints(perfHintOptions, 5 * 1024 * 1024)
}),
Object.assign({}, config, {
performance: getPerformanceHints(perfHintOptions, 5 * 1024 * 1024) },
{ ...config,
entry: {
'alwaysontop': './react/features/always-on-top/index.tsx'
},
@@ -312,9 +310,8 @@ module.exports = (_env, argv) => {
...config.plugins,
...getBundleAnalyzerPlugin(analyzeBundle, 'alwaysontop')
],
performance: getPerformanceHints(perfHintOptions, 800 * 1024)
}),
Object.assign({}, config, {
performance: getPerformanceHints(perfHintOptions, 800 * 1024) },
{ ...config,
entry: {
'close3': './static/close3.js'
},
@@ -322,24 +319,21 @@ module.exports = (_env, argv) => {
...config.plugins,
...getBundleAnalyzerPlugin(analyzeBundle, 'close3')
],
performance: getPerformanceHints(perfHintOptions, 128 * 1024)
}),
performance: getPerformanceHints(perfHintOptions, 128 * 1024) },
Object.assign({}, config, {
{ ...config,
entry: {
'external_api': './modules/API/external/index.js'
},
output: Object.assign({}, config.output, {
output: { ...config.output,
library: 'JitsiMeetExternalAPI',
libraryTarget: 'umd'
}),
libraryTarget: 'umd' },
plugins: [
...config.plugins,
...getBundleAnalyzerPlugin(analyzeBundle, 'external_api')
],
performance: getPerformanceHints(perfHintOptions, 95 * 1024)
}),
Object.assign({}, config, {
performance: getPerformanceHints(perfHintOptions, 95 * 1024) },
{ ...config,
entry: {
'face-landmarks-worker': './react/features/face-landmarks/faceLandmarksWorker.ts'
},
@@ -347,10 +341,8 @@ module.exports = (_env, argv) => {
...config.plugins,
...getBundleAnalyzerPlugin(analyzeBundle, 'face-landmarks-worker')
],
performance: getPerformanceHints(perfHintOptions, 1024 * 1024 * 2)
}),
Object.assign({}, config, {
/**
performance: getPerformanceHints(perfHintOptions, 1024 * 1024 * 2) },
{ ...config, /**
* The NoiseSuppressorWorklet is loaded in an audio worklet which doesn't have the same
* context as a normal window, (e.g. self/window is not defined).
* While running a production build webpack's boilerplate code doesn't introduce any
@@ -380,10 +372,9 @@ module.exports = (_env, argv) => {
...config.output,
globalObject: 'AudioWorkletGlobalScope'
}
}),
} },
Object.assign({}, config, {
{ ...config,
entry: {
'screenshot-capture-worker': './react/features/screenshot-capture/worker.ts'
},
@@ -391,7 +382,6 @@ module.exports = (_env, argv) => {
...config.plugins,
...getBundleAnalyzerPlugin(analyzeBundle, 'screenshot-capture-worker')
],
performance: getPerformanceHints(perfHintOptions, 30 * 1024)
})
performance: getPerformanceHints(perfHintOptions, 30 * 1024) }
];
};