Compare commits

..

1 Commits

Author SHA1 Message Date
Saúl Ibarra Corretgé
9f4c036174 fix(blur) fix model paths 2021-02-18 15:36:37 +01:00
678 changed files with 8908 additions and 16930 deletions

View File

@@ -5,9 +5,8 @@ build/*
# modify as little as possible.
flow-typed/*
libs/*
resources/*
react/features/stream-effects/virtual-background/vendor/*
load-test/*
react/features/stream-effects/blur/vendor/*
# 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

View File

@@ -12,6 +12,5 @@ jobs:
with:
node-version: '12.x'
- run: npm install
- run: git status -s --untracked-files=no
- run: npm run lint
- run: make

View File

@@ -5,8 +5,8 @@ LIBJITSIMEET_DIR = node_modules/lib-jitsi-meet/
LIBFLAC_DIR = node_modules/libflacjs/dist/min/
OLM_DIR = node_modules/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/
TFLITE_WASM = react/features/stream-effects/blur/vendor/tflite
MEET_MODELS_DIR = react/features/stream-effects/blur/vendor/models/
NODE_SASS = ./node_modules/.bin/sass
NPM = npm
OUTPUT_DIR = .
@@ -51,6 +51,10 @@ deploy-appbundle:
$(OUTPUT_DIR)/analytics-ga.js \
$(BUILD_DIR)/analytics-ga.min.js \
$(BUILD_DIR)/analytics-ga.min.map \
$(BUILD_DIR)/video-blur-effect.min.js \
$(BUILD_DIR)/video-blur-effect.min.map \
$(BUILD_DIR)/rnnoise-processor.min.js \
$(BUILD_DIR)/rnnoise-processor.min.map \
$(BUILD_DIR)/close3.min.js \
$(BUILD_DIR)/close3.min.map \
$(DEPLOY_DIR)

View File

@@ -122,7 +122,7 @@ gradle.projectsEvaluated {
android.applicationVariants.all { variant ->
variant.outputs.each { output ->
output.getProcessManifestProvider().get().doLast {
def outputDir = multiApkManifestOutputDirectory.get().asFile
def outputDir = manifestOutputDirectory.get().asFile
def manifestPath = new File(outputDir, 'AndroidManifest.xml')
def charset = 'UTF-8'
def text

View File

@@ -25,5 +25,5 @@ android.enableDexingArtifactTransform.desugaring=false
android.useAndroidX=true
android.enableJetifier=true
appVersion=21.1.0
sdkVersion=3.4.0
appVersion=21.0.0
sdkVersion=3.1.0

View File

@@ -70,6 +70,7 @@ dependencies {
implementation project(':react-native-default-preference')
implementation project(':react-native-immersive')
implementation project(':react-native-keep-awake')
implementation project(':react-native-linear-gradient')
implementation project(':react-native-sound')
implementation project(':react-native-svg')
implementation project(':react-native-webrtc')

View File

@@ -36,17 +36,8 @@ public class BroadcastAction {
for (String key : this.data.keySet()) {
try {
if (this.data.get(key) instanceof Boolean) {
nativeMap.putBoolean(key, (Boolean) this.data.get(key));
} else if (this.data.get(key) instanceof Integer) {
nativeMap.putInt(key, (Integer) this.data.get(key));
} else if (this.data.get(key) instanceof Double) {
nativeMap.putDouble(key, (Double) this.data.get(key));
} else if (this.data.get(key) instanceof String) {
nativeMap.putString(key, (String) this.data.get(key));
} else {
throw new Exception("Unsupported extra data type");
}
// TODO add support for different types of objects
nativeMap.putString(key, this.data.get(key).toString());
} catch (Exception e) {
JitsiMeetLogger.w(TAG + " invalid extra data in event", e);
}
@@ -75,8 +66,7 @@ public class BroadcastAction {
RETRIEVE_PARTICIPANTS_INFO("org.jitsi.meet.RETRIEVE_PARTICIPANTS_INFO"),
OPEN_CHAT("org.jitsi.meet.OPEN_CHAT"),
CLOSE_CHAT("org.jitsi.meet.CLOSE_CHAT"),
SEND_CHAT_MESSAGE("org.jitsi.meet.SEND_CHAT_MESSAGE"),
SET_VIDEO_MUTED("org.jitsi.meet.SET_VIDEO_MUTED");
SEND_CHAT_MESSAGE("org.jitsi.meet.SEND_CHAT_MESSAGE");
private final String action;

View File

@@ -85,9 +85,7 @@ public class BroadcastEvent {
SCREEN_SHARE_TOGGLED("org.jitsi.meet.SCREEN_SHARE_TOGGLED"),
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");
CHAT_TOGGLED("org.jitsi.meet.CHAT_TOGGLED");
private static final String CONFERENCE_WILL_JOIN_NAME = "CONFERENCE_WILL_JOIN";
private static final String CONFERENCE_JOINED_NAME = "CONFERENCE_JOINED";
@@ -100,7 +98,6 @@ public class BroadcastEvent {
private static final String PARTICIPANTS_INFO_RETRIEVED_NAME = "PARTICIPANTS_INFO_RETRIEVED";
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 final String action;
@@ -145,8 +142,6 @@ public class BroadcastEvent {
return CHAT_MESSAGE_RECEIVED;
case CHAT_TOGGLED_NAME:
return CHAT_TOGGLED;
case VIDEO_MUTED_CHANGED_NAME:
return VIDEO_MUTED_CHANGED;
}
return null;

View File

@@ -20,10 +20,8 @@ public class BroadcastIntentHelper {
return intent;
}
public static Intent buildToggleScreenShareIntent(boolean enabled) {
Intent intent = new Intent(BroadcastAction.Type.TOGGLE_SCREEN_SHARE.getAction());
intent.putExtra("enabled", enabled);
return intent;
public static Intent buildToggleScreenShareIntent() {
return new Intent(BroadcastAction.Type.TOGGLE_SCREEN_SHARE.getAction());
}
public static Intent buildOpenChatIntent(String participantId) {
@@ -42,10 +40,4 @@ public class BroadcastIntentHelper {
intent.putExtra("message", message);
return intent;
}
public static Intent buildSetVideoMutedIntent(boolean muted) {
Intent intent = new Intent(BroadcastAction.Type.SET_VIDEO_MUTED.getAction());
intent.putExtra("muted", muted);
return intent;
}
}

View File

@@ -85,7 +85,6 @@ class ExternalAPIModule
constants.put("OPEN_CHAT", BroadcastAction.Type.OPEN_CHAT.getAction());
constants.put("CLOSE_CHAT", BroadcastAction.Type.CLOSE_CHAT.getAction());
constants.put("SEND_CHAT_MESSAGE", BroadcastAction.Type.SEND_CHAT_MESSAGE.getAction());
constants.put("SET_VIDEO_MUTED", BroadcastAction.Type.SET_VIDEO_MUTED.getAction());
return constants;
}

View File

@@ -32,7 +32,6 @@ import com.facebook.react.modules.core.PermissionListener;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import java.util.HashMap;
import android.app.Activity;
/**
* A base activity for SDK users to embed. It uses {@link JitsiMeetFragment} to do the heavy
@@ -59,9 +58,6 @@ public class JitsiMeetActivity extends FragmentActivity
Intent intent = new Intent(context, JitsiMeetActivity.class);
intent.setAction(ACTION_JITSI_MEET_CONFERENCE);
intent.putExtra(JITSI_MEET_CONFERENCE_OPTIONS, options);
if (!(context instanceof Activity)) {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
context.startActivity(intent);
}

View File

@@ -132,7 +132,6 @@ public class JitsiMeetOngoingConferenceService extends Service
public void onCurrentConferenceChanged(String conferenceUrl) {
if (conferenceUrl == null) {
stopSelf();
OngoingNotification.resetStartingtime();
JitsiMeetLogger.i(TAG + "Service stopped");
}
}

View File

@@ -43,7 +43,6 @@ class OngoingNotification {
private static final String CHANNEL_NAME = "Ongoing Conference Notifications";
static final int NOTIFICATION_ID = new Random().nextInt(99999) + 10000;
private static long startingTime = 0;
static void createOngoingConferenceNotificationChannel() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
@@ -86,10 +85,6 @@ class OngoingNotification {
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID);
if (startingTime == 0) {
startingTime = System.currentTimeMillis();
}
builder
.setCategory(NotificationCompat.CATEGORY_CALL)
.setContentTitle(context.getString(R.string.ongoing_notification_title))
@@ -97,8 +92,6 @@ class OngoingNotification {
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingIntent)
.setOngoing(true)
.setWhen(startingTime)
.setUsesChronometer(true)
.setAutoCancel(false)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setOnlyAlertOnce(true)
@@ -117,10 +110,6 @@ class OngoingNotification {
return builder.build();
}
static void resetStartingtime() {
startingTime = 0;
}
private static NotificationCompat.Action createAction(Context context, JitsiMeetOngoingConferenceService.Action action, @StringRes int titleId) {
Intent intent = new Intent(context, JitsiMeetOngoingConferenceService.class);
intent.setAction(action.getName());

View File

@@ -178,6 +178,7 @@ class ReactInstanceManagerHolder {
List<ReactPackage> packages
= new ArrayList<>(Arrays.asList(
new com.BV.LinearGradient.LinearGradientPackage(),
new com.calendarevents.CalendarEventsPackage(),
new com.corbt.keepawake.KCKeepAwakePackage(),
new com.facebook.react.shell.MainReactPackage(),

View File

@@ -19,6 +19,8 @@ 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-linear-gradient'
project(':react-native-linear-gradient').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-linear-gradient/android')
include ':react-native-sound'
project(':react-native-sound').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-sound/android')
include ':react-native-splash-screen'

2
app.js
View File

@@ -1,6 +1,8 @@
/* application specific logic */
import 'jquery';
import 'jquery-contextmenu';
import 'jQuery-Impromptu';
import 'olm';

View File

