Compare commits

..

2 Commits

Author SHA1 Message Date
Дамян Минков
f515617140 debug: Fix lint errors. 2021-09-23 22:04:38 -05:00
Дамян Минков
b66468b8c4 debug: Do not merge, debugging raise hand. 2021-09-23 21:53:47 -05:00
1029 changed files with 23295 additions and 52363 deletions

View File

@@ -8,12 +8,8 @@ libs/*
resources/*
react/features/stream-effects/virtual-background/vendor/*
load-test/*
react/features/facial-recognition/resources/*
# ESLint will by default ignore its own configuration file. However, there does
# not seem to be a reason why we will want to risk being inconsistent with our
# remaining JavaScript source code.
!.eslintrc.js
# Not worth it.
actionTypes.js

View File

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

View File

@@ -10,12 +10,8 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: '16.x'
node-version: '12.x'
- run: npm install
- name: Check git status
run: git status
- name: Check git diff
run: git diff
- name: Check if the git repository is clean
run: exit $( git status --porcelain --untracked-files=no | head -255 | wc -l )
- run: npm run lint

2
.npmrc
View File

@@ -1,3 +1 @@
package-lock=true
; FIXME Set legacy-peer-deps=false when we upgrade RN.
legacy-peer-deps=true

1
.nvmrc
View File

@@ -1 +0,0 @@
16

View File

@@ -7,7 +7,6 @@ OLM_DIR = node_modules/@matrix-org/olm
RNNOISE_WASM_DIR = node_modules/rnnoise-wasm/dist/
TFLITE_WASM = react/features/stream-effects/virtual-background/vendor/tflite
MEET_MODELS_DIR = react/features/stream-effects/virtual-background/vendor/models/
FACIAL_MODELS_DIR = react/features/facial-recognition/resources
NODE_SASS = ./node_modules/.bin/sass
NPM = npm
OUTPUT_DIR = .
@@ -15,12 +14,12 @@ STYLES_BUNDLE = css/all.bundle.css
STYLES_DESTINATION = css/all.css
STYLES_MAIN = css/main.scss
WEBPACK = ./node_modules/.bin/webpack
WEBPACK_DEV_SERVER = ./node_modules/.bin/webpack serve --mode development
WEBPACK_DEV_SERVER = ./node_modules/.bin/webpack-dev-server
all: compile deploy clean
compile: compile-load-test
$(WEBPACK)
$(WEBPACK) -p
compile-load-test:
${NPM} install --prefix resources/load-test && ${NPM} run build --prefix resources/load-test
@@ -29,7 +28,7 @@ clean:
rm -fr $(BUILD_DIR)
.NOTPARALLEL:
deploy: deploy-init deploy-appbundle deploy-rnnoise-binary deploy-tflite deploy-meet-models deploy-lib-jitsi-meet deploy-libflac deploy-olm deploy-css deploy-local deploy-facial-expressions
deploy: deploy-init deploy-appbundle deploy-rnnoise-binary deploy-tflite deploy-meet-models deploy-lib-jitsi-meet deploy-libflac deploy-olm deploy-css deploy-local
deploy-init:
rm -fr $(DEPLOY_DIR)
@@ -38,27 +37,23 @@ deploy-init:
deploy-appbundle:
cp \
$(BUILD_DIR)/app.bundle.min.js \
$(BUILD_DIR)/app.bundle.min.js.map \
$(BUILD_DIR)/app.bundle.min.map \
$(BUILD_DIR)/do_external_connect.min.js \
$(BUILD_DIR)/do_external_connect.min.js.map \
$(BUILD_DIR)/do_external_connect.min.map \
$(BUILD_DIR)/external_api.min.js \
$(BUILD_DIR)/external_api.min.js.map \
$(BUILD_DIR)/external_api.min.map \
$(BUILD_DIR)/flacEncodeWorker.min.js \
$(BUILD_DIR)/flacEncodeWorker.min.js.map \
$(BUILD_DIR)/flacEncodeWorker.min.map \
$(BUILD_DIR)/dial_in_info_bundle.min.js \
$(BUILD_DIR)/dial_in_info_bundle.min.js.map \
$(BUILD_DIR)/dial_in_info_bundle.min.map \
$(BUILD_DIR)/alwaysontop.min.js \
$(BUILD_DIR)/alwaysontop.min.js.map \
$(BUILD_DIR)/alwaysontop.min.map \
$(OUTPUT_DIR)/analytics-ga.js \
$(BUILD_DIR)/analytics-ga.min.js \
$(BUILD_DIR)/analytics-ga.min.js.map \
$(BUILD_DIR)/facial-expressions-worker.min.js \
$(BUILD_DIR)/facial-expressions-worker.min.js.map \
$(DEPLOY_DIR)
cp \
$(BUILD_DIR)/analytics-ga.min.map \
$(BUILD_DIR)/close3.min.js \
$(BUILD_DIR)/close3.min.js.map \
$(DEPLOY_DIR) || true
$(BUILD_DIR)/close3.min.map \
$(DEPLOY_DIR)
deploy-lib-jitsi-meet:
cp \
@@ -88,17 +83,12 @@ deploy-rnnoise-binary:
deploy-tflite:
cp \
$(TFLITE_WASM)/*.wasm \
$(DEPLOY_DIR)
$(DEPLOY_DIR)
deploy-meet-models:
cp \
$(MEET_MODELS_DIR)/*.tflite \
$(DEPLOY_DIR)
deploy-facial-expressions:
cp \
$(FACIAL_MODELS_DIR)/* \
$(DEPLOY_DIR)
$(DEPLOY_DIR)
deploy-css:
$(NODE_SASS) $(STYLES_MAIN) $(STYLES_BUNDLE) && \
@@ -109,8 +99,8 @@ deploy-local:
([ ! -x deploy-local.sh ] || ./deploy-local.sh)
.NOTPARALLEL:
dev: deploy-init deploy-css deploy-rnnoise-binary deploy-tflite deploy-meet-models deploy-lib-jitsi-meet deploy-libflac deploy-olm deploy-facial-expressions
$(WEBPACK_DEV_SERVER)
dev: deploy-init deploy-css deploy-rnnoise-binary deploy-tflite deploy-meet-models deploy-lib-jitsi-meet deploy-libflac deploy-olm
$(WEBPACK_DEV_SERVER) --detect-circular-deps
source-package:
mkdir -p source_package/jitsi-meet/css && \

View File

@@ -50,7 +50,7 @@ If you'd like to run your own Jitsi Meet installation head over to the [handbook
We provide Debian packages and a comprehensive Docker setup to make deployments as simple as possible.
Advanced users also have the possibility of building all the components from source.
You can check the latest releases [here](https://jitsi.github.io/handbook/docs/releases).
You can check the latest releases [[here](https://jitsi.github.io/handbook/docs/releases).
## Jitsi as a Service

View File

@@ -78,7 +78,7 @@ dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.2.0'
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.7'
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.2'
if (!rootProject.ext.libreBuild) {
implementation 'com.google.android.gms:play-services-auth:16.0.1'
@@ -109,7 +109,6 @@ gradle.projectsEvaluated {
def dropboxActivity = """
<activity
android:configChanges="keyboard|orientation"
android:exported="true"
android:launchMode="singleTask"
android:name="com.dropbox.core.android.AuthActivity">
<intent-filter>

View File

@@ -85,9 +85,4 @@
# ^^^ We added the above when we switched minifyEnabled on.
# Rule to avoid build errors related to SVGs.
-keep public class com.horcrux.svg.** {*;}
# https://github.com/facebook/fresco/issues/2638
-keep public class com.facebook.imageutils.** {
public *;
}
-keep public class com.horcrux.svg.** {*;}

View File

@@ -4,7 +4,6 @@
android:installLocation="auto">
<application
android:allowBackup="true"
android:extractNativeLibs="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
@@ -14,7 +13,6 @@
android:resource="@xml/app_restrictions" />
<activity
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize"
android:exported="true"
android:label="@string/app_name"
android:launchMode="singleTask"
android:name=".MainActivity"

View File

@@ -82,7 +82,7 @@ public class MainActivity extends JitsiMeetActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
JitsiMeet.showSplashScreen(this);
super.onCreate(null);
super.onCreate(savedInstanceState);
}
@Override
@@ -150,8 +150,8 @@ public class MainActivity extends JitsiMeetActivity {
// Set default options
JitsiMeetConferenceOptions defaultOptions
= new JitsiMeetConferenceOptions.Builder()
.setWelcomePageEnabled(true)
.setServerURL(buildURL(defaultURL))
.setFeatureFlag("welcomepage.enabled", true)
.setFeatureFlag("call-integration.enabled", false)
.setFeatureFlag("resolution", 360)
.setFeatureFlag("server-url-change.enabled", !configurationByRestrictions)
@@ -182,6 +182,11 @@ public class MainActivity extends JitsiMeetActivity {
}
}
@Override
protected void onConferenceTerminated(HashMap<String, Object> extraData) {
Log.d(TAG, "Conference terminated: " + extraData);
}
// Activity lifecycle method overrides
//

View File

@@ -18,9 +18,9 @@ buildscript {
ext {
buildToolsVersion = "30.0.3"
compileSdkVersion = 31
compileSdkVersion = 30
minSdkVersion = 23
targetSdkVersion = 31
targetSdkVersion = 30
supportLibVersion = "28.0.0"
// The Maven artifact groupdId of the third-party react-native modules which
@@ -110,7 +110,7 @@ allprojects {
project.version = "${json.version}-jitsi-${versionQualifierNumber}"
task jitsiAndroidSourcesJar(type: Jar) {
task androidSourcesJar(type: Jar) {
classifier = 'sources'
from android.sourceSets.main.java.source
}
@@ -124,7 +124,7 @@ allprojects {
artifact("${project.buildDir}/outputs/aar/${project.name}-release.aar") {
extension "aar"
}
artifact(jitsiAndroidSourcesJar)
artifact(androidSourcesJar)
pom.withXml {
def pomXml = asNode()
pomXml.appendNode('name', project.name)

View File

@@ -24,7 +24,6 @@ android.enableDexingArtifactTransform.desugaring=false
android.useAndroidX=true
android.enableJetifier=true
android.bundle.enableUncompressedNativeLibs=false
appVersion=21.6.0
sdkVersion=4.1.0
appVersion=21.4.0
sdkVersion=3.10.0

View File

@@ -48,7 +48,6 @@ dependencies {
implementation 'com.jakewharton.timber:timber:4.7.1'
implementation 'com.squareup.duktape:duktape-android:1.3.0'
implementation 'com.google.code.gson:gson:2.8.6'
implementation "androidx.startup:startup-runtime:1.1.0"
if (rootProject.ext.libreBuild) {
implementation(project(':react-native-device-info')) {
@@ -68,18 +67,11 @@ dependencies {
implementation project(':react-native-async-storage')
implementation project(':react-native-background-timer')
implementation project(':react-native-calendar-events')
implementation project(':react-native-community_clipboard')
implementation project(':react-native-community_netinfo')
implementation project(':react-native-default-preference')
implementation project(':react-native-gesture-handler')
implementation project(':react-native-get-random-values')
implementation project(':react-native-immersive')
implementation project(':react-native-keep-awake')
implementation project(':react-native-masked-view_masked-view')
implementation project(':react-native-performance')
implementation project(':react-native-reanimated')
implementation project(':react-native-safe-area-context')
implementation project(':react-native-screens')
implementation project(':react-native-slider')
implementation project(':react-native-sound')
implementation project(':react-native-splash-screen')
@@ -218,7 +210,7 @@ publishing {
def groupId = it.moduleGroup
def artifactId = it.moduleName
if (artifactId.startsWith('react-native-')) {
if (artifactId.startsWith('react-native-') && groupId.equals('jitsi-meet')) {
groupId = rootProject.ext.moduleGroupId
}

View File

@@ -57,14 +57,6 @@
android:enabled="false"
tools:replace="android:authorities">
</provider>
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false">
<meta-data android:name="org.jitsi.meet.sdk.JitsiInitializer"
android:value="androidx.startup" />
</provider>
</application>
</manifest>

View File

@@ -86,8 +86,8 @@ public class BroadcastEvent {
PARTICIPANTS_INFO_RETRIEVED("org.jitsi.meet.PARTICIPANTS_INFO_RETRIEVED"),
CHAT_MESSAGE_RECEIVED("org.jitsi.meet.CHAT_MESSAGE_RECEIVED"),
CHAT_TOGGLED("org.jitsi.meet.CHAT_TOGGLED"),
VIDEO_MUTED_CHANGED("org.jitsi.meet.VIDEO_MUTED_CHANGED"),
READY_TO_CLOSE("org.jitsi.meet.READY_TO_CLOSE");
VIDEO_MUTED_CHANGED("org.jitsi.meet.VIDEO_MUTED_CHANGED");
private static final String CONFERENCE_WILL_JOIN_NAME = "CONFERENCE_WILL_JOIN";
private static final String CONFERENCE_JOINED_NAME = "CONFERENCE_JOINED";
@@ -101,7 +101,6 @@ public class BroadcastEvent {
private static final String CHAT_MESSAGE_RECEIVED_NAME = "CHAT_MESSAGE_RECEIVED";
private static final String CHAT_TOGGLED_NAME = "CHAT_TOGGLED";
private static final String VIDEO_MUTED_CHANGED_NAME = "VIDEO_MUTED_CHANGED";
private static final String READY_TO_CLOSE_NAME = "READY_TO_CLOSE";
private final String action;
@@ -148,8 +147,6 @@ public class BroadcastEvent {
return CHAT_TOGGLED;
case VIDEO_MUTED_CHANGED_NAME:
return VIDEO_MUTED_CHANGED;
case READY_TO_CLOSE_NAME:
return READY_TO_CLOSE;
}
return null;

View File

@@ -1,42 +0,0 @@
/*
* Copyright @ 2021-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.
*/
package org.jitsi.meet.sdk;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.startup.Initializer;
import com.facebook.soloader.SoLoader;
import java.util.ArrayList;
import java.util.List;
public class JitsiInitializer implements Initializer<Boolean> {
@NonNull
@Override
public Boolean create(@NonNull Context context) {
SoLoader.init(context, /* native exopackage */ false);
return true;
}
@NonNull
@Override
public List<Class<? extends Initializer<?>>> dependencies() {
return new ArrayList<>();
}
}

View File

@@ -24,7 +24,7 @@ import android.net.Uri;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentActivity;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import com.facebook.react.modules.core.PermissionListener;
@@ -38,7 +38,7 @@ import android.app.Activity;
* A base activity for SDK users to embed. It uses {@link JitsiMeetFragment} to do the heavy
* lifting and wires the remaining Activity lifecycle methods so it works out of the box.
*/
public class JitsiMeetActivity extends AppCompatActivity
public class JitsiMeetActivity extends FragmentActivity
implements JitsiMeetActivityInterface {
protected static final String TAG = JitsiMeetActivity.class.getSimpleName();
@@ -194,6 +194,7 @@ public class JitsiMeetActivity extends AppCompatActivity
protected void onConferenceTerminated(HashMap<String, Object> extraData) {
JitsiMeetLogger.i("Conference terminated: " + extraData);
finish();
}
protected void onConferenceWillJoin(HashMap<String, Object> extraData) {
@@ -216,11 +217,6 @@ public class JitsiMeetActivity extends AppCompatActivity
}
}
protected void onReadyToClose() {
JitsiMeetLogger.i("SDK is ready to close");
finish();
}
// Activity lifecycle methods
//
@@ -302,9 +298,6 @@ public class JitsiMeetActivity extends AppCompatActivity
case PARTICIPANT_LEFT:
onParticipantLeft(event.getData());
break;
case READY_TO_CLOSE:
onReadyToClose();
break;
}
}
}

View File

