Compare commits

...

26 Commits

Author SHA1 Message Date
Saúl Ibarra Corretgé
9148d1262d misc: s/Atlassian/8x8/ 2019-03-29 13:09:15 +01:00
Leonard Kim
3b911b0362 chore(deps): bump lib-jitsi-meet for permissions api fixes 2019-03-28 08:47:42 -05:00
Philip-Choi
7ae8ae5791 doc: update README 2019-03-28 09:46:03 +01:00
paweldomas
a386740103 fix(ConnectionService): history and audio focus on Samsung devices
On some Samsung devices the call done with the ConnectionService end up
in the native call history which we don't want. That's fixable by
marking the Connection as "external" just before the call is
disconnected.

Another issue specific to Samsung devices about the audio focus not
always being release when that call ends. That's fixable by marking
the call as holding just before disconnecting it.
2019-03-27 13:39:52 -05:00
Saúl Ibarra Corretgé
451949f49d android: enable PiP support by default in JitsiMeetActivity 2019-03-27 17:39:09 +01:00
Saúl Ibarra Corretgé
61ed459971 android: add JitsiMeetActivity.launch helper methods
They greatly simplify starting a JitsiMeetActivity by encapsulating the creation
of the Intent adn extras placement.

In order to make this possible JitsiMeetConferenceOptions now implements
Parcelable so it can be serialized and passed around when creating an Intent.
2019-03-27 17:39:09 +01:00
Saúl Ibarra Corretgé
c30a4a0aa6 android: make Amplitude and Dropbox modules package private 2019-03-27 17:39:09 +01:00
paweldomas
e839684ae9 fix(base/conference): tracks not added to the conference
If tracks are created while the conference is in the 'joining' state
they will never be added.
2019-03-27 10:06:59 +01:00
Saúl Ibarra Corretgé
15c5a2339b android: fix getting permission request results
Now that we have both a Fragment and an Activity there are lifecycle methods
that overlap. If a Fragment requests permission by calling requestPermissions
then the result handler will be called on itself. React Native's permissions
module, however, calls ActivityCompat.requestPermissions on the Activity, thus
we need to handle the results at the Activity level and not at the Fragment
level.
2019-03-26 11:56:14 -05:00
virtuacoplenny
d7e112aaf0 fix(display-name): do not default name to placeholder name (#4027)
* ref(display-name): do not pass in display name

The component gets the state itself from redux.

* fix(display-name): do not default name to placeholder name

The web display name component supports inline editing of
the name. Problems can occur when the displayed name
differs from the actual saved name, because participants
without a display name, including the local user, have
a different, default display name displayed. So when
editing starts, the input field is populated with the
default name. To workaround such while supporting fetching
the display name using mapStateToProps, pass in both the
name which should be shown and the name value saved in
settings.

* ref(display-name): rename methods
2019-03-26 09:34:02 -07:00
Saúl Ibarra Corretgé
24339b2461 ios: update Podfile.lock 2019-03-26 13:47:57 +01:00
Bettenbuk Zoltan
5b02c575f7 eslint-config-jitsi#1.0.0 2019-03-26 13:35:02 +01:00
Mayur Shah
1f8904a95b deps: react-native@0.59.2 2019-03-26 10:53:50 +01:00
Saúl Ibarra Corretgé
50268a08a0 ios: ensure the git tree is clean when / after building 2019-03-25 19:08:12 +01:00
Saúl Ibarra Corretgé
985385f364 ios: update fastlane Fastfile 2019-03-25 19:08:12 +01:00
Saúl Ibarra Corretgé
f662edd135 ios: don't bundle a dummy GoogleService-Info.plist file
It complicates automated builds.
2019-03-25 19:08:12 +01:00
Saúl Ibarra Corretgé
7ebcf69937 android: add fastlane integration 2019-03-25 19:08:12 +01:00
Saúl Ibarra Corretgé
40364ae269 misc: update gitignore 2019-03-25 19:08:12 +01:00
Saúl Ibarra Corretgé
030af37668 android: generate versionCode automatically
It's a number whichb must be ever increasing with each build submitted to the
store.

Automate its value by using the number of seconds since 1st of January 2019.
That should be enough for ~680 years.
2019-03-25 19:08:12 +01:00
Saúl Ibarra Corretgé
e29bc4bbb6 deps: update react-native-callstats to version 3.58.2 2019-03-25 14:56:52 +01:00
Bettenbuk Zoltan
13212a5980 [RN] Replace chat modal with SlidingView 2019-03-25 14:52:43 +01:00
Bettenbuk Zoltan
2a5adfc601 Remove some Flow annotations 2019-03-25 13:53:08 +01:00
paweldomas
19e8e8710a fix(Android/ConnectionService): do not display the address
Turns out that on Samsung phones the calls placed with
the ConnectionService appear in the calls log as weird long numbers.
The system mangles the address we give it ("sip:meet.jit.si/something")
into this weird long number and the call to request.getAddress() returns
that. Turn off the presentation as neither this number nor our address
makes sense. This way the call appears as from "Unknown" caller in call
history which is still not perfect, but better than the random number.

Note that other phones will preserve the originally passed address value
(tested on One Plus 5).
2019-03-25 09:24:33 +01:00
paweldomas
3b24124d57 fix(Android/ConnectionService): mic not working
Turns out the microphone will not work on some devices when starting in
"audio only", because the audio mode is not set to the MODE_IN_COMMUNICATION,
but to the MODE_IN_CALL. Calling setAudioModeIsVoip(true) makes
the system adjust to MODE_IN_COMMUNICATION and the mic works fine.
2019-03-25 09:24:33 +01:00
damencho
6894de00cc Fixes a typo of getting default number. 2019-03-23 09:59:25 +00:00
paweldomas
6d0b6bee85 ref(AudioModeModule): check 1 method to enable ConnectionService 2019-03-22 09:17:14 +01:00
204 changed files with 1007 additions and 792 deletions

2
.gitignore vendored
View File

@@ -86,4 +86,6 @@ android/.settings/org.eclipse.buildship.core.prefs
# Secrets
android/app/dropbox.key
android/app/google-services.json
ios/app/dropbox.key
ios/app/GoogleService-Info.plist

View File

@@ -13,7 +13,7 @@ Found a bug and know how to fix it? Great! Please read on.
## Contributor License Agreement
While the Jitsi projects are released under the
[Apache License 2.0](https://github.com/jitsi/jitsi-meet/blob/master/LICENSE), the copyright
holder and principal creator is [Atlassian](https://www.atlassian.com/). To
holder and principal creator is [8x8](https://www.8x8.com/). To
ensure that we can continue making these projects available under an Open Source license,
we need you to sign our Apache-based contributor
license agreement as either a [corporation](https://jitsi.org/ccla) or an

View File

@@ -1,16 +1,16 @@
# Jitsi Meet - Secure, Simple and Scalable Video Conferences
Jitsi Meet is an open-source (Apache) WebRTC JavaScript application that uses [Jitsi Videobridge](https://jitsi.org/videobridge) to provide high quality, [secure](#security) and scalable video conferences. You can see Jitsi Meet in action [here at the session #482 of the VoIP Users Conference](http://youtu.be/7vFUVClsNh0).
Jitsi Meet is an open-source (Apache) WebRTC JavaScript application that uses [Jitsi Videobridge](https://jitsi.org/videobridge) to provide high quality, [secure](#security) and scalable video conferences. Jitsi Meet in action can be seen at [here at the session #482 of the VoIP Users Conference](http://youtu.be/7vFUVClsNh0).
The Jitsi Meet client runs in your browser, without the need for installing anything on your computer. You can also try it out yourself at https://meet.jit.si .
The Jitsi Meet client runs in your browser, without installing anything on your computer. You can try it out at https://meet.jit.si .
Jitsi Meet allows for very efficient collaboration. It allows users to stream their desktop or only some windows. It also supports shared document editing with Etherpad.
Jitsi Meet allows very efficient collaboration. Users can stream their desktop or only some windows. It also supports shared document editing with Etherpad.
## Installation
On the client side, no installation is necessary. You just point your browser to the URL of your deployment. This section is about installing the Jitsi Meet suite on your server and hosting your own conferencing service.
On the client side, no installation is necessary. You just point your browser to the URL of your deployment. This section is about installing a Jitsi Meet suite on your server and hosting your own conferencing service.
Installing Jitsi Meet is quite a simple experience. For Debian-based systems, we recommend following the [quick-install](https://github.com/jitsi/jitsi-meet/blob/master/doc/quick-install.md) document, which uses the package system. You can also see a demonstration of the process in [this tutorial video](https://jitsi.org/tutorial).
Installing Jitsi Meet is a simple experience. For Debian-based system, following the [quick-install](https://github.com/jitsi/jitsi-meet/blob/master/doc/quick-install.md) document, which uses the package system. You can also see a demonstration of the process in [this tutorial video](https://jitsi.org/tutorial).
For other systems, or if you wish to install all components manually, see the [detailed manual installation instructions](https://github.com/jitsi/jitsi-meet/blob/master/doc/manual-install.md).
@@ -59,7 +59,7 @@ To work with local copy you must change the path to:
"lib-jitsi-meet": "file:///Users/name/local-lib-jitsi-meet-copy",
```
To make the project you must force it to take the sources as 'npm update' will not do it.
To make the project you must force it to take the sources as 'npm update':
```
npm install lib-jitsi-meet --force && make
```
@@ -84,8 +84,8 @@ cd ../jitsi-meet
npm link lib-jitsi-meet
```
So now after changes in local `lib-jitsi-meet` repository you can rebuild it with `npm run install` and your `jitsi-meet` repository will use that modified library.
Note: when using node version 4.x, the make file of jitsi-meet do npm update which will delete the link, no longer the case with version 6.x.
After changes in local `lib-jitsi-meet` repository, you can rebuild it with `npm run install` and your `jitsi-meet` repository will use that modified library.
Note: when using node version 4.x, the make file of jitsi-meet do npm update which will delete the link. It is no longer the case with version 6.x.
If you do not want to use local repository anymore you should run
```bash
@@ -100,7 +100,7 @@ Use it at the CLI, type
make dev
```
By default the backend deployment used is `beta.meet.jit.si`, you can point the Jitsi-Meet app at a different backend by using a proxy server. To do this set the WEBPACK_DEV_SERVER_PROXY_TARGET variable:
By default the backend deployment used is `beta.meet.jit.si`. You can point the Jitsi-Meet app at a different backend by using a proxy server. To do this, set the WEBPACK_DEV_SERVER_PROXY_TARGET variable:
```
export WEBPACK_DEV_SERVER_PROXY_TARGET=https://your-example-server.com
make dev
@@ -115,18 +115,16 @@ see our [guidelines for contributing](CONTRIBUTING.md).
## Embedding in external applications
Jitsi Meet provides a very flexible way of embedding it in external applications by using the [Jitsi Meet API](doc/api.md).
Jitsi Meet provides a very flexible way of embedding in external applications by using the [Jitsi Meet API](doc/api.md).
## Security
WebRTC today does not provide a way of conducting multiparty conversations with
end-to-end encryption. As a matter of fact, unless you consistently vocally
compare DTLS fingerprints with your peers, the same goes for one-to-one calls.
As a result when using a Jitsi Meet instance, your stream is encrypted on the
network but decrypted on the machine that hosts the bridge.
WebRTC does not provide a way of conducting multi-party conversations with end-to-end encryption.
Unless you consistently compare DTLS fingerprints with your peers vocally, the same goes for one-to-one calls.
As a result, your stream is encrypted on the network but decrypted on the machine that hosts the bridge when using Jitsi Meet.
The Jitsi Meet architecture allows you to deploy your own version, including
all server components, and in that case your security guarantees will be roughly
equivalent to these of a direct one-to-one WebRTC call. This is what's unique to
all server components. In that case, your security guarantees will be roughly
equivalent to a direct one-to-one WebRTC call. This is the uniqueness of
Jitsi Meet in terms of security.
The [meet.jit.si](https://meet.jit.si) service is maintained by the Jitsi team
@@ -138,4 +136,4 @@ Instructions on how to build it can be found [here](doc/mobile.md).
## Acknowledgements
Jitsi Meet started out as a sample conferencing application using Jitsi Videobridge. It was originally developed by then ESTOS' developer Philipp Hancke who then contributed it to the community where development continues with joint forces!
Jitsi Meet started out as a sample conferencing application using Jitsi Videobridge. It was originally developed by ESTOS' developer Philipp Hancke who then contributed it to the community where development continues with joint forces!

View File

@@ -8,6 +8,11 @@ if (googleServicesEnabled) {
apply plugin: 'io.fabric'
}
// Use the number of seconds/10 since Jan 1 2019 as the versionCode.
// This lets us upload a new build at most every 10 seconds for the
// next ~680 years.
// https://stackoverflow.com/a/38643838
def vcode = (int)(((new Date().getTime()/1000) - 1546297200) / 10)
android {
compileSdkVersion rootProject.ext.compileSdkVersion
@@ -15,7 +20,7 @@ android {
defaultConfig {
applicationId 'org.jitsi.meet'
versionCode Integer.parseInt(project.buildNumber)
versionCode vcode
versionName project.appVersion
minSdkVersion rootProject.ext.minSdkVersion

2
android/fastlane/Appfile Normal file
View File

@@ -0,0 +1,2 @@
json_key_file("")
package_name("org.jitsi.meet")

34
android/fastlane/Fastfile Normal file
View File

@@ -0,0 +1,34 @@
ENV["FASTLANE_SKIP_UPDATE_CHECK"] = "1"
opt_out_usage
default_platform(:android)
platform :android do
desc "Deploy a new version to Goolge Play (Closed Beta)"
lane :deploy do
# Cleanup
gradle(task: "clean")
# Build and sign the app
gradle(
task: "assemble",
build_type: "Release",
print_command: false,
properties: {
"android.injected.signing.store.file" => ENV["JITSI_KEYSTORE"],
"android.injected.signing.store.password" => ENV["JITSI_KEYSTORE_PASSWORD"],
"android.injected.signing.key.alias" => ENV["JITSI_KEY_ALIAS"],
"android.injected.signing.key.password" => ENV["JITSI_KEY_PASSWORD"],
}
)
# Upload built artifact to the Closed Beta track
upload_to_play_store(
track: "Closed Beta",
json_key: ENV["JITSI_JSON_KEY_FILE"],
skip_upload_metadata: true,
skip_upload_images: true,
skip_upload_screenshots: true
)
end
end

View File

@@ -0,0 +1,29 @@
fastlane documentation
================
# Installation
Make sure you have the latest version of the Xcode command line tools installed:
```
xcode-select --install
```
Install _fastlane_ using
```
[sudo] gem install fastlane -NV
```
or alternatively using `brew cask install fastlane`
# Available Actions
## Android
### android deploy
```
fastlane android deploy
```
Deploy a new version to Goolge Play (Closed Beta)
----
This README.md is auto-generated and will be re-generated every time [fastlane](https://fastlane.tools) is run.
More information about fastlane can be found on [fastlane.tools](https://fastlane.tools).
The documentation of fastlane can be found on [docs.fastlane.tools](https://docs.fastlane.tools).

View File

@@ -17,6 +17,5 @@
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
buildNumber=1
appVersion=19.1.0
sdkVersion=2.0.0

View File

@@ -27,7 +27,14 @@
android:allowBackup="true"
android:label="@string/app_name"
android:supportsRtl="true">
<activity android:name=".JitsiMeetActivity"></activity>
<activity
android:name=".JitsiMeetActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize"
android:launchMode="singleTask"
android:resizeableActivity="true"
android:supportsPictureInPicture="true"
android:windowSoftInputMode="adjustResize">
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
<service

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jitsi.meet.sdk.analytics;
package org.jitsi.meet.sdk;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
@@ -31,7 +31,7 @@ import org.json.JSONObject;
* Implements the react-native module for the Amplitude integration.
*/
@ReactModule(name = AmplitudeModule.NAME)
public class AmplitudeModule
class AmplitudeModule
extends ReactContextBaseJavaModule {
public static final String NAME = "Amplitude";

View File

@@ -158,7 +158,7 @@ class AudioModeModule extends ReactContextBaseJavaModule
/**
* Whether or not the ConnectionService is used for selecting audio devices.
*/
private static boolean useConnectionService() {
static boolean useConnectionService() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
}
@@ -295,9 +295,9 @@ class AudioModeModule extends ReactContextBaseJavaModule
= (AudioManager)
reactContext.getSystemService(Context.AUDIO_SERVICE);
// Starting Oreo the ConnectionImpl from ConnectionService us used to
// Starting Oreo the ConnectionImpl from ConnectionService is used to
// detect the available devices.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
if (!useConnectionService()) {
// Setup runtime device change detection.
setupAudioRouteChangeDetection();

View File

@@ -81,6 +81,13 @@ public class ConnectionService extends android.telecom.ConnectionService {
return new ArrayList<>(connections.values());
}
/**
* @return {@code true} if running a Samsung device.
*/
static boolean isSamsungDevice() {
return android.os.Build.MANUFACTURER.toLowerCase().contains("samsung");
}
/**
* Registers a start call promise.
*
@@ -129,6 +136,14 @@ public class ConnectionService extends android.telecom.ConnectionService {
ConnectionImpl connection = connections.get(callUUID);
if (connection != null) {
if (isSamsungDevice()) {
// Required to release the audio focus correctly.
connection.setOnHold();
// Prevents from including in the native phone calls history
connection.setConnectionProperties(
Connection.PROPERTY_SELF_MANAGED
| Connection.PROPERTY_IS_EXTERNAL_CALL);
}
// Note that the connection is not removed from the list here, but
// in ConnectionImpl's state changed callback. It's a safer
// approach, because in case the app would crash on the JavaScript
@@ -189,8 +204,11 @@ public class ConnectionService extends android.telecom.ConnectionService {
connection.setConnectionProperties(Connection.PROPERTY_SELF_MANAGED);
connection.setAddress(
request.getAddress(),
TelecomManager.PRESENTATION_ALLOWED);
TelecomManager.PRESENTATION_UNKNOWN);
connection.setExtras(request.getExtras());
connection.setAudioModeIsVoip(true);
// NOTE there's a time gap between the placeCall and this callback when
// things could get out of sync, but they are put back in sync once
// the startCall Promise is resolved below. That's because on
@@ -426,7 +444,7 @@ public class ConnectionService extends android.telecom.ConnectionService {
@Override
public String toString() {
return String.format(
"ConnectionImpl[adress=%s, uuid=%s]@%d",
"ConnectionImpl[address=%s, uuid=%s]@%d",
getAddress(), getCallUUID(), hashCode());
}
}

View File

@@ -1,4 +1,4 @@
package org.jitsi.meet.sdk.dropbox;
package org.jitsi.meet.sdk;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -28,8 +28,8 @@ import java.util.Map;
/**
* Implements the react-native module for the dropbox integration.
*/
@ReactModule(name = Dropbox.NAME)
public class Dropbox
@ReactModule(name = DropboxModule.NAME)
class DropboxModule
extends ReactContextBaseJavaModule
implements LifecycleEventListener {
@@ -43,7 +43,7 @@ public class Dropbox
private Promise promise;
public Dropbox(ReactApplicationContext reactContext) {
public DropboxModule(ReactApplicationContext reactContext) {
super(reactContext);
String pkg = reactContext.getApplicationContext().getPackageName();

View File

@@ -16,6 +16,7 @@
package org.jitsi.meet.sdk;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
@@ -37,6 +38,25 @@ public class JitsiMeetActivity extends FragmentActivity
protected static final String TAG = JitsiMeetActivity.class.getSimpleName();
public static final String ACTION_JITSI_MEET_CONFERENCE = "org.jitsi.meet.CONFERENCE";
public static final String JITSI_MEET_CONFERENCE_OPTIONS = "JitsiMeetConferenceOptions";
// Helpers for starting the activity
//
public static void launch(Context context, JitsiMeetConferenceOptions options) {
Intent intent = new Intent(context, JitsiMeetActivity.class);
intent.setAction(ACTION_JITSI_MEET_CONFERENCE);
intent.putExtra(JITSI_MEET_CONFERENCE_OPTIONS, options);
context.startActivity(intent);
}
public static void launch(Context context, String url) {
JitsiMeetConferenceOptions options
= new JitsiMeetConferenceOptions.Builder().setRoom(url).build();
launch(context, options);
}
// Overrides
//
@@ -80,19 +100,17 @@ public class JitsiMeetActivity extends FragmentActivity
}
private @Nullable JitsiMeetConferenceOptions getConferenceOptions(Intent intent) {
Uri uri;
String action = intent.getAction();
if (Intent.ACTION_VIEW.equals(intent.getAction())
&& (uri = intent.getData()) != null) {
JitsiMeetConferenceOptions options
= new JitsiMeetConferenceOptions.Builder()
.setRoom(uri.toString())
.build();
return options;
if (Intent.ACTION_VIEW.equals(action)) {
Uri uri = intent.getData();
if (uri != null) {
return new JitsiMeetConferenceOptions.Builder().setRoom(uri.toString()).build();
}
} else if (ACTION_JITSI_MEET_CONFERENCE.equals(action)) {
return intent.getParcelableExtra(JITSI_MEET_CONFERENCE_OPTIONS);
}
// TODO: accept JitsiMeetConferenceOptions directly.
return null;
}
@@ -151,6 +169,11 @@ public class JitsiMeetActivity extends FragmentActivity
JitsiMeetActivityDelegate.requestPermissions(this, permissions, requestCode, listener);
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
JitsiMeetActivityDelegate.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
// JitsiMeetViewListener
//

View File

@@ -17,6 +17,8 @@
package org.jitsi.meet.sdk;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import java.net.URL;
@@ -29,7 +31,7 @@ import java.net.URL;
* The resulting {@link JitsiMeetConferenceOptions} object is immutable and represents how the
* conference will be joined.
*/
public class JitsiMeetConferenceOptions {
public class JitsiMeetConferenceOptions implements Parcelable {
/**
* Server where the conference should take place.
*/
@@ -197,6 +199,20 @@ public class JitsiMeetConferenceOptions {
private JitsiMeetConferenceOptions() {
}
private JitsiMeetConferenceOptions(Parcel in) {
room = in.readString();
token = in.readString();
colorScheme = in.readBundle();
byte tmpAudioMuted = in.readByte();
audioMuted = tmpAudioMuted == 0 ? null : tmpAudioMuted == 1;
byte tmpAudioOnly = in.readByte();
audioOnly = tmpAudioOnly == 0 ? null : tmpAudioOnly == 1;
byte tmpVideoMuted = in.readByte();
videoMuted = tmpVideoMuted == 0 ? null : tmpVideoMuted == 1;
byte tmpWelcomePageEnabled = in.readByte();
welcomePageEnabled = tmpWelcomePageEnabled == 0 ? null : tmpWelcomePageEnabled == 1;
}
Bundle asProps() {
Bundle props = new Bundle();
@@ -246,4 +262,35 @@ public class JitsiMeetConferenceOptions {
return props;
}
// Parcelable interface
//
public static final Creator<JitsiMeetConferenceOptions> CREATOR = new Creator<JitsiMeetConferenceOptions>() {
@Override
public JitsiMeetConferenceOptions createFromParcel(Parcel in) {
return new JitsiMeetConferenceOptions(in);
}
@Override
public JitsiMeetConferenceOptions[] newArray(int size) {
return new JitsiMeetConferenceOptions[size];
}
};
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(room);
dest.writeString(token);
dest.writeBundle(colorScheme);
dest.writeByte((byte) (audioMuted == null ? 0 : audioMuted ? 1 : 2));
dest.writeByte((byte) (audioOnly == null ? 0 : audioOnly ? 1 : 2));
dest.writeByte((byte) (videoMuted == null ? 0 : videoMuted ? 1 : 2));
dest.writeByte((byte) (welcomePageEnabled == null ? 0 : welcomePageEnabled ? 1 : 2));
}
@Override
public int describeContents() {
return 0;
}
}

View File

@@ -81,15 +81,6 @@ public class JitsiMeetFragment extends Fragment {
JitsiMeetActivityDelegate.onHostDestroy(getActivity());
}
// https://developer.android.com/reference/android/support/v4/app/ActivityCompat.OnRequestPermissionsResultCallback
@Override
public void onRequestPermissionsResult(
final int requestCode,
final String[] permissions,
final int[] grantResults) {
JitsiMeetActivityDelegate.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@Override
public void onResume() {
super.onResume();

View File

@@ -48,20 +48,19 @@ class ReactInstanceManagerHolder {
ReactApplicationContext reactContext) {
List<NativeModule> nativeModules
= new ArrayList<>(Arrays.<NativeModule>asList(
new AmplitudeModule(reactContext),
new AndroidSettingsModule(reactContext),
new AppInfoModule(reactContext),
new AudioModeModule(reactContext),
new DropboxModule(reactContext),
new ExternalAPIModule(reactContext),
new LocaleDetector(reactContext),
new PictureInPictureModule(reactContext),
new ProximityModule(reactContext),
new WiFiStatsModule(reactContext),
new org.jitsi.meet.sdk.analytics.AmplitudeModule(reactContext),
new org.jitsi.meet.sdk.dropbox.Dropbox(reactContext),
new org.jitsi.meet.sdk.net.NAT64AddrInfoModule(reactContext)));
if (android.os.Build.VERSION.SDK_INT
>= android.os.Build.VERSION_CODES.O) {
if (AudioModeModule.useConnectionService()) {
nativeModules.add(new RNConnectionService(reactContext));
}

View File

@@ -84,8 +84,8 @@ PODS:
- nanopb/decode (0.3.901)
- nanopb/encode (0.3.901)
- ObjectiveDropboxOfficial (3.9.4)
- React (0.59.1):
- React/Core (= 0.59.1)
- React (0.59.2):
- React/Core (= 0.59.2)
- react-native-background-timer (2.1.1):
- React
- react-native-calendar-events (1.6.4):
@@ -99,50 +99,50 @@ PODS:
- React
- react-native-webrtc (1.69.0):
- React
- React/Core (0.59.1):
- yoga (= 0.59.1.React)
- React/CxxBridge (0.59.1):
- React/Core (0.59.2):
- yoga (= 0.59.2.React)
- React/CxxBridge (0.59.2):
- Folly (= 2018.10.22.00)
- React/Core
- React/cxxreact
- React/jsiexecutor
- React/cxxreact (0.59.1):
- React/cxxreact (0.59.2):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React/jsinspector
- React/DevSupport (0.59.1):
- React/DevSupport (0.59.2):
- React/Core
- React/RCTWebSocket
- React/fishhook (0.59.1)
- React/jsi (0.59.1):
- React/fishhook (0.59.2)
- React/jsi (0.59.2):
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React/jsiexecutor (0.59.1):
- React/jsiexecutor (0.59.2):
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React/cxxreact
- React/jsi
- React/jsinspector (0.59.1)
- React/RCTActionSheet (0.59.1):
- React/jsinspector (0.59.2)
- React/RCTActionSheet (0.59.2):
- React/Core
- React/RCTAnimation (0.59.1):
- React/RCTAnimation (0.59.2):
- React/Core
- React/RCTBlob (0.59.1):
- React/RCTBlob (0.59.2):
- React/Core
- React/RCTImage (0.59.1):
- React/RCTImage (0.59.2):
- React/Core
- React/RCTNetwork
- React/RCTLinkingIOS (0.59.1):
- React/RCTLinkingIOS (0.59.2):
- React/Core
- React/RCTNetwork (0.59.1):
- React/RCTNetwork (0.59.2):
- React/Core
- React/RCTText (0.59.1):
- React/RCTText (0.59.2):
- React/Core
- React/RCTWebSocket (0.59.1):
- React/RCTWebSocket (0.59.2):
- React/Core
- React/fishhook
- React/RCTBlob
@@ -160,7 +160,7 @@ PODS:
- SDWebImage/GIF (4.4.6):
- FLAnimatedImage (~> 1.0)
- SDWebImage/Core
- yoga (0.59.1.React)
- yoga (0.59.2.React)
DEPENDENCIES:
- Amplitude-iOS (~> 4.0.4)
@@ -268,7 +268,7 @@ SPEC CHECKSUMS:
GTMSessionFetcher: 32aeca0aa144acea523e1c8e053089dec2cb98ca
nanopb: 2901f78ea1b7b4015c860c2fdd1ea2fee1a18d48
ObjectiveDropboxOfficial: a5afefc83f6467c42c45f2253f583f2ad1ffc701
React: 34a405ead72252839fdc4afc1f972a7ed984af84
React: 9d063e2f356c8cd2f54dd550d4507740037cbabe
react-native-background-timer: 0d34748e53a972507c66963490c775321a88f6f2
react-native-calendar-events: ee9573e355711ac679e071be70789542431f4ce3
react-native-fast-image: 47487b71169aea34868e7b38bf870b6b3f2157c5
@@ -278,7 +278,7 @@ SPEC CHECKSUMS:
RNSound: 53d2fc9c6589bd68daba530262b7560393def3ac
RNVectorIcons: d819334932bcda3332deb3d2c8ea4d069e0b98f9
SDWebImage: 3f3f0c02f09798048c47a5ed0a13f17b063572d8
yoga: 8fb47f180b19b0dadb285a09e4c74c8a41721d3a
yoga: 3768a3026ade0fb46a68f3a31a917cf86bc34fc4
PODFILE CHECKSUM: 4a11c3d66127a9845d4a5b2c7fad49f58a9c7a89

View File

@@ -1,28 +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>API_KEY</key>
<string>correct_api_key</string>
<key>TRACKING_ID</key>
<string>correct_tracking_id</string>
<key>CLIENT_ID</key>
<string>correct_client_id</string>
<key>REVERSED_CLIENT_ID</key>
<string>com.google.correct-reversed-client-id</string>
<key>GOOGLE_APP_ID</key>
<string>1:123:ios:123abc</string>
<key>GCM_SENDER_ID</key>
<string>correct_gcm_sender_id</string>
<key>PLIST_VERSION</key>
<string>1</string>
<key>BUNDLE_ID</key>
<string>com.google.FirebaseSDKTests</string>
<key>PROJECT_ID</key>
<string>abc-xyz-123</string>
<key>DATABASE_URL</key>
<string>https://abc-xyz-123.firebaseio.com</string>
<key>STORAGE_BUCKET</key>
<string>project-id-123.storage.firebase.com</string>
</dict>
</plist>

View File

@@ -18,7 +18,6 @@
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
695AF3ED6F686F9C5EE40F9A /* libPods-jitsi-meet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 489E8EFE2C720D10F5961AEF /* libPods-jitsi-meet.a */; };
DE4C455E21DE1E4300EA0709 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = DE4C455D21DE1E4300EA0709 /* GoogleService-Info.plist */; };
DE4C456121DE1E4E00EA0709 /* FIRUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = DE4C455F21DE1E4E00EA0709 /* FIRUtilities.m */; };
/* End PBXBuildFile section */
@@ -55,7 +54,6 @@
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>"; };
489E8EFE2C720D10F5961AEF /* libPods-jitsi-meet.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-jitsi-meet.a"; sourceTree = BUILT_PRODUCTS_DIR; };
B3B083EB1D4955FF0069CEE7 /* app.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = app.entitlements; sourceTree = "<group>"; };
DE4C455D21DE1E4300EA0709 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = SOURCE_ROOT; };
DE4C455F21DE1E4E00EA0709 /* FIRUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FIRUtilities.m; sourceTree = "<group>"; };
DE4C456021DE1E4E00EA0709 /* FIRUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FIRUtilities.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
@@ -91,7 +89,6 @@
13B07FB01A68108700A75B9A /* AppDelegate.m */,
DE4C456021DE1E4E00EA0709 /* FIRUtilities.h */,
DE4C455F21DE1E4E00EA0709 /* FIRUtilities.m */,
DE4C455D21DE1E4300EA0709 /* GoogleService-Info.plist */,
13B07FB51A68108700A75B9A /* Images.xcassets */,
13B07FB61A68108700A75B9A /* Info.plist */,
13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
@@ -149,6 +146,7 @@
0B26BE701EC5BC3C00EEFB41 /* Embed Frameworks */,
B35383AD1DDA0083008F406A /* Adjust embedded framework architectures */,
0BB7DA181EC9E695007AAE98 /* Adjust ATS */,
DEF4813D224925A2002AD03A /* Copy Google Plist file */,
DEC2069321CBBD6900072F03 /* Setup Fabric */,
DE11877A21EE09640078D059 /* Setup Google reverse URL handler */,
DE4F6D6E22005C0400DE699E /* Setup Dropbox */,
@@ -209,7 +207,6 @@
buildActionMask = 2147483647;
files = (
0B412F211EDEE95300B1A0A6 /* Main.storyboard in Resources */,
DE4C455E21DE1E4300EA0709 /* GoogleService-Info.plist in Resources */,
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,
);
@@ -298,7 +295,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "INFO_PLIST=\"$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH\"\nREVERSED_CLIENT_ID=$(/usr/libexec/PlistBuddy -c \"Print :REVERSED_CLIENT_ID:\" $PROJECT_DIR/GoogleService-Info.plist)\n\n/usr/libexec/PlistBuddy -c \"Set :CFBundleURLTypes:1:CFBundleURLSchemes:0 $REVERSED_CLIENT_ID\" $INFO_PLIST\n";
shellScript = "INFO_PLIST=\"$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH\"\nGOOGLE_PLIST=\"$PROJECT_DIR/GoogleService-Info.plist\"\n\nif [[ -f $GOOGLE_PLIST ]]; then\n REVERSED_CLIENT_ID=$(/usr/libexec/PlistBuddy -c \"Print :REVERSED_CLIENT_ID:\" $GOOGLE_PLIST)\n /usr/libexec/PlistBuddy -c \"Set :CFBundleURLTypes:1:CFBundleURLSchemes:0 $REVERSED_CLIENT_ID\" $INFO_PLIST\nfi\n";
};
DE4F6D6E22005C0400DE699E /* Setup Dropbox */ = {
isa = PBXShellScriptBuildPhase;
@@ -336,6 +333,24 @@
shellPath = /bin/sh;
shellScript = "${PODS_ROOT}/Fabric/run\n";
};
DEF4813D224925A2002AD03A /* Copy Google Plist file */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
name = "Copy Google Plist file";
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "GOOGLE_PLIST_NAME=\"GoogleService-Info.plist\"\nGOOGLE_PLIST=\"$PROJECT_DIR/$GOOGLE_PLIST_NAME\"\nBUILD_APP_DIR=\"$BUILT_PRODUCTS_DIR/$PRODUCT_NAME.app\"\n\nif [[ -f $GOOGLE_PLIST ]]; then\n cp $GOOGLE_PLIST \"$BUILD_APP_DIR/$GOOGLE_PLIST_NAME\"\nfi\n";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */

View File

@@ -21,8 +21,6 @@ NSString *const kGoogleServiceInfoFileName = @"GoogleService-Info";
// Plist file type.
NSString *const kGoogleServiceInfoFileType = @"plist";
NSString *const kGoogleAppIDPlistKey = @"GOOGLE_APP_ID";
// Dummy plist GOOGLE_APP_ID
NSString *const kDummyGoogleAppID = @"1:123:ios:123abc";
@implementation FIRUtilities
@@ -59,9 +57,6 @@ NSString *const kDummyGoogleAppID = @"1:123:ios:123abc";
if (!googleAppID.length) {
return NO;
}
if ([googleAppID isEqualToString:kDummyGoogleAppID]) {
return NO;
}
return YES;
}

View File

@@ -1,8 +1,14 @@
ENV["FASTLANE_SKIP_UPDATE_CHECK"] = "1"
opt_out_usage
default_platform(:ios)
platform :ios do
desc "Push a new beta build to TestFlight"
lane :beta do
lane :deploy do
# Make sure we are on a clean tree
ensure_git_status_clean
# Set the app identifier
update_app_identifier(
xcodeproj: "app/app.xcodeproj",
@@ -24,5 +30,6 @@ platform :ios do
# Cleanup
clean_build_artifacts
reset_git_repo(skip_clean: true)
end
end

View File

@@ -16,9 +16,9 @@ or alternatively using `brew cask install fastlane`
# Available Actions
## iOS
### ios beta
### ios deploy
```
fastlane ios beta
fastlane ios deploy
```
Push a new beta build to TestFlight

View File

@@ -19,7 +19,7 @@ export default function SharedVideoThumb(participant, videoType, VideoLayout) {
this.bindHoverHandler();
SmallVideo.call(this, VideoLayout);
this.isVideoMuted = true;
this.setDisplayName(participant.name);
this.updateDisplayName();
this.container.onclick = this._onContainerClick;
this.container.ondblclick = this._onContainerDoubleClick;
@@ -65,9 +65,11 @@ SharedVideoThumb.prototype.createContainer = function(spanId) {
};
/**
* Sets the display name for the thumb.
* Triggers re-rendering of the display name using current instance state.
*
* @returns {void}
*/
SharedVideoThumb.prototype.setDisplayName = function(displayName) {
SharedVideoThumb.prototype.updateDisplayName = function() {
if (!this.container) {
logger.warn(`Unable to set displayName - ${this.videoSpanId
} does not exist`);
@@ -75,8 +77,7 @@ SharedVideoThumb.prototype.setDisplayName = function(displayName) {
return;
}
this.updateDisplayName({
displayName: displayName || '',
this._renderDisplayName({
elementID: `${this.videoSpanId}_name`,
participantID: this.id
});

View File

@@ -50,7 +50,7 @@ function LocalVideo(VideoLayout, emitter, streamEndedCallback) {
SmallVideo.call(this, VideoLayout);
// Set default display name.
this.setDisplayName();
this.updateDisplayName();
// Initialize the avatar display with an avatar url selected from the redux
// state. Redux stores the local user with a hardcoded participant id of
@@ -87,9 +87,11 @@ LocalVideo.prototype.createContainer = function() {
};
/**
* Sets the display name for the given video span id.
* Triggers re-rendering of the display name using current instance state.
*
* @returns {void}
*/
LocalVideo.prototype.setDisplayName = function(displayName) {
LocalVideo.prototype.updateDisplayName = function() {
if (!this.container) {
logger.warn(
`Unable to set displayName - ${this.videoSpanId
@@ -98,9 +100,8 @@ LocalVideo.prototype.setDisplayName = function(displayName) {
return;
}
this.updateDisplayName({
this._renderDisplayName({
allowEditing: APP.store.getState()['features/base/jwt'].isGuest,
displayName,
displayNameSuffix: interfaceConfig.DEFAULT_LOCAL_DISPLAY_NAME,
elementID: 'localDisplayName',
participantID: this.id

View File

@@ -53,7 +53,7 @@ function RemoteVideo(user, VideoLayout, emitter) {
? 'left bottom' : 'top center';
this.addRemoteVideoContainer();
this.updateIndicators();
this.setDisplayName();
this.updateDisplayName();
this.bindHoverHandler();
this.flipX = false;
this.isLocal = false;
@@ -519,11 +519,11 @@ RemoteVideo.prototype.addRemoteStreamElement = function(stream) {
};
/**
* Sets the display name for the given video span id.
* Triggers re-rendering of the display name using current instance state.
*
* @param displayName the display name to set
* @returns {void}
*/
RemoteVideo.prototype.setDisplayName = function(displayName) {
RemoteVideo.prototype.updateDisplayName = function() {
if (!this.container) {
logger.warn(`Unable to set displayName - ${this.videoSpanId
} does not exist`);
@@ -531,8 +531,7 @@ RemoteVideo.prototype.setDisplayName = function(displayName) {
return;
}
this.updateDisplayName({
displayName: displayName || interfaceConfig.DEFAULT_REMOTE_DISPLAY_NAME,
this._renderDisplayName({
elementID: `${this.videoSpanId}_name`,
participantID: this.id
});

View File

@@ -439,9 +439,11 @@ SmallVideo.prototype.$displayName = function() {
* Creates or updates the participant's display name that is shown over the
* video preview.
*
* @param {Object} props - The React {@code Component} props to pass into the
* {@code DisplayName} component.
* @returns {void}
*/
SmallVideo.prototype.updateDisplayName = function(props) {
SmallVideo.prototype._renderDisplayName = function(props) {
const displayNameContainer
= this.container.querySelector('.displayNameContainer');

View File

@@ -659,15 +659,15 @@ const VideoLayout = {
/**
* Display name changed.
*/
onDisplayNameChanged(id, displayName, status) {
onDisplayNameChanged(id) {
if (id === 'localVideoContainer'
|| APP.conference.isLocalId(id)) {
localVideoThumbnail.setDisplayName(displayName);
localVideoThumbnail.updateDisplayName();
} else {
const remoteVideo = remoteVideos[id];
if (remoteVideo) {
remoteVideo.setDisplayName(displayName, status);
remoteVideo.updateDisplayName();
}
}
},

165
package-lock.json generated
View File

@@ -2058,23 +2058,97 @@
}
},
"@babel/register": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/@babel/register/-/register-7.0.0.tgz",
"integrity": "sha512-f/+CRmaCe7rVEvcvPvxeA8j5aJhHC3aJie7YuqcMDhUOuyWLA7J/aNrTaHIzoWPEhpHA54mec4Mm8fv8KBlv3g==",
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/@babel/register/-/register-7.4.0.tgz",
"integrity": "sha512-ekziebXBnS/7V6xk8sBfLSSD6YZuy6P29igBtR6OL/tswKdxOV+Yqq0nzICMguVYtGRZYUCGpfGV8J9Za2iBdw==",
"requires": {
"core-js": "^2.5.7",
"find-cache-dir": "^1.0.0",
"home-or-tmp": "^3.0.0",
"lodash": "^4.17.10",
"core-js": "^3.0.0",
"find-cache-dir": "^2.0.0",
"lodash": "^4.17.11",
"mkdirp": "^0.5.1",
"pirates": "^4.0.0",
"source-map-support": "^0.5.9"
},
"dependencies": {
"core-js": {
"version": "2.6.5",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz",
"integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A=="
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.0.0.tgz",
"integrity": "sha512-WBmxlgH2122EzEJ6GH8o9L/FeoUKxxxZ6q6VUxoTlsE4EvbTWKJb447eyVxTEuq0LpXjlq/kCB2qgBvsYRkLvQ=="
},
"find-cache-dir": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
"integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
"requires": {
"commondir": "^1.0.1",
"make-dir": "^2.0.0",
"pkg-dir": "^3.0.0"
}
},
"find-up": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
"requires": {
"locate-path": "^3.0.0"
}
},
"locate-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
"integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
"requires": {
"p-locate": "^3.0.0",
"path-exists": "^3.0.0"
}
},
"make-dir": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
"integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
"requires": {
"pify": "^4.0.1",
"semver": "^5.6.0"
}
},
"p-limit": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz",
"integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==",
"requires": {
"p-try": "^2.0.0"
}
},
"p-locate": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
"integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
"requires": {
"p-limit": "^2.0.0"
}
},
"p-try": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.1.0.tgz",
"integrity": "sha512-H2RyIJ7+A3rjkwKC2l5GGtU4H1vkxKCAGsWasNVd0Set+6i4znxbWy6/j16YDPJDWxhsgZiKAstMEP8wCdSpjA=="
},
"pify": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g=="
},
"pkg-dir": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
"integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
"requires": {
"find-up": "^3.0.0"
}
},
"semver": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
"integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg=="
}
}
},
@@ -2201,9 +2275,9 @@
}
},
"@react-native-community/cli": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-1.4.2.tgz",
"integrity": "sha512-d+8ntrs8K/J+FaliQIpo0KO8v2/iDpZOcATvbxcCUWKuJGv8j0jUYrcx8d7rjNHy8Ie/BDXtjRA+bDi2wruUJg==",
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-1.5.1.tgz",
"integrity": "sha512-HFCYxI6WW3SoayrOSdhYxor5CaF/SBp7W73TyvTRRNAqQdA9/NX9wMZly+UpmFQkQFkiLvgc2yqS5vT918XXUw==",
"requires": {
"chalk": "^1.1.1",
"commander": "^2.19.0",
@@ -3413,9 +3487,9 @@
}
},
"big-integer": {
"version": "1.6.42",
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.42.tgz",
"integrity": "sha512-3UQFKcRMx+5Z+IK5vYTMYK2jzLRJkt+XqyDdacgWgtMjjuifKpKTFneJLEgeBElOE2/lXZ1LcMcb5s8pwG2U8Q=="
"version": "1.6.43",
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.43.tgz",
"integrity": "sha512-9dULc9jsKmXl0Aeunug8wbF+58n+hQoFjqClN7WeZwGLh0XJUWyJJ9Ee+Ep+Ql/J9fRsTVaeThp8MhiCCrY0Jg=="
},
"big.js": {
"version": "3.2.0",
@@ -4453,14 +4527,13 @@
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"cosmiconfig": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.1.0.tgz",
"integrity": "sha512-kCNPvthka8gvLtzAxQXvWo4FxqRB+ftRZyPZNuab5ngvM9Y7yw7hbEysglptLgpkGX9nAOKTBVkHUAe8xtYR6Q==",
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.0.tgz",
"integrity": "sha512-nxt+Nfc3JAqf4WIWd0jXLjTJZmsPLrA9DDc4nRw2KFJQJK7DNooqSXrNI7tzLG50CF8axczly5UV929tBmh/7g==",
"requires": {
"import-fresh": "^2.0.0",
"is-directory": "^0.3.1",
"js-yaml": "^3.9.0",
"lodash.get": "^4.4.2",
"js-yaml": "^3.13.0",
"parse-json": "^4.0.0"
},
"dependencies": {
@@ -4470,9 +4543,9 @@
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
},
"js-yaml": {
"version": "3.12.2",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.2.tgz",
"integrity": "sha512-QHn/Lh/7HhZ/Twc7vJYQTkjuCa0kaCcDcjK5Zlk2rvnUpy7DxMJ23+Jc2dcyvltwQVg1nygAVlB2oRDFHoRS5Q==",
"version": "3.13.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.0.tgz",
"integrity": "sha512-pZZoSxcCYco+DIKBTimr67J6Hy+EYGZDY/HCWC+iAEA9h1ByhMXAIVUXMcMFpOCxQ/xjXmPI2MkDL5HRm5eFrQ==",
"requires": {
"argparse": "^1.0.7",
"esprima": "^4.0.0"
@@ -5446,8 +5519,8 @@
}
},
"eslint-config-jitsi": {
"version": "github:jitsi/eslint-config-jitsi#7474f6668515eb5852f1273dc5a50b940a550d3f",
"from": "github:jitsi/eslint-config-jitsi#7474f6668515eb5852f1273dc5a50b940a550d3f",
"version": "github:jitsi/eslint-config-jitsi#1f3fbcea8baa1ab95929a351be3977e00cb162ec",
"from": "github:jitsi/eslint-config-jitsi#1.0.0",
"dev": true
},
"eslint-import-resolver-node": {
@@ -5995,13 +6068,13 @@
"integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ=="
},
"fbjs-scripts": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fbjs-scripts/-/fbjs-scripts-1.1.0.tgz",
"integrity": "sha512-VMCpHJd76YI2nYOfVM/d9LDAIFTH4uw4/7sAIGEgxk6kaNmirgTY9bLgpla9DTu+DvV2+ufvDxehGbl2U9bYCA==",
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/fbjs-scripts/-/fbjs-scripts-1.2.0.tgz",
"integrity": "sha512-5krZ8T0Bf8uky0abPoCLrfa7Orxd8UH4Qq8hRUF2RZYNMu+FmEOrBc7Ib3YVONmxTXTlLAvyrrdrVmksDb2OqQ==",
"requires": {
"@babel/core": "^7.0.0",
"ansi-colors": "^1.0.1",
"babel-preset-fbjs": "^3.0.0",
"babel-preset-fbjs": "^3.2.0",
"core-js": "^2.4.1",
"cross-spawn": "^5.1.0",
"fancy-log": "^1.3.2",
@@ -6092,6 +6165,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz",
"integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=",
"dev": true,
"requires": {
"commondir": "^1.0.1",
"make-dir": "^1.0.0",
@@ -7161,11 +7235,6 @@
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz",
"integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw=="
},
"home-or-tmp": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-3.0.0.tgz",
"integrity": "sha1-V6j+JM8zzdUkhgoVgh3cJchmcfs="
},
"hosted-git-info": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz",
@@ -8565,8 +8634,8 @@
}
},
"lib-jitsi-meet": {
"version": "github:jitsi/lib-jitsi-meet#282ef6b9fd69700f91c0b4a3fc3f1bd124e2bb67",
"from": "github:jitsi/lib-jitsi-meet#282ef6b9fd69700f91c0b4a3fc3f1bd124e2bb67",
"version": "github:jitsi/lib-jitsi-meet#83af6e78a82466153e93d4a467e1459c9c97d5ee",
"from": "github:jitsi/lib-jitsi-meet#83af6e78a82466153e93d4a467e1459c9c97d5ee",
"requires": {
"@jitsi/sdp-interop": "0.1.13",
"@jitsi/sdp-simulcast": "0.2.1",
@@ -8685,11 +8754,6 @@
"resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
"integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8="
},
"lodash.get": {
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
"integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk="
},
"lodash.isequal": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
@@ -8781,6 +8845,7 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.2.0.tgz",
"integrity": "sha512-aNUAa4UMg/UougV25bbrU4ZaaKNjJ/3/xnvg/twpmKROPdKZPZ9wGgI0opdZzO8q/zUFawoUuixuOv33eZ61Iw==",
"dev": true,
"requires": {
"pify": "^3.0.0"
},
@@ -8788,7 +8853,8 @@
"pify": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
"dev": true
}
}
},
@@ -10542,6 +10608,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
"integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
"dev": true,
"requires": {
"find-up": "^2.1.0"
}
@@ -11678,9 +11745,9 @@
}
},
"react-native": {
"version": "0.59.1",
"resolved": "https://registry.npmjs.org/react-native/-/react-native-0.59.1.tgz",
"integrity": "sha512-KA/MyoCQLGavPBc/Q2QRfdbxHuKHTcYTks9xwwRPzgDqTfmTuDcyoC6jUBTfhZ0LEes5GMoKVM4eVrYUbprOmw==",
"version": "0.59.2",
"resolved": "https://registry.npmjs.org/react-native/-/react-native-0.59.2.tgz",
"integrity": "sha512-gIygrCr42rGEQnfjcAZdCOqgjC0oZtTIp+mdbUW+yqHpNUU1PbYKzUkLlvSFGeN+IUcL8WTaC1JtJvghKhaLmA==",
"requires": {
"@babel/runtime": "^7.0.0",
"@react-native-community/cli": "^1.2.1",
@@ -11811,9 +11878,9 @@
"integrity": "sha512-By4lgWQG9eewS9WzhzxVHAewxX40v1CzLnNYXFMOqF06fYVCNykiiTMGlLzz3UXHVwwN1Drxw9uWroQfGRFMsw=="
},
"react-native-callstats": {
"version": "3.57.1",
"resolved": "https://registry.npmjs.org/react-native-callstats/-/react-native-callstats-3.57.1.tgz",
"integrity": "sha512-IrPYu/Q4AgC2lMDVgORHNM5OpgIxwqPmYw6Rhqbr1RXgMIN91Ve/NG6hjM6logk+gxbacxeyXpl3XCmtaM6RPg==",
"version": "3.58.2",
"resolved": "https://registry.npmjs.org/react-native-callstats/-/react-native-callstats-3.58.2.tgz",
"integrity": "sha512-XTZcQN0raFBRXB01Y78sH9rkskSXsEamFogq3hr85+DMSUCGmXmPWKsQ9cYp0bLa7HaKWaQLEB3jmQ3xOAwF4g==",
"requires": {
"base-64": "0.1.0",
"jssha": "^2.2.0"

View File

@@ -51,7 +51,7 @@
"js-utils": "github:jitsi/js-utils#73a67a7a60d52f8e895f50939c8fcbd1f20fe7b5",
"jsrsasign": "8.0.12",
"jwt-decode": "2.2.0",
"lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#282ef6b9fd69700f91c0b4a3fc3f1bd124e2bb67",
"lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#83af6e78a82466153e93d4a467e1459c9c97d5ee",
"libflacjs": "github:mmig/libflac.js#93d37e7f811f01cf7d8b6a603e38bd3c3810907d",
"lodash": "4.17.11",
"moment": "2.19.4",
@@ -62,10 +62,10 @@
"react-emoji-render": "0.4.6",
"react-i18next": "7.13.0",
"react-linkify": "0.2.2",
"react-native": "0.59.1",
"react-native": "0.59.2",
"react-native-background-timer": "2.1.1",
"react-native-calendar-events": "1.6.4",
"react-native-callstats": "3.57.1",
"react-native-callstats": "3.58.2",
"react-native-fast-image": "5.1.1",
"react-native-gifted-chat": "0.6.0",
"react-native-google-signin": "1.0.2",
@@ -99,7 +99,7 @@
"clean-css": "3.4.25",
"css-loader": "0.28.7",
"eslint": "5.6.1",
"eslint-config-jitsi": "github:jitsi/eslint-config-jitsi#7474f6668515eb5852f1273dc5a50b940a550d3f",
"eslint-config-jitsi": "github:jitsi/eslint-config-jitsi#1.0.0",
"eslint-plugin-flowtype": "2.50.3",
"eslint-plugin-import": "2.14.0",
"eslint-plugin-jsdoc": "3.8.0",

View File

@@ -1,11 +1,11 @@
// @flow
import React, { Component } from 'react';
import { connect } from 'react-redux';
import type { Dispatch } from 'redux';
import { ConfirmDialog } from '../../base/dialog';
import { translate } from '../../base/i18n';
import { connect } from '../../base/redux';
import { cancelWaitForOwner, _openLoginDialog } from '../actions';

View File

@@ -55,8 +55,6 @@ export default class BaseApp extends Component<*, State> {
this.state = {
route: {},
// $FlowFixMe
store: undefined
};
}

View File

@@ -43,6 +43,7 @@ import {
import {
_addLocalTracksToConference,
forEachConference,
getCurrentConference,
_handleParticipantError,
_removeLocalTracksFromConference
} from './functions';
@@ -620,13 +621,10 @@ function _setRoom({ dispatch, getState }, next, action) {
* @returns {Promise}
*/
function _syncConferenceLocalTracksWithState({ getState }, action) {
const state = getState()['features/base/conference'];
const { conference } = state;
const conference = getCurrentConference(getState);
let promise;
// XXX The conference may already be in the process of being left, that's
// why we should not add/remove local tracks to such conference.
if (conference && conference !== state.leaving) {
if (conference) {
const track = action.track.jitsiTrack;
if (action.type === TRACK_ADDED) {

View File

@@ -2,10 +2,10 @@
import React, { Component, type Node } from 'react';
import { TouchableWithoutFeedback, View } from 'react-native';
import { connect } from 'react-redux';
import { ColorSchemeRegistry } from '../../../color-scheme';
import { Modal } from '../../../react';
import { connect } from '../../../redux';
import { StyleType } from '../../../styles';
import { bottomSheetStyles as styles } from './styles';
@@ -107,5 +107,4 @@ function _mapStateToProps(state) {
};
}
// $FlowExpectedError
export default connect(_mapStateToProps)(BottomSheet);

View File

@@ -2,9 +2,9 @@
import React from 'react';
import { Text, TouchableOpacity } from 'react-native';
import { connect } from 'react-redux';
import { translate } from '../../../i18n';
import { connect } from '../../../redux';
import { StyleType } from '../../../styles';
import { _abstractMapStateToProps } from '../../functions';

View File

@@ -1,6 +1,6 @@
// @flow
import { connect } from 'react-redux';
import { connect } from '../../../redux';
import { _abstractMapStateToProps } from '../../functions';
@@ -21,5 +21,4 @@ class CustomDialog extends BaseDialog<Props, *> {
}
}
// $FlowExpectedError
export default connect(_abstractMapStateToProps)(CustomDialog);

View File

@@ -1,8 +1,7 @@
// @flow
import { connect } from 'react-redux';
import { translate } from '../../../i18n';
import { connect } from '../../../redux';
import { _abstractMapStateToProps } from '../../functions';

View File

@@ -1,4 +1,4 @@
import { connect } from 'react-redux';
import { connect } from '../../../redux';
import AbstractDialogContainer, {
abstractMapStateToProps

View File

@@ -2,9 +2,9 @@
import React from 'react';
import { View, Text, TextInput, TouchableOpacity } from 'react-native';
import { connect } from 'react-redux';
import { translate } from '../../../i18n';
import { connect } from '../../../redux';
import { StyleType } from '../../../styles';
import { _abstractMapStateToProps } from '../../functions';

View File

@@ -1,7 +1,8 @@
// @flow
import React from 'react';
import { connect } from 'react-redux';
import { connect } from '../../../redux';
import AbstractDialog from '../AbstractDialog';
import type { Props as AbstractDialogProps, State } from '../AbstractDialog';
@@ -84,5 +85,4 @@ class Dialog extends AbstractDialog<Props, State> {
_onSubmit: (?string) => void;
}
// $FlowExpectedError
export default connect()(Dialog);

View File

@@ -1,6 +1,7 @@
import { ModalTransition } from '@atlaskit/modal-dialog';
import React from 'react';
import { connect } from 'react-redux';
import { connect } from '../../../redux';
import AbstractDialogContainer, {
abstractMapStateToProps

View File

@@ -63,13 +63,10 @@ export function getLocalizedDurationFormatter(duration: number) {
// showing the hour and we want to include the hour if the conference is
// more than an hour long
// $FlowFixMe
if (moment.duration(duration).format('h') !== '0') {
// $FlowFixMe
return moment.duration(duration).format('h:mm:ss');
}
// $FlowFixMe
return moment.duration(duration).format('mm:ss', { trim: false });
}
@@ -97,8 +94,6 @@ function _getSupportedLocale() {
// FIXME The flow-type definition of moment is v2.3 while our
// package.json states v2.19 so maybe locales on moment was
// introduced in between?
//
// $FlowFixMe
= moment.locales().find(lang => currentLocaleRegexp.exec(lang));
}
}

View File

@@ -7,7 +7,7 @@ import { Component } from 'react';
* playback.
*/
export type AudioElement = {
currentTime?: number,
currentTime: number,
pause: () => void,
play: () => void,
setSinkId?: string => void,

View File

@@ -2,7 +2,8 @@
import React from 'react';
import { View } from 'react-native';
import { connect } from 'react-redux';
import { connect } from '../../../redux';
import AbstractVideoTrack from '../AbstractVideoTrack';
import type { Props } from '../AbstractVideoTrack';
@@ -29,5 +30,4 @@ class VideoTrack extends AbstractVideoTrack<Props> {
}
}
// $FlowExpectedError
export default connect()(VideoTrack);

View File

@@ -2,9 +2,10 @@
import React, { Component } from 'react';
import { PanResponder, PixelRatio, View } from 'react-native';
import { connect } from 'react-redux';
import { type Dispatch } from 'redux';
import { connect } from '../../../redux';
import type { PanResponderInstance } from 'PanResponder';
import { storeVideoTransform } from '../../actions';
@@ -727,5 +728,4 @@ function _mapStateToProps(state) {
};
}
// $FlowExpectedError
export default connect(_mapStateToProps, _mapDispatchToProps)(VideoTransform);

View File

@@ -1,7 +1,8 @@
/* @flow */
import React from 'react';
import { connect } from 'react-redux';
import { connect } from '../../../redux';
import AbstractVideoTrack from '../AbstractVideoTrack';
import type { Props as AbstractVideoTrackProps } from '../AbstractVideoTrack';
@@ -63,5 +64,4 @@ class VideoTrack extends AbstractVideoTrack<Props> {
_onVideoPlaying: () => void;
}
// $FlowExpectedError
export default connect()(VideoTrack);

View File

@@ -2,7 +2,10 @@
import React, { Component, Fragment, PureComponent } from 'react';
import { Dimensions, Image, Platform, View } from 'react-native';
import FastImage from 'react-native-fast-image';
import FastImage, {
type CacheControls,
type Priorities
} from 'react-native-fast-image';
import { ColorPalette } from '../../styles';
@@ -63,7 +66,12 @@ type State = {
/**
* Source for the non-local avatar.
*/
source: { uri: ?string }
source: {
uri?: string,
headers?: Object,
priority?: Priorities,
cache?: CacheControls,
}
};
/**
@@ -261,7 +269,7 @@ class AvatarContent extends Component<Props, State> {
}
}
return (// $FlowFixMe
return (
<FastImage
onError = { this._onAvatarLoadError }
onLoadEnd = { this._onAvatarLoaded }

View File

@@ -3,7 +3,6 @@
import React, { Component } from 'react';
import { Text, View } from 'react-native';
import FastImage from 'react-native-fast-image';
import { connect } from 'react-redux';
import { translate } from '../../i18n';
import { JitsiParticipantConnectionStatus } from '../../lib-jitsi-meet';
@@ -12,6 +11,7 @@ import {
VideoTrack
} from '../../media';
import { Container, TintedView } from '../../react';
import { connect } from '../../redux';
import { StyleType } from '../../styles';
import { TestHint } from '../../testing/components';
import { getTrackByMediaTypeAndParticipant } from '../../tracks';

View File

@@ -2,10 +2,10 @@
import React, { Component } from 'react';
import { TouchableOpacity } from 'react-native';
import { connect } from 'react-redux';
import { ColorSchemeRegistry } from '../../../color-scheme';
import { Icon } from '../../../font-icons';
import { connect } from '../../../redux';
/**
* The type of the React {@code Component} props of {@link BackButton}
@@ -68,5 +68,4 @@ function _mapStateToProps(state) {
};
}
// $FlowExpectedError
export default connect(_mapStateToProps)(BackButton);

View File

@@ -2,10 +2,10 @@
import React, { Component } from 'react';
import { Text, TouchableOpacity } from 'react-native';
import { connect } from 'react-redux';
import { ColorSchemeRegistry } from '../../../color-scheme';
import { translate } from '../../../i18n';
import { connect } from '../../../redux';
/**
* The type of the React {@code Component} props of {@link ForwardButton}

View File

@@ -2,9 +2,9 @@
import React, { Component, type Node } from 'react';
import { Platform, SafeAreaView, StatusBar, View } from 'react-native';
import { connect } from 'react-redux';
import { ColorSchemeRegistry } from '../../../color-scheme';
import { connect } from '../../../redux';
import { isDarkColor } from '../../../styles';
import { HEADER_PADDING } from './headerstyles';
@@ -165,5 +165,4 @@ function _mapStateToProps(state) {
};
}
// $FlowExpectedError
export default connect(_mapStateToProps)(Header);

View File

@@ -2,10 +2,10 @@
import React, { Component } from 'react';
import { Text, View } from 'react-native';
import { connect } from 'react-redux';
import { ColorSchemeRegistry } from '../../../color-scheme';
import { translate } from '../../../i18n';
import { connect } from '../../../redux';
/**
* The type of the React {@code Component} props of {@link HeaderLabel}

View File

@@ -11,7 +11,7 @@ type Props = {
* Prop to set the size of the indicator. This is the same as the
* prop of the native component.
*/
size: 'large' | 'medium' | 'small'
size: 'large' | 'small'
};
/**
@@ -40,7 +40,7 @@ export default class LoadingIndicator extends Component<Props> {
size
};
return (// $FlowFixMe
return (
<ActivityIndicator
animating = { true }
color = { ColorPalette.white }

View File

@@ -2,9 +2,9 @@
import React, { Component } from 'react';
import { SafeAreaView, Text, TouchableOpacity, View } from 'react-native';
import { connect } from 'react-redux';
import { Icon } from '../../../font-icons';
import { connect } from '../../../redux';
import styles from './styles';
@@ -283,5 +283,4 @@ class PagedList extends Component<Props, State> {
}
}
// $FlowExpectedError
export default connect()(PagedList);

View File

@@ -1,178 +0,0 @@
// @flow
import React, { PureComponent, type Node } from 'react';
import { Animated, TouchableWithoutFeedback, View } from 'react-native';
import styles, { SIDEBAR_WIDTH } from './styles';
/**
* The type of the React {@code Component} props of {@link SideBar}.
*/
type Props = {
/**
* The children of {@code SideBar}.
*/
children: Node,
/**
* Callback to notify the containing {@code Component} that the sidebar is
* closing.
*/
onHide: Function,
/**
* Whether the menu (of the {@code SideBar}?) is displayed/rendered/shown.
*/
show: boolean
};
/**
* The type of the React {@code Component} state of {@link SideBar}.
*/
type State = {
/**
* Whether the side overlay should be displayed/rendered/shown.
*/
showOverlay: boolean,
/**
* The native animation object.
*/
sliderAnimation: Animated.Value
};
/**
* A generic animated side bar to be used for left-side, hamburger-style menus.
*/
export default class SideBar extends PureComponent<Props, State> {
/**
* Implements React's {@link Component#getDerivedStateFromProps()}.
*
* @inheritdoc
*/
static getDerivedStateFromProps(props: Props, prevState: State) {
return {
showOverlay: props.show || prevState.showOverlay
};
}
/**
* Initializes a new {@code SideBar} instance.
*
* @inheritdoc
*/
constructor(props: Props) {
super(props);
this.state = {
showOverlay: false,
sliderAnimation: new Animated.Value(0)
};
// Bind event handlers so they are only bound once per instance.
this._onHideMenu = this._onHideMenu.bind(this);
}
/**
* Implements React's {@link Component#componentDidMount()}.
*
* @inheritdoc
*/
componentDidMount() {
this._setShow(this.props.show);
}
/**
* Implements React's {@link Component#componentDidUpdate()}.
*
* @inheritdoc
*/
componentDidUpdate() {
this._setShow(this.props.show);
}
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
*/
render() {
return (
<View
pointerEvents = 'box-none'
style = { styles.sideMenuContainer } >
{
this.state.showOverlay
&& <TouchableWithoutFeedback
onPress = { this._onHideMenu } >
<View style = { styles.sideMenuShadow } />
</TouchableWithoutFeedback>
}
<Animated.View style = { this._getContentStyle() }>
{ this.props.children }
</Animated.View>
</View>
);
}
_getContentStyle: () => Array<Object>;
/**
* Assembles a style array for the sidebar content.
*
* @private
* @returns {Array<Object>}
*/
_getContentStyle() {
return [
styles.sideMenuContent,
{ transform: [ { translateX: this.state.sliderAnimation } ] }
];
}
_onHideMenu: () => void;
/**
* Hides the side menu.
*
* @private
* @returns {void}
*/
_onHideMenu() {
this._setShow(false);
const { onHide } = this.props;
onHide && onHide();
}
_setShow: (boolean) => void;
/**
* Shows/hides the side menu.
*
* @param {boolean} show - If the side menu is to be made visible,
* {@code true}; otherwise, {@code false}.
* @private
* @returns {void}
*/
_setShow(show) {
Animated
.timing(
/* value */ this.state.sliderAnimation,
/* config */ {
toValue: show ? SIDEBAR_WIDTH : 0,
useNativeDriver: true
})
.start(({ finished }) => {
finished && !show && this.setState({ showOverlay: false });
// XXX Technically, the arrow function can further be simplified
// by removing the {} and returning the boolean expression
// above. Practically and unfortunately though, Flow freaks out
// and states that Animated.timing doesn't exist!?
});
}
}

View File

@@ -0,0 +1,265 @@
// @flow
import React, { PureComponent, type Node } from 'react';
import {
Animated,
Dimensions,
TouchableWithoutFeedback,
View
} from 'react-native';
import { type StyleType } from '../../../styles';
import styles from './slidingviewstyles';
/**
* The type of the React {@code Component} props of {@link SlidingView}.
*/
type Props = {
/**
* The children of {@code SlidingView}.
*/
children: Node,
/**
* Callback to notify the containing {@code Component} that the view is
* closing.
*/
onHide: Function,
/**
* Position of the SlidingView: 'left', 'right', 'top', 'bottom'.
* later).
*/
position: string,
/**
* Whether the {@code SlidingView} is to be displayed/rendered/shown or not.
*/
show: boolean,
/**
* Style of the animated view.
*/
style: StyleType
};
/**
* The type of the React {@code Component} state of {@link SlidingView}.
*/
type State = {
/**
* Whether the sliding overlay should be displayed/rendered/shown.
*/
showOverlay: boolean,
/**
* The native animation object.
*/
sliderAnimation: Animated.Value,
/**
* Offset to move the view out of the screen.
*/
positionOffset: number
};
/**
* A generic animated slider view to be used for animated menus.
*/
export default class SlidingView extends PureComponent<Props, State> {
/**
* True if the component is mounted.
*/
_mounted: boolean;
/**
* Implements React's {@link Component#getDerivedStateFromProps()}.
*
* @inheritdoc
*/
static getDerivedStateFromProps(props: Props, prevState: State) {
return {
showOverlay: props.show || prevState.showOverlay
};
}
/**
* Initializes a new {@code SlidingView} instance.
*
* @inheritdoc
*/
constructor(props: Props) {
super(props);
const { height, width } = Dimensions.get('window');
const { position } = props;
let positionOffset = height;
if (position === 'left' || position === 'right') {
positionOffset = width;
}
this.state = {
showOverlay: false,
sliderAnimation: new Animated.Value(0),
positionOffset
};
// Bind event handlers so they are only bound once per instance.
this._onHideMenu = this._onHideMenu.bind(this);
}
/**
* Implements React's {@link Component#componentDidMount()}.
*
* @inheritdoc
*/
componentDidMount() {
this._mounted = true;
this._setShow(this.props.show);
}
/**
* Implements React's {@link Component#componentDidUpdate()}.
*
* @inheritdoc
*/
componentDidUpdate() {
this._setShow(this.props.show);
}
/**
* Implements React's {@link Component#componentWillUnmount()}.
*
* @inheritdoc
*/
componentWillUnmount() {
this._mounted = false;
}
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
*/
render() {
const { showOverlay } = this.state;
if (!showOverlay) {
return null;
}
return (
<View
pointerEvents = 'box-none'
style = { styles.sliderViewContainer } >
<TouchableWithoutFeedback
onPress = { this._onHideMenu } >
<View style = { styles.sliderViewShadow } />
</TouchableWithoutFeedback>
<Animated.View
style = { this._getContentStyle() }>
{ this.props.children }
</Animated.View>
</View>
);
}
_getContentStyle: () => Array<Object>;
/**
* Assembles a style array for the SlideView content.
*
* @private
* @returns {Array<Object>}
*/
_getContentStyle() {
const style = {
...this.props.style,
...styles.sliderViewContent
};
const { positionOffset } = this.state;
switch (this.props.position) {
case 'bottom':
Object.assign(style, {
bottom: -positionOffset,
left: 0,
right: 0,
top: positionOffset
}, {
transform: [ { translateY: this.state.sliderAnimation } ]
});
break;
case 'left':
Object.assign(style, {
bottom: 0,
left: -positionOffset,
right: positionOffset,
top: 0
}, {
transform: [ { translateX: this.state.sliderAnimation } ]
});
break;
}
return style;
}
_onHideMenu: () => void;
/**
* Hides the slider.
*
* @private
* @returns {void}
*/
_onHideMenu() {
this._setShow(false);
const { onHide } = this.props;
onHide && onHide();
}
_setShow: (boolean) => void;
/**
* Shows/hides the slider menu.
*
* @param {boolean} show - If the slider view is to be made visible,
* {@code true}; otherwise, {@code false}.
* @private
* @returns {void}
*/
_setShow(show) {
if (!this._mounted) {
return;
}
const { positionOffset } = this.state;
const { position } = this.props;
let toValue = positionOffset;
if (position === 'bottom' || position === 'right') {
toValue = -positionOffset;
}
Animated
.timing(
/* value */ this.state.sliderAnimation,
/* config */ {
duration: 200,
toValue: show ? toValue : 0,
useNativeDriver: true
})
.start(({ finished }) => {
finished && this._mounted && !show
&& this.setState({ showOverlay: false });
});
}
}

View File

@@ -20,7 +20,7 @@ export { default as NavigateSectionListSectionHeader }
export { default as PagedList } from './PagedList';
export { default as Pressable } from './Pressable';
export { default as SectionList } from './SectionList';
export { default as SideBar } from './SideBar';
export { default as SlidingView } from './SlidingView';
export { default as Switch } from './Switch';
export { default as Text } from './Text';
export { default as TintedView } from './TintedView';

View File

@@ -0,0 +1,31 @@
// @flow
import { StyleSheet } from 'react-native';
import { OVERLAY_Z_INDEX } from '../../constants';
export default {
/**
* The topmost container of the side bar.
*/
sliderViewContainer: {
...StyleSheet.absoluteFillObject,
zIndex: OVERLAY_Z_INDEX
},
/**
* The container of the actual content of the side menu.
*/
sliderViewContent: {
position: 'absolute'
},
/**
* The opaque area that covers the rest of the screen, when the side bar is
* open.
*/
sliderViewShadow: {
...StyleSheet.absoluteFillObject,
backgroundColor: 'rgba(0, 0, 0, 0.5)'
}
};

View File

@@ -1,7 +1,5 @@
// @flow
import { StyleSheet } from 'react-native';
import { BoxModel, ColorPalette, createStyleSheet } from '../../../styles';
const AVATAR_OPACITY = 0.4;
@@ -9,7 +7,6 @@ const OVERLAY_FONT_COLOR = 'rgba(255, 255, 255, 0.6)';
const SECONDARY_ACTION_BUTTON_SIZE = 30;
export const AVATAR_SIZE = 65;
export const SIDEBAR_WIDTH = 250;
export const UNDERLAY_COLOR = 'rgba(255, 255, 255, 0.2)';
/**
@@ -241,35 +238,6 @@ const SECTION_LIST_STYLES = {
}
};
const SIDEBAR_STYLES = {
/**
* The topmost container of the side bar.
*/
sideMenuContainer: {
...StyleSheet.absoluteFillObject
},
/**
* The container of the actual content of the side menu.
*/
sideMenuContent: {
bottom: 0,
left: -SIDEBAR_WIDTH,
position: 'absolute',
top: 0,
width: SIDEBAR_WIDTH
},
/**
* The opaque area that covers the rest of the screen, when the side bar is
* open.
*/
sideMenuShadow: {
...StyleSheet.absoluteFillObject,
backgroundColor: 'rgba(0, 0, 0, 0.5)'
}
};
export const TINTED_VIEW_DEFAULT = {
backgroundColor: ColorPalette.appBackground,
opacity: 0.8
@@ -281,6 +249,5 @@ export const TINTED_VIEW_DEFAULT = {
*/
export default createStyleSheet({
...PAGED_LIST_STYLES,
...SECTION_LIST_STYLES,
...SIDEBAR_STYLES
...SECTION_LIST_STYLES
});

View File

@@ -1,9 +1,9 @@
/* @flow */
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { translate } from '../../../i18n';
import { connect } from '../../../redux';
declare var interfaceConfig: Object;
@@ -242,5 +242,4 @@ function _mapStateToProps(state) {
};
}
// $FlowExpectedError
export default connect(_mapStateToProps)(translate(Watermarks));

View File

@@ -0,0 +1,7 @@
// @flow
/**
* Z-index for components that are to be rendered like an overlay, to be over
* everything, such as modal-type of components, or dialogs.
*/
export const OVERLAY_Z_INDEX = 1000;

View File

@@ -1,6 +1,7 @@
// @flow
import _ from 'lodash';
import { connect as reduxConnect } from 'react-redux';
/**
* Sets specific properties of a specific state to specific values and prevents
@@ -25,6 +26,19 @@ export function assign(target: Object, source: Object) {
return t;
}
/**
* Wrapper function for the react-redux connect function to avoid having to
* declare function types for flow, but still let flow warn for other errors.
*
* @param {Function?} mapStateToProps - Redux mapStateToProps function.
* @param {Function?} mapDispatchToProps - Redux mapDispatchToProps function.
* @returns {Connector}
*/
export function connect(
mapStateToProps?: Function, mapDispatchToProps?: Function) {
return reduxConnect<*, *, *, *, *, *>(mapStateToProps, mapDispatchToProps);
}
/**
* Determines whether {@code a} equals {@code b} according to deep comparison
* (which makes sense for Redux and its state definition).

View File

@@ -1,7 +1,8 @@
// @flow
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { connect } from '../../redux';
import { ASPECT_RATIO_NARROW, ASPECT_RATIO_WIDE } from '../constants';
@@ -51,7 +52,6 @@ export function makeAspectRatioAware(
}
}
// $FlowFixMe
return connect(_mapStateToProps)(AspectRatioAware);
}

View File

@@ -1,9 +1,10 @@
// @flow
import React, { Component, type Node } from 'react';
import { connect } from 'react-redux';
import { type Dispatch } from 'redux';
import { connect } from '../../redux';
import { setAspectRatio } from '../actions';
import DimensionsDetector from './DimensionsDetector';
@@ -69,5 +70,4 @@ function _mapDispatchToProps(dispatch: Dispatch<any>) {
};
}
// $FlowExpectedError
export default connect(undefined, _mapDispatchToProps)(AspectRatioDetector);

View File

@@ -1,9 +1,10 @@
// @flow
import React, { Component, type Node } from 'react';
import { connect } from 'react-redux';
import { type Dispatch } from 'redux';
import { connect } from '../../redux';
import { setReducedUI } from '../actions';
import DimensionsDetector from './DimensionsDetector';
@@ -70,5 +71,4 @@ function _mapDispatchToProps(dispatch: Dispatch<any>) {
};
}
// $FlowExpectedError
export default connect(undefined, _mapDispatchToProps)(ReducedUIDetector);

View File

@@ -1,10 +1,10 @@
// @flow
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Audio } from '../../media';
import type { AudioElement } from '../../media';
import { connect } from '../../redux';
import { _addAudioElement, _removeAudioElement } from '../actions';
import type { Sound } from '../reducer';
@@ -153,5 +153,4 @@ export function _mapDispatchToProps(dispatch: Function) {
};
}
// $FlowExpectedError
export default connect(_mapStateToProps, _mapDispatchToProps)(SoundCollection);

View File

@@ -1,9 +1,9 @@
// @flow
import React, { Component, Fragment } from 'react';
import { connect } from 'react-redux';
import { getLocalParticipant } from '../../participants';
import { connect } from '../../redux';
// FIXME this imports feature to 'base'
import { statsEmitter } from '../../../connection-indicator';
@@ -215,5 +215,4 @@ function _mapStateToProps(state) {
};
}
// $FlowExpectedError
export default connect(_mapStateToProps)(TestConnectionInfo);

View File

@@ -1,9 +1,10 @@
/* @flow */
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Text } from 'react-native';
import { connect } from '../../redux';
import type { TestHintProps } from './AbstractTestHint';
import { _mapStateToProps } from './AbstractTestHint';

View File

@@ -1,9 +1,10 @@
/* @flow */
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Text } from 'react-native';
import { connect } from '../../redux';
import type { TestHintProps } from './AbstractTestHint';
import { _mapStateToProps } from './AbstractTestHint';
@@ -34,5 +35,4 @@ class TestHint extends Component<TestHintProps> {
}
}
// $FlowExpectedError
export default connect(_mapStateToProps)(TestHint);

View File

@@ -2,7 +2,6 @@
import Tooltip from '@atlaskit/tooltip';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import type { Dispatch } from 'redux';
import {
@@ -10,6 +9,7 @@ import {
sendAnalytics
} from '../../analytics';
import { translate } from '../../base/i18n';
import { connect } from '../../base/redux';
import { updateCalendarEvent } from '../actions';

View File

@@ -2,11 +2,11 @@
import React from 'react';
import { Text, TouchableOpacity, View } from 'react-native';
import { connect } from 'react-redux';
import { openSettings } from '../../mobile/permissions';
import { translate } from '../../base/i18n';
import { AbstractPage } from '../../base/react';
import { connect } from '../../base/redux';
import { refreshCalendar } from '../actions';
import { isCalendarEnabled } from '../functions';

View File

@@ -2,10 +2,10 @@
import Spinner from '@atlaskit/spinner';
import React from 'react';
import { connect } from 'react-redux';
import { translate } from '../../base/i18n';
import { AbstractPage } from '../../base/react';
import { connect } from '../../base/redux';
import { openSettingsDialog, SETTINGS_TABS } from '../../settings';
import {
createCalendarClickedEvent,

View File

@@ -1,7 +1,6 @@
// @flow
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { appNavigate } from '../../app';
import {
@@ -11,6 +10,7 @@ import {
} from '../../analytics';
import { getLocalizedDateFormatter, translate } from '../../base/i18n';
import { NavigateSectionList } from '../../base/react';
import { connect } from '../../base/redux';
import { refreshCalendar, openUpdateCalendarEventDialog } from '../actions';
import { isCalendarEnabled } from '../functions';

View File

@@ -1,7 +1,6 @@
// @flow
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { appNavigate } from '../../app';
import {
@@ -10,6 +9,7 @@ import {
sendAnalytics
} from '../../analytics';
import { MeetingsList } from '../../base/react';
import { connect } from '../../base/redux';
import { isCalendarEnabled } from '../functions';
@@ -173,7 +173,5 @@ function _mapStateToProps(state: Object) {
}
export default isCalendarEnabled()
// $FlowExpectedError
? connect(_mapStateToProps)(CalendarListContent)
: undefined;

View File

@@ -2,12 +2,12 @@
import React, { Component } from 'react';
import { Text, TouchableOpacity, View } from 'react-native';
import { connect } from 'react-redux';
import { appNavigate } from '../../app';
import { getURLWithoutParamsNormalized } from '../../base/connection';
import { Icon } from '../../base/font-icons';
import { getLocalizedDateFormatter, translate } from '../../base/i18n';
import { connect } from '../../base/redux';
import { ASPECT_RATIO_NARROW } from '../../base/responsive-ui';
import { isCalendarEnabled } from '../functions';

View File

@@ -1,10 +1,10 @@
// @flow
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { ConfirmDialog } from '../../base/dialog';
import { translate } from '../../base/i18n';
import { connect } from '../../base/redux';
import { updateCalendarEvent } from '../actions';

View File

@@ -107,15 +107,16 @@ export function _updateCalendarEntries(events: Array<Object>) {
*/
function _checkPattern(str, positivePattern, negativePattern) {
const positiveRegExp = new RegExp(positivePattern, 'gi');
let positiveMatch;
let positiveMatch = positiveRegExp.exec(str);
while ((positiveMatch = positiveRegExp.exec(str)) !== null) {
// $FlowFixMe
while (positiveMatch !== null) {
const url = positiveMatch[0];
if (!new RegExp(negativePattern, 'gi').exec(url)) {
return url;
}
positiveMatch = positiveRegExp.exec(str);
}
}

View File

@@ -63,7 +63,6 @@ isCalendarEnabled()
// knownDomains. At this point, it should have already been
// translated into the new state format (namely, base/known-domains)
// and the app no longer needs it.
// $FlowFixMe
if (typeof state.knownDomains !== 'undefined') {
return set(state, 'knownDomains', undefined);
}

View File

@@ -1,31 +1,28 @@
// @flow
import React from 'react';
import { SafeAreaView } from 'react-native';
import { SafeAreaView, View } from 'react-native';
import { GiftedChat } from 'react-native-gifted-chat';
import { connect } from 'react-redux';
import { translate } from '../../../base/i18n';
import { BackButton, Header, HeaderLabel, Modal } from '../../../base/react';
import {
BackButton,
Header,
HeaderLabel,
SlidingView
} from '../../../base/react';
import { connect } from '../../../base/redux';
import AbstractChat, {
_mapDispatchToProps,
_mapStateToProps as _abstractMapStateToProps,
type Props as AbstractProps
_mapStateToProps,
type Props
} from '../AbstractChat';
import ChatMessage from './ChatMessage';
import styles from './styles';
type Props = AbstractProps & {
/**
* True if the chat window should have a solid BG render.
*/
_solidBackground: boolean
}
/**
* Implements a React native component that renders the chat window (modal) of
* the mobile client.
@@ -55,32 +52,24 @@ class Chat extends AbstractChat<Props> {
// of messages.
const messages
= this.props._messages.map(this._transformMessage).reverse();
const modalStyle = [
styles.modalBackdrop
];
if (this.props._solidBackground) {
// We only use a transparent background, when we are in a video
// meeting to give a user a glympse of what's happening. Otherwise
// we use a non-transparent background.
modalStyle.push(styles.solidModalBackdrop);
}
return (
<Modal
onRequestClose = { this.props._onToggleChat }
visible = { this.props._isOpen }>
<Header>
<BackButton onPress = { this.props._onToggleChat } />
<HeaderLabel labelKey = 'chat.title' />
</Header>
<SafeAreaView style = { modalStyle }>
<GiftedChat
messages = { messages }
onSend = { this._onSend }
renderMessage = { this._renderMessage } />
</SafeAreaView>
</Modal>
<SlidingView
position = 'bottom'
show = { this.props._isOpen } >
<View style = { styles.chatContainer }>
<Header>
<BackButton onPress = { this.props._onToggleChat } />
<HeaderLabel labelKey = 'chat.title' />
</Header>
<SafeAreaView style = { styles.backdrop }>
<GiftedChat
messages = { messages }
onSend = { this._onSend }
renderMessage = { this._renderMessage } />
</SafeAreaView>
</View>
</SlidingView>
);
}
@@ -146,21 +135,4 @@ class Chat extends AbstractChat<Props> {
}
}
/**
* Maps part of the Redux state to the props of this component.
*
* @param {Object} state - The Redux state.
* @returns {{
* _solidBackground: boolean
* }}
*/
function _mapStateToProps(state) {
const abstractReduxProps = _abstractMapStateToProps(state);
return {
...abstractReduxProps,
_solidBackground: state['features/base/conference'].audioOnly
};
}
export default translate(connect(_mapStateToProps, _mapDispatchToProps)(Chat));

View File

@@ -1,8 +1,7 @@
// @flow
import { connect } from 'react-redux';
import { getLocalParticipant } from '../../../base/participants';
import { connect } from '../../../base/redux';
import {
AbstractButton,
type AbstractButtonProps
@@ -126,5 +125,4 @@ function _mapStateToProps(state) {
};
}
// $FlowExpectedError
export default connect(_mapStateToProps, _mapDispatchToProps)(ChatButton);

View File

@@ -2,14 +2,14 @@
import React from 'react';
import { Text, View } from 'react-native';
import { connect } from 'react-redux';
import { getLocalizedDateFormatter, translate } from '../../../base/i18n';
import { Avatar } from '../../../base/participants';
import { connect } from '../../../base/redux';
import AbstractChatMessage, {
_mapStateToProps as _abstractMapStateToProps,
type Props as AbstractProps
_mapStateToProps,
type Props
} from '../AbstractChatMessage';
import styles from './styles';
@@ -23,14 +23,6 @@ const AVATAR_SIZE = 32;
*/
const TIMESTAMP_FORMAT = 'H:mm';
type Props = AbstractProps & {
/**
* True if the chat window has a solid BG so then we have to adopt in style.
*/
_solidBackground: boolean
}
/**
* Renders a single chat message.
*/
@@ -54,9 +46,6 @@ class ChatMessage extends AbstractChatMessage<Props> {
const textWrapperStyle = [
styles.textWrapper
];
const timeTextStyles = [
styles.timeText
];
if (localMessage) {
// The wrapper needs to be aligned to the right.
@@ -69,10 +58,6 @@ class ChatMessage extends AbstractChatMessage<Props> {
textWrapperStyle.push(styles.systemTextWrapper);
}
if (this.props._solidBackground) {
timeTextStyles.push(styles.solidBGTimeText);
}
return (
<View style = { styles.messageWrapper } >
{
@@ -92,7 +77,7 @@ class ChatMessage extends AbstractChatMessage<Props> {
{ message.text }
</Text>
</View>
<Text style = { timeTextStyles }>
<Text style = { styles.timeText }>
{ timeStamp }
</Text>
</View>
@@ -133,20 +118,4 @@ class ChatMessage extends AbstractChatMessage<Props> {
}
}
/**
* Maps part of the Redux state to the props of this component.
*
* @param {Object} state - The Redux state.
* @param {Props} ownProps - The own props of the component.
* @returns {{
* _solidBackground: boolean
* }}
*/
function _mapStateToProps(state, ownProps) {
return {
..._abstractMapStateToProps(state, ownProps),
_solidBackground: state['features/base/conference'].audioOnly
};
}
export default translate(connect(_mapStateToProps)(ChatMessage));

View File

@@ -1,9 +1,6 @@
// @flow
import {
ColorPalette,
createStyleSheet
} from '../../../base/styles';
import { ColorPalette } from '../../../base/styles';
/**
* The styles of the feature chat.
@@ -13,7 +10,7 @@ import {
* need to extract the brand colors and sizes into a branding feature (planned
* for the future).
*/
export default createStyleSheet({
export default {
/**
* Wrapper View for the avatar.
@@ -22,6 +19,19 @@ export default createStyleSheet({
marginRight: 8
},
/**
* Background of the chat screen.
*/
backdrop: {
backgroundColor: ColorPalette.white,
flex: 1
},
chatContainer: {
flex: 1,
flexDirection: 'column'
},
/**
* Wrapper for the details together, such as name, message and time.
*/
@@ -58,16 +68,6 @@ export default createStyleSheet({
marginVertical: 4
},
/**
* Background of the chat screen. Currently it's set to a transparent value
* as the idea is that the participant would still want to see at least a
* part of the video when he/she is in the chat window.
*/
modalBackdrop: {
backgroundColor: 'rgba(127, 127, 127, 0.8)',
flex: 1
},
/**
* Style modifier for the {@code detailsWrapper} for own messages.
*/
@@ -84,17 +84,6 @@ export default createStyleSheet({
borderTopRightRadius: 0
},
solidBGTimeText: {
color: 'rgb(164, 184, 209)'
},
/**
* Style modifier for the chat window when we're in audio only mode.
*/
solidModalBackdrop: {
backgroundColor: ColorPalette.white
},
/**
* Style modifier for system (error) messages.
*/
@@ -118,7 +107,7 @@ export default createStyleSheet({
* Text node for the timestamp.
*/
timeText: {
color: ColorPalette.white,
color: 'rgb(164, 184, 209)',
fontSize: 13
}
});
};

View File

@@ -1,10 +1,10 @@
// @flow
import React from 'react';
import { connect } from 'react-redux';
import Transition from 'react-transition-group/Transition';
import { translate } from '../../../base/i18n';
import { connect } from '../../../base/redux';
import AbstractChat, {
_mapDispatchToProps,

View File

@@ -1,7 +1,8 @@
// @flow
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { connect } from '../../../base/redux';
import { getUnreadCount } from '../../functions';
@@ -57,5 +58,4 @@ function _mapStateToProps(state) {
};
}
// $FlowExpectedError
export default connect(_mapStateToProps)(ChatCounter);

View File

@@ -1,10 +1,11 @@
// @flow
import React, { Component } from 'react';
import { connect } from 'react-redux';
import Emoji from 'react-emoji-render';
import type { Dispatch } from 'redux';
import { connect } from '../../../base/redux';
import { sendMessage } from '../../actions';
import SmileysPanel from './SmileysPanel';
@@ -232,5 +233,4 @@ class ChatInput extends Component<Props, State> {
}
}
// $FlowExpectedError
export default connect()(ChatInput);

View File

@@ -2,10 +2,10 @@
import { FieldTextStateless } from '@atlaskit/field-text';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import type { Dispatch } from 'redux';
import { translate } from '../../../base/i18n';
import { connect } from '../../../base/redux';
import { updateSettings } from '../../../base/settings';
/**

View File

@@ -3,12 +3,12 @@
import React from 'react';
import { BackHandler, SafeAreaView, StatusBar, View } from 'react-native';
import { connect as reactReduxConnect } from 'react-redux';
import { appNavigate } from '../../../app';
import { connect, disconnect } from '../../../base/connection';
import { getParticipantCount } from '../../../base/participants';
import { Container, LoadingIndicator, TintedView } from '../../../base/react';
import { connect as reactReduxConnect } from '../../../base/redux';
import {
isNarrowAspectRatio,
makeAspectRatioAware
@@ -540,6 +540,5 @@ function _mapStateToProps(state) {
};
}
// $FlowFixMe
export default reactReduxConnect(_mapStateToProps, _mapDispatchToProps)(
makeAspectRatioAware(Conference));

View File

@@ -2,13 +2,13 @@
import React, { Component } from 'react';
import { Text, View } from 'react-native';
import { connect } from 'react-redux';
import {
getLocalParticipant,
getParticipantDisplayName,
shouldRenderParticipantVideo
} from '../../../base/participants';
import { connect } from '../../../base/redux';
import { shouldDisplayTileView } from '../../../video-layout';
@@ -76,5 +76,4 @@ function _mapStateToProps(state: Object) {
};
}
// $FlowExpectedError
export default connect(_mapStateToProps)(DisplayNameLabel);

View File

@@ -2,9 +2,9 @@
import React from 'react';
import { TouchableOpacity, View } from 'react-native';
import { connect } from 'react-redux';
import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet';
import { connect } from '../../../base/redux';
import {
isNarrowAspectRatio,
makeAspectRatioAware
@@ -370,5 +370,4 @@ function _mapStateToProps(state) {
};
}
// $FlowExpectedError
export default connect(_mapStateToProps)(makeAspectRatioAware(Labels));

View File

@@ -4,9 +4,9 @@ import _ from 'lodash';
import React, { Component } from 'react';
import { SafeAreaView, Text, View } from 'react-native';
import LinearGradient from 'react-native-linear-gradient';
import { connect } from 'react-redux';
import { getConferenceName } from '../../../base/conference';
import { connect } from '../../../base/redux';
import { PictureInPictureButton } from '../../../mobile/picture-in-picture';
import { isToolboxVisible } from '../../../toolbox';
@@ -87,5 +87,4 @@ function _mapStateToProps(state) {
};
}
// $FlowExpectedError
export default connect(_mapStateToProps)(NavigationBar);

View File

@@ -2,13 +2,13 @@
import _ from 'lodash';
import React from 'react';
import { connect as reactReduxConnect } from 'react-redux';
import VideoLayout from '../../../../../modules/UI/videolayout/VideoLayout';
import { obtainConfig } from '../../../base/config';
import { connect, disconnect } from '../../../base/connection';
import { translate } from '../../../base/i18n';
import { connect as reactReduxConnect } from '../../../base/redux';
import { Chat } from '../../../chat';
import { Filmstrip } from '../../../filmstrip';
import { CalleeInfoContainer } from '../../../invite';
@@ -293,5 +293,4 @@ function _mapStateToProps(state) {
};
}
// $FlowExpectedError
export default reactReduxConnect(_mapStateToProps)(translate(Conference));

View File

@@ -1,9 +1,9 @@
// @flow
import React from 'react';
import { connect } from 'react-redux';
import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet';
import { connect } from '../../../base/redux';
import AbstractLabels, {
_abstractMapStateToProps as _mapStateToProps,
@@ -105,5 +105,4 @@ class Labels extends AbstractLabels<Props, State> {
_renderVideoQualityLabel: () => React$Element<*>;
}
// $FlowExpectedError
export default connect(_mapStateToProps)(Labels);

View File

@@ -1,9 +1,9 @@
/* @flow */
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { translate } from '../../../base/i18n';
import { connect } from '../../../base/redux';
declare var config: Object;

View File

@@ -1,8 +1,8 @@
/* @flow */
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { connect } from '../../../base/redux';
import { isToolboxVisible } from '../../../toolbox';
/**
@@ -65,5 +65,4 @@ function _mapStateToProps(state) {
};
}
// $FlowExpectedError
export default connect(_mapStateToProps)(Subject);

View File

@@ -3,7 +3,7 @@
import Button, { ButtonGroup } from '@atlaskit/button';
import { AtlasKitThemeProvider } from '@atlaskit/theme';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { connect } from '../../base/redux';
import type { Dispatch } from 'redux';
import { createDeepLinkingPageEvent, sendAnalytics } from '../../analytics';

View File

@@ -1,7 +1,7 @@
// @flow
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { connect } from '../../base/redux';
import { createDeepLinkingPageEvent, sendAnalytics } from '../../analytics';
import { translate, translateToHTML } from '../../base/i18n';

View File

@@ -2,7 +2,7 @@
import Tabs from '@atlaskit/tabs';
import React, { PureComponent } from 'react';
import { connect } from 'react-redux';
import { connect } from '../../base/redux';
import type { Dispatch } from 'redux';
import { Dialog, hideDialog } from '../../base/dialog';

View File

@@ -1,14 +1,15 @@
/* @flow */
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { connect } from '../../base/redux';
import type { Dispatch } from 'redux';
import { appendSuffix } from '../functions';
import { translate } from '../../base/i18n';
import {
getParticipantDisplayName
getParticipantDisplayName,
getParticipantById
} from '../../base/participants';
import { updateSettings } from '../../base/settings';
@@ -18,9 +19,15 @@ import { updateSettings } from '../../base/settings';
type Props = {
/**
* The participant's current display name.
* The participant's current display name which should be shown when in
* edit mode. Can be different from what is shown when not editing.
*/
_displayName: string,
_configuredDisplayName: string,
/**
* The participant's current display name which should be shown.
*/
_nameToDisplay: string,
/**
* Whether or not the display name should be editable on click.
@@ -78,6 +85,10 @@ type State = {
class DisplayName extends Component<Props, State> {
_nameInput: ?HTMLInputElement;
static defaultProps = {
_configuredDisplayName: ''
};
/**
* Initializes a new {@code DisplayName} instance.
*
@@ -134,7 +145,7 @@ class DisplayName extends Component<Props, State> {
*/
render() {
const {
_displayName,
_nameToDisplay,
allowEditing,
displayNameSuffix,
elementID,
@@ -163,7 +174,7 @@ class DisplayName extends Component<Props, State> {
className = 'displayname'
id = { elementID }
onClick = { this._onStartEditing }>
{ appendSuffix(_displayName, displayNameSuffix) }
{ appendSuffix(_nameToDisplay, displayNameSuffix) }
</span>
);
}
@@ -212,7 +223,7 @@ class DisplayName extends Component<Props, State> {
if (this.props.allowEditing) {
this.setState({
isEditing: true,
editDisplayNameValue: this.props._displayName || ''
editDisplayNameValue: this.props._configuredDisplayName
});
}
}
@@ -268,14 +279,17 @@ class DisplayName extends Component<Props, State> {
* @param {Props} ownProps - The own props of the component.
* @private
* @returns {{
* _displayName: string
* _configuredDisplayName: string,
* _nameToDisplay: string
* }}
*/
function _mapStateToProps(state, ownProps) {
const { participantID } = ownProps;
const participant = getParticipantById(state, participantID);
return {
_displayName: getParticipantDisplayName(
_configuredDisplayName: participant && participant.name,
_nameToDisplay: getParticipantDisplayName(
state, participantID)
};
}

View File

@@ -1,7 +1,7 @@
// @flow
import React from 'react';
import { connect } from 'react-redux';
import { connect } from '../../base/redux';
import { InputDialog } from '../../base/dialog';
@@ -27,5 +27,4 @@ class DisplayNamePrompt extends AbstractDisplayNamePrompt<*> {
_onSetDisplayName: string => boolean;
}
// $FlowExpectedError
export default connect()(DisplayNamePrompt);

View File

@@ -1,7 +1,7 @@
/* @flow */
import React from 'react';
import { connect } from 'react-redux';
import { connect } from '../../base/redux';
import { FieldTextStateless as TextField } from '@atlaskit/field-text';
import { Dialog } from '../../base/dialog';

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