@@ -1,12 +1,10 @@
/* global APP, JitsiMeetJS, config, interfaceConfig */
import { jitsiLocalStorage } from '@jitsi/js-utils';
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 mediaDeviceHelper from './modules/devices/mediaDeviceHelper';
@@ -101,7 +99,6 @@ import {
destroyLocalTracks,
getLocalJitsiAudioTrack,
getLocalJitsiVideoTrack,
getLocalTracks,
isLocalCameraTrackMuted,
isLocalTrackMuted,
isUserInteractionRequiredForUnmute,
@@ -118,7 +115,7 @@ import {
submitFeedback
} from './react/features/feedback';
import { showNotification } from './react/features/notifications';
import { mediaPermissionPromptVisibilityChanged, toggleSlowGUMOverlay } from './react/features/overlay';
import { mediaPermissionPromptVisibilityChanged } from './react/features/overlay';
import { suspendDetected } from './react/features/power-monitor';
import {
initPrejoin,
@@ -127,9 +124,8 @@ import {
makePrecallTest
} from './react/features/prejoin';
import { disableReceiver, stopReceiver } from './react/features/remote-control';
import { setScreenAudioShareState, isScreenAudioShared } from './react/features/screen-share/';
import { toggleScreenshotCaptureEffect } from './react/features/screenshot-capture';
import { setSharedVideoStatus } from './react/features/shared-video/actions';
import { setSharedVideoStatus } from './react/features/shared-video';
import { AudioMixerEffect } from './react/features/stream-effects/audio-mixer/AudioMixerEffect';
import { createPresenterEffect } from './react/features/stream-effects/presenter';
import { endpointMessageReceived } from './react/features/subtitles';
@@ -381,6 +377,7 @@ class ConferenceConnector {
if (this.reconnectTimeout !== null) {
clearTimeout(this.reconnectTimeout);
}
AuthHandler.closeAuth();
}
/**
@@ -395,8 +392,7 @@ class ConferenceConnector {
*
*/
connect() {
// the local storage overrides here and in connection.js can be used by jibri
room.join(jitsiLocalStorage.getItem('xmpp_conference_password_override'));
room.join();
}
}
@@ -477,13 +473,18 @@ export default {
*/
createInitialLocalTracks(options = {}) {
const errors = {};
// Always get a handle on the audio input device so that we have statistics (such as "No audio input" or
// "Are you trying to speak?" ) even if the user joins the conference muted.
const initialDevices = config.disableInitialGUM ? [] : [ 'audio' ];
const requestedAudio = !config.disableInitialGUM;
let requestedVideo = false;
// Always get a handle on the audio input device so that we have statistics even if the user joins the
// conference muted. Previous implementation would only acquire the handle when the user first unmuted,
// which would results in statistics ( such as "No audio input" or "Are you trying to speak?") being available
// only after that point.
if (options.startWithAudioMuted) {
this.muteAudio(true, true);
}
if (!config.disableInitialGUM
&& !options.startWithVideoMuted
&& !options.startAudioOnly
@@ -501,15 +502,10 @@ export default {
);
}
JitsiMeetJS.mediaDevices.addEventListener(
JitsiMediaDevicesEvents.SLOW_GET_USER_MEDIA,
() => APP.store.dispatch(toggleSlowGUMOverlay(true))
);
let tryCreateLocalTracks;
// On Electron there is no permission prompt for granting permissions. That's why we don't need to
// spend much time displaying the overlay screen. If GUM is not resolved within 15 seconds it will
// spend much time displaying the overlay screen. If GUM is not resolved withing 15 seconds it will
// probably never resolve.
const timeout = browser.isElectron() ? 15000 : 60000;
@@ -523,10 +519,8 @@ export default {
return createLocalTracksF({
devices: [ 'audio' ],
timeout,
firePermissionPromptIsShownEvent: true,
fireSlowPromiseEvent: true
})
timeout
}, true)
.then(([ audioStream ]) =>
[ desktopStream, audioStream ])
.catch(error => {
@@ -542,10 +536,8 @@ export default {
return requestedAudio
? createLocalTracksF({
devices: [ 'audio' ],
timeout,
firePermissionPromptIsShownEvent: true,
fireSlowPromiseEvent: true
})
timeout
}, true)
: [];
})
.catch(error => {
@@ -559,10 +551,8 @@ export default {
} else {
tryCreateLocalTracks = createLocalTracksF({
devices: initialDevices,
timeout,
firePermissionPromptIsShownEvent: true,
fireSlowPromiseEvent: true
})
timeout
}, true)
.catch(err => {
if (requestedAudio && requestedVideo) {
@@ -571,7 +561,7 @@ export default {
if (err.name === JitsiTrackErrors.TIMEOUT && !browser.isElectron()) {
// In this case we expect that the permission prompt is still visible. There is no point of
// executing GUM with different source. Also at the time of writing the following
// executing GUM with different source. Also at the time of writting the following
// inconsistency have been noticed in some browsers - if the permissions prompt is visible
// and another GUM is executed the prompt does not change its content but if the user
// clicks allow the user action isassociated with the latest GUM call.
@@ -584,10 +574,8 @@ export default {
return (
createLocalTracksF({
devices: [ 'audio' ],
timeout,
firePermissionPromptIsShownEvent: true,
fireSlowPromiseEvent: true
}));
timeout
}, true));
} else if (requestedAudio && !requestedVideo) {
errors.audioOnlyError = err;
@@ -610,9 +598,8 @@ export default {
return requestedVideo
? createLocalTracksF({
devices: [ 'video' ],
firePermissionPromptIsShownEvent: true,
fireSlowPromiseEvent: true
})
timeout
}, true)
: [];
})
.catch(err => {
@@ -628,11 +615,10 @@ export default {
// Hide the permissions prompt/overlay as soon as the tracks are
// created. Don't wait for the connection to be made, since in some
// cases, when auth is required, for instance, that won't happen until
// cases, when auth is rquired, for instance, that won't happen until
// the user inputs their credentials, but the dialog would be
// overshadowed by the overlay.
tryCreateLocalTracks.then(tracks => {
APP.store.dispatch(toggleSlowGUMOverlay(false));
APP.store.dispatch(mediaPermissionPromptVisibilityChanged(false));
return tracks;
@@ -823,16 +809,12 @@ export default {
return this._setLocalAudioVideoStreams(tracks);
}
const [ tracks, con ] = await this.createInitialLocalTracksAndConnect(roomName, initialOptions);
let localTracks = tracks;
const [ tracks, con ] = await this.createInitialLocalTracksAndConnect(
roomName, initialOptions);
this._initDeviceList(true);
if (initialOptions.startWithAudioMuted) {
localTracks = localTracks.filter(track => track.getType() !== MEDIA_TYPE.AUDIO);
}
return this.startConference(con, localTracks);
return this.startConference(con, tracks);
},
/**
@@ -900,7 +882,7 @@ export default {
showUI && APP.store.dispatch(notifyMicError(error));
};
createLocalTracksF({ devices: [ 'audio' ] })
createLocalTracksF({ devices: [ 'audio' ] }, false)
.then(([ audioTrack ]) => audioTrack)
.catch(error => {
maybeShowErrorDialog(error);
@@ -1014,7 +996,7 @@ export default {
//
// FIXME when local track creation is moved to react/redux
// it should take care of the use case described above
createLocalTracksF({ devices: [ 'video' ] })
createLocalTracksF({ devices: [ 'video' ] }, false)
.then(([ videoTrack ]) => videoTrack)
.catch(error => {
// FIXME should send some feedback to the API on error ?
@@ -1023,11 +1005,7 @@ export default {
// Rollback the video muted status by using null track
return null;
})
.then(videoTrack => {
logger.debug(`muteVideo: calling useVideoStream for track: ${videoTrack}`);
return this.useVideoStream(videoTrack);
});
.then(videoTrack => this.useVideoStream(videoTrack));
} else {
// FIXME show error dialog if it fails (should be handled by react)
muteLocalVideo(mute);
@@ -1327,11 +1305,7 @@ export default {
this._getConferenceOptions());
APP.store.dispatch(conferenceWillJoin(room));
// Filter out the tracks that are muted.
const tracks = localTracks.filter(track => !track.isMuted());
this._setLocalAudioVideoStreams(tracks);
this._setLocalAudioVideoStreams(localTracks);
this._room = room; // FIXME do not use this
sendLocalParticipant(APP.store, room);
@@ -1350,11 +1324,8 @@ export default {
if (track.isAudioTrack()) {
return this.useAudioStream(track);
} else if (track.isVideoTrack()) {
logger.debug(`_setLocalAudioVideoStreams is calling useVideoStream with track: ${track}`);
return this.useVideoStream(track);
}
logger.error(
'Ignored not an audio nor a video track: ', track);
@@ -1374,8 +1345,6 @@ export default {
* @returns {Promise}
*/
useVideoStream(newTrack) {
logger.debug(`useVideoStream: ${newTrack}`);
return new Promise((resolve, reject) => {
_replaceLocalVideoTrackQueue.enqueue(onFinish => {
const state = APP.store.getState();
@@ -1385,30 +1354,24 @@ export default {
if (isPrejoinPageVisible(state)) {
const oldTrack = getLocalJitsiVideoTrack(state);
logger.debug(`useVideoStream on the prejoin screen: Replacing ${oldTrack} with ${newTrack}`);
return APP.store.dispatch(replaceLocalTrack(oldTrack, newTrack))
.then(resolve)
.catch(error => {
logger.error(`useVideoStream failed on the prejoin screen: ${error}`);
reject(error);
})
.catch(reject)
.then(onFinish);
}
logger.debug(`useVideoStream: Replacing ${this.localVideo} with ${newTrack}`);
APP.store.dispatch(
replaceLocalTrack(this.localVideo, newTrack, room))
replaceLocalTrack(this.localVideo, newTrack, room))
.then(() => {
this.localVideo = newTrack;
this._setSharingScreen(newTrack);
if (newTrack) {
APP.UI.addLocalVideoStream(newTrack);
}
this.setVideoMuteStatus(this.isLocalVideoMuted());
})
.then(resolve)
.catch(error => {
logger.error(`useVideoStream failed: ${error}`);
reject(error);
})
.catch(reject)
.then(onFinish);
});
});
@@ -1553,15 +1516,9 @@ export default {
this._desktopAudioStream = undefined;
}
APP.store.dispatch(setScreenAudioShareState(false));
if (didHaveVideo) {
promise = promise.then(() => createLocalTracksF({ devices: [ 'video' ] }))
.then(([ stream ]) => {
logger.debug(`_turnScreenSharingOff using ${stream} for useVideoStream`);
return this.useVideoStream(stream);
})
.then(([ stream ]) => this.useVideoStream(stream))
.catch(error => {
logger.error('failed to switch back to local video', error);
@@ -1572,11 +1529,7 @@ export default {
);
});
} else {
promise = promise.then(() => {
logger.debug('_turnScreenSharingOff using null for useVideoStream');
return this.useVideoStream(null);
});
promise = promise.then(() => this.useVideoStream(null));
}
return promise.then(
@@ -1587,8 +1540,6 @@ export default {
},
error => {
this.videoSwitchInProgress = false;
logger.error(`_turnScreenSharingOff failed: ${error}`);
throw error;
});
},
@@ -1609,7 +1560,6 @@ export default {
* @return {Promise.<T>}
*/
async toggleScreenSharing(toggle = !this._untoggleScreenSharing, options = {}) {
logger.debug(`toggleScreenSharing: ${toggle}`);
if (this.videoSwitchInProgress) {
return Promise.reject('Switch in progress.');
}
@@ -1671,30 +1621,11 @@ export default {
= this._turnScreenSharingOff.bind(this, didHaveVideo);
const desktopVideoStream = desktopStreams.find(stream => stream.getType() === MEDIA_TYPE.VIDEO);
const dekstopAudioStream = desktopStreams.find(stream => stream.getType() === MEDIA_TYPE.AUDIO);
if (dekstopAudioStream) {
dekstopAudioStream.on(
JitsiTrackEvents.LOCAL_TRACK_STOPPED,
() => {
logger.debug(`Local screensharing audio track stopped. ${this.isSharingScreen}`);
// Handle case where screen share was stopped from the browsers 'screen share in progress'
// window. If audio screen sharing is stopped via the normal UX flow this point shouldn't
// be reached.
isScreenAudioShared(APP.store.getState())
&& this._untoggleScreenSharing
&& this._untoggleScreenSharing();
}
);
}
if (desktopVideoStream) {
desktopVideoStream.on(
JitsiTrackEvents.LOCAL_TRACK_STOPPED,
() => {
logger.debug(`Local screensharing track stopped. ${this.isSharingScreen}`);
// If the stream was stopped during screen sharing
// session then we should switch back to video.
this.isSharingScreen
@@ -1771,12 +1702,16 @@ export default {
const isPortrait = height >= width;
const DESKTOP_STREAM_CAP = 720;
// Config.js setting for resizing high resolution desktop tracks to 720p when presenter is turned on.
const resizeEnabled = config.videoQuality && config.videoQuality.resizeDesktopForPresenter;
const highResolutionTrack
= (isPortrait && width > DESKTOP_STREAM_CAP) || (!isPortrait && height > DESKTOP_STREAM_CAP);
// Resizing the desktop track for presenter is causing blurriness of the desktop share on chrome.
// Disable resizing by default, enable it only when config.js setting is enabled.
const resizeDesktopStream = highResolutionTrack && config.videoQuality?.resizeDesktopForPresenter;
// Firefox doesn't return width and height for desktop tracks. Therefore, track needs to be resized
// for creating the canvas for presenter.
const resizeDesktopStream = browser.isFirefox() || (highResolutionTrack && resizeEnabled);
if (resizeDesktopStream) {
let desktopResizeConstraints = {};
@@ -1794,7 +1729,7 @@ export default {
};
}
// Apply the constraints on the desktop track.
// Apply the contraints on the desktop track.
try {
await this.localVideo.track.applyConstraints(desktopResizeConstraints);
} catch (err) {
@@ -1852,28 +1787,13 @@ export default {
return this._createDesktopTrack(options)
.then(async streams => {
let desktopVideoStream = streams.find(stream => stream.getType() === MEDIA_TYPE.VIDEO);
this._desktopAudioStream = streams.find(stream => stream.getType() === MEDIA_TYPE.AUDIO);
const { audioOnly = false } = options;
// If we're in audio only mode dispose of the video track otherwise the screensharing state will be
// inconsistent.
if (audioOnly) {
desktopVideoStream.dispose();
desktopVideoStream = undefined;
if (!this._desktopAudioStream) {
return Promise.reject(AUDIO_ONLY_SCREEN_SHARE_NO_TRACK);
}
}
const desktopVideoStream = streams.find(stream => stream.getType() === MEDIA_TYPE.VIDEO);
if (desktopVideoStream) {
logger.debug(`_switchToScreenSharing is using ${desktopVideoStream} for useVideoStream`);
await this.useVideoStream(desktopVideoStream);
}
this._desktopAudioStream = streams.find(stream => stream.getType() === MEDIA_TYPE.AUDIO);
if (this._desktopAudioStream) {
// If there is a localAudio stream, mix in the desktop audio stream captured by the screen sharing
@@ -1886,9 +1806,7 @@ export default {
// If no local stream is present ( i.e. no input audio devices) we use the screen share audio
// stream as we would use a regular stream.
await this.useAudioStream(this._desktopAudioStream);
}
APP.store.dispatch(setScreenAudioShareState(true));
}
})
.then(() => {
@@ -1956,9 +1874,6 @@ export default {
} else if (error.name === JitsiTrackErrors.SCREENSHARING_GENERIC_ERROR) {
descriptionKey = 'dialog.screenSharingFailed';
titleKey = 'dialog.screenSharingFailedTitle';
} else if (error === AUDIO_ONLY_SCREEN_SHARE_NO_TRACK) {
descriptionKey = 'notify.screenShareNoAudio';
titleKey = 'notify.screenShareNoAudioTitle';
}
APP.UI.messageHandler.showError({
@@ -2004,7 +1919,7 @@ export default {
}
APP.store.dispatch(updateRemoteParticipantFeatures(user));
logger.log(`USER ${id} connected:`, user);
logger.log(`USER ${id} connnected:`, user);
APP.UI.addUser(user);
});
@@ -2078,11 +1993,7 @@ export default {
room.on(JitsiConferenceEvents.TRACK_MUTE_CHANGED, (track, participantThatMutedUs) => {
if (participantThatMutedUs) {
APP.store.dispatch(participantMutedUs(participantThatMutedUs, track));
if (this.isSharingScreen && track.isVideoTrack()) {
logger.debug('TRACK_MUTE_CHANGED while screen sharing');
this._turnScreenSharingOff(false);
}
APP.store.dispatch(participantMutedUs(participantThatMutedUs));
}
});
@@ -2234,26 +2145,8 @@ export default {
}
);
room.on(JitsiConferenceEvents.STARTED_MUTED, () => {
const audioMuted = room.isStartAudioMuted();
const videoMuted = room.isStartVideoMuted();
const localTracks = getLocalTracks(APP.store.getState()['features/base/tracks']);
const promises = [];
APP.store.dispatch(setAudioMuted(audioMuted));
APP.store.dispatch(setVideoMuted(videoMuted));
// Remove the tracks from the peerconnection.
for (const track of localTracks) {
if (audioMuted && track.jitsiTrack?.getType() === MEDIA_TYPE.AUDIO) {
promises.push(this.useAudioStream(null));
}
if (videoMuted && track.jitsiTrack?.getType() === MEDIA_TYPE.VIDEO) {
promises.push(this.useVideoStream(null));
}
}
Promise.allSettled(promises)
.then(() => APP.UI.notifyInitiallyMuted());
(room.isStartAudioMuted() || room.isStartVideoMuted())
&& APP.UI.notifyInitiallyMuted();
});
room.on(
@@ -2304,7 +2197,7 @@ export default {
.then(effect => this.localVideo.setEffect(effect))
.then(() => {
this.setVideoMuteStatus(false);
logger.log('Switched local video device while screen sharing and the video is unmuted');
logger.log('switched local video device');
this._updateVideoDeviceId();
})
.catch(err => APP.store.dispatch(notifyCameraError(err)));
@@ -2313,7 +2206,7 @@ export default {
// id for video, dispose the existing presenter track and create a new effect
// that can be applied on un-mute.
} else if (this.isSharingScreen && videoWasMuted) {
logger.log('Switched local video device: while screen sharing and the video is muted');
logger.log('switched local video device');
const { height } = this.localVideo.track.getSettings();
this._updateVideoDeviceId();
@@ -2340,20 +2233,12 @@ export default {
return stream;
})
.then(stream => {
logger.log('Switching the local video device.');
return this.useVideoStream(stream);
})
.then(stream => this.useVideoStream(stream))
.then(() => {
logger.log('Switched local video device.');
logger.log('switched local video device');
this._updateVideoDeviceId();
})
.catch(error => {
logger.error(`Switching the local video device failed: ${error}`);
return APP.store.dispatch(notifyCameraError(error));
});
.catch(err => APP.store.dispatch(notifyCameraError(err)));
}
}
);
@@ -2442,17 +2327,11 @@ export default {
// There is no guarantee another event will trigger the update
// immediately and in all situations, for example because a remote
// participant is having connection trouble so no status changes.
const displayedUserId = APP.UI.getLargeVideoID();
if (displayedUserId) {
APP.UI.updateLargeVideo(displayedUserId, true);
}
APP.UI.updateAllVideos();
});
APP.UI.addListener(
UIEvents.TOGGLE_SCREENSHARING, audioOnly => {
this.toggleScreenSharing(undefined, { audioOnly });
}
UIEvents.TOGGLE_SCREENSHARING, this.toggleScreenSharing.bind(this)
);
/* eslint-disable max-params */
@@ -2711,7 +2590,6 @@ export default {
delete newDevices.videoinput;
// Removing the current video track in order to force the unmute to select the preferred device.
logger.debug('_onDeviceListChanged: Removing the current video track.');
this.useVideoStream(null);
}

111
config.js
View File

@@ -59,10 +59,8 @@ var config = {
// simulcast is turned off for the desktop share. If presenter is turned
// on while screensharing is in progress, the max bitrate is automatically
// adjusted to 2.5 Mbps. This takes a value between 0 and 1 which determines
// the probability for this to be enabled. This setting has been deprecated.
// desktopSharingFrameRate.max now determines whether simulcast will be enabled
// or disabled for the screenshare.
// capScreenshareBitrate: 1 // 0 to disable - deprecated.
// the probability for this to be enabled.
// capScreenshareBitrate: 1 // 0 to disable
// Enable callstats only for a percentage of users.
// This takes a value between 0 and 100 which determines the probability for
@@ -119,15 +117,13 @@ var config = {
// participants and to enable it back a reload is needed.
// startSilent: false
// Enables support for opus-red (redundancy for Opus).
// enableOpusRed: false,
// Sets the preferred target bitrate for the Opus audio codec by setting its
// 'maxaveragebitrate' parameter. Currently not available in p2p mode.
// Valid values are in the range 6000 to 510000
// opusMaxAverageBitrate: 20000,
// Specify audio quality stereo and opusMaxAverageBitrate values in order to enable HD audio.
// Beware, by doing so, you are disabling echo cancellation, noise suppression and AGC.
// audioQuality: {
// stereo: false,
// opusMaxAverageBitrate: null // Value to fit the 6000 to 510000 range.
// },
// Enables support for opus-red (redundancy for Opus).
// enableOpusRed: false
// Video
@@ -228,11 +224,6 @@ var config = {
// Default value for the channel "last N" attribute. -1 for unlimited.
channelLastN: -1,
// Provides a way for the lastN value to be controlled through the UI.
// When startLastN is present, conference starts with a last-n value of startLastN and channelLastN
// value will be used when the quality level is selected using "Manage Video Quality" slider.
// startLastN: 1,
// Provides a way to use different "last N" values based on the number of participants in the conference.
// The keys in an Object represent number of participants and the values are "last N" to be used when number of
// participants gets to or above the number.
@@ -249,12 +240,6 @@ var config = {
// 90: 2
// },
// Provides a way to translate the legacy bridge signaling messages, 'LastNChangedEvent',
// 'SelectedEndpointsChangedEvent' and 'ReceiverVideoConstraint' into the new 'ReceiverVideoConstraints' message
// that invokes the new bandwidth allocation algorithm in the bridge which is described here
// - https://github.com/jitsi/jitsi-videobridge/blob/master/doc/allocation.md.
// useNewBandwidthAllocationStrategy: false,
// Specify the settings for video quality optimizations on the client.
// videoQuality: {
// // Provides a way to prevent a video codec from being negotiated on the JVB connection. The codec specified
@@ -270,24 +255,12 @@ var config = {
// // to take effect.
// preferredCodec: 'VP8',
//
// // Provides a way to enforce the preferred codec for the conference even when the conference has endpoints
// // that do not support the preferred codec. For example, older versions of Safari do not support VP9 yet.
// // This will result in Safari not being able to decode video from endpoints sending VP9 video.
// // When set to false, the conference falls back to VP8 whenever there is an endpoint that doesn't support the
// // preferred codec and goes back to the preferred codec when that endpoint leaves.
// // enforcePreferredCodec: false,
//
// // Provides a way to configure the maximum bitrates that will be enforced on the simulcast streams for
// // video tracks. The keys in the object represent the type of the stream (LD, SD or HD) and the values
// // are the max.bitrates to be set on that particular type of stream. The actual send may vary based on
// // the available bandwidth calculated by the browser, but it will be capped by the values specified here.
// // This is currently not implemented on app based clients on mobile.
// maxBitratesVideo: {
// H264: {
// low: 200000,
// standard: 500000,
// high: 1500000
// },
// VP8 : {
// low: 200000,
// standard: 500000,
@@ -353,7 +326,8 @@ var config = {
// enableIceRestart: false,
// Enables forced reload of the client when the call is migrated as a result of
// the bridge going down.
// the bridge going down. Currently enabled by default as call migration through
// session-terminate is causing siganling issues when Octo is enabled.
// enableForcedReload: true,
// Use TURN/UDP servers for the jitsi-videobridge connection (by default
@@ -432,26 +406,7 @@ var config = {
// enableAutomaticUrlCopy: false,
// Base URL for a Gravatar-compatible service. Defaults to libravatar.
// gravatarBaseURL: 'https://seccdn.libravatar.org/avatar/',
// Moved from interfaceConfig(TOOLBAR_BUTTONS).
// The name of the toolbar buttons to display in the toolbar, including the
// "More actions" menu. If present, the button will display. Exceptions are
// "livestreaming" and "recording" which also require being a moderator and
// some other values in config.js to be enabled. Also, the "profile" button will
// not display for users with a JWT.
// Notes:
// - it's impossible to choose which buttons go in the "More actions" menu
// - it's impossible to control the placement of buttons
// - 'desktop' controls the "Share your screen" button
// - if `toolbarButtons` is undefined, we fallback to enabling all buttons on the UI
// toolbarButtons: [
// 'microphone', 'camera', 'closedcaptions', 'desktop', 'embedmeeting', 'fullscreen',
// 'fodeviceselection', 'hangup', 'profile', 'chat', 'recording',
// 'livestreaming', 'etherpad', 'sharedvideo', 'shareaudio', 'settings', 'raisehand',
// 'videoquality', 'filmstrip', 'invite', 'feedback', 'stats', 'shortcuts',
// 'tileview', 'select-background', 'download', 'help', 'mute-everyone', 'mute-video-everyone', 'security'
// ],
// gravatarBaseURL: 'https://seccdn.libravatar.org/avatar/';
// Stats
//
@@ -476,10 +431,6 @@ var config = {
// Enables sending participants' emails (if available) to callstats and other analytics
// enableEmailInStats: false,
// 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,
// Privacy
//
@@ -501,6 +452,13 @@ var config = {
// connection.
enabled: true,
// The STUN servers that will be used in the peer to peer connections
stunServers: [
// { urls: 'stun:jitsi-meet.example.com:3478' },
{ urls: 'stun:meet-jit-si-turnrelay.jitsi.net:443' }
]
// Sets the ICE transport policy for the p2p connection. At the time
// of this writing the list of possible values are 'all' and 'relay',
// but that is subject to change in the future. The enum is defined in
@@ -511,7 +469,7 @@ var config = {
// If set to true, it will prefer to use H.264 for P2P calls (if H.264
// is supported). This setting is deprecated, use preferredCodec instead.
// preferH264: true,
// preferH264: true
// Provides a way to set the video codec preference on the p2p connection. Acceptable
// codec values are 'VP8', 'VP9' and 'H264'.
@@ -526,14 +484,7 @@ var config = {
// How long we're going to wait, before going back to P2P after the 3rd
// participant has left the conference (to filter out page reload).
// backToP2PDelay: 5,
// The STUN servers that will be used in the peer to peer connections
stunServers: [
// { urls: 'stun:jitsi-meet.example.com:3478' },
{ urls: 'stun:meet-jit-si-turnrelay.jitsi.net:443' }
]
// backToP2PDelay: 5
},
analytics: {
@@ -560,7 +511,7 @@ var config = {
// The interval at which rtcstats will poll getStats, defaults to 1000ms.
// If the value is set to 0 getStats won't be polled and the rtcstats client
// will only send data related to RTCPeerConnection events.
// rtcstatsPolIInterval: 1000,
// rtcstatsPolIInterval: 1000
// Array of script URLs to load as lib-jitsi-meet "analytics handlers".
// scriptURLs: [
@@ -583,10 +534,6 @@ var config = {
// Decides whether the start/stop recording audio notifications should play on record.
// disableRecordAudioNotification: false,
// Disables the sounds that play when other participants join or leave the
// conference (if set to true, these sounds will not be played).
// disableJoinLeaveSounds: false,
// Information for the chrome extension banner
// chromeExtensionBanner: {
// // The chrome extension to be installed address
@@ -646,10 +593,6 @@ var config = {
// the menu has option to flip the locally seen video for local presentations
// disableLocalVideoFlip: false,
// A property used to unset the default flip state of the local video.
// When it is set to 'true', the local(self) video will not be mirrored anymore.
// doNotFlipLocalVideo: false,
// Mainly privacy related settings
// Disables all invite functions from the app (share, invite, dial out...etc)
@@ -697,9 +640,6 @@ var config = {
*/
// dynamicBrandingUrl: '',
// Sets the background transparency level. '0' is fully transparent, '1' is opaque.
// backgroundAlpha: 1,
// The URL of the moderated rooms microservice, if available. If it
// is present, a link to the service will be rendered on the welcome page,
// otherwise the app doesn't render it.
@@ -709,22 +649,17 @@ var config = {
// disableTileView: true,
// Hides the conference subject
// hideConferenceSubject: true,
// hideConferenceSubject: true
// Hides the conference timer.
// hideConferenceTimer: true,
// Hides the participants stats
// hideParticipantsStats: true,
// hideParticipantsStats: true
// Sets the conference subject
// subject: 'Conference 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.
// useHostPageLocalStorage: true,
// List of undocumented settings used in jitsi-meet
/**
_immediateReloadThreshold

View File

@@ -3,20 +3,18 @@
import { jitsiLocalStorage } from '@jitsi/js-utils';
import Logger from 'jitsi-meet-logger';
import { redirectToTokenAuthService } from './modules/UI/authentication/AuthHandler';
import { LoginDialog } from './react/features/authentication/components';
import { isTokenAuthEnabled } from './react/features/authentication/functions';
import AuthHandler from './modules/UI/authentication/AuthHandler';
import {
connectionEstablished,
connectionFailed
} from './react/features/base/connection/actions';
import { openDialog } from './react/features/base/dialog/actions';
import {
isFatalJitsiConnectionError,
JitsiConnectionErrors,
JitsiConnectionEvents
} from './react/features/base/lib-jitsi-meet';
import { setPrejoinDisplayNameRequired } from './react/features/prejoin/actions';
const logger = Logger.getLogger(__filename);
/**
@@ -82,7 +80,7 @@ function checkForAttachParametersAndConnect(id, password, connection) {
* @returns {Promise<JitsiConnection>} connection if
* everything is ok, else error.
*/
export function connect(id, password, roomName) {
function connect(id, password, roomName) {
const connectionConfig = Object.assign({}, config);
const { jwt } = APP.store.getState()['features/base/jwt'];
@@ -216,38 +214,10 @@ export function openConnection({ id, password, retry, roomName }) {
const { jwt } = APP.store.getState()['features/base/jwt'];
if (err === JitsiConnectionErrors.PASSWORD_REQUIRED && !jwt) {
return requestAuth(roomName);
return AuthHandler.requestAuth(roomName, connect);
}
}
throw err;
});
}
/**
* Show Authentication Dialog and try to connect with new credentials.
* If failed to connect because of PASSWORD_REQUIRED error
* then ask for password again.
* @param {string} [roomName] name of the conference room
*
* @returns {Promise<JitsiConnection>}
*/
function requestAuth(roomName) {
const config = APP.store.getState()['features/base/config'];
if (isTokenAuthEnabled(config)) {
// This Promise never resolves as user gets redirected to another URL
return new Promise(() => redirectToTokenAuthService(roomName));
}
return new Promise(resolve => {
const onSuccess = connection => {
resolve(connection);
};
APP.store.dispatch(
openDialog(LoginDialog, { onSuccess,
roomName })
);
});
}

View File

@@ -1,21 +1,3 @@
/**
* Mixins that mimic the way Atlaskit fills the screen with modals at low screen widths.
*/
@mixin full-size-modal-positioner() {
height: 100%;
left: 0;
position: fixed;
top: 0;
max-width: 100%;
width: 100%;
}
@mixin full-size-modal-dialog() {
height: 100%;
max-height: 100%;
border-radius: 0;
}
/**
* Move the @atlaskit/flag container up a little bit so it does not cover the
* toolbar with the first notification.
@@ -72,63 +54,6 @@
* Keep overflow menu within screen vertical bounds and make it scrollable.
*/
.toolbox-button-wth-dialog > div:nth-child(2) {
background: $menuBG;
max-height: calc(100vh - #{$newToolbarSizeWithPadding} - 46px);
margin-bottom: 4px;
padding: 0;
overflow-y: auto;
}
.audio-preview > div:nth-child(2),
.video-preview > div:nth-child(2) {
margin-bottom: 4px;
outline: none;
padding: 0;
}
/**
* The following selectors keep the chat modal full-size anywhere between 100px
* and 580px for desktop or 680px for mobile.
*/
@media (min-width: 100px) and (max-width: 320px) {
.smiley-input {
display: none;
}
.shift-right .focus-lock > div > div {
@include full-size-modal-positioner();
}
.shift-right .focus-lock [role="dialog"] {
@include full-size-modal-dialog();
}
}
@media (min-width: 480px) and (max-width: 580px) {
.shift-right .focus-lock > div > div {
@include full-size-modal-positioner();
}
.shift-right .focus-lock [role="dialog"] {
@include full-size-modal-dialog();
}
}
@media (max-width: 580px) {
// Override Atlaskit inline style for the modal background.
// Important is unfortunately needed for that.
.shift-right .focus-lock [role="dialog"][style] {
background-color: $chatBackgroundColor !important;
}
// Remove Atlaskit padding from the chat dialog.
.shift-right .focus-lock [role="dialog"] > div:first-child > div:nth-child(2) {
padding: 0;
}
}
div.Tooltip {
color: #fff;
font-size: 12px;
line-height: 14px;
padding: 8px;
}
}

View File

@@ -1,37 +1,26 @@
.audio-preview {
display: inline-block;
&-content {
background: $menuBG;
border-radius: 3px;
font-size: 14px;
background: #2A3A4B;
font-size: 15px;
line-height: 24px;
max-height: 456px;
overflow: auto;
width: 300px;
width: 328px;
}
&-header {
color: #fff;
align-items: center;
display: flex;
margin-top: 8px;
padding: 8px 16px;
padding: 16px;
&-icon {
color: #A4B8D1;
display: inline-block;
svg {
fill: #fff;
}
}
&--bordered {
border-bottom: 1px solid #4C4D50;
}
&-text {
margin-left: 12px;
font-weight: bold;
margin-left: 8px;
}
}
@@ -40,18 +29,19 @@
color: #fff;
cursor: pointer;
display: flex;
padding: 8px 0;
padding: 12px 0;
margin-left: 48px;
&--selected {
background: #131519;
background: #1C2025;
cursor: initial;
margin-left: 0;
padding-left: 18px;
padding-left: 21px;
}
&-text {
color: #fff;
font-size: 15px;
display: inline-block;
line-height: 24px;
text-overflow: ellipsis;
@@ -66,13 +56,12 @@
&:hover {
.audio-preview-entry {
background: #36383C;
background: #3F4E5E;
margin-left: 0;
padding-left: 48px;
&--selected {
padding-left: 18px;
background: $newToolbarBackgroundColor;
padding-left: 21px;
}
}
@@ -85,10 +74,6 @@
}
}
&:last-child {
padding-bottom: 8px;
}
.audio-preview-entry-text {
max-width: 256px;
}
@@ -99,19 +84,18 @@
&:hover {
.audio-preview-entry {
background: #36383C;
background: #3F4E5E;
margin-left: 0;
padding-left: 48px;
&--selected {
background: $newToolbarBackgroundColor;
padding-left: 18px;
padding-left: 21px;
}
}
}
.audio-preview-entry-text {
max-width: 178px;
max-width: 196px;
}
}
@@ -126,7 +110,7 @@
&--check {
background: #31B76A;
margin-right: 16px;
margin-right: 13px;
}
&--exclamation {
@@ -137,11 +121,6 @@
}
}
&-hr {
border-top: 1px solid #4C4D50;
border-bottom: 0;
}
&-test-button {
display: none;
background: #FFF;
@@ -150,16 +129,23 @@
color: #1C2025;
cursor: pointer;
font-weight: 600;
font-size: 15px;
line-height: 24px;
padding: 2px 16px;
padding: 4px 16px;
position: absolute;
right: 16px;
top: 5px;
top: 8px;
}
&-meter-mic {
position: absolute;
right: 16px;
top: 14px;
top: 18px;
}
// Override @atlaskit/InlineDialog container which is made with styled components
& > div:nth-child(2) {
outline: none;
padding: 0;
}
}

View File

@@ -55,10 +55,6 @@ body {
fill: white;
}
.disabled .jitsi-icon svg {
fill: #929292;
}
.jitsi-icon.gray svg {
fill: #5E6D7A;
cursor: pointer;

View File

@@ -1,5 +1,5 @@
#sideToolbarContainer {
background-color: $chatBackgroundColor;
background-color: $newToolbarBackgroundColor;
box-sizing: border-box;
color: #FFF;
display: flex;
@@ -32,13 +32,6 @@
width: $sidebarWidth;
word-wrap: break-word;
display: flex;
flex-direction: column;
& > :first-child {
margin-top: auto;
}
a {
display: block;
}
@@ -105,12 +98,13 @@
}
.chat-header {
background-color: $chatHeaderBackgroundColor;
height: 70px;
position: relative;
width: 100%;
z-index: 1;
display: flex;
justify-content: flex-end;
justify-content: space-between;
padding: 16px;
align-items: center;
box-sizing: border-box;
@@ -122,85 +116,22 @@
.jitsi-icon {
cursor: pointer;
}
}
.chat-input-container {
padding: 0 16px 16px;
&.populated {
#chat-input {
.send-button {
background: #1B67EC;
cursor: pointer;
@media (hover: hover) and (pointer: fine) {
&:hover {
background: #3D82FB;
}
}
&:active {
background: #0852D4;
}
path {
fill: #fff;
}
}
}
.jitsi-icon > svg {
fill: #A4B8D1;
}
}
#chat-input {
border: 1px solid $chatInputSeparatorColor;
border-top: 1px solid $chatInputSeparatorColor;
display: flex;
padding: 4px;
border-radius: 3px;
&:focus-within {
border: 1px solid #619CF4;
}
padding: 5px 10px;
* {
background-color: transparent;
}
}
.send-button-container {
display: flex;
align-items: center;
}
.send-button {
display: flex;
align-items: center;
justify-content: center;
height: 40px;
width: 40px;
border-radius: 3px;
path {
fill: $chatInputSeparatorColor;
}
}
.smiley-button {
display: flex;
align-items: center;
justify-content: center;
height: 40px;
width: 40px;
border-radius: 3px;
}
#chat-input .smiley-button {
@media (hover: hover) and (pointer: fine) {
&:hover {
background-color: #484A4F;
}
}
}
.remoteuser {
color: #B8C7E0;
}
@@ -214,7 +145,7 @@
border-radius:0;
box-shadow: none;
color: white;
font-size: 14px;
font-size: 15px;
padding: 10px;
overflow-y: auto;
resize: none;
@@ -230,55 +161,10 @@
#nickname {
text-align: center;
color: #9d9d9d;
font-size: 16px;
margin: auto 0;
padding: 0 16px;
input {
height: 40px;
}
label {
line-height: 24px;
}
.enter-chat {
display: flex;
align-items: center;
justify-content: center;
margin-top: 16px;
height: 40px;
background: #1B67EC;
border-radius: 3px;
color: #fff;
cursor: pointer;
&.disabled {
color: #757575;
background: #11336E;
pointer-events: none;
}
}
}
.mobile-browser {
#nickname {
input {
height: 48px;
}
.enter-chat {
height: 48px;
}
}
#usermsg {
font-size: 16px;
}
.chatmessage .usermessage {
font-size: 16px;
}
font-size: 18px;
margin-top: 30px;
left: 5px;
right: 5px;
}
.sideToolbarContainer {
@@ -288,8 +174,8 @@
}
.display-name {
font-size: 12px;
font-weight: 600;
font-size: 13px;
font-weight: bold;
margin-bottom: 5px;
white-space: nowrap;
text-overflow: ellipsis;
@@ -317,7 +203,6 @@
.usermessage {
white-space: pre-wrap;
font-size: 14px;
}
&.error {
@@ -340,16 +225,12 @@
}
.messagecontent {
margin: 8px;
margin: 5px 10px;
max-width: 100%;
overflow: hidden;
}
}
.timestamp {
color: #757575;
}
.smiley {
font-size: 14pt;
}
@@ -385,9 +266,7 @@
max-height: 0;
overflow: hidden;
position: absolute;
width: calc(#{$sidebarWidth} - 32px);
margin-bottom: 5px;
margin-left: -5px;
width: $sidebarWidth;
/**
* CSS transitions do not apply for auto dimensions. So to produce the css
@@ -402,8 +281,9 @@
}
#smileysContainer {
background-color: $chatBackgroundColor;
border-top: 1px solid $chatInputSeparatorColor;
background-color: $newToolbarBackgroundColor;
border-bottom: 1px solid;
border-top: 1px solid;
}
}
@@ -509,9 +389,9 @@
&-header {
display: flex;
justify-content: flex-end;
justify-content: space-between;
align-items: center;
margin: 16px;
margin: 16px 16px 24px;
width: calc(100% - 32px);
box-sizing: border-box;
color: #fff;
@@ -522,6 +402,10 @@
.jitsi-icon {
cursor: pointer;
}
.jitsi-icon > svg {
fill: #A4B8D1;
}
}
#chatconversation {
@@ -529,12 +413,6 @@
}
}
.touchmove-hack {
display: flex;
flex: 1;
overflow: auto;
}
/**
* Make header close button more easily tappable on mobile.
*/
@@ -543,6 +421,6 @@
place-items: center;
height: 48px;
width: 48px;
background: #36383C;
background: #2a3a4b;
border-radius: 3px;
}

View File

@@ -7,6 +7,7 @@
}
.drawer-menu {
padding: 0 16px;
max-height: 50vh;
background: #242528;
border-radius: 16px 16px 0 0;
@@ -23,6 +24,12 @@
height: 44px;
cursor: pointer;
@media (hover: hover) and (pointer: fine) {
&:hover {
background-color: $overflowMenuItemHoverBG;
}
}
svg {
fill: none;
}
@@ -60,6 +67,13 @@
align-items: center;
}
@media (hover: hover) and (pointer: fine) {
&:hover {
background-color: $overflowMenuItemHoverBG;
color: $overflowMenuItemHoverColor;
}
}
&.unclickable {
cursor: default;
}
@@ -74,6 +88,42 @@
}
}
.beta-tag {
background: $overflowMenuItemColor;
border-radius: 2px;
color: $overflowMenuBG;
font-size: 11px;
font-weight: bold;
margin-left: 8px;
padding: 0 6px;
}
.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: #B8C7E0 !important;
height: 20px;
width: 20px;
}
}
.profile-text {
max-width: 100%;
text-overflow: ellipsis;

129
css/_jquery-impromptu.scss Normal file
View File

@@ -0,0 +1,129 @@
/*
------------------------------
Impromptu
------------------------------
*/
.jqifade{
position: absolute;
background-color: #000;
}
div.jqi{
width: 400px;
position: absolute;
color: #3a3a3a;
background-color: #ffffff;
font-size: 11px;
text-align: left;
border: solid 1px #eeeeee;
border-radius: 6px;
-moz-border-radius: 6px;
-webkit-border-radius: 6px;
padding: 7px;
}
div.jqi .jqicontainer{
}
div.jqi .jqiclose{
position: absolute;
top: 4px; right: -2px;
width: 18px;
cursor: default;
color: #bbbbbb;
font-weight: bold;
}
div.jqi .jqistate{
background-color: #fff;
}
div.jqi .jqititle{
padding: 5px 10px;
font-size: 16px;
line-height: 20px;
border-bottom: solid 1px #eeeeee;
}
div.jqi .jqimessage{
padding: 10px;
line-height: 20px;
color: #444444;
}
div.jqi .jqibuttons{
text-align: right;
margin: 0 -7px -7px -7px;
border-top: solid 1px #e4e4e4;
background-color: #f4f4f4;
border-radius: 0 0 6px 6px;
-moz-border-radius: 0 0 6px 6px;
-webkit-border-radius: 0 0 6px 6px;
}
div.jqi .jqibuttons button{
margin: 0;
padding: 5px 20px;
background-color: transparent !important;
font-weight: normal;
border: none;
border-left: solid 1px #e4e4e4;
color: #777;
font-weight: bold;
font-size: 12px;
}
div.jqi .jqibuttons button.jqidefaultbutton{
color: #489afe;
}
div.jqi .jqibuttons button:disabled {
color: #b6b6b6 !important;
}
div.jqi .jqibuttons button:hover,
div.jqi .jqibuttons button:focus{
color: #287ade;
outline: none;
}
.jqiwarning .jqi .jqibuttons{
background-color: #b95656;
}
/* sub states */
div.jqi .jqiparentstate::after{
background-color: #777;
opacity: 0.6;
filter: alpha(opacity=60);
content: '';
position: absolute;
top:0;left:0;bottom:0;right:0;
border-radius: 6px;
-moz-border-radius: 6px;
-webkit-border-radius: 6px;
}
div.jqi .jqisubstate{
position: absolute;
top:0;
left: 20%;
width: 60%;
padding: 7px;
border: solid 1px #eeeeee;
border-top: none;
border-radius: 0 0 6px 6px;
-moz-border-radius: 0 0 6px 6px;
-webkit-border-radius: 0 0 6px 6px;
}
div.jqi .jqisubstate .jqibuttons button{
padding: 10px 18px;
}
/* arrows for tooltips/tours */
.jqi .jqiarrow{ position: absolute; height: 0; width:0; line-height: 0; font-size: 0; border: solid 10px transparent;}
.jqi .jqiarrowtl{ left: 10px; top: -20px; border-bottom-color: #ffffff; }
.jqi .jqiarrowtc{ left: 50%; top: -20px; border-bottom-color: #ffffff; margin-left: -10px; }
.jqi .jqiarrowtr{ right: 10px; top: -20px; border-bottom-color: #ffffff; }
.jqi .jqiarrowbl{ left: 10px; bottom: -20px; border-top-color: #ffffff; }
.jqi .jqiarrowbc{ left: 50%; bottom: -20px; border-top-color: #ffffff; margin-left: -10px; }
.jqi .jqiarrowbr{ right: 10px; bottom: -20px; border-top-color: #ffffff; }
.jqi .jqiarrowlt{ left: -20px; top: 10px; border-right-color: #ffffff; }
.jqi .jqiarrowlm{ left: -20px; top: 50%; border-right-color: #ffffff; margin-top: -10px; }
.jqi .jqiarrowlb{ left: -20px; bottom: 10px; border-right-color: #ffffff; }
.jqi .jqiarrowrt{ right: -20px; top: 10px; border-left-color: #ffffff; }
.jqi .jqiarrowrm{ right: -20px; top: 50%; border-left-color: #ffffff; margin-top: -10px; }
.jqi .jqiarrowrb{ right: -20px; bottom: 10px; border-left-color: #ffffff; }

View File

@@ -0,0 +1,206 @@
@charset "UTF-8";
/*!
* jQuery contextMenu - Plugin for simple contextMenu handling
*
* Version: v2.1.1
*
* Authors: Björn Brala (SWIS.nl), Rodney Rehm, Addy Osmani (patches for FF)
* Web: http://swisnl.github.io/jQuery-contextMenu/
*
* Copyright (c) 2011-2016 SWIS BV and contributors
*
* Licensed under
* MIT License http://www.opensource.org/licenses/mit-license
*
* Date: 2016-02-28T09:53:18.890Z
*/
@font-face {
font-family: "context-menu-icons";
font-style: normal;
font-weight: normal;
src: url("font/context-menu-icons.eot?2qmzf");
src: url("font/context-menu-icons.eot?2qmzf#iefix") format("embedded-opentype"), url("font/context-menu-icons.woff2?2qmzf") format("woff2"), url("font/context-menu-icons.woff?2qmzf") format("woff"), url("font/context-menu-icons.ttf?2qmzf") format("truetype");
}
.context-menu-icon:before {
position: absolute;
top: 50%;
left: 0;
width: 28px;
font-family: "context-menu-icons";
font-size: 16px;
font-style: normal;
font-weight: normal;
line-height: 1;
color: #2980b9;
text-align: center;
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
-o-transform: translateY(-50%);
transform: translateY(-50%);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.context-menu-icon-add:before {
content: "";
}
.context-menu-icon-copy:before {
content: "";
}
.context-menu-icon-cut:before {
content: "";
}
.context-menu-icon-delete:before {
content: "";
}
.context-menu-icon-edit:before {
content: "";
}
.context-menu-icon-paste:before {
content: "";
}
.context-menu-icon-quit:before {
content: "";
}
.context-menu-icon.context-menu-hover:before {
color: #fff;
}
.context-menu-list {
position: absolute;
display: inline-block;
min-width: 180px;
max-width: 360px;
padding: 4px 0;
margin: 5px;
font-family: inherit;
font-size: inherit;
list-style-type: none;
background: #fff;
border: 1px solid #bebebe;
border-radius: $borderRadius;
-webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, .5);
box-shadow: 0 2px 5px rgba(0, 0, 0, .5);
}
.context-menu-item {
position: relative;
padding: 3px 28px;
color: #2f2f2f;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-color: #fff;
}
.context-menu-separator {
padding: 0;
margin: 5px 0;
border-bottom: 1px solid #e6e6e6;
}
.context-menu-item > label > input,
.context-menu-item > label > textarea {
-webkit-user-select: text;
-moz-user-select: text;
-ms-user-select: text;
user-select: text;
}
.context-menu-item.context-menu-hover {
color: #fff;
cursor: pointer;
background-color: #2980b9;
}
.context-menu-item.context-menu-disabled {
color: #626262;
background-color: #fff;
}
.context-menu-item.context-menu-disabled {
color: #626262;
}
.context-menu-input.context-menu-hover,
.context-menu-item.context-menu-disabled.context-menu-hover {
cursor: default;
background-color: #eee;
}
.context-menu-submenu:after {
position: absolute;
top: 50%;
right: 8px;
z-index: $zindex1;
width: 0;
height: 0;
content: '';
border-color: transparent transparent transparent #2f2f2f;
border-style: solid;
border-width: 4px 0 4px 4px;
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
-o-transform: translateY(-50%);
transform: translateY(-50%);
}
/**
* Inputs
*/
.context-menu-item.context-menu-input {
padding: 5px 10px;
}
/* vertically align inside labels */
.context-menu-input > label > * {
vertical-align: top;
}
/* position checkboxes and radios as icons */
.context-menu-input > label > input[type="checkbox"],
.context-menu-input > label > input[type="radio"] {
position: relative;
top: 3px;
}
.context-menu-input > label,
.context-menu-input > label > input[type="text"],
.context-menu-input > label > textarea,
.context-menu-input > label > select {
display: block;
width: 100%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.context-menu-input > label > textarea {
height: 100px;
}
.context-menu-item > .context-menu-list {
top: 5px;
/* re-positioned by js */
right: -5px;
display: none;
}
.context-menu-item.context-menu-visible > .context-menu-list {
display: block;
}
.context-menu-accesskey {
text-decoration: underline;
}

View File

@@ -1,37 +1,68 @@
.label {
align-items: center;
background: #36383C;
border-radius: 3px;
color: #fff;
.large-video-labels {
display: flex;
font-size: 12px;
font-weight: 600;
height: 28px;
margin: 0 0 4px 4px;
padding: 0 8px;
position: absolute;
top: 30px;
right: 30px;
transition: right 0.5s;
z-index: $labelsZ;
&--green {
background: #31B76A;
.circular-label {
align-items: center;
color: white;
display: flex;
font-weight: bold;
justify-content: center;
margin-left: 8px;
opacity: 0.8;
}
&--red {
background: #E34F56
.circular-label {
background: #B8C7E0;
}
&--white {
background: #fff;
color: #5e6d7a;
.circular-label.e2ee {
align-items: center;
background: #76CF9C;
display: flex;
justify-content: center;
}
svg {
fill: #5e6d7a;
}
.circular-label.file {
background: #FF5630;
}
.circular-label.local-rec {
background: #FF5630;
}
.circular-label.stream {
background: #0065FF;
}
.circular-label.insecure {
background: $defaultWarningColor;
}
.recording-label.center-message {
background: $videoStateIndicatorBackground;
bottom: 50%;
display: block;
left: 50%;
padding: 10px;
position: fixed;
transform: translate(-50%, -50%);
z-index: $centeredVideoLabelZ;
}
}
.label-text-with-icon {
margin-left: 8px;
}
.participants-count {
cursor: pointer;
}
.circular-label {
background: $videoStateIndicatorBackground;
border-radius: 50%;
box-sizing: border-box;
cursor: default;
font-size: 13px;
height: $videoStateIndicatorSize;
line-height: $videoStateIndicatorSize;
text-align: center;
min-width: $videoStateIndicatorSize;
}

View File

@@ -9,7 +9,7 @@
.spinner {
margin: 30px;
}
.joining-message {
margin: 10px;
}
@@ -49,7 +49,7 @@
position: fixed;
top: 20;
transition: top 1s ease;
z-index: $toolbarZ + 1;
z-index: 100;
&.toolbox-visible {
// Same as toolbox subject position
@@ -62,6 +62,31 @@
padding: 15px
}
ul {
list-style-type: none;
padding: 0 15px 15px 15px;
li {
align-items: center;
display: flex;
flex-direction: row;
margin: 8px 0;
.details {
display: flex;
flex: 1;
flex-direction: column;
justify-content: space-evenly;
margin: 0 30px 0 10px;
}
button {
align-self: unset;
margin: 0 5px;
}
}
}
button {
align-self: stretch;
margin: 8px 0;
@@ -91,50 +116,3 @@
}
}
}
.knocking-participants-container {
list-style-type: none;
max-height: 600px;
overflow-y: scroll;
padding: 0 15px 15px 15px;
}
.knocking-participant {
align-items: center;
display: flex;
flex-direction: row;
margin: 8px 0;
.details {
display: flex;
flex: 1;
flex-direction: column;
justify-content: space-evenly;
margin: 0 30px 0 10px;
}
button {
align-self: unset;
margin: 0 5px;
}
}
@media (max-width: 300px) {
#knocking-participant-list {
margin: 0;
text-align: center;
width: 100%;
.avatar {
display: none;
}
}
.knocking-participant {
flex-direction: column;
.details {
margin: 0;
}
}
}

View File

@@ -8,11 +8,9 @@
.toolbox-icon {
cursor: pointer;
padding: 7px;
width: 22px;
height : 22px;
&.toggled {
background: none;
background: $AOTToolbarButtonToggleColor;
}
&.disabled {
@@ -25,11 +23,44 @@
flex-direction: row;
left: 50%;
position: absolute;
bottom: 10px;
top: 10px;
transform: translateX(-50%);
padding: 3px !important;
.toolbox-button {
&:first-child {
.toolbox-icon {
border-top-left-radius: 3px;
border-bottom-left-radius: 3px;
}
}
&:nth-child(2) {
svg {
fill: $hangupColor;
}
}
&:last-child {
.toolbox-icon {
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
}
}
}
}
.filmstrip-toolbox {
flex-direction: column;
}
.toolbox-button {
&:nth-child(1) {
svg {
fill: $hangupColor;
}
}
.toolbox-icon {
border-radius: 3px;
}
}
}

View File

@@ -0,0 +1,26 @@
.participants-count {
background: #fff;
border-radius: 4px;
color: #5e6d7a;
cursor: pointer;
display: inline-block;
font-size: 13px;
line-height: 20px;
margin-left: 16px;
padding: 4px 8px;
pointer-events: auto;
&-number {
margin-right: 8px;
vertical-align: middle;
}
&-icon {
background: url('../images/user-groups.svg');
background-repeat: no-repeat;
display: inline-block;
height: 16px;
width: 16px;
vertical-align: middle;
}
}

View File

@@ -1,51 +0,0 @@
.participants_pane {
background-color: $participantsPaneBgColor;
flex-shrink: 0;
overflow: hidden;
position: relative;
transition: width .16s ease-in-out;
width: 315px;
z-index: $zindex0;
&--closed {
width: 0;
}
}
.participants_pane-content {
display: flex;
flex-direction: column;
font-weight: 600;
height: 100%;
width: 315px;
& > *:first-child,
& > *:last-child {
flex-shrink: 0;
}
}
.participant-avatar {
margin: 8px 16px 8px 0;
}
@media (max-width: 375px) {
.participants_pane {
height: 100vh;
height: -webkit-fill-available;
left: 0;
position: fixed;
right: 0;
top: 0;
width: auto;
&--closed {
display: none;
width: auto;
}
}
.participants_pane-content {
width: 100%;
}
}

View File

@@ -3,11 +3,10 @@
**/
.popupmenu {
background-color: $menuBG;
border-radius: 3px;
min-width: 150px;
min-width: 75px;
text-align: left;
padding: 0px;
width: 180px;
white-space: nowrap;
&__item {
@@ -40,7 +39,6 @@
&__text {
display: inline-block;
margin-left: 8px;
vertical-align: middle;
}
@@ -112,6 +110,6 @@ ul.popupmenu {
margin: -16px -24px;
}
span.localvideomenu:hover ul.popupmenu, span.remotevideomenu:hover ul.popupmenu, ul.popupmenu:hover {
span.remotevideomenu:hover ul.popupmenu, ul.popupmenu:hover {
display:block !important;
}

View File

@@ -25,7 +25,7 @@
text {
fill: black;
font-size: 26px;
font-weight: 400;
font-weight: 400;
}
}
@@ -197,6 +197,14 @@
&> div {
margin: 0 12px;
}
.settings-button-small-icon {
right: -8px;
&--hovered {
right: -10px;
}
}
}
}

View File

@@ -1,3 +1,73 @@
@mixin small-button-size() {
.new-toolbox {
.toolbox-content {
.button-group-center, .button-group-left, .button-group-right {
.toolbox-button {
.toolbox-icon {
width: 28px;
height: 28px;
svg {
width: 18px;
height: 18px;
}
}
&:nth-child(2) {
.toolbox-icon {
width: 30px;
height: 30px;
}
}
}
}
}
}
}
@mixin very-small-button-size() {
.new-toolbox {
.toolbox-content {
.button-group-center, .button-group-left, .button-group-right {
.settings-button-small-icon {
display: none;
}
.toolbox-button {
.toolbox-icon {
width: 18px;
height: 18px;
svg {
width: 12px;
height: 12px;
}
}
&:nth-child(2) {
.toolbox-icon {
width: 20px;
height: 20px;
}
}
}
}
}
}
}
@mixin full-size-modal-positioner() {
height: 100%;
left: 0;
position: fixed;
top: 0;
max-width: 100%;
width: 100%;
}
@mixin full-size-modal-dialog() {
height: 100%;
max-height: 100%;
border-radius: 0;
}
@media only screen and (max-width: $verySmallScreen) {
.welcome {
display: block;
@@ -67,9 +137,21 @@
}
.desktop-browser {
@media only screen and (max-width: $smallScreen) {
@include small-button-size();
}
@media only screen and (max-width: $verySmallScreen) {
@include very-small-button-size();
}
&.shift-right {
@media only screen and (max-width: $smallScreen + $sidebarWidth) {
@include small-button-size()
}
@media only screen and (max-width: $verySmallScreen + $sidebarWidth) {
@include very-small-button-size();
#videoResolutionLabel {
display: none;
@@ -83,3 +165,25 @@
}
}
}
@media (min-width: 480px) and (max-width: 580px) {
.shift-right .focus-lock > div > div {
@include full-size-modal-positioner();
}
.shift-right .focus-lock [role="dialog"] {
@include full-size-modal-dialog();
}
}
@media (min-width: 580px) and (max-width: 680px) {
.mobile-browser {
&.shift-right .focus-lock > div > div {
@include full-size-modal-positioner();
}
&.shift-right .focus-lock [role="dialog"] {
@include full-size-modal-dialog();
}
}
}

View File

@@ -1,62 +1,84 @@
.settings-button-container {
position: relative;
.settings-button {
&-container {
position: relative;
.toolbox-icon {
align-items: center;
border-radius: 3px;
cursor: pointer;
display: flex;
justify-content: center;
&.disabled, .disabled & {
cursor: initial;
color: #929292;
background-color: #36383c;
.toolbox-icon {
align-items: center;
cursor: pointer;
display: flex;
background-color: #fff;
border-radius: 50%;
border: 1px solid #d1dbe8;
justify-content: center;
width: 38px;
height: 38px;
&:hover {
background-color: #36383c;
background-color: #daebfa;
border: 1px solid #daebfa;
}
&.toggled {
background: #2a3a4b;
border: 1px solid #5e6d7a;
svg {
fill: #fff;
}
&:hover {
background-color: #5e6d7a;
}
}
&.disabled, .disabled & {
cursor: initial;
color: #fff;
background-color: #a4b8d1;
&:hover {
background-color: #a4b8d1;
}
}
svg {
fill: #5e6d7a;
}
}
}
&-small-icon {
background: #FFF;
border: 1px solid rgba(0, 0, 0, 0.2);
border-radius: 50%;
bottom: 0;
box-shadow: 0px 1px 4px rgba(0, 0, 0, 0.25);
cursor: pointer;
height: 16px;
position: absolute;
text-align: center;
right: 4px;
width: 16px;
&> svg {
fill: #5e6d7a;
margin-top: 5px;
}
&--disabled {
background-color: #a4b8d1;
cursor: default;
}
&--hovered {
bottom: -1px;
height: 20px;
right: 2px;
width: 20px;
&> svg {
margin-top: 6px;
}
}
}
}
.settings-button-small-icon {
background: #36383C;
box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25), 0px 0px 0px 1px rgba(0, 0, 0, 0.1);
border-radius: 3px;
cursor: pointer;
padding: 4px;
position: absolute;
right: -4px;
top: -3px;
&:hover {
background: #F2F3F4;
box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25), 0px 0px 0px 1px rgba(0, 0, 0, 0.1);
&> svg {
fill: #000;
}
&.settings-button-small-icon--disabled {
background: #36383C;
&> svg {
fill: #929292;
}
}
}
&> svg {
fill: #fff;
}
&--disabled {
background-color: #36383c;
cursor: default;
&> svg {
fill: #929292;
}
}
}

View File

@@ -1,60 +1,35 @@
.subject {
box-sizing: border-box;
color: #fff;
margin-top: 20px;
position: absolute;
top: -120px;
transition: top .3s ease-in;
height: 95px;
width: 100%;
z-index: $zindex3;
pointer-events: none;
position: absolute;
padding: 25px 140px 0 140px;
text-align: center;
font-size: 17px;
color: #fff;
z-index: $zindex10;
overflow: hidden;
text-overflow: ellipsis;
box-sizing: border-box;
white-space: nowrap;
&.visible {
top: 0px;
}
}
.subject-info-container {
display: flex;
justify-content: center;
max-width: calc(100% - 280px);
margin: 0 auto;
&--full-width {
max-width: 100%;
&.gradient {
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
}
@media (max-width: 500px) {
flex-wrap: wrap;
max-width: 100%;
&-text {
vertical-align: middle;
}
&-conference-timer {
display: block;
font-size: 15px;
opacity: 0.6;
}
}
.subject-info {
align-items: center;
display: flex;
margin-bottom: 4px;
max-width: 80%;
height: 28px;
}
.subject-text {
background: rgba(0, 0, 0, 0.6);
border-radius: 3px 0px 0px 3px;
font-size: 14px;
line-height: 24px;
padding: 2px 16px;
height: 24px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.subject-timer {
background: rgba(0, 0, 0, 0.8);
border-radius: 0px 3px 3px 0px;
display: inline-block;
font-size: 12px;
line-height: 16px;
min-width: 34px;
padding: 6px 8px;
}

View File

@@ -33,6 +33,9 @@
&.visible {
bottom: 0;
.toolbox-background {
bottom: 0px;
}
}
&.no-buttons {
@@ -45,233 +48,253 @@
width: calc(100% - #{$sidebarWidth});
}
}
}
.toolbox-content {
align-items: center;
box-sizing: border-box;
display: flex;
margin-bottom: 16px;
position: relative;
z-index: $toolbarZ;
.button-group-center,
.button-group-left,
.button-group-right {
display: flex;
width: 33%;
}
.button-group-center {
justify-content: center;
}
.button-group-right {
justify-content: flex-end;
}
.toolbox-button-wth-dialog {
display: inline-block;
}
}
.toolbox-button {
color: $toolbarButtonColor;
cursor: pointer;
display: inline-block;
line-height: $newToolbarSize;
text-align: center;
}
.toolbar-button-with-badge {
display: inline-block;
position: relative;
.badge-round {
bottom: -5px;
font-size: 12px;
line-height: 20px;
min-width: 20px;
.toolbox-background {
background-image: linear-gradient(to top, rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0));
transition: bottom .3s ease-in;
height: 160px;
width: 100%;
bottom: -160px;
pointer-events: none;
position: absolute;
right: -5px;
}
}
.toolbox-content-wrapper {
display: flex;
flex-direction: column;
margin: 0 auto;
max-width: 100%;
}
.toolbox-content-items {
background: $newToolbarBackgroundColor;
box-shadow: 0px 2px 8px 4px rgba(0, 0, 0, 0.25), 0px 0px 0px 1px rgba(0, 0, 0, 0.15);
border-radius: 6px;
margin: 0 auto;
padding: 6px;
text-align: center;
>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;
}
z-index: $toolbarBackgroundZ;
}
div {
.toolbox-content {
box-sizing: border-box;
display: flex;
flex-direction: row;
align-items: center;
}
justify-content: space-between;
margin-left: auto;
margin-right: auto;
padding: 20px 16px;
position: relative;
width: 100%;
z-index: $toolbarZ;
&.unclickable {
cursor: default;
}
&.disabled {
cursor: initial;
color: #929292;
&:hover {
background: none;
.button-group-center,
.button-group-left,
.button-group-right {
display: flex;
width: 33%;
}
svg {
fill: #929292;
.button-group-center {
justify-content: center;
.toolbox-button {
.toolbox-icon {
background-color: #fff;
border-radius: 50%;
border: 1px solid #d1dbe8;
margin: 0px 4px;
width: 38px;
height: 38px;
@media (hover: hover) and (pointer: fine) {
&:hover {
background-color: #daebfa;
border: 1px solid #daebfa;
}
}
&.toggled {
background: #2a3a4b;
border: 1px solid #5e6d7a;
svg {
fill: #fff;
}
@media (hover: hover) and (pointer: fine) {
&:hover {
background-color: #5e6d7a;
}
}
}
&.disabled, .disabled & {
cursor: initial;
color: #fff;
background-color: #a4b8d1;
}
svg {
fill: #5e6d7a;
}
}
&:nth-child(2) {
.toolbox-icon {
background-color: $hangupColor;
border: 1px solid $hangupColor;
width: 40px;
height: 40px;
@media (hover: hover) and (pointer: fine) {
&:hover {
background-color: $hangupColor;
}
}
svg {
fill: #fff;
}
}
}
}
}
}
@media (hover: hover) and (pointer: fine) {
&.unclickable:hover {
background: inherit;
.button-group-right {
justify-content: flex-end;
}
}
}
.beta-tag {
background: #36383C;
border-radius: 3px;
color: #fff;
font-size: 12px;
margin-left: 8px;
padding: 0 4px;
text-transform: uppercase;
}
.overflow-menu {
font-size: 1.2em;
list-style-type: none;
background-color: $overflowMenuBG;
/**
* Undo atlaskit padding by reducing margins.
*/
margin: -16px -24px;
padding: 4px 0;
.overflow-menu-item-icon {
margin-right: 16px;
.overflow-menu-item {
align-items: center;
color: $overflowMenuItemColor;
cursor: pointer;
display: flex;
font-size: 14px;
height: 40px;
padding: 5px 12px;
box-sizing: border-box;
i {
display: inline;
font-size: 24px;
}
div {
display: flex;
flex-direction: row;
align-items: center;
}
@media (hover: hover) and (pointer: fine) {
i:hover {
background-color: initial;
@media (hover: hover) and (pointer: fine) {
&:hover {
background-color: $overflowMenuItemHoverBG;
color: $overflowMenuItemHoverColor;
}
}
&.unclickable {
cursor: default;
}
@media (hover: hover) and (pointer: fine) {
&.unclickable:hover {
background: inherit;
}
}
&.disabled {
cursor: initial;
color: #3b475c;
}
}
.beta-tag {
background: $overflowMenuItemColor;
border-radius: 2px;
color: $overflowMenuBG;
font-size: 11px;
font-weight: bold;
margin-left: 8px;
padding: 0 6px;
}
.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: #B8C7E0 !important;
height: 20px;
width: 20px;
}
}
.profile-text {
max-width: 150px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
}
}
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;
.toolbox-button {
color: $toolbarButtonColor;
cursor: pointer;
display: inline-block;
line-height: $newToolbarSize;
margin: 0 8px;
text-align: center;
}
}
@media (max-width: 320px) {
height: 36px;
width: 36px;
}
.toolbar-button-with-badge {
position: relative;
&.toggled {
background: $newToolbarButtonToggleColor;
}
&.disabled {
cursor: initial !important;
background-color: #36383c !important;
svg {
fill: #929292 !important;
.badge-round {
bottom: -5px;
font-size: 12px;
line-height: 20px;
min-width: 20px;
pointer-events: none;
position: absolute;
right: -5px;
}
}
}
}
.hangup-button {
background-color: $hangupColor;
@media (hover: hover) and (pointer: fine) {
&:hover {
background-color: $hangupHoverColor;
.toolbox-button-wth-dialog {
display: inline-block;
}
}
svg {
fill: #fff;
.toolbox-icon {
display: flex;
border-radius: 5px;
flex-direction: column;
font-size: 24px;
height: $newToolbarSize;
justify-content: center;
width: $newToolbarSize;
@media (hover: hover) and (pointer: fine) {
&:hover {
background: $newToolbarButtonHoverColor;
}
}
&.toggled {
background: $newToolbarButtonHoverColor;
}
&.disabled {
cursor: initial !important;
background-color: #a4b8d1 !important;
svg {
fill: #fff !important;
}
}
}
}
}
@@ -289,47 +312,3 @@
@include transition(all .3s ease-out);
}
/**
* Audio and video buttons do not have toggled state.
*/
.audio-preview,
.video-preview {
.toolbox-icon.toggled {
background: none;
&:hover {
background: $newToolbarButtonHoverColor;
}
}
}
/**
* On small mobile devices make the toolbar full width and pad the invite prompt.
*/
.toolbox-content-mobile {
@media (max-width: 500px) {
margin-bottom: 0;
.toolbox-content-wrapper {
width: 100%;
}
.toolbox-content-items {
border-radius: 0;
display: flex;
justify-content: space-evenly;
padding: 6px 0;
width: 100%;
}
.invite-more-container {
margin: 0 16px 8px;
}
.invite-more-container.elevated {
margin-bottom: 52px;
}
}
}

View File

@@ -1,11 +1,10 @@
.transcription-subtitles {
bottom: $newToolbarSize + 40px;
.transcription-subtitles{
bottom: 10%;
font-size: 16px;
font-weight: 1000;
left: 50%;
max-width: 50vw;
opacity: 0.80;
overflow-wrap: break-word;
pointer-events: none;
position: absolute;
text-shadow: 0px 0px 1px rgba(0,0,0,0.3),
@@ -15,11 +14,6 @@
transform: translateX(-50%);
z-index: $subtitlesZ;
&.lifted {
// Lift subtitle above toolbar+invite box.
bottom: $newToolbarSize + 112px + 40px;
}
span {
background: black;
}

View File

@@ -4,8 +4,7 @@
* Style variables
*/
$baseFontFamily: -apple-system, BlinkMacSystemFont, 'open_sanslight', 'Helvetica Neue', Helvetica, Arial, sans-serif;
$hangupColor:#DD3849;
$hangupHoverColor: #F25363;
$hangupColor: #bf2117;
$hangupFontSize: 2em;
/**
@@ -30,7 +29,6 @@ $defaultSideBarFontColor: #44A5FF;
$defaultSemiDarkColor: #ACACAC;
$defaultDarkColor: #2b3d5c;
$defaultWarningColor: rgb(215, 121, 118);
$participantsPaneBgColor: #141414;
$presence-available: rgb(110, 176, 5);
$presence-away: rgb(250, 201, 20);
$presence-busy: rgb(233, 0, 27);
@@ -39,18 +37,20 @@ $presence-idle: rgb(172, 172, 172);
/**
* Toolbar
*/
$newToolbarBackgroundColor: #131519;
$newToolbarButtonHoverColor: rgba(255, 255, 255, 0.2);
$newToolbarButtonToggleColor: rgba(255, 255, 255, 0.15);
$menuBG:#242528;
$newToolbarBackgroundColor: rgba(22, 38, 55, 0.8);
$newToolbarButtonHoverColor: rgba(255, 255, 255, 0.15);
$newToolbarButtonToggleColor: rgba(255, 255, 255, 0.2);
$AOTToolbarButtonHoverColor: rgba(14, 20, 35, 0.6);
$AOTToolbarButtonToggleColor: rgba(14, 20, 35, 1);
$newToolbarFontSize: 24px;
$newToolbarHangupFontSize: 32px;
$newToolbarSize: 48px;
$newToolbarSize: 40px;
$newToolbarSizeWithPadding: calc(#{$newToolbarSize} + 24px);
$toolbarTitleFontSize: 19px;
$overflowMenuItemColor: #fff;
$overflowMenuItemBackground: #36383C;
$overflowMenuBG: initial;
$overflowMenuItemHoverBG: #313D52;
$overflowMenuItemHoverColor: #B8C7E0;
$overflowMenuItemColor: #B8C7E0;
/**
* Video layout
@@ -90,12 +90,12 @@ $modalTextColor: #333;
* Chat
*/
$chatActionsSeparatorColor: rgb(173, 105, 112);
$chatBackgroundColor: #131519;
$chatHeaderBackgroundColor: rgba(42, 58, 75, 0.9);
$chatInputSeparatorColor: #A4B8D1;
$chatLocalMessageBackgroundColor: #484A4F;
$chatLocalMessageBackgroundColor: rgb(4, 98, 178);
$chatPrivateMessageBackgroundColor: rgb(153, 69, 77);
$chatRemoteMessageBackgroundColor: #242528;
$sidebarWidth: 315px;
$chatRemoteMessageBackgroundColor: rgb(86, 101, 114);
$sidebarWidth: 375px;
/**
* Misc.
@@ -122,8 +122,8 @@ $zindex10: 10;
$reloadZ: 20;
$poweredByZ: 100;
$ringingZ: 300;
$sideToolbarContainerZ: 200;
$toolbarZ: 250;
$sideToolbarContainerZ: 300;
$toolbarZ: 350;
$drawerZ: 351;
$tooltipsZ: 401;
$dropdownMaskZ: 900;

View File

@@ -1,21 +1,18 @@
.video-preview {
background: none;
display: inline-block;
max-height: 344px;
max-height: 290px;
&-container {
background: $menuBG;
border-radius: 3px;
overflow: auto;
padding: 8px;
padding: 16px;
}
&-entry {
cursor: pointer;
height: 168px;
margin-bottom: 8px;
height: 135px;
margin-bottom: 16px;
position: relative;
width: 284px;
width: 240px;
&:last-child {
margin-bottom: 0;
@@ -23,15 +20,13 @@
&--selected {
border: 3px solid #31B76A;
border-radius: 3px;
cursor: default;
height: 162px;
width: 278px;
height: 129px;
width: 234px;
}
}
&-video {
border-radius: 3px;
height: 100%;
object-fit: cover;
width: 100%;
@@ -55,28 +50,21 @@
}
&-label {
bottom: 8px;
color: #fff;
font-size: 13px;
line-height: 20px;
overflow: hidden;
padding: 8px;
position: absolute;
width: 100%;
text-align: center;
text-overflow: ellipsis;
width: 220px;
z-index: 2;
}
&-container {
margin: 0 16px;
}
&-text {
background-color: #131519;
border-radius: 3px;
padding: 2px 8px;
font-size: 13px;
line-height: 20px;
margin: 0 auto;
max-width: calc(100% - 16px);
overflow: hidden;
text-overflow: ellipsis;
width: fit-content;
white-space: nowrap;
}
// Override @atlaskit/InlineDialog container which is made with styled components
& > div:nth-child(2) {
outline: none;
padding: 0;
}
}

View File

@@ -1,13 +1,5 @@
#videoconference_page {
min-height: 100%;
position: relative;
transform: translate3d(0, 0, 0);
width: 100%;
}
#layout_wrapper {
display: flex;
height: 100%;
}
#videospace {
@@ -408,9 +400,7 @@
}
}
.local-video-menu-trigger,
.remote-video-menu-trigger,
.localvideomenu,
.remotevideomenu
{
display: inline-block;
@@ -428,7 +418,6 @@
cursor: hand;
}
}
.local-video-menu-trigger,
.remote-video-menu-trigger {
margin-top: 7px;
}

View File

@@ -208,11 +208,6 @@ body.welcome-page {
cursor: pointer;
font-size: 32px;
}
.toolbox-icon {
height: 24px;
width: 24px;
}
}
.welcome-watermark {
@@ -233,10 +228,6 @@ body.welcome-page {
}
}
&.without-footer {
justify-content: start;
}
.welcome-cards-container {
color:#131519;
padding-top: 40px;

View File

@@ -1,5 +1,3 @@
$rangeInputThumbSize: 14;
/**
* Disable the default webkit styles for range inputs (sliders).
*/

View File

@@ -19,7 +19,7 @@
0 0 3px $videoThumbnailSelected;
}
.remotevideomenu > .icon-menu, .localvideomenu > .icon-menu {
.remotevideomenu > .icon-menu {
display: none;
}
@@ -32,7 +32,7 @@
box-shadow: inset 0 0 3px $videoThumbnailHovered,
0 0 3px $videoThumbnailHovered;
.remotevideomenu > .icon-menu, .localvideomenu > .icon-menu {
.remotevideomenu > .icon-menu {
display: inline-block;
}
}

View File

@@ -16,7 +16,7 @@
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
width: 100vw;
}
.filmstrip__videos .videocontainer {
@@ -50,6 +50,10 @@
&.shift-right {
margin-left: $sidebarWidth;
width: calc(100% - #{$sidebarWidth});
#filmstripRemoteVideos {
width: calc(100vw - #{$sidebarWidth});
}
}
}
}
@@ -117,15 +121,3 @@
align-self: baseline;
}
}
.shift-right #filmstripRemoteVideosContainer {
/**
* Max-width corresponding to the ASPECT_RATIO_BREAKPOINT from features/filmstrip/constants,
* from which we subtract the chat size.
*/
@media only screen and (max-width: calc(500px + #{$sidebarWidth})) {
video {
object-fit: cover;
}
}
}

View File

@@ -43,7 +43,6 @@
* specifically the various status icons.
*/
.remotevideomenu,
.localvideomenu,
.videocontainer__toptoolbar {
z-index: auto;
}

View File

@@ -51,7 +51,6 @@
* 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);
@@ -69,9 +68,7 @@
* 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;
@@ -79,7 +76,6 @@
right: auto;
}
.local-video-menu-trigger,
.remote-video-menu-trigger {
margin-bottom: 7px;
margin-left: $remoteVideoMenuIconMargin;

View File

@@ -43,11 +43,11 @@ $flagsImagePath: "../images/";
@import 'modals/settings/settings';
@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';
@import 'notice';
@import 'subject';
@import 'participants-count';
@import 'popup_menu';
@import 'recording';
@import 'login_menu';
@@ -57,6 +57,7 @@ $flagsImagePath: "../images/";
@import 'welcome_page_content';
@import 'welcome_page_settings_toolbar';
@import 'toolbars';
@import 'jquery.contextMenu';
@import 'keyboard-shortcuts';
@import 'redirect_page';
@import 'components/form-control';
@@ -103,6 +104,5 @@ $flagsImagePath: "../images/";
@import 'responsive';
@import 'connection-status';
@import 'drawer';
@import 'participants-pane';
/* Modules END */

View File

@@ -1,42 +1,31 @@
.invite-more {
&-container {
margin-bottom: 8px;
transition: margin-bottom 0.3s;
&.elevated {
margin-bottom: 36px;
}
}
&-content {
display: flex;
flex-direction: column;
align-items: center;
padding: 16px;
background: rgba(0, 0, 0, 0.7);
border-radius: 8px;
color: #fff;
font-size: 14px;
line-height: 24px;
font-weight: 600;
position: absolute;
width: 100%;
text-align: center;
z-index: $zindex2;
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
}
&-header {
max-width: 100%;
margin-bottom: 16px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
font-size: 19px;
line-height: 28px;
margin: 24px 0 16px 0;
}
&-button {
display: flex;
max-width: 100%;
height: 40px;
box-sizing: border-box;
margin: auto;
padding: 8px 16px;
width: fit-content;
width: -moz-fit-content;
height: 24px;
background: #0376DA;
border-radius: 3px;
font-size: 14px;
line-height: 24px;
cursor: pointer;
@media (hover: hover) and (pointer: fine) {
@@ -47,9 +36,8 @@
&-text {
margin-left: 8px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
font-size: 15px;
line-height: 24px;
}
}
&-dialog {
@@ -97,18 +85,18 @@
border-top: none;
border-radius: 0 0 3px 3px;
.copy-invite-icon, .provider-icon {
align-items: center;
cursor: pointer;
& > * {
display: flex;
justify-content: center;
align-items: center;
height: 40px;
place-content: center;
width: 40px;
border-radius: 4px;
cursor: pointer;
}
&:hover > div:hover {
background-color: rgba(255, 255, 255, 0.2);
border-radius: 4px;
}
& > :not(:last-child) {
@@ -207,14 +195,3 @@
}
}
}
.mobile-browser {
.invite-more-content {
font-size: 16px;
}
.invite-more-button {
height: 48px;
padding: 12px 16px;
}
}

View File

@@ -47,7 +47,6 @@
.language-settings {
max-width: 50%;
width: 35%;
}
.calendar-tab {

View File

@@ -1,159 +0,0 @@
.virtual-background-dialog {
max-height: 300px;
color: white;
display: inline-grid;
grid-template-columns: auto auto auto auto auto;
column-gap: 8px;
cursor: pointer;
.thumbnail:hover, .blur:hover, .slight-blur:hover, .virtual-background-none:hover{
height: 56px;
width: 103px;
opacity: .5;
border: 2px solid #99bbf3;
@media (min-width: 432px) and (max-width: 632px) {
height: 56px;
width: 56px;
}
}
.thumbnail {
margin-top: 8px;
border-radius: 6px;
object-fit: cover;
height: 60px;
width: 107px;
}
.thumbnail:hover ~ .delete-image-icon {
display: block;
}
.thumbnail-selected {
margin-top: 8px;
border-radius: 6px;
object-fit: cover;
height: 60px;
width: 107px;
border: 2px solid #246FE5;
}
.blur{
box-shadow: inset 0 0 12px #000000;
margin-top: 8px;
background: #7E8287;
font-weight: bold;
height: 60px;
width: 107px;
border-radius: 6px;
text-align: center;
vertical-align: middle;
line-height: 60px;
}
.blur-selected {
box-shadow: inset 0 0 12px #000000;
margin-top: 8px;
background: #7E8287;
font-weight: bold;
height: 60px;
width: 107px;
border-radius: 6px;
border: 2px solid #246FE5;
text-align: center;
vertical-align: middle;
line-height: 60px;
}
.slight-blur{
box-shadow: inset 0 0 12px #000000;
margin-top: 8px;
background: #A4A4A4;
font-weight: bold;
height: 60px;
width: 107px;
border-radius: 6px;
text-align: center;
vertical-align: middle;
line-height: 60px;
}
.slight-blur-selected{
box-shadow: inset 0 0 12px #000000;
margin-top: 8px;
background: #A4A4A4;
font-weight: bold;
height: 60px;
width: 107px;
border-radius: 6px;
border: 2px solid #246FE5;
text-align: center;
vertical-align: middle;
line-height: 60px;
}
.virtual-background-none {
margin-top: 8px;
background: #525252;
font-weight: bold;
height: 60px;
width: 107px;
border-radius: 6px;
text-align: center;
vertical-align: middle;
line-height: 60px;
}
.none-selected {
margin-top: 8px;
background: #525252;
font-weight: bold;
height: 60px;
width: 107px;
border-radius: 6px;
border: 2px solid #246FE5;
text-align: center;
vertical-align: middle;
line-height: 60px;
}
@media (min-width: 432px) and (max-width: 632px) {
font-size: 1.5vw;
.virtual-background-none, .thumbnail, .thumbnail-selected, .none-selected, .blur, .blur-selected, .slight-blur, .slight-blur-selected{
height: 60px;
width: 60px;
}
}
}
.modal-dialog-form .virtual-background-loading {
overflow: hidden;
}
.file-upload-btn {
display: none;
}
.file-upload-label{
font-size: 14px;
font-weight: 600;
line-height: 20px;
margin-bottom: 8px;
color: #669AEC;
display: inline-flex;
cursor: pointer;
}
.delete-image-icon {
background: #3d3d3d;
position: absolute;
display: none;
left: 96;
bottom: 51;
@media (min-width: 432px) and (max-width: 632px) {
left: 51px
}
}
.delete-image-icon:hover {
display: block;
}
.thumbnail-container {
position: relative;
}
.loading-content-text{
margin-right: 15px;
}
.add-background{
margin-right: 8px;
}

View File

@@ -33,12 +33,4 @@
bottom: 24px;
width: 100%;
}
&__spinner-container {
display: flex;
width: 100%;
height: 100%;
justify-content: center;
align-items: center;
}
}

View File

@@ -35,7 +35,7 @@ case "$1" in
db_input critical jitsi-videobridge/jvb-hostname || true
db_go
fi
JVB_HOSTNAME=$(echo "$RET" | xargs echo -n)
JVB_HOSTNAME="$RET"
db_get jitsi-videobridge/jvbsecret
if [ -z "$RET" ] ; then
@@ -64,7 +64,7 @@ case "$1" in
# detect dpkg-reconfigure, just delete old links
db_get jitsi-meet-prosody/jvb-hostname
JVB_HOSTNAME_OLD=$(echo "$RET" | xargs echo -n)
JVB_HOSTNAME_OLD=$RET
if [ -n "$RET" ] && [ ! "$JVB_HOSTNAME_OLD" = "$JVB_HOSTNAME" ] ; then
rm -f /etc/prosody/conf.d/$JVB_HOSTNAME_OLD.cfg.lua
rm -f /etc/prosody/certs/$JVB_HOSTNAME_OLD.key

View File

@@ -31,7 +31,7 @@ case "$1" in
purge)
db_get jitsi-meet-prosody/jvb-hostname
JVB_HOSTNAME=$(echo "$RET" | xargs echo -n)
JVB_HOSTNAME=$RET
if [ -n "$RET" ]; then
rm -f /etc/prosody/conf.avail/$JVB_HOSTNAME.cfg.lua
rm -f /etc/prosody/conf.d/$JVB_HOSTNAME.cfg.lua

View File

@@ -25,7 +25,7 @@ case "$1" in
. /usr/share/debconf/confmodule
db_get jitsi-meet-prosody/jvb-hostname
JVB_HOSTNAME=$(echo "$RET" | xargs echo -n)
JVB_HOSTNAME="$RET"
db_get jitsi-meet-tokens/appid
if [ "$RET" = "false" ] ; then

View File

@@ -30,7 +30,7 @@ case "$1" in
db_input critical jitsi-videobridge/jvb-hostname || true
db_go
fi
JVB_HOSTNAME=$(echo "$RET" | xargs echo -n)
JVB_HOSTNAME="$RET"
TURN_CONFIG="/etc/turnserver.conf"
NGINX_CONFIG="/etc/nginx/sites-available/$JVB_HOSTNAME.conf"
@@ -44,7 +44,7 @@ case "$1" in
# detect dpkg-reconfigure, just delete old links
db_get jitsi-meet-turnserver/jvb-hostname
JVB_HOSTNAME_OLD=$(echo "$RET" | xargs echo -n)
JVB_HOSTNAME_OLD=$RET
if [ -n "$RET" ] && [ ! "$JVB_HOSTNAME_OLD" = "$JVB_HOSTNAME" ] ; then
if [[ -f $TURN_CONFIG ]] && grep -q "jitsi-meet coturn config" "$TURN_CONFIG" ; then
rm -f $TURN_CONFIG

View File

@@ -32,12 +32,12 @@ case "$1" in
db_go
db_get jitsi-videobridge/jvb-hostname
fi
JVB_HOSTNAME=$(echo "$RET" | xargs echo -n)
JVB_HOSTNAME="$RET"
# detect dpkg-reconfigure
RECONFIGURING="false"
db_get jitsi-meet/jvb-hostname
JVB_HOSTNAME_OLD=$(echo "$RET" | xargs echo -n)
JVB_HOSTNAME_OLD=$RET
if [ -n "$RET" ] && [ ! "$JVB_HOSTNAME_OLD" = "$JVB_HOSTNAME" ] ; then
RECONFIGURING="true"
rm -f /etc/jitsi/meet/$JVB_HOSTNAME_OLD-config.js

View File

@@ -33,7 +33,7 @@ case "$1" in
;;
purge)
db_get jitsi-meet/jvb-hostname
JVB_HOSTNAME=$(echo "$RET" | xargs echo -n)
JVB_HOSTNAME=$RET
if [ -n "$RET" ]; then
rm -f /etc/jitsi/meet/$JVB_HOSTNAME-config.js
rm -f /etc/nginx/sites-available/$JVB_HOSTNAME.conf

View File

@@ -1,5 +1,6 @@
interface_config.js /usr/share/jitsi-meet/
logging_config.js /usr/share/jitsi-meet/
*.json /usr/share/jitsi-meet/
*.html /usr/share/jitsi-meet/
*.ico /usr/share/jitsi-meet/
libs /usr/share/jitsi-meet/

View File

@@ -2,6 +2,9 @@
<VirtualHost *:80>
ServerName jitsi-meet.example.com
Redirect permanent / https://jitsi-meet.example.com/
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</VirtualHost>
<VirtualHost *:443>
@@ -39,12 +42,11 @@
</Location>
ProxyPreserveHost on
ProxyPass /http-bind http://localhost:5280/http-bind
ProxyPassReverse /http-bind http://localhost:5280/http-bind
ProxyPass /http-bind http://localhost:5280/http-bind/
ProxyPassReverse /http-bind http://localhost:5280/http-bind/
ProxyPass /xmpp-websocket ws://localhost:5280/xmpp-websocket
ProxyPassReverse /xmpp-websocket ws://localhost:5280/xmpp-websocket
ProxyPass /colibri-ws/default-id ws://localhost:9090/colibri-ws/default-id
ProxyPassReverse /colibri-ws/default-id ws://localhost:9090/colibri-ws/default-id
ProxyPassMatch ^/colibri-ws/default-id ws://localhost:9090
RewriteEngine on
RewriteRule ^/([a-zA-Z0-9]+)$ /index.html

View File

@@ -1,3 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.33331 2C6.28101 2 7.09675 2.56499 7.46207 3.37651C7.00766 3.45023 6.58406 3.61583 6.21095 3.85361C6.04111 3.54356 5.71176 3.33333 5.33331 3.33333C4.78103 3.33333 4.33331 3.78105 4.33331 4.33333C4.33331 4.75895 4.59921 5.12246 4.97395 5.26682C4.77672 5.69245 4.66665 6.16671 4.66665 6.66667L4.66678 6.6967C3.12249 6.85332 2.66665 7.65415 2.66665 9.83333C2.66665 9.89666 2.66835 9.95222 2.67088 10H3.13441C2.977 10.3982 2.86114 10.8423 2.7841 11.3333H2.33331C1.66665 11.3333 1.33331 10.8333 1.33331 9.83333C1.33331 7.60559 1.88097 6.20498 3.39417 5.63152C3.14521 5.26038 2.99998 4.81382 2.99998 4.33333C2.99998 3.04467 4.04465 2 5.33331 2ZM9.78901 3.85361C9.4159 3.61583 8.9923 3.45023 8.53788 3.37651C8.90321 2.56499 9.71895 2 10.6666 2C11.9553 2 13 3.04467 13 4.33333C13 4.81382 12.8547 5.26038 12.6058 5.63152C14.119 6.20498 14.6666 7.60559 14.6666 9.83333C14.6666 10.8333 14.3333 11.3333 13.6666 11.3333H13.2159C13.1388 10.8423 13.023 10.3982 12.8656 10H13.3291C13.3316 9.95222 13.3333 9.89666 13.3333 9.83333C13.3333 7.65415 12.8775 6.85332 11.3332 6.6967L11.3333 6.66667C11.3333 6.1667 11.2232 5.69245 11.026 5.26682C11.4008 5.12246 11.6666 4.75895 11.6666 4.33333C11.6666 3.78105 11.2189 3.33333 10.6666 3.33333C10.2882 3.33333 9.95885 3.54356 9.78901 3.85361ZM4.49998 14.6667C3.7222 14.6667 3.33331 14.1111 3.33331 13C3.33331 10.4598 4.0062 8.8875 5.87888 8.28308C5.5366 7.83462 5.33331 7.27438 5.33331 6.66667C5.33331 5.19391 6.52722 4 7.99998 4C9.47274 4 10.6666 5.19391 10.6666 6.66667C10.6666 7.27438 10.4634 7.83462 10.1211 8.28308C11.9938 8.8875 12.6666 10.4598 12.6666 13C12.6666 14.1111 12.2778 14.6667 11.5 14.6667H4.49998ZM9.33331 6.66667C9.33331 7.40305 8.73636 8 7.99998 8C7.2636 8 6.66665 7.40305 6.66665 6.66667C6.66665 5.93029 7.2636 5.33333 7.99998 5.33333C8.73636 5.33333 9.33331 5.93029 9.33331 6.66667ZM11.3333 13C11.3333 13.1426 11.3252 13.2536 11.3152 13.3333H4.68477C4.67476 13.2536 4.66665 13.1426 4.66665 13C4.66665 10.1957 5.42021 9.33333 7.99998 9.33333C10.5797 9.33333 11.3333 10.1957 11.3333 13Z" />
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.33331 2C6.28101 2 7.09675 2.56499 7.46207 3.37651C7.00766 3.45023 6.58406 3.61583 6.21095 3.85361C6.04111 3.54356 5.71176 3.33333 5.33331 3.33333C4.78103 3.33333 4.33331 3.78105 4.33331 4.33333C4.33331 4.75895 4.59921 5.12246 4.97395 5.26682C4.77672 5.69245 4.66665 6.16671 4.66665 6.66667L4.66678 6.6967C3.12249 6.85332 2.66665 7.65415 2.66665 9.83333C2.66665 9.89666 2.66835 9.95222 2.67088 10H3.13441C2.977 10.3982 2.86114 10.8423 2.7841 11.3333H2.33331C1.66665 11.3333 1.33331 10.8333 1.33331 9.83333C1.33331 7.60559 1.88097 6.20498 3.39417 5.63152C3.14521 5.26038 2.99998 4.81382 2.99998 4.33333C2.99998 3.04467 4.04465 2 5.33331 2ZM9.78901 3.85361C9.4159 3.61583 8.9923 3.45023 8.53788 3.37651C8.90321 2.56499 9.71895 2 10.6666 2C11.9553 2 13 3.04467 13 4.33333C13 4.81382 12.8547 5.26038 12.6058 5.63152C14.119 6.20498 14.6666 7.60559 14.6666 9.83333C14.6666 10.8333 14.3333 11.3333 13.6666 11.3333H13.2159C13.1388 10.8423 13.023 10.3982 12.8656 10H13.3291C13.3316 9.95222 13.3333 9.89666 13.3333 9.83333C13.3333 7.65415 12.8775 6.85332 11.3332 6.6967L11.3333 6.66667C11.3333 6.1667 11.2232 5.69245 11.026 5.26682C11.4008 5.12246 11.6666 4.75895 11.6666 4.33333C11.6666 3.78105 11.2189 3.33333 10.6666 3.33333C10.2882 3.33333 9.95885 3.54356 9.78901 3.85361ZM4.49998 14.6667C3.7222 14.6667 3.33331 14.1111 3.33331 13C3.33331 10.4598 4.0062 8.8875 5.87888 8.28308C5.5366 7.83462 5.33331 7.27438 5.33331 6.66667C5.33331 5.19391 6.52722 4 7.99998 4C9.47274 4 10.6666 5.19391 10.6666 6.66667C10.6666 7.27438 10.4634 7.83462 10.1211 8.28308C11.9938 8.8875 12.6666 10.4598 12.6666 13C12.6666 14.1111 12.2778 14.6667 11.5 14.6667H4.49998ZM9.33331 6.66667C9.33331 7.40305 8.73636 8 7.99998 8C7.2636 8 6.66665 7.40305 6.66665 6.66667C6.66665 5.93029 7.2636 5.33333 7.99998 5.33333C8.73636 5.33333 9.33331 5.93029 9.33331 6.66667ZM11.3333 13C11.3333 13.1426 11.3252 13.2536 11.3152 13.3333H4.68477C4.67476 13.2536 4.66665 13.1426 4.66665 13C4.66665 10.1957 5.42021 9.33333 7.99998 9.33333C10.5797 9.33333 11.3333 10.1957 11.3333 13Z" fill="#5E6D7A"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 463 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 338 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 685 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 599 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 894 KiB

View File

@@ -1,13 +1,6 @@
/* eslint-disable no-unused-vars, no-var, max-len */
/* eslint sort-keys: ["error", "asc", {"caseSensitive": false}] */
/**
* !!!IMPORTANT!!!
*
* This file is considered deprecated. All options will eventually be moved to
* config.js, and no new options should be added here.
*/
var interfaceConfig = {
APP_NAME: 'Jitsi Meet',
AUDIO_LEVEL_PRIMARY_COLOR: 'rgba(255,255,255,0.4)',
@@ -175,13 +168,6 @@ var interfaceConfig = {
REMOTE_THUMBNAIL_RATIO: 1, // 1:1
SETTINGS_SECTIONS: [ 'devices', 'language', 'moderator', 'profile', 'calendar' ],
/**
* Specify which sharing features should be displayed. If the value is not set
* all sharing features will be shown. You can set [] to disable all.
*/
// SHARING_FEATURES: ['email', 'url', 'dial-in', 'embed'],
SHOW_BRAND_WATERMARK: false,
/**
@@ -205,16 +191,23 @@ var interfaceConfig = {
TOOLBAR_ALWAYS_VISIBLE: false,
/**
* DEPRECATED!
* This config was moved to config.js as `toolbarButtons`.
* The name of the toolbar buttons to display in the toolbar, including the
* "More actions" menu. If present, the button will display. Exceptions are
* "livestreaming" and "recording" which also require being a moderator and
* some values in config.js to be enabled. Also, the "profile" button will
* not display for users with a JWT.
* Notes:
* - it's impossible to choose which buttons go in the "More actions" menu
* - it's impossible to control the placement of buttons
* - 'desktop' controls the "Share your screen" button
*/
// TOOLBAR_BUTTONS: [
// 'microphone', 'camera', 'closedcaptions', 'desktop', 'embedmeeting', 'fullscreen',
// 'fodeviceselection', 'hangup', 'profile', 'chat', 'recording',
// 'livestreaming', 'etherpad', 'sharedvideo', 'settings', 'raisehand',
// 'videoquality', 'filmstrip', 'invite', 'feedback', 'stats', 'shortcuts',
// 'tileview', 'select-background', 'download', 'help', 'mute-everyone', 'mute-video-everyone', 'security'
// ],
TOOLBAR_BUTTONS: [
'microphone', 'camera', 'closedcaptions', 'desktop', 'embedmeeting', 'fullscreen',
'fodeviceselection', 'hangup', 'profile', 'chat', 'recording',
'livestreaming', 'etherpad', 'sharedvideo', 'settings', 'raisehand',
'videoquality', 'filmstrip', 'invite', 'feedback', 'stats', 'shortcuts',
'tileview', 'videobackgroundblur', 'download', 'help', 'mute-everyone', 'security'
],
TOOLBAR_TIMEOUT: 4000,

View File

@@ -61,6 +61,7 @@ target 'JitsiMeetSDK' do
pod 'react-native-splash-screen', :path => '../node_modules/react-native-splash-screen'
pod 'react-native-webview', :path => '../node_modules/react-native-webview'
pod 'react-native-webrtc', :path => '../node_modules/react-native-webrtc'
pod 'BVLinearGradient', :path => '../node_modules/react-native-linear-gradient'
pod 'RNCAsyncStorage', :path => '../node_modules/@react-native-async-storage/async-storage'
pod 'RNDeviceInfo', :path => '../node_modules/react-native-device-info'
pod 'RNGoogleSignin', :path => '../node_modules/@react-native-community/google-signin'

View File

@@ -5,6 +5,8 @@ PODS:
- AppAuth/Core (1.2.0)
- AppAuth/ExternalUserAgent (1.2.0)
- boost-for-react-native (1.63.0)
- BVLinearGradient (2.5.6):
- React
- CocoaLumberjack (3.5.3):
- CocoaLumberjack/Core (= 3.5.3)
- CocoaLumberjack/Core (3.5.3)
@@ -290,7 +292,7 @@ PODS:
- React
- react-native-splash-screen (3.2.0):
- React
- react-native-webrtc (1.89.1):
- react-native-webrtc (1.87.3):
- React-Core
- react-native-webview (11.0.2):
- React-Core
@@ -369,6 +371,7 @@ PODS:
- Yoga (1.14.0)
DEPENDENCIES:
- BVLinearGradient (from `../node_modules/react-native-linear-gradient`)
- CocoaLumberjack (~> 3.5.3)
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector/`)
@@ -439,6 +442,8 @@ SPEC REPOS:
- PromisesObjC
EXTERNAL SOURCES:
BVLinearGradient:
:path: "../node_modules/react-native-linear-gradient"
DoubleConversion:
:podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
FBLazyVector:
@@ -521,6 +526,7 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
AppAuth: bce82c76043657c99d91e7882e8a9e1a93650cd4
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
BVLinearGradient: e3aad03778a456d77928f594a649e96995f1c872
CocoaLumberjack: 2f44e60eb91c176d471fdba43b9e3eae6a721947
DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2
FBLazyVector: ca7f56c8ff6cd8590f7a673d7903b06019805581
@@ -557,7 +563,7 @@ SPEC CHECKSUMS:
react-native-keep-awake: eba3137546b10003361b37c761f6c429b59814ae
react-native-netinfo: 8d8db463bcc5db66a8ac5c48a7d86beb3b92f61a
react-native-splash-screen: 200d11d188e2e78cea3ad319964f6142b6384865
react-native-webrtc: ccb0c21eb4fb04326648fbdb4a5d49977e2cf274
react-native-webrtc: dc1208bdca2c4d091f7b57859e69332bff6f1986
react-native-webview: b2542d6fd424bcc3e3b2ec5f854f0abb4ec86c87
React-RCTActionSheet: bcbc311dc3b47bc8efb2737ff0940239a45789a9
React-RCTAnimation: 65f61080ce632f6dea23d52e354ffac9948396c6
@@ -578,6 +584,6 @@ SPEC CHECKSUMS:
RNWatch: a5320c959c75e72845c07985f3e935e58998f1d3
Yoga: 96b469c5e81ff51b917b92e8c3390642d4ded30c
PODFILE CHECKSUM: d059cebf82da14a53940a16c24c3330752d4b0c8
PODFILE CHECKSUM: 5be5132e41831a98362eeed760558227a4df89ae
COCOAPODS: 1.10.1
COCOAPODS: 1.10.0

View File

@@ -8,10 +8,6 @@
<string>applinks:beta.meet.jit.si</string>
<string>applinks:meet.jit.si</string>
</array>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.jitsi.meet.appgroup</string>
</array>
<key>com.apple.developer.siri</key>
<true/>
</dict>

View File

@@ -23,13 +23,6 @@
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
4E90F9402632D1AB001102D4 /* Atomic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E90F93F2632D1AB001102D4 /* Atomic.swift */; };
4EB06024260E026600F524C5 /* ReplayKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4EC49B8625BED71300E76218 /* ReplayKit.framework */; };
4EB06027260E026600F524C5 /* SampleHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB06026260E026600F524C5 /* SampleHandler.swift */; };
4EB0602B260E026600F524C5 /* JitsiMeetBroadcastExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 4EB06023260E026600F524C5 /* JitsiMeetBroadcastExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
4EB0603C260E09D000F524C5 /* SocketConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB06039260E09D000F524C5 /* SocketConnection.swift */; };
4EB0603D260E09D000F524C5 /* DarwinNotificationCenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB0603A260E09D000F524C5 /* DarwinNotificationCenter.swift */; };
4EB0603E260E09D000F524C5 /* SampleUploader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB0603B260E09D000F524C5 /* SampleUploader.swift */; };
55BEDABDA92D47D399A70A5E /* libPods-JitsiMeet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D878B07B3FBD6E305EAA6B27 /* libPods-JitsiMeet.a */; };
DE050389256E904600DEE3A5 /* WebRTC.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = DE050388256E904600DEE3A5 /* WebRTC.xcframework */; };
DE05038A256E904600DEE3A5 /* WebRTC.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DE050388256E904600DEE3A5 /* WebRTC.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
@@ -55,13 +48,6 @@
remoteGlobalIDString = 0BEA5C241F7B8F73000D0AB4;
remoteInfo = JitsiMeetCompanion;
};
4EB06029260E026600F524C5 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 4EB06022260E026600F524C5;
remoteInfo = "JitsiMeetBroadcast Extension";
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
@@ -99,17 +85,6 @@
name = "Embed Watch Content";
runOnlyForDeploymentPostprocessing = 0;
};
4EC49B9025BED71300E76218 /* Embed App Extensions */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 13;
files = (
4EB0602B260E026600F524C5 /* JitsiMeetBroadcastExtension.appex in Embed App Extensions */,
);
name = "Embed App Extensions";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
@@ -140,18 +115,7 @@
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
4670A512A688E2DC34528282 /* Pods-jitsi-meet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-jitsi-meet.debug.xcconfig"; path = "../Pods/Target Support Files/Pods-jitsi-meet/Pods-jitsi-meet.debug.xcconfig"; sourceTree = "<group>"; };
4E90F93F2632D1AB001102D4 /* Atomic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Atomic.swift; sourceTree = "<group>"; };
4EB06023260E026600F524C5 /* JitsiMeetBroadcastExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = JitsiMeetBroadcastExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
4EB06026260E026600F524C5 /* SampleHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleHandler.swift; sourceTree = "<group>"; };
4EB06028260E026600F524C5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
4EB06032260E08CC00F524C5 /* extension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = extension.entitlements; sourceTree = "<group>"; };
4EB06039260E09D000F524C5 /* SocketConnection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocketConnection.swift; sourceTree = "<group>"; };
4EB0603A260E09D000F524C5 /* DarwinNotificationCenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DarwinNotificationCenter.swift; sourceTree = "<group>"; };
4EB0603B260E09D000F524C5 /* SampleUploader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SampleUploader.swift; sourceTree = "<group>"; };
4EC49B8625BED71300E76218 /* ReplayKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ReplayKit.framework; path = System/Library/Frameworks/ReplayKit.framework; sourceTree = SDKROOT; };
5FEF9D87A4D2A38AD7193308 /* Pods-JitsiMeet-JitsiMeetBroadcastExtension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JitsiMeet-JitsiMeetBroadcastExtension.release.xcconfig"; path = "../Pods/Target Support Files/Pods-JitsiMeet-JitsiMeetBroadcastExtension/Pods-JitsiMeet-JitsiMeetBroadcastExtension.release.xcconfig"; sourceTree = "<group>"; };
609CB2080B75F75A89923F3D /* 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>"; };
A7B2827E068A0E05260054AC /* Pods-JitsiMeet-JitsiMeetBroadcastExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JitsiMeet-JitsiMeetBroadcastExtension.debug.xcconfig"; path = "../Pods/Target Support Files/Pods-JitsiMeet-JitsiMeetBroadcastExtension/Pods-JitsiMeet-JitsiMeetBroadcastExtension.debug.xcconfig"; sourceTree = "<group>"; };
B3B083EB1D4955FF0069CEE7 /* app.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = app.entitlements; sourceTree = "<group>"; };
D878B07B3FBD6E305EAA6B27 /* libPods-JitsiMeet.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-JitsiMeet.a"; sourceTree = BUILT_PRODUCTS_DIR; };
DE050388256E904600DEE3A5 /* WebRTC.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = WebRTC.xcframework; path = "../../node_modules/react-native-webrtc/apple/WebRTC.xcframework"; sourceTree = "<group>"; };
@@ -189,14 +153,6 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
4EB06020260E026600F524C5 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
4EB06024260E026600F524C5 /* ReplayKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
@@ -209,7 +165,6 @@
DEFDBBDB25656E3B00344B23 /* WebRTC.xcframework */,
0BD6B4361EF82A6B00D1F4CD /* WebRTC.framework */,
D878B07B3FBD6E305EAA6B27 /* libPods-JitsiMeet.a */,
4EC49B8625BED71300E76218 /* ReplayKit.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@@ -261,23 +216,6 @@
path = src;
sourceTree = "<group>";
};
4EB06025260E026600F524C5 /* JitsiMeetBroadcast Extension */ = {
isa = PBXGroup;
children = (
4EB06032260E08CC00F524C5 /* extension.entitlements */,
4EB06026260E026600F524C5 /* SampleHandler.swift */,
4EB0603B260E09D000F524C5 /* SampleUploader.swift */,
4EB06039260E09D000F524C5 /* SocketConnection.swift */,
4EB0603A260E09D000F524C5 /* DarwinNotificationCenter.swift */,
4E90F93F2632D1AB001102D4 /* Atomic.swift */,
4EB06028260E026600F524C5 /* Info.plist */,
);
indentWidth = 4;
name = "JitsiMeetBroadcast Extension";
path = "broadcast-extension";
sourceTree = "<group>";
tabWidth = 4;
};
5E96ADD5E49F3B3822EF9A52 /* Pods */ = {
isa = PBXGroup;
children = (
@@ -285,8 +223,6 @@
09AA3B93E4CC62D84B424690 /* Pods-jitsi-meet.release.xcconfig */,
609CB2080B75F75A89923F3D /* Pods-JitsiMeet.debug.xcconfig */,
FC040BBED70876444D89E91C /* Pods-JitsiMeet.release.xcconfig */,
A7B2827E068A0E05260054AC /* Pods-JitsiMeet-JitsiMeetBroadcastExtension.debug.xcconfig */,
5FEF9D87A4D2A38AD7193308 /* Pods-JitsiMeet-JitsiMeetBroadcastExtension.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
@@ -301,7 +237,6 @@
5E96ADD5E49F3B3822EF9A52 /* Pods */,
0BEA5C261F7B8F73000D0AB4 /* Watch app */,
0BEA5C351F7B8F73000D0AB4 /* WatchKit extension */,
4EB06025260E026600F524C5 /* JitsiMeetBroadcast Extension */,
);
indentWidth = 2;
sourceTree = "<group>";
@@ -313,7 +248,6 @@
13B07F961A680F5B00A75B9A /* jitsi-meet.app */,
0BEA5C251F7B8F73000D0AB4 /* JitsiMeetCompanion.app */,
0BEA5C311F7B8F73000D0AB4 /* JitsiMeetCompanion Extension.appex */,
4EB06023260E026600F524C5 /* JitsiMeetBroadcastExtension.appex */,
);
name = Products;
sourceTree = "<group>";
@@ -371,43 +305,23 @@
DE11877A21EE09640078D059 /* Setup Google reverse URL handler */,
DE4F6D6E22005C0400DE699E /* Setup Dropbox */,
0BEA5C491F7B8F73000D0AB4 /* Embed Watch Content */,
4EC49B9025BED71300E76218 /* Embed App Extensions */,
);
buildRules = (
);
dependencies = (
0BEA5C401F7B8F73000D0AB4 /* PBXTargetDependency */,
4EB0602A260E026600F524C5 /* PBXTargetDependency */,
);
name = JitsiMeet;
productName = "Jitsi Meet";
productReference = 13B07F961A680F5B00A75B9A /* jitsi-meet.app */;
productType = "com.apple.product-type.application";
};
4EB06022260E026600F524C5 /* JitsiMeetBroadcastExtension */ = {
isa = PBXNativeTarget;
buildConfigurationList = 4EB0602C260E026700F524C5 /* Build configuration list for PBXNativeTarget "JitsiMeetBroadcastExtension" */;
buildPhases = (
4EB0601F260E026600F524C5 /* Sources */,
4EB06020260E026600F524C5 /* Frameworks */,
4EB06021260E026600F524C5 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = JitsiMeetBroadcastExtension;
productName = "JitsiMeetBroadcast Extension";
productReference = 4EB06023260E026600F524C5 /* JitsiMeetBroadcastExtension.appex */;
productType = "com.apple.product-type.app-extension";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
83CBB9F71A601CBA00E9B192 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1240;
LastUpgradeCheck = 1020;
ORGANIZATIONNAME = Facebook;
TargetAttributes = {
@@ -422,6 +336,8 @@
ProvisioningStyle = Automatic;
};
13B07F861A680F5B00A75B9A = {
DevelopmentTeam = FC967L3QRG;
ProvisioningStyle = Automatic;
SystemCapabilities = {
com.apple.SafariKeychain = {
enabled = 1;
@@ -431,9 +347,6 @@
};
};
};
4EB06022260E026600F524C5 = {
CreatedOnToolsVersion = 12.4;
};
};
};
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "app" */;
@@ -452,7 +365,6 @@
13B07F861A680F5B00A75B9A /* JitsiMeet */,
0BEA5C241F7B8F73000D0AB4 /* JitsiMeetCompanion */,
0BEA5C301F7B8F73000D0AB4 /* JitsiMeetCompanion Extension */,
4EB06022260E026600F524C5 /* JitsiMeetBroadcastExtension */,
);
};
/* End PBXProject section */
@@ -485,13 +397,6 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
4EB06021260E026600F524C5 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
@@ -627,18 +532,6 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
4EB0601F260E026600F524C5 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
4EB0603C260E09D000F524C5 /* SocketConnection.swift in Sources */,
4EB0603E260E09D000F524C5 /* SampleUploader.swift in Sources */,
4EB0603D260E09D000F524C5 /* DarwinNotificationCenter.swift in Sources */,
4EB06027260E026600F524C5 /* SampleHandler.swift in Sources */,
4E90F9402632D1AB001102D4 /* Atomic.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
@@ -652,11 +545,6 @@
target = 0BEA5C241F7B8F73000D0AB4 /* JitsiMeetCompanion */;
targetProxy = 0BEA5C3F1F7B8F73000D0AB4 /* PBXContainerItemProxy */;
};
4EB0602A260E026600F524C5 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 4EB06022260E026600F524C5 /* JitsiMeetBroadcastExtension */;
targetProxy = 4EB06029260E026600F524C5 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
@@ -830,7 +718,7 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIconDebug;
CODE_SIGN_ENTITLEMENTS = app.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = NO;
@@ -860,7 +748,7 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIconRelease;
CODE_SIGN_ENTITLEMENTS = app.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = FC967L3QRG;
@@ -882,75 +770,6 @@
};
name = Release;
};
4EB0602D260E026700F524C5 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = "broadcast-extension/extension.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = FC967L3QRG;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = "broadcast-extension/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 14.4;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.meet.broadcast.extension;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
4EB0602E260E026700F524C5 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = "broadcast-extension/extension.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = FC967L3QRG;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = "broadcast-extension/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 14.4;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.meet.broadcast.extension;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
83CBBA201A601CBA00E9B192 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -1095,15 +914,6 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
4EB0602C260E026700F524C5 /* Build configuration list for PBXNativeTarget "JitsiMeetBroadcastExtension" */ = {
isa = XCConfigurationList;
buildConfigurations = (
4EB0602D260E026700F524C5 /* Debug */,
4EB0602E260E026700F524C5 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "app" */ = {
isa = XCConfigurationList;
buildConfigurations = (

View File

@@ -1,30 +0,0 @@
import Foundation
@propertyWrapper
struct Atomic<Value> {
private var value: Value
private let lock = NSLock()
init(wrappedValue value: Value) {
self.value = value
}
var wrappedValue: Value {
get { return load() }
set { store(newValue: newValue) }
}
func load() -> Value {
lock.lock()
defer { lock.unlock() }
return value
}
mutating func store(newValue: Value) {
lock.lock()
defer { lock.unlock() }
value = newValue
}
}

View File

@@ -1,37 +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.
*/
import Foundation
enum DarwinNotification: String {
case broadcastStarted = "iOS_BroadcastStarted"
case broadcastStopped = "iOS_BroadcastStopped"
}
class DarwinNotificationCenter {
static var shared = DarwinNotificationCenter()
private var notificationCenter: CFNotificationCenter
init() {
notificationCenter = CFNotificationCenterGetDarwinNotifyCenter()
}
func postNotification(_ name: DarwinNotification) {
CFNotificationCenterPostNotification(notificationCenter, CFNotificationName(rawValue: name.rawValue as CFString), nil, nil, true)
}
}

View File

@@ -1,33 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>Jitsi Meet Broadcast Extension</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>21.1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.broadcast-services-upload</string>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).SampleHandler</string>
<key>RPBroadcastProcessMode</key>
<string>RPBroadcastProcessModeSampleBuffer</string>
</dict>
</dict>
</plist>

View File

@@ -1,117 +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.
*/
import ReplayKit
import JitsiMeetSDK
private enum Constants {
// the App Group ID value that the app and the broadcast extension targets are setup with. It differs for each app.
static let appGroupIdentifier = "group.org.jitsi.meet.appgroup"
}
class SampleHandler: RPBroadcastSampleHandler {
private var clientConnection: SocketConnection?
private var uploader: SampleUploader?
private var frameCount: Int = 0
var socketFilePath: String {
let sharedContainer = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: Constants.appGroupIdentifier)
return sharedContainer?.appendingPathComponent("rtc_SSFD").path ?? ""
}
override init() {
super.init()
if let connection = SocketConnection(filePath: socketFilePath) {
clientConnection = connection
setupConnection()
uploader = SampleUploader(connection: connection)
}
}
override func broadcastStarted(withSetupInfo setupInfo: [String: NSObject]?) {
// User has requested to start the broadcast. Setup info from the UI extension can be supplied but optional.
print("broadcast started")
frameCount = 0
DarwinNotificationCenter.shared.postNotification(.broadcastStarted)
openConnection()
}
override func broadcastPaused() {
// User has requested to pause the broadcast. Samples will stop being delivered.
}
override func broadcastResumed() {
// User has requested to resume the broadcast. Samples delivery will resume.
}
override func broadcastFinished() {
// User has requested to finish the broadcast.
DarwinNotificationCenter.shared.postNotification(.broadcastStopped)
clientConnection?.close()
}
override func processSampleBuffer(_ sampleBuffer: CMSampleBuffer, with sampleBufferType: RPSampleBufferType) {
switch sampleBufferType {
case RPSampleBufferType.video:
// very simple mechanism for adjusting frame rate by using every third frame
frameCount += 1
if frameCount % 3 == 0 {
uploader?.send(sample: sampleBuffer)
}
default:
break
}
}
}
private extension SampleHandler {
func setupConnection() {
clientConnection?.didClose = { [weak self] error in
print("client connection did close \(String(describing: error))")
if let error = error {
self?.finishBroadcastWithError(error)
} else {
// the displayed failure message is more user friendly when using NSError instead of Error
let JMScreenSharingStopped = 10001
let customError = NSError(domain: RPRecordingErrorDomain, code: JMScreenSharingStopped, userInfo: [NSLocalizedDescriptionKey: "Screen sharing stopped"])
self?.finishBroadcastWithError(customError)
}
}
}
func openConnection() {
let queue = DispatchQueue(label: "broadcast.connectTimer")
let timer = DispatchSource.makeTimerSource(queue: queue)
timer.schedule(deadline: .now(), repeating: .milliseconds(100), leeway: .milliseconds(500))
timer.setEventHandler { [weak self] in
guard self?.clientConnection?.open() == true else {
return
}
timer.cancel()
}
timer.resume()
}
}

View File

@@ -1,154 +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.
*/
import Foundation
import ReplayKit
private enum Constants {
static let bufferMaxLength = 10240
}
class SampleUploader {
private static var imageContext = CIContext(options: nil)
@Atomic private var isReady: Bool = false
private var connection: SocketConnection
private var dataToSend: Data?
private var byteIndex = 0
private let serialQueue: DispatchQueue
init(connection: SocketConnection) {
self.connection = connection
self.serialQueue = DispatchQueue(label: "org.jitsi.meet.broadcast.sampleUploader")
setupConnection()
}
@discardableResult func send(sample buffer: CMSampleBuffer) -> Bool {
guard isReady == true else {
return false
}
isReady = false
dataToSend = prepare(sample: buffer)
byteIndex = 0
serialQueue.async { [weak self] in
self?.sendDataChunk()
}
return true
}
}
private extension SampleUploader {
func setupConnection() {
connection.didOpen = { [weak self] in
self?.isReady = true
}
connection.streamHasSpaceAvailable = { [weak self] in
self?.serialQueue.async {
self?.isReady = !(self?.sendDataChunk() ?? true)
}
}
}
@discardableResult func sendDataChunk() -> Bool {
guard let dataToSend = dataToSend else {
return false
}
var bytesLeft = dataToSend.count - byteIndex
var length = bytesLeft > Constants.bufferMaxLength ? Constants.bufferMaxLength : bytesLeft
length = dataToSend[byteIndex..<(byteIndex + length)].withUnsafeBytes {
guard let ptr = $0.bindMemory(to: UInt8.self).baseAddress else {
return 0
}
return connection.writeToStream(buffer: ptr, maxLength: length)
}
if length > 0 {
byteIndex += length
bytesLeft -= length
if bytesLeft == 0 {
self.dataToSend = nil
byteIndex = 0
}
} else {
print("writeBufferToStream failure")
}
return true
}
func prepare(sample buffer: CMSampleBuffer) -> Data? {
guard let imageBuffer = CMSampleBufferGetImageBuffer(buffer) else {
print("image buffer not available")
return nil
}
CVPixelBufferLockBaseAddress(imageBuffer, .readOnly)
let scaleFactor = 2.0
let width = CVPixelBufferGetWidth(imageBuffer)/Int(scaleFactor)
let height = CVPixelBufferGetHeight(imageBuffer)/Int(scaleFactor)
let orientation = CMGetAttachment(buffer, key: RPVideoSampleOrientationKey as CFString, attachmentModeOut: nil)?.uintValue ?? 0
let scaleTransform = CGAffineTransform(scaleX: CGFloat(1.0/scaleFactor), y: CGFloat(1.0/scaleFactor))
let bufferData = self.jpegData(from: imageBuffer, scale: scaleTransform)
CVPixelBufferUnlockBaseAddress(imageBuffer, .readOnly)
guard let messageData = bufferData else {
print("corrupted image buffer")
return nil
}
let httpResponse = CFHTTPMessageCreateResponse(nil, 200, nil, kCFHTTPVersion1_1).takeRetainedValue()
CFHTTPMessageSetHeaderFieldValue(httpResponse, "Content-Length" as CFString, String(messageData.count) as CFString)
CFHTTPMessageSetHeaderFieldValue(httpResponse, "Buffer-Width" as CFString, String(width) as CFString)
CFHTTPMessageSetHeaderFieldValue(httpResponse, "Buffer-Height" as CFString, String(height) as CFString)
CFHTTPMessageSetHeaderFieldValue(httpResponse, "Buffer-Orientation" as CFString, String(orientation) as CFString)
CFHTTPMessageSetBody(httpResponse, messageData as CFData)
let serializedMessage = CFHTTPMessageCopySerializedMessage(httpResponse)?.takeRetainedValue() as Data?
return serializedMessage
}
func jpegData(from buffer: CVPixelBuffer, scale scaleTransform: CGAffineTransform) -> Data? {
var image = CIImage(cvPixelBuffer: buffer)
image = image.transformed(by: scaleTransform)
guard let colorSpace = image.colorSpace else {
return nil
}
let options: [CIImageRepresentationOption: Float] = [kCGImageDestinationLossyCompressionQuality as CIImageRepresentationOption: 1.0]
let imageData = SampleUploader.imageContext.jpegRepresentation(of: image, colorSpace: colorSpace, options: options)
return imageData
}
}

View File

@@ -1,205 +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.
*/
import Foundation
class SocketConnection: NSObject {
var didOpen: (() -> Void)?
var didClose: ((Error?) -> Void)?
var streamHasSpaceAvailable: (() -> Void)?
private let filePath: String
private var socketHandle: Int32 = -1
private var address: sockaddr_un?
private var inputStream: InputStream?
private var outputStream: OutputStream?
private var networkQueue: DispatchQueue?
private var shouldKeepRunning = false
init?(filePath path: String) {
filePath = path
socketHandle = Darwin.socket(AF_UNIX, SOCK_STREAM, 0)
guard socketHandle != -1 else {
print("failure: create socket")
return nil
}
}
func open() -> Bool {
print("open socket connection")
guard FileManager.default.fileExists(atPath: filePath) else {
print("failure: socket file missing")
return false
}
guard setupAddress() == true else {
return false
}
guard connectSocket() == true else {
return false
}
setupStreams()
inputStream?.open()
outputStream?.open()
return true
}
func close() {
unscheduleStreams()
inputStream?.delegate = nil
outputStream?.delegate = nil
inputStream?.close()
outputStream?.close()
inputStream = nil
outputStream = nil
}
func writeToStream(buffer: UnsafePointer<UInt8>, maxLength length: Int) -> Int {
return outputStream?.write(buffer, maxLength: length) ?? 0
}
}
extension SocketConnection: StreamDelegate {
func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
switch eventCode {
case .openCompleted:
print("client stream open completed")
if aStream == outputStream {
didOpen?()
}
case .hasBytesAvailable:
if aStream == inputStream {
var buffer: UInt8 = 0
let numberOfBytesRead = inputStream?.read(&buffer, maxLength: 1)
if numberOfBytesRead == 0 && aStream.streamStatus == .atEnd {
print("server socket closed")
close()
notifyDidClose(error: nil)
}
}
case .hasSpaceAvailable:
if aStream == outputStream {
streamHasSpaceAvailable?()
}
case .errorOccurred:
print("client stream error occured: \(String(describing: aStream.streamError))")
close()
notifyDidClose(error: aStream.streamError)
default:
break
}
}
}
private extension SocketConnection {
func setupAddress() -> Bool {
var addr = sockaddr_un()
guard filePath.count < MemoryLayout.size(ofValue: addr.sun_path) else {
print("failure: fd path is too long")
return false
}
_ = withUnsafeMutablePointer(to: &addr.sun_path.0) { ptr in
filePath.withCString {
strncpy(ptr, $0, filePath.count)
}
}
address = addr
return true
}
func connectSocket() -> Bool {
guard var addr = address else {
return false
}
let status = withUnsafePointer(to: &addr) { ptr in
ptr.withMemoryRebound(to: sockaddr.self, capacity: 1) {
Darwin.connect(socketHandle, $0, socklen_t(MemoryLayout<sockaddr_un>.size))
}
}
guard status == noErr else {
print("failure: \(status)")
return false
}
return true
}
func setupStreams() {
var readStream: Unmanaged<CFReadStream>?
var writeStream: Unmanaged<CFWriteStream>?
CFStreamCreatePairWithSocket(kCFAllocatorDefault, socketHandle, &readStream, &writeStream)
inputStream = readStream?.takeRetainedValue()
inputStream?.delegate = self
inputStream?.setProperty(kCFBooleanTrue, forKey: Stream.PropertyKey(kCFStreamPropertyShouldCloseNativeSocket as String))
outputStream = writeStream?.takeRetainedValue()
outputStream?.delegate = self
outputStream?.setProperty(kCFBooleanTrue, forKey: Stream.PropertyKey(kCFStreamPropertyShouldCloseNativeSocket as String))
scheduleStreams()
}
func scheduleStreams() {
shouldKeepRunning = true
networkQueue = DispatchQueue.global(qos: .userInitiated)
networkQueue?.async { [weak self] in
self?.inputStream?.schedule(in: .current, forMode: .common)
self?.outputStream?.schedule(in: .current, forMode: .common)
var isRunning = false
repeat {
isRunning = self?.shouldKeepRunning ?? false && RunLoop.current.run(mode: .default, before: .distantFuture)
} while (isRunning)
}
}
func unscheduleStreams() {
networkQueue?.sync { [weak self] in
self?.inputStream?.remove(from: .current, forMode: .common)
self?.outputStream?.remove(from: .current, forMode: .common)
}
shouldKeepRunning = false
}
func notifyDidClose(error: Error?) {
if didClose != nil {
didClose?(error)
}
}
}

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.jitsi.meet.appgroup</string>
</array>
</dict>
</plist>

View File

@@ -35,7 +35,6 @@
jitsiMeet.defaultConferenceOptions = [JitsiMeetConferenceOptions fromBuilder:^(JitsiMeetConferenceOptionsBuilder *builder) {
[builder setFeatureFlag:@"resolution" withValue:@(360)];
[builder setFeatureFlag:@"ios.screensharing.enabled" withBoolean:YES];
builder.serverURL = [NSURL URLWithString:@"https://meet.jit.si"];
builder.welcomePageEnabled = YES;
@@ -52,7 +51,7 @@
if ([FIRUtilities appContainsRealServiceInfoPlist]) {
NSLog(@"Enabling Firebase");
[FIRApp configure];
// Crashlytics defaults to disabled with the FirebaseCrashlyticsCollectionEnabled Info.plist key.
// Crashlytics defaults to disabled wirth the FirebaseCrashlyticsCollectionEnabled Info.plist key.
[[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:![jitsiMeet isCrashReportingDisabled]];
}

View File

@@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>21.1.0</string>
<string>21.0.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
@@ -45,8 +45,6 @@
</array>
<key>CFBundleVersion</key>
<string>1</string>
<key>FirebaseCrashlyticsCollectionEnabled</key>
<string>false</string>
<key>FirebaseScreenReportingEnabled</key>
<false/>
<key>ITSAppUsesNonExemptEncryption</key>
@@ -68,18 +66,14 @@
<string>See your scheduled meetings in the app.</string>
<key>NSCameraUsageDescription</key>
<string>Participate in meetings with video.</string>
<key>NSLocalNetworkUsageDescription</key>
<string>Local network is used for establishing Peer-to-Peer connections.</string>
<key>NSMicrophoneUsageDescription</key>
<string>Participate in meetings with voice.</string>
<key>NSLocalNetworkUsageDescription</key>
<string>Local network is used for establishing Peer-to-Peer connections.</string>
<key>NSUserActivityTypes</key>
<array>
<string>org.jitsi.JitsiMeet.ios.conference</string>
</array>
<key>RTCAppGroupIdentifier</key>
<string>group.org.jitsi.meet.appgroup</string>
<key>RTCScreenSharingExtension</key>
<string>org.jitsi.meet.broadcast.extension</string>
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
@@ -105,5 +99,7 @@
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>FirebaseCrashlyticsCollectionEnabled</key>
<string>false</string>
</dict>
</plist>

View File

@@ -131,10 +131,6 @@
NSLog(@"%@%@", @"Chat toggled: ", data);
}
- (void)videoMutedChanged:(NSDictionary *)data {
NSLog(@"%@%@", @"Video muted changed: ", data[@"muted"]);
}
#pragma mark - Helpers
- (void)terminate {

View File

@@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>21.1.0</string>
<string>21.0.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.1.0</string>
<string>21.0.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>CLKComplicationPrincipalClass</key>

View File

@@ -35,7 +35,7 @@ fi
echo "PR_REPO_SLUG=${PR_REPO_SLUG} PR_BRANCH=${PR_BRANCH}"
# do the merge and git log
# do the marge and git log
if [ $PR_BRANCH != "master" ]; then
echo "Will merge ${PR_REPO_SLUG}/${PR_BRANCH} into master"

View File

@@ -90,7 +90,7 @@ echo "importing dev-key.p12"
security import ${CERT_DIR}/dev-key.p12 -k ios-build.keychain -P $IOS_SIGNING_CERT_PASSWORD -A
echo "will set-key-partition-list"
# Fix for OS X Sierra that hangs in the codesign step
# Fix for OS X Sierra that hungs in the codesign step
security set-key-partition-list -S apple-tool:,apple: -s -k $ENCRYPTION_PASSWORD ios-build.keychain > /dev/null
echo "done set-key-partition-list"

View File

@@ -9,15 +9,6 @@ platform :ios do
# Make sure we are on a clean tree
ensure_git_status_clean
# Connect to Apple Store Connect
app_store_connect_api_key(
key_id: ENV["ASC_KEY_ID"],
issuer_id: ENV["ASC_ISSUER_ID"],
key_content: ENV["ASC_KEY_CONTENT"],
duration: 1200,
in_house: false
)
# Set the app identifier
update_app_identifier(
xcodeproj: "app/app.xcodeproj",
@@ -25,20 +16,6 @@ platform :ios do
app_identifier: "com.atlassian.JitsiMeet.ios"
)
# Set the broadcast extension identifier
update_app_identifier(
xcodeproj: "app/app.xcodeproj",
plist_path: "broadcast-extension/Info.plist",
app_identifier: "com.atlassian.JitsiMeet.ios.broadcast"
)
update_info_plist(
xcodeproj: "app/app.xcodeproj",
plist_path: "src/Info.plist",
block: proc do |plist|
plist["RTCScreenSharingExtension"] = "com.atlassian.JitsiMeet.ios.broadcast"
end
)
# Set the (watch) app identifier
update_app_identifier(
xcodeproj: "app/app.xcodeproj",
@@ -103,24 +80,12 @@ platform :ios do
uses_non_exempt_encryption: false
)
# Upload dSYMs to Crashlytics
download_dsyms
upload_symbols_to_crashlytics
# Cleanup
clean_build_artifacts
reset_git_repo(skip_clean: true)
end
lane :refresh_dsyms do
# Connect to Apple Store Connect
app_store_connect_api_key(
key_id: ENV["ASC_KEY_ID"],
issuer_id: ENV["ASC_ISSUER_ID"],
key_content: ENV["ASC_KEY_CONTENT"],
duration: 1200,
in_house: false
)
# Upload dSYMs to Crashlytics
download_dsyms(min_version: ENV["DSYMS_MIN_VERSION"]) # Download dSYM files from iTC
upload_symbols_to_crashlytics # Upload them to Crashlytics
clean_build_artifacts # Delete the local dSYM files
end
end

View File

@@ -24,8 +24,6 @@
0BCA49601EC4B6C600B793EE /* POSIX.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BCA495D1EC4B6C600B793EE /* POSIX.m */; };
0BCA49611EC4B6C600B793EE /* Proximity.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BCA495E1EC4B6C600B793EE /* Proximity.m */; };
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 */; };
6C31EDC820C06D490089C899 /* recordingOn.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 6C31EDC720C06D490089C899 /* recordingOn.mp3 */; };
6C31EDCA20C06D530089C899 /* recordingOff.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 6C31EDC920C06D530089C899 /* recordingOff.mp3 */; };
6F08DF7D4458EE3CF3F36F6D /* libPods-JitsiMeetSDK.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E4376CA6886DE68FD7A4294B /* libPods-JitsiMeetSDK.a */; };
@@ -87,8 +85,6 @@
0BD906E51EC0C00300C8C18E /* JitsiMeetSDK.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = JitsiMeetSDK.framework; sourceTree = BUILT_PRODUCTS_DIR; };
0BD906E81EC0C00300C8C18E /* JitsiMeet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JitsiMeet.h; sourceTree = "<group>"; };
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>"; };
6C31EDC720C06D490089C899 /* recordingOn.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; name = recordingOn.mp3; path = ../../sounds/recordingOn.mp3; sourceTree = "<group>"; };
6C31EDC920C06D530089C899 /* recordingOff.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; name = recordingOff.mp3; path = ../../sounds/recordingOff.mp3; sourceTree = "<group>"; };
75635B0820751D6D00F29C9F /* joined.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = joined.wav; path = ../../sounds/joined.wav; sourceTree = "<group>"; };
@@ -198,6 +194,7 @@
0BCA495C1EC4B6C600B793EE /* AudioMode.m */,
C69EFA02209A0EFD0027712B /* callkit */,
A4A934E7212F3AB8001E9388 /* dropbox */,
0BA13D301EE83FF8007BEF7F /* ExternalAPI.m */,
0BD906E91EC0C00300C8C18E /* Info.plist */,
DE438CD82350934700DD541D /* JavaScriptSandbox.m */,
0BD906E81EC0C00300C8C18E /* JitsiMeet.h */,
@@ -234,9 +231,6 @@
C8AFD27D2462C613000293D2 /* InfoPlistUtil.h */,
C8AFD27E2462C613000293D2 /* InfoPlistUtil.m */,
C81E9AB825AC5AD800B134D9 /* ExternalAPI.h */,
0BA13D301EE83FF8007BEF7F /* ExternalAPI.m */,
4E51B76225E5345E0038575A /* ScheenshareEventEmiter.h */,
4E51B76325E5345E0038575A /* ScheenshareEventEmiter.m */,
);
path = src;
sourceTree = "<group>";
@@ -304,7 +298,6 @@
0B93EF7E1EC9DDCD0030D24D /* RCTBridgeWrapper.h in Headers */,
DE81A2DE2317ED5400AE1940 /* JitsiMeetBaseLogHandler.h in Headers */,
DEA9F284258A5D9900D4CD74 /* JitsiMeetSDK.h in Headers */,
4E51B76425E5345E0038575A /* ScheenshareEventEmiter.h in Headers */,
DE65AACC2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h in Headers */,
0B412F221EDEF6EA00B1A0A6 /* JitsiMeetViewDelegate.h in Headers */,
0BD906EA1EC0C00300C8C18E /* JitsiMeet.h in Headers */,
@@ -473,7 +466,6 @@
C69EFA0C209A0F660027712B /* JMCallKitEmitter.swift in Sources */,
DEFE535621FB2E8300011A3A /* ReactUtils.m in Sources */,
C6A34261204EF76800E062DD /* DragGestureController.swift in Sources */,
4E51B76525E5345E0038575A /* ScheenshareEventEmiter.m in Sources */,
A4A934E9212F3ADB001E9388 /* Dropbox.m in Sources */,
C69EFA0D209A0F660027712B /* JMCallKitProxy.swift in Sources */,
DE81A2D52316AC4D00AE1940 /* JitsiMeetLogger.m in Sources */,

View File

@@ -20,12 +20,11 @@
- (void)sendHangUp;
- (void)sendSetAudioMuted:(BOOL)muted;
- (void)sendEndpointTextMessage:(NSString*)message :(NSString*)to;
- (void)toggleScreenShare:(BOOL)enabled;
- (void)sendEndpointTextMessage:(NSString*)to :(NSString*)message;
- (void)toggleScreenShare;
- (void)retrieveParticipantsInfo:(void (^)(NSArray*))completion;
- (void)openChat:(NSString*)to;
- (void)closeChat;
- (void)sendChatMessage:(NSString*)message :(NSString*)to ;
- (void)sendSetVideoMuted:(BOOL)muted;
- (void)sendChatMessage:(NSString*)to :(NSString*)message;
@end

View File

@@ -26,7 +26,6 @@ static NSString * const retrieveParticipantsInfoAction = @"org.jitsi.meet.RETRIE
static NSString * const openChatAction = @"org.jitsi.meet.OPEN_CHAT";
static NSString * const closeChatAction = @"org.jitsi.meet.CLOSE_CHAT";
static NSString * const sendChatMessageAction = @"org.jitsi.meet.SEND_CHAT_MESSAGE";
static NSString * const setVideoMutedAction = @"org.jitsi.meet.SET_VIDEO_MUTED";
@implementation ExternalAPI
@@ -48,8 +47,7 @@ RCT_EXPORT_MODULE();
@"RETRIEVE_PARTICIPANTS_INFO": retrieveParticipantsInfoAction,
@"OPEN_CHAT": openChatAction,
@"CLOSE_CHAT": closeChatAction,
@"SEND_CHAT_MESSAGE": sendChatMessageAction,
@"SET_VIDEO_MUTED" : setVideoMutedAction
@"SEND_CHAT_MESSAGE": sendChatMessageAction
};
};
@@ -72,8 +70,7 @@ RCT_EXPORT_MODULE();
retrieveParticipantsInfoAction,
openChatAction,
closeChatAction,
sendChatMessageAction,
setVideoMutedAction
sendChatMessageAction
];
}
@@ -156,7 +153,7 @@ RCT_EXPORT_METHOD(sendEvent:(NSString *)name
[self sendEventWithName:setAudioMutedAction body:data];
}
- (void)sendEndpointTextMessage:(NSString*)message :(NSString*)to {
- (void)sendEndpointTextMessage:(NSString*)to :(NSString*)message {
NSMutableDictionary *data = [[NSMutableDictionary alloc] init];
data[@"to"] = to;
data[@"message"] = message;
@@ -164,11 +161,8 @@ RCT_EXPORT_METHOD(sendEvent:(NSString *)name
[self sendEventWithName:sendEndpointTextMessageAction body:data];
}
- (void)toggleScreenShare:(BOOL)enabled {
NSMutableDictionary *data = [[NSMutableDictionary alloc] init];
data[@"enabled"] = [NSNumber numberWithBool:enabled];
[self sendEventWithName:toggleScreenShareAction body:data];
- (void)toggleScreenShare {
[self sendEventWithName:toggleScreenShareAction body:nil];
}
- (void)retrieveParticipantsInfo:(void (^)(NSArray*))completionHandler {
@@ -191,7 +185,7 @@ RCT_EXPORT_METHOD(sendEvent:(NSString *)name
[self sendEventWithName:closeChatAction body:nil];
}
- (void)sendChatMessage:(NSString*)message :(NSString*)to {
- (void)sendChatMessage:(NSString*)to :(NSString*)message {
NSMutableDictionary *data = [[NSMutableDictionary alloc] init];
data[@"to"] = to;
data[@"message"] = message;
@@ -199,11 +193,4 @@ RCT_EXPORT_METHOD(sendEvent:(NSString *)name
[self sendEventWithName:sendChatMessageAction body:data];
}
- (void)sendSetVideoMuted:(BOOL)muted {
NSDictionary *data = @{ @"muted": [NSNumber numberWithBool:muted]};
[self sendEventWithName:setVideoMutedAction body:data];
}
@end

View File

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

View File

@@ -23,7 +23,6 @@
#import "RCTBridgeWrapper.h"
#import "ReactUtils.h"
#import "RNSplashScreen.h"
#import "ScheenshareEventEmiter.h"
#import <RNGoogleSignin/RNGoogleSignin.h>
#import <WebRTC/RTCLogging.h>
@@ -32,7 +31,6 @@
@implementation JitsiMeet {
RCTBridgeWrapper *_bridgeWrapper;
NSDictionary *_launchOptions;
ScheenshareEventEmiter *_screenshareEventEmiter;
}
#pragma mak - This class is a singleton
@@ -52,9 +50,6 @@
if (self = [super init]) {
// Initialize the on and only bridge for interfacing with React Native.
_bridgeWrapper = [[RCTBridgeWrapper alloc] init];
// Initialize the listener for handling start/stop screensharing notifications.
_screenshareEventEmiter = [[ScheenshareEventEmiter alloc] init];
// Register a fatal error handler for React.
registerReactFatalErrorHandler();

View File

@@ -71,16 +71,6 @@
- (void)setFeatureFlag:(NSString *_Nonnull)flag withBoolean:(BOOL)value;
- (void)setFeatureFlag:(NSString *_Nonnull)flag withValue:(id _Nonnull)value;
/**
* CallKit call handle, to be used when implementing incoming calls.
*/
@property (nonatomic, copy, nullable) NSString *callHandle;
/**
* CallKit call UUID, to be used when implementing incoming calls.
*/
@property (nonatomic, copy, nullable) NSUUID *callUUID;
@end
@interface JitsiMeetConferenceOptions : NSObject
@@ -102,9 +92,6 @@
@property (nonatomic, nullable) JitsiMeetUserInfo *userInfo;
@property (nonatomic, copy, nullable, readonly) NSString *callHandle;
@property (nonatomic, copy, nullable, readonly) NSUUID *callUUID;
+ (instancetype _Nonnull)fromBuilder:(void (^_Nonnull)(JitsiMeetConferenceOptionsBuilder *_Nonnull))initBlock;
- (instancetype _Nonnull)init NS_UNAVAILABLE;

View File

@@ -52,9 +52,6 @@ static NSString *const WelcomePageEnabledFeatureFlag = @"welcomepage.enabled";
_videoMuted = nil;
_userInfo = nil;
_callHandle = nil;
_callUUID = nil;
}
return self;
@@ -171,9 +168,6 @@ static NSString *const WelcomePageEnabledFeatureFlag = @"welcomepage.enabled";
_featureFlags = [NSDictionary dictionaryWithDictionary:builder.featureFlags];
_userInfo = builder.userInfo;
_callHandle = builder.callHandle;
_callUUID = builder.callUUID;
}
return self;
@@ -211,12 +205,6 @@ static NSString *const WelcomePageEnabledFeatureFlag = @"welcomepage.enabled";
if (_subject != nil) {
config[@"subject"] = self.subject;
}
if (_callHandle != nil) {
config[@"callHandle"] = self.callHandle;
}
if (_callUUID != nil) {
config[@"callUUID"] = [self.callUUID UUIDString];
}
NSMutableDictionary *urlProps = [[NSMutableDictionary alloc] init];

View File

@@ -38,12 +38,11 @@
- (void)leave;
- (void)hangUp;
- (void)setAudioMuted:(BOOL)muted;
- (void)sendEndpointTextMessage:(NSString * _Nonnull)message :(NSString * _Nullable)to;
- (void)toggleScreenShare:(BOOL)enabled;
- (void)retrieveParticipantsInfo:(void (^ _Nonnull)(NSArray * _Nullable))completionHandler;
- (void)openChat:(NSString * _Nullable)to;
- (void)sendEndpointTextMessage:(NSString*)to :(NSString*)message;
- (void)toggleScreenShare;
- (void)retrieveParticipantsInfo:(void (^)(NSArray*))completionHandler;
- (void)openChat:(NSString*)to;
- (void)closeChat;
- (void)sendChatMessage:(NSString * _Nonnull)message :(NSString * _Nullable)to;
- (void)setVideoMuted:(BOOL)muted;
- (void)sendChatMessage:(NSString*)to :(NSString*)message;
@end

View File

@@ -125,17 +125,17 @@ static void initializeViewsMap() {
[externalAPI sendSetAudioMuted:muted];
}
- (void)sendEndpointTextMessage:(NSString * _Nonnull)message :(NSString * _Nullable)to {
- (void)sendEndpointTextMessage:(NSString*)to :(NSString*)message {
ExternalAPI *externalAPI = [[JitsiMeet sharedInstance] getExternalAPI];
[externalAPI sendEndpointTextMessage:message :to];
[externalAPI sendEndpointTextMessage:to :message];
}
- (void)toggleScreenShare:(BOOL)enabled {
- (void)toggleScreenShare {
ExternalAPI *externalAPI = [[JitsiMeet sharedInstance] getExternalAPI];
[externalAPI toggleScreenShare:enabled];
[externalAPI toggleScreenShare];
}
- (void)retrieveParticipantsInfo:(void (^ _Nonnull)(NSArray * _Nullable))completionHandler {
- (void)retrieveParticipantsInfo:(void (^)(NSArray*))completionHandler {
ExternalAPI *externalAPI = [[JitsiMeet sharedInstance] getExternalAPI];
[externalAPI retrieveParticipantsInfo:completionHandler];
}
@@ -150,14 +150,9 @@ static void initializeViewsMap() {
[externalAPI closeChat];
}
- (void)sendChatMessage:(NSString * _Nonnull)message :(NSString * _Nullable)to {
- (void)sendChatMessage:(NSString*)to :(NSString*)message {
ExternalAPI *externalAPI = [[JitsiMeet sharedInstance] getExternalAPI];
[externalAPI sendChatMessage:message :to];
}
- (void)setVideoMuted:(BOOL)muted {
ExternalAPI *externalAPI = [[JitsiMeet sharedInstance] getExternalAPI];
[externalAPI sendSetVideoMuted:muted];
[externalAPI sendChatMessage:to :message];
}
#pragma mark Private methods
@@ -189,7 +184,7 @@ static void initializeViewsMap() {
// conference. However, React and, respectively,
// appProperties/initialProperties are declarative expressions i.e. one and
// the same URL will not trigger an automatic re-render in the JavaScript
// source code. The workaround implemented below introduces imperativeness
// source code. The workaround implemented bellow introduces imperativeness
// in React Component props by defining a unique value per invocation.
props[@"timestamp"] = @(mach_absolute_time());

View File

@@ -95,7 +95,7 @@
*
* The `data` dictionary contains `message`, `senderId` and `isPrivate` keys.
*/
- (void)chatMessageReceived:(NSDictionary *)data;
- (void)chatMessaageReceived:(NSDictionary *)data;
/**
* Called when the chat dialog is displayed/hidden.
@@ -104,11 +104,4 @@
*/
- (void)chatToggled:(NSDictionary *)data;
/**
* Called when videoMuted state changed.
*
* The `data` dictionary contains a `muted` key with state of the videoMuted for the localParticipant.
*/
- (void)videoMutedChanged:(NSDictionary *)data;
@end

View File

@@ -1,25 +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.
*/
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface ScheenshareEventEmiter : NSObject
@end
NS_ASSUME_NONNULL_END

View File

@@ -1,72 +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.
*/
#import "ScheenshareEventEmiter.h"
#import "JitsiMeet+Private.h"
#import "ExternalAPI.h"
NSNotificationName const kBroadcastStartedNotification = @"iOS_BroadcastStarted";
NSNotificationName const kBroadcastStoppedNotification = @"iOS_BroadcastStopped";
@implementation ScheenshareEventEmiter {
CFNotificationCenterRef _notificationCenter;
}
- (instancetype)init {
self = [super init];
if (self) {
_notificationCenter = CFNotificationCenterGetDarwinNotifyCenter();
[self setupObserver];
}
return self;
}
- (void)dealloc {
[self clearObserver];
}
// MARK: Private Methods
- (void)setupObserver {
CFNotificationCenterAddObserver(_notificationCenter, (__bridge const void *)(self), broadcastStartedNotificationCallback, (__bridge CFStringRef)kBroadcastStartedNotification, NULL, CFNotificationSuspensionBehaviorDeliverImmediately);
CFNotificationCenterAddObserver(_notificationCenter, (__bridge const void *)(self), broadcastStoppedNotificationCallback, (__bridge CFStringRef)kBroadcastStoppedNotification, NULL, CFNotificationSuspensionBehaviorDeliverImmediately);
}
- (void)clearObserver {
CFNotificationCenterRemoveObserver(_notificationCenter, (__bridge const void *)(self), (__bridge CFStringRef)kBroadcastStartedNotification, NULL);
CFNotificationCenterRemoveObserver(_notificationCenter, (__bridge const void *)(self), (__bridge CFStringRef)kBroadcastStoppedNotification, NULL);
}
void broadcastStartedNotificationCallback(CFNotificationCenterRef center,
void *observer,
CFStringRef name,
const void *object,
CFDictionaryRef userInfo) {
ExternalAPI *externalAPI = [[JitsiMeet sharedInstance] getExternalAPI];
[externalAPI toggleScreenShare:true];
}
void broadcastStoppedNotificationCallback(CFNotificationCenterRef center,
void *observer,
CFStringRef name,
const void *object,
CFDictionaryRef userInfo) {
ExternalAPI *externalAPI = [[JitsiMeet sharedInstance] getExternalAPI];
[externalAPI toggleScreenShare:false];
}
@end

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