@@ -45,6 +45,11 @@ public class JitsiMeetConferenceOptions implements Parcelable {
*/
private String token;
/**
* Color scheme override, see: https://github.com/jitsi/jitsi-meet/blob/dbedee5e22e5dcf9c92db96ef5bb3c9982fc526d/react/features/base/color-scheme/defaultScheme.js
*/
private Bundle colorScheme;
/**
* Config. See: https://github.com/jitsi/jitsi-meet/blob/master/config.js
*/
@@ -72,6 +77,10 @@ public class JitsiMeetConferenceOptions implements Parcelable {
return token;
}
public Bundle getColorScheme() {
return colorScheme;
}
public Bundle getFeatureFlags() {
return featureFlags;
}
@@ -88,6 +97,7 @@ public class JitsiMeetConferenceOptions implements Parcelable {
private String room;
private String token;
private Bundle colorScheme;
private Bundle config;
private Bundle featureFlags;
@@ -142,6 +152,19 @@ public class JitsiMeetConferenceOptions implements Parcelable {
return this;
}
/**
* Sets the color scheme override so the app is themed. See:
* https://github.com/jitsi/jitsi-meet/blob/master/react/features/base/color-scheme/defaultScheme.js
* for the structure.
* @param colorScheme - A color scheme to be applied to the app.
* @return - The {@link Builder} object itself so the method calls can be chained.
*/
public Builder setColorScheme(Bundle colorScheme) {
this.colorScheme = colorScheme;
return this;
}
/**
* Indicates the conference will be joined with the microphone muted.
* @param audioMuted - Muted indication.
@@ -175,6 +198,19 @@ public class JitsiMeetConferenceOptions implements Parcelable {
return this;
}
/**
* Sets the welcome page enabled / disabled. The welcome page lists recent meetings and
* calendar appointments and it's meant to be used by standalone applications. Defaults to
* false.
* @param enabled - Whether the welcome page should be enabled or not.
* @return - The {@link Builder} object itself so the method calls can be chained.
*/
public Builder setWelcomePageEnabled(boolean enabled) {
this.featureFlags.putBoolean("welcomepage.enabled", enabled);
return this;
}
public Builder setFeatureFlag(String flag, boolean value) {
this.featureFlags.putBoolean(flag, value);
@@ -240,6 +276,7 @@ public class JitsiMeetConferenceOptions implements Parcelable {
options.serverURL = this.serverURL;
options.room = this.room;
options.token = this.token;
options.colorScheme = this.colorScheme;
options.config = this.config;
options.featureFlags = this.featureFlags;
options.userInfo = this.userInfo;
@@ -255,9 +292,11 @@ public class JitsiMeetConferenceOptions implements Parcelable {
serverURL = (URL) in.readSerializable();
room = in.readString();
token = in.readString();
colorScheme = in.readBundle();
config = in.readBundle();
featureFlags = in.readBundle();
userInfo = new JitsiMeetUserInfo(in.readBundle());
byte tmpAudioMuted = in.readByte();
}
Bundle asProps() {
@@ -270,6 +309,10 @@ public class JitsiMeetConferenceOptions implements Parcelable {
props.putBundle("flags", featureFlags);
if (colorScheme != null) {
props.putBundle("colorScheme", colorScheme);
}
Bundle urlProps = new Bundle();
// The room is fully qualified
@@ -318,6 +361,7 @@ public class JitsiMeetConferenceOptions implements Parcelable {
dest.writeSerializable(serverURL);
dest.writeString(room);
dest.writeString(token);
dest.writeBundle(colorScheme);
dest.writeBundle(config);
dest.writeBundle(featureFlags);
dest.writeBundle(userInfo != null ? userInfo.asBundle() : new Bundle());

View File

@@ -5,6 +5,7 @@ import java.util.List;
public class NotificationChannels {
static final String ONGOING_CONFERENCE_CHANNEL_ID = "JitsiOngoingConferenceChannel";
static final String ONGOING_CONFERNCE_CHANNEL_NAME = "Ongoing Conference Notifications";
public static List<String> allIds = new ArrayList<String>() {{ add(ONGOING_CONFERENCE_CHANNEL_ID); }};
}

View File

@@ -17,6 +17,7 @@
package org.jitsi.meet.sdk;
import static org.jitsi.meet.sdk.NotificationChannels.ONGOING_CONFERENCE_CHANNEL_ID;
import static org.jitsi.meet.sdk.NotificationChannels.ONGOING_CONFERNCE_CHANNEL_NAME;
import android.app.Notification;
import android.app.NotificationChannel;
@@ -65,7 +66,7 @@ class OngoingNotification {
return;
}
channel = new NotificationChannel(ONGOING_CONFERENCE_CHANNEL_ID, context.getString(R.string.ongoing_notification_action_unmute), NotificationManager.IMPORTANCE_DEFAULT);
channel = new NotificationChannel(ONGOING_CONFERENCE_CHANNEL_ID, ONGOING_CONFERNCE_CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
channel.enableLights(false);
channel.enableVibration(false);
channel.setShowBadge(false);
@@ -81,7 +82,7 @@ class OngoingNotification {
}
Intent notificationIntent = new Intent(context, context.getClass());
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, ONGOING_CONFERENCE_CHANNEL_ID);
@@ -124,7 +125,7 @@ class OngoingNotification {
Intent intent = new Intent(context, JitsiMeetOngoingConferenceService.class);
intent.setAction(action.getName());
PendingIntent pendingIntent
= PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_IMMUTABLE);
= PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
String title = context.getString(titleId);
return new NotificationCompat.Action(0, title, pendingIntent);
}

View File

@@ -30,6 +30,7 @@ import com.facebook.react.devsupport.DevInternalSettings;
import com.facebook.react.jscexecutor.JSCExecutorFactory;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.facebook.react.uimanager.ViewManager;
import com.facebook.soloader.SoLoader;
import com.oney.WebRTCModule.RTCVideoViewManager;
import com.oney.WebRTCModule.WebRTCModule;
@@ -173,30 +174,25 @@ class ReactInstanceManagerHolder {
return;
}
SoLoader.init(activity.getApplication(), /* native exopackage */ false);
List<ReactPackage> packages
= new ArrayList<>(Arrays.asList(
new com.reactnativecommunity.asyncstorage.AsyncStoragePackage(),
new com.ocetnik.timer.BackgroundTimerPackage(),
new com.calendarevents.CalendarEventsPackage(),
new com.corbt.keepawake.KCKeepAwakePackage(),
new com.facebook.react.shell.MainReactPackage(),
new com.reactnativecommunity.clipboard.ClipboardPackage(),
new com.reactnativecommunity.netinfo.NetInfoPackage(),
new com.oblador.performance.PerformancePackage(),
new com.reactnativecommunity.slider.ReactSliderPackage(),
new com.brentvatne.react.ReactVideoPackage(),
new com.swmansion.reanimated.ReanimatedPackage(),
new org.reactnative.maskedview.RNCMaskedViewPackage(),
new com.reactnativecommunity.webview.RNCWebViewPackage(),
new com.horcrux.svg.SvgPackage(),
new com.kevinresol.react_native_default_preference.RNDefaultPreferencePackage(),
new com.learnium.RNDeviceInfo.RNDeviceInfo(),
new com.swmansion.gesturehandler.react.RNGestureHandlerPackage(),
new org.linusu.RNGetRandomValuesPackage(),
new com.oblador.performance.PerformancePackage(),
new com.ocetnik.timer.BackgroundTimerPackage(),
new com.reactnativecommunity.asyncstorage.AsyncStoragePackage(),
new com.reactnativecommunity.netinfo.NetInfoPackage(),
new com.reactnativecommunity.slider.ReactSliderPackage(),
new com.reactnativecommunity.webview.RNCWebViewPackage(),
new com.rnimmersive.RNImmersivePackage(),
new com.swmansion.rnscreens.RNScreensPackage(),
new com.zmxv.RNSound.RNSoundPackage(),
new com.th3rdwave.safeareacontext.SafeAreaContextPackage(),
new com.horcrux.svg.SvgPackage(),
new com.brentvatne.react.ReactVideoPackage(),
new ReactPackageAdapter() {
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {

View File

@@ -6,5 +6,4 @@
<string name="ongoing_notification_action_hang_up">Hang up</string>
<string name="ongoing_notification_action_mute">Mute</string>
<string name="ongoing_notification_action_unmute">Unmute</string>
<string name="ongoing_notification_channel_name">Ongoing Conference Notifications</string>
</resources>

View File

@@ -9,34 +9,20 @@ include ':react-native-background-timer'
project(':react-native-background-timer').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-background-timer/android')
include ':react-native-calendar-events'
project(':react-native-calendar-events').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-calendar-events/android')
include ':react-native-community_clipboard'
project(':react-native-community_clipboard').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/clipboard/android')
include ':react-native-community_netinfo'
project(':react-native-community_netinfo').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/netinfo/android')
include ':react-native-default-preference'
project(':react-native-default-preference').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-default-preference/android')
include ':react-native-device-info'
project(':react-native-device-info').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-device-info/android')
include ':react-native-gesture-handler'
project(':react-native-gesture-handler').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-gesture-handler/android')
include ':react-native-get-random-values'
project(':react-native-get-random-values').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-get-random-values/android')
include ':react-native-google-signin'
project(':react-native-google-signin').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/google-signin/android')
include ':react-native-immersive'
project(':react-native-immersive').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-immersive/android')
include ':react-native-keep-awake'
project(':react-native-keep-awake').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-keep-awake/android')
include ':react-native-masked-view_masked-view'
project(':react-native-masked-view_masked-view').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-masked-view/masked-view/android')
include ':react-native-performance'
project(':react-native-performance').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-performance/android')
include ':react-native-reanimated'
project(':react-native-reanimated').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-reanimated/android')
include ':react-native-safe-area-context'
project(':react-native-safe-area-context').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-safe-area-context/android')
include ':react-native-screens'
project(':react-native-screens').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-screens/android')
include ':react-native-slider'
project(':react-native-slider').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/slider/android')
include ':react-native-sound'

View File

@@ -1,15 +1,14 @@
/* global APP, JitsiMeetJS, config, interfaceConfig */
import { jitsiLocalStorage } from '@jitsi/js-utils';
import Logger from '@jitsi/logger';
import EventEmitter from 'events';
import Logger from 'jitsi-meet-logger';
import { openConnection } from './connection';
import { ENDPOINT_TEXT_MESSAGE_NAME } from './modules/API/constants';
import { AUDIO_ONLY_SCREEN_SHARE_NO_TRACK } from './modules/UI/UIErrors';
import AuthHandler from './modules/UI/authentication/AuthHandler';
import UIUtil from './modules/UI/util/UIUtil';
import VideoLayout from './modules/UI/videolayout/VideoLayout';
import mediaDeviceHelper from './modules/devices/mediaDeviceHelper';
import Recorder from './modules/recorder/Recorder';
import { createTaskQueue } from './modules/util/helpers';
@@ -30,7 +29,6 @@ import { shouldShowModeratedNotification } from './react/features/av-moderation/
import {
AVATAR_URL_COMMAND,
EMAIL_COMMAND,
_conferenceWillJoin,
authStatusChanged,
commonUserJoinedHandling,
commonUserLeftHandling,
@@ -49,7 +47,7 @@ import {
onStartMutedPolicyChanged,
p2pStatusChanged,
sendLocalParticipant,
nonParticipantMessageReceived
_conferenceWillJoin
} from './react/features/base/conference';
import { getReplaceParticipant } from './react/features/base/config/functions';
import {
@@ -61,6 +59,7 @@ import {
setAudioOutputDeviceId,
updateDeviceList
} from './react/features/base/devices';
import { isIosMobileBrowser } from './react/features/base/environment/utils';
import {
browser,
isFatalJitsiConnectionError,
@@ -71,8 +70,7 @@ import {
JitsiMediaDevicesEvents,
JitsiParticipantConnectionStatus,
JitsiTrackErrors,
JitsiTrackEvents,
JitsiRecordingConstants
JitsiTrackEvents
} from './react/features/base/lib-jitsi-meet';
import {
getStartWithAudioMuted,
@@ -81,15 +79,14 @@ import {
MEDIA_TYPE,
setAudioAvailable,
setAudioMuted,
setAudioUnmutePermissions,
setVideoAvailable,
setVideoMuted,
setVideoUnmutePermissions
setVideoMuted
} from './react/features/base/media';
import {
dominantSpeakerChanged,
getLocalParticipant,
getNormalizedDisplayName,
getParticipantById,
localParticipantConnectionStatusChanged,
localParticipantRoleChanged,
participantConnectionStatusChanged,
@@ -111,7 +108,6 @@ import {
getLocalJitsiAudioTrack,
getLocalJitsiVideoTrack,
getLocalTracks,
getLocalVideoTrack,
isLocalCameraTrackMuted,
isLocalTrackMuted,
isUserInteractionRequiredForUnmute,
@@ -126,24 +122,18 @@ import {
maybeOpenFeedbackDialog,
submitFeedback
} from './react/features/feedback';
import {
isModerationNotificationDisplayed,
showNotification,
NOTIFICATION_TIMEOUT_TYPE
} from './react/features/notifications';
import { isModerationNotificationDisplayed, showNotification } from './react/features/notifications';
import { mediaPermissionPromptVisibilityChanged, toggleSlowGUMOverlay } from './react/features/overlay';
import { suspendDetected } from './react/features/power-monitor';
import {
initPrejoin,
isPrejoinPageEnabled,
isPrejoinPageVisible,
makePrecallTest,
setJoiningInProgress,
setPrejoinPageVisibility
makePrecallTest
} from './react/features/prejoin';
import { getActiveSession } from './react/features/recording/functions';
import { disableReceiver, stopReceiver } from './react/features/remote-control';
import { setScreenAudioShareState, isScreenAudioShared } from './react/features/screen-share/';
import { toggleScreenshotCaptureSummary } from './react/features/screenshot-capture';
import { toggleScreenshotCaptureEffect } from './react/features/screenshot-capture';
import { AudioMixerEffect } from './react/features/stream-effects/audio-mixer/AudioMixerEffect';
import { createPresenterEffect } from './react/features/stream-effects/presenter';
import { createRnnoiseProcessor } from './react/features/stream-effects/rnnoise';
@@ -166,15 +156,6 @@ let connection;
*/
let _connectionPromise;
/**
* We are storing the resolve function of a Promise that waits for the _connectionPromise to be created. This is needed
* when the prejoin button was pressed before the conference object was initialized and the _connectionPromise has not
* been initialized when we tried to execute prejoinStart. In this case in prejoinStart we create a new Promise, assign
* the resolve function to this variable and wait for the promise to resolve before we continue. The
* _onConnectionPromiseCreated will be called once the _connectionPromise is created.
*/
let _onConnectionPromiseCreated;
/**
* This promise is used for chaining mutePresenterVideo calls in order to avoid calling GUM multiple times if it takes
* a while to finish.
@@ -238,6 +219,17 @@ function sendData(command, value) {
room.sendCommand(command, { value });
}
/**
* Get user nickname by user id.
* @param {string} id user id
* @returns {string?} user nickname or undefined if user is unknown.
*/
function getDisplayName(id) {
const participant = getParticipantById(APP.store.getState(), id);
return participant && participant.name;
}
/**
* Mute or unmute local audio stream if it exists.
* @param {boolean} muted - if audio stream should be muted or unmuted.
@@ -353,10 +345,7 @@ class ConferenceConnector {
case JitsiConferenceErrors.FOCUS_DISCONNECTED: {
const [ focus, retrySec ] = params;
APP.store.dispatch(showNotification({
descriptionKey: focus,
titleKey: retrySec
}, NOTIFICATION_TIMEOUT_TYPE.SHORT));
APP.UI.notifyFocusDisconnected(focus, retrySec);
break;
}
@@ -754,13 +743,13 @@ export default {
APP.store.dispatch(showNotification({
descriptionKey: 'notify.startSilentDescription',
titleKey: 'notify.startSilentTitle'
}, NOTIFICATION_TIMEOUT_TYPE.LONG));
}));
}
// XXX The API will take care of disconnecting from the XMPP
// server (and, thus, leaving the room) on unload.
return new Promise((resolve, reject) => {
new ConferenceConnector(resolve, reject).connect();
(new ConferenceConnector(resolve, reject)).connect();
});
},
@@ -796,7 +785,7 @@ export default {
logger.warn('initial device list initialization failed', error);
}
if (isPrejoinPageVisible(APP.store.getState())) {
if (isPrejoinPageEnabled(APP.store.getState())) {
_connectionPromise = connect(roomName).then(c => {
// we want to initialize it early, in case of errors to be able
// to gather logs
@@ -805,10 +794,6 @@ export default {
return c;
});
if (_onConnectionPromiseCreated) {
_onConnectionPromiseCreated();
}
APP.store.dispatch(makePrecallTest(this._getConferenceOptions()));
const { tryCreateLocalTracks, errors } = this.createInitialLocalTracks(initialOptions);
@@ -836,9 +821,9 @@ export default {
this._initDeviceList(true);
if (initialOptions.startWithAudioMuted) {
// Always add the track on Safari because of a known issue where audio playout doesn't happen
// if the user joins audio and video muted, i.e., if there is no local media capture.
if (browser.isWebKitBased()) {
// Always add the audio track to the peer connection and then mute the track on mobile Safari
// because of a known issue where audio playout doesn't happen if the user joins audio and video muted.
if (isIosMobileBrowser()) {
this.muteAudio(true, true);
} else {
localTracks = localTracks.filter(track => track.getType() !== MEDIA_TYPE.AUDIO);
@@ -852,26 +837,12 @@ export default {
* Joins conference after the tracks have been configured in the prejoin screen.
*
* @param {Object[]} tracks - An array with the configured tracks
* @returns {void}
* @returns {Promise}
*/
async prejoinStart(tracks) {
if (!_connectionPromise) {
// The conference object isn't initialized yet. Wait for the promise to initialise.
await new Promise(resolve => {
_onConnectionPromiseCreated = resolve;
});
_onConnectionPromiseCreated = undefined;
}
const con = await _connectionPromise;
let con;
try {
con = await _connectionPromise;
this.startConference(con, tracks);
} catch (error) {
logger.error(`An error occurred while trying to join a meeting from the prejoin screen: ${error}`);
APP.store.dispatch(setJoiningInProgress(false));
}
return this.startConference(con, tracks);
},
/**
@@ -1015,14 +986,6 @@ export default {
* dialogs in case of media permissions error.
*/
muteVideo(mute, showUI = true) {
if (this.videoSwitchInProgress) {
// Turning the camera on while the screen sharing mode is being turned off is causing issues around
// the presenter mode handling. It should be okay for the user to click the button again once that's done.
console.warn('muteVideo - unable to perform operations while video switch is in progress');
return;
}
if (!mute
&& isUserInteractionRequiredForUnmute(APP.store.getState())) {
logger.error('Unmuting video requires user interaction');
@@ -1210,6 +1173,14 @@ export default {
return room.isConnectionInterrupted();
},
/**
* Obtains the local display name.
* @returns {string|undefined}
*/
getLocalDisplayName() {
return getDisplayName(this.getMyUserId());
},
/**
* Finds JitsiParticipant for given id.
*
@@ -1222,6 +1193,29 @@ export default {
return room ? room.getParticipantById(id) : null;
},
/**
* Gets the display name foe the <tt>JitsiParticipant</tt> identified by
* the given <tt>id</tt>.
*
* @param id {string} the participant's id(MUC nickname/JVB endpoint id)
*
* @return {string} the participant's display name or the default string if
* absent.
*/
getParticipantDisplayName(id) {
const displayName = getDisplayName(id);
if (displayName) {
return displayName;
}
if (APP.conference.isLocalId(id)) {
return APP.translation.generateTranslationHTML(
interfaceConfig.DEFAULT_LOCAL_DISPLAY_NAME);
}
return interfaceConfig.DEFAULT_REMOTE_DISPLAY_NAME;
},
getMyUserId() {
return room && room.myUserId();
},
@@ -1329,43 +1323,14 @@ export default {
}
},
/**
* Used by the Breakout Rooms feature to join a breakout room or go back to the main room.
*/
async joinRoom(roomName, options) {
// Reset VideoLayout. It's destroyed in features/video-layout/middleware.web.js so re-initialize it.
VideoLayout.initLargeVideo();
VideoLayout.resizeVideoArea();
// Restore initial state.
this._localTracksInitialized = false;
this.isSharingScreen = false;
this.localPresenterVideo = null;
this.roomName = roomName;
const { tryCreateLocalTracks, errors } = this.createInitialLocalTracks(options);
const localTracks = await tryCreateLocalTracks;
this._displayErrorsForCreateInitialLocalTracks(errors);
localTracks.forEach(track => {
if ((track.isAudioTrack() && this.isLocalAudioMuted())
|| (track.isVideoTrack() && this.isLocalVideoMuted())) {
track.mute();
}
});
this._createRoom(localTracks);
return new Promise((resolve, reject) => {
new ConferenceConnector(resolve, reject).connect();
});
},
_createRoom(localTracks) {
room = connection.initJitsiConference(APP.conference.roomName, this._getConferenceOptions());
room
= connection.initJitsiConference(
APP.conference.roomName,
this._getConferenceOptions());
// Filter out the tracks that are muted (except on Safari).
const tracks = browser.isWebKitBased() ? localTracks : localTracks.filter(track => !track.isMuted());
// Filter out the tracks that are muted (except on mobile Safari).
const tracks = isIosMobileBrowser() ? localTracks : localTracks.filter(track => !track.isMuted());
this._setLocalAudioVideoStreams(tracks);
this._room = room; // FIXME do not use this
@@ -1552,12 +1517,9 @@ export default {
APP.store.dispatch(stopReceiver());
this._stopProxyConnection();
if (config.enableScreenshotCapture) {
APP.store.dispatch(toggleScreenshotCaptureSummary(false));
APP.store.dispatch(toggleScreenshotCaptureEffect(false));
}
const tracks = APP.store.getState()['features/base/tracks'];
const duration = getLocalVideoTrack(tracks)?.jitsiTrack.getDuration() ?? 0;
// It can happen that presenter GUM is in progress while screensharing is being turned off. Here it needs to
// wait for that GUM to be resolved in order to prevent leaking the presenter track(this.localPresenterVideo
@@ -1619,8 +1581,7 @@ export default {
return promise.then(
() => {
this.videoSwitchInProgress = false;
sendAnalytics(createScreenSharingEvent('stopped',
duration === 0 ? null : duration));
sendAnalytics(createScreenSharingEvent('stopped'));
logger.info('Screen sharing stopped.');
},
error => {
@@ -1650,7 +1611,7 @@ export default {
async toggleScreenSharing(toggle = !this._untoggleScreenSharing, options = {}, ignoreDidHaveVideo) {
logger.debug(`toggleScreenSharing: ${toggle}`);
if (this.videoSwitchInProgress) {
return Promise.reject(`toggleScreenSharing: ${toggle} aborted - video switch in progress.`);
return Promise.reject('Switch in progress.');
}
if (!JitsiMeetJS.isDesktopSharingEnabled()) {
return Promise.reject('Cannot toggle screen sharing: not supported.');
@@ -1710,10 +1671,10 @@ export default {
= this._turnScreenSharingOff.bind(this, didHaveVideo);
const desktopVideoStream = desktopStreams.find(stream => stream.getType() === MEDIA_TYPE.VIDEO);
const desktopAudioStream = desktopStreams.find(stream => stream.getType() === MEDIA_TYPE.AUDIO);
const dekstopAudioStream = desktopStreams.find(stream => stream.getType() === MEDIA_TYPE.AUDIO);
if (desktopAudioStream) {
desktopAudioStream.on(
if (dekstopAudioStream) {
dekstopAudioStream.on(
JitsiTrackEvents.LOCAL_TRACK_STOPPED,
() => {
logger.debug(`Local screensharing audio track stopped. ${this.isSharingScreen}`);
@@ -1935,9 +1896,7 @@ export default {
.then(() => {
this.videoSwitchInProgress = false;
if (config.enableScreenshotCapture) {
if (getActiveSession(APP.store.getState(), JitsiRecordingConstants.mode.FILE)) {
APP.store.dispatch(toggleScreenshotCaptureSummary(true));
}
APP.store.dispatch(toggleScreenshotCaptureEffect(true));
}
sendAnalytics(createScreenSharingEvent('started'));
logger.log('Screen sharing started');
@@ -2018,9 +1977,6 @@ export default {
room.on(JitsiConferenceEvents.CONFERENCE_JOINED, () => {
this._onConferenceJoined();
});
room.on(JitsiConferenceEvents.CONFERENCE_JOIN_IN_PROGRESS, () => {
APP.store.dispatch(setPrejoinPageVisibility(false));
});
room.on(
JitsiConferenceEvents.CONFERENCE_LEFT,
@@ -2135,8 +2091,6 @@ export default {
}
});
room.on(JitsiConferenceEvents.TRACK_UNMUTE_REJECTED, track => APP.store.dispatch(destroyLocalTracks(track)));
room.on(JitsiConferenceEvents.SUBJECT_CHANGED,
subject => APP.store.dispatch(conferenceSubjectChanged(subject)));
@@ -2178,10 +2132,6 @@ export default {
(id, displayName) => {
const formattedDisplayName
= getNormalizedDisplayName(displayName);
const state = APP.store.getState();
const {
defaultRemoteDisplayName
} = state['features/base/config'];
APP.store.dispatch(participantUpdated({
conference: room,
@@ -2193,7 +2143,7 @@ export default {
formattedDisplayName:
appendSuffix(
formattedDisplayName
|| defaultRemoteDisplayName)
|| interfaceConfig.DEFAULT_REMOTE_DISPLAY_NAME)
});
}
);
@@ -2228,10 +2178,6 @@ export default {
}
});
room.on(
JitsiConferenceEvents.NON_PARTICIPANT_MESSAGE_RECEIVED,
(...args) => APP.store.dispatch(nonParticipantMessageReceived(...args)));
room.on(
JitsiConferenceEvents.LOCK_STATE_CHANGED,
(...args) => APP.store.dispatch(lockStateChanged(room, ...args)));
@@ -2265,17 +2211,6 @@ export default {
APP.store.dispatch(suspendDetected());
});
room.on(
JitsiConferenceEvents.AUDIO_UNMUTE_PERMISSIONS_CHANGED,
disableAudioMuteChange => {
APP.store.dispatch(setAudioUnmutePermissions(disableAudioMuteChange));
});
room.on(
JitsiConferenceEvents.VIDEO_UNMUTE_PERMISSIONS_CHANGED,
disableVideoMuteChange => {
APP.store.dispatch(setVideoUnmutePermissions(disableVideoMuteChange));
});
APP.UI.addListener(UIEvents.AUDIO_MUTED, muted => {
this.muteAudio(muted);
});
@@ -2331,9 +2266,9 @@ export default {
// Remove the tracks from the peerconnection.
for (const track of localTracks) {
// Always add the track on Safari because of a known issue where audio playout doesn't happen
// if the user joins audio and video muted, i.e., if there is no local media capture.
if (audioMuted && track.jitsiTrack?.getType() === MEDIA_TYPE.AUDIO && !browser.isWebKitBased()) {
// Always add the track on mobile Safari because of a known issue where audio playout doesn't happen
// if the user joins audio and video muted.
if (audioMuted && track.jitsiTrack?.getType() === MEDIA_TYPE.AUDIO && !isIosMobileBrowser()) {
promises.push(this.useAudioStream(null));
}
if (videoMuted && track.jitsiTrack?.getType() === MEDIA_TYPE.VIDEO) {
@@ -2342,12 +2277,7 @@ export default {
}
Promise.allSettled(promises)
.then(() => {
APP.store.dispatch(showNotification({
titleKey: 'notify.mutedTitle',
descriptionKey: 'notify.muted'
}, NOTIFICATION_TIMEOUT_TYPE.SHORT));
});
.then(() => APP.UI.notifyInitiallyMuted());
});
room.on(
@@ -2676,17 +2606,12 @@ export default {
APP.store.dispatch(updateDeviceList(devices));
// Firefox users can choose their preferred device in the gUM prompt. In that case
// we should respect that and not attempt to switch to the preferred device from
// our settings.
const newLabelsOnly = mediaDeviceHelper.newDeviceListAddedLabelsOnly(oldDevices, devices);
const newDevices
= mediaDeviceHelper.getNewMediaDevicesAfterDeviceListChanged(
devices,
this.isSharingScreen,
localVideo,
localAudio,
newLabelsOnly);
localAudio);
const promises = [];
const audioWasMuted = this.isLocalAudioMuted();
const videoWasMuted = this.isLocalVideoMuted();
@@ -2912,7 +2837,7 @@ export default {
Promise.all([
requestFeedbackPromise,
this.leaveRoom()
this.leaveRoomAndDisconnect()
])
.then(values => {
this._room = undefined;
@@ -2931,25 +2856,18 @@ export default {
},
/**
* Leaves the room.
* Leaves the room and calls JitsiConnection.disconnect.
*
* @param {boolean} doDisconnect - Wether leaving the room should also terminate the connection.
* @returns {Promise}
*/
async leaveRoom(doDisconnect = true) {
leaveRoomAndDisconnect() {
APP.store.dispatch(conferenceWillLeave(room));
if (room && room.isJoined()) {
return room.leave().finally(() => {
if (doDisconnect) {
return disconnect();
}
});
return room.leave().then(disconnect, disconnect);
}
if (doDisconnect) {
return disconnect();
}
return disconnect();
},
/**
@@ -3031,15 +2949,6 @@ export default {
room.sendEndpointMessage(to, payload);
},
/**
* Sends a facial expression as a string and its duration as a number
* @param {object} payload - Object containing the {string} facialExpression
* and {number} duration
*/
sendFacialExpression(payload) {
room.sendFacialExpression(payload);
},
/**
* Adds new listener.
* @param {String} eventName the name of the event

265
config.js
View File

@@ -74,30 +74,15 @@ var config = {
// callStatsThreshold: 5 // enable callstats for 5% of the users.
},
// Feature Flags.
flags: {
// Enables source names in the signaling.
// sourceNameSignaling: false,
},
// Disables moderator indicators.
// disableModeratorIndicator: false,
// Disables the reactions feature.
// disableReactions: true,
// Disables the reactions moderation feature.
// disableReactionsModeration: false,
// Disables polls feature.
// disablePolls: false,
// Disables self-view tile. (hides it from tile view and from filmstrip)
// disableSelfView: false,
// Disables self-view settings in UI
// disableSelfViewSettings: false,
// Disables ICE/UDP by filtering out local and remote UDP candidates in
// signalling.
// webrtcIceUdpDisable: false,
@@ -294,7 +279,6 @@ var config = {
// autoHide: true,
// autoHideTimeout: 5000,
// disabled: false,
// disableDetails: false,
// inactiveDisabled: false
// },
@@ -390,13 +374,6 @@ var config = {
// resizeDesktopForPresenter: false
// },
// Notification timeouts
// notificationTimeouts: {
// short: 2500,
// medium: 5000,
// long: 10000
// },
// // Options for the recording limit notification.
// recordingLimit: {
//
@@ -415,9 +392,6 @@ var config = {
// Disables or enables RTX (RFC 4588) (defaults to false).
// disableRtx: false,
// Moves all Jitsi Meet 'beforeunload' logic (cleanup, leaving, disconnecting, etc) to the 'unload' event.
// disableBeforeUnloadHandlers: true,
// Disables or enables TCC support in this client (default: enabled).
// enableTcc: true,
@@ -455,12 +429,6 @@ var config = {
// Hides lobby button
// hideLobbyButton: false,
// If Lobby is enabled starts knocking automatically.
// autoKnockLobby: false,
// Hides add breakout room button
// hideAddRoomButton: false,
// Require users to always specify a display name.
// requireDisplayName: true,
@@ -484,24 +452,12 @@ var config = {
// when the toolbar is shown on mouse movements
// disable1On1Mode: null | false | true,
// Default local name to be displayed
// defaultLocalDisplayName: 'me',
// Default remote name to be displayed
// defaultRemoteDisplayName: 'Fellow Jitster',
// Hides the display name from the participant thumbnail
// hideDisplayName: false
// Default language for the user interface.
// defaultLanguage: 'en',
// Disables profile and the edit of all fields from the profile settings (display name and email)
// disableProfile: false,
// Hides the email section under profile settings.
// hideEmailInSettings: false,
// Whether or not some features are checked based on token.
// enableFeaturesBasedOnToken: false,
@@ -517,18 +473,8 @@ var config = {
// and microsoftApiApplicationClientID
// enableCalendarIntegration: false,
// Configs for prejoin page.
// prejoinConfig: {
// // When 'true', it shows an intermediate page before joining, where the user can configure their devices.
// // This replaces `prejoinPageEnabled`.
// enabled: true,
// // List of buttons to hide from the extra join options dropdown.
// hideExtraJoinButtons: ['no-audio', 'by-phone']
// },
// When 'true', the user cannot edit the display name.
// (Mainly useful when used in conjuction with the JWT so the JWT name becomes read only.)
// readOnlyName: false,
// When 'true', it shows an intermediate page before joining, where the user can configure their devices.
// prejoinPageEnabled: false,
// If etherpad integration is enabled, setting this to true will
// automatically open the etherpad when a participant joins. This
@@ -546,9 +492,6 @@ var config = {
// Document should be focused for this option to work
// enableAutomaticUrlCopy: false,
// Array with avatar URL prefixes that need to use CORS.
// corsAvatarURLs: [ 'https://www.gravatar.com/avatar/' ],
// Base URL for a Gravatar-compatible service. Defaults to libravatar.
// gravatarBaseURL: 'https://seccdn.libravatar.org/avatar/',
@@ -602,74 +545,41 @@ var config = {
// '__end'
// ],
// Holds values related to toolbar visibility control.
// toolbarConfig: {
// // Moved from interfaceConfig.INITIAL_TOOLBAR_TIMEOUT
// // The initial numer of miliseconds for the toolbar buttons to be visible on screen.
// initialTimeout: 20000,
// // Moved from interfaceConfig.TOOLBAR_TIMEOUT
// // Number of miliseconds for the toolbar buttons to be visible on screen.
// timeout: 4000,
// // Moved from interfaceConfig.TOOLBAR_ALWAYS_VISIBLE
// // Whether toolbar should be always visible or should hide after x miliseconds.
// alwaysVisible: false
// },
// Toolbar buttons which have their click/tap event exposed through the API on
// `toolbarButtonClicked`. Passing a string for the button key will
// prevent execution of the click/tap routine; passing an object with `key` and
// `preventExecution` flag on false will not prevent execution of the click/tap
// routine. Below array with mixed mode for passing the buttons.
// Toolbar buttons which have their click event exposed through the API on
// `toolbarButtonClicked` event instead of executing the normal click routine.
// buttonsWithNotifyClick: [
// 'camera',
// {
// key: 'chat',
// preventExecution: false
// },
// {
// key: 'closedcaptions',
// preventExecution: true
// },
// 'desktop',
// 'download',
// 'embedmeeting',
// 'etherpad',
// 'feedback',
// 'filmstrip',
// 'fullscreen',
// 'hangup',
// 'help',
// {
// key: 'invite',
// preventExecution: false
// },
// 'livestreaming',
// 'microphone',
// 'mute-everyone',
// 'mute-video-everyone',
// 'participants-pane',
// 'profile',
// {
// key: 'raisehand',
// preventExecution: true
// },
// 'recording',
// 'security',
// 'select-background',
// 'settings',
// 'shareaudio',
// 'sharedvideo',
// 'shortcuts',
// 'stats',
// 'tileview',
// 'toggle-camera',
// 'videoquality',
// // The add passcode button from the security dialog.
// {
// key: 'add-passcode',
// preventExecution: false
// }
// '__end'
// 'camera',
// 'chat',
// 'closedcaptions',
// 'desktop',
// 'download',
// 'embedmeeting',
// 'etherpad',
// 'feedback',
// 'filmstrip',
// 'fullscreen',
// 'hangup',
// 'help',
// 'invite',
// 'livestreaming',
// 'microphone',
// 'mute-everyone',
// 'mute-video-everyone',
// 'participants-pane',
// 'profile',
// 'raisehand',
// 'recording',
// 'security',
// 'select-background',
// 'settings',
// 'shareaudio',
// 'sharedvideo',
// 'shortcuts',
// 'stats',
// 'tileview',
// 'toggle-camera',
// 'videoquality',
// '__end'
// ],
// List of pre meeting screens buttons to hide. The values must be one or more of the 5 allowed buttons:
@@ -721,9 +631,6 @@ var config = {
// Enables sending participants' emails (if available) to callstats and other analytics
// enableEmailInStats: false,
// Enables detecting faces of participants and get their expression and send it to other participants
// enableFacialRecognition: true,
// Controls the percentage of automatic feedback shown to participants when callstats is enabled.
// The default value is 100%. If set to 0, no automatic feedback will be requested
// feedbackPercentage: 100,
@@ -806,7 +713,7 @@ var config = {
// module connects to the provided rtcstatsEndpoint and sends statistics regarding
// PeerConnection states along with getStats metrics polled at the specified
// interval.
// rtcstatsEnabled: false,
// rtcstatsEnabled: true,
// In order to enable rtcstats one needs to provide a endpoint url.
// rtcstatsEndpoint: wss://rtcstats-server-pilot.jitsi.net/,
@@ -852,7 +759,6 @@ var config = {
// - 'PARTICIPANT_JOINED_SOUND'
// - 'PARTICIPANT_LEFT_SOUND'
// - 'RAISE_HAND_SOUND'
// - 'REACTION_SOUND'
// - 'RECORDING_OFF_SOUND'
// - 'RECORDING_ON_SOUND'
// - 'TALK_WHILE_MUTED_SOUND'
@@ -901,10 +807,6 @@ var config = {
// format: 'flac'
//
// },
// e2ee: {
// labels,
// externallyManagedKey: false
// },
// Options related to end-to-end (participant to participant) ping.
@@ -975,65 +877,25 @@ var config = {
If there is no url set or there are missing fields, the defaults are applied.
The config file should be in JSON.
None of the fields are mandatory and the response must have the shape:
{
// The domain url to apply (will replace the domain in the sharing conference link/embed section)
inviteDomain: 'example-company.org,
// The hex value for the colour used as background
backgroundColor: '#fff',
// The url for the image used as background
backgroundImageUrl: 'https://example.com/background-img.png',
// The anchor url used when clicking the logo image
logoClickUrl: 'https://example-company.org',
// The url used for the image used as logo
logoImageUrl: 'https://example.com/logo-img.png',
// Overwrite for pool of background images for avatars
avatarBackgrounds: ['url(https://example.com/avatar-background-1.png)', '#FFF'],
// The lobby/prejoin screen background
premeetingBackground: 'url(https://example.com/premeeting-background.png)',
// A list of images that can be used as video backgrounds.
// When this field is present, the default images will be replaced with those provided.
virtualBackgrounds: ['https://example.com/img.jpg'],
// Object containing a theme's properties. It also supports partial overwrites of the main theme.
// For a list of all possible theme tokens and their current defaults, please check:
// https://github.com/jitsi/jitsi-meet/tree/master/resources/custom-theme/custom-theme.json
// For a short explanations on each of the tokens, please check:
// https://github.com/jitsi/jitsi-meet/blob/master/react/features/base/ui/Tokens.js
// IMPORTANT!: This is work in progress so many of the various tokens are not yet applied in code
// or they are partially applied.
customTheme: {
palette: {
ui01: "orange !important",
ui02: "maroon",
surface02: 'darkgreen',
ui03: "violet",
ui04: "magenta",
ui05: "blueviolet",
field02Hover: 'red',
action01: 'green',
action01Hover: 'lightgreen',
action02Disabled: 'beige',
success02: 'cadetblue',
action02Hover: 'aliceblue'
},
typography: {
labelRegular: {
fontSize: 25,
lineHeight: 30,
fontWeight: 500
}
}
}
}
{
// The domain url to apply (will replace the domain in the sharing conference link/embed section)
inviteDomain: 'example-company.org,
// The hex value for the colour used as background
backgroundColor: '#fff',
// The url for the image used as background
backgroundImageUrl: 'https://example.com/background-img.png',
// The anchor url used when clicking the logo image
logoClickUrl: 'https://example-company.org',
// The url used for the image used as logo
logoImageUrl: 'https://example.com/logo-img.png',
// Overwrite for pool of background images for avatars
avatarBackgrounds: ['url(https://example.com/avatar-background-1.png)', '#FFF'],
// The lobby/prejoin screen background
premeetingBackground: 'url(https://example.com/premeeting-background.png)'
}
*/
// dynamicBrandingUrl: '',
// When true the user cannot add more images to be used as virtual background.
// Only the default ones from will be available.
// disableAddingBackgroundImages: false,
// Disables using screensharing as virtual background.
// disableScreensharingVirtualBackground: false,
// Sets the background transparency level. '0' is fully transparent, '1' is opaque.
// backgroundAlpha: 1,
@@ -1045,14 +907,11 @@ var config = {
// If true, tile view will not be enabled automatically when the participants count threshold is reached.
// disableTileView: true,
// If true, the tiles will be displayed contained within the available space rather than enlarged to cover it.
// disableTileEnlargement: true,
// Controls the visibility and behavior of the top header conference info labels.
// If a label's id is not in any of the 2 arrays, it will not be visible at all on the header.
// conferenceInfo: {
// // those labels will not be hidden in tandem with the toolbox.
// alwaysVisible: ['recording', 'local-recording', 'raised-hands-count'],
// alwaysVisible: ['recording', 'local-recording'],
// // those labels will be auto-hidden in tandem with the toolbox buttons.
// autoHide: [
// 'subject',
@@ -1066,10 +925,10 @@ var config = {
// },
// Hides the conference subject
// hideConferenceSubject: false,
// hideConferenceSubject: true,
// Hides the conference timer.
// hideConferenceTimer: false,
// hideConferenceTimer: true,
// Hides the recording label
// hideRecordingLabel: false,
@@ -1080,9 +939,6 @@ var config = {
// Sets the conference subject
// subject: 'Conference Subject',
// Sets the conference local subject
// localSubject: 'Conference Local Subject',
// This property is related to the use case when jitsi-meet is used via the IFrame API. When the property is true
// jitsi-meet will use the local storage of the host page instead of its own. This option is useful if the browser
// is not persisting the local storage inside the iframe.
@@ -1095,6 +951,11 @@ var config = {
// will open an etherpad document.
// etherpad_base: 'https://your-etherpad-installati.on/p/',
// If etherpad_base is set, and useRoomAsSharedDocumentName is set to true,
// open a pad with the name of the room (lowercased) instead of a pad with a
// random UUID.
// useRoomAsSharedDocumentName: true,
// List of undocumented settings used in jitsi-meet
/**
_immediateReloadThreshold
@@ -1187,14 +1048,10 @@ var config = {
// 'lobby.joinRejectedMessage', // shown when while in a lobby, user's request to join is rejected
// 'lobby.notificationTitle', // shown when lobby is toggled and when join requests are allowed / denied
// 'localRecording.localRecording', // shown when a local recording is started
// 'notify.chatMessages', // shown when receiving chat messages while the chat window is closed
// 'notify.disconnected', // shown when a participant has left
// 'notify.connectedOneMember', // show when a participant joined
// 'notify.connectedTwoMembers', // show when two participants joined simultaneously
// 'notify.connectedThreePlusMembers', // show when more than 2 participants joined simultaneously
// 'notify.leftOneMember', // show when a participant left
// 'notify.leftTwoMembers', // show when two participants left simultaneously
// 'notify.leftThreePlusMembers', // show when more than 2 participants left simultaneously
// 'notify.grantedTo', // shown when moderator rights were granted to a participant
// 'notify.invitedOneMember', // shown when 1 participant has been invited
// 'notify.invitedThreePlusMembers', // shown when 3+ participants have been invited

View File

@@ -1,7 +1,7 @@
/* global APP, JitsiMeetJS, config */
import { jitsiLocalStorage } from '@jitsi/js-utils';
import Logger from '@jitsi/logger';
import Logger from 'jitsi-meet-logger';
import { redirectToTokenAuthService } from './modules/UI/authentication/AuthHandler';
import { LoginDialog } from './react/features/authentication/components';

View File

@@ -24,6 +24,69 @@
bottom: calc(#{$newToolbarSizeWithPadding}) !important;
}
.modal-dialog-form {
/**
* Override @atlaskit/dropdown-menu styling when in a modal because the
* dropdown backgrounds clash with the modal backgrounds.
*/
.dropdown-menu div[style*="transform"] {
outline: 1px solid #455166;
}
.dropdown-menu button:not(:active):not(:hover) > span {
color: #B8C7E0;
}
/**
* Override @atlaskit/tab styling when in a modal because the
* tab text color clash with the modal backgrounds.
*/
div[role="tablist"] > div:not([data-selected]):not(:hover),
label > div > span {
color: #B8C7E0 !important;
}
}
/**
* Override @atlaskit/modal-dialog header styling
*/
.atlaskit-portal [role="dialog"] header {
box-shadow: none;
.jitsi-icon {
cursor: pointer;
}
.jitsi-icon svg {
fill: #B8C7E0;
}
}
/**
* Override @atlaskit/modal-dialog footer styling.
*/
.atlaskit-portal [role="dialog"] footer {
box-shadow: none;
}
/**
* Make header close button more easily tappable on mobile.
*/
.mobile-browser .atlaskit-portal [role="dialog"] header .jitsi-icon {
display: grid;
place-items: center;
height: 48px;
width: 48px;
background: #2a3a4b;
border-radius: 3px;
}
/**
* Override @atlaskit/theme styling for the top toolbar so it displays over
* the video thumbnail while obscuring as little as possible.
*/
.videocontainer__toptoolbar > div > div {
background: none;
}
/**
* Keep overflow menu within screen vertical bounds and make it scrollable.
@@ -95,20 +158,3 @@ div.Tooltip {
line-height: 14px;
padding: 8px;
}
// make modal full screen on landscape orientation
@media (max-height: 420px) {
.atlaskit-portal {
.css-1oc7v0j {
height: 100%;
padding: 0;
max-width: 100%;
top: 0;
width: 100%;
&> div {
height: 100%;
}
}
}
}

View File

@@ -6,10 +6,6 @@
* {
-webkit-user-select: none;
user-select: none;
// Firefox only
scrollbar-width: thin;
scrollbar-color: rgba(0, 0, 0, .5) transparent;
}
input,

View File

@@ -2,39 +2,34 @@
background-color: $chatBackgroundColor;
box-sizing: border-box;
color: #FFF;
display: flex;
flex-direction: column;
height: 100%;
left: -$sidebarWidth;
overflow: hidden;
position: absolute;
top: 0;
width: $sidebarWidth;
z-index: $sideToolbarContainerZ;
@media (max-width: 580px) {
width: 100%;
/**
* The sidebar (chat) is off-screen when hidden. Move it flush to the left
* side of the window when it should be visible.
*/
&.slideInExt {
left: 0;
}
}
.chat-panel {
display: flex;
flex-direction: column;
// extract header + tabs height
height: calc(100% - 102px);
}
.chat-panel-no-tabs {
// extract header height
height: calc(100% - 70px);
}
#chatconversation {
box-sizing: border-box;
flex: 1;
font-size: 10pt;
// extract message input height
height: calc(100% - 68px);
line-height: 20px;
overflow: auto;
padding: 16px;
text-align: left;
width: $sidebarWidth;
word-wrap: break-word;
display: flex;
@@ -63,6 +58,28 @@
a:active {
color: black;
}
&::-webkit-scrollbar {
background: #06a5df;
width: 7px;
}
&::-webkit-scrollbar-button {
display: none;
}
&::-webkit-scrollbar-track {
background: black;
}
&::-webkit-scrollbar-track-piece {
background: black;
}
&::-webkit-scrollbar-thumb {
background: #06a5df;
border-radius: 4px;
}
}
#chat-recipient {
@@ -196,7 +213,6 @@
}
#usermsg {
-ms-overflow-style: none;
border: 0px none;
border-radius:0;
box-shadow: none;
@@ -205,13 +221,8 @@
padding: 10px;
overflow-y: auto;
resize: none;
scrollbar-width: none;
width: 100%;
word-break: break-word;
&::-webkit-scrollbar {
display: none;
}
}
#usermsg:hover {
@@ -302,6 +313,10 @@
text-overflow: ellipsis;
overflow: hidden;
}
@media (max-width: 580px) {
display: none !important;
}
}
.sr-only {
@@ -542,6 +557,11 @@
}
}
.touchmove-hack {
display: flex;
flex: 1;
overflow: auto;
}
/**
* Make header close button more easily tappable on mobile.

View File

@@ -11,6 +11,12 @@
{
@extend %connection-info;
/**
* Apply negative margin to reduce the appearance of padding in AtlasKit
* InlineDialog.
*/
margin: -15px;
> table {
white-space: nowrap;
@extend %connection-info;

View File

@@ -5,10 +5,6 @@
bottom: 0;
z-index: $drawerZ;
border-radius: 16px 16px 0 0;
&.notification-portal {
z-index: $dropdownZ;
}
}
.drawer-portal::after {
@@ -24,9 +20,10 @@
}
.drawer-menu {
max-height: calc(80vh - 64px);
background: #242528;
border-radius: 16px 16px 0 0;
overflow-y: auto;
overflow-y: scroll;
margin-bottom: env(safe-area-inset-bottom, 0);
width: 100%;
@@ -42,6 +39,15 @@
}
}
.popupmenu {
margin: auto;
width: 100%;
}
.popupmenu__item {
height: 48px;
}
&#{&} .overflow-menu {
margin: auto;
font-size: 1.2em;

37
css/_labels.scss Normal file
View File

@@ -0,0 +1,37 @@
.label {
align-items: center;
background: #36383C;
border-radius: 3px;
color: #fff;
display: flex;
font-size: 12px;
font-weight: 600;
height: 28px;
margin: 0 0 4px 4px;
padding: 0 8px;
&--green {
background: #31B76A;
}
&--red {
background: #E34F56
}
&--white {
background: #fff;
color: #5e6d7a;
svg {
fill: #5e6d7a;
}
}
}
.label-text-with-icon {
margin-left: 8px;
}
.participants-count {
cursor: pointer;
}

View File

@@ -1,23 +0,0 @@
.notification-appear, .notification-enter {
opacity: 0;
position: relative;
left: -200px;
transition: all .2s !important; // !important needed to overwrite atlaskit default style
&-active {
opacity: 1;
left: 0;
}
}
.notification-exit {
opacity: 1;
position: relative;
left: 0;
transition: all .2s !important; // !important needed to overwrite atlaskit default style
&-active {
opacity: 0;
left: -200px;
}
}

View File

@@ -56,9 +56,3 @@
border-radius: 3px;
}
}
.mobile-browser.shift-right {
.participants_pane {
z-index: -1;
}
}

View File

@@ -1,7 +1,5 @@
.poll-dialog {
font-size: 14px;
font-weight: 400;
line-height: 20px;
font-size: 1rem;
h1, span, li, strong {
color: #bce;
@@ -18,50 +16,20 @@
}
.poll-header {
margin-bottom: 8px;
padding: 8px 16px;
}
.poll-creator {
color: #C2C2C2;
font-weight: 600;
margin: 4px 0 16px 0;
}
.poll-answer-container {
.poll-answer-container{
padding: 8px;
background: #3D3D3D;
border-radius: 3px;
margin-bottom: 8px;
@media (max-width: 580px) {
&> span {
padding: 8px 0;
}
svg {
margin-top: 6px;
}
}
}
.poll-answer-option {
font-weight: 400;
display: block;
margin: 4px;
@media (max-width: 580px) {
font-size: 16px;
margin: 11px 8px
}
}
.poll-answer-field-list, .poll-answer-list, .poll-result-list {
list-style-type: none;
padding: 0;
margin: 0;
}
.poll-answer-field-list {
padding: 0 16px;
margin: 0;
}
ol.poll-result-list {
@@ -69,7 +37,7 @@ ol.poll-result-list {
}
.poll-result-list > li {
margin-bottom: 16px;
margin-bottom: 8px;
}
.poll-answer-field {
@@ -92,7 +60,7 @@ ol.poll-result-list {
.poll-create-container .jsYMHu {
background: #292929;
border-color: #808090;
color: #fff // #808090
color: white // #808090
}
.poll-add-button {
@@ -104,7 +72,7 @@ ol.poll-result-list {
.poll-remove-option-button {
background: 0 0;
border: none;
color: #E04757;
color: #8B8B8B;
padding-left: 0;
}
@@ -117,7 +85,7 @@ ol.poll-result-list {
.poll-icon-button, .poll-drag-handle {
.jitsi-icon svg {
fill: #929292;
fill: #bce;
}
}
@@ -126,7 +94,6 @@ ol.poll-result-list {
border: none;
cursor: grab;
padding-left: 8;
padding-top: 8px;
display: flex;
}
@@ -138,12 +105,13 @@ ol.poll-result-list {
}
.poll-question {
font-size: 16px;
font-size: 1.2em;
font-weight: 600;
line-height: 26px;
margin-bottom: 0.5em;
}
.poll-answer-voters {
font-size: 1em;
font-weight: lighter;
list-style-type: none;
border: #616161 solid 1px;
@@ -223,36 +191,29 @@ ol.poll-result-list {
display: flex;
flex-direction: row;
justify-content: space-between;
a.poll-detail-link, a.poll-change-vote-link {
color: #669AEC;
cursor: pointer;
font-weight: 600;
text-decoration: none;
&:hover {
color: #669AEC;
}
&:visited {
color: #669AEC;
}
}
}
a.poll-detail-link, a.poll-change-vote-link {
color: #246FE5;
cursor: pointer;
text-decoration: none;
}
.polls-pane-content {
height: 100%;
position: relative;
display: flex;
flex-direction: column;
font-weight: 600;
height: 85%;
align-items: stretch;
}
.pane-content{
display: flex;
flex-direction: column;
height: 100%;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
}
.empty-pane-icon {
@@ -267,41 +228,36 @@ ol.poll-result-list {
}
.empty-pane-message {
color: #fff;
padding: 0 16px;
text-align: center;
}
.poll-results, .poll-answer {
background: #292929;
border-radius: 8px;
border: 1px solid #666666;
margin: 16px;
padding: 16px;
word-break: break-word;
}
.poll-results {
color: #fff;
color: white;
}
.poll-answer {
h1, strong ,span {
color: #fff;
color: white;
}
}
.poll-results, .poll-answer {
margin-bottom: 16px;
background: #292929;
border-radius: 8px;
padding: 12px 8px;
border-width: thin;
border-style: solid;
border-color: #616161;
}
.poll-create-label {
color: #C2C2C2;
display: flex;
font-weight: 400;
color: white;
margin-bottom: 4;
display: flex;
}
.expandable-input{
line-height: 18px;
resize: none;
width: 100%;
height: 40px;
@@ -314,31 +270,24 @@ ol.poll-result-list {
padding: 10px 16px;
}
#polls-panel {
height: calc(100% - 102px);
}
.poll-container {
font-size: 14px;
font-weight: 600;
height: calc(100% - 88px);
line-height: 20px;
box-sizing: border-box;
flex: 1;
overflow-y: auto;
position: relative;
padding: 16px;
& > * + *:not(.ignore-child) {
margin-top: 16px;
}
@media (max-width: 580px) {
height: calc(100% - 102px);
&::-webkit-scrollbar {
display: none;
}
}
.poll-create-header {
color: #fff;
font-size: 20px;
line-height: 28px;
margin: 20px 16px;
font-weight: 600;
}
@@ -347,45 +296,28 @@ ol.poll-result-list {
padding: 8px 0;
}
.poll-create-footer {
background-color: #141414;
bottom: 0;
position: absolute;
width: calc(100% - 32px);
}
.poll-footer {
display: flex;
justify-content: space-between;
padding: 0 16px 16px 16px;
display: flex;
justify-content: flex-end;
padding: 8px 16px;
height: 40px;
align-items: stretch;
& > *:not(:last-child) {
margin-right: 16px;
}
}
.poll-answer-footer {
padding: 8px 0 0 0;
}
.poll-button {
align-items: center;
border: 0;
border-radius: 6px;
font-size: 14px;
font-weight: 600;
display: flex;
justify-content: center;
min-height: 40px;
width: 100%;
&:disabled {
cursor: initial;
}
@media (max-width: 580px) {
min-height: 48px;
}
}
.poll-button-primary {
.poll-primary-button {
align-items: center;
background-color: #0056E0;
border: 0;
border-radius: 6px;
display: flex;
font-weight: unset;
justify-content: center;
font-size: 15px;
flex: 1;
&:hover {
background-color: #246FE5;
@@ -404,10 +336,23 @@ ol.poll-result-list {
background-color: #00225A;
color: #858585;
}
& > *:not(:last-child) {
margin-right: 8px;
}
}
.poll-button-secondary {
.poll-secondary-button {
align-items: center;
background-color: #3D3D3D;
border: 0;
border-radius: 6px;
display: flex;
font-weight: unset;
justify-content: center;
font-size: 15px;
height: 40px;
width: 100%;
&:hover {
background-color: #525252;
@@ -426,19 +371,78 @@ ol.poll-result-list {
background-color: #141414;
color: #858585;
}
& > *:not(:last-child) {
margin-right: 8px;
}
}
.poll-button-short {
max-width: 132px;
.poll-small-primary-button {
align-items: center;
background-color: #0056E0;
border: 0;
border-radius: 6px;
display: flex;
font-weight: unset;
justify-content: center;
font-size: 15px;
height: 40px;
width: 50%;
&:hover {
background-color: #246FE5;
}
&:active {
background-color: #0045B3;
}
&:focus {
background-color: #0045B3;
border: 3px solid #99BBF3;
}
&:disabled {
background-color: #00225A;
color: #858585;
}
& > *:not(:last-child) {
margin-right: 8px;
}
}
.poll-button-shortest {
max-width: 117px;
}
.poll-small-secondary-button {
align-items: center;
background-color: #3D3D3D;
border: 0;
border-radius: 6px;
display: flex;
font-weight: unset;
justify-content: center;
font-size: 15px;
height: 40px;
width: 50%;
.poll-button-short,
.poll-button-shortest {
@media (max-width: 580px) {
min-width: 49%;
}
&:hover {
background-color: #525252;
}
&:active {
background-color: #292929;
}
&:focus {
background-color: #292929;
border: 3px solid #858585;
}
&:disabled {
background-color: #141414;
color: #858585;
}
& > *:not(:last-child) {
margin-right: 8px;
}
}

View File

@@ -3,45 +3,49 @@
* to allow mouse movement from the popover trigger to the popover itself
* without triggering a mouseleave event.
*/
.popover-mousemove-padding-bottom {
bottom: -15px;
height: 20px;
position: absolute;
right: 0;
width: 100%;
}
%vertical-popover-padding {
height: 100%;
position: absolute;
top: 0;
width: 20px;
padding: 20px 0;
top: -20px;
}
%horizontal-popover-padding {
height: 25px;
position: absolute;
right: 0;
width: 100%;
padding: 0 35px;
left: -35px;
width: 40px;
}
.popover-mousemove-padding-left {
@extend %vertical-popover-padding;
left: -35px;
left: -20px;
}
.popover-mousemove-padding-right {
@extend %vertical-popover-padding;
right: -35px;
right: -20px;
}
.popover-mousemove-padding-bottom {
@extend %horizontal-popover-padding;
bottom: -40px;
}
.popover-mousemove-padding-top {
@extend %horizontal-popover-padding;
top: -40px;
/**
* An invisible element is added to the top of the popover to ensure the mouse
* stays over the popover when the popover's height is shrunk, which would then
* normally leave the mouse outside of the popover itself and cause a mouseleave
* event.
*/
.popover-mouse-padding-top {
height: 30px;
position: absolute;
right: 0;
top: -25px;
width: 100%;
}
.popover {
background-color: $popoverBg;
border-radius: 3px;
margin: -16px -24px;
padding: 16px 24px;
z-index: $popoverZ;
}

View File

@@ -2,18 +2,116 @@
* Initialize
**/
.popupmenu__contents {
.popupmenu__volume-slider {
&::-webkit-slider-runnable-track {
background-color: $popupSliderColor;
}
.popupmenu {
background-color: $menuBG;
border-radius: 3px;
min-width: 150px;
text-align: left;
padding: 0px;
white-space: nowrap;
&::-moz-range-track {
background-color: $popupSliderColor;
}
&__item {
list-style-type: none;
height: 35px;
}
&::-ms-fill-lower {
background-color: $popupSliderColor;
// Link Appearance
&__link,
&__contents {
display: block;
box-sizing: border-box;
text-decoration: none;
height: 100%;
font-size: 9pt;
width: 100%;
cursor: pointer;
padding: 0 5px;
color: $popupMenuColor;
&:hover {
background-color: $popupMenuHoverBackground;
color: $popupMenuHoverColor;
}
&.disabled {
pointer-events: none;
}
}
&__text {
display: inline-block;
margin-left: 8px;
vertical-align: middle;
}
&__link {
i {
cursor: pointer;
}
}
&__contents {
display: flex;
/**
* Positioning styles on the slider and its container are used to make
* the container fit the popup width, by removing the slider from the
* page flow, and then making the slider fit the container.
*/
.popupmenu__slider_container {
position: relative;
width: 100%;
.popupmenu__slider {
position: absolute;
top: 50%;
transform: translate(0, -50%);
width: 100%;
&::-webkit-slider-runnable-track {
background-color: $popupSliderColor;
}
&::-moz-range-track {
background-color: $popupSliderColor;
}
&::-ms-fill-lower {
background-color: $popupSliderColor;
}
}
}
}
&__icon {
vertical-align: middle;
position: relative;
display: inline-block;
min-width: 20px;
height: 100%;
padding-right: 10px;
> * {
@include absoluteAligning();
}
}
.icon-kick,
.icon-play,
.icon-stop {
font-size: 8pt;
}
}
/**
* Override reset css styling modifying all lists and set negative margin to
* reduce the visibility of padding on AtlasKit
* InlineDialogs.
*/
ul.popupmenu {
margin: -16px -24px;
}
span.localvideomenu:hover ul.popupmenu, span.remotevideomenu:hover ul.popupmenu, ul.popupmenu:hover {
display:block !important;
}

View File

@@ -8,6 +8,12 @@
padding: 16px;
&.overflow {
width: auto;
padding-bottom: max(env(safe-area-inset-bottom, 0), 16px);
background-color: #141414;
box-shadow: none;
border-radius: 0;
position: relative;
.toolbox-icon {
width: 48px;

View File

@@ -1,25 +1,11 @@
.subject {
color: #fff;
transition: opacity .6s ease-in-out;
margin-top: -120px;
transition: margin-top .3s ease-in;
z-index: $zindex3;
margin-top: 20px;
opacity: 0;
&.visible {
opacity: 1;
}
&#autoHide.with-always-on {
overflow: hidden;
animation: hideSubject forwards .6s ease-out;
& > .subject-info-container {
justify-content: flex-start;
}
&.visible {
animation: showSubject forwards .6s ease-out;
}
margin-top: 20px;
}
}
@@ -50,7 +36,10 @@
line-height: 28px;
padding: 0 16px;
height: 28px;
max-width: 324px;
@media (max-width: 700px) {
max-width: 100px;
}
@media (max-width: 300px) {
display: none;
@@ -85,29 +74,4 @@
position: absolute;
top: 0;
height: 48px;
max-width: calc(100% - 24px);
}
.shift-right .details-container {
margin-left: calc(#{$sidebarWidth} / 2);
}
@keyframes hideSubject {
0% {
max-width: 100%;
}
100% {
max-width: 0;
}
}
@keyframes showSubject {
0% {
max-width: 0%;
}
100% {
max-width: 100%;
}
}

View File

@@ -29,7 +29,6 @@
right: 0;
transition: bottom .3s ease-in;
width: 100%;
pointer-events: none;
&.visible {
@@ -77,6 +76,14 @@
}
}
.toolbox-button {
color: $toolbarButtonColor;
cursor: pointer;
display: inline-block;
line-height: $newToolbarSize;
text-align: center;
}
.toolbar-button-with-badge {
display: inline-block;
position: relative;
@@ -107,6 +114,86 @@
padding-bottom: env(safe-area-inset-bottom, 0);
}
.toolbox-content-items {
background: $newToolbarBackgroundColor;
border-radius: 6px;
margin: 0 auto;
padding: 6px;
text-align: center;
pointer-events: all;
box-shadow: 0px 2px 8px 4px rgba(0, 0, 0, 0.25), 0px 0px 0px 1px rgba(0, 0, 0, 0.15);
>div {
margin-left: 8px;
&:first-child {
margin-left: 0;
}
}
}
.overflow-menu {
font-size: 14px;
list-style-type: none;
padding: 8px 0;
background-color: $menuBG;
.profile-text {
max-width: 150px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
}
.overflow-menu-item {
align-items: center;
color: $overflowMenuItemColor;
cursor: pointer;
display: flex;
font-size: 14px;
font-weight: 400;
height: 40px;
line-height: 24px;
padding: 8px 16px;
box-sizing: border-box;
@media (hover: hover) and (pointer: fine) {
&:hover {
background: $overflowMenuItemBackground;
}
}
div {
display: flex;
flex-direction: row;
align-items: center;
}
&.unclickable {
cursor: default;
}
&.disabled {
cursor: initial;
color: #929292;
&:hover {
background: none;
}
svg {
fill: #929292;
}
}
@media (hover: hover) and (pointer: fine) {
&.unclickable:hover {
background: inherit;
}
}
}
.beta-tag {
background: #36383C;
border-radius: 3px;
@@ -117,12 +204,73 @@
text-transform: uppercase;
}
.overflow-menu-item-icon {
margin-right: 16px;
i {
display: inline;
font-size: 24px;
}
@media (hover: hover) and (pointer: fine) {
i:hover {
background-color: initial;
}
}
img {
max-width: 24px;
max-height: 24px;
}
svg {
fill: #fff;
height: 20px;
width: 20px;
}
}
.overflow-menu-hr {
border-top: 1px solid #4C4D50;
border-bottom: 0;
margin: 8px 0;
}
.toolbox-icon {
display: flex;
border-radius: 3px;
flex-direction: column;
font-size: 24px;
height: $newToolbarSize;
justify-content: center;
width: $newToolbarSize;
@media (hover: hover) and (pointer: fine) {
&:hover {
background: $newToolbarButtonHoverColor;
}
}
@media (max-width: 320px) {
height: 36px;
width: 36px;
}
&.toggled {
background: $newToolbarButtonToggleColor;
}
&.disabled {
cursor: initial !important;
background-color: #36383c !important;
svg {
fill: #929292 !important;
}
}
}
.hangup-button {
background-color: $hangupColor;

View File

@@ -13,6 +13,9 @@ $hangupFontSize: 2em;
*/
// Video layout.
$thumbnailToolbarHeight: 22px;
$thumbnailIndicatorBorder: 2px;
$thumbnailIndicatorSize: $thumbnailToolbarHeight;
$thumbnailVideoMargin: 2px;
$thumbnailsBorder: 2px;
$thumbnailVideoBorder: 2px;
@@ -53,12 +56,19 @@ $overflowMenuItemBackground: #36383C;
/**
* Video layout
*/
$videoThumbnailHovered: rgba(22, 94, 204, .4);
$videoThumbnailSelected: #165ECC;
$participantNameColor: #fff;
$thumbnailPictogramColor: #fff;
$dominantSpeakerBg: #165ecc;
$raiseHandBg: #D6D61E;
$audioLevelBg: #44A5FF;
$connectionIndicatorBg: #165ecc;
$audioLevelShadow: rgba(9, 36, 77, 0.9);
$videoStateIndicatorColor: $defaultColor;
$videoStateIndicatorBackground: $toolbarBackground;
$videoStateIndicatorSize: 40px;
$remoteVideoMenuIconMargin: initial;
/**
* Feedback Modal
@@ -92,6 +102,7 @@ $sidebarWidth: 315px;
* Misc.
*/
$borderRadius: 4px;
$popoverMenuPadding: 13px;
$happySoftwareBackground: transparent;
$desktopAppDragBarHeight: 25px;
$scrollHeight: 7px;
@@ -107,10 +118,11 @@ $toolbarBackgroundZ: 4;
$labelsZ: 5;
$subtitlesZ: 7;
$popoverZ: 8;
$zindex10: 10;
$reloadZ: 20;
$poweredByZ: 100;
$ringingZ: 300;
$sideToolbarContainerZ: 300;
$sideToolbarContainerZ: 200;
$toolbarZ: 250;
$drawerZ: 351;
$tooltipsZ: 401;
@@ -257,4 +269,4 @@ $verySmallScreen: 500px;
* Prejoin / premeeting screen
*/
$prejoinDefaultContentWidth: 336px;
$prejoinDefaultContentWidth: 336px;

View File

@@ -43,7 +43,152 @@
.videocontainer {
position: relative;
text-align: center;
overflow: 'hidden';
&__background {
@include topLeft();
background-color: black;
border-radius: $borderRadius;
width: 100%;
height: 100%;
}
/**
* The toolbar of the video thumbnail.
*/
&__toolbar,
&__toptoolbar {
position: absolute;
left: 0;
pointer-events: none;
z-index: $zindex10;
width: 100%;
box-sizing: border-box; // Includes the padding in the 100% width.
/**
* FIXME (lenny): Disabling pointer-events is a pretty big sin that
* sidesteps the problems. There are z-index wars occurring within
* videocontainer and AtlasKit Tooltips rely on their parent z-indexe
* being higher than whatever they need to appear over. So set a higher
* z-index for the tooltip containers but make any empty space not block
* mouse overs for various mouseover triggers.
*/
pointer-events: none;
* {
pointer-events: auto;
}
.indicator-container {
display: inline-block;
float: left;
pointer-events: all;
}
}
&__toolbar {
bottom: 0;
height: $thumbnailToolbarHeight;
padding: 0 5px 0 5px;
}
&__toptoolbar {
$toolbarIconMargin: 5px;
top: 0;
padding-bottom: 0;
/**
* Override text-align center as icons need to be left justified.
*/
text-align: left;
/**
* Intentionally use margin on the icon itself as AtlasKit InlineDialog
* positioning depends on the trigger (indicator icon).
*/
.indicator {
margin-left: 5px;
margin-top: $toolbarIconMargin;
}
.indicator-container:nth-child(1) .indicator {
margin-left: $toolbarIconMargin;
}
.indicator-container {
display: inline-block;
vertical-align: top;
.popover-trigger {
display: inline-block;
}
}
.connection-indicator,
.indicator {
position: relative;
font-size: 8px;
text-align: center;
line-height: $thumbnailIndicatorSize;
padding: 0;
@include circle($thumbnailIndicatorSize);
box-sizing: border-box;
z-index: $zindex3;
background: $dominantSpeakerBg;
color: $thumbnailPictogramColor;
border: $thumbnailIndicatorBorder solid $thumbnailPictogramColor;
.indicatoricon {
@include absoluteAligning();
}
.connection {
position: relative;
display: inline-block;
margin: 0 auto;
left: 0;
@include transform(translate(0, -50%));
&_empty,
&_lost
{
color: #8B8B8B;/*#FFFFFF*/
overflow: hidden;
}
&_full
{
@include topLeft();
color: #FFFFFF;/*#15A1ED*/
overflow: hidden;
}
&_ninja
{
font-size: 1.5em;
}
}
.icon-gsm-bars {
cursor: pointer;
font-size: 1em;
}
}
.hide-connection-indicator {
display: none;
}
}
&__hoverOverlay {
background: rgba(0,0,0,.6);
border-radius: $borderRadius;
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
visibility: hidden;
z-index: $zindex2;
}
@media (min-width: 581px) {
&.shift-right {
@@ -130,6 +275,29 @@
z-index: $zindex0;
}
/**
* Positions video thumbnail display name and editor.
*/
#alwaysOnTop .displayname,
.videocontainer .displayname,
.videocontainer .editdisplayname {
display: inline-block;
position: absolute;
left: 10%;
width: 80%;
top: 50%;
@include transform(translateY(-40%));
color: $participantNameColor;
text-align: center;
text-overflow: ellipsis;
font-size: 12px;
font-weight: 100;
overflow: hidden;
white-space: nowrap;
line-height: $thumbnailToolbarHeight;
z-index: $zindex2;
}
#alwaysOnTop .displayname {
font-size: 15px;
position: inherit;
@@ -139,6 +307,141 @@
margin-top: 10px;
}
/**
* Positions video thumbnail display name editor.
*/
.videocontainer .editdisplayname {
outline: none;
border: none;
background: none;
box-shadow: none;
padding: 0;
}
#localVideoContainer .displayname:hover {
cursor: text;
}
.videocontainer .displayname {
pointer-events: none;
padding: 0 3px 0 3px;
}
.videocontainer .editdisplayname {
height: auto;
}
#localDisplayName {
pointer-events: auto !important;
}
.videocontainer>a.displayname {
display: inline-block;
position: absolute;
color: #FFFFFF;
bottom: 0;
right: 0;
padding: 3px 5px;
font-size: 9pt;
cursor: pointer;
z-index: $zindex2;
}
/**
* Video thumbnail toolbar icon.
*/
.videocontainer .toolbar-icon {
font-size: 8pt;
text-align: center;
text-shadow: 0px 1px 0px rgba(255,255,255,.3), 0px -1px 0px rgba(0,0,0,.7);
color: #FFFFFF;
width: 12px;
line-height: $thumbnailToolbarHeight;
height: $thumbnailToolbarHeight;
padding: 0;
border: 0;
margin: 0px 5px 0px 0px;
}
/**
* Toolbar icon internal i elements (font icons).
*/
.toolbar-icon>div {
height: $thumbnailToolbarHeight;
display: flex;
flex-direction: column;
justify-content: center;
}
/**
* Toolbar icons positioned on the right.
*/
.moderator-icon {
display: inline-block;
&.right {
float: right;
margin: 0px 0px 0px 5px;
}
.toolbar-icon {
margin: 0;
}
}
.raisehandindicator {
background: $raiseHandBg;
}
.connection-indicator {
background: $connectionIndicatorBg;
&.status-high {
background: green;
}
&.status-med {
background: #FFD740;
}
&.status-lost {
background: gray;
}
&.status-low {
background: #BF2117;
}
&.status-other {
background: $connectionIndicatorBg;
}
}
.local-video-menu-trigger,
.remote-video-menu-trigger,
.localvideomenu,
.remotevideomenu
{
display: inline-block;
position: absolute;
top: 0px;
right: 0;
z-index: $zindex2;
width: 18px;
height: 18px;
color: #FFF;
font-size: 10pt;
margin-right: $remoteVideoMenuIconMargin;
>i{
cursor: hand;
}
}
.local-video-menu-trigger,
.remote-video-menu-trigger {
margin-top: 7px;
}
/**
* Audio indicator on video thumbnails.
*/
@@ -315,11 +618,74 @@
display: none;
}
.display-avatar-with-name {
.avatar-container {
visibility: visible;
}
.displayNameContainer {
visibility: visible;
}
.videocontainer__hoverOverlay {
visibility: visible;
}
video {
visibility: hidden;
}
}
.display-name-on-black {
.avatar-container {
visibility: hidden;
}
.displayNameContainer {
visibility: visible;
}
.videocontainer__hoverOverlay {
visibility: hidden;
}
video {
opacity: 0.2;
visibility: visible;
}
}
.display-video {
.avatar-container {
visibility: hidden;
}
.displayNameContainer {
visibility: hidden;
}
.videocontainer__hoverOverlay {
visibility: hidden;
}
video {
visibility: visible;
}
}
.display-name-on-video {
.avatar-container {
visibility: hidden;
}
.displayNameContainer {
visibility: visible;
}
.videocontainer__hoverOverlay {
visibility: visible;
}
video {
visibility: visible;
}
@@ -330,6 +696,14 @@
visibility: visible;
}
.displayNameContainer {
visibility: hidden;
}
.videocontainer__hoverOverlay {
visibility: hidden;
}
video {
visibility: hidden;
}

38
css/buttons/copy.scss Normal file
View File

@@ -0,0 +1,38 @@
.copy-button {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 8px 8px 16px;
margin-top: 5px;
width: calc(100% - 24px);
height: 24px;
background: #0376DA;
border-radius: 4px;
cursor: pointer;
&:hover {
background: #278ADF;
font-weight: 600;
}
&-content {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 292px;
margin-right: 16px;
&.selected {
font-weight: 600;
}
}
&.clicked {
background: #31B76A;
}
& > div > svg > path {
fill: #fff;
}
}

View File

@@ -63,8 +63,6 @@
}
.remote-videos {
overscroll-behavior: contain;
& > div {
transition: opacity 1s;
position: absolute;

View File

@@ -6,10 +6,37 @@
border-radius: $borderRadius;
margin: 0 $thumbnailVideoMargin;
&:hover {
&.videoContainerFocused, &:hover {
cursor: hand;
}
/**
* Focused video thumbnail.
*/
&.videoContainerFocused {
border: $thumbnailVideoBorder solid $videoThumbnailSelected;
box-shadow: inset 0 0 3px $videoThumbnailSelected,
0 0 3px $videoThumbnailSelected;
}
.remotevideomenu > .icon-menu, .localvideomenu > .icon-menu {
display: none;
}
/**
* Hovered video thumbnail.
*/
&:hover:not(.videoContainerFocused):not(.active-speaker) {
cursor: hand;
border: $thumbnailVideoBorder solid $videoThumbnailHovered;
box-shadow: inset 0 0 3px $videoThumbnailHovered,
0 0 3px $videoThumbnailHovered;
.remotevideomenu > .icon-menu, .localvideomenu > .icon-menu {
display: inline-block;
}
}
& > video {
cursor: hand;
border-radius: $borderRadius;

View File

@@ -2,13 +2,19 @@
* CSS styles that are specific to the filmstrip that shows the thumbnail tiles.
*/
.tile-view {
/**
* Add a border around the active speaker to make the thumbnail easier to
* see.
*/
.active-speaker {
box-shadow: 0px 0px 1px 1.5px black, 0px 0px 1.3px 4px $videoThumbnailSelected;
}
.remote-videos {
align-items: center;
box-sizing: border-box;
display: flex;
flex-direction: column;
overscroll-behavior: contain;
}
.filmstrip__videos .videocontainer {
@@ -99,6 +105,19 @@
display: block;
margin: 2px;
}
video {
object-fit: contain;
}
/**
* Max-width corresponding to the ASPECT_RATIO_BREAKPOINT from features/filmstrip/constants.
*/
@media only screen and (max-width: 500px) {
video {
object-fit: cover;
}
}
}
}
}
@@ -114,3 +133,7 @@
}
}
}
.indicator-icon-container {
display: inline-block;
}

View File

@@ -35,4 +35,16 @@
#remotePresenceMessage {
display: none !important;
}
/**
* Thumbnail popover menus can overlap other thumbnails. Setting an auto
* z-index will allow AtlasKit InlineDialog's large z-index to be
* respected and thereby display over elements in other thumbnails,
* specifically the various status icons.
*/
.remotevideomenu,
.localvideomenu,
.videocontainer__toptoolbar {
z-index: auto;
}
}

View File

@@ -114,7 +114,6 @@
.remote-videos {
display: flex;
transition: height .3s ease-in;
overscroll-behavior: contain;
& > div {
position: absolute;

View File

@@ -19,6 +19,72 @@
* Overrides for small videos in vertical filmstrip mode.
*/
.vertical-filmstrip .filmstrip__videos .videocontainer {
/**
* Move status icons to the bottom right of the thumbnail.
*/
.videocontainer__toolbar {
/**
* FIXME: disable pointer to allow any elements moved below to still
* be clickable. The real fix would to make sure those moved elements
* are actually part of the toolbar instead of positioning being faked.
*/
pointer-events: none;
text-align: right;
> div {
pointer-events: none;
}
.right {
float: none;
margin: auto;
}
.toolbar-icon {
pointer-events: all;
}
}
/**
* Apply hardware acceleration to prevent flickering on scroll. The
* selectors are specific to icon wrappers to prevent fixed position dialogs
* and tooltips from getting a new location context due to translate3d.
*/
.connection-indicator,
.local-video-menu-trigger,
.remote-video-menu-trigger,
.indicator-icon-container {
transform: translate3d(0, 0, 0);
}
.indicator-icon-container {
display: inline-block;
}
.indicator-container {
float: none;
}
/**
* Move the remote video menu trigger to the bottom left of the video
* thumbnail.
*/
.localvideomenu,
.remotevideomenu,
.local-video-menu-trigger,
.remote-video-menu-trigger {
bottom: 0;
left: 0;
top: auto;
right: auto;
}
.local-video-menu-trigger,
.remote-video-menu-trigger {
margin-bottom: 3px;
margin-left: $remoteVideoMenuIconMargin;
}
.self-view-mobile-portrait video {
object-fit: contain;
}

View File

@@ -33,6 +33,7 @@ $flagsImagePath: "../images/";
@import 'inlay';
@import 'reload_overlay/reload_overlay';
@import 'mini_toolbox';
@import 'buttons/copy.scss';
@import 'modals/desktop-picker/desktop-picker';
@import 'modals/device-selection/device-selection';
@import 'modals/dialog';
@@ -43,6 +44,7 @@ $flagsImagePath: "../images/";
@import 'modals/screen-share/share-audio';
@import 'modals/screen-share/share-screen-warning';
@import 'modals/speaker_stats/speaker_stats';
@import 'modals/video-quality/video-quality';
@import 'modals/virtual-background/virtual-background';
@import 'modals/local-recording/local-recording';
@import 'videolayout_default';
@@ -76,6 +78,7 @@ $flagsImagePath: "../images/";
@import 'filmstrip/tile_view_overrides';
@import 'filmstrip/vertical_filmstrip';
@import 'filmstrip/vertical_filmstrip_overrides';
@import 'labels';
@import 'unsupported-browser/main';
@import 'modals/invite/add-people';
@import 'deep-linking/main';
@@ -103,6 +106,5 @@ $flagsImagePath: "../images/";
@import 'reactions-menu';
@import 'plan-limit';
@import 'polls';
@import 'notifications';
/* Modules END */

View File

@@ -122,6 +122,9 @@
margin-bottom: 8px;
}
}
.modal-dialog-footer {
font-size: $modalButtonFontSize;
}
/**
* Styling inline dialog errors.

View File

@@ -48,7 +48,7 @@
}
.profile-edit-field {
flex: .5;
flex: 1;
}
.settings-sub-pane {
flex: 1;
@@ -65,11 +65,6 @@
text-align: left;
flex: 1;
}
.moderator-settings-wrapper {
padding-top: 20px;
}
.profile-edit-field {
margin-right: 20px;
}

View File

@@ -27,10 +27,7 @@
.speaker-stats-item__status,
.speaker-stats-item__name,
.speaker-stats-item__time,
.speaker-stats-item__name_expressions_on,
.speaker-stats-item__time_expressions_on,
.speaker-stats-item__expression {
.speaker-stats-item__time {
display: inline-block;
margin: 5px 0;
vertical-align: middle;
@@ -44,35 +41,9 @@
.speaker-stats-item__time {
width: 55%;
}
.speaker-stats-item__name_expressions_on {
width: 20%;
}
.speaker-stats-item__time_expressions_on {
width: 25%;
}
.speaker-stats-item__expression {
width: 7%;
text-align: center;
}
@media(max-width: 750px) {
.speaker-stats-item__name_expressions_on {
width: 25%;
}
.speaker-stats-item__time_expressions_on {
width: 30%;
}
.speaker-stats-item__expression {
width: 10%;
}
}
.speaker-stats-item__name,
.speaker-stats-item__time,
.speaker-stats-item__name_expressions_on,
.speaker-stats-item__time_expressions_on,
.speaker-stats-item__expression {
.speaker-stats-item__time {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;

View File

@@ -0,0 +1,114 @@
.video-quality-dialog {
.video-quality-dialog-title {
margin-bottom: 10px;
}
.video-quality-dialog-contents {
align-items: center;
display: flex;
flex-direction: column;
padding: 10px;
min-width: 250px;
.video-quality-dialog-slider-container {
width: 100%;
text-align: center;
}
.video-quality-dialog-slider {
width: calc(100% - 5px);
@mixin sliderTrackStyles() {
height: 15px;
border-radius: 10px;
background: rgb(14, 22, 36);
}
&::-ms-track {
@include sliderTrackStyles();
}
&::-moz-range-track {
@include sliderTrackStyles();
}
&::-webkit-slider-runnable-track {
@include sliderTrackStyles();
}
@mixin sliderThumbStyles() {
top: 50%;
border: none;
position: relative;
opacity: 0;
}
&::-ms-thumb {
@include sliderThumbStyles();
}
&::-moz-range-thumb {
@include sliderThumbStyles();
}
&::-webkit-slider-thumb {
@include sliderThumbStyles();
}
}
.video-quality-dialog-labels {
box-sizing: border-box;
display: flex;
margin-top: 5px;
position: relative;
width: 90%;
}
.video-quality-dialog-label-container {
position: absolute;
text-align: center;
transform: translate(-50%, 0%);
&::before {
content: '';
border-radius: 50%;
left: 0;
height: 6px;
margin: 0 auto;
pointer-events: none;
position: absolute;
right: 0;
top: -16px;
width: 6px;
}
}
.video-quality-dialog-label-container.active {
color: $videoQualityActive;
font-weight: bold;
&::before {
background: $videoQualityActive;
height: 12px;
top: -19px;
width: 12px;
}
}
.video-quality-dialog-label-container:first-child {
position: relative;
}
.video-quality-dialog-label {
display: table-caption;
word-spacing: unset;
}
}
}
.modal-dialog-form {
.video-quality-dialog-title {
display: none;
}
}

View File

@@ -21,6 +21,7 @@
.prejoin-preview {
&-dropdown-btns {
padding: 8px 0;
width: calc(100% - 48px);
}
&-dropdown-btn {
@@ -58,6 +59,8 @@
background: #fff;
padding: 0;
position: absolute !important;
top: 48px !important;
transform: none !important;
width: 100%;
}
}

View File

@@ -138,6 +138,7 @@
.toolbox-content-items {
background: transparent;
border-radius: 0;
box-shadow: none;
display: flex;
justify-content: space-evenly;
@@ -170,19 +171,6 @@
}
}
// mobile phone landscape
@media (max-height: 420px) {
flex-direction: row;
div.content {
padding: 16px 16px 0 16px;
}
.con-status {
display: none;
}
}
@media (max-width: 400px) {
.content {
padding: 16px;
@@ -238,6 +226,8 @@
.avatar {
text {
fill: white;
font-size: 26px;
font-weight: 400;
}
}

View File

@@ -75,7 +75,11 @@ $errorColor: #c61600;
$feedbackCancelFontColor: #333;
// Popover colors
$popoverBg: initial;
$popoverFontColor: #ffffff !important;
$popupMenuColor: #ffffff !important;
$popupMenuHoverColor: #ffffff !important;
$popupMenuHoverBackground: rgba(255, 255, 255, 0.1);
$popupSliderColor: #0376da;
// Toolbar

View File

@@ -130,8 +130,6 @@ case "$1" in
echo -e " storage = \"memory\"" >> $PROSODY_HOST_CONFIG
echo -e " modules_enabled = { \"ping\"; }" >> $PROSODY_HOST_CONFIG
echo -e " admins = { \"$JICOFO_AUTH_USER@$JICOFO_AUTH_DOMAIN\", \"jvb@$JICOFO_AUTH_DOMAIN\" }" >> $PROSODY_HOST_CONFIG
echo -e " muc_room_locking = false" >> $PROSODY_HOST_CONFIG
echo -e " muc_room_default_public_jids = true" >> $PROSODY_HOST_CONFIG
fi
# Convert the old focus component config to the new one.

View File

@@ -61,7 +61,7 @@ case "$1" in
sed -i '/^\s*--\s*"token_verification"/ s/--\s*//' $PROSODY_HOST_CONFIG
# Install luajwt
if ! luarocks install luajwtjitsi 2.0-0; then
if ! luarocks install luajwtjitsi; then
echo "Failed to install luajwtjitsi - try installing it manually"
fi

View File

@@ -52,12 +52,10 @@ VirtualHost "jitmeet.example.com"
"external_services";
"conference_duration";
"muc_lobby_rooms";
"muc_breakout_rooms";
"av_moderation";
}
c2s_require_encryption = false
lobby_muc = "lobby.jitmeet.example.com"
breakout_rooms_muc = "breakout.jitmeet.example.com"
main_muc = "conference.jitmeet.example.com"
-- muc_lobby_whitelist = { "recorder.jitmeet.example.com" } -- Here we can whitelist jibri to enter lobby enabled rooms
@@ -69,20 +67,6 @@ Component "conference.jitmeet.example.com" "muc"
"muc_domain_mapper";
"polls";
--"token_verification";
"muc_rate_limit";
}
admins = { "focusUser@auth.jitmeet.example.com" }
muc_room_locking = false
muc_room_default_public_jids = true
Component "breakout.jitmeet.example.com" "muc"
restrict_room_creation = true
storage = "memory"
modules_enabled = {
"muc_meeting_id";
"muc_domain_mapper";
--"token_verification";
"muc_rate_limit";
}
admins = { "focusUser@auth.jitmeet.example.com" }
muc_room_locking = false
@@ -122,7 +106,3 @@ Component "lobby.jitmeet.example.com" "muc"
restrict_room_creation = true
muc_room_locking = false
muc_room_default_public_jids = true
modules_enabled = {
"muc_rate_limit";
"polls";
}

View File

@@ -32,12 +32,4 @@ denied-peer-ip=198.18.0.0-198.19.255.255
denied-peer-ip=198.51.100.0-198.51.100.255
denied-peer-ip=203.0.113.0-203.0.113.255
denied-peer-ip=240.0.0.0-255.255.255.255
denied-peer-ip=::1
denied-peer-ip=64:ff9b::-64:ff9b::ffff:ffff
denied-peer-ip=::ffff:0.0.0.0-::ffff:255.255.255.255
denied-peer-ip=100::-100::ffff:ffff:ffff:ffff
denied-peer-ip=2001::-2001:1ff:ffff:ffff:ffff:ffff:ffff:ffff
denied-peer-ip=2002::-2002:ffff:ffff:ffff:ffff:ffff:ffff:ffff
denied-peer-ip=fc00::-fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
denied-peer-ip=fe80::-febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff
syslog

View File

@@ -0,0 +1,8 @@
var config = {
hosts: {
domain: 'jitsi.example.com',
muc: 'conference.jitsi.example.com', // FIXME: use XEP-0030
bridge: 'jitsi-videobridge.jitsi.example.com' // FIXME: use XEP-0030
},
bosh: '//jitsi.example.com/http-bind' // FIXME: use xep-0156 for that
};

View File

@@ -0,0 +1,39 @@
server {
listen 80;
server_name jitsi.example.com;
# set the root
root /srv/jitsi.example.com;
index index.html;
location ~ ^/([a-zA-Z0-9=\?]+)$ {
rewrite ^/(.*)$ / break;
}
location / {
ssi on;
}
gzip on;
gzip_types text/plain text/css application/javascript application/json image/x-icon application/octet-stream application/wasm;
gzip_vary on;
gzip_proxied no-cache no-store private expired auth;
gzip_min_length 512;
# BOSH
location /http-bind {
proxy_pass http://localhost:5280/http-bind;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
}
# xmpp websockets
location /xmpp-websocket {
proxy_pass http://localhost:5280/xmpp-websocket;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
tcp_nodelay on;
}
}

View File

@@ -0,0 +1,14 @@
var subdomain = "<!--# echo var="subdomain" default="" -->";
if (subdomain) {
subdomain = subdomain.substr(0,subdomain.length-1).split('.').join('_').toLowerCase() + '.';
}
var config = {
hosts: {
domain: 'jitsi.example.com',
muc: 'conference.'+subdomain+'jitsi.example.com', // FIXME: use XEP-0030
focus: 'focus.jitsi.example.com',
},
bosh: '//jitsi.example.com/http-bind', // FIXME: use xep-0156 for that
websocket: 'wss://jitsi.example.com/xmpp-websocket'
};

View File

@@ -0,0 +1,76 @@
server {
listen 80;
server_name jitsi.example.com;
# set the root
root /srv/jitsi.example.com;
# ssi on with javascript for multidomain variables in config.js
ssi on;
ssi_types application/x-javascript application/javascript;
index index.html;
set $prefix "";
# BOSH
location /http-bind {
proxy_pass http://localhost:5280/http-bind;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
}
# xmpp websockets
location /xmpp-websocket {
proxy_pass http://localhost:5280/xmpp-websocket;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
tcp_nodelay on;
}
gzip on;
gzip_types text/plain text/css application/javascript application/json image/x-icon application/octet-stream application/wasm;
gzip_vary on;
gzip_proxied no-cache no-store private expired auth;
gzip_min_length 512;
location ~ ^/([^/?&:'"]+)$ {
try_files $uri @root_path;
}
location @root_path {
rewrite ^/(.*)$ / break;
}
location ~ ^/([^/?&:'"]+)/config.js$
{
set $subdomain "$1.";
set $subdir "$1/";
alias /etc/jitsi/meet/{{jitsi_meet_domain_name}}-config.js;
}
# Anything that didn't match above, and isn't a real file, assume it's a room name and redirect to /
location ~ ^/([^/?&:'"]+)/(.*)$ {
set $subdomain "$1.";
set $subdir "$1/";
rewrite ^/([^/?&:'"]+)/(.*)$ /$2;
}
# BOSH for subdomains
location ~ ^/([^/?&:'"]+)/http-bind {
set $subdomain "$1.";
set $subdir "$1/";
set $prefix "$1";
rewrite ^/(.*)$ /http-bind;
}
# websockets for subdomains
location ~ ^/([^/?&:'"]+)/xmpp-websocket {
set $subdomain "$1.";
set $subdir "$1/";
set $prefix "$1";
rewrite ^/(.*)$ /xmpp-websocket;
}
}

View File

@@ -0,0 +1,218 @@
-- Prosody XMPP Server Configuration
--
-- Information on configuring Prosody can be found on our
-- website at http://prosody.im/doc/configure
--
-- Tip: You can check that the syntax of this file is correct
-- when you have finished by running: prosodyctl check config
-- If there are any errors, it will let you know what and where
-- they are, otherwise it will keep quiet.
--
-- Good luck, and happy Jabbering!
---------- Server-wide settings ----------
-- Settings in this section apply to the whole server and are the default settings
-- for any virtual hosts
-- This is a (by default, empty) list of accounts that are admins
-- for the server. Note that you must create the accounts separately
-- (see http://prosody.im/doc/creating_accounts for info)
-- Example: admins = { "user1@example.com", "user2@example.net" }
admins = { }
daemonize = true
cross_domain_bosh = true;
component_ports = { 5347 }
--component_interface = "192.168.0.10"
-- Enable use of libevent for better performance under high load
-- For more information see: http://prosody.im/doc/libevent
--use_libevent = true
-- This is the list of modules Prosody will load on startup.
-- It looks for mod_modulename.lua in the plugins folder, so make sure that exists too.
-- Documentation on modules can be found at: http://prosody.im/doc/modules
modules_enabled = {
-- Generally required
"roster"; -- Allow users to have a roster. Recommended ;)
"saslauth"; -- Authentication for clients and servers. Recommended if you want to log in.
"tls"; -- Add support for secure TLS on c2s/s2s connections
"dialback"; -- s2s dialback support
"disco"; -- Service discovery
"posix"; -- POSIX functionality, sends server to background, enables syslog, etc.
-- Not essential, but recommended
"private"; -- Private XML storage (for room bookmarks, etc.)
"vcard"; -- Allow users to set vCards
-- These are commented by default as they have a performance impact
--"privacy"; -- Support privacy lists
"compression"; -- Stream compression (requires the lua-zlib package installed)
-- Nice to have
"version"; -- Replies to server version requests
"uptime"; -- Report how long server has been running
"time"; -- Let others know the time here on this server
"ping"; -- Replies to XMPP pings with pongs
"pep"; -- Enables users to publish their mood, activity, playing music and more
"register"; -- Allow users to register on this server using a client and change passwords
-- Admin interfaces
"admin_adhoc"; -- Allows administration via an XMPP client that supports ad-hoc commands
--"admin_telnet"; -- Opens telnet console interface on localhost port 5582
-- HTTP modules
"bosh"; -- Enable BOSH clients, aka "Jabber over HTTP"
--"http_files"; -- Serve static files from a directory over HTTP
-- Other specific functionality
--"groups"; -- Shared roster support
--"announce"; -- Send announcement to all online users
--"welcome"; -- Welcome users who register accounts
--"watchregistrations"; -- Alert admins of registrations
--"motd"; -- Send a message to users when they log in
--"legacyauth"; -- Legacy authentication. Only used by some old clients and bots.
-- jitsi
"smacks";
"carbons";
"mam";
"lastactivity";
"offline";
"pubsub";
"adhoc";
"websocket";
"http_altconnect";
}
-- domain mapper options, must at least have domain base set to use the mapper
muc_mapper_domain_base = "jitsi.example.com";
-- These modules are auto-loaded, but should you want
-- to disable them then uncomment them here:
modules_disabled = {
--"offline"; -- Store offline messages
--"c2s"; -- Handle client connections
--"s2s"; -- Handle server-to-server connections
}
-- Disable account creation by default, for security
-- For more information see http://prosody.im/doc/creating_accounts
allow_registration = false
-- These are the SSL/TLS-related settings. If you don't want
-- to use SSL/TLS, you may comment or remove this
ssl = {
key = "/etc/prosody/certs/localhost.key";
certificate = "/etc/prosody/certs/localhost.crt";
}
-- Force clients to use encrypted connections? This option will
-- prevent clients from authenticating unless they are using encryption.
--c2s_require_encryption = true
-- Force certificate authentication for server-to-server connections?
-- This provides ideal security, but requires servers you communicate
-- with to support encryption AND present valid, trusted certificates.
-- NOTE: Your version of LuaSec must support certificate verification!
-- For more information see http://prosody.im/doc/s2s#security
--s2s_secure_auth = false
-- Many servers don't support encryption or have invalid or self-signed
-- certificates. You can list domains here that will not be required to
-- authenticate using certificates. They will be authenticated using DNS.
--s2s_insecure_domains = { "gmail.com" }
-- Even if you leave s2s_secure_auth disabled, you can still require valid
-- certificates for some domains by specifying a list here.
--s2s_secure_domains = { "jabber.org" }
-- Required for init scripts and prosodyctl
pidfile = "/var/run/prosody/prosody.pid"
-- Select the authentication backend to use. The 'internal' providers
-- use Prosody's configured data storage to store the authentication data.
-- To allow Prosody to offer secure authentication mechanisms to clients, the
-- default provider stores passwords in plaintext. If you do not trust your
-- server please see http://prosody.im/doc/modules/mod_auth_internal_hashed
-- for information about using the hashed backend.
authentication = "internal_hashed"
-- Select the storage backend to use. By default Prosody uses flat files
-- in its configured data directory, but it also supports more backends
-- through modules. An "sql" backend is included by default, but requires
-- additional dependencies. See http://prosody.im/doc/storage for more info.
--storage = "sql" -- Default is "internal"
-- For the "sql" backend, you can uncomment *one* of the below to configure:
--sql = { driver = "SQLite3", database = "prosody.sqlite" } -- Default. 'database' is the filename.
--sql = { driver = "MySQL", database = "prosody", username = "prosody", password = "secret", host = "localhost" }
--sql = { driver = "PostgreSQL", database = "prosody", username = "prosody", password = "secret", host = "localhost" }
-- Logging configuration
-- For advanced logging see http://prosody.im/doc/logging
log = {
info = "/var/log/prosody/prosody.log"; -- Change 'info' to 'debug' for verbose logging
error = "/var/log/prosody/prosody.err";
"*syslog";
}
----------- Virtual hosts -----------
-- You need to add a VirtualHost entry for each domain you wish Prosody to serve.
-- Settings under each VirtualHost entry apply *only* to that host.
--VirtualHost "localhost"
VirtualHost "jitsi.example.com"
-- enabled = false -- Remove this line to enable this host
authentication = "anonymous"
-- Assign this host a certificate for TLS, otherwise it would use the one
-- set in the global section (if any).
-- Note that old-style SSL on port 5223 only supports one certificate, and will always
-- use the global one.
ssl = {
key = "/var/lib/prosody/jitsi.example.com.key";
certificate = "/var/lib/prosody/jitsi.example.com.crt";
}
c2s_require_encryption = false
VirtualHost "auth.jitsi.example.com"
ssl = {
key = "/var/lib/prosody/auth.jitsi.example.com.key";
certificate = "/var/lib/prosody/auth.jitsi.example.com.crt";
}
authentication = "internal_hashed"
------ Components ------
-- You can specify components to add hosts that provide special services,
-- like multi-user conferences, and transports.
-- For more information on components, see http://prosody.im/doc/components
---Set up a MUC (multi-user chat) room server on conference.example.com:
--Component "conference.example.com" "muc"
-- Set up a SOCKS5 bytestream proxy for server-proxied file transfers:
--Component "proxy.example.com" "proxy65"
---Set up an external component (default component port is 5347)
--
-- External components allow adding various services, such as gateways/
-- transports to other networks like ICQ, MSN and Yahoo. For more info
-- see: http://prosody.im/doc/components#adding_an_external_component
--
--Component "gateway.example.com"
-- component_secret = "password"
Component "conference.jitsi.example.com" "muc"
modules_enabled = { "muc_domain_mapper" }
Component "jitsi-videobridge.jitsi.example.com"
component_secret = "IfGaish6"

View File

@@ -0,0 +1,54 @@
user www-data;
worker_processes 1;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
# multi_accept on;
}
http {
include /etc/nginx/mime.types;
access_log /var/log/nginx/access.log;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
tcp_nodelay on;
tcp_nopush on;
types_hash_max_size 2048;
server_names_hash_bucket_size 64;
gzip on;
gzip_disable "MSIE [1-6]\.(?!.*SV1)";
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
# mail {
# # See sample authentication script at:
# # http://wiki.nginx.org/NginxImapAuthenticateWithApachePhpScript
#
# # auth_http localhost/auth.php;
# # pop3_capabilities "TOP" "USER";
# # imap_capabilities "IMAP4rev1" "UIDPLUS";
#
# server {
# listen localhost:110;
# protocol pop3;
# proxy on;
# }
#
# server {
# listen localhost:143;
# protocol imap;
# proxy on;
# }
# }

View File

@@ -0,0 +1,214 @@
-- Prosody XMPP Server Configuration
--
-- Information on configuring Prosody can be found on our
-- website at http://prosody.im/doc/configure
--
-- Tip: You can check that the syntax of this file is correct
-- when you have finished by running: prosodyctl check config
-- If there are any errors, it will let you know what and where
-- they are, otherwise it will keep quiet.
--
-- Good luck, and happy Jabbering!
---------- Server-wide settings ----------
-- Settings in this section apply to the whole server and are the default settings
-- for any virtual hosts
-- This is a (by default, empty) list of accounts that are admins
-- for the server. Note that you must create the accounts separately
-- (see http://prosody.im/doc/creating_accounts for info)
-- Example: admins = { "user1@example.com", "user2@example.net" }
admins = { }
daemonize = true
cross_domain_bosh = true;
component_ports = { 5347 }
--component_interface = "192.168.0.10"
-- Enable use of libevent for better performance under high load
-- For more information see: http://prosody.im/doc/libevent
--use_libevent = true
-- This is the list of modules Prosody will load on startup.
-- It looks for mod_modulename.lua in the plugins folder, so make sure that exists too.
-- Documentation on modules can be found at: http://prosody.im/doc/modules
modules_enabled = {
-- Generally required
"roster"; -- Allow users to have a roster. Recommended ;)
"saslauth"; -- Authentication for clients and servers. Recommended if you want to log in.
"tls"; -- Add support for secure TLS on c2s/s2s connections
"dialback"; -- s2s dialback support
"disco"; -- Service discovery
"posix"; -- POSIX functionality, sends server to background, enables syslog, etc.
-- Not essential, but recommended
"private"; -- Private XML storage (for room bookmarks, etc.)
"vcard"; -- Allow users to set vCards
-- These are commented by default as they have a performance impact
--"privacy"; -- Support privacy lists
"compression"; -- Stream compression (requires the lua-zlib package installed)
-- Nice to have
"version"; -- Replies to server version requests
"uptime"; -- Report how long server has been running
"time"; -- Let others know the time here on this server
"ping"; -- Replies to XMPP pings with pongs
"pep"; -- Enables users to publish their mood, activity, playing music and more
"register"; -- Allow users to register on this server using a client and change passwords
-- Admin interfaces
"admin_adhoc"; -- Allows administration via an XMPP client that supports ad-hoc commands
--"admin_telnet"; -- Opens telnet console interface on localhost port 5582
-- HTTP modules
"bosh"; -- Enable BOSH clients, aka "Jabber over HTTP"
--"http_files"; -- Serve static files from a directory over HTTP
-- Other specific functionality
--"groups"; -- Shared roster support
--"announce"; -- Send announcement to all online users
--"welcome"; -- Welcome users who register accounts
--"watchregistrations"; -- Alert admins of registrations
--"motd"; -- Send a message to users when they log in
--"legacyauth"; -- Legacy authentication. Only used by some old clients and bots.
-- jitsi
"smacks";
"carbons";
"mam";
"lastactivity";
"offline";
"pubsub";
"adhoc";
"websocket";
"http_altconnect";
}
-- These modules are auto-loaded, but should you want
-- to disable them then uncomment them here:
modules_disabled = {
--"offline"; -- Store offline messages
--"c2s"; -- Handle client connections
--"s2s"; -- Handle server-to-server connections
}
-- Disable account creation by default, for security
-- For more information see http://prosody.im/doc/creating_accounts
allow_registration = false
-- These are the SSL/TLS-related settings. If you don't want
-- to use SSL/TLS, you may comment or remove this
ssl = {
key = "/etc/prosody/certs/localhost.key";
certificate = "/etc/prosody/certs/localhost.crt";
}
-- Force clients to use encrypted connections? This option will
-- prevent clients from authenticating unless they are using encryption.
--c2s_require_encryption = true
-- Force certificate authentication for server-to-server connections?
-- This provides ideal security, but requires servers you communicate
-- with to support encryption AND present valid, trusted certificates.
-- NOTE: Your version of LuaSec must support certificate verification!
-- For more information see http://prosody.im/doc/s2s#security
--s2s_secure_auth = false
-- Many servers don't support encryption or have invalid or self-signed
-- certificates. You can list domains here that will not be required to
-- authenticate using certificates. They will be authenticated using DNS.
--s2s_insecure_domains = { "gmail.com" }
-- Even if you leave s2s_secure_auth disabled, you can still require valid
-- certificates for some domains by specifying a list here.
--s2s_secure_domains = { "jabber.org" }
-- Required for init scripts and prosodyctl
pidfile = "/var/run/prosody/prosody.pid"
-- Select the authentication backend to use. The 'internal' providers
-- use Prosody's configured data storage to store the authentication data.
-- To allow Prosody to offer secure authentication mechanisms to clients, the
-- default provider stores passwords in plaintext. If you do not trust your
-- server please see http://prosody.im/doc/modules/mod_auth_internal_hashed
-- for information about using the hashed backend.
authentication = "internal_hashed"
-- Select the storage backend to use. By default Prosody uses flat files
-- in its configured data directory, but it also supports more backends
-- through modules. An "sql" backend is included by default, but requires
-- additional dependencies. See http://prosody.im/doc/storage for more info.
--storage = "sql" -- Default is "internal"
-- For the "sql" backend, you can uncomment *one* of the below to configure:
--sql = { driver = "SQLite3", database = "prosody.sqlite" } -- Default. 'database' is the filename.
--sql = { driver = "MySQL", database = "prosody", username = "prosody", password = "secret", host = "localhost" }
--sql = { driver = "PostgreSQL", database = "prosody", username = "prosody", password = "secret", host = "localhost" }
-- Logging configuration
-- For advanced logging see http://prosody.im/doc/logging
log = {
info = "/var/log/prosody/prosody.log"; -- Change 'info' to 'debug' for verbose logging
error = "/var/log/prosody/prosody.err";
"*syslog";
}
----------- Virtual hosts -----------
-- You need to add a VirtualHost entry for each domain you wish Prosody to serve.
-- Settings under each VirtualHost entry apply *only* to that host.
--VirtualHost "localhost"
VirtualHost "jitsi.example.com"
-- enabled = false -- Remove this line to enable this host
authentication = "anonymous"
-- Assign this host a certificate for TLS, otherwise it would use the one
-- set in the global section (if any).
-- Note that old-style SSL on port 5223 only supports one certificate, and will always
-- use the global one.
ssl = {
key = "/var/lib/prosody/jitsi.example.com.key";
certificate = "/var/lib/prosody/jitsi.example.com.crt";
}
c2s_require_encryption = false
VirtualHost "auth.jitsi.example.com"
ssl = {
key = "/var/lib/prosody/auth.jitsi.example.com.key";
certificate = "/var/lib/prosody/auth.jitsi.example.com.crt";
}
authentication = "internal_hashed"
------ Components ------
-- You can specify components to add hosts that provide special services,
-- like multi-user conferences, and transports.
-- For more information on components, see http://prosody.im/doc/components
---Set up a MUC (multi-user chat) room server on conference.example.com:
--Component "conference.example.com" "muc"
-- Set up a SOCKS5 bytestream proxy for server-proxied file transfers:
--Component "proxy.example.com" "proxy65"
---Set up an external component (default component port is 5347)
--
-- External components allow adding various services, such as gateways/
-- transports to other networks like ICQ, MSN and Yahoo. For more info
-- see: http://prosody.im/doc/components#adding_an_external_component
--
--Component "gateway.example.com"
-- component_secret = "password"
Component "conference.jitsi.example.com" "muc"
Component "jitsi-videobridge.jitsi.example.com"
component_secret = "IfGaish6"

View File

@@ -0,0 +1,32 @@
# Jitsi Conference Focus settings
# sets the host name of the XMPP server
JICOFO_HOST=localhost
# sets the XMPP domain (default: none)
JICOFO_HOSTNAME=meet.example.com
# sets the secret used to authenticate as an XMPP component
JICOFO_SECRET=$JICOFO_SECRET
# sets the port to use for the XMPP component connection
JICOFO_PORT=5347
# sets the XMPP domain name to use for XMPP user logins
JICOFO_AUTH_DOMAIN=auth.meet.example.com
# sets the username to use for XMPP user logins
JICOFO_AUTH_USER=focus
# sets the password to use for XMPP user logins
JICOFO_AUTH_PASSWORD=$JICOFO_PASSWORD
# extra options to pass to the jicofo daemon
JICOFO_OPTS=""
# adds java system props that are passed to jicofo (default are for home and logging config file)
JAVA_SYS_PROPS=" \
-Dnet.java.sip.communicator.SC_HOME_DIR_LOCATION=/etc/jitsi \
-Dnet.java.sip.communicator.SC_HOME_DIR_NAME=jicofo \
-Dnet.java.sip.communicator.SC_LOG_DIR_LOCATION=/var/log/jitsi \
-Djava.util.logging.config.file=/etc/jitsi/jicofo/logging.properties \
"

View File

@@ -0,0 +1,6 @@
org.jitsi.jicofo.BRIDGE_MUC=JvbBrewery@internal.auth.meet.example.com
org.jitsi.jicofo.ALWAYS_TRUST_MODE_ENABLED=true
org.jitsi.jicofo.jibri.BREWERY=JibriBrewery@internal.auth.meet.example.com
org.jitsi.jicofo.jibri.PENDING_TIMEOUT=90

View File

@@ -0,0 +1,87 @@
plugin_paths = { "/usr/share/jitsi-meet/prosody-plugins/" }
-- domain mapper options, must at least have domain base set to use the mapper
muc_mapper_domain_base = "meet.example.com";
turncredentials_secret = "turncredentials_secret_test";
turncredentials = {
{ type = "stun", host = "meet.example.com", port = "443" },
{ type = "turn", host = "meet.example.com", port = "443", transport = "udp" },
{ type = "turns", host = "meet.example.com", port = "443", transport = "tcp" }
};
cross_domain_bosh = false;
consider_bosh_secure = true;
VirtualHost "meet.example.com"
-- enabled = false -- Remove this line to enable this host
authentication = "anonymous"
-- Properties below are modified by jitsi-meet-tokens package config
-- and authentication above is switched to "token"
--app_id="example_app_id"
--app_secret="example_app_secret"
-- Assign this host a certificate for TLS, otherwise it would use the one
-- set in the global section (if any).
-- Note that old-style SSL on port 5223 only supports one certificate, and will always
-- use the global one.
ssl = {
key = "/etc/prosody/certs/meet.example.com.key";
certificate = "/etc/prosody/certs/meet.example.com.crt";
}
speakerstats_component = "speakerstats.meet.example.com"
conference_duration_component = "conferenceduration.meet.example.com"
-- we need bosh
modules_enabled = {
"bosh";
"pubsub";
"ping"; -- Enable mod_ping
"speakerstats";
"turncredentials";
"conference_duration";
}
c2s_require_encryption = false
Component "conference.meet.example.com" "muc"
storage = "memory"
modules_enabled = {
"muc_meeting_id";
"muc_domain_mapper";
--"token_verification";
}
admins = { "focus@auth.meet.example.com" }
muc_room_locking = false
muc_room_default_public_jids = true
-- internal muc component
-- Note: This is also used from jibris
Component "internal.auth.meet.example.com" "muc"
storage = "memory"
modules_enabled = {
"ping";
}
admins = { "focus@auth.meet.example.com", "jvb@auth.meet.example.com" }
VirtualHost "auth.meet.example.com"
ssl = {
key = "/etc/prosody/certs/auth.meet.example.com.key";
certificate = "/etc/prosody/certs/auth.meet.example.com.crt";
}
authentication = "internal_hashed"
Component "focus.meet.example.com"
component_secret = "jicofo_secret_test"
Component "speakerstats.meet.example.com" "speakerstats_component"
muc_component = "conference.meet.example.com"
Component "conferenceduration.meet.example.com" "conference_duration_component"
muc_component = "conference.meet.example.com"
-- for Jibri
VirtualHost "recorder.meet.example.com"
modules_enabled = {
"ping";
}
authentication = "internal_hashed"
c2s_require_encryption = false

View File

@@ -0,0 +1,112 @@
-- Prosody XMPP Server Configuration
---------- Server-wide settings ----------
-- Settings in this section apply to the whole server and are the default settings
-- for any virtual hosts
admins = { }
network_backend = "epoll"
-- This is the list of modules Prosody will load on startup.
-- It looks for mod_modulename.lua in the plugins folder, so make sure that exists too.
-- Documentation for bundled modules can be found at: https://prosody.im/doc/modules
modules_enabled = {
-- Generally required
"roster"; -- Allow users to have a roster. Recommended ;)
"saslauth"; -- Authentication for clients and servers. Recommended if you want to log in.
"tls"; -- Add support for secure TLS on c2s/s2s connections
"dialback"; -- s2s dialback support
"disco"; -- Service discovery
-- Not essential, but recommended
"carbons"; -- Keep multiple clients in sync
"pep"; -- Enables users to publish their avatar, mood, activity, playing music and more
"private"; -- Private XML storage (for room bookmarks, etc.)
"blocklist"; -- Allow users to block communications with other users
"vcard4"; -- User profiles (stored in PEP)
"vcard_legacy"; -- Conversion between legacy vCard and PEP Avatar, vcard
-- Nice to have
"version"; -- Replies to server version requests
"uptime"; -- Report how long server has been running
"time"; -- Let others know the time here on this server
"ping"; -- Replies to XMPP pings with pongs
"register"; -- Allow users to register on this server using a client and change passwords
--"mam"; -- Store messages in an archive and allow users to access it
--"csi_simple"; -- Simple Mobile optimizations
-- Admin interfaces
"admin_adhoc"; -- Allows administration via an XMPP client that supports ad-hoc commands
--"admin_telnet"; -- Opens telnet console interface on localhost port 5582
-- HTTP modules
--"bosh"; -- Enable BOSH clients, aka "Jabber over HTTP"
--"websocket"; -- XMPP over WebSockets
--"http_files"; -- Serve static files from a directory over HTTP
-- Other specific functionality
--"limits"; -- Enable bandwidth limiting for XMPP connections
--"groups"; -- Shared roster support
--"server_contact_info"; -- Publish contact information for this service
--"announce"; -- Send announcement to all online users
--"welcome"; -- Welcome users who register accounts
--"watchregistrations"; -- Alert admins of registrations
--"motd"; -- Send a message to users when they log in
--"legacyauth"; -- Legacy authentication. Only used by some old clients and bots.
--"proxy65"; -- Enables a file transfer proxy service which clients behind NAT can use
}
-- These modules are auto-loaded, but should you want
-- to disable them then uncomment them here:
modules_disabled = {
--"offline"; -- Store offline messages
--"c2s"; -- Handle client connections
--"s2s"; -- Handle server-to-server connections
--"posix"; -- POSIX functionality, sends server to background, enables syslog, etc.
}
-- Disable account creation by default, for security
-- For more information see https://prosody.im/doc/creating_accounts
allow_registration = false
-- Force clients to use encrypted connections? This option will
-- prevent clients from authenticating unless they are using encryption.
c2s_require_encryption = true
-- Force servers to use encrypted connections? This option will
-- prevent servers from authenticating unless they are using encryption.
s2s_require_encryption = true
-- Force certificate authentication for server-to-server connections?
s2s_secure_auth = false
-- Required for init scripts and prosodyctl
pidfile = "/var/run/prosody/prosody.pid"
-- Select the authentication backend to use. The 'internal' providers
-- use Prosody's configured data storage to store the authentication data.
authentication = "internal_hashed"
archive_expires_after = "1w" -- Remove archived messages after 1 week
-- Logging configuration
-- For advanced logging see https://prosody.im/doc/logging
log = {
info = "/var/log/prosody/prosody.log"; -- Change 'info' to 'debug' for verbose logging
error = "/var/log/prosody/prosody.err";
--"*syslog"; -- Uncomment this for logging to syslog
--"*console"; -- Log to the console, useful for debugging with daemonize=false
}
-- Location of directory to find certificates in (relative to main config file):
certificates = "certs"
VirtualHost "localhost"
Include "conf.d/*.cfg.lua"

View File

@@ -0,0 +1,24 @@
# Jitsi Videobridge settings
# sets the XMPP domain (default: none)
JVB_HOSTNAME=meet.example.com
# sets the hostname of the XMPP server (default: domain if set, localhost otherwise)
JVB_HOST=
# sets the port of the XMPP server (default: 5275)
JVB_PORT=5347
# sets the shared secret used to authenticate to the XMPP server
JVB_SECRET=$VP_SECRET
# extra options to pass to the JVB daemon
JVB_OPTS="--apis=rest,"
# adds java system props that are passed to jvb (default are for home and logging config file)
JAVA_SYS_PROPS=" \
-Dnet.java.sip.communicator.SC_HOME_DIR_LOCATION=/etc/jitsi \
-Dnet.java.sip.communicator.SC_HOME_DIR_NAME=videobridge \
-Dnet.java.sip.communicator.SC_LOG_DIR_LOCATION=/var/log/jitsi \
-Djava.util.logging.config.file=/etc/jitsi/videobridge/logging.properties \
"

View File

@@ -0,0 +1,19 @@
org.ice4j.ice.harvest.DISABLE_AWS_HARVESTER=true
org.ice4j.ice.harvest.STUN_MAPPING_HARVESTER_ADDRESSES=meet-jit-si-turnrelay.jitsi.net:443
org.jitsi.jicofo.ALWAYS_TRUST_MODE_ENABLED=true
org.jitsi.videobridge.ENABLE_REST_SHUTDOWN=true
# Enable broadcasting stats/presence in a MUC
org.jitsi.videobridge.ENABLE_STATISTICS=true
org.jitsi.videobridge.STATISTICS_TRANSPORT=muc,colibri,rest
org.jitsi.videobridge.STATISTICS_INTERVAL=5000
org.jitsi.videobridge.xmpp.user.shard-1.HOSTNAME=meet.example.com
org.jitsi.videobridge.xmpp.user.shard-1.DOMAIN=auth.meet.example.com
org.jitsi.videobridge.xmpp.user.shard-1.USERNAME=jvb
org.jitsi.videobridge.xmpp.user.shard-1.PASSWORD=$VB_PASSWORD
org.jitsi.videobridge.xmpp.user.shard-1.MUC_JIDS=JvbBrewery@internal.auth.meet.example.com
org.jitsi.videobridge.xmpp.user.shard-1.MUC_NICKNAME=$NICKNAME_OF_VB
org.jitsi.videobridge.xmpp.user.shard-1.DISABLE_CERTIFICATE_VERIFICATION=true

102
flow-typed/npm/uuid_v3.x.x.js vendored Normal file
View File

@@ -0,0 +1,102 @@
// flow-typed signature: 609c1622fc97de96d59519934aa5ce87
// flow-typed version: c6154227d1/uuid_v3.x.x/flow_>=v0.32.x <=v0.103.x
declare module "uuid" {
declare class uuid {
static (
options?: {|
random?: number[],
rng?: () => number[] | Buffer
|},
buffer?: number[] | Buffer,
offset?: number
): string,
static v1(
options?: {|
node?: number[],
clockseq?: number,
msecs?: number | Date,
nsecs?: number
|},
buffer?: number[] | Buffer,
offset?: number
): string,
static v4(
options?: {|
random?: number[],
rng?: () => number[] | Buffer
|},
buffer?: number[] | Buffer,
offset?: number
): string
}
declare module.exports: Class<uuid>;
}
declare module "uuid/v1" {
declare class v1 {
static (
options?: {|
node?: number[],
clockseq?: number,
msecs?: number | Date,
nsecs?: number
|},
buffer?: number[] | Buffer,
offset?: number
): string
}
declare module.exports: Class<v1>;
}
declare module "uuid/v3" {
declare class v3 {
static (
name?: string | number[],
namespace?: string | number[],
buffer?: number[] | Buffer,
offset?: number
): string,
static name: string,
static DNS: string,
static URL: string
}
declare module.exports: Class<v3>;
}
declare module "uuid/v4" {
declare class v4 {
static (
options?: {|
random?: number[],
rng?: () => number[] | Buffer
|},
buffer?: number[] | Buffer,
offset?: number
): string
}
declare module.exports: Class<v4>;
}
declare module "uuid/v5" {
declare class v5 {
static (
name?: string | number[],
namespace?: string | number[],
buffer?: number[] | Buffer,
offset?: number
): string,
static name: string,
static DNS: string,
static URL: string
}
declare module.exports: Class<v5>;
}

View File

@@ -1,71 +0,0 @@
declare module 'uuid' {
// v1 (Timestamp)
declare type V1Options = {|
node?: $ReadOnlyArray<number>,
clockseq?: number,
msecs?: number,
nsecs?: number,
random?: $ReadOnlyArray<number>,
rng?: () => $ReadOnlyArray<number>,
|};
declare export function v1(options?: V1Options): string;
declare export function v1(
options: V1Options | null,
buffer: Array<number>,
offset?: number
): Array<number>;
// v3 (Namespace)
declare function v3Impl(
name: string | $ReadOnlyArray<number>,
namespace: string | $ReadOnlyArray<number>
): string;
declare function v3Impl(
name: string | $ReadOnlyArray<number>,
namespace: string | $ReadOnlyArray<number>,
buffer: Array<number>,
offset?: number
): Array<number>;
declare export var v3: {|
[[call]]: typeof v3Impl,
DNS: string,
URL: string,
|};
// v4 (Random)
declare type V4Options = {|
random?: $ReadOnlyArray<number>,
rng?: () => $ReadOnlyArray<number>,
|};
declare export function v4(options?: V4Options): string;
declare export function v4(
options: V4Options | null,
buffer: Array<number>,
offset?: number
): Array<number>;
// v5 (Namespace)
declare function v5Impl(
name: string | $ReadOnlyArray<number>,
namespace: string | $ReadOnlyArray<number>
): string;
declare function v5Impl(
name: string | $ReadOnlyArray<number>,
namespace: string | $ReadOnlyArray<number>,
buffer: Array<number>,
offset?: number
): Array<number>;
declare export var v5: {|
[[call]]: typeof v5Impl,
DNS: string,
URL: string,
|};
}

View File

View File

@@ -9,7 +9,6 @@
<link rel="apple-touch-icon" href="images/apple-touch-icon.png">
<link rel="stylesheet" href="css/all.css">
<!--#include virtual="fonts.html"-->
<link rel="manifest" id="manifest-placeholder">
<script>

View File

@@ -26,12 +26,22 @@ var interfaceConfig = {
CLOSE_PAGE_GUEST_HINT: false, // A html text to be shown to guests on the close page, false disables it
DEFAULT_BACKGROUND: '#040404',
// Connection indicators (
// CONNECTION_INDICATOR_AUTO_HIDE_ENABLED,
// CONNECTION_INDICATOR_AUTO_HIDE_TIMEOUT,
// CONNECTION_INDICATOR_DISABLED) got moved to config.js.
DEFAULT_BACKGROUND: '#474747',
DEFAULT_LOCAL_DISPLAY_NAME: 'me',
DEFAULT_LOGO_URL: 'images/watermark.svg',
DEFAULT_REMOTE_DISPLAY_NAME: 'Fellow Jitster',
DEFAULT_WELCOME_PAGE_LOGO_URL: 'images/watermark.svg',
DISABLE_DOMINANT_SPEAKER_INDICATOR: false,
// Deprecated. Please use disableModeratorIndicator from config.js
// DISABLE_FOCUS_INDICATOR: false,
/**
* If true, notifications regarding joining/leaving are no longer displayed.
*/
@@ -87,6 +97,7 @@ var interfaceConfig = {
*/
HIDE_INVITE_MORE_HEADER: false,
INITIAL_TOOLBAR_TIMEOUT: 20000,
JITSI_WATERMARK_LINK: 'https://jitsi.org',
LANG_DETECTION: true, // Allow i18n to detect the system language
@@ -172,6 +183,16 @@ var interfaceConfig = {
*/
SUPPORT_URL: 'https://community.jitsi.org/',
TOOLBAR_ALWAYS_VISIBLE: false,
/**
* DEPRECATED!
* This config was moved to config.js as `toolbarButtons`.
*/
// TOOLBAR_BUTTONS: [],
TOOLBAR_TIMEOUT: 4000,
// Browsers, in addition to those which do not fully support WebRTC, that
// are not supported and should show the unsupported browser page.
UNSUPPORTED_BROWSERS: [],
@@ -223,40 +244,19 @@ var interfaceConfig = {
*/
// ANDROID_APP_PACKAGE: 'org.jitsi.meet',
/**
* Override the behavior of some notifications to remain displayed until
* explicitly dismissed through a user action. The value is how long, in
* milliseconds, those notifications should remain displayed.
*/
// ENFORCE_NOTIFICATION_AUTO_DISMISS_TIMEOUT: 15000,
// List of undocumented settings
/**
INDICATOR_FONT_SIZES
PHONE_NUMBER_REGEX
*/
// -----------------DEPRECATED CONFIGS BELOW THIS LINE-----------------------------
// Connection indicators (
// CONNECTION_INDICATOR_AUTO_HIDE_ENABLED,
// CONNECTION_INDICATOR_AUTO_HIDE_TIMEOUT,
// CONNECTION_INDICATOR_DISABLED) got moved to config.js.
// Please use disableModeratorIndicator from config.js
// DISABLE_FOCUS_INDICATOR: false,
// Please use defaultLocalDisplayName from config.js
// DEFAULT_LOCAL_DISPLAY_NAME: 'me',
// Please use defaultRemoteDisplayName from config.js
// DEFAULT_REMOTE_DISPLAY_NAME: 'Fellow Jitster',
// Moved to config.js as `toolbarConfig.initialTimeout`.
// INITIAL_TOOLBAR_TIMEOUT: 20000,
// Moved to config.js as `toolbarConfig.alwaysVisible`.
// TOOLBAR_ALWAYS_VISIBLE: false,
// This config was moved to config.js as `toolbarButtons`.
// TOOLBAR_BUTTONS: [],
// Moved to config.js as `toolbarConfig.timeout`.
// TOOLBAR_TIMEOUT: 4000,
// Allow all above example options to include a trailing comma and
// prevent fear when commenting out the last value.
// eslint-disable-next-line sort-keys

View File

@@ -1,4 +1,4 @@
platform :ios, '12.0'
platform :ios, '11.0'
workspace 'jitsi-meet'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
install! 'cocoapods', :deterministic_uuids => false
@@ -57,28 +57,21 @@ target 'JitsiMeetSDK' do
pod 'amplitude-react-native', :path => '../node_modules/@amplitude/react-native'
pod 'react-native-background-timer', :path => '../node_modules/react-native-background-timer'
pod 'react-native-calendar-events', :path => '../node_modules/react-native-calendar-events'
pod 'react-native-get-random-values', :path => '../node_modules/react-native-get-random-values'
pod 'react-native-keep-awake', :path => '../node_modules/react-native-keep-awake'
pod 'react-native-netinfo', :path => '../node_modules/@react-native-community/netinfo'
pod 'react-native-performance', :path => '../node_modules/react-native-performance/ios'
pod 'react-native-safe-area-context', :path => '../node_modules/react-native-safe-area-context'
pod 'react-native-slider', :path => '../node_modules/@react-native-community/slider'
pod 'react-native-splash-screen', :path => '../node_modules/react-native-splash-screen'
pod 'react-native-video', :path => '../node_modules/react-native-video/react-native-video.podspec'
pod 'react-native-webview', :path => '../node_modules/react-native-webview'
pod 'react-native-webrtc', :path => '../node_modules/react-native-webrtc'
pod 'RNCAsyncStorage', :path => '../node_modules/@react-native-async-storage/async-storage'
pod 'RNCClipboard', :path => '../node_modules/@react-native-community/clipboard'
pod 'RNCMaskedView', :path => '../node_modules/@react-native-masked-view/masked-view'
pod 'RNDefaultPreference', :path => '../node_modules/react-native-default-preference'
pod 'RNDeviceInfo', :path => '../node_modules/react-native-device-info'
pod 'RNGestureHandler', :path => '../node_modules/react-native-gesture-handler'
pod 'RNGoogleSignin', :path => '../node_modules/@react-native-community/google-signin'
pod 'RNReanimated', :path => '../node_modules/react-native-reanimated'
pod 'RNScreens', :path => '../node_modules/react-native-screens'
pod 'RNSound', :path => '../node_modules/react-native-sound'
pod 'RNSVG', :path => '../node_modules/react-native-svg'
pod 'RNWatch', :path => '../node_modules/react-native-watch-connectivity'
pod 'RNDefaultPreference', :path => '../node_modules/react-native-default-preference'
# Native pod dependencies
#
@@ -94,7 +87,7 @@ post_install do |installer|
target.build_configurations.each do |config|
config.build_settings['ENABLE_BITCODE'] = 'YES'
config.build_settings['SUPPORTS_MACCATALYST'] = 'NO'
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0'
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0'
end
end
end

View File

@@ -109,7 +109,7 @@ PODS:
- GTMAppAuth (1.2.2):
- AppAuth/Core (~> 1.4)
- GTMSessionFetcher/Core (~> 1.5)
- GTMSessionFetcher/Core (1.7.0)
- GTMSessionFetcher/Core (1.6.1)
- nanopb (1.30906.0):
- nanopb/decode (= 1.30906.0)
- nanopb/encode (= 1.30906.0)
@@ -284,16 +284,12 @@ PODS:
- React
- react-native-calendar-events (2.0.0):
- React
- react-native-get-random-values (1.7.0):
- React-Core
- react-native-keep-awake (4.0.0):
- React
- react-native-netinfo (4.1.5):
- React
- react-native-performance (2.0.0):
- React-Core
- react-native-safe-area-context (3.3.2):
- React-Core
- react-native-slider (3.0.3):
- React
- react-native-splash-screen (3.2.0):
@@ -303,7 +299,7 @@ PODS:
- react-native-video/Video (= 5.1.1)
- react-native-video/Video (5.1.1):
- React-Core
- react-native-webrtc (1.94.1):
- react-native-webrtc (1.92.1):
- React-Core
- react-native-webview (11.0.2):
- React-Core
@@ -363,23 +359,13 @@ PODS:
- ReactCommon/turbomodule/core (= 0.61.5-jitsi.2)
- RNCAsyncStorage (1.15.5):
- React-Core
- RNCClipboard (1.5.1):
- React-Core
- RNCMaskedView (0.2.6):
- React-Core
- RNDefaultPreference (1.4.2):
- React
- RNDeviceInfo (8.0.0):
- React-Core
- RNGestureHandler (1.10.3):
- React-Core
- RNGoogleSignin (3.0.1):
- GoogleSignIn (~> 5.0.0)
- React
- RNReanimated (1.13.3):
- React-Core
- RNScreens (2.18.1):
- React-Core
- RNSound (0.11.0):
- React
- RNSound/Core (= 0.11.0)
@@ -416,11 +402,9 @@ DEPENDENCIES:
- React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
- react-native-background-timer (from `../node_modules/react-native-background-timer`)
- react-native-calendar-events (from `../node_modules/react-native-calendar-events`)
- react-native-get-random-values (from `../node_modules/react-native-get-random-values`)
- react-native-keep-awake (from `../node_modules/react-native-keep-awake`)
- "react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)"
- react-native-performance (from `../node_modules/react-native-performance/ios`)
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
- "react-native-slider (from `../node_modules/@react-native-community/slider`)"
- react-native-splash-screen (from `../node_modules/react-native-splash-screen`)
- react-native-video (from `../node_modules/react-native-video/react-native-video.podspec`)
@@ -437,14 +421,9 @@ DEPENDENCIES:
- React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`)
- ReactCommon/turbomodule (from `../node_modules/react-native/ReactCommon`)
- "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)"
- "RNCClipboard (from `../node_modules/@react-native-community/clipboard`)"
- "RNCMaskedView (from `../node_modules/@react-native-masked-view/masked-view`)"
- RNDefaultPreference (from `../node_modules/react-native-default-preference`)
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
- "RNGoogleSignin (from `../node_modules/@react-native-community/google-signin`)"
- RNReanimated (from `../node_modules/react-native-reanimated`)
- RNScreens (from `../node_modules/react-native-screens`)
- RNSound (from `../node_modules/react-native-sound`)
- RNSVG (from `../node_modules/react-native-svg`)
- RNWatch (from `../node_modules/react-native-watch-connectivity`)
@@ -508,16 +487,12 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-background-timer"
react-native-calendar-events:
:path: "../node_modules/react-native-calendar-events"
react-native-get-random-values:
:path: "../node_modules/react-native-get-random-values"
react-native-keep-awake:
:path: "../node_modules/react-native-keep-awake"
react-native-netinfo:
:path: "../node_modules/@react-native-community/netinfo"
react-native-performance:
:path: "../node_modules/react-native-performance/ios"
react-native-safe-area-context:
:path: "../node_modules/react-native-safe-area-context"
react-native-slider:
:path: "../node_modules/@react-native-community/slider"
react-native-splash-screen:
@@ -550,22 +525,12 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon"
RNCAsyncStorage:
:path: "../node_modules/@react-native-async-storage/async-storage"
RNCClipboard:
:path: "../node_modules/@react-native-community/clipboard"
RNCMaskedView:
:path: "../node_modules/@react-native-masked-view/masked-view"
RNDefaultPreference:
:path: "../node_modules/react-native-default-preference"
RNDeviceInfo:
:path: "../node_modules/react-native-device-info"
RNGestureHandler:
:path: "../node_modules/react-native-gesture-handler"
RNGoogleSignin:
:path: "../node_modules/@react-native-community/google-signin"
RNReanimated:
:path: "../node_modules/react-native-reanimated"
RNScreens:
:path: "../node_modules/react-native-screens"
RNSound:
:path: "../node_modules/react-native-sound"
RNSVG:
@@ -577,7 +542,7 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
Amplitude: 263118b9e691e73a1c864b05bb08a3aff3636d16
amplitude-react-native: 9369759dc6d01590aeb6261f714d53beaebc7e6f
amplitude-react-native: 833a4bd7f656f826bda1de01a7b8593b58842209
AppAuth: 31bcec809a638d7bd2f86ea8a52bd45f6e81e7c7
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
CocoaLumberjack: 2f44e60eb91c176d471fdba43b9e3eae6a721947
@@ -598,7 +563,7 @@ SPEC CHECKSUMS:
GoogleSignIn: 7137d297ddc022a7e0aa4619c86d72c909fa7213
GoogleUtilities: 7f2f5a07f888cdb145101d6042bc4422f57e70b3
GTMAppAuth: ad5c2b70b9a8689e1a04033c9369c4915bfcbe89
GTMSessionFetcher: 43748f93435c2aa068b1cbe39655aaf600652e91
GTMSessionFetcher: 36689134877faeb055b27dfa4ccc9ceaa42e029e
nanopb: 59317e09cf1f1a0af72f12af412d54edf52603fc
ObjectiveDropboxOfficial: b4765572e334d6fc6214b43a7595510324bbbbaa
PromisesObjC: 3113f7f76903778cf4a0586bd1ab89329a0b7b97
@@ -611,18 +576,16 @@ SPEC CHECKSUMS:
React-jsi: ddb471a56185e4007835a1bba0882ecb5ce3dc0e
React-jsiexecutor: 67106691c60030ec888d7cbbc4f48a3168e27a02
React-jsinspector: 92ceee6c66dc19886289b52436ade7e020b89602
react-native-background-timer: 029c606b3fd6dd476b153e177c518b6ade4c169f
react-native-calendar-events: 82dc6c915653a1a8a266e43fdbbfdb3b1022ca99
react-native-get-random-values: 237bffb1c7e05fb142092681531810a29ba53015
react-native-keep-awake: afad8a51dfef9fe9655a6344771be32c8596d774
react-native-netinfo: 0e563248a4b9a99c33ec29bd03c2d50767db22a6
react-native-performance: 6bd6cfac80594775fb782405fceaaf206becf53b
react-native-safe-area-context: 584dc04881deb49474363f3be89e4ca0e854c057
react-native-slider: e99fc201cefe81270fc9d81714a7a0f5e566b168
react-native-background-timer: e0384ea2fa5a98f67f84f9c4dc274260ddd674ed
react-native-calendar-events: 1442fad71a00388f933cfa25512588fec300fcf8
react-native-keep-awake: eba3137546b10003361b37c761f6c429b59814ae
react-native-netinfo: 8d8db463bcc5db66a8ac5c48a7d86beb3b92f61a
react-native-performance: 8edfa2bbc9a2af4a02f01d342118e413a95145e0
react-native-slider: b733e17fdd31186707146debf1f04b5d94aa1a93
react-native-splash-screen: 200d11d188e2e78cea3ad319964f6142b6384865
react-native-video: 0bb76b6d6b77da3009611586c7dbf817b947f30e
react-native-webrtc: 2f20515f3ebb9dbf1f2aad638cc7573396cf948f
react-native-webview: dfd7202ff115c44d3ea401c2f36122fb3ac79f07
react-native-video: 1574074179ecaf6a9dd067116c8f31bf9fec15c8
react-native-webrtc: 77b969fe6bc5b7c93b455f93a13698812fb8bb4e
react-native-webview: b2542d6fd424bcc3e3b2ec5f854f0abb4ec86c87
React-RCTActionSheet: bcbc311dc3b47bc8efb2737ff0940239a45789a9
React-RCTAnimation: 65f61080ce632f6dea23d52e354ffac9948396c6
React-RCTBlob: 70d88f7b68b5c44953cdb286ac2e36a7a509a97e
@@ -633,20 +596,15 @@ SPEC CHECKSUMS:
React-RCTText: 4f1b99f228278d2a5e9008eced8dc9c974c4a270
React-RCTVibration: c1041024893fdfdb8371e7c720c437751b711676
ReactCommon: 18014e1d98dbeb9141e935cfe35fc93bd511ffb6
RNCAsyncStorage: 56a3355a10b5d660c48c6e37325ac85ebfd09885
RNCClipboard: 41d8d918092ae8e676f18adada19104fa3e68495
RNCMaskedView: c298b644a10c0c142055b3ae24d83879ecb13ccd
RNDefaultPreference: 1f8133ec0bc0f9453cdada578564ba1ef551fb44
RNDeviceInfo: 87d2d175c760f6bcf58acd036f887e8b2392802c
RNGestureHandler: a479ebd5ed4221a810967000735517df0d2db211
RNCAsyncStorage: 8324611026e8dc3706f829953aa6e3899f581589
RNDefaultPreference: 56a405ce61033ac77b95004dccd7ac54c2eb50d1
RNDeviceInfo: 72ded653ce636b3f03571e90bed99309a714944e
RNGoogleSignin: 39336070b35fc4cea6a98cf111e00480317be0ae
RNReanimated: 514a11da3a2bcc6c3dfd9de32b38e2b9bf101926
RNScreens: f7ad633b2e0190b77b6a7aab7f914fad6f198d8d
RNSound: da030221e6ac7e8290c6b43f2b5f2133a8e225b0
RNSound: c980916b596cc15c8dcd2f6ecd3b13c4881dbe20
RNSVG: ce9d996113475209013317e48b05c21ee988d42e
RNWatch: a5320c959c75e72845c07985f3e935e58998f1d3
Yoga: 96b469c5e81ff51b917b92e8c3390642d4ded30c
PODFILE CHECKSUM: 0cfc1f35e2872ceb0a86252e14e226bd489a2602
PODFILE CHECKSUM: e830b1b5a46d340e22689b146b55dcf24664c6f1
COCOAPODS: 1.11.2
COCOAPODS: 1.10.1

View File

@@ -996,7 +996,7 @@
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
);
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -1049,7 +1049,7 @@
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
);
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;

View File

@@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>21.6.0</string>
<string>21.4.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>NSExtension</key>

View File

@@ -34,10 +34,10 @@
jitsiMeet.universalLinkDomains = @[@"meet.jit.si", @"alpha.jitsi.net", @"beta.meet.jit.si"];
jitsiMeet.defaultConferenceOptions = [JitsiMeetConferenceOptions fromBuilder:^(JitsiMeetConferenceOptionsBuilder *builder) {
[builder setFeatureFlag:@"welcomepage.enabled" withBoolean:YES];
[builder setFeatureFlag:@"resolution" withValue:@(360)];
[builder setFeatureFlag:@"ios.screensharing.enabled" withBoolean:YES];
builder.serverURL = [NSURL URLWithString:@"https://meet.jit.si"];
builder.welcomePageEnabled = YES;
// Apple rejected our app because they claim requiring a
// Dropbox account for recording is not acceptable.

View File

@@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>21.6.0</string>
<string>21.4.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>

View File

@@ -1,5 +1,6 @@
/*
* Copyright @ 2017-present 8x8, Inc.
* 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.
@@ -14,6 +15,8 @@
* limitations under the License.
*/
#import <Availability.h>
@import CoreSpotlight;
@import MobileCoreServices;
@import Intents; // Needed for NSUserActivity suggestedInvocationPhrase
@@ -55,29 +58,34 @@
[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];
// Siri shortcut. This is only supported in iOS >= 12.
#ifdef __IPHONE_12_0
if (@available(iOS 12.0, *)) {
NSUserActivity *userActivity
= [[NSUserActivity alloc] initWithActivityType:JitsiMeetConferenceActivityType];
NSString *urlStr = data[@"url"];
NSURL *url = [NSURL URLWithString:urlStr];
NSString *conference = [url.pathComponents lastObject];
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];
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;
// Subtitle
CSSearchableItemAttributeSet *attributes
= [[CSSearchableItemAttributeSet alloc] initWithItemContentType:(NSString *)kUTTypeItem];
attributes.contentDescription = urlStr;
userActivity.contentAttributeSet = attributes;
self.userActivity = userActivity;
[userActivity becomeCurrent];
}
#endif
self.userActivity = userActivity;
[userActivity becomeCurrent];
}
- (void)conferenceTerminated:(NSDictionary *)data {
@@ -91,13 +99,10 @@
#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)participantJoined:(NSDictionary *)data {
NSLog(@"%@%@", @"Participant joined: ", data[@"participantId"]);
}

View File

@@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>21.6.0</string>
<string>21.4.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>UISupportedInterfaceOrientations</key>

View File

@@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<string>21.6.0</string>
<string>21.4.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>CLKComplicationPrincipalClass</key>

View File

@@ -24,8 +24,6 @@
0BD906EA1EC0C00300C8C18E /* JitsiMeet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BD906E81EC0C00300C8C18E /* JitsiMeet.h */; settings = {ATTRIBUTES = (Public, ); }; };
4E51B76425E5345E0038575A /* ScheenshareEventEmiter.h in Headers */ = {isa = PBXBuildFile; fileRef = 4E51B76225E5345E0038575A /* ScheenshareEventEmiter.h */; };
4E51B76525E5345E0038575A /* ScheenshareEventEmiter.m in Sources */ = {isa = PBXBuildFile; fileRef = 4E51B76325E5345E0038575A /* ScheenshareEventEmiter.m */; };
4ED4FFF32721B9B90074E620 /* JitsiAudioSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 4ED4FFF12721B9B90074E620 /* JitsiAudioSession.h */; settings = {ATTRIBUTES = (Public, ); }; };
4ED4FFF42721B9B90074E620 /* JitsiAudioSession.m in Sources */ = {isa = PBXBuildFile; fileRef = 4ED4FFF22721B9B90074E620 /* JitsiAudioSession.m */; };
6F08DF7D4458EE3CF3F36F6D /* libPods-JitsiMeetSDK.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E4376CA6886DE68FD7A4294B /* libPods-JitsiMeetSDK.a */; };
A4A934E9212F3ADB001E9388 /* Dropbox.m in Sources */ = {isa = PBXBuildFile; fileRef = A4A934E8212F3ADB001E9388 /* Dropbox.m */; };
C6245F5D2053091D0040BE68 /* image-resize@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C6245F5B2053091D0040BE68 /* image-resize@2x.png */; };
@@ -79,9 +77,6 @@
0BD906E91EC0C00300C8C18E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
4E51B76225E5345E0038575A /* ScheenshareEventEmiter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ScheenshareEventEmiter.h; sourceTree = "<group>"; };
4E51B76325E5345E0038575A /* ScheenshareEventEmiter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ScheenshareEventEmiter.m; sourceTree = "<group>"; };
4ED4FFF12721B9B90074E620 /* JitsiAudioSession.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JitsiAudioSession.h; sourceTree = "<group>"; };
4ED4FFF22721B9B90074E620 /* JitsiAudioSession.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JitsiAudioSession.m; sourceTree = "<group>"; };
4ED4FFF52721BAE10074E620 /* JitsiAudioSession+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "JitsiAudioSession+Private.h"; sourceTree = "<group>"; };
891FE43DAD30BC8976683100 /* Pods-JitsiMeetSDK.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JitsiMeetSDK.release.xcconfig"; path = "../Pods/Target Support Files/Pods-JitsiMeetSDK/Pods-JitsiMeetSDK.release.xcconfig"; sourceTree = "<group>"; };
98E09B5C73D9036B4ED252FC /* Pods-JitsiMeet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JitsiMeet.debug.xcconfig"; path = "../Pods/Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet.debug.xcconfig"; sourceTree = "<group>"; };
9C77CA3CC919B081F1A52982 /* Pods-JitsiMeet.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JitsiMeet.release.xcconfig"; path = "../Pods/Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet.release.xcconfig"; sourceTree = "<group>"; };
@@ -179,9 +174,6 @@
DEFE535821FB311F00011A3A /* JitsiMeet+Private.h */,
DEA9F283258A5D9900D4CD74 /* JitsiMeetSDK.h */,
DEFE535321FB1BF800011A3A /* JitsiMeet.m */,
4ED4FFF12721B9B90074E620 /* JitsiAudioSession.h */,
4ED4FFF52721BAE10074E620 /* JitsiAudioSession+Private.h */,
4ED4FFF22721B9B90074E620 /* JitsiAudioSession.m */,
DEAD3224220C497000E93636 /* JitsiMeetConferenceOptions.h */,
DEAD3228220C734300E93636 /* JitsiMeetConferenceOptions+Private.h */,
DEAD3225220C497000E93636 /* JitsiMeetConferenceOptions.m */,
@@ -285,7 +277,6 @@
4E51B76425E5345E0038575A /* ScheenshareEventEmiter.h in Headers */,
DE65AACC2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h in Headers */,
0B412F221EDEF6EA00B1A0A6 /* JitsiMeetViewDelegate.h in Headers */,
4ED4FFF32721B9B90074E620 /* JitsiAudioSession.h in Headers */,
0BD906EA1EC0C00300C8C18E /* JitsiMeet.h in Headers */,
DE81A2D42316AC4D00AE1940 /* JitsiMeetLogger.h in Headers */,
DE65AACA2317FFCD00290BEC /* LogUtils.h in Headers */,
@@ -447,7 +438,6 @@
files = (
0BB9AD7B1F5EC8F4001C08DB /* CallKit.m in Sources */,
DE81A2DF2317ED5400AE1940 /* JitsiMeetBaseLogHandler.m in Sources */,
4ED4FFF42721B9B90074E620 /* JitsiAudioSession.m in Sources */,
0BB9AD7D1F60356D001C08DB /* AppInfo.m in Sources */,
DE81A2D92316AC7600AE1940 /* LogBridge.m in Sources */,
DEAFA779229EAD520033A7FA /* RNRootView.m in Sources */,
@@ -530,7 +520,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -586,7 +576,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;

View File

@@ -20,7 +20,6 @@
#import <React/RCTLog.h>
#import <WebRTC/WebRTC.h>
#import "JitsiAudioSession+Private.h"
#import "LogUtils.h"
@@ -114,7 +113,7 @@ RCT_EXPORT_MODULE();
isSpeakerOn = NO;
isEarpieceOn = NO;
RTCAudioSession *session = JitsiAudioSession.rtcAudioSession;
RTCAudioSession *session = [RTCAudioSession sharedInstance];
[session addDelegate:self];
}
@@ -128,7 +127,7 @@ RCT_EXPORT_MODULE();
- (BOOL)setConfigWithoutLock:(RTCAudioSessionConfiguration *)config
error:(NSError * _Nullable *)outError {
RTCAudioSession *session = JitsiAudioSession.rtcAudioSession;
RTCAudioSession *session = [RTCAudioSession sharedInstance];
return [session setConfiguration:config error:outError];
}
@@ -136,7 +135,7 @@ RCT_EXPORT_MODULE();
- (BOOL)setConfig:(RTCAudioSessionConfiguration *)config
error:(NSError * _Nullable *)outError {
RTCAudioSession *session = JitsiAudioSession.rtcAudioSession;
RTCAudioSession *session = [RTCAudioSession sharedInstance];
[session lockForConfiguration];
BOOL success = [self setConfigWithoutLock:config error:outError];
[session unlockForConfiguration];
@@ -179,7 +178,7 @@ RCT_EXPORT_METHOD(setAudioDevice:(NSString *)device
reject:(RCTPromiseRejectBlock)reject) {
DDLogInfo(@"[AudioMode] Selected device: %@", device);
RTCAudioSession *session = JitsiAudioSession.rtcAudioSession;
RTCAudioSession *session = [RTCAudioSession sharedInstance];
[session lockForConfiguration];
BOOL success;
NSError *error = nil;
@@ -274,7 +273,7 @@ RCT_EXPORT_METHOD(updateDeviceList) {
RTCAudioSessionConfiguration *config = [self configForMode:self->activeMode];
[self setConfig:config error:nil];
if (self->forceSpeaker && !self->isSpeakerOn) {
RTCAudioSession *session = JitsiAudioSession.rtcAudioSession;
RTCAudioSession *session = [RTCAudioSession sharedInstance];
[session lockForConfiguration];
[session overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil];
[session unlockForConfiguration];

View File

@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>4.1.0</string>
<string>3.10.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>

View File

@@ -1,24 +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 "JitsiAudioSession.h"
#import <WebRTC/WebRTC.h>
@interface JitsiAudioSession (Private)
+ (RTCAudioSession *)rtcAudioSession;
@end

View File

@@ -1,26 +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 <Foundation/Foundation.h>
@class AVAudioSession;
@interface JitsiAudioSession : NSObject
+ (void)activateWithAudioSession:(AVAudioSession *)session;
+ (void)deactivateWithAudioSession:(AVAudioSession *)session;
@end

View File

@@ -1,34 +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 "JitsiAudioSession.h"
#import "JitsiAudioSession+Private.h"
@implementation JitsiAudioSession
+ (RTCAudioSession *)rtcAudioSession {
return [RTCAudioSession sharedInstance];
}
+ (void)activateWithAudioSession:(AVAudioSession *)session {
[self.rtcAudioSession audioSessionDidActivate:session];
}
+ (void)deactivateWithAudioSession:(AVAudioSession *)session {
[self.rtcAudioSession audioSessionDidDeactivate:session];
}
@end

View File

@@ -127,7 +127,6 @@
}
- (void)destroyReactNativeBridge {
[_bridgeWrapper invalidate];
_bridgeWrapper = nil;
}

View File

@@ -34,6 +34,12 @@
*/
@property (nonatomic, copy, nullable) NSString *token;
/**
* Color scheme override, see:
* https://github.com/jitsi/jitsi-meet/blob/master/react/features/base/color-scheme/defaultScheme.js
*/
@property (nonatomic, copy, nullable) NSDictionary *colorScheme;
/**
* Feature flags. See: https://github.com/jitsi/jitsi-meet/blob/master/react/features/base/flags/constants.js
*/
@@ -41,6 +47,12 @@
@property (nonatomic, readonly, nonnull) NSDictionary *config;
/**
* Set to YES to enable the welcome page. Typically SDK users won't need this enabled
* since the host application decides which meeting to join.
*/
@property (nonatomic) BOOL welcomePageEnabled;
/**
* Information about the local user. It will be used in absence of a token.
*/
@@ -70,8 +82,11 @@
@property (nonatomic, copy, nullable, readonly) NSString *room;
@property (nonatomic, copy, nullable, readonly) NSString *token;
@property (nonatomic, copy, nullable) NSDictionary *colorScheme;
@property (nonatomic, readonly, nonnull) NSDictionary *featureFlags;
@property (nonatomic, readonly) BOOL welcomePageEnabled;
@property (nonatomic, nullable) JitsiMeetUserInfo *userInfo;
+ (instancetype _Nonnull)fromBuilder:(void (^_Nonnull)(JitsiMeetConferenceOptionsBuilder *_Nonnull))initBlock;

View File

@@ -19,17 +19,26 @@
#import "JitsiMeetConferenceOptions+Private.h"
#import "JitsiMeetUserInfo+Private.h"
/**
* Backwards compatibility: turn the boolean property into a feature flag.
*/
static NSString *const WelcomePageEnabledFeatureFlag = @"welcomepage.enabled";
@implementation JitsiMeetConferenceOptionsBuilder {
NSMutableDictionary *_featureFlags;
NSMutableDictionary *_config;
}
@dynamic welcomePageEnabled;
- (instancetype)init {
if (self = [super init]) {
_serverURL = nil;
_room = nil;
_token = nil;
_colorScheme = nil;
_config = [[NSMutableDictionary alloc] init];
_featureFlags = [[NSMutableDictionary alloc] init];
@@ -87,6 +96,19 @@
_config[config] = value;
}
#pragma mark - Dynamic properties
- (void)setWelcomePageEnabled:(BOOL)welcomePageEnabled {
[self setFeatureFlag:WelcomePageEnabledFeatureFlag
withBoolean:welcomePageEnabled];
}
- (BOOL)welcomePageEnabled {
NSNumber *n = _featureFlags[WelcomePageEnabledFeatureFlag];
return n != nil ? [n boolValue] : NO;
}
@end
@implementation JitsiMeetConferenceOptions {
@@ -94,6 +116,16 @@
NSDictionary *_config;
}
@dynamic welcomePageEnabled;
#pragma mark - Dynamic properties
- (BOOL)welcomePageEnabled {
NSNumber *n = _featureFlags[WelcomePageEnabledFeatureFlag];
return n != nil ? [n boolValue] : NO;
}
#pragma mark - Internal initializer
- (instancetype)initWithBuilder:(JitsiMeetConferenceOptionsBuilder *)builder {
@@ -102,6 +134,8 @@
_room = builder.room;
_token = builder.token;
_colorScheme = builder.colorScheme;
_config = builder.config;
_featureFlags = [NSDictionary dictionaryWithDictionary:builder.featureFlags];
@@ -127,6 +161,10 @@
props[@"flags"] = [NSMutableDictionary dictionaryWithDictionary:_featureFlags];
if (_colorScheme != nil) {
props[@"colorScheme"] = self.colorScheme;
}
NSMutableDictionary *urlProps = [[NSMutableDictionary alloc] init];
// The room is fully qualified.

View File

@@ -20,5 +20,4 @@
#import <JitsiMeetSDK/JitsiMeetConferenceOptions.h>
#import <JitsiMeetSDK/JitsiMeetLogger.h>
#import <JitsiMeetSDK/JitsiMeetBaseLogHandler.h>
#import <JitsiMeetSDK/JitsiAudioSession.h>
#import <JitsiMeetSDK/InfoPlistUtil.h>

View File

@@ -23,7 +23,7 @@
*/
@property (nonatomic, copy, nullable) NSString *displayName;
/**
* User email.
* User e-mail.
*/
@property (nonatomic, copy, nullable) NSString *email;
/**

Some files were not shown because too many files have changed in this diff Show More