Switch to react-navigation (#687)
21
README.md
|
@ -228,24 +228,3 @@ $ detox build
|
||||||
```bash
|
```bash
|
||||||
$ detox test
|
$ detox test
|
||||||
```
|
```
|
||||||
|
|
||||||
## Storybook
|
|
||||||
- General requirements
|
|
||||||
- Install storybook
|
|
||||||
```bash
|
|
||||||
$ yarn global add @storybook/cli
|
|
||||||
```
|
|
||||||
|
|
||||||
- Running storybook
|
|
||||||
- Run storybook application
|
|
||||||
```bash
|
|
||||||
$ yarn storybook
|
|
||||||
```
|
|
||||||
- Run application in other shell
|
|
||||||
```bash
|
|
||||||
$ react-native run-ios
|
|
||||||
```
|
|
||||||
- Running storybook on browser to help stories navigation
|
|
||||||
```
|
|
||||||
open http://localhost:7007/
|
|
||||||
```
|
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
export default {
|
||||||
|
hide: () => ''
|
||||||
|
};
|
|
@ -73,7 +73,7 @@ import com.android.build.OutputFile
|
||||||
*/
|
*/
|
||||||
|
|
||||||
project.ext.react = [
|
project.ext.react = [
|
||||||
entryFile: "index.android.js",
|
entryFile: "index.js",
|
||||||
iconFontNames: [ 'custom.ttf' ]
|
iconFontNames: [ 'custom.ttf' ]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -107,14 +107,7 @@ android {
|
||||||
ndk {
|
ndk {
|
||||||
abiFilters "armeabi-v7a", "x86"
|
abiFilters "armeabi-v7a", "x86"
|
||||||
}
|
}
|
||||||
missingDimensionStrategy "RNN.reactNativeVersion", "reactNative57_5"
|
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
multiDexEnabled true
|
|
||||||
}
|
|
||||||
|
|
||||||
compileOptions {
|
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
|
||||||
targetCompatibility JavaVersion.VERSION_1_8
|
|
||||||
}
|
}
|
||||||
|
|
||||||
packagingOptions {
|
packagingOptions {
|
||||||
|
@ -192,6 +185,9 @@ configurations.all {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
implementation project(':react-native-orientation-locker')
|
||||||
|
implementation project(':react-native-splash-screen')
|
||||||
|
implementation project(':react-native-screens')
|
||||||
implementation project(':react-native-action-sheet')
|
implementation project(':react-native-action-sheet')
|
||||||
implementation project(':react-native-device-info')
|
implementation project(':react-native-device-info')
|
||||||
implementation project(':react-native-gesture-handler')
|
implementation project(':react-native-gesture-handler')
|
||||||
|
@ -206,7 +202,6 @@ dependencies {
|
||||||
implementation project(':@remobile/react-native-toast')
|
implementation project(':@remobile/react-native-toast')
|
||||||
implementation project(':react-native-fast-image')
|
implementation project(':react-native-fast-image')
|
||||||
implementation project(':realm')
|
implementation project(':realm')
|
||||||
implementation project(':react-native-navigation')
|
|
||||||
implementation project(':reactnativenotifications')
|
implementation project(':reactnativenotifications')
|
||||||
implementation fileTree(dir: "libs", include: ["*.jar"])
|
implementation fileTree(dir: "libs", include: ["*.jar"])
|
||||||
implementation "com.android.support:appcompat-v7:27.1.1"
|
implementation "com.android.support:appcompat-v7:27.1.1"
|
||||||
|
@ -230,4 +225,3 @@ task copyDownloadableDepsToLibs(type: Copy) {
|
||||||
from configurations.compile
|
from configurations.compile
|
||||||
into 'libs'
|
into 'libs'
|
||||||
}
|
}
|
||||||
apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"
|
|
||||||
|
|
|
@ -1,40 +1,47 @@
|
||||||
package chat.rocket.reactnative;
|
package chat.rocket.reactnative;
|
||||||
|
|
||||||
import android.graphics.drawable.Drawable;
|
import com.facebook.react.ReactActivityDelegate;
|
||||||
import android.support.v4.content.ContextCompat;
|
import com.facebook.react.ReactRootView;
|
||||||
import android.widget.LinearLayout;
|
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;
|
||||||
// import com.reactnativenavigation.controllers.SplashActivity;
|
|
||||||
import com.reactnativenavigation.NavigationActivity;
|
|
||||||
import android.view.View;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.Nullable;
|
import com.facebook.react.ReactFragmentActivity;
|
||||||
|
import org.devio.rn.splashscreen.SplashScreen;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
|
||||||
public class MainActivity extends NavigationActivity {
|
public class MainActivity extends ReactFragmentActivity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNewIntent(Intent intent) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onNewIntent(intent);
|
SplashScreen.show(this);
|
||||||
setIntent(intent);
|
super.onCreate(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
* Returns the name of the main component registered from JavaScript.
|
||||||
super.onCreate(savedInstanceState);
|
* This is used to schedule rendering of the component.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected String getMainComponentName() {
|
||||||
|
return "RocketChatRN";
|
||||||
|
}
|
||||||
|
|
||||||
View view = new View(this);
|
@Override
|
||||||
view.setBackgroundResource(R.drawable.launch_screen_bitmap);
|
protected ReactActivityDelegate createReactActivityDelegate() {
|
||||||
setContentView(view);
|
return new ReactActivityDelegate(this, getMainComponentName()) {
|
||||||
|
@Override
|
||||||
|
protected ReactRootView createRootView() {
|
||||||
|
return new RNGestureHandlerEnabledRootView(MainActivity.this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConfigurationChanged(Configuration newConfig) {
|
||||||
|
super.onConfigurationChanged(newConfig);
|
||||||
|
Intent intent = new Intent("onConfigurationChanged");
|
||||||
|
intent.putExtra("newConfig", newConfig);
|
||||||
|
this.sendBroadcast(intent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// public class MainActivity extends SplashActivity {
|
|
||||||
// @Override
|
|
||||||
// public LinearLayout createSplashLayout() {
|
|
||||||
// LinearLayout splash = new LinearLayout(this);
|
|
||||||
// Drawable launch_screen_bitmap = ContextCompat.getDrawable(getApplicationContext(),R.drawable.launch_screen_bitmap);
|
|
||||||
// splash.setBackground(launch_screen_bitmap);
|
|
||||||
|
|
||||||
// return splash;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
|
@ -1,7 +1,14 @@
|
||||||
package chat.rocket.reactnative;
|
package chat.rocket.reactnative;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.app.Application;
|
||||||
import android.os.Bundle;
|
|
||||||
|
import com.facebook.react.ReactApplication;
|
||||||
|
import org.wonday.orientation.OrientationPackage;
|
||||||
|
import org.devio.rn.splashscreen.SplashScreenReactPackage;
|
||||||
|
import com.facebook.react.ReactNativeHost;
|
||||||
|
import com.facebook.react.ReactPackage;
|
||||||
|
import com.facebook.react.shell.MainReactPackage;
|
||||||
|
import com.facebook.soloader.SoLoader;
|
||||||
|
|
||||||
import com.AlexanderZaytsev.RNI18n.RNI18nPackage;
|
import com.AlexanderZaytsev.RNI18n.RNI18nPackage;
|
||||||
import com.reactnative.ivpusic.imagepicker.PickerPackage;
|
import com.reactnative.ivpusic.imagepicker.PickerPackage;
|
||||||
|
@ -9,16 +16,10 @@ import com.RNFetchBlob.RNFetchBlobPackage;
|
||||||
import com.brentvatne.react.ReactVideoPackage;
|
import com.brentvatne.react.ReactVideoPackage;
|
||||||
import com.crashlytics.android.Crashlytics;
|
import com.crashlytics.android.Crashlytics;
|
||||||
import com.dylanvann.fastimage.FastImageViewPackage;
|
import com.dylanvann.fastimage.FastImageViewPackage;
|
||||||
import com.facebook.react.ReactPackage;
|
|
||||||
import com.facebook.react.shell.MainReactPackage;
|
|
||||||
import com.oblador.vectoricons.VectorIconsPackage;
|
import com.oblador.vectoricons.VectorIconsPackage;
|
||||||
import com.reactnativenavigation.NavigationApplication;
|
|
||||||
import com.facebook.react.ReactNativeHost;
|
|
||||||
import com.remobile.toast.RCTToastPackage;
|
import com.remobile.toast.RCTToastPackage;
|
||||||
import com.rnim.rn.audio.ReactNativeAudioPackage;
|
import com.rnim.rn.audio.ReactNativeAudioPackage;
|
||||||
import com.smixx.fabric.FabricPackage;
|
import com.smixx.fabric.FabricPackage;
|
||||||
import com.reactnativenavigation.react.NavigationReactNativeHost;
|
|
||||||
import com.reactnativenavigation.react.ReactGateway;
|
|
||||||
import com.wix.reactnativekeyboardinput.KeyboardInputPackage;
|
import com.wix.reactnativekeyboardinput.KeyboardInputPackage;
|
||||||
import com.wix.reactnativenotifications.RNNotificationsPackage;
|
import com.wix.reactnativenotifications.RNNotificationsPackage;
|
||||||
import com.wix.reactnativenotifications.core.AppLaunchHelper;
|
import com.wix.reactnativenotifications.core.AppLaunchHelper;
|
||||||
|
@ -29,82 +30,76 @@ import com.wix.reactnativenotifications.core.notification.IPushNotification;
|
||||||
import com.swmansion.gesturehandler.react.RNGestureHandlerPackage;
|
import com.swmansion.gesturehandler.react.RNGestureHandlerPackage;
|
||||||
import com.learnium.RNDeviceInfo.RNDeviceInfo;
|
import com.learnium.RNDeviceInfo.RNDeviceInfo;
|
||||||
import com.actionsheet.ActionSheetPackage;
|
import com.actionsheet.ActionSheetPackage;
|
||||||
|
import io.fabric.sdk.android.Fabric;
|
||||||
|
import io.realm.react.RealmReactPackage;
|
||||||
|
import com.swmansion.rnscreens.RNScreensPackage;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import io.fabric.sdk.android.Fabric;
|
public class MainApplication extends Application implements ReactApplication, INotificationsApplication {
|
||||||
import io.realm.react.RealmReactPackage;
|
|
||||||
|
|
||||||
public class MainApplication extends NavigationApplication implements INotificationsApplication {
|
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
|
||||||
|
@Override
|
||||||
// private NotificationsLifecycleFacade notificationsLifecycleFacade;
|
public boolean getUseDeveloperSupport() {
|
||||||
|
return BuildConfig.DEBUG;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDebug() {
|
|
||||||
return BuildConfig.DEBUG;
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Override
|
|
||||||
// public String getJSMainModuleName() {
|
|
||||||
// return "index.android";
|
|
||||||
// }
|
|
||||||
|
|
||||||
protected ReactGateway createReactGateway() {
|
|
||||||
ReactNativeHost host = new NavigationReactNativeHost(this, isDebug(), createAdditionalReactPackages()) {
|
|
||||||
@Override
|
|
||||||
protected String getJSMainModuleName() {
|
|
||||||
return "index.android";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return new ReactGateway(this, isDebug(), host);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected List<ReactPackage> getPackages() {
|
protected List<ReactPackage> getPackages() {
|
||||||
// Add additional packages you require here
|
return Arrays.<ReactPackage>asList(
|
||||||
// No need to add RnnPackage and MainReactPackage
|
new MainReactPackage(),
|
||||||
return Arrays.<ReactPackage>asList(
|
new OrientationPackage(),
|
||||||
);
|
new SplashScreenReactPackage(),
|
||||||
|
new RNGestureHandlerPackage(),
|
||||||
|
new RNScreensPackage(),
|
||||||
|
new ActionSheetPackage(),
|
||||||
|
new RNDeviceInfo(),
|
||||||
|
new PickerPackage(),
|
||||||
|
new VectorIconsPackage(),
|
||||||
|
new RNFetchBlobPackage(),
|
||||||
|
new RealmReactPackage(),
|
||||||
|
new ReactVideoPackage(),
|
||||||
|
new RCTToastPackage(),
|
||||||
|
new ReactNativeAudioPackage(),
|
||||||
|
new KeyboardInputPackage(MainApplication.this),
|
||||||
|
new RocketChatNativePackage(),
|
||||||
|
new FabricPackage(),
|
||||||
|
new FastImageViewPackage(),
|
||||||
|
new RNI18nPackage(),
|
||||||
|
new RNNotificationsPackage(MainApplication.this)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ReactPackage> createAdditionalReactPackages() {
|
protected String getJSMainModuleName() {
|
||||||
return Arrays.<ReactPackage>asList(
|
return "index";
|
||||||
new MainReactPackage(),
|
|
||||||
new ActionSheetPackage(),
|
|
||||||
new RNDeviceInfo(),
|
|
||||||
new RNGestureHandlerPackage(),
|
|
||||||
new PickerPackage(),
|
|
||||||
new VectorIconsPackage(),
|
|
||||||
new RNFetchBlobPackage(),
|
|
||||||
new RealmReactPackage(),
|
|
||||||
new ReactVideoPackage(),
|
|
||||||
new RCTToastPackage(),
|
|
||||||
new ReactNativeAudioPackage(),
|
|
||||||
new KeyboardInputPackage(MainApplication.this),
|
|
||||||
new RocketChatNativePackage(),
|
|
||||||
new FabricPackage(),
|
|
||||||
new FastImageViewPackage(),
|
|
||||||
new RNI18nPackage(),
|
|
||||||
new RNNotificationsPackage(MainApplication.this)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public ReactNativeHost getReactNativeHost() {
|
||||||
super.onCreate();
|
return mReactNativeHost;
|
||||||
Fabric.with(this, new Crashlytics());
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IPushNotification getPushNotification(Context context, Bundle bundle, AppLifecycleFacade defaultFacade, AppLaunchHelper defaultAppLaunchHelper) {
|
public void onCreate() {
|
||||||
return new CustomPushNotification(
|
super.onCreate();
|
||||||
context,
|
Fabric.with(this, new Crashlytics());
|
||||||
bundle,
|
SoLoader.init(this, /* native exopackage */ false);
|
||||||
defaultFacade,
|
}
|
||||||
defaultAppLaunchHelper,
|
|
||||||
new JsIOHelper()
|
@Override
|
||||||
);
|
public IPushNotification getPushNotification(Context context, Bundle bundle, AppLifecycleFacade defaultFacade, AppLaunchHelper defaultAppLaunchHelper) {
|
||||||
}
|
return new CustomPushNotification(
|
||||||
|
context,
|
||||||
|
bundle,
|
||||||
|
defaultFacade,
|
||||||
|
defaultAppLaunchHelper,
|
||||||
|
new JsIOHelper()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical" android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
<ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/launch_screen" android:scaleType="centerCrop" />
|
||||||
|
</RelativeLayout>
|
|
@ -46,12 +46,6 @@ subprojects { subproject ->
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
targetSdkVersion 28
|
targetSdkVersion 28
|
||||||
}
|
}
|
||||||
variantFilter { variant ->
|
|
||||||
def names = variant.flavors*.name
|
|
||||||
if (names.contains("reactNative51") || names.contains("reactNative55") || names.contains("reactNative56") || names.contains("reactNative57") || names.contains("reactNative57WixFork")) {
|
|
||||||
setIgnore(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,6 @@
|
||||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||||
# org.gradle.parallel=true
|
# org.gradle.parallel=true
|
||||||
|
|
||||||
# android.enableAapt2=false
|
android.enableAapt2=false # commenting this makes notifications to stop working
|
||||||
android.useDeprecatedNdk=true
|
android.useDeprecatedNdk=true
|
||||||
VERSIONCODE=999999999
|
VERSIONCODE=999999999
|
||||||
|
|
|
@ -1,4 +1,10 @@
|
||||||
rootProject.name = 'RocketChatRN'
|
rootProject.name = 'RocketChatRN'
|
||||||
|
include ':react-native-orientation-locker'
|
||||||
|
project(':react-native-orientation-locker').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-orientation-locker/android')
|
||||||
|
include ':react-native-splash-screen'
|
||||||
|
project(':react-native-splash-screen').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-splash-screen/android')
|
||||||
|
include ':react-native-screens'
|
||||||
|
project(':react-native-screens').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-screens/android')
|
||||||
include ':react-native-action-sheet'
|
include ':react-native-action-sheet'
|
||||||
project(':react-native-action-sheet').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-action-sheet/android')
|
project(':react-native-action-sheet').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-action-sheet/android')
|
||||||
include ':react-native-device-info'
|
include ':react-native-device-info'
|
||||||
|
@ -27,8 +33,6 @@ include ':react-native-vector-icons'
|
||||||
project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android')
|
project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android')
|
||||||
include ':realm'
|
include ':realm'
|
||||||
project(':realm').projectDir = new File(rootProject.projectDir, '../node_modules/realm/android')
|
project(':realm').projectDir = new File(rootProject.projectDir, '../node_modules/realm/android')
|
||||||
include ':react-native-navigation'
|
|
||||||
project(':react-native-navigation').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-navigation/lib/android/app/')
|
|
||||||
include ':reactnativenotifications'
|
include ':reactnativenotifications'
|
||||||
project(':reactnativenotifications').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-notifications/android')
|
project(':reactnativenotifications').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-notifications/android')
|
||||||
include ':app'
|
include ':app'
|
||||||
|
|
|
@ -38,7 +38,7 @@ export const ROOM = createRequestTypes('ROOM', [
|
||||||
'MESSAGE_RECEIVED',
|
'MESSAGE_RECEIVED',
|
||||||
'SET_LAST_OPEN'
|
'SET_LAST_OPEN'
|
||||||
]);
|
]);
|
||||||
export const APP = createRequestTypes('APP', ['START', 'READY', 'INIT', 'SET_STACK_ROOT']);
|
export const APP = createRequestTypes('APP', ['START', 'READY', 'INIT']);
|
||||||
export const MESSAGES = createRequestTypes('MESSAGES', [
|
export const MESSAGES = createRequestTypes('MESSAGES', [
|
||||||
...defaultTypes,
|
...defaultTypes,
|
||||||
'ACTIONS_SHOW',
|
'ACTIONS_SHOW',
|
||||||
|
|
|
@ -20,13 +20,6 @@ export function appInit() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setStackRoot(stackRoot) {
|
|
||||||
return {
|
|
||||||
type: APP.SET_STACK_ROOT,
|
|
||||||
stackRoot
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setCurrentServer(server) {
|
export function setCurrentServer(server) {
|
||||||
return {
|
return {
|
||||||
type: types.SET_CURRENT_SERVER,
|
type: types.SET_CURRENT_SERVER,
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
import * as types from './actionsTypes';
|
|
||||||
|
|
||||||
export function openSnippetedMessages(rid, limit) {
|
|
||||||
return {
|
|
||||||
type: types.SNIPPETED_MESSAGES.OPEN,
|
|
||||||
rid,
|
|
||||||
limit
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function readySnippetedMessages() {
|
|
||||||
return {
|
|
||||||
type: types.SNIPPETED_MESSAGES.READY
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function closeSnippetedMessages() {
|
|
||||||
return {
|
|
||||||
type: types.SNIPPETED_MESSAGES.CLOSE
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function snippetedMessagesReceived(messages) {
|
|
||||||
return {
|
|
||||||
type: types.SNIPPETED_MESSAGES.MESSAGES_RECEIVED,
|
|
||||||
messages
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { isIOS } from '../utils/deviceInfo';
|
||||||
|
|
||||||
export const COLOR_DANGER = '#f5455c';
|
export const COLOR_DANGER = '#f5455c';
|
||||||
export const COLOR_BUTTON_PRIMARY = '#1d74f5';
|
export const COLOR_BUTTON_PRIMARY = '#1d74f5';
|
||||||
export const COLOR_TEXT = '#292E35';
|
export const COLOR_TEXT = '#292E35';
|
||||||
|
@ -8,3 +10,7 @@ export const STATUS_COLORS = {
|
||||||
away: '#ffd21f',
|
away: '#ffd21f',
|
||||||
offline: '#cbced1'
|
offline: '#cbced1'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const HEADER_BACKGROUND = isIOS ? '#FFF' : '#2F343D';
|
||||||
|
export const HEADER_TITLE = isIOS ? '#0C0D0F' : '#FFF';
|
||||||
|
export const HEADER_BACK = isIOS ? '#1d74f5' : '#FFF';
|
||||||
|
|
|
@ -1,62 +0,0 @@
|
||||||
import { Platform } from 'react-native';
|
|
||||||
|
|
||||||
export const DARK_HEADER = {
|
|
||||||
statusBar: {
|
|
||||||
backgroundColor: '#2F343D',
|
|
||||||
style: 'light'
|
|
||||||
},
|
|
||||||
topBar: {
|
|
||||||
backButton: {
|
|
||||||
showTitle: false,
|
|
||||||
color: '#fff'
|
|
||||||
},
|
|
||||||
background: {
|
|
||||||
color: '#2F343D'
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
color: '#FFF'
|
|
||||||
},
|
|
||||||
leftButtonStyle: {
|
|
||||||
color: '#FFF'
|
|
||||||
},
|
|
||||||
rightButtonStyle: {
|
|
||||||
color: '#FFF'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const LIGHT_HEADER = {
|
|
||||||
statusBar: {
|
|
||||||
backgroundColor: '#FFF',
|
|
||||||
style: 'dark'
|
|
||||||
},
|
|
||||||
topBar: {
|
|
||||||
backButton: {
|
|
||||||
showTitle: false,
|
|
||||||
color: '#1d74f5'
|
|
||||||
},
|
|
||||||
background: {
|
|
||||||
color: undefined
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
color: '#0C0D0F'
|
|
||||||
},
|
|
||||||
leftButtonStyle: {
|
|
||||||
color: '#1d74f5'
|
|
||||||
},
|
|
||||||
rightButtonStyle: {
|
|
||||||
color: '#1d74f5'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const DEFAULT_HEADER = {
|
|
||||||
...Platform.select({
|
|
||||||
ios: {
|
|
||||||
...LIGHT_HEADER
|
|
||||||
},
|
|
||||||
android: {
|
|
||||||
...DARK_HEADER
|
|
||||||
}
|
|
||||||
})
|
|
||||||
};
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { Text } from 'react-native';
|
||||||
|
import HeaderButtons, { HeaderButton, Item } from 'react-navigation-header-buttons';
|
||||||
|
|
||||||
|
import { CustomIcon } from '../lib/Icons';
|
||||||
|
import { isIOS } from '../utils/deviceInfo';
|
||||||
|
|
||||||
|
const color = isIOS ? '#1D74F5' : '#FFF';
|
||||||
|
|
||||||
|
const CustomHeaderButton = React.memo(props => (
|
||||||
|
<HeaderButton {...props} IconComponent={CustomIcon} iconSize={23} color={color} />
|
||||||
|
));
|
||||||
|
|
||||||
|
export const CustomHeaderButtons = React.memo(props => (
|
||||||
|
<HeaderButtons
|
||||||
|
HeaderButtonComponent={CustomHeaderButton}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
|
||||||
|
export const DrawerButton = React.memo(({ navigation, testID }) => (
|
||||||
|
<CustomHeaderButtons left>
|
||||||
|
<Item title='drawer' iconName='customize' onPress={navigation.toggleDrawer} testID={testID} />
|
||||||
|
</CustomHeaderButtons>
|
||||||
|
));
|
||||||
|
|
||||||
|
export const CloseModalButton = React.memo(({ navigation, testID }) => (
|
||||||
|
<CustomHeaderButtons left>
|
||||||
|
<Item title='close' iconName='cross' onPress={() => navigation.pop()} testID={testID} />
|
||||||
|
</CustomHeaderButtons>
|
||||||
|
));
|
||||||
|
|
||||||
|
export const MoreButton = React.memo(({ onPress, testID }) => (
|
||||||
|
<CustomHeaderButtons>
|
||||||
|
<Item title='more' iconName='menu' onPress={onPress} testID={testID} />
|
||||||
|
</CustomHeaderButtons>
|
||||||
|
));
|
||||||
|
|
||||||
|
export const LegalButton = React.memo(({ navigation, testID }) => (
|
||||||
|
<MoreButton onPress={() => navigation.navigate('LegalView')} testID={testID} />
|
||||||
|
));
|
||||||
|
|
||||||
|
DrawerButton.propTypes = {
|
||||||
|
navigation: PropTypes.object.isRequired,
|
||||||
|
testID: PropTypes.string.isRequired
|
||||||
|
};
|
||||||
|
CloseModalButton.propTypes = {
|
||||||
|
navigation: PropTypes.object.isRequired,
|
||||||
|
testID: PropTypes.string.isRequired
|
||||||
|
};
|
||||||
|
MoreButton.propTypes = {
|
||||||
|
onPress: PropTypes.func.isRequired,
|
||||||
|
testID: PropTypes.string.isRequired
|
||||||
|
};
|
||||||
|
LegalButton.propTypes = {
|
||||||
|
navigation: PropTypes.object.isRequired,
|
||||||
|
testID: PropTypes.string.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
export { Item };
|
||||||
|
|
||||||
|
export default () => <Text>a</Text>;
|
|
@ -6,7 +6,7 @@ const styles = StyleSheet.create({
|
||||||
style: {
|
style: {
|
||||||
marginRight: 7,
|
marginRight: 7,
|
||||||
marginTop: 3,
|
marginTop: 3,
|
||||||
color: '#9EA2A8'
|
tintColor: '#9EA2A8'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { StatusBar as StatusBarRN } from 'react-native';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import { isIOS } from '../utils/deviceInfo';
|
||||||
|
import { HEADER_BACKGROUND } from '../constants/colors';
|
||||||
|
|
||||||
|
const HEADER_BAR_STYLE = isIOS ? 'dark-content' : 'light-content';
|
||||||
|
|
||||||
|
const StatusBar = React.memo(({ light }) => {
|
||||||
|
if (light) {
|
||||||
|
return <StatusBarRN backgroundColor='#FFF' barStyle='dark-content' animated />;
|
||||||
|
}
|
||||||
|
return <StatusBarRN backgroundColor={HEADER_BACKGROUND} barStyle={HEADER_BAR_STYLE} animated />;
|
||||||
|
});
|
||||||
|
|
||||||
|
StatusBar.propTypes = {
|
||||||
|
light: PropTypes.bool
|
||||||
|
};
|
||||||
|
|
||||||
|
StatusBar.defaultProps = {
|
||||||
|
light: false
|
||||||
|
};
|
||||||
|
|
||||||
|
export default StatusBar;
|
|
@ -214,7 +214,6 @@ export default {
|
||||||
No_mentioned_messages: 'Keine erwähnten Nachrichten',
|
No_mentioned_messages: 'Keine erwähnten Nachrichten',
|
||||||
No_pinned_messages: 'Keine angehefteten Nachrichten',
|
No_pinned_messages: 'Keine angehefteten Nachrichten',
|
||||||
No_results_found: 'keine Ergebnisse gefunden',
|
No_results_found: 'keine Ergebnisse gefunden',
|
||||||
No_snippeted_messages: 'Keine Nachrichten-Snippets',
|
|
||||||
No_starred_messages: 'Keine markierten Nachrichten',
|
No_starred_messages: 'Keine markierten Nachrichten',
|
||||||
No_announcement_provided: 'Keine Ankündigung erfolgt.',
|
No_announcement_provided: 'Keine Ankündigung erfolgt.',
|
||||||
No_description_provided: 'Keine Beschreibung angegeben.',
|
No_description_provided: 'Keine Beschreibung angegeben.',
|
||||||
|
@ -292,9 +291,6 @@ export default {
|
||||||
Share: 'Teilen',
|
Share: 'Teilen',
|
||||||
Sign_in_your_server: 'Melden Sie sich bei Ihrem Server an',
|
Sign_in_your_server: 'Melden Sie sich bei Ihrem Server an',
|
||||||
Sign_Up: 'Anmelden',
|
Sign_Up: 'Anmelden',
|
||||||
Snippet_Messages: 'Snippet-Nachrichten',
|
|
||||||
snippeted: 'snippeted',
|
|
||||||
Snippets: 'Snippets',
|
|
||||||
Some_field_is_invalid_or_empty: 'Ein Feld ist ungültig oder leer',
|
Some_field_is_invalid_or_empty: 'Ein Feld ist ungültig oder leer',
|
||||||
Sorting_by: 'Sortierung nach {{key}}',
|
Sorting_by: 'Sortierung nach {{key}}',
|
||||||
Star_room: 'Favorisierter Raum',
|
Star_room: 'Favorisierter Raum',
|
||||||
|
|
|
@ -214,7 +214,6 @@ export default {
|
||||||
No_mentioned_messages: 'No mentioned messages',
|
No_mentioned_messages: 'No mentioned messages',
|
||||||
No_pinned_messages: 'No pinned messages',
|
No_pinned_messages: 'No pinned messages',
|
||||||
No_results_found: 'No results found',
|
No_results_found: 'No results found',
|
||||||
No_snippeted_messages: 'No snippeted messages',
|
|
||||||
No_starred_messages: 'No starred messages',
|
No_starred_messages: 'No starred messages',
|
||||||
No_announcement_provided: 'No announcement provided.',
|
No_announcement_provided: 'No announcement provided.',
|
||||||
No_description_provided: 'No description provided.',
|
No_description_provided: 'No description provided.',
|
||||||
|
@ -292,9 +291,6 @@ export default {
|
||||||
Share: 'Share',
|
Share: 'Share',
|
||||||
Sign_in_your_server: 'Sign in your server',
|
Sign_in_your_server: 'Sign in your server',
|
||||||
Sign_Up: 'Sign Up',
|
Sign_Up: 'Sign Up',
|
||||||
Snippet_Messages: 'Snippet Messages',
|
|
||||||
snippeted: 'snippeted',
|
|
||||||
Snippets: 'Snippets',
|
|
||||||
Some_field_is_invalid_or_empty: 'Some field is invalid or empty',
|
Some_field_is_invalid_or_empty: 'Some field is invalid or empty',
|
||||||
Sorting_by: 'Sorting by {{key}}',
|
Sorting_by: 'Sorting by {{key}}',
|
||||||
Star_room: 'Star room',
|
Star_room: 'Star room',
|
||||||
|
|
|
@ -214,7 +214,6 @@ export default {
|
||||||
No_mentioned_messages: 'Aucun message mentionné',
|
No_mentioned_messages: 'Aucun message mentionné',
|
||||||
No_pinned_messages: 'Aucun message épinglé',
|
No_pinned_messages: 'Aucun message épinglé',
|
||||||
No_results_found: 'Aucun résultat trouvé',
|
No_results_found: 'Aucun résultat trouvé',
|
||||||
No_snippeted_messages: 'Aucun message extrait',
|
|
||||||
No_starred_messages: 'Pas de messages suivis',
|
No_starred_messages: 'Pas de messages suivis',
|
||||||
No_announcement_provided: 'Aucune annonce fournie.',
|
No_announcement_provided: 'Aucune annonce fournie.',
|
||||||
No_description_provided: 'Aucune description fournie.',
|
No_description_provided: 'Aucune description fournie.',
|
||||||
|
@ -292,9 +291,6 @@ export default {
|
||||||
Share: 'Partager',
|
Share: 'Partager',
|
||||||
Sign_in_your_server: 'Connectez-vous à votre serveur',
|
Sign_in_your_server: 'Connectez-vous à votre serveur',
|
||||||
Sign_Up: 'S\'inscrire',
|
Sign_Up: 'S\'inscrire',
|
||||||
Snippet_Messages: 'Messages Extraits',
|
|
||||||
snippeted: 'extrait',
|
|
||||||
Snippets: 'Extraits',
|
|
||||||
Some_field_is_invalid_or_empty: 'Certains champs sont invalides ou vides',
|
Some_field_is_invalid_or_empty: 'Certains champs sont invalides ou vides',
|
||||||
Sorting_by: 'Tri par {{key}}',
|
Sorting_by: 'Tri par {{key}}',
|
||||||
Star_room: 'Favoriser canal',
|
Star_room: 'Favoriser canal',
|
||||||
|
|
|
@ -217,7 +217,6 @@ export default {
|
||||||
No_mentioned_messages: 'Não há menções',
|
No_mentioned_messages: 'Não há menções',
|
||||||
No_pinned_messages: 'Não há mensagens fixadas',
|
No_pinned_messages: 'Não há mensagens fixadas',
|
||||||
No_results_found: 'Nenhum resultado encontrado',
|
No_results_found: 'Nenhum resultado encontrado',
|
||||||
No_snippeted_messages: 'Não há trechos de mensagens',
|
|
||||||
No_starred_messages: 'Não há mensagens favoritas',
|
No_starred_messages: 'Não há mensagens favoritas',
|
||||||
No_announcement_provided: 'Sem anúncio.',
|
No_announcement_provided: 'Sem anúncio.',
|
||||||
No_description_provided: 'Sem descrição.',
|
No_description_provided: 'Sem descrição.',
|
||||||
|
@ -293,9 +292,6 @@ export default {
|
||||||
Share: 'Compartilhar',
|
Share: 'Compartilhar',
|
||||||
Sign_in_your_server: 'Entrar no seu servidor',
|
Sign_in_your_server: 'Entrar no seu servidor',
|
||||||
Sign_Up: 'Registrar',
|
Sign_Up: 'Registrar',
|
||||||
Snippet_Messages: 'Trecho de Mensagens',
|
|
||||||
snippeted: 'trecho de mensagem',
|
|
||||||
Snippets: 'Trecho de mensagem',
|
|
||||||
Some_field_is_invalid_or_empty: 'Algum campo está inválido ou vazio',
|
Some_field_is_invalid_or_empty: 'Algum campo está inválido ou vazio',
|
||||||
Sorting_by: 'Ordenando por {{key}}',
|
Sorting_by: 'Ordenando por {{key}}',
|
||||||
Star_room: 'Favoritar sala',
|
Star_room: 'Favoritar sala',
|
||||||
|
|
|
@ -183,7 +183,6 @@ export default {
|
||||||
No_files: 'Нет файлов',
|
No_files: 'Нет файлов',
|
||||||
No_mentioned_messages: 'Нет упоминаний',
|
No_mentioned_messages: 'Нет упоминаний',
|
||||||
No_pinned_messages: 'Нет прикрепленных сообщений',
|
No_pinned_messages: 'Нет прикрепленных сообщений',
|
||||||
No_snippeted_messages: 'Нет сообщений со сниппетом',
|
|
||||||
No_starred_messages: 'Нет отмеченных сообщений',
|
No_starred_messages: 'Нет отмеченных сообщений',
|
||||||
No_announcement_provided: 'Нет объявлений.',
|
No_announcement_provided: 'Нет объявлений.',
|
||||||
No_description_provided: 'Нет описания.',
|
No_description_provided: 'Нет описания.',
|
||||||
|
@ -255,9 +254,6 @@ export default {
|
||||||
Share: 'Поделиться',
|
Share: 'Поделиться',
|
||||||
Sign_in_your_server: 'Войдите на ваш сервер',
|
Sign_in_your_server: 'Войдите на ваш сервер',
|
||||||
Sign_Up: 'Регистрация',
|
Sign_Up: 'Регистрация',
|
||||||
Snippet_Messages: 'Сообщения со сниппетом',
|
|
||||||
snippeted: 'сниппет добавлен',
|
|
||||||
Snippets: 'Сниппеты',
|
|
||||||
Some_field_is_invalid_or_empty: 'Некоторые поля недопустимы или пусты',
|
Some_field_is_invalid_or_empty: 'Некоторые поля недопустимы или пусты',
|
||||||
Star_room: 'Star room',
|
Star_room: 'Star room',
|
||||||
Star: 'Звезда',
|
Star: 'Звезда',
|
||||||
|
|
|
@ -287,9 +287,6 @@ export default {
|
||||||
Share: '分享',
|
Share: '分享',
|
||||||
Sign_in_your_server: '登录你的服务器',
|
Sign_in_your_server: '登录你的服务器',
|
||||||
Sign_Up: '注册',
|
Sign_Up: '注册',
|
||||||
Snippet_Messages: '代码片段消息',
|
|
||||||
snippeted: '代码片段',
|
|
||||||
Snippets: '代码片段',
|
|
||||||
Some_field_is_invalid_or_empty: '某些字段无效或为空',
|
Some_field_is_invalid_or_empty: '某些字段无效或为空',
|
||||||
Sorting_by: '按{{key}}排序',
|
Sorting_by: '按{{key}}排序',
|
||||||
Star_room: '将房间标星',
|
Star_room: '将房间标星',
|
||||||
|
|
283
app/index.js
|
@ -1,78 +1,49 @@
|
||||||
import { Component } from 'react';
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
createStackNavigator, createAppContainer, createSwitchNavigator, createDrawerNavigator
|
||||||
|
} from 'react-navigation';
|
||||||
|
import { Provider } from 'react-redux';
|
||||||
|
import { useScreens } from 'react-native-screens'; // eslint-disable-line import/no-unresolved
|
||||||
import { Linking } from 'react-native';
|
import { Linking } from 'react-native';
|
||||||
|
|
||||||
import { appInit } from './actions';
|
|
||||||
import { deepLinkingOpen } from './actions/deepLinking';
|
import { deepLinkingOpen } from './actions/deepLinking';
|
||||||
import store from './lib/createStore';
|
import OnboardingView from './views/OnboardingView';
|
||||||
import Icons from './lib/Icons';
|
import NewServerView from './views/NewServerView';
|
||||||
|
import LoginSignupView from './views/LoginSignupView';
|
||||||
|
import AuthLoadingView from './views/AuthLoadingView';
|
||||||
|
import RoomsListView from './views/RoomsListView';
|
||||||
|
import RoomView from './views/RoomView';
|
||||||
|
import NewMessageView from './views/NewMessageView';
|
||||||
|
import LoginView from './views/LoginView';
|
||||||
import Navigation from './lib/Navigation';
|
import Navigation from './lib/Navigation';
|
||||||
|
import Sidebar from './views/SidebarView';
|
||||||
|
import ProfileView from './views/ProfileView';
|
||||||
|
import SettingsView from './views/SettingsView';
|
||||||
|
import RoomActionsView from './views/RoomActionsView';
|
||||||
|
import RoomInfoView from './views/RoomInfoView';
|
||||||
|
import RoomInfoEditView from './views/RoomInfoEditView';
|
||||||
|
import RoomMembersView from './views/RoomMembersView';
|
||||||
|
import RoomFilesView from './views/RoomFilesView';
|
||||||
|
import MentionedMessagesView from './views/MentionedMessagesView';
|
||||||
|
import StarredMessagesView from './views/StarredMessagesView';
|
||||||
|
import SearchMessagesView from './views/SearchMessagesView';
|
||||||
|
import PinnedMessagesView from './views/PinnedMessagesView';
|
||||||
|
import SelectedUsersView from './views/SelectedUsersView';
|
||||||
|
import CreateChannelView from './views/CreateChannelView';
|
||||||
|
import LegalView from './views/LegalView';
|
||||||
|
import TermsServiceView from './views/TermsServiceView';
|
||||||
|
import PrivacyPolicyView from './views/PrivacyPolicyView';
|
||||||
|
import ForgotPasswordView from './views/ForgotPasswordView';
|
||||||
|
import RegisterView from './views/RegisterView';
|
||||||
|
import OAuthView from './views/OAuthView';
|
||||||
|
import SetUsernameView from './views/SetUsernameView';
|
||||||
|
import { HEADER_BACKGROUND, HEADER_TITLE, HEADER_BACK } from './constants/colors';
|
||||||
import parseQuery from './lib/methods/helpers/parseQuery';
|
import parseQuery from './lib/methods/helpers/parseQuery';
|
||||||
import { initializePushNotifications } from './push';
|
import { initializePushNotifications } from './push';
|
||||||
import { DEFAULT_HEADER } from './constants/headerOptions';
|
import store from './lib/createStore';
|
||||||
|
|
||||||
const startLogged = () => {
|
useScreens();
|
||||||
Navigation.loadView('ProfileView');
|
initializePushNotifications();
|
||||||
Navigation.loadView('RoomsListHeaderView');
|
|
||||||
Navigation.loadView('RoomsListView');
|
|
||||||
Navigation.loadView('RoomView');
|
|
||||||
Navigation.loadView('RoomHeaderView');
|
|
||||||
Navigation.loadView('SettingsView');
|
|
||||||
Navigation.loadView('SidebarView');
|
|
||||||
|
|
||||||
Navigation.setRoot({
|
|
||||||
root: {
|
|
||||||
stack: {
|
|
||||||
id: 'AppRoot',
|
|
||||||
children: [{
|
|
||||||
component: {
|
|
||||||
id: 'RoomsListView',
|
|
||||||
name: 'RoomsListView'
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const startNotLogged = () => {
|
|
||||||
Navigation.loadView('OnboardingView');
|
|
||||||
Navigation.setRoot({
|
|
||||||
root: {
|
|
||||||
stack: {
|
|
||||||
children: [{
|
|
||||||
component: {
|
|
||||||
name: 'OnboardingView'
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
options: {
|
|
||||||
layout: {
|
|
||||||
orientation: ['portrait']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const startSetUsername = () => {
|
|
||||||
Navigation.loadView('SetUsernameView');
|
|
||||||
Navigation.setRoot({
|
|
||||||
root: {
|
|
||||||
stack: {
|
|
||||||
children: [{
|
|
||||||
component: {
|
|
||||||
name: 'SetUsernameView'
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
options: {
|
|
||||||
layout: {
|
|
||||||
orientation: ['portrait']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleOpenURL = ({ url }) => {
|
const handleOpenURL = ({ url }) => {
|
||||||
if (url) {
|
if (url) {
|
||||||
|
@ -86,51 +57,139 @@ const handleOpenURL = ({ url }) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Icons.configure();
|
Linking
|
||||||
|
.getInitialURL()
|
||||||
|
.then(url => handleOpenURL({ url }))
|
||||||
|
.catch(e => console.warn(e));
|
||||||
|
Linking.addEventListener('url', handleOpenURL);
|
||||||
|
|
||||||
export default class App extends Component {
|
const defaultHeader = {
|
||||||
constructor(props) {
|
headerStyle: {
|
||||||
super(props);
|
backgroundColor: HEADER_BACKGROUND
|
||||||
initializePushNotifications();
|
},
|
||||||
|
headerTitleStyle: {
|
||||||
|
color: HEADER_TITLE
|
||||||
|
},
|
||||||
|
headerBackTitle: null,
|
||||||
|
headerTintColor: HEADER_BACK
|
||||||
|
};
|
||||||
|
|
||||||
Navigation.events().registerAppLaunchedListener(() => {
|
// Outside
|
||||||
Navigation.setDefaultOptions({
|
const OutsideStack = createStackNavigator({
|
||||||
...DEFAULT_HEADER,
|
OnboardingView: {
|
||||||
sideMenu: {
|
screen: OnboardingView,
|
||||||
left: {
|
header: null
|
||||||
enabled: false
|
},
|
||||||
},
|
NewServerView,
|
||||||
right: {
|
LoginSignupView,
|
||||||
enabled: false
|
LoginView,
|
||||||
}
|
ForgotPasswordView,
|
||||||
}
|
RegisterView
|
||||||
});
|
}, {
|
||||||
store.dispatch(appInit());
|
defaultNavigationOptions: defaultHeader
|
||||||
store.subscribe(this.onStoreUpdate.bind(this));
|
});
|
||||||
});
|
|
||||||
Linking
|
const LegalStack = createStackNavigator({
|
||||||
.getInitialURL()
|
LegalView,
|
||||||
.then(url => handleOpenURL({ url }))
|
TermsServiceView,
|
||||||
.catch(e => console.warn(e));
|
PrivacyPolicyView
|
||||||
Linking.addEventListener('url', handleOpenURL);
|
}, {
|
||||||
|
defaultNavigationOptions: defaultHeader
|
||||||
|
});
|
||||||
|
|
||||||
|
const OAuthStack = createStackNavigator({
|
||||||
|
OAuthView
|
||||||
|
}, {
|
||||||
|
defaultNavigationOptions: defaultHeader
|
||||||
|
});
|
||||||
|
|
||||||
|
const OutsideStackModal = createStackNavigator({
|
||||||
|
OutsideStack,
|
||||||
|
LegalStack,
|
||||||
|
OAuthStack
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mode: 'modal',
|
||||||
|
headerMode: 'none'
|
||||||
|
});
|
||||||
|
|
||||||
|
// Inside
|
||||||
|
const ChatsStack = createStackNavigator({
|
||||||
|
RoomsListView,
|
||||||
|
RoomView,
|
||||||
|
RoomActionsView,
|
||||||
|
RoomInfoView,
|
||||||
|
RoomInfoEditView,
|
||||||
|
RoomMembersView,
|
||||||
|
RoomFilesView,
|
||||||
|
MentionedMessagesView,
|
||||||
|
StarredMessagesView,
|
||||||
|
SearchMessagesView,
|
||||||
|
PinnedMessagesView,
|
||||||
|
SelectedUsersView
|
||||||
|
}, {
|
||||||
|
defaultNavigationOptions: defaultHeader
|
||||||
|
});
|
||||||
|
|
||||||
|
const ProfileStack = createStackNavigator({
|
||||||
|
ProfileView
|
||||||
|
}, {
|
||||||
|
defaultNavigationOptions: defaultHeader
|
||||||
|
});
|
||||||
|
|
||||||
|
const SettingsStack = createStackNavigator({
|
||||||
|
SettingsView
|
||||||
|
}, {
|
||||||
|
defaultNavigationOptions: defaultHeader
|
||||||
|
});
|
||||||
|
|
||||||
|
const ChatsDrawer = createDrawerNavigator({
|
||||||
|
ChatsStack,
|
||||||
|
ProfileStack,
|
||||||
|
SettingsStack
|
||||||
|
}, {
|
||||||
|
contentComponent: Sidebar
|
||||||
|
});
|
||||||
|
|
||||||
|
const NewMessageStack = createStackNavigator({
|
||||||
|
NewMessageView,
|
||||||
|
SelectedUsersViewCreateChannel: SelectedUsersView,
|
||||||
|
CreateChannelView
|
||||||
|
}, {
|
||||||
|
defaultNavigationOptions: defaultHeader
|
||||||
|
});
|
||||||
|
|
||||||
|
const InsideStackModal = createStackNavigator({
|
||||||
|
Main: ChatsDrawer,
|
||||||
|
NewMessageStack
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mode: 'modal',
|
||||||
|
headerMode: 'none'
|
||||||
|
});
|
||||||
|
|
||||||
|
const SetUsernameStack = createStackNavigator({
|
||||||
|
SetUsernameView
|
||||||
|
});
|
||||||
|
|
||||||
|
const App = createAppContainer(createSwitchNavigator(
|
||||||
|
{
|
||||||
|
OutsideStack: OutsideStackModal,
|
||||||
|
InsideStack: InsideStackModal,
|
||||||
|
AuthLoading: AuthLoadingView,
|
||||||
|
SetUsernameStack
|
||||||
|
},
|
||||||
|
{
|
||||||
|
initialRouteName: 'AuthLoading'
|
||||||
}
|
}
|
||||||
|
));
|
||||||
|
|
||||||
onStoreUpdate = () => {
|
export default () => (
|
||||||
const { root } = store.getState().app;
|
<Provider store={store}>
|
||||||
|
<App
|
||||||
if (this.currentRoot !== root) {
|
ref={(navigatorRef) => {
|
||||||
this.currentRoot = root;
|
Navigation.setTopLevelNavigator(navigatorRef);
|
||||||
if (root === 'outside') {
|
}}
|
||||||
startNotLogged();
|
/>
|
||||||
} else if (root === 'inside') {
|
</Provider>
|
||||||
startLogged();
|
);
|
||||||
} else if (root === 'setUsername') {
|
|
||||||
startSetUsername();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setDeviceToken(deviceToken) {
|
|
||||||
this.deviceToken = deviceToken;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -9,36 +9,3 @@ const CustomIcon = createIconSetFromIcoMoon(
|
||||||
);
|
);
|
||||||
|
|
||||||
export { CustomIcon };
|
export { CustomIcon };
|
||||||
|
|
||||||
// icon name from provider: [ size of the uri, icon provider, name to be used later ]
|
|
||||||
const icons = {
|
|
||||||
'Star-filled': [25, CustomIcon, 'star'],
|
|
||||||
star: [25, CustomIcon, 'starOutline'],
|
|
||||||
menu: [25, CustomIcon, 'more'],
|
|
||||||
edit: [25, CustomIcon, 'edit'],
|
|
||||||
cross: [25, CustomIcon, 'close'],
|
|
||||||
customize: [25, CustomIcon, 'settings'],
|
|
||||||
magnifier: [25, CustomIcon, 'search'],
|
|
||||||
'edit-rounded': [25, CustomIcon, 'new_channel']
|
|
||||||
};
|
|
||||||
|
|
||||||
class Icons {
|
|
||||||
constructor() {
|
|
||||||
this.icons = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
async configure() {
|
|
||||||
const promises = Object.keys(icons).map((icon) => {
|
|
||||||
const Provider = icons[icon][1];
|
|
||||||
return Provider.getImageSource(icon, icons[icon][0], '#FFF');
|
|
||||||
});
|
|
||||||
const sources = await Promise.all(promises);
|
|
||||||
Object.keys(icons).forEach((icon, i) => (this.icons[icons[icon][2]] = sources[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
getSource(icon) {
|
|
||||||
return this.icons[icon];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default new Icons();
|
|
||||||
|
|
|
@ -1,260 +1,21 @@
|
||||||
import { Navigation } from 'react-native-navigation';
|
import { NavigationActions } from 'react-navigation';
|
||||||
import { Provider } from 'react-redux';
|
|
||||||
import { gestureHandlerRootHOC } from 'react-native-gesture-handler';
|
|
||||||
|
|
||||||
import store from './createStore';
|
let _navigator;
|
||||||
import debounce from '../utils/debounce';
|
|
||||||
|
|
||||||
const DRAWER_ID = 'SidebarView';
|
function setTopLevelNavigator(navigatorRef) {
|
||||||
|
_navigator = navigatorRef;
|
||||||
class NavigationManager {
|
|
||||||
constructor() {
|
|
||||||
this.views = {
|
|
||||||
OnboardingView: {
|
|
||||||
name: 'OnboardingView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/OnboardingView').default
|
|
||||||
},
|
|
||||||
ProfileView: {
|
|
||||||
name: 'ProfileView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/ProfileView').default
|
|
||||||
},
|
|
||||||
RoomsListHeaderView: {
|
|
||||||
name: 'RoomsListHeaderView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/RoomsListView/Header').default
|
|
||||||
},
|
|
||||||
RoomsListView: {
|
|
||||||
name: 'RoomsListView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/RoomsListView').default
|
|
||||||
},
|
|
||||||
RoomView: {
|
|
||||||
name: 'RoomView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/RoomView').default
|
|
||||||
},
|
|
||||||
RoomHeaderView: {
|
|
||||||
name: 'RoomHeaderView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/RoomView/Header').default
|
|
||||||
},
|
|
||||||
SettingsView: {
|
|
||||||
name: 'SettingsView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/SettingsView').default
|
|
||||||
},
|
|
||||||
SidebarView: {
|
|
||||||
name: 'SidebarView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/SidebarView').default
|
|
||||||
},
|
|
||||||
NewServerView: {
|
|
||||||
name: 'NewServerView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/NewServerView').default
|
|
||||||
},
|
|
||||||
CreateChannelView: {
|
|
||||||
name: 'CreateChannelView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/CreateChannelView').default
|
|
||||||
},
|
|
||||||
ForgotPasswordView: {
|
|
||||||
name: 'ForgotPasswordView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/ForgotPasswordView').default
|
|
||||||
},
|
|
||||||
LegalView: {
|
|
||||||
name: 'LegalView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/LegalView').default
|
|
||||||
},
|
|
||||||
LoginSignupView: {
|
|
||||||
name: 'LoginSignupView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/LoginSignupView').default
|
|
||||||
},
|
|
||||||
LoginView: {
|
|
||||||
name: 'LoginView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/LoginView').default
|
|
||||||
},
|
|
||||||
NewMessageView: {
|
|
||||||
name: 'NewMessageView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/NewMessageView').default
|
|
||||||
},
|
|
||||||
OAuthView: {
|
|
||||||
name: 'OAuthView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/OAuthView').default
|
|
||||||
},
|
|
||||||
PrivacyPolicyView: {
|
|
||||||
name: 'PrivacyPolicyView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/PrivacyPolicyView').default
|
|
||||||
},
|
|
||||||
RegisterView: {
|
|
||||||
name: 'RegisterView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/RegisterView').default
|
|
||||||
},
|
|
||||||
SelectedUsersView: {
|
|
||||||
name: 'SelectedUsersView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/SelectedUsersView').default
|
|
||||||
},
|
|
||||||
SetUsernameView: {
|
|
||||||
name: 'SetUsernameView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/SetUsernameView').default
|
|
||||||
},
|
|
||||||
TermsServiceView: {
|
|
||||||
name: 'TermsServiceView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/TermsServiceView').default
|
|
||||||
},
|
|
||||||
MentionedMessagesView: {
|
|
||||||
name: 'MentionedMessagesView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/MentionedMessagesView').default
|
|
||||||
},
|
|
||||||
PinnedMessagesView: {
|
|
||||||
name: 'PinnedMessagesView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/PinnedMessagesView').default
|
|
||||||
},
|
|
||||||
RoomActionsView: {
|
|
||||||
name: 'RoomActionsView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/RoomActionsView').default
|
|
||||||
},
|
|
||||||
RoomFilesView: {
|
|
||||||
name: 'RoomFilesView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/RoomFilesView').default
|
|
||||||
},
|
|
||||||
RoomInfoEditView: {
|
|
||||||
name: 'RoomInfoEditView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/RoomInfoEditView').default
|
|
||||||
},
|
|
||||||
RoomInfoView: {
|
|
||||||
name: 'RoomInfoView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/RoomInfoView').default
|
|
||||||
},
|
|
||||||
RoomMembersView: {
|
|
||||||
name: 'RoomMembersView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/RoomMembersView').default
|
|
||||||
},
|
|
||||||
SearchMessagesView: {
|
|
||||||
name: 'SearchMessagesView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/SearchMessagesView').default
|
|
||||||
},
|
|
||||||
SnippetedMessagesView: {
|
|
||||||
name: 'SnippetedMessagesView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/SnippetedMessagesView').default
|
|
||||||
},
|
|
||||||
StarredMessagesView: {
|
|
||||||
name: 'StarredMessagesView',
|
|
||||||
loaded: false,
|
|
||||||
require: () => require('../views/StarredMessagesView').default
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.isDrawerVisible = false;
|
|
||||||
|
|
||||||
Navigation.events().registerComponentDidAppearListener(({ componentId }) => {
|
|
||||||
if (componentId === DRAWER_ID) {
|
|
||||||
this.isDrawerVisible = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Navigation.events().registerComponentDidDisappearListener(({ componentId }) => {
|
|
||||||
if (componentId === DRAWER_ID) {
|
|
||||||
this.isDrawerVisible = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
handleComponentName = (componentName) => {
|
|
||||||
if (!componentName) {
|
|
||||||
return console.error('componentName not found');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
loadView = (componentName) => {
|
|
||||||
const view = this.views[componentName];
|
|
||||||
if (!view) {
|
|
||||||
return console.error('view not found');
|
|
||||||
}
|
|
||||||
if (!view.loaded) {
|
|
||||||
Navigation.registerComponentWithRedux(view.name, () => gestureHandlerRootHOC(view.require()), Provider, store);
|
|
||||||
view.loaded = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
push = debounce((...args) => {
|
|
||||||
let componentName;
|
|
||||||
try {
|
|
||||||
componentName = args[1].component.name;
|
|
||||||
} catch (error) {
|
|
||||||
return console.error(error);
|
|
||||||
}
|
|
||||||
this.handleComponentName(componentName);
|
|
||||||
this.loadView(componentName);
|
|
||||||
Navigation.push(...args);
|
|
||||||
}, 300, true)
|
|
||||||
|
|
||||||
showModal = debounce((...args) => {
|
|
||||||
let componentName;
|
|
||||||
try {
|
|
||||||
componentName = args[0].stack.children[0].component.name;
|
|
||||||
} catch (error) {
|
|
||||||
return console.error(error);
|
|
||||||
}
|
|
||||||
this.handleComponentName(componentName);
|
|
||||||
this.loadView(componentName);
|
|
||||||
Navigation.showModal(...args);
|
|
||||||
}, 300, true)
|
|
||||||
|
|
||||||
pop = (...args) => Navigation.pop(...args);
|
|
||||||
|
|
||||||
popToRoot = (...args) => Navigation.popToRoot(...args);
|
|
||||||
|
|
||||||
dismissModal = (...args) => Navigation.dismissModal(...args);
|
|
||||||
|
|
||||||
dismissAllModals = (...args) => Navigation.dismissAllModals(...args);
|
|
||||||
|
|
||||||
events = (...args) => Navigation.events(...args);
|
|
||||||
|
|
||||||
mergeOptions = (...args) => Navigation.mergeOptions(...args);
|
|
||||||
|
|
||||||
setDefaultOptions = (...args) => Navigation.setDefaultOptions(...args);
|
|
||||||
|
|
||||||
setRoot = (...args) => Navigation.setRoot(...args);
|
|
||||||
|
|
||||||
setStackRoot = (...args) => Navigation.setStackRoot(...args);
|
|
||||||
|
|
||||||
toggleDrawer = () => {
|
|
||||||
try {
|
|
||||||
const visibility = !this.isDrawerVisible;
|
|
||||||
Navigation.mergeOptions(DRAWER_ID, {
|
|
||||||
sideMenu: {
|
|
||||||
left: {
|
|
||||||
visible: visibility
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.isDrawerVisible = visibility;
|
|
||||||
} catch (error) {
|
|
||||||
console.warn(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default new NavigationManager();
|
function navigate(routeName, params) {
|
||||||
|
_navigator.dispatch(
|
||||||
|
NavigationActions.navigate({
|
||||||
|
routeName,
|
||||||
|
params
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
navigate,
|
||||||
|
setTopLevelNavigator
|
||||||
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { createStore as reduxCreateStore, applyMiddleware, compose } from 'redux';
|
import { createStore as reduxCreateStore, applyMiddleware, compose } from 'redux';
|
||||||
import Reactotron from 'reactotron-react-native' ; // eslint-disable-line
|
import Reactotron from 'reactotron-react-native';
|
||||||
import createSagaMiddleware from 'redux-saga';
|
import createSagaMiddleware from 'redux-saga';
|
||||||
import applyAppStateListener from 'redux-enhancer-react-native-appstate';
|
import applyAppStateListener from 'redux-enhancer-react-native-appstate';
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@ import {
|
||||||
} from '../actions/login';
|
} from '../actions/login';
|
||||||
import { disconnect, connectSuccess, connectRequest } from '../actions/connect';
|
import { disconnect, connectSuccess, connectRequest } from '../actions/connect';
|
||||||
import { setActiveUser } from '../actions/activeUsers';
|
import { setActiveUser } from '../actions/activeUsers';
|
||||||
import { snippetedMessagesReceived } from '../actions/snippetedMessages';
|
|
||||||
import { someoneTyping, roomMessageReceived } from '../actions/room';
|
import { someoneTyping, roomMessageReceived } from '../actions/room';
|
||||||
import { setRoles } from '../actions/roles';
|
import { setRoles } from '../actions/roles';
|
||||||
|
|
||||||
|
@ -213,27 +212,6 @@ const RocketChat = {
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this.sdk.onStreamData('rocketchat_snippeted_message', protectedFunction((ddpMessage) => {
|
|
||||||
if (ddpMessage.msg === 'added') {
|
|
||||||
this.snippetedMessages = this.snippetedMessages || [];
|
|
||||||
|
|
||||||
if (this.snippetedMessagesTimer) {
|
|
||||||
clearTimeout(this.snippetedMessagesTimer);
|
|
||||||
this.snippetedMessagesTimer = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.snippetedMessagesTimer = setTimeout(() => {
|
|
||||||
reduxStore.dispatch(snippetedMessagesReceived(this.snippetedMessages));
|
|
||||||
this.snippetedMessagesTimer = null;
|
|
||||||
return this.snippetedMessages = [];
|
|
||||||
}, 1000);
|
|
||||||
const message = ddpMessage.fields;
|
|
||||||
message._id = ddpMessage.id;
|
|
||||||
const snippetedMessage = _buildMessage(message);
|
|
||||||
this.snippetedMessages = [...this.snippetedMessages, snippetedMessage];
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
this.sdk.onStreamData('rocketchat_roles', protectedFunction((ddpMessage) => {
|
this.sdk.onStreamData('rocketchat_roles', protectedFunction((ddpMessage) => {
|
||||||
this.roles = this.roles || {};
|
this.roles = this.roles || {};
|
||||||
|
|
||||||
|
|
|
@ -110,7 +110,7 @@ const renderNumber = (unread, userMentions) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const attrs = ['name', 'unread', 'userMentions', 'alert', 'showLastMessage', 'type'];
|
const attrs = ['name', 'unread', 'userMentions', 'StoreLastMessage', 'alert', 'type'];
|
||||||
@connect(state => ({
|
@connect(state => ({
|
||||||
user: {
|
user: {
|
||||||
id: state.login.user && state.login.user.id,
|
id: state.login.user && state.login.user.id,
|
||||||
|
@ -128,7 +128,6 @@ export default class RoomItem extends React.Component {
|
||||||
StoreLastMessage: PropTypes.bool,
|
StoreLastMessage: PropTypes.bool,
|
||||||
_updatedAt: PropTypes.string,
|
_updatedAt: PropTypes.string,
|
||||||
lastMessage: PropTypes.object,
|
lastMessage: PropTypes.object,
|
||||||
showLastMessage: PropTypes.bool,
|
|
||||||
favorite: PropTypes.bool,
|
favorite: PropTypes.bool,
|
||||||
alert: PropTypes.bool,
|
alert: PropTypes.bool,
|
||||||
unread: PropTypes.number,
|
unread: PropTypes.number,
|
||||||
|
@ -146,7 +145,6 @@ export default class RoomItem extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
showLastMessage: true,
|
|
||||||
avatarSize: 48
|
avatarSize: 48
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,10 +172,10 @@ export default class RoomItem extends React.Component {
|
||||||
|
|
||||||
get lastMessage() {
|
get lastMessage() {
|
||||||
const {
|
const {
|
||||||
lastMessage, type, showLastMessage, StoreLastMessage, user
|
lastMessage, type, StoreLastMessage, user
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
if (!StoreLastMessage || !showLastMessage) {
|
if (!StoreLastMessage) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
if (!lastMessage) {
|
if (!lastMessage) {
|
||||||
|
|
|
@ -24,6 +24,7 @@ class PushNotification {
|
||||||
configure(params) {
|
configure(params) {
|
||||||
this.onRegister = params.onRegister;
|
this.onRegister = params.onRegister;
|
||||||
this.onNotification = params.onNotification;
|
this.onNotification = params.onNotification;
|
||||||
|
NotificationsAndroid.refreshToken();
|
||||||
|
|
||||||
PendingNotifications.getInitialNotification()
|
PendingNotifications.getInitialNotification()
|
||||||
.then((notification) => {
|
.then((notification) => {
|
||||||
|
|
|
@ -3,7 +3,6 @@ import { APP } from '../actions/actionsTypes';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
root: null,
|
root: null,
|
||||||
stackRoot: 'RoomsListView',
|
|
||||||
ready: false,
|
ready: false,
|
||||||
inactive: false,
|
inactive: false,
|
||||||
background: false
|
background: false
|
||||||
|
@ -37,11 +36,6 @@ export default function app(state = initialState, action) {
|
||||||
...state,
|
...state,
|
||||||
root: action.root
|
root: action.root
|
||||||
};
|
};
|
||||||
case APP.SET_STACK_ROOT:
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
stackRoot: action.stackRoot
|
|
||||||
};
|
|
||||||
case APP.INIT:
|
case APP.INIT:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
|
|
@ -12,7 +12,6 @@ import app from './app';
|
||||||
import customEmojis from './customEmojis';
|
import customEmojis from './customEmojis';
|
||||||
import activeUsers from './activeUsers';
|
import activeUsers from './activeUsers';
|
||||||
import roles from './roles';
|
import roles from './roles';
|
||||||
import snippetedMessages from './snippetedMessages';
|
|
||||||
import sortPreferences from './sortPreferences';
|
import sortPreferences from './sortPreferences';
|
||||||
|
|
||||||
export default combineReducers({
|
export default combineReducers({
|
||||||
|
@ -29,6 +28,5 @@ export default combineReducers({
|
||||||
customEmojis,
|
customEmojis,
|
||||||
activeUsers,
|
activeUsers,
|
||||||
roles,
|
roles,
|
||||||
snippetedMessages,
|
|
||||||
sortPreferences
|
sortPreferences
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
import { SNIPPETED_MESSAGES } from '../actions/actionsTypes';
|
|
||||||
|
|
||||||
const initialState = {
|
|
||||||
messages: [],
|
|
||||||
ready: false
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function server(state = initialState, action) {
|
|
||||||
switch (action.type) {
|
|
||||||
case SNIPPETED_MESSAGES.OPEN:
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
ready: false
|
|
||||||
};
|
|
||||||
case SNIPPETED_MESSAGES.READY:
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
ready: true
|
|
||||||
};
|
|
||||||
case SNIPPETED_MESSAGES.MESSAGES_RECEIVED:
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
messages: [...state.messages, ...action.messages]
|
|
||||||
};
|
|
||||||
case SNIPPETED_MESSAGES.CLOSE:
|
|
||||||
return initialState;
|
|
||||||
default:
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,7 +6,6 @@ import {
|
||||||
|
|
||||||
import Navigation from '../lib/Navigation';
|
import Navigation from '../lib/Navigation';
|
||||||
import * as types from '../actions/actionsTypes';
|
import * as types from '../actions/actionsTypes';
|
||||||
import { appStart, setStackRoot } from '../actions';
|
|
||||||
import { selectServerRequest } from '../actions/server';
|
import { selectServerRequest } from '../actions/server';
|
||||||
import database from '../lib/realm';
|
import database from '../lib/realm';
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
|
@ -16,40 +15,12 @@ const roomTypes = {
|
||||||
channel: 'c', direct: 'd', group: 'p'
|
channel: 'c', direct: 'd', group: 'p'
|
||||||
};
|
};
|
||||||
|
|
||||||
const navigate = function* navigate({ params, sameServer = true }) {
|
const navigate = function* navigate({ params }) {
|
||||||
if (!sameServer) {
|
|
||||||
yield put(appStart('inside'));
|
|
||||||
}
|
|
||||||
if (params.rid) {
|
if (params.rid) {
|
||||||
const canOpenRoom = yield RocketChat.canOpenRoom(params);
|
const canOpenRoom = yield RocketChat.canOpenRoom(params);
|
||||||
if (canOpenRoom) {
|
if (canOpenRoom) {
|
||||||
const stack = 'RoomsListView';
|
|
||||||
const stackRoot = yield select(state => state.app.stackRoot);
|
|
||||||
|
|
||||||
// Make sure current stack is RoomsListView before navigate to RoomView
|
|
||||||
if (stackRoot !== stack) {
|
|
||||||
yield Navigation.setStackRoot('AppRoot', {
|
|
||||||
component: {
|
|
||||||
id: stack,
|
|
||||||
name: stack
|
|
||||||
}
|
|
||||||
});
|
|
||||||
yield put(setStackRoot(stack));
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
yield Navigation.popToRoot(stack);
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
const [type, name] = params.path.split('/');
|
const [type, name] = params.path.split('/');
|
||||||
Navigation.push(stack, {
|
Navigation.navigate('RoomView', { rid: params.rid, name, t: roomTypes[type] });
|
||||||
component: {
|
|
||||||
name: 'RoomView',
|
|
||||||
passProps: {
|
|
||||||
rid: params.rid, name, t: roomTypes[type]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -100,9 +71,13 @@ const handleOpen = function* handleOpen({ params }) {
|
||||||
const servers = yield database.databases.serversDB.objects('servers').filtered('id = $0', host); // TODO: need better test
|
const servers = yield database.databases.serversDB.objects('servers').filtered('id = $0', host); // TODO: need better test
|
||||||
if (servers.length && user) {
|
if (servers.length && user) {
|
||||||
yield put(selectServerRequest(host));
|
yield put(selectServerRequest(host));
|
||||||
yield navigate({ params, sameServer: false });
|
yield race({
|
||||||
|
typing: take(types.SERVER.SELECT_SUCCESS),
|
||||||
|
timeout: delay(3000)
|
||||||
|
});
|
||||||
|
yield navigate({ params });
|
||||||
} else {
|
} else {
|
||||||
yield put(appStart('outside'));
|
Navigation.navigate('OnboardingView', { previousServer: server });
|
||||||
yield delay(1000);
|
yield delay(1000);
|
||||||
EventEmitter.emit('NewServer', { server: host });
|
EventEmitter.emit('NewServer', { server: host });
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ import selectServer from './selectServer';
|
||||||
import createChannel from './createChannel';
|
import createChannel from './createChannel';
|
||||||
import init from './init';
|
import init from './init';
|
||||||
import state from './state';
|
import state from './state';
|
||||||
import snippetedMessages from './snippetedMessages';
|
|
||||||
import deepLinking from './deepLinking';
|
import deepLinking from './deepLinking';
|
||||||
|
|
||||||
const root = function* root() {
|
const root = function* root() {
|
||||||
|
@ -20,7 +19,6 @@ const root = function* root() {
|
||||||
messages(),
|
messages(),
|
||||||
selectServer(),
|
selectServer(),
|
||||||
state(),
|
state(),
|
||||||
snippetedMessages(),
|
|
||||||
deepLinking()
|
deepLinking()
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { AsyncStorage } from 'react-native';
|
import { AsyncStorage } from 'react-native';
|
||||||
import { put, takeLatest, all } from 'redux-saga/effects';
|
import { put, takeLatest, all } from 'redux-saga/effects';
|
||||||
|
import SplashScreen from 'react-native-splash-screen';
|
||||||
|
|
||||||
import * as actions from '../actions';
|
import * as actions from '../actions';
|
||||||
import { selectServerRequest } from '../actions/server';
|
import { selectServerRequest } from '../actions/server';
|
||||||
|
@ -7,6 +8,7 @@ import { setAllPreferences } from '../actions/sortPreferences';
|
||||||
import { APP } from '../actions/actionsTypes';
|
import { APP } from '../actions/actionsTypes';
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
import log from '../utils/log';
|
import log from '../utils/log';
|
||||||
|
import Navigation from '../lib/Navigation';
|
||||||
|
|
||||||
const restore = function* restore() {
|
const restore = function* restore() {
|
||||||
try {
|
try {
|
||||||
|
@ -34,7 +36,19 @@ const restore = function* restore() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const start = function* start({ root }) {
|
||||||
|
if (root === 'inside') {
|
||||||
|
yield Navigation.navigate('InsideStack');
|
||||||
|
} else if (root === 'setUsername') {
|
||||||
|
yield Navigation.navigate('SetUsernameView');
|
||||||
|
} else if (root === 'outside') {
|
||||||
|
yield Navigation.navigate('OutsideStack');
|
||||||
|
}
|
||||||
|
SplashScreen.hide();
|
||||||
|
};
|
||||||
|
|
||||||
const root = function* root() {
|
const root = function* root() {
|
||||||
yield takeLatest(APP.INIT, restore);
|
yield takeLatest(APP.INIT, restore);
|
||||||
|
yield takeLatest(APP.START, start);
|
||||||
};
|
};
|
||||||
export default root;
|
export default root;
|
||||||
|
|
|
@ -3,7 +3,6 @@ import {
|
||||||
put, call, takeLatest, select
|
put, call, takeLatest, select
|
||||||
} from 'redux-saga/effects';
|
} from 'redux-saga/effects';
|
||||||
|
|
||||||
import Navigation from '../lib/Navigation';
|
|
||||||
import * as types from '../actions/actionsTypes';
|
import * as types from '../actions/actionsTypes';
|
||||||
import { appStart } from '../actions';
|
import { appStart } from '../actions';
|
||||||
import { serverFinishAdd, selectServerRequest } from '../actions/server';
|
import { serverFinishAdd, selectServerRequest } from '../actions/server';
|
||||||
|
@ -50,7 +49,7 @@ const handleLoginSuccess = function* handleLoginSuccess({ user }) {
|
||||||
yield put(appStart('setUsername'));
|
yield put(appStart('setUsername'));
|
||||||
} else if (adding) {
|
} else if (adding) {
|
||||||
yield put(serverFinishAdd());
|
yield put(serverFinishAdd());
|
||||||
yield Navigation.dismissAllModals();
|
yield put(appStart('inside'));
|
||||||
} else {
|
} else {
|
||||||
yield put(appStart('inside'));
|
yield put(appStart('inside'));
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,16 +74,9 @@ const handleTogglePinRequest = function* handleTogglePinRequest({ message }) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const goRoom = function* goRoom({ rid, name }) {
|
const goRoom = function goRoom({ rid, name }) {
|
||||||
yield Navigation.popToRoot('RoomsListView');
|
Navigation.navigate('RoomsListView');
|
||||||
Navigation.push('RoomsListView', {
|
Navigation.navigate('RoomView', { rid, name, t: 'd' });
|
||||||
component: {
|
|
||||||
name: 'RoomView',
|
|
||||||
passProps: {
|
|
||||||
rid, name, t: 'd'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleReplyBroadcast = function* handleReplyBroadcast({ message }) {
|
const handleReplyBroadcast = function* handleReplyBroadcast({ message }) {
|
||||||
|
|
|
@ -124,7 +124,7 @@ const handleLeaveRoom = function* handleLeaveRoom({ rid, t }) {
|
||||||
try {
|
try {
|
||||||
const result = yield RocketChat.leaveRoom(rid, t);
|
const result = yield RocketChat.leaveRoom(rid, t);
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
yield Navigation.popToRoot('RoomsListView');
|
yield Navigation.navigate('RoomsListView');
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.data && e.data.errorType === 'error-you-are-last-owner') {
|
if (e.data && e.data.errorType === 'error-you-are-last-owner') {
|
||||||
|
@ -139,7 +139,7 @@ const handleEraseRoom = function* handleEraseRoom({ rid, t }) {
|
||||||
try {
|
try {
|
||||||
const result = yield RocketChat.eraseRoom(rid, t);
|
const result = yield RocketChat.eraseRoom(rid, t);
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
yield Navigation.popToRoot('RoomsListView');
|
yield Navigation.navigate('RoomsListView');
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Alert.alert(I18n.t('Oops'), I18n.t('There_was_an_error_while_action', { action: I18n.t('erasing_room') }));
|
Alert.alert(I18n.t('Oops'), I18n.t('There_was_an_error_while_action', { action: I18n.t('erasing_room') }));
|
||||||
|
|
|
@ -53,17 +53,9 @@ const handleServerRequest = function* handleServerRequest({ server }) {
|
||||||
|
|
||||||
const loginServicesLength = yield RocketChat.getLoginServices(server);
|
const loginServicesLength = yield RocketChat.getLoginServices(server);
|
||||||
if (loginServicesLength === 0) {
|
if (loginServicesLength === 0) {
|
||||||
yield Navigation.push('NewServerView', {
|
Navigation.navigate('LoginView');
|
||||||
component: {
|
|
||||||
name: 'LoginView'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
yield Navigation.push('NewServerView', {
|
Navigation.navigate('LoginSignupView');
|
||||||
component: {
|
|
||||||
name: 'LoginSignupView'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
database.databases.serversDB.write(() => {
|
database.databases.serversDB.write(() => {
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
import { put, takeLatest } from 'redux-saga/effects';
|
|
||||||
|
|
||||||
import * as types from '../actions/actionsTypes';
|
|
||||||
import RocketChat from '../lib/rocketchat';
|
|
||||||
import { readySnippetedMessages } from '../actions/snippetedMessages';
|
|
||||||
import log from '../utils/log';
|
|
||||||
|
|
||||||
let sub;
|
|
||||||
let newSub;
|
|
||||||
|
|
||||||
const openSnippetedMessagesRoom = function* openSnippetedMessagesRoom({ rid, limit }) {
|
|
||||||
try {
|
|
||||||
newSub = yield RocketChat.subscribe('snippetedMessages', rid, limit);
|
|
||||||
yield put(readySnippetedMessages());
|
|
||||||
if (sub) {
|
|
||||||
sub.unsubscribe().catch(err => console.warn(err));
|
|
||||||
}
|
|
||||||
sub = newSub;
|
|
||||||
} catch (e) {
|
|
||||||
log('openSnippetedMessagesRoom', e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const closeSnippetedMessagesRoom = function* closeSnippetedMessagesRoom() {
|
|
||||||
try {
|
|
||||||
if (sub) {
|
|
||||||
yield sub.unsubscribe();
|
|
||||||
}
|
|
||||||
if (newSub) {
|
|
||||||
yield newSub.unsubscribe();
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
log('closeSnippetedMessagesRoom', e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const root = function* root() {
|
|
||||||
yield takeLatest(types.SNIPPETED_MESSAGES.OPEN, openSnippetedMessagesRoom);
|
|
||||||
yield takeLatest(types.SNIPPETED_MESSAGES.CLOSE, closeSnippetedMessagesRoom);
|
|
||||||
};
|
|
||||||
export default root;
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { StyleSheet, Image } from 'react-native';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import StatusBar from '../containers/StatusBar';
|
||||||
|
import { isAndroid } from '../utils/deviceInfo';
|
||||||
|
import { appInit as appInitAction } from '../actions';
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
image: {
|
||||||
|
width: '100%',
|
||||||
|
height: '100%'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
@connect(null, dispatch => ({
|
||||||
|
appInit: () => dispatch(appInitAction())
|
||||||
|
}))
|
||||||
|
export default class Loading extends React.PureComponent {
|
||||||
|
static propTypes = {
|
||||||
|
appInit: PropTypes.func
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
props.appInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<StatusBar />
|
||||||
|
{isAndroid ? <Image source={{ uri: 'launch_screen' }} style={styles.image} /> : null}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,10 +4,9 @@ import PropTypes from 'prop-types';
|
||||||
import {
|
import {
|
||||||
View, Text, Switch, ScrollView, TextInput, StyleSheet, FlatList
|
View, Text, Switch, ScrollView, TextInput, StyleSheet, FlatList
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import SafeAreaView from 'react-native-safe-area-view';
|
import { SafeAreaView } from 'react-navigation';
|
||||||
import equal from 'deep-equal';
|
import equal from 'deep-equal';
|
||||||
|
|
||||||
import Navigation from '../lib/Navigation';
|
|
||||||
import Loading from '../containers/Loading';
|
import Loading from '../containers/Loading';
|
||||||
import LoggedView from './View';
|
import LoggedView from './View';
|
||||||
import { createChannelRequest as createChannelRequestAction } from '../actions/createChannel';
|
import { createChannelRequest as createChannelRequestAction } from '../actions/createChannel';
|
||||||
|
@ -19,6 +18,8 @@ import I18n from '../i18n';
|
||||||
import UserItem from '../presentation/UserItem';
|
import UserItem from '../presentation/UserItem';
|
||||||
import { showErrorAlert } from '../utils/info';
|
import { showErrorAlert } from '../utils/info';
|
||||||
import { isAndroid } from '../utils/deviceInfo';
|
import { isAndroid } from '../utils/deviceInfo';
|
||||||
|
import { CustomHeaderButtons, Item } from '../containers/HeaderButton';
|
||||||
|
import StatusBar from '../containers/StatusBar';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
|
@ -91,18 +92,25 @@ const styles = StyleSheet.create({
|
||||||
}))
|
}))
|
||||||
/** @extends React.Component */
|
/** @extends React.Component */
|
||||||
export default class CreateChannelView extends LoggedView {
|
export default class CreateChannelView extends LoggedView {
|
||||||
static options() {
|
static navigationOptions = ({ navigation }) => {
|
||||||
|
const submit = navigation.getParam('submit', () => {});
|
||||||
|
const showSubmit = navigation.getParam('showSubmit');
|
||||||
return {
|
return {
|
||||||
topBar: {
|
title: I18n.t('Create_Channel'),
|
||||||
title: {
|
headerRight: (
|
||||||
text: I18n.t('Create_Channel')
|
showSubmit
|
||||||
}
|
? (
|
||||||
}
|
<CustomHeaderButtons>
|
||||||
|
<Item title={I18n.t('Create')} onPress={submit} testID='create-channel-submit' />
|
||||||
|
</CustomHeaderButtons>
|
||||||
|
)
|
||||||
|
: null
|
||||||
|
)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
componentId: PropTypes.string,
|
navigation: PropTypes.object,
|
||||||
baseUrl: PropTypes.string,
|
baseUrl: PropTypes.string,
|
||||||
create: PropTypes.func.isRequired,
|
create: PropTypes.func.isRequired,
|
||||||
removeUser: PropTypes.func.isRequired,
|
removeUser: PropTypes.func.isRequired,
|
||||||
|
@ -125,10 +133,11 @@ export default class CreateChannelView extends LoggedView {
|
||||||
readOnly: false,
|
readOnly: false,
|
||||||
broadcast: false
|
broadcast: false
|
||||||
};
|
};
|
||||||
Navigation.events().bindComponent(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
const { navigation } = this.props;
|
||||||
|
navigation.setParams({ submit: this.submit });
|
||||||
this.timeout = setTimeout(() => {
|
this.timeout = setTimeout(() => {
|
||||||
this.channelNameRef.focus();
|
this.channelNameRef.focus();
|
||||||
}, 600);
|
}, 600);
|
||||||
|
@ -173,26 +182,18 @@ export default class CreateChannelView extends LoggedView {
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
const {
|
const {
|
||||||
isFetching, failure, error, result, componentId
|
isFetching, failure, error, result, navigation
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
if (!isFetching && isFetching !== prevProps.isFetching) {
|
if (!isFetching && isFetching !== prevProps.isFetching) {
|
||||||
setTimeout(async() => {
|
setTimeout(() => {
|
||||||
if (failure) {
|
if (failure) {
|
||||||
const msg = error.reason || I18n.t('There_was_an_error_while_action', { action: I18n.t('creating_channel') });
|
const msg = error.reason || I18n.t('There_was_an_error_while_action', { action: I18n.t('creating_channel') });
|
||||||
showErrorAlert(msg);
|
showErrorAlert(msg);
|
||||||
} else {
|
} else {
|
||||||
const { type } = this.state;
|
const { type } = this.state;
|
||||||
const { rid, name } = result;
|
const { rid, name } = result;
|
||||||
await Navigation.dismissModal(componentId);
|
navigation.navigate('RoomView', { rid, name, t: type ? 'p' : 'c' });
|
||||||
Navigation.push('RoomsListView', {
|
|
||||||
component: {
|
|
||||||
name: 'RoomView',
|
|
||||||
passProps: {
|
|
||||||
rid, name, t: type ? 'p' : 'c'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}, 300);
|
}, 300);
|
||||||
}
|
}
|
||||||
|
@ -205,30 +206,11 @@ export default class CreateChannelView extends LoggedView {
|
||||||
}
|
}
|
||||||
|
|
||||||
onChangeText = (channelName) => {
|
onChangeText = (channelName) => {
|
||||||
const { componentId } = this.props;
|
const { navigation } = this.props;
|
||||||
const rightButtons = [];
|
navigation.setParams({ showSubmit: channelName.trim().length > 0 });
|
||||||
if (channelName.trim().length > 0) {
|
|
||||||
rightButtons.push({
|
|
||||||
id: 'create',
|
|
||||||
text: 'Create',
|
|
||||||
testID: 'create-channel-submit',
|
|
||||||
color: isAndroid ? '#FFF' : undefined
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Navigation.mergeOptions(componentId, {
|
|
||||||
topBar: {
|
|
||||||
rightButtons
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.setState({ channelName });
|
this.setState({ channelName });
|
||||||
}
|
}
|
||||||
|
|
||||||
navigationButtonPressed = ({ buttonId }) => {
|
|
||||||
if (buttonId === 'create') {
|
|
||||||
this.submit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
submit = () => {
|
submit = () => {
|
||||||
const {
|
const {
|
||||||
channelName, type, readOnly, broadcast
|
channelName, type, readOnly, broadcast
|
||||||
|
@ -354,6 +336,7 @@ export default class CreateChannelView extends LoggedView {
|
||||||
contentContainerStyle={[sharedStyles.container, styles.container]}
|
contentContainerStyle={[sharedStyles.container, styles.container]}
|
||||||
keyboardVerticalOffset={128}
|
keyboardVerticalOffset={128}
|
||||||
>
|
>
|
||||||
|
<StatusBar />
|
||||||
<SafeAreaView testID='create-channel-view' style={styles.container} forceInset={{ bottom: 'never' }}>
|
<SafeAreaView testID='create-channel-view' style={styles.container} forceInset={{ bottom: 'never' }}>
|
||||||
<ScrollView {...scrollPersistTaps}>
|
<ScrollView {...scrollPersistTaps}>
|
||||||
<View style={sharedStyles.separatorVertical}>
|
<View style={sharedStyles.separatorVertical}>
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { Text, ScrollView } from 'react-native';
|
import { Text, ScrollView } from 'react-native';
|
||||||
import SafeAreaView from 'react-native-safe-area-view';
|
import { SafeAreaView } from 'react-navigation';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import Navigation from '../lib/Navigation';
|
|
||||||
import LoggedView from './View';
|
import LoggedView from './View';
|
||||||
import KeyboardView from '../presentation/KeyboardView';
|
import KeyboardView from '../presentation/KeyboardView';
|
||||||
import TextInput from '../containers/TextInput';
|
import TextInput from '../containers/TextInput';
|
||||||
|
@ -13,19 +12,20 @@ import { showErrorAlert } from '../utils/info';
|
||||||
import isValidEmail from '../utils/isValidEmail';
|
import isValidEmail from '../utils/isValidEmail';
|
||||||
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
||||||
import I18n from '../i18n';
|
import I18n from '../i18n';
|
||||||
import { DARK_HEADER } from '../constants/headerOptions';
|
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
|
import StatusBar from '../containers/StatusBar';
|
||||||
|
|
||||||
/** @extends React.Component */
|
/** @extends React.Component */
|
||||||
export default class ForgotPasswordView extends LoggedView {
|
export default class ForgotPasswordView extends LoggedView {
|
||||||
static options() {
|
static navigationOptions = ({ navigation }) => {
|
||||||
|
const title = navigation.getParam('title', 'Rocket.Chat');
|
||||||
return {
|
return {
|
||||||
...DARK_HEADER
|
title
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
componentId: PropTypes.string
|
navigation: PropTypes.object
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -81,8 +81,8 @@ export default class ForgotPasswordView extends LoggedView {
|
||||||
this.setState({ isFetching: true });
|
this.setState({ isFetching: true });
|
||||||
const result = await RocketChat.forgotPassword(email);
|
const result = await RocketChat.forgotPassword(email);
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
const { componentId } = this.props;
|
const { navigation } = this.props;
|
||||||
Navigation.pop(componentId);
|
navigation.pop();
|
||||||
showErrorAlert(I18n.t('Forgot_password_If_this_email_is_registered'), I18n.t('Alert'));
|
showErrorAlert(I18n.t('Forgot_password_If_this_email_is_registered'), I18n.t('Alert'));
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -100,6 +100,7 @@ export default class ForgotPasswordView extends LoggedView {
|
||||||
contentContainerStyle={sharedStyles.container}
|
contentContainerStyle={sharedStyles.container}
|
||||||
keyboardVerticalOffset={128}
|
keyboardVerticalOffset={128}
|
||||||
>
|
>
|
||||||
|
<StatusBar />
|
||||||
<ScrollView {...scrollPersistTaps} contentContainerStyle={sharedStyles.containerScrollView}>
|
<ScrollView {...scrollPersistTaps} contentContainerStyle={sharedStyles.containerScrollView}>
|
||||||
<SafeAreaView style={sharedStyles.container} testID='forgot-password-view' forceInset={{ bottom: 'never' }}>
|
<SafeAreaView style={sharedStyles.container} testID='forgot-password-view' forceInset={{ bottom: 'never' }}>
|
||||||
<Text style={[sharedStyles.loginTitle, sharedStyles.textBold]}>{I18n.t('Forgot_password')}</Text>
|
<Text style={[sharedStyles.loginTitle, sharedStyles.textBold]}>{I18n.t('Forgot_password')}</Text>
|
||||||
|
|
|
@ -3,18 +3,16 @@ import PropTypes from 'prop-types';
|
||||||
import {
|
import {
|
||||||
Text, ScrollView, View, StyleSheet
|
Text, ScrollView, View, StyleSheet
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import SafeAreaView from 'react-native-safe-area-view';
|
import { SafeAreaView } from 'react-navigation';
|
||||||
import { RectButton } from 'react-native-gesture-handler';
|
import { RectButton } from 'react-native-gesture-handler';
|
||||||
|
|
||||||
import Navigation from '../lib/Navigation';
|
|
||||||
import sharedStyles from './Styles';
|
import sharedStyles from './Styles';
|
||||||
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
||||||
import { isIOS, isAndroid } from '../utils/deviceInfo';
|
|
||||||
import LoggedView from './View';
|
import LoggedView from './View';
|
||||||
import I18n from '../i18n';
|
import I18n from '../i18n';
|
||||||
import { DARK_HEADER } from '../constants/headerOptions';
|
|
||||||
import Icons from '../lib/Icons';
|
|
||||||
import DisclosureIndicator from '../containers/DisclosureIndicator';
|
import DisclosureIndicator from '../containers/DisclosureIndicator';
|
||||||
|
import { CloseModalButton } from '../containers/HeaderButton';
|
||||||
|
import StatusBar from '../containers/StatusBar';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
|
@ -55,48 +53,22 @@ const Separator = () => <View style={styles.separator} />;
|
||||||
|
|
||||||
/** @extends React.Component */
|
/** @extends React.Component */
|
||||||
export default class LegalView extends LoggedView {
|
export default class LegalView extends LoggedView {
|
||||||
static options() {
|
static navigationOptions = ({ navigation }) => ({
|
||||||
return {
|
headerLeft: <CloseModalButton testID='legal-view-close' navigation={navigation} />,
|
||||||
...DARK_HEADER,
|
title: I18n.t('Legal')
|
||||||
topBar: {
|
})
|
||||||
...DARK_HEADER.topBar,
|
|
||||||
title: {
|
|
||||||
...DARK_HEADER.topBar.title,
|
|
||||||
text: I18n.t('Legal')
|
|
||||||
},
|
|
||||||
leftButtons: [{
|
|
||||||
id: 'close',
|
|
||||||
icon: isAndroid ? Icons.getSource('close') : undefined,
|
|
||||||
text: isIOS ? I18n.t('Close') : undefined,
|
|
||||||
testID: 'legal-view-close'
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
componentId: PropTypes.string
|
navigation: PropTypes.object
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super('LegalView', props);
|
super('LegalView', props);
|
||||||
Navigation.events().bindComponent(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
navigationButtonPressed = ({ buttonId }) => {
|
|
||||||
if (buttonId === 'close') {
|
|
||||||
const { componentId } = this.props;
|
|
||||||
Navigation.dismissModal(componentId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onPressItem = ({ route }) => {
|
onPressItem = ({ route }) => {
|
||||||
const { componentId } = this.props;
|
const { navigation } = this.props;
|
||||||
Navigation.push(componentId, {
|
navigation.navigate(route);
|
||||||
component: {
|
|
||||||
name: route
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderItem = ({ text, route, testID }) => (
|
renderItem = ({ text, route, testID }) => (
|
||||||
|
@ -109,6 +81,7 @@ export default class LegalView extends LoggedView {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<SafeAreaView style={styles.container} testID='legal-view' forceInset={{ bottom: 'never' }}>
|
<SafeAreaView style={styles.container} testID='legal-view' forceInset={{ bottom: 'never' }}>
|
||||||
|
<StatusBar />
|
||||||
<ScrollView {...scrollPersistTaps} contentContainerStyle={styles.scroll}>
|
<ScrollView {...scrollPersistTaps} contentContainerStyle={styles.scroll}>
|
||||||
{this.renderItem({ text: 'Terms_of_Service', route: 'TermsServiceView', testID: 'legal-terms-button' })}
|
{this.renderItem({ text: 'Terms_of_Service', route: 'TermsServiceView', testID: 'legal-terms-button' })}
|
||||||
<Separator />
|
<Separator />
|
||||||
|
|
|
@ -5,19 +5,18 @@ import {
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { Base64 } from 'js-base64';
|
import { Base64 } from 'js-base64';
|
||||||
import SafeAreaView from 'react-native-safe-area-view';
|
import { SafeAreaView } from 'react-navigation';
|
||||||
import { RectButton, BorderlessButton } from 'react-native-gesture-handler';
|
import { RectButton, BorderlessButton } from 'react-native-gesture-handler';
|
||||||
import equal from 'deep-equal';
|
import equal from 'deep-equal';
|
||||||
|
|
||||||
import Navigation from '../lib/Navigation';
|
|
||||||
import LoggedView from './View';
|
import LoggedView from './View';
|
||||||
import sharedStyles from './Styles';
|
import sharedStyles from './Styles';
|
||||||
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
||||||
import random from '../utils/random';
|
import random from '../utils/random';
|
||||||
import Button from '../containers/Button';
|
import Button from '../containers/Button';
|
||||||
import I18n from '../i18n';
|
import I18n from '../i18n';
|
||||||
import { DARK_HEADER } from '../constants/headerOptions';
|
import { LegalButton } from '../containers/HeaderButton';
|
||||||
import Icons from '../lib/Icons';
|
import StatusBar from '../containers/StatusBar';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
|
@ -96,22 +95,16 @@ const SERVICES_COLLAPSED_HEIGHT = 174;
|
||||||
}))
|
}))
|
||||||
/** @extends React.Component */
|
/** @extends React.Component */
|
||||||
export default class LoginSignupView extends LoggedView {
|
export default class LoginSignupView extends LoggedView {
|
||||||
static options() {
|
static navigationOptions = ({ navigation }) => {
|
||||||
|
const title = navigation.getParam('title', 'Rocket.Chat');
|
||||||
return {
|
return {
|
||||||
...DARK_HEADER,
|
title,
|
||||||
topBar: {
|
headerRight: <LegalButton testID='welcome-view-more' navigation={navigation} />
|
||||||
...DARK_HEADER.topBar,
|
|
||||||
rightButtons: [{
|
|
||||||
id: 'more',
|
|
||||||
icon: Icons.getSource('more'),
|
|
||||||
testID: 'welcome-view-more'
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
componentId: PropTypes.string,
|
navigation: PropTypes.object,
|
||||||
server: PropTypes.string,
|
server: PropTypes.string,
|
||||||
services: PropTypes.object,
|
services: PropTypes.object,
|
||||||
Site_Name: PropTypes.string
|
Site_Name: PropTypes.string
|
||||||
|
@ -123,9 +116,8 @@ export default class LoginSignupView extends LoggedView {
|
||||||
collapsed: true,
|
collapsed: true,
|
||||||
servicesHeight: new Animated.Value(SERVICES_COLLAPSED_HEIGHT)
|
servicesHeight: new Animated.Value(SERVICES_COLLAPSED_HEIGHT)
|
||||||
};
|
};
|
||||||
Navigation.events().bindComponent(this);
|
const { Site_Name } = this.props;
|
||||||
const { componentId, Site_Name } = this.props;
|
this.setTitle(Site_Name);
|
||||||
this.setTitle(componentId, Site_Name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
|
@ -150,34 +142,15 @@ export default class LoginSignupView extends LoggedView {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
const { componentId, Site_Name } = this.props;
|
const { Site_Name } = this.props;
|
||||||
if (Site_Name && prevProps.Site_Name !== Site_Name) {
|
if (Site_Name && prevProps.Site_Name !== Site_Name) {
|
||||||
this.setTitle(componentId, Site_Name);
|
this.setTitle(Site_Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setTitle = (componentId, title) => {
|
setTitle = (title) => {
|
||||||
Navigation.mergeOptions(componentId, {
|
const { navigation } = this.props;
|
||||||
topBar: {
|
navigation.setParams({ title });
|
||||||
title: {
|
|
||||||
text: title
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
navigationButtonPressed = ({ buttonId }) => {
|
|
||||||
if (buttonId === 'more') {
|
|
||||||
Navigation.showModal({
|
|
||||||
stack: {
|
|
||||||
children: [{
|
|
||||||
component: {
|
|
||||||
name: 'LegalView'
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onPressFacebook = () => {
|
onPressFacebook = () => {
|
||||||
|
@ -258,57 +231,18 @@ export default class LoginSignupView extends LoggedView {
|
||||||
}
|
}
|
||||||
|
|
||||||
openOAuth = (oAuthUrl) => {
|
openOAuth = (oAuthUrl) => {
|
||||||
Navigation.showModal({
|
const { navigation } = this.props;
|
||||||
stack: {
|
navigation.navigate('OAuthView', { oAuthUrl });
|
||||||
children: [{
|
|
||||||
component: {
|
|
||||||
name: 'OAuthView',
|
|
||||||
passProps: {
|
|
||||||
oAuthUrl
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
topBar: {
|
|
||||||
title: {
|
|
||||||
text: 'OAuth'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
login = () => {
|
login = () => {
|
||||||
const { componentId, Site_Name } = this.props;
|
const { navigation, Site_Name } = this.props;
|
||||||
Navigation.push(componentId, {
|
navigation.navigate('LoginView', { title: Site_Name });
|
||||||
component: {
|
|
||||||
name: 'LoginView',
|
|
||||||
options: {
|
|
||||||
topBar: {
|
|
||||||
title: {
|
|
||||||
text: Site_Name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
register = () => {
|
register = () => {
|
||||||
const { componentId, Site_Name } = this.props;
|
const { navigation, Site_Name } = this.props;
|
||||||
Navigation.push(componentId, {
|
navigation.navigate('RegisterView', { title: Site_Name });
|
||||||
component: {
|
|
||||||
name: 'RegisterView',
|
|
||||||
options: {
|
|
||||||
topBar: {
|
|
||||||
title: {
|
|
||||||
text: Site_Name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
transitionServicesTo = (height) => {
|
transitionServicesTo = (height) => {
|
||||||
|
@ -428,6 +362,7 @@ export default class LoginSignupView extends LoggedView {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<ScrollView style={[sharedStyles.containerScrollView, sharedStyles.container, styles.container]} {...scrollPersistTaps}>
|
<ScrollView style={[sharedStyles.containerScrollView, sharedStyles.container, styles.container]} {...scrollPersistTaps}>
|
||||||
|
<StatusBar />
|
||||||
<SafeAreaView testID='welcome-view' forceInset={{ bottom: 'never' }} style={styles.safeArea}>
|
<SafeAreaView testID='welcome-view' forceInset={{ bottom: 'never' }} style={styles.safeArea}>
|
||||||
{this.renderServices()}
|
{this.renderServices()}
|
||||||
{this.renderServicesSeparator()}
|
{this.renderServicesSeparator()}
|
||||||
|
|
|
@ -5,10 +5,9 @@ import {
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { Answers } from 'react-native-fabric';
|
import { Answers } from 'react-native-fabric';
|
||||||
import SafeAreaView from 'react-native-safe-area-view';
|
import { SafeAreaView } from 'react-navigation';
|
||||||
import equal from 'deep-equal';
|
import equal from 'deep-equal';
|
||||||
|
|
||||||
import Navigation from '../lib/Navigation';
|
|
||||||
import KeyboardView from '../presentation/KeyboardView';
|
import KeyboardView from '../presentation/KeyboardView';
|
||||||
import TextInput from '../containers/TextInput';
|
import TextInput from '../containers/TextInput';
|
||||||
import Button from '../containers/Button';
|
import Button from '../containers/Button';
|
||||||
|
@ -16,9 +15,9 @@ import sharedStyles from './Styles';
|
||||||
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
||||||
import LoggedView from './View';
|
import LoggedView from './View';
|
||||||
import I18n from '../i18n';
|
import I18n from '../i18n';
|
||||||
import { DARK_HEADER } from '../constants/headerOptions';
|
|
||||||
import { loginRequest as loginRequestAction } from '../actions/login';
|
import { loginRequest as loginRequestAction } from '../actions/login';
|
||||||
import Icons from '../lib/Icons';
|
import { LegalButton } from '../containers/HeaderButton';
|
||||||
|
import StatusBar from '../containers/StatusBar';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
buttonsContainer: {
|
buttonsContainer: {
|
||||||
|
@ -58,22 +57,16 @@ const styles = StyleSheet.create({
|
||||||
}))
|
}))
|
||||||
/** @extends React.Component */
|
/** @extends React.Component */
|
||||||
export default class LoginView extends LoggedView {
|
export default class LoginView extends LoggedView {
|
||||||
static options() {
|
static navigationOptions = ({ navigation }) => {
|
||||||
|
const title = navigation.getParam('title', 'Rocket.Chat');
|
||||||
return {
|
return {
|
||||||
...DARK_HEADER,
|
title,
|
||||||
topBar: {
|
headerRight: <LegalButton navigation={navigation} testID='login-view-more' />
|
||||||
...DARK_HEADER.topBar,
|
|
||||||
rightButtons: [{
|
|
||||||
id: 'more',
|
|
||||||
icon: Icons.getSource('more'),
|
|
||||||
testID: 'login-view-more'
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
componentId: PropTypes.string,
|
navigation: PropTypes.object,
|
||||||
loginRequest: PropTypes.func.isRequired,
|
loginRequest: PropTypes.func.isRequired,
|
||||||
error: PropTypes.object,
|
error: PropTypes.object,
|
||||||
Site_Name: PropTypes.string,
|
Site_Name: PropTypes.string,
|
||||||
|
@ -91,9 +84,8 @@ export default class LoginView extends LoggedView {
|
||||||
code: '',
|
code: '',
|
||||||
showTOTP: false
|
showTOTP: false
|
||||||
};
|
};
|
||||||
Navigation.events().bindComponent(this);
|
const { Site_Name } = this.props;
|
||||||
const { componentId, Site_Name } = this.props;
|
this.setTitle(Site_Name);
|
||||||
this.setTitle(componentId, Site_Name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
@ -103,9 +95,9 @@ export default class LoginView extends LoggedView {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
const { componentId, Site_Name, error } = this.props;
|
const { Site_Name, error } = this.props;
|
||||||
if (Site_Name && nextProps.Site_Name !== Site_Name) {
|
if (Site_Name && nextProps.Site_Name !== Site_Name) {
|
||||||
this.setTitle(componentId, nextProps.Site_Name);
|
this.setTitle(nextProps.Site_Name);
|
||||||
} else if (nextProps.failure && !equal(error, nextProps.error)) {
|
} else if (nextProps.failure && !equal(error, nextProps.error)) {
|
||||||
if (nextProps.error && nextProps.error.error === 'totp-required') {
|
if (nextProps.error && nextProps.error.error === 'totp-required') {
|
||||||
LayoutAnimation.easeInEaseOut();
|
LayoutAnimation.easeInEaseOut();
|
||||||
|
@ -167,28 +159,9 @@ export default class LoginView extends LoggedView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setTitle = (componentId, title) => {
|
setTitle = (title) => {
|
||||||
Navigation.mergeOptions(componentId, {
|
const { navigation } = this.props;
|
||||||
topBar: {
|
navigation.setParams({ title });
|
||||||
title: {
|
|
||||||
text: title
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
navigationButtonPressed = ({ buttonId }) => {
|
|
||||||
if (buttonId === 'more') {
|
|
||||||
Navigation.showModal({
|
|
||||||
stack: {
|
|
||||||
children: [{
|
|
||||||
component: {
|
|
||||||
name: 'LegalView'
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
valid = () => {
|
valid = () => {
|
||||||
|
@ -214,35 +187,13 @@ export default class LoginView extends LoggedView {
|
||||||
}
|
}
|
||||||
|
|
||||||
register = () => {
|
register = () => {
|
||||||
const { componentId, Site_Name } = this.props;
|
const { navigation, Site_Name } = this.props;
|
||||||
Navigation.push(componentId, {
|
navigation.navigate('RegisterView', { title: Site_Name });
|
||||||
component: {
|
|
||||||
name: 'RegisterView',
|
|
||||||
options: {
|
|
||||||
topBar: {
|
|
||||||
title: {
|
|
||||||
text: Site_Name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
forgotPassword = () => {
|
forgotPassword = () => {
|
||||||
const { componentId, Site_Name } = this.props;
|
const { navigation, Site_Name } = this.props;
|
||||||
Navigation.push(componentId, {
|
navigation.navigate('ForgotPasswordView', { title: Site_Name });
|
||||||
component: {
|
|
||||||
name: 'ForgotPasswordView',
|
|
||||||
options: {
|
|
||||||
topBar: {
|
|
||||||
title: {
|
|
||||||
text: Site_Name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderTOTP = () => {
|
renderTOTP = () => {
|
||||||
|
@ -336,6 +287,7 @@ export default class LoginView extends LoggedView {
|
||||||
keyboardVerticalOffset={128}
|
keyboardVerticalOffset={128}
|
||||||
key='login-view'
|
key='login-view'
|
||||||
>
|
>
|
||||||
|
<StatusBar />
|
||||||
<ScrollView {...scrollPersistTaps} contentContainerStyle={sharedStyles.containerScrollView}>
|
<ScrollView {...scrollPersistTaps} contentContainerStyle={sharedStyles.containerScrollView}>
|
||||||
{!showTOTP ? this.renderUserForm() : null}
|
{!showTOTP ? this.renderUserForm() : null}
|
||||||
{showTOTP ? this.renderTOTP() : null}
|
{showTOTP ? this.renderTOTP() : null}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { FlatList, View, Text } from 'react-native';
|
import { FlatList, View, Text } from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import SafeAreaView from 'react-native-safe-area-view';
|
import { SafeAreaView } from 'react-navigation';
|
||||||
import equal from 'deep-equal';
|
import equal from 'deep-equal';
|
||||||
|
|
||||||
import LoggedView from '../View';
|
import LoggedView from '../View';
|
||||||
|
@ -11,6 +11,7 @@ import Message from '../../containers/message/Message';
|
||||||
import RCActivityIndicator from '../../containers/ActivityIndicator';
|
import RCActivityIndicator from '../../containers/ActivityIndicator';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
import RocketChat from '../../lib/rocketchat';
|
import RocketChat from '../../lib/rocketchat';
|
||||||
|
import StatusBar from '../../containers/StatusBar';
|
||||||
|
|
||||||
@connect(state => ({
|
@connect(state => ({
|
||||||
baseUrl: state.settings.Site_Url || state.server ? state.server.server : '',
|
baseUrl: state.settings.Site_Url || state.server ? state.server.server : '',
|
||||||
|
@ -24,14 +25,8 @@ import RocketChat from '../../lib/rocketchat';
|
||||||
}))
|
}))
|
||||||
/** @extends React.Component */
|
/** @extends React.Component */
|
||||||
export default class MentionedMessagesView extends LoggedView {
|
export default class MentionedMessagesView extends LoggedView {
|
||||||
static options() {
|
static navigationOptions = {
|
||||||
return {
|
title: I18n.t('Mentions')
|
||||||
topBar: {
|
|
||||||
title: {
|
|
||||||
text: I18n.t('Mentions')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
@ -42,7 +37,7 @@ export default class MentionedMessagesView extends LoggedView {
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super('StarredMessagesView', props);
|
super('MentionedMessagesView', props);
|
||||||
this.state = {
|
this.state = {
|
||||||
loading: false,
|
loading: false,
|
||||||
messages: []
|
messages: []
|
||||||
|
@ -130,6 +125,7 @@ export default class MentionedMessagesView extends LoggedView {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SafeAreaView style={styles.list} testID='mentioned-messages-view' forceInset={{ bottom: 'never' }}>
|
<SafeAreaView style={styles.list} testID='mentioned-messages-view' forceInset={{ bottom: 'never' }}>
|
||||||
|
<StatusBar />
|
||||||
<FlatList
|
<FlatList
|
||||||
data={messages}
|
data={messages}
|
||||||
renderItem={this.renderItem}
|
renderItem={this.renderItem}
|
||||||
|
|
|
@ -4,10 +4,9 @@ import {
|
||||||
View, StyleSheet, FlatList, Text
|
View, StyleSheet, FlatList, Text
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import SafeAreaView from 'react-native-safe-area-view';
|
import { SafeAreaView } from 'react-navigation';
|
||||||
import equal from 'deep-equal';
|
import equal from 'deep-equal';
|
||||||
|
|
||||||
import Navigation from '../lib/Navigation';
|
|
||||||
import database from '../lib/realm';
|
import database from '../lib/realm';
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
import UserItem from '../presentation/UserItem';
|
import UserItem from '../presentation/UserItem';
|
||||||
|
@ -16,9 +15,11 @@ import LoggedView from './View';
|
||||||
import sharedStyles from './Styles';
|
import sharedStyles from './Styles';
|
||||||
import I18n from '../i18n';
|
import I18n from '../i18n';
|
||||||
import Touch from '../utils/touch';
|
import Touch from '../utils/touch';
|
||||||
import { isIOS, isAndroid } from '../utils/deviceInfo';
|
import { isIOS } from '../utils/deviceInfo';
|
||||||
import SearchBox from '../containers/SearchBox';
|
import SearchBox from '../containers/SearchBox';
|
||||||
import Icons, { CustomIcon } from '../lib/Icons';
|
import { CustomIcon } from '../lib/Icons';
|
||||||
|
import { CloseModalButton } from '../containers/HeaderButton';
|
||||||
|
import StatusBar from '../containers/StatusBar';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
safeAreaView: {
|
safeAreaView: {
|
||||||
|
@ -56,22 +57,14 @@ const styles = StyleSheet.create({
|
||||||
}))
|
}))
|
||||||
/** @extends React.Component */
|
/** @extends React.Component */
|
||||||
export default class NewMessageView extends LoggedView {
|
export default class NewMessageView extends LoggedView {
|
||||||
static options() {
|
static navigationOptions = ({ navigation }) => ({
|
||||||
return {
|
headerLeft: <CloseModalButton navigation={navigation} testID='new-message-view-close' />,
|
||||||
topBar: {
|
title: I18n.t('New_Message')
|
||||||
leftButtons: [{
|
})
|
||||||
id: 'cancel',
|
|
||||||
icon: isAndroid ? Icons.getSource('close') : undefined,
|
|
||||||
text: isIOS ? I18n.t('Cancel') : undefined
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
componentId: PropTypes.string,
|
navigation: PropTypes.object,
|
||||||
baseUrl: PropTypes.string,
|
baseUrl: PropTypes.string,
|
||||||
onPressItem: PropTypes.func.isRequired,
|
|
||||||
user: PropTypes.shape({
|
user: PropTypes.shape({
|
||||||
id: PropTypes.string,
|
id: PropTypes.string,
|
||||||
token: PropTypes.string
|
token: PropTypes.string
|
||||||
|
@ -85,7 +78,6 @@ export default class NewMessageView extends LoggedView {
|
||||||
search: []
|
search: []
|
||||||
};
|
};
|
||||||
this.data.addListener(this.updateState);
|
this.data.addListener(this.updateState);
|
||||||
Navigation.events().bindComponent(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
|
@ -105,21 +97,15 @@ export default class NewMessageView extends LoggedView {
|
||||||
this.search(text);
|
this.search(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
onPressItem = async(item) => {
|
onPressItem = (item) => {
|
||||||
const { onPressItem } = this.props;
|
const { navigation } = this.props;
|
||||||
await this.dismiss();
|
const onPressItem = navigation.getParam('onPressItem', () => {});
|
||||||
onPressItem(item);
|
onPressItem(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
navigationButtonPressed = ({ buttonId }) => {
|
|
||||||
if (buttonId === 'cancel') {
|
|
||||||
this.dismiss();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dismiss = () => {
|
dismiss = () => {
|
||||||
const { componentId } = this.props;
|
const { navigation } = this.props;
|
||||||
return Navigation.dismissModal(componentId);
|
return navigation.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line react/sort-comp
|
// eslint-disable-next-line react/sort-comp
|
||||||
|
@ -135,22 +121,8 @@ export default class NewMessageView extends LoggedView {
|
||||||
}
|
}
|
||||||
|
|
||||||
createChannel = () => {
|
createChannel = () => {
|
||||||
const { componentId } = this.props;
|
const { navigation } = this.props;
|
||||||
Navigation.push(componentId, {
|
navigation.navigate('SelectedUsersViewCreateChannel', { nextActionID: 'CREATE_CHANNEL', title: I18n.t('Select_Users') });
|
||||||
component: {
|
|
||||||
name: 'SelectedUsersView',
|
|
||||||
passProps: {
|
|
||||||
nextAction: 'CREATE_CHANNEL'
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
topBar: {
|
|
||||||
title: {
|
|
||||||
text: I18n.t('Select_Users')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderHeader = () => (
|
renderHeader = () => (
|
||||||
|
@ -211,6 +183,7 @@ export default class NewMessageView extends LoggedView {
|
||||||
|
|
||||||
render = () => (
|
render = () => (
|
||||||
<SafeAreaView style={styles.safeAreaView} testID='new-message-view' forceInset={{ bottom: 'never' }}>
|
<SafeAreaView style={styles.safeAreaView} testID='new-message-view' forceInset={{ bottom: 'never' }}>
|
||||||
|
<StatusBar />
|
||||||
{this.renderList()}
|
{this.renderList()}
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
);
|
);
|
||||||
|
|
|
@ -4,9 +4,8 @@ import {
|
||||||
Text, ScrollView, Keyboard, Image, StyleSheet, TouchableOpacity
|
Text, ScrollView, Keyboard, Image, StyleSheet, TouchableOpacity
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import SafeAreaView from 'react-native-safe-area-view';
|
import { SafeAreaView } from 'react-navigation';
|
||||||
|
|
||||||
import Navigation from '../lib/Navigation';
|
|
||||||
import { serverRequest } from '../actions/server';
|
import { serverRequest } from '../actions/server';
|
||||||
import sharedStyles from './Styles';
|
import sharedStyles from './Styles';
|
||||||
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
||||||
|
@ -17,8 +16,9 @@ import I18n from '../i18n';
|
||||||
import { verticalScale, moderateScale } from '../utils/scaling';
|
import { verticalScale, moderateScale } from '../utils/scaling';
|
||||||
import KeyboardView from '../presentation/KeyboardView';
|
import KeyboardView from '../presentation/KeyboardView';
|
||||||
import { isIOS, isNotch } from '../utils/deviceInfo';
|
import { isIOS, isNotch } from '../utils/deviceInfo';
|
||||||
import { LIGHT_HEADER } from '../constants/headerOptions';
|
// import { LIGHT_HEADER } from '../constants/headerOptions';
|
||||||
import { CustomIcon } from '../lib/Icons';
|
import { CustomIcon } from '../lib/Icons';
|
||||||
|
import StatusBar from '../containers/StatusBar';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
image: {
|
image: {
|
||||||
|
@ -64,18 +64,12 @@ const defaultServer = 'https://open.rocket.chat';
|
||||||
}))
|
}))
|
||||||
/** @extends React.Component */
|
/** @extends React.Component */
|
||||||
export default class NewServerView extends LoggedView {
|
export default class NewServerView extends LoggedView {
|
||||||
static options() {
|
static navigationOptions = () => ({
|
||||||
return {
|
header: null
|
||||||
...LIGHT_HEADER,
|
})
|
||||||
topBar: {
|
|
||||||
visible: false,
|
|
||||||
drawBehind: true
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
componentId: PropTypes.string,
|
navigation: PropTypes.object,
|
||||||
server: PropTypes.string,
|
server: PropTypes.string,
|
||||||
connecting: PropTypes.bool.isRequired,
|
connecting: PropTypes.bool.isRequired,
|
||||||
connectServer: PropTypes.func.isRequired
|
connectServer: PropTypes.func.isRequired
|
||||||
|
@ -86,11 +80,11 @@ export default class NewServerView extends LoggedView {
|
||||||
this.state = {
|
this.state = {
|
||||||
text: ''
|
text: ''
|
||||||
};
|
};
|
||||||
Navigation.events().bindComponent(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { server, connectServer } = this.props;
|
const { navigation, connectServer } = this.props;
|
||||||
|
const server = navigation.getParam('server');
|
||||||
if (server) {
|
if (server) {
|
||||||
connectServer(server);
|
connectServer(server);
|
||||||
this.setState({ text: server });
|
this.setState({ text: server });
|
||||||
|
@ -153,7 +147,7 @@ export default class NewServerView extends LoggedView {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderBack = () => {
|
renderBack = () => {
|
||||||
const { componentId } = this.props;
|
const { navigation } = this.props;
|
||||||
|
|
||||||
let top = 15;
|
let top = 15;
|
||||||
if (isIOS) {
|
if (isIOS) {
|
||||||
|
@ -163,7 +157,7 @@ export default class NewServerView extends LoggedView {
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={[styles.backButton, { top }]}
|
style={[styles.backButton, { top }]}
|
||||||
onPress={() => Navigation.pop(componentId)}
|
onPress={() => navigation.pop()}
|
||||||
>
|
>
|
||||||
<CustomIcon
|
<CustomIcon
|
||||||
name='back'
|
name='back'
|
||||||
|
@ -183,6 +177,7 @@ export default class NewServerView extends LoggedView {
|
||||||
keyboardVerticalOffset={128}
|
keyboardVerticalOffset={128}
|
||||||
key='login-view'
|
key='login-view'
|
||||||
>
|
>
|
||||||
|
<StatusBar light />
|
||||||
<ScrollView {...scrollPersistTaps} contentContainerStyle={sharedStyles.containerScrollView}>
|
<ScrollView {...scrollPersistTaps} contentContainerStyle={sharedStyles.containerScrollView}>
|
||||||
<SafeAreaView style={sharedStyles.container} testID='new-server-view' forceInset={{ bottom: 'never' }}>
|
<SafeAreaView style={sharedStyles.container} testID='new-server-view' forceInset={{ bottom: 'never' }}>
|
||||||
<Image style={styles.image} source={{ uri: 'new_server' }} />
|
<Image style={styles.image} source={{ uri: 'new_server' }} />
|
||||||
|
|
|
@ -3,12 +3,10 @@ import PropTypes from 'prop-types';
|
||||||
import { WebView } from 'react-native';
|
import { WebView } from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import Navigation from '../lib/Navigation';
|
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
import I18n from '../i18n';
|
import { isIOS } from '../utils/deviceInfo';
|
||||||
import { DARK_HEADER } from '../constants/headerOptions';
|
import { CloseModalButton } from '../containers/HeaderButton';
|
||||||
import { isIOS, isAndroid } from '../utils/deviceInfo';
|
import StatusBar from '../containers/StatusBar';
|
||||||
import Icons from '../lib/Icons';
|
|
||||||
|
|
||||||
const userAgentAndroid = 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1';
|
const userAgentAndroid = 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1';
|
||||||
const userAgent = isIOS ? 'UserAgent' : userAgentAndroid;
|
const userAgent = isIOS ? 'UserAgent' : userAgentAndroid;
|
||||||
|
@ -17,23 +15,13 @@ const userAgent = isIOS ? 'UserAgent' : userAgentAndroid;
|
||||||
server: state.server.server
|
server: state.server.server
|
||||||
}))
|
}))
|
||||||
export default class OAuthView extends React.PureComponent {
|
export default class OAuthView extends React.PureComponent {
|
||||||
static options() {
|
static navigationOptions = ({ navigation }) => ({
|
||||||
return {
|
headerLeft: <CloseModalButton navigation={navigation} />,
|
||||||
...DARK_HEADER,
|
title: 'OAuth'
|
||||||
topBar: {
|
})
|
||||||
...DARK_HEADER.topBar,
|
|
||||||
leftButtons: [{
|
|
||||||
id: 'cancel',
|
|
||||||
icon: isAndroid ? Icons.getSource('close') : undefined,
|
|
||||||
text: isIOS ? I18n.t('Cancel') : undefined
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
componentId: PropTypes.string,
|
navigation: PropTypes.object,
|
||||||
oAuthUrl: PropTypes.string,
|
|
||||||
server: PropTypes.string
|
server: PropTypes.string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,18 +31,11 @@ export default class OAuthView extends React.PureComponent {
|
||||||
logging: false
|
logging: false
|
||||||
};
|
};
|
||||||
this.redirectRegex = new RegExp(`(?=.*(${ props.server }))(?=.*(credentialToken))(?=.*(credentialSecret))`, 'g');
|
this.redirectRegex = new RegExp(`(?=.*(${ props.server }))(?=.*(credentialToken))(?=.*(credentialSecret))`, 'g');
|
||||||
Navigation.events().bindComponent(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
navigationButtonPressed = ({ buttonId }) => {
|
|
||||||
if (buttonId === 'cancel') {
|
|
||||||
this.dismiss();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dismiss = () => {
|
dismiss = () => {
|
||||||
const { componentId } = this.props;
|
const { navigation } = this.props;
|
||||||
Navigation.dismissModal(componentId);
|
navigation.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
login = async(params) => {
|
login = async(params) => {
|
||||||
|
@ -75,20 +56,24 @@ export default class OAuthView extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { oAuthUrl } = this.props;
|
const { navigation } = this.props;
|
||||||
|
const oAuthUrl = navigation.getParam('oAuthUrl');
|
||||||
return (
|
return (
|
||||||
<WebView
|
<React.Fragment>
|
||||||
source={{ uri: oAuthUrl }}
|
<StatusBar />
|
||||||
userAgent={userAgent}
|
<WebView
|
||||||
onNavigationStateChange={(webViewState) => {
|
source={{ uri: oAuthUrl }}
|
||||||
const url = decodeURIComponent(webViewState.url);
|
userAgent={userAgent}
|
||||||
if (this.redirectRegex.test(url)) {
|
onNavigationStateChange={(webViewState) => {
|
||||||
const parts = url.split('#');
|
const url = decodeURIComponent(webViewState.url);
|
||||||
const credentials = JSON.parse(parts[1]);
|
if (this.redirectRegex.test(url)) {
|
||||||
this.login({ oauth: { ...credentials } });
|
const parts = url.split('#');
|
||||||
}
|
const credentials = JSON.parse(parts[1]);
|
||||||
}}
|
this.login({ oauth: { ...credentials } });
|
||||||
/>
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,8 @@ import {
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import SafeAreaView from 'react-native-safe-area-view';
|
import { SafeAreaView } from 'react-navigation';
|
||||||
|
import Orientation from 'react-native-orientation-locker';
|
||||||
|
|
||||||
import { selectServerRequest, serverInitAdd, serverFinishAdd } from '../../actions/server';
|
import { selectServerRequest, serverInitAdd, serverFinishAdd } from '../../actions/server';
|
||||||
import { appStart as appStartAction } from '../../actions';
|
import { appStart as appStartAction } from '../../actions';
|
||||||
|
@ -15,9 +16,8 @@ import styles from './styles';
|
||||||
import LoggedView from '../View';
|
import LoggedView from '../View';
|
||||||
import { isIOS, isNotch } from '../../utils/deviceInfo';
|
import { isIOS, isNotch } from '../../utils/deviceInfo';
|
||||||
import EventEmitter from '../../utils/events';
|
import EventEmitter from '../../utils/events';
|
||||||
import { LIGHT_HEADER } from '../../constants/headerOptions';
|
|
||||||
import Navigation from '../../lib/Navigation';
|
|
||||||
import { CustomIcon } from '../../lib/Icons';
|
import { CustomIcon } from '../../lib/Icons';
|
||||||
|
import StatusBar from '../../containers/StatusBar';
|
||||||
|
|
||||||
@connect(state => ({
|
@connect(state => ({
|
||||||
currentServer: state.server.server,
|
currentServer: state.server.server,
|
||||||
|
@ -26,23 +26,16 @@ import { CustomIcon } from '../../lib/Icons';
|
||||||
initAdd: () => dispatch(serverInitAdd()),
|
initAdd: () => dispatch(serverInitAdd()),
|
||||||
finishAdd: () => dispatch(serverFinishAdd()),
|
finishAdd: () => dispatch(serverFinishAdd()),
|
||||||
selectServer: server => dispatch(selectServerRequest(server)),
|
selectServer: server => dispatch(selectServerRequest(server)),
|
||||||
appStart: () => dispatch(appStartAction())
|
appStart: root => dispatch(appStartAction(root))
|
||||||
}))
|
}))
|
||||||
/** @extends React.Component */
|
/** @extends React.Component */
|
||||||
export default class OnboardingView extends LoggedView {
|
export default class OnboardingView extends LoggedView {
|
||||||
static options() {
|
static navigationOptions = () => ({
|
||||||
return {
|
header: null
|
||||||
...LIGHT_HEADER,
|
})
|
||||||
topBar: {
|
|
||||||
visible: false,
|
|
||||||
drawBehind: true
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
componentId: PropTypes.string,
|
navigation: PropTypes.object,
|
||||||
previousServer: PropTypes.string,
|
|
||||||
adding: PropTypes.bool,
|
adding: PropTypes.bool,
|
||||||
selectServer: PropTypes.func.isRequired,
|
selectServer: PropTypes.func.isRequired,
|
||||||
currentServer: PropTypes.string,
|
currentServer: PropTypes.string,
|
||||||
|
@ -54,11 +47,13 @@ export default class OnboardingView extends LoggedView {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super('OnboardingView', props);
|
super('OnboardingView', props);
|
||||||
BackHandler.addEventListener('hardwareBackPress', this.handleBackPress);
|
BackHandler.addEventListener('hardwareBackPress', this.handleBackPress);
|
||||||
|
this.previousServer = props.navigation.getParam('previousServer');
|
||||||
|
Orientation.lockToPortrait();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { previousServer, initAdd } = this.props;
|
const { initAdd } = this.props;
|
||||||
if (previousServer) {
|
if (this.previousServer) {
|
||||||
initAdd();
|
initAdd();
|
||||||
}
|
}
|
||||||
EventEmitter.addEventListener('NewServer', this.handleNewServerEvent);
|
EventEmitter.addEventListener('NewServer', this.handleNewServerEvent);
|
||||||
|
@ -70,11 +65,11 @@ export default class OnboardingView extends LoggedView {
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
const {
|
const {
|
||||||
selectServer, previousServer, currentServer, adding, finishAdd
|
selectServer, currentServer, adding, finishAdd
|
||||||
} = this.props;
|
} = this.props;
|
||||||
if (adding) {
|
if (adding) {
|
||||||
if (previousServer !== currentServer) {
|
if (this.previousServer !== currentServer) {
|
||||||
selectServer(previousServer);
|
selectServer(this.previousServer);
|
||||||
}
|
}
|
||||||
finishAdd();
|
finishAdd();
|
||||||
}
|
}
|
||||||
|
@ -89,26 +84,13 @@ export default class OnboardingView extends LoggedView {
|
||||||
}
|
}
|
||||||
|
|
||||||
close = () => {
|
close = () => {
|
||||||
const { componentId } = this.props;
|
const { appStart } = this.props;
|
||||||
Navigation.dismissModal(componentId);
|
appStart('inside');
|
||||||
}
|
}
|
||||||
|
|
||||||
newServer = (server) => {
|
newServer = (server) => {
|
||||||
const { componentId } = this.props;
|
const { navigation } = this.props;
|
||||||
Navigation.push(componentId, {
|
navigation.navigate('NewServerView', { server });
|
||||||
component: {
|
|
||||||
id: 'NewServerView',
|
|
||||||
name: 'NewServerView',
|
|
||||||
passProps: {
|
|
||||||
server
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
topBar: {
|
|
||||||
visible: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleNewServerEvent = (event) => {
|
handleNewServerEvent = (event) => {
|
||||||
|
@ -129,9 +111,7 @@ export default class OnboardingView extends LoggedView {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderClose = () => {
|
renderClose = () => {
|
||||||
const { previousServer } = this.props;
|
if (this.previousServer) {
|
||||||
|
|
||||||
if (previousServer) {
|
|
||||||
let top = 15;
|
let top = 15;
|
||||||
if (isIOS) {
|
if (isIOS) {
|
||||||
top = isNotch ? 45 : 30;
|
top = isNotch ? 45 : 30;
|
||||||
|
@ -156,6 +136,7 @@ export default class OnboardingView extends LoggedView {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<SafeAreaView style={styles.container} testID='onboarding-view' forceInset={{ bottom: 'never' }}>
|
<SafeAreaView style={styles.container} testID='onboarding-view' forceInset={{ bottom: 'never' }}>
|
||||||
|
<StatusBar light />
|
||||||
<Image style={styles.onboarding} source={{ uri: 'onboarding' }} fadeDuration={0} />
|
<Image style={styles.onboarding} source={{ uri: 'onboarding' }} fadeDuration={0} />
|
||||||
<Text style={styles.title}>{I18n.t('Welcome_to_RocketChat')}</Text>
|
<Text style={styles.title}>{I18n.t('Welcome_to_RocketChat')}</Text>
|
||||||
<Text style={styles.subtitle}>{I18n.t('Open_Source_Communication')}</Text>
|
<Text style={styles.subtitle}>{I18n.t('Open_Source_Communication')}</Text>
|
||||||
|
|
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
||||||
import { FlatList, View, Text } from 'react-native';
|
import { FlatList, View, Text } from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import ActionSheet from 'react-native-action-sheet';
|
import ActionSheet from 'react-native-action-sheet';
|
||||||
import SafeAreaView from 'react-native-safe-area-view';
|
import { SafeAreaView } from 'react-navigation';
|
||||||
import equal from 'deep-equal';
|
import equal from 'deep-equal';
|
||||||
|
|
||||||
import LoggedView from '../View';
|
import LoggedView from '../View';
|
||||||
|
@ -12,6 +12,7 @@ import Message from '../../containers/message/Message';
|
||||||
import RCActivityIndicator from '../../containers/ActivityIndicator';
|
import RCActivityIndicator from '../../containers/ActivityIndicator';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
import RocketChat from '../../lib/rocketchat';
|
import RocketChat from '../../lib/rocketchat';
|
||||||
|
import StatusBar from '../../containers/StatusBar';
|
||||||
|
|
||||||
const PIN_INDEX = 0;
|
const PIN_INDEX = 0;
|
||||||
const CANCEL_INDEX = 1;
|
const CANCEL_INDEX = 1;
|
||||||
|
@ -29,14 +30,8 @@ const options = [I18n.t('Unpin'), I18n.t('Cancel')];
|
||||||
}))
|
}))
|
||||||
/** @extends React.Component */
|
/** @extends React.Component */
|
||||||
export default class PinnedMessagesView extends LoggedView {
|
export default class PinnedMessagesView extends LoggedView {
|
||||||
static options() {
|
static navigationOptions = {
|
||||||
return {
|
title: I18n.t('Pinned')
|
||||||
topBar: {
|
|
||||||
title: {
|
|
||||||
text: I18n.t('Pinned')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
@ -169,6 +164,7 @@ export default class PinnedMessagesView extends LoggedView {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SafeAreaView style={styles.list} testID='pinned-messages-view' forceInset={{ bottom: 'never' }}>
|
<SafeAreaView style={styles.list} testID='pinned-messages-view' forceInset={{ bottom: 'never' }}>
|
||||||
|
<StatusBar />
|
||||||
<FlatList
|
<FlatList
|
||||||
data={messages}
|
data={messages}
|
||||||
renderItem={this.renderItem}
|
renderItem={this.renderItem}
|
||||||
|
|
|
@ -2,29 +2,20 @@ import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { WebView } from 'react-native';
|
import { WebView } from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import SafeAreaView from 'react-native-safe-area-view';
|
import { SafeAreaView } from 'react-navigation';
|
||||||
|
|
||||||
import styles from './Styles';
|
import styles from './Styles';
|
||||||
import LoggedView from './View';
|
import LoggedView from './View';
|
||||||
import { DARK_HEADER } from '../constants/headerOptions';
|
|
||||||
import I18n from '../i18n';
|
import I18n from '../i18n';
|
||||||
|
import StatusBar from '../containers/StatusBar';
|
||||||
|
|
||||||
@connect(state => ({
|
@connect(state => ({
|
||||||
privacyPolicy: state.settings.Layout_Privacy_Policy
|
privacyPolicy: state.settings.Layout_Privacy_Policy
|
||||||
}))
|
}))
|
||||||
/** @extends React.Component */
|
/** @extends React.Component */
|
||||||
export default class PrivacyPolicyView extends LoggedView {
|
export default class PrivacyPolicyView extends LoggedView {
|
||||||
static options() {
|
static navigationOptions = {
|
||||||
return {
|
title: I18n.t('Privacy_Policy')
|
||||||
...DARK_HEADER,
|
|
||||||
topBar: {
|
|
||||||
...DARK_HEADER.topBar,
|
|
||||||
title: {
|
|
||||||
...DARK_HEADER.topBar.title,
|
|
||||||
text: I18n.t('Privacy_Policy')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
@ -40,6 +31,7 @@ export default class PrivacyPolicyView extends LoggedView {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SafeAreaView style={styles.container} testID='privacy-view'>
|
<SafeAreaView style={styles.container} testID='privacy-view'>
|
||||||
|
<StatusBar />
|
||||||
<WebView originWhitelist={['*']} source={{ html: privacyPolicy, baseUrl: '' }} />
|
<WebView originWhitelist={['*']} source={{ html: privacyPolicy, baseUrl: '' }} />
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
);
|
);
|
||||||
|
|
|
@ -6,7 +6,7 @@ import Dialog from 'react-native-dialog';
|
||||||
import SHA256 from 'js-sha256';
|
import SHA256 from 'js-sha256';
|
||||||
import ImagePicker from 'react-native-image-crop-picker';
|
import ImagePicker from 'react-native-image-crop-picker';
|
||||||
import RNPickerSelect from 'react-native-picker-select';
|
import RNPickerSelect from 'react-native-picker-select';
|
||||||
import SafeAreaView from 'react-native-safe-area-view';
|
import { SafeAreaView } from 'react-navigation';
|
||||||
import equal from 'deep-equal';
|
import equal from 'deep-equal';
|
||||||
|
|
||||||
import LoggedView from '../View';
|
import LoggedView from '../View';
|
||||||
|
@ -24,6 +24,8 @@ import Avatar from '../../containers/Avatar';
|
||||||
import Touch from '../../utils/touch';
|
import Touch from '../../utils/touch';
|
||||||
import { setUser as setUserAction } from '../../actions/login';
|
import { setUser as setUserAction } from '../../actions/login';
|
||||||
import { CustomIcon } from '../../lib/Icons';
|
import { CustomIcon } from '../../lib/Icons';
|
||||||
|
import { DrawerButton } from '../../containers/HeaderButton';
|
||||||
|
import StatusBar from '../../containers/StatusBar';
|
||||||
|
|
||||||
@connect(state => ({
|
@connect(state => ({
|
||||||
user: {
|
user: {
|
||||||
|
@ -41,15 +43,10 @@ import { CustomIcon } from '../../lib/Icons';
|
||||||
}))
|
}))
|
||||||
/** @extends React.Component */
|
/** @extends React.Component */
|
||||||
export default class ProfileView extends LoggedView {
|
export default class ProfileView extends LoggedView {
|
||||||
static options() {
|
static navigationOptions = ({ navigation }) => ({
|
||||||
return {
|
headerLeft: <DrawerButton navigation={navigation} />,
|
||||||
topBar: {
|
title: I18n.t('Profile')
|
||||||
title: {
|
})
|
||||||
text: I18n.t('Profile')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
baseUrl: PropTypes.string,
|
baseUrl: PropTypes.string,
|
||||||
|
@ -388,6 +385,7 @@ export default class ProfileView extends LoggedView {
|
||||||
contentContainerStyle={sharedStyles.container}
|
contentContainerStyle={sharedStyles.container}
|
||||||
keyboardVerticalOffset={128}
|
keyboardVerticalOffset={128}
|
||||||
>
|
>
|
||||||
|
<StatusBar />
|
||||||
<ScrollView
|
<ScrollView
|
||||||
contentContainerStyle={sharedStyles.containerScrollView}
|
contentContainerStyle={sharedStyles.containerScrollView}
|
||||||
testID='profile-view-list'
|
testID='profile-view-list'
|
||||||
|
|
|
@ -4,9 +4,8 @@ import {
|
||||||
Keyboard, Text, ScrollView, Alert
|
Keyboard, Text, ScrollView, Alert
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import SafeAreaView from 'react-native-safe-area-view';
|
import { SafeAreaView } from 'react-navigation';
|
||||||
|
|
||||||
import Navigation from '../lib/Navigation';
|
|
||||||
import TextInput from '../containers/TextInput';
|
import TextInput from '../containers/TextInput';
|
||||||
import Button from '../containers/Button';
|
import Button from '../containers/Button';
|
||||||
import KeyboardView from '../presentation/KeyboardView';
|
import KeyboardView from '../presentation/KeyboardView';
|
||||||
|
@ -14,11 +13,11 @@ import sharedStyles from './Styles';
|
||||||
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
||||||
import LoggedView from './View';
|
import LoggedView from './View';
|
||||||
import I18n from '../i18n';
|
import I18n from '../i18n';
|
||||||
import { DARK_HEADER } from '../constants/headerOptions';
|
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
import { loginRequest as loginRequestAction } from '../actions/login';
|
import { loginRequest as loginRequestAction } from '../actions/login';
|
||||||
import isValidEmail from '../utils/isValidEmail';
|
import isValidEmail from '../utils/isValidEmail';
|
||||||
import Icons from '../lib/Icons';
|
import { LegalButton } from '../containers/HeaderButton';
|
||||||
|
import StatusBar from '../containers/StatusBar';
|
||||||
|
|
||||||
const shouldUpdateState = ['name', 'email', 'password', 'username', 'saving'];
|
const shouldUpdateState = ['name', 'email', 'password', 'username', 'saving'];
|
||||||
|
|
||||||
|
@ -27,22 +26,16 @@ const shouldUpdateState = ['name', 'email', 'password', 'username', 'saving'];
|
||||||
}))
|
}))
|
||||||
/** @extends React.Component */
|
/** @extends React.Component */
|
||||||
export default class RegisterView extends LoggedView {
|
export default class RegisterView extends LoggedView {
|
||||||
static options() {
|
static navigationOptions = ({ navigation }) => {
|
||||||
|
const title = navigation.getParam('title', 'Rocket.Chat');
|
||||||
return {
|
return {
|
||||||
...DARK_HEADER,
|
title,
|
||||||
topBar: {
|
headerRight: <LegalButton testID='register-view-more' navigation={navigation} />
|
||||||
...DARK_HEADER.topBar,
|
|
||||||
rightButtons: [{
|
|
||||||
id: 'more',
|
|
||||||
icon: Icons.getSource('more'),
|
|
||||||
testID: 'register-view-more'
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
componentId: PropTypes.string,
|
navigation: PropTypes.object,
|
||||||
loginRequest: PropTypes.func,
|
loginRequest: PropTypes.func,
|
||||||
Site_Name: PropTypes.string
|
Site_Name: PropTypes.string
|
||||||
}
|
}
|
||||||
|
@ -56,7 +49,6 @@ export default class RegisterView extends LoggedView {
|
||||||
username: '',
|
username: '',
|
||||||
saving: false
|
saving: false
|
||||||
};
|
};
|
||||||
Navigation.events().bindComponent(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
@ -71,9 +63,9 @@ export default class RegisterView extends LoggedView {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
const { componentId, Site_Name } = this.props;
|
const { Site_Name } = this.props;
|
||||||
if (Site_Name && prevProps.Site_Name !== Site_Name) {
|
if (Site_Name && prevProps.Site_Name !== Site_Name) {
|
||||||
this.setTitle(componentId, Site_Name);
|
this.setTitle(Site_Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,28 +75,9 @@ export default class RegisterView extends LoggedView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setTitle = (componentId, title) => {
|
setTitle = (title) => {
|
||||||
Navigation.mergeOptions(componentId, {
|
const { navigation } = this.props;
|
||||||
topBar: {
|
navigation.setParams({ title });
|
||||||
title: {
|
|
||||||
text: title
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
navigationButtonPressed = ({ buttonId }) => {
|
|
||||||
if (buttonId === 'more') {
|
|
||||||
Navigation.showModal({
|
|
||||||
stack: {
|
|
||||||
children: [{
|
|
||||||
component: {
|
|
||||||
name: 'LegalView'
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
valid = () => {
|
valid = () => {
|
||||||
|
@ -137,42 +110,11 @@ export default class RegisterView extends LoggedView {
|
||||||
this.setState({ saving: false });
|
this.setState({ saving: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
termsService = () => {
|
|
||||||
const { componentId } = this.props;
|
|
||||||
Navigation.push(componentId, {
|
|
||||||
component: {
|
|
||||||
name: 'TermsServiceView',
|
|
||||||
options: {
|
|
||||||
topBar: {
|
|
||||||
title: {
|
|
||||||
text: I18n.t('Terms_of_Service')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
privacyPolicy = () => {
|
|
||||||
const { componentId } = this.props;
|
|
||||||
Navigation.push(componentId, {
|
|
||||||
component: {
|
|
||||||
name: 'PrivacyPolicyView',
|
|
||||||
options: {
|
|
||||||
topBar: {
|
|
||||||
title: {
|
|
||||||
text: I18n.t('Privacy_Policy')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { saving } = this.state;
|
const { saving } = this.state;
|
||||||
return (
|
return (
|
||||||
<KeyboardView contentContainerStyle={sharedStyles.container}>
|
<KeyboardView contentContainerStyle={sharedStyles.container}>
|
||||||
|
<StatusBar />
|
||||||
<ScrollView {...scrollPersistTaps} contentContainerStyle={sharedStyles.containerScrollView}>
|
<ScrollView {...scrollPersistTaps} contentContainerStyle={sharedStyles.containerScrollView}>
|
||||||
<SafeAreaView style={sharedStyles.container} testID='register-view' forceInset={{ bottom: 'never' }}>
|
<SafeAreaView style={sharedStyles.container} testID='register-view' forceInset={{ bottom: 'never' }}>
|
||||||
<Text style={[sharedStyles.loginTitle, sharedStyles.textBold]}>{I18n.t('Sign_Up')}</Text>
|
<Text style={[sharedStyles.loginTitle, sharedStyles.textBold]}>{I18n.t('Sign_Up')}</Text>
|
||||||
|
|
|
@ -4,10 +4,9 @@ import {
|
||||||
View, SectionList, Text, Alert
|
View, SectionList, Text, Alert
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import SafeAreaView from 'react-native-safe-area-view';
|
import { SafeAreaView } from 'react-navigation';
|
||||||
import equal from 'deep-equal';
|
import equal from 'deep-equal';
|
||||||
|
|
||||||
import Navigation from '../../lib/Navigation';
|
|
||||||
import { leaveRoom as leaveRoomAction } from '../../actions/room';
|
import { leaveRoom as leaveRoomAction } from '../../actions/room';
|
||||||
import LoggedView from '../View';
|
import LoggedView from '../View';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
|
@ -23,6 +22,7 @@ import I18n from '../../i18n';
|
||||||
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
||||||
import { CustomIcon } from '../../lib/Icons';
|
import { CustomIcon } from '../../lib/Icons';
|
||||||
import DisclosureIndicator from '../../containers/DisclosureIndicator';
|
import DisclosureIndicator from '../../containers/DisclosureIndicator';
|
||||||
|
import StatusBar from '../../containers/StatusBar';
|
||||||
|
|
||||||
const renderSeparator = () => <View style={styles.separator} />;
|
const renderSeparator = () => <View style={styles.separator} />;
|
||||||
|
|
||||||
|
@ -38,20 +38,13 @@ const renderSeparator = () => <View style={styles.separator} />;
|
||||||
}))
|
}))
|
||||||
/** @extends React.Component */
|
/** @extends React.Component */
|
||||||
export default class RoomActionsView extends LoggedView {
|
export default class RoomActionsView extends LoggedView {
|
||||||
static options() {
|
static navigationOptions = {
|
||||||
return {
|
title: I18n.t('Actions')
|
||||||
topBar: {
|
|
||||||
title: {
|
|
||||||
text: I18n.t('Actions')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
baseUrl: PropTypes.string,
|
baseUrl: PropTypes.string,
|
||||||
rid: PropTypes.string,
|
navigation: PropTypes.object,
|
||||||
componentId: PropTypes.string,
|
|
||||||
user: PropTypes.shape({
|
user: PropTypes.shape({
|
||||||
id: PropTypes.string,
|
id: PropTypes.string,
|
||||||
token: PropTypes.string
|
token: PropTypes.string
|
||||||
|
@ -62,10 +55,10 @@ export default class RoomActionsView extends LoggedView {
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super('RoomActionsView', props);
|
super('RoomActionsView', props);
|
||||||
const { rid, room } = props;
|
this.rid = props.navigation.getParam('rid');
|
||||||
this.rooms = database.objects('subscriptions').filtered('rid = $0', rid);
|
this.rooms = database.objects('subscriptions').filtered('rid = $0', this.rid);
|
||||||
this.state = {
|
this.state = {
|
||||||
room,
|
room: this.rooms[0] || props.room,
|
||||||
membersCount: 0,
|
membersCount: 0,
|
||||||
member: {},
|
member: {},
|
||||||
joined: false,
|
joined: false,
|
||||||
|
@ -76,9 +69,8 @@ export default class RoomActionsView extends LoggedView {
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
const { room } = this.state;
|
const { room } = this.state;
|
||||||
if (room && room.t !== 'd' && this.canViewMembers) {
|
if (room && room.t !== 'd' && this.canViewMembers) {
|
||||||
const { rid } = this.props;
|
|
||||||
try {
|
try {
|
||||||
const counters = await RocketChat.getRoomCounters(rid, room.t);
|
const counters = await RocketChat.getRoomCounters(room.rid, room.t);
|
||||||
if (counters.success) {
|
if (counters.success) {
|
||||||
this.setState({ membersCount: counters.members, joined: counters.joined });
|
this.setState({ membersCount: counters.members, joined: counters.joined });
|
||||||
}
|
}
|
||||||
|
@ -119,14 +111,8 @@ export default class RoomActionsView extends LoggedView {
|
||||||
|
|
||||||
onPressTouchable = (item) => {
|
onPressTouchable = (item) => {
|
||||||
if (item.route) {
|
if (item.route) {
|
||||||
const { componentId } = this.props;
|
const { navigation } = this.props;
|
||||||
Navigation.push(componentId, {
|
navigation.navigate(item.route, item.params);
|
||||||
component: {
|
|
||||||
name: item.route,
|
|
||||||
passProps: item.params,
|
|
||||||
options: item.navigationOptions
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
if (item.event) {
|
if (item.event) {
|
||||||
return item.event();
|
return item.event();
|
||||||
|
@ -181,7 +167,7 @@ export default class RoomActionsView extends LoggedView {
|
||||||
const notificationsAction = {
|
const notificationsAction = {
|
||||||
icon: notifications ? 'bell' : 'Bell-off',
|
icon: notifications ? 'bell' : 'Bell-off',
|
||||||
name: I18n.t(`${ notifications ? 'Enable' : 'Disable' }_notifications`),
|
name: I18n.t(`${ notifications ? 'Enable' : 'Disable' }_notifications`),
|
||||||
event: () => this.toggleNotifications(),
|
event: this.toggleNotifications,
|
||||||
testID: 'room-actions-notifications'
|
testID: 'room-actions-notifications'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -248,13 +234,6 @@ export default class RoomActionsView extends LoggedView {
|
||||||
name: I18n.t('Pinned'),
|
name: I18n.t('Pinned'),
|
||||||
route: 'PinnedMessagesView',
|
route: 'PinnedMessagesView',
|
||||||
testID: 'room-actions-pinned'
|
testID: 'room-actions-pinned'
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: 'code',
|
|
||||||
name: I18n.t('Snippets'),
|
|
||||||
route: 'SnippetedMessagesView',
|
|
||||||
params: { rid },
|
|
||||||
testID: 'room-actions-snippeted'
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
renderItem: this.renderItem
|
renderItem: this.renderItem
|
||||||
|
@ -267,7 +246,7 @@ export default class RoomActionsView extends LoggedView {
|
||||||
icon: 'ban',
|
icon: 'ban',
|
||||||
name: I18n.t(`${ blocker ? 'Unblock' : 'Block' }_user`),
|
name: I18n.t(`${ blocker ? 'Unblock' : 'Block' }_user`),
|
||||||
type: 'danger',
|
type: 'danger',
|
||||||
event: () => this.toggleBlockUser(),
|
event: this.toggleBlockUser,
|
||||||
testID: 'room-actions-block-user'
|
testID: 'room-actions-block-user'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -294,15 +273,9 @@ export default class RoomActionsView extends LoggedView {
|
||||||
name: I18n.t('Add_user'),
|
name: I18n.t('Add_user'),
|
||||||
route: 'SelectedUsersView',
|
route: 'SelectedUsersView',
|
||||||
params: {
|
params: {
|
||||||
nextAction: 'ADD_USER',
|
nextActionID: 'ADD_USER',
|
||||||
rid
|
rid,
|
||||||
},
|
title: I18n.t('Add_user')
|
||||||
navigationOptions: {
|
|
||||||
topBar: {
|
|
||||||
title: {
|
|
||||||
text: I18n.t('Add_user')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
testID: 'room-actions-add-user'
|
testID: 'room-actions-add-user'
|
||||||
});
|
});
|
||||||
|
@ -317,7 +290,7 @@ export default class RoomActionsView extends LoggedView {
|
||||||
icon: 'sign-out',
|
icon: 'sign-out',
|
||||||
name: I18n.t('Leave_channel'),
|
name: I18n.t('Leave_channel'),
|
||||||
type: 'danger',
|
type: 'danger',
|
||||||
event: () => this.leaveChannel(),
|
event: this.leaveChannel,
|
||||||
testID: 'room-actions-leave-channel'
|
testID: 'room-actions-leave-channel'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -468,6 +441,7 @@ export default class RoomActionsView extends LoggedView {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<SafeAreaView style={styles.container} testID='room-actions-view' forceInset={{ bottom: 'never' }}>
|
<SafeAreaView style={styles.container} testID='room-actions-view' forceInset={{ bottom: 'never' }}>
|
||||||
|
<StatusBar />
|
||||||
<SectionList
|
<SectionList
|
||||||
style={styles.container}
|
style={styles.container}
|
||||||
stickySectionHeadersEnabled={false}
|
stickySectionHeadersEnabled={false}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { FlatList, View, Text } from 'react-native';
|
import { FlatList, View, Text } from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import SafeAreaView from 'react-native-safe-area-view';
|
import { SafeAreaView } from 'react-navigation';
|
||||||
import equal from 'deep-equal';
|
import equal from 'deep-equal';
|
||||||
|
|
||||||
import LoggedView from '../View';
|
import LoggedView from '../View';
|
||||||
|
@ -11,6 +11,7 @@ import Message from '../../containers/message/Message';
|
||||||
import RCActivityIndicator from '../../containers/ActivityIndicator';
|
import RCActivityIndicator from '../../containers/ActivityIndicator';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
import RocketChat from '../../lib/rocketchat';
|
import RocketChat from '../../lib/rocketchat';
|
||||||
|
import StatusBar from '../../containers/StatusBar';
|
||||||
|
|
||||||
@connect(state => ({
|
@connect(state => ({
|
||||||
baseUrl: state.settings.Site_Url || state.server ? state.server.server : '',
|
baseUrl: state.settings.Site_Url || state.server ? state.server.server : '',
|
||||||
|
@ -24,14 +25,8 @@ import RocketChat from '../../lib/rocketchat';
|
||||||
}))
|
}))
|
||||||
/** @extends React.Component */
|
/** @extends React.Component */
|
||||||
export default class RoomFilesView extends LoggedView {
|
export default class RoomFilesView extends LoggedView {
|
||||||
static options() {
|
static navigationOptions = {
|
||||||
return {
|
title: I18n.t('Files')
|
||||||
topBar: {
|
|
||||||
title: {
|
|
||||||
text: I18n.t('Files')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
@ -142,6 +137,7 @@ export default class RoomFilesView extends LoggedView {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SafeAreaView style={styles.list} testID='room-files-view' forceInset={{ bottom: 'never' }}>
|
<SafeAreaView style={styles.list} testID='room-files-view' forceInset={{ bottom: 'never' }}>
|
||||||
|
<StatusBar />
|
||||||
<FlatList
|
<FlatList
|
||||||
data={messages}
|
data={messages}
|
||||||
renderItem={this.renderItem}
|
renderItem={this.renderItem}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import {
|
||||||
Text, View, ScrollView, TouchableOpacity, Keyboard, Alert
|
Text, View, ScrollView, TouchableOpacity, Keyboard, Alert
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import SafeAreaView from 'react-native-safe-area-view';
|
import { SafeAreaView } from 'react-navigation';
|
||||||
import equal from 'deep-equal';
|
import equal from 'deep-equal';
|
||||||
|
|
||||||
import { eraseRoom as eraseRoomAction } from '../../actions/room';
|
import { eraseRoom as eraseRoomAction } from '../../actions/room';
|
||||||
|
@ -22,6 +22,7 @@ import SwitchContainer from './SwitchContainer';
|
||||||
import random from '../../utils/random';
|
import random from '../../utils/random';
|
||||||
import log from '../../utils/log';
|
import log from '../../utils/log';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
|
import StatusBar from '../../containers/StatusBar';
|
||||||
|
|
||||||
const PERMISSION_SET_READONLY = 'set-readonly';
|
const PERMISSION_SET_READONLY = 'set-readonly';
|
||||||
const PERMISSION_SET_REACT_WHEN_READONLY = 'set-react-when-readonly';
|
const PERMISSION_SET_REACT_WHEN_READONLY = 'set-react-when-readonly';
|
||||||
|
@ -43,24 +44,18 @@ const PERMISSIONS_ARRAY = [
|
||||||
}))
|
}))
|
||||||
/** @extends React.Component */
|
/** @extends React.Component */
|
||||||
export default class RoomInfoEditView extends LoggedView {
|
export default class RoomInfoEditView extends LoggedView {
|
||||||
static options() {
|
static navigationOptions = {
|
||||||
return {
|
title: I18n.t('Room_Info_Edit')
|
||||||
topBar: {
|
|
||||||
title: {
|
|
||||||
text: I18n.t('Room_Info_Edit')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
rid: PropTypes.string,
|
navigation: PropTypes.object,
|
||||||
eraseRoom: PropTypes.func
|
eraseRoom: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super('RoomInfoEditView', props);
|
super('RoomInfoEditView', props);
|
||||||
const { rid } = props;
|
const rid = props.navigation.getParam('rid');
|
||||||
this.rooms = database.objects('subscriptions').filtered('rid = $0', rid);
|
this.rooms = database.objects('subscriptions').filtered('rid = $0', rid);
|
||||||
this.permissions = {};
|
this.permissions = {};
|
||||||
this.state = {
|
this.state = {
|
||||||
|
@ -298,6 +293,7 @@ export default class RoomInfoEditView extends LoggedView {
|
||||||
contentContainerStyle={sharedStyles.container}
|
contentContainerStyle={sharedStyles.container}
|
||||||
keyboardVerticalOffset={128}
|
keyboardVerticalOffset={128}
|
||||||
>
|
>
|
||||||
|
<StatusBar />
|
||||||
<ScrollView
|
<ScrollView
|
||||||
contentContainerStyle={sharedStyles.containerScrollView}
|
contentContainerStyle={sharedStyles.containerScrollView}
|
||||||
testID='room-info-edit-view-list'
|
testID='room-info-edit-view-list'
|
||||||
|
|
|
@ -3,10 +3,9 @@ import PropTypes from 'prop-types';
|
||||||
import { View, Text, ScrollView } from 'react-native';
|
import { View, Text, ScrollView } from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import SafeAreaView from 'react-native-safe-area-view';
|
import { SafeAreaView } from 'react-navigation';
|
||||||
import equal from 'deep-equal';
|
import equal from 'deep-equal';
|
||||||
|
|
||||||
import Navigation from '../../lib/Navigation';
|
|
||||||
import LoggedView from '../View';
|
import LoggedView from '../View';
|
||||||
import Status from '../../containers/Status';
|
import Status from '../../containers/Status';
|
||||||
import Avatar from '../../containers/Avatar';
|
import Avatar from '../../containers/Avatar';
|
||||||
|
@ -17,7 +16,8 @@ import RocketChat from '../../lib/rocketchat';
|
||||||
import log from '../../utils/log';
|
import log from '../../utils/log';
|
||||||
import RoomTypeIcon from '../../containers/RoomTypeIcon';
|
import RoomTypeIcon from '../../containers/RoomTypeIcon';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
import Icons from '../../lib/Icons';
|
import { CustomHeaderButtons, Item } from '../../containers/HeaderButton';
|
||||||
|
import StatusBar from '../../containers/StatusBar';
|
||||||
|
|
||||||
const PERMISSION_EDIT_ROOM = 'edit-room';
|
const PERMISSION_EDIT_ROOM = 'edit-room';
|
||||||
|
|
||||||
|
@ -45,19 +45,23 @@ const getRoomTitle = room => (room.t === 'd'
|
||||||
}))
|
}))
|
||||||
/** @extends React.Component */
|
/** @extends React.Component */
|
||||||
export default class RoomInfoView extends LoggedView {
|
export default class RoomInfoView extends LoggedView {
|
||||||
static options() {
|
static navigationOptions = ({ navigation }) => {
|
||||||
|
const showEdit = navigation.getParam('showEdit');
|
||||||
|
const rid = navigation.getParam('rid');
|
||||||
return {
|
return {
|
||||||
topBar: {
|
title: I18n.t('Room_Info'),
|
||||||
title: {
|
headerRight: showEdit
|
||||||
text: I18n.t('Room_Info')
|
? (
|
||||||
}
|
<CustomHeaderButtons>
|
||||||
}
|
<Item iconName='edit' onPress={() => navigation.navigate('RoomInfoEditView', { rid })} testID='room-info-view-edit-button' />
|
||||||
|
</CustomHeaderButtons>
|
||||||
|
)
|
||||||
|
: null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
componentId: PropTypes.string,
|
navigation: PropTypes.object,
|
||||||
rid: PropTypes.string,
|
|
||||||
user: PropTypes.shape({
|
user: PropTypes.shape({
|
||||||
id: PropTypes.string,
|
id: PropTypes.string,
|
||||||
token: PropTypes.string
|
token: PropTypes.string
|
||||||
|
@ -65,46 +69,30 @@ export default class RoomInfoView extends LoggedView {
|
||||||
baseUrl: PropTypes.string,
|
baseUrl: PropTypes.string,
|
||||||
activeUsers: PropTypes.object,
|
activeUsers: PropTypes.object,
|
||||||
Message_TimeFormat: PropTypes.string,
|
Message_TimeFormat: PropTypes.string,
|
||||||
allRoles: PropTypes.object,
|
allRoles: PropTypes.object
|
||||||
room: PropTypes.object
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super('RoomInfoView', props);
|
super('RoomInfoView', props);
|
||||||
const { rid, room } = props;
|
const rid = props.navigation.getParam('rid');
|
||||||
this.rooms = database.objects('subscriptions').filtered('rid = $0', rid);
|
this.rooms = database.objects('subscriptions').filtered('rid = $0', rid);
|
||||||
this.sub = {
|
this.sub = {
|
||||||
unsubscribe: () => {}
|
unsubscribe: () => {}
|
||||||
};
|
};
|
||||||
this.state = {
|
this.state = {
|
||||||
room,
|
room: this.rooms[0] || {},
|
||||||
roomUser: {},
|
roomUser: {},
|
||||||
roles: []
|
roles: []
|
||||||
};
|
};
|
||||||
Navigation.events().bindComponent(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
this.rooms.addListener(this.updateRoom);
|
this.rooms.addListener(this.updateRoom);
|
||||||
|
const { room } = this.state;
|
||||||
let room = {};
|
|
||||||
if (this.rooms.length > 0) {
|
|
||||||
room = this.rooms[0]; // eslint-disable-line prefer-destructuring
|
|
||||||
} else {
|
|
||||||
room = this.state.room; // eslint-disable-line
|
|
||||||
}
|
|
||||||
const { componentId } = this.props;
|
|
||||||
const permissions = RocketChat.hasPermission([PERMISSION_EDIT_ROOM], room.rid);
|
const permissions = RocketChat.hasPermission([PERMISSION_EDIT_ROOM], room.rid);
|
||||||
if (permissions[PERMISSION_EDIT_ROOM]) {
|
if (permissions[PERMISSION_EDIT_ROOM]) {
|
||||||
Navigation.mergeOptions(componentId, {
|
const { navigation } = this.props;
|
||||||
topBar: {
|
navigation.setParams({ showEdit: true });
|
||||||
rightButtons: [{
|
|
||||||
id: 'edit',
|
|
||||||
icon: Icons.getSource('edit'),
|
|
||||||
testID: 'room-info-view-edit-button'
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// get user of room
|
// get user of room
|
||||||
|
@ -164,21 +152,6 @@ export default class RoomInfoView extends LoggedView {
|
||||||
this.sub.unsubscribe();
|
this.sub.unsubscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
navigationButtonPressed = ({ buttonId }) => {
|
|
||||||
const { rid, componentId } = this.props;
|
|
||||||
if (buttonId === 'edit') {
|
|
||||||
Navigation.push(componentId, {
|
|
||||||
component: {
|
|
||||||
id: 'RoomInfoEditView',
|
|
||||||
name: 'RoomInfoEditView',
|
|
||||||
passProps: {
|
|
||||||
rid
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getFullUserData = async(username) => {
|
getFullUserData = async(username) => {
|
||||||
try {
|
try {
|
||||||
const result = await RocketChat.subscribe('fullUserData', username);
|
const result = await RocketChat.subscribe('fullUserData', username);
|
||||||
|
@ -312,6 +285,7 @@ export default class RoomInfoView extends LoggedView {
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<ScrollView style={styles.scroll}>
|
<ScrollView style={styles.scroll}>
|
||||||
|
<StatusBar />
|
||||||
<SafeAreaView style={styles.container} testID='room-info-view' forceInset={{ bottom: 'never' }}>
|
<SafeAreaView style={styles.container} testID='room-info-view' forceInset={{ bottom: 'never' }}>
|
||||||
<View style={styles.avatarContainer}>
|
<View style={styles.avatarContainer}>
|
||||||
{this.renderAvatar(room, roomUser)}
|
{this.renderAvatar(room, roomUser)}
|
||||||
|
|
|
@ -3,10 +3,9 @@ import PropTypes from 'prop-types';
|
||||||
import { FlatList, View } from 'react-native';
|
import { FlatList, View } from 'react-native';
|
||||||
import ActionSheet from 'react-native-action-sheet';
|
import ActionSheet from 'react-native-action-sheet';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import SafeAreaView from 'react-native-safe-area-view';
|
import { SafeAreaView } from 'react-navigation';
|
||||||
import equal from 'deep-equal';
|
import equal from 'deep-equal';
|
||||||
|
|
||||||
import Navigation from '../../lib/Navigation';
|
|
||||||
import LoggedView from '../View';
|
import LoggedView from '../View';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
import UserItem from '../../presentation/UserItem';
|
import UserItem from '../../presentation/UserItem';
|
||||||
|
@ -15,11 +14,12 @@ import RocketChat from '../../lib/rocketchat';
|
||||||
import database from '../../lib/realm';
|
import database from '../../lib/realm';
|
||||||
import { showToast } from '../../utils/info';
|
import { showToast } from '../../utils/info';
|
||||||
import log from '../../utils/log';
|
import log from '../../utils/log';
|
||||||
import { isAndroid } from '../../utils/deviceInfo';
|
|
||||||
import { vibrate } from '../../utils/vibration';
|
import { vibrate } from '../../utils/vibration';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
import SearchBox from '../../containers/SearchBox';
|
import SearchBox from '../../containers/SearchBox';
|
||||||
import protectedFunction from '../../lib/methods/helpers/protectedFunction';
|
import protectedFunction from '../../lib/methods/helpers/protectedFunction';
|
||||||
|
import { CustomHeaderButtons, Item } from '../../containers/HeaderButton';
|
||||||
|
import StatusBar from '../../containers/StatusBar';
|
||||||
|
|
||||||
@connect(state => ({
|
@connect(state => ({
|
||||||
baseUrl: state.settings.Site_Url || state.server ? state.server.server : '',
|
baseUrl: state.settings.Site_Url || state.server ? state.server.server : '',
|
||||||
|
@ -31,24 +31,22 @@ import protectedFunction from '../../lib/methods/helpers/protectedFunction';
|
||||||
}))
|
}))
|
||||||
/** @extends React.Component */
|
/** @extends React.Component */
|
||||||
export default class RoomMembersView extends LoggedView {
|
export default class RoomMembersView extends LoggedView {
|
||||||
static options() {
|
static navigationOptions = ({ navigation }) => {
|
||||||
|
const toggleStatus = navigation.getParam('toggleStatus', () => {});
|
||||||
|
const allUsers = navigation.getParam('allUsers');
|
||||||
|
const toggleText = allUsers ? I18n.t('Online') : I18n.t('All');
|
||||||
return {
|
return {
|
||||||
topBar: {
|
title: I18n.t('Members'),
|
||||||
title: {
|
headerRight: (
|
||||||
text: I18n.t('Members')
|
<CustomHeaderButtons>
|
||||||
},
|
<Item title={toggleText} onPress={toggleStatus} testID='room-members-view-toggle-status' />
|
||||||
rightButtons: [{
|
</CustomHeaderButtons>
|
||||||
id: 'toggleOnline',
|
)
|
||||||
text: I18n.t('Online'),
|
|
||||||
testID: 'room-members-view-toggle-status',
|
|
||||||
color: isAndroid ? '#FFF' : undefined
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
componentId: PropTypes.string,
|
navigation: PropTypes.object,
|
||||||
rid: PropTypes.string,
|
rid: PropTypes.string,
|
||||||
members: PropTypes.array,
|
members: PropTypes.array,
|
||||||
baseUrl: PropTypes.string,
|
baseUrl: PropTypes.string,
|
||||||
|
@ -65,7 +63,7 @@ export default class RoomMembersView extends LoggedView {
|
||||||
this.CANCEL_INDEX = 0;
|
this.CANCEL_INDEX = 0;
|
||||||
this.MUTE_INDEX = 1;
|
this.MUTE_INDEX = 1;
|
||||||
this.actionSheetOptions = [''];
|
this.actionSheetOptions = [''];
|
||||||
const { rid, members, room } = props;
|
const { rid, members } = props.navigation.state.params;
|
||||||
this.rooms = database.objects('subscriptions').filtered('rid = $0', rid);
|
this.rooms = database.objects('subscriptions').filtered('rid = $0', rid);
|
||||||
this.permissions = RocketChat.hasPermission(['mute-user'], rid);
|
this.permissions = RocketChat.hasPermission(['mute-user'], rid);
|
||||||
this.state = {
|
this.state = {
|
||||||
|
@ -75,15 +73,17 @@ export default class RoomMembersView extends LoggedView {
|
||||||
members,
|
members,
|
||||||
membersFiltered: [],
|
membersFiltered: [],
|
||||||
userLongPressed: {},
|
userLongPressed: {},
|
||||||
room,
|
room: this.rooms[0] || {},
|
||||||
options: []
|
options: []
|
||||||
};
|
};
|
||||||
Navigation.events().bindComponent(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.fetchMembers();
|
this.fetchMembers();
|
||||||
this.rooms.addListener(this.updateRoom);
|
this.rooms.addListener(this.updateRoom);
|
||||||
|
|
||||||
|
const { navigation } = this.props;
|
||||||
|
navigation.setParams({ toggleStatus: this.toggleStatus });
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
|
@ -128,29 +128,6 @@ export default class RoomMembersView extends LoggedView {
|
||||||
this.setState({ filtering: !!text, membersFiltered });
|
this.setState({ filtering: !!text, membersFiltered });
|
||||||
})
|
})
|
||||||
|
|
||||||
navigationButtonPressed = ({ buttonId }) => {
|
|
||||||
const { allUsers } = this.state;
|
|
||||||
const { componentId } = this.props;
|
|
||||||
|
|
||||||
if (buttonId === 'toggleOnline') {
|
|
||||||
try {
|
|
||||||
Navigation.mergeOptions(componentId, {
|
|
||||||
topBar: {
|
|
||||||
rightButtons: [{
|
|
||||||
id: 'toggleOnline',
|
|
||||||
text: allUsers ? I18n.t('Online') : I18n.t('All'),
|
|
||||||
testID: 'room-members-view-toggle-status',
|
|
||||||
color: isAndroid ? '#FFF' : undefined
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.fetchMembers(!allUsers);
|
|
||||||
} catch (e) {
|
|
||||||
log('RoomMembers.onNavigationButtonPressed', e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onPressUser = async(item) => {
|
onPressUser = async(item) => {
|
||||||
try {
|
try {
|
||||||
const subscriptions = database.objects('subscriptions').filtered('name = $0', item.username);
|
const subscriptions = database.objects('subscriptions').filtered('name = $0', item.username);
|
||||||
|
@ -187,6 +164,15 @@ export default class RoomMembersView extends LoggedView {
|
||||||
this.showActionSheet();
|
this.showActionSheet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleStatus = () => {
|
||||||
|
try {
|
||||||
|
const { allUsers } = this.state;
|
||||||
|
this.fetchMembers(!allUsers);
|
||||||
|
} catch (e) {
|
||||||
|
log('RoomMembers.toggleStatus', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
showActionSheet = () => {
|
showActionSheet = () => {
|
||||||
ActionSheet.showActionSheetWithOptions({
|
ActionSheet.showActionSheetWithOptions({
|
||||||
options: this.actionSheetOptions,
|
options: this.actionSheetOptions,
|
||||||
|
@ -199,9 +185,11 @@ export default class RoomMembersView extends LoggedView {
|
||||||
|
|
||||||
fetchMembers = async(status) => {
|
fetchMembers = async(status) => {
|
||||||
const { rid } = this.state;
|
const { rid } = this.state;
|
||||||
|
const { navigation } = this.props;
|
||||||
const membersResult = await RocketChat.getRoomMembers(rid, status);
|
const membersResult = await RocketChat.getRoomMembers(rid, status);
|
||||||
const members = membersResult.records;
|
const members = membersResult.records;
|
||||||
this.setState({ allUsers: status, members });
|
this.setState({ allUsers: status, members });
|
||||||
|
navigation.setParams({ allUsers: status });
|
||||||
}
|
}
|
||||||
|
|
||||||
updateRoom = () => {
|
updateRoom = () => {
|
||||||
|
@ -212,16 +200,9 @@ export default class RoomMembersView extends LoggedView {
|
||||||
}
|
}
|
||||||
|
|
||||||
goRoom = async({ rid, name }) => {
|
goRoom = async({ rid, name }) => {
|
||||||
const { componentId } = this.props;
|
const { navigation } = this.props;
|
||||||
await Navigation.popToRoot(componentId);
|
await navigation.popToTop();
|
||||||
Navigation.push('RoomsListView', {
|
navigation.navigate('RoomView', { rid, name, t: 'd' });
|
||||||
component: {
|
|
||||||
name: 'RoomView',
|
|
||||||
passProps: {
|
|
||||||
rid, name, t: 'd'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleMute = async() => {
|
handleMute = async() => {
|
||||||
|
@ -272,6 +253,7 @@ export default class RoomMembersView extends LoggedView {
|
||||||
} = this.state;
|
} = this.state;
|
||||||
return (
|
return (
|
||||||
<SafeAreaView style={styles.list} testID='room-members-view' forceInset={{ bottom: 'never' }}>
|
<SafeAreaView style={styles.list} testID='room-members-view' forceInset={{ bottom: 'never' }}>
|
||||||
|
<StatusBar />
|
||||||
<FlatList
|
<FlatList
|
||||||
data={filtering ? membersFiltered : members}
|
data={filtering ? membersFiltered : members}
|
||||||
renderItem={this.renderItem}
|
renderItem={this.renderItem}
|
||||||
|
|
|
@ -18,9 +18,7 @@ const TITLE_SIZE = 18;
|
||||||
const ICON_SIZE = 18;
|
const ICON_SIZE = 18;
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1
|
||||||
justifyContent: 'center',
|
|
||||||
backgroundColor: isIOS ? 'transparent' : '#2F343D'
|
|
||||||
},
|
},
|
||||||
titleContainer: {
|
titleContainer: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
|
@ -175,25 +173,16 @@ export default class RoomHeaderView extends Component {
|
||||||
window, title, usersTyping
|
window, title, usersTyping
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const portrait = window.height > window.width;
|
const portrait = window.height > window.width;
|
||||||
let height = isIOS ? 44 : 60;
|
|
||||||
let scale = 1;
|
let scale = 1;
|
||||||
|
|
||||||
if (!portrait) {
|
if (!portrait) {
|
||||||
if (isIOS) {
|
|
||||||
height = 32;
|
|
||||||
}
|
|
||||||
if (usersTyping.length > 0) {
|
if (usersTyping.length > 0) {
|
||||||
scale = 0.8;
|
scale = 0.8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View style={styles.container}>
|
||||||
style={[
|
|
||||||
styles.container,
|
|
||||||
{ width: window.width - 150, height }
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<View style={styles.titleContainer}>
|
<View style={styles.titleContainer}>
|
||||||
{this.renderIcon()}
|
{this.renderIcon()}
|
||||||
<Text style={[styles.title, { fontSize: TITLE_SIZE * scale }]} numberOfLines={1}>{title}</Text>
|
<Text style={[styles.title, { fontSize: TITLE_SIZE * scale }]} numberOfLines={1}>{title}</Text>
|
||||||
|
|
|
@ -5,10 +5,9 @@ import {
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { RectButton } from 'react-native-gesture-handler';
|
import { RectButton } from 'react-native-gesture-handler';
|
||||||
import SafeAreaView from 'react-native-safe-area-view';
|
import { SafeAreaView } from 'react-navigation';
|
||||||
import equal from 'deep-equal';
|
import equal from 'deep-equal';
|
||||||
|
|
||||||
import Navigation from '../../lib/Navigation';
|
|
||||||
import { openRoom as openRoomAction, closeRoom as closeRoomAction, setLastOpen as setLastOpenAction } from '../../actions/room';
|
import { openRoom as openRoomAction, closeRoom as closeRoomAction, setLastOpen as setLastOpenAction } from '../../actions/room';
|
||||||
import { toggleReactionPicker as toggleReactionPickerAction, actionsShow as actionsShowAction } from '../../actions/messages';
|
import { toggleReactionPicker as toggleReactionPickerAction, actionsShow as actionsShowAction } from '../../actions/messages';
|
||||||
import LoggedView from '../View';
|
import LoggedView from '../View';
|
||||||
|
@ -25,8 +24,10 @@ import styles from './styles';
|
||||||
import log from '../../utils/log';
|
import log from '../../utils/log';
|
||||||
import { isIOS } from '../../utils/deviceInfo';
|
import { isIOS } from '../../utils/deviceInfo';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
import Icons from '../../lib/Icons';
|
|
||||||
import ConnectionBadge from '../../containers/ConnectionBadge';
|
import ConnectionBadge from '../../containers/ConnectionBadge';
|
||||||
|
import { CustomHeaderButtons, Item } from '../../containers/HeaderButton';
|
||||||
|
import RoomHeaderView from './Header';
|
||||||
|
import StatusBar from '../../containers/StatusBar';
|
||||||
|
|
||||||
@connect(state => ({
|
@connect(state => ({
|
||||||
user: {
|
user: {
|
||||||
|
@ -47,31 +48,27 @@ import ConnectionBadge from '../../containers/ConnectionBadge';
|
||||||
}))
|
}))
|
||||||
/** @extends React.Component */
|
/** @extends React.Component */
|
||||||
export default class RoomView extends LoggedView {
|
export default class RoomView extends LoggedView {
|
||||||
static options() {
|
static navigationOptions = ({ navigation }) => {
|
||||||
|
const rid = navigation.getParam('rid');
|
||||||
|
const t = navigation.getParam('t');
|
||||||
|
const f = navigation.getParam('f');
|
||||||
|
const toggleFav = navigation.getParam('toggleFav', () => {});
|
||||||
|
const starIcon = f ? 'Star-filled' : 'star';
|
||||||
return {
|
return {
|
||||||
topBar: {
|
headerTitle: <RoomHeaderView />,
|
||||||
title: {
|
headerRight: t === 'l'
|
||||||
component: {
|
? null
|
||||||
name: 'RoomHeaderView',
|
: (
|
||||||
alignment: 'left'
|
<CustomHeaderButtons>
|
||||||
}
|
<Item title='star' iconName={starIcon} onPress={toggleFav} testID='room-view-header-star' />
|
||||||
},
|
<Item title='more' iconName='menu' onPress={() => navigation.navigate('RoomActionsView', { rid })} testID='room-view-header-actions' />
|
||||||
rightButtons: [{
|
</CustomHeaderButtons>
|
||||||
id: 'more',
|
)
|
||||||
testID: 'room-view-header-actions',
|
|
||||||
icon: Icons.getSource('more')
|
|
||||||
}, {
|
|
||||||
id: 'star',
|
|
||||||
testID: 'room-view-header-star',
|
|
||||||
icon: Icons.getSource('starOutline')
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
blurOnUnmount: true
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
componentId: PropTypes.string,
|
navigation: PropTypes.object,
|
||||||
openRoom: PropTypes.func.isRequired,
|
openRoom: PropTypes.func.isRequired,
|
||||||
setLastOpen: PropTypes.func.isRequired,
|
setLastOpen: PropTypes.func.isRequired,
|
||||||
user: PropTypes.shape({
|
user: PropTypes.shape({
|
||||||
|
@ -79,9 +76,6 @@ export default class RoomView extends LoggedView {
|
||||||
username: PropTypes.string.isRequired,
|
username: PropTypes.string.isRequired,
|
||||||
token: PropTypes.string.isRequired
|
token: PropTypes.string.isRequired
|
||||||
}),
|
}),
|
||||||
rid: PropTypes.string,
|
|
||||||
name: PropTypes.string,
|
|
||||||
t: PropTypes.string,
|
|
||||||
showActions: PropTypes.bool,
|
showActions: PropTypes.bool,
|
||||||
showErrorActions: PropTypes.bool,
|
showErrorActions: PropTypes.bool,
|
||||||
actionMessage: PropTypes.object,
|
actionMessage: PropTypes.object,
|
||||||
|
@ -93,7 +87,7 @@ export default class RoomView extends LoggedView {
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super('RoomView', props);
|
super('RoomView', props);
|
||||||
this.rid = props.rid;
|
this.rid = props.navigation.getParam('rid');
|
||||||
this.rooms = database.objects('subscriptions').filtered('rid = $0', this.rid);
|
this.rooms = database.objects('subscriptions').filtered('rid = $0', this.rid);
|
||||||
this.state = {
|
this.state = {
|
||||||
loaded: false,
|
loaded: false,
|
||||||
|
@ -101,12 +95,14 @@ export default class RoomView extends LoggedView {
|
||||||
room: {}
|
room: {}
|
||||||
};
|
};
|
||||||
this.onReactionPress = this.onReactionPress.bind(this);
|
this.onReactionPress = this.onReactionPress.bind(this);
|
||||||
Navigation.events().bindComponent(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
const { navigation } = this.props;
|
||||||
|
navigation.setParams({ toggleFav: this.toggleFav });
|
||||||
|
|
||||||
if (this.rooms.length === 0 && this.rid) {
|
if (this.rooms.length === 0 && this.rid) {
|
||||||
const { rid, name, t } = this.props;
|
const { rid, name, t } = navigation.state.params;
|
||||||
this.setState(
|
this.setState(
|
||||||
{ room: { rid, name, t } },
|
{ room: { rid, name, t } },
|
||||||
() => this.updateRoom()
|
() => this.updateRoom()
|
||||||
|
@ -150,26 +146,10 @@ export default class RoomView extends LoggedView {
|
||||||
|
|
||||||
componentDidUpdate(prevProps, prevState) {
|
componentDidUpdate(prevProps, prevState) {
|
||||||
const { room } = this.state;
|
const { room } = this.state;
|
||||||
const { componentId, appState } = this.props;
|
const { appState, navigation } = this.props;
|
||||||
|
|
||||||
if (prevState.room.f !== room.f) {
|
if (prevState.room.f !== room.f) {
|
||||||
const rightButtons = [{
|
navigation.setParams({ f: room.f });
|
||||||
id: 'star',
|
|
||||||
testID: 'room-view-header-star',
|
|
||||||
icon: room.f ? Icons.getSource('star') : Icons.getSource('starOutline')
|
|
||||||
}];
|
|
||||||
if (room.t !== 'l') {
|
|
||||||
rightButtons.unshift({
|
|
||||||
id: 'more',
|
|
||||||
testID: 'room-view-header-actions',
|
|
||||||
icon: Icons.getSource('more')
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Navigation.mergeOptions(componentId, {
|
|
||||||
topBar: {
|
|
||||||
rightButtons
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if (appState === 'foreground' && appState !== prevProps.appState) {
|
} else if (appState === 'foreground' && appState !== prevProps.appState) {
|
||||||
RocketChat.loadMissedMessages(room).catch(e => console.log(e));
|
RocketChat.loadMissedMessages(room).catch(e => console.log(e));
|
||||||
RocketChat.readMessages(room.rid).catch(e => console.log(e));
|
RocketChat.readMessages(room.rid).catch(e => console.log(e));
|
||||||
|
@ -207,30 +187,6 @@ export default class RoomView extends LoggedView {
|
||||||
this.setState(...args);
|
this.setState(...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
navigationButtonPressed = ({ buttonId }) => {
|
|
||||||
const { room } = this.state;
|
|
||||||
const { rid, f } = room;
|
|
||||||
const { componentId } = this.props;
|
|
||||||
|
|
||||||
if (buttonId === 'more') {
|
|
||||||
Navigation.push(componentId, {
|
|
||||||
component: {
|
|
||||||
id: 'RoomActionsView',
|
|
||||||
name: 'RoomActionsView',
|
|
||||||
passProps: {
|
|
||||||
rid
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if (buttonId === 'star') {
|
|
||||||
try {
|
|
||||||
RocketChat.toggleFavorite(rid, !f);
|
|
||||||
} catch (e) {
|
|
||||||
log('toggleFavorite', e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line react/sort-comp
|
// eslint-disable-next-line react/sort-comp
|
||||||
updateRoom = () => {
|
updateRoom = () => {
|
||||||
const { openRoom, setLastOpen } = this.props;
|
const { openRoom, setLastOpen } = this.props;
|
||||||
|
@ -259,6 +215,16 @@ export default class RoomView extends LoggedView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleFav = () => {
|
||||||
|
try {
|
||||||
|
const { room } = this.state;
|
||||||
|
const { rid, f } = room;
|
||||||
|
RocketChat.toggleFavorite(rid, !f);
|
||||||
|
} catch (e) {
|
||||||
|
log('toggleFavorite', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sendMessage = (message) => {
|
sendMessage = (message) => {
|
||||||
const { setLastOpen } = this.props;
|
const { setLastOpen } = this.props;
|
||||||
LayoutAnimation.easeInEaseOut();
|
LayoutAnimation.easeInEaseOut();
|
||||||
|
@ -268,9 +234,8 @@ export default class RoomView extends LoggedView {
|
||||||
};
|
};
|
||||||
|
|
||||||
joinRoom = async() => {
|
joinRoom = async() => {
|
||||||
const { rid } = this.props;
|
|
||||||
try {
|
try {
|
||||||
const result = await RocketChat.joinRoom(rid);
|
const result = await RocketChat.joinRoom(this.rid);
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
this.internalSetState({
|
this.internalSetState({
|
||||||
joined: true
|
joined: true
|
||||||
|
@ -388,6 +353,7 @@ export default class RoomView extends LoggedView {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SafeAreaView style={styles.container} testID='room-view' forceInset={{ bottom: 'never' }}>
|
<SafeAreaView style={styles.container} testID='room-view' forceInset={{ bottom: 'never' }}>
|
||||||
|
<StatusBar />
|
||||||
{this.renderList()}
|
{this.renderList()}
|
||||||
{room._id && showActions
|
{room._id && showActions
|
||||||
? <MessageActions room={room} user={user} />
|
? <MessageActions room={room} user={user} />
|
||||||
|
|
|
@ -39,7 +39,7 @@ const styles = StyleSheet.create({
|
||||||
});
|
});
|
||||||
|
|
||||||
const Header = ({
|
const Header = ({
|
||||||
isFetching, serverName, showServerDropdown, width, setSearchInputRef, showSearchHeader, onSearchChangeText, onPress
|
isFetching, serverName, showServerDropdown, setSearchInputRef, showSearchHeader, onSearchChangeText, onPress
|
||||||
}) => {
|
}) => {
|
||||||
if (showSearchHeader) {
|
if (showSearchHeader) {
|
||||||
return (
|
return (
|
||||||
|
@ -55,7 +55,7 @@ const Header = ({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<View style={[styles.container, { width: width - 150 }]}>
|
<View style={styles.container}>
|
||||||
<TouchableOpacity onPress={onPress} testID='rooms-list-header-server-dropdown-button'>
|
<TouchableOpacity onPress={onPress} testID='rooms-list-header-server-dropdown-button'>
|
||||||
{isFetching ? <Text style={styles.updating}>{I18n.t('Updating')}</Text> : null}
|
{isFetching ? <Text style={styles.updating}>{I18n.t('Updating')}</Text> : null}
|
||||||
<View style={styles.button}>
|
<View style={styles.button}>
|
||||||
|
@ -74,8 +74,7 @@ Header.propTypes = {
|
||||||
onSearchChangeText: PropTypes.func.isRequired,
|
onSearchChangeText: PropTypes.func.isRequired,
|
||||||
setSearchInputRef: PropTypes.func.isRequired,
|
setSearchInputRef: PropTypes.func.isRequired,
|
||||||
isFetching: PropTypes.bool,
|
isFetching: PropTypes.bool,
|
||||||
serverName: PropTypes.string,
|
serverName: PropTypes.string
|
||||||
width: PropTypes.number
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Header.defaultProps = {
|
Header.defaultProps = {
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { responsive } from 'react-native-responsive-ui';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
toggleServerDropdown, closeServerDropdown, closeSortDropdown, setSearch as setSearchAction
|
toggleServerDropdown, closeServerDropdown, closeSortDropdown, setSearch as setSearchAction
|
||||||
} from '../../../actions/rooms';
|
} from '../../../actions/rooms';
|
||||||
import Header from './Header';
|
import Header from './Header';
|
||||||
|
|
||||||
@responsive
|
|
||||||
@connect(state => ({
|
@connect(state => ({
|
||||||
showServerDropdown: state.rooms.showServerDropdown,
|
showServerDropdown: state.rooms.showServerDropdown,
|
||||||
showSortDropdown: state.rooms.showSortDropdown,
|
showSortDropdown: state.rooms.showSortDropdown,
|
||||||
|
@ -31,8 +29,7 @@ export default class RoomsListHeaderView extends PureComponent {
|
||||||
open: PropTypes.func,
|
open: PropTypes.func,
|
||||||
close: PropTypes.func,
|
close: PropTypes.func,
|
||||||
closeSort: PropTypes.func,
|
closeSort: PropTypes.func,
|
||||||
setSearch: PropTypes.func,
|
setSearch: PropTypes.func
|
||||||
window: PropTypes.object
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
|
@ -69,10 +66,9 @@ export default class RoomsListHeaderView extends PureComponent {
|
||||||
this.searchInputRef = ref;
|
this.searchInputRef = ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
serverName, showServerDropdown, showSearchHeader, isFetching, window: { width }
|
serverName, showServerDropdown, showSearchHeader, isFetching
|
||||||
} = this.props;
|
} = this.props;
|
||||||
return (
|
return (
|
||||||
<Header
|
<Header
|
||||||
|
@ -80,7 +76,6 @@ export default class RoomsListHeaderView extends PureComponent {
|
||||||
showServerDropdown={showServerDropdown}
|
showServerDropdown={showServerDropdown}
|
||||||
showSearchHeader={showSearchHeader}
|
showSearchHeader={showSearchHeader}
|
||||||
isFetching={isFetching}
|
isFetching={isFetching}
|
||||||
width={width}
|
|
||||||
setSearchInputRef={this.setSearchInputRef}
|
setSearchInputRef={this.setSearchInputRef}
|
||||||
onPress={this.onPress}
|
onPress={this.onPress}
|
||||||
onSearchChangeText={text => this.onSearchChangeText(text)}
|
onSearchChangeText={text => this.onSearchChangeText(text)}
|
||||||
|
|
|
@ -5,8 +5,8 @@ import {
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import equal from 'deep-equal';
|
import equal from 'deep-equal';
|
||||||
|
import { withNavigation } from 'react-navigation';
|
||||||
|
|
||||||
import Navigation from '../../lib/Navigation';
|
|
||||||
import { toggleServerDropdown as toggleServerDropdownAction } from '../../actions/rooms';
|
import { toggleServerDropdown as toggleServerDropdownAction } from '../../actions/rooms';
|
||||||
import { selectServerRequest as selectServerRequestAction } from '../../actions/server';
|
import { selectServerRequest as selectServerRequestAction } from '../../actions/server';
|
||||||
import { appStart as appStartAction } from '../../actions';
|
import { appStart as appStartAction } from '../../actions';
|
||||||
|
@ -29,8 +29,9 @@ const ANIMATION_DURATION = 200;
|
||||||
selectServerRequest: server => dispatch(selectServerRequestAction(server)),
|
selectServerRequest: server => dispatch(selectServerRequestAction(server)),
|
||||||
appStart: () => dispatch(appStartAction('outside'))
|
appStart: () => dispatch(appStartAction('outside'))
|
||||||
}))
|
}))
|
||||||
export default class ServerDropdown extends Component {
|
class ServerDropdown extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
navigation: PropTypes.object,
|
||||||
closeServerDropdown: PropTypes.bool,
|
closeServerDropdown: PropTypes.bool,
|
||||||
server: PropTypes.string,
|
server: PropTypes.string,
|
||||||
toggleServerDropdown: PropTypes.func,
|
toggleServerDropdown: PropTypes.func,
|
||||||
|
@ -108,30 +109,11 @@ export default class ServerDropdown extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
addServer = () => {
|
addServer = () => {
|
||||||
const { server } = this.props;
|
const { server, navigation } = this.props;
|
||||||
|
|
||||||
this.close();
|
this.close();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
Navigation.showModal({
|
navigation.navigate('OnboardingView', { previousServer: server });
|
||||||
stack: {
|
|
||||||
children: [{
|
|
||||||
component: {
|
|
||||||
name: 'OnboardingView',
|
|
||||||
passProps: {
|
|
||||||
previousServer: server
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
topBar: {
|
|
||||||
visible: false
|
|
||||||
},
|
|
||||||
layout: {
|
|
||||||
orientation: 'portrait'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, ANIMATION_DURATION);
|
}, ANIMATION_DURATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,3 +210,4 @@ export default class ServerDropdown extends Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
export default withNavigation(ServerDropdown);
|
||||||
|
|
|
@ -5,9 +5,9 @@ import {
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { isEqual } from 'lodash';
|
import { isEqual } from 'lodash';
|
||||||
import SafeAreaView from 'react-native-safe-area-view';
|
import { SafeAreaView, NavigationEvents } from 'react-navigation';
|
||||||
|
import Orientation from 'react-native-orientation-locker';
|
||||||
|
|
||||||
import Navigation from '../../lib/Navigation';
|
|
||||||
import SearchBox from '../../containers/SearchBox';
|
import SearchBox from '../../containers/SearchBox';
|
||||||
import ConnectionBadge from '../../containers/ConnectionBadge';
|
import ConnectionBadge from '../../containers/ConnectionBadge';
|
||||||
import database from '../../lib/realm';
|
import database from '../../lib/realm';
|
||||||
|
@ -23,13 +23,16 @@ import Touch from '../../utils/touch';
|
||||||
import {
|
import {
|
||||||
toggleSortDropdown as toggleSortDropdownAction,
|
toggleSortDropdown as toggleSortDropdownAction,
|
||||||
openSearchHeader as openSearchHeaderAction,
|
openSearchHeader as openSearchHeaderAction,
|
||||||
closeSearchHeader as closeSearchHeaderAction,
|
closeSearchHeader as closeSearchHeaderAction
|
||||||
roomsRequest as roomsRequestAction
|
// roomsRequest as roomsRequestAction
|
||||||
} from '../../actions/rooms';
|
} from '../../actions/rooms';
|
||||||
import { appStart as appStartAction } from '../../actions';
|
import { appStart as appStartAction } from '../../actions';
|
||||||
import debounce from '../../utils/debounce';
|
import debounce from '../../utils/debounce';
|
||||||
import { isIOS, isAndroid } from '../../utils/deviceInfo';
|
import { isIOS, isAndroid } from '../../utils/deviceInfo';
|
||||||
import Icons, { CustomIcon } from '../../lib/Icons';
|
import { CustomIcon } from '../../lib/Icons';
|
||||||
|
import RoomsListHeaderView from './Header';
|
||||||
|
import { DrawerButton, CustomHeaderButtons, Item } from '../../containers/HeaderButton';
|
||||||
|
import StatusBar from '../../containers/StatusBar';
|
||||||
|
|
||||||
const ROW_HEIGHT = 70;
|
const ROW_HEIGHT = 70;
|
||||||
const SCROLL_OFFSET = 56;
|
const SCROLL_OFFSET = 56;
|
||||||
|
@ -38,24 +41,6 @@ const shouldUpdateProps = ['searchText', 'loadingServer', 'showServerDropdown',
|
||||||
const getItemLayout = (data, index) => ({ length: ROW_HEIGHT, offset: ROW_HEIGHT * index, index });
|
const getItemLayout = (data, index) => ({ length: ROW_HEIGHT, offset: ROW_HEIGHT * index, index });
|
||||||
const keyExtractor = item => item.rid;
|
const keyExtractor = item => item.rid;
|
||||||
|
|
||||||
const leftButtons = [{
|
|
||||||
id: 'settings',
|
|
||||||
icon: Icons.getSource('settings'),
|
|
||||||
testID: 'rooms-list-view-sidebar'
|
|
||||||
}];
|
|
||||||
const rightButtons = [{
|
|
||||||
id: 'newMessage',
|
|
||||||
icon: Icons.getSource('new_channel'),
|
|
||||||
testID: 'rooms-list-view-create-channel'
|
|
||||||
}];
|
|
||||||
|
|
||||||
if (isAndroid) {
|
|
||||||
rightButtons.push({
|
|
||||||
id: 'search',
|
|
||||||
icon: Icons.getSource('search')
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@connect(state => ({
|
@connect(state => ({
|
||||||
userId: state.login.user && state.login.user.id,
|
userId: state.login.user && state.login.user.id,
|
||||||
server: state.server.server,
|
server: state.server.server,
|
||||||
|
@ -74,36 +59,43 @@ if (isAndroid) {
|
||||||
toggleSortDropdown: () => dispatch(toggleSortDropdownAction()),
|
toggleSortDropdown: () => dispatch(toggleSortDropdownAction()),
|
||||||
openSearchHeader: () => dispatch(openSearchHeaderAction()),
|
openSearchHeader: () => dispatch(openSearchHeaderAction()),
|
||||||
closeSearchHeader: () => dispatch(closeSearchHeaderAction()),
|
closeSearchHeader: () => dispatch(closeSearchHeaderAction()),
|
||||||
appStart: () => dispatch(appStartAction()),
|
appStart: () => dispatch(appStartAction())
|
||||||
roomsRequest: () => dispatch(roomsRequestAction())
|
// roomsRequest: () => dispatch(roomsRequestAction())
|
||||||
}))
|
}))
|
||||||
/** @extends React.Component */
|
/** @extends React.Component */
|
||||||
export default class RoomsListView extends LoggedView {
|
export default class RoomsListView extends LoggedView {
|
||||||
static options() {
|
static navigationOptions = ({ navigation }) => {
|
||||||
|
const searching = navigation.getParam('searching');
|
||||||
|
const cancelSearchingAndroid = navigation.getParam('cancelSearchingAndroid');
|
||||||
|
const onPressItem = navigation.getParam('onPressItem', () => {});
|
||||||
|
const initSearchingAndroid = navigation.getParam('initSearchingAndroid', () => {});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
topBar: {
|
headerLeft: (
|
||||||
leftButtons,
|
searching
|
||||||
rightButtons,
|
? (
|
||||||
title: {
|
<CustomHeaderButtons left>
|
||||||
component: {
|
<Item title='cancel' iconName='cross' onPress={cancelSearchingAndroid} />
|
||||||
name: 'RoomsListHeaderView',
|
</CustomHeaderButtons>
|
||||||
alignment: isAndroid ? 'left' : 'fill'
|
)
|
||||||
}
|
: <DrawerButton navigation={navigation} testID='rooms-list-view-sidebar' />
|
||||||
}
|
),
|
||||||
},
|
headerTitle: <RoomsListHeaderView />,
|
||||||
sideMenu: {
|
headerRight: (
|
||||||
left: {
|
searching
|
||||||
enabled: true
|
? null
|
||||||
},
|
: (
|
||||||
right: {
|
<CustomHeaderButtons>
|
||||||
enabled: true
|
{isAndroid ? <Item title='search' iconName='magnifier' onPress={initSearchingAndroid} /> : null}
|
||||||
}
|
<Item title='new' iconName='edit-rounded' onPress={() => navigation.navigate('NewMessageView', { onPressItem })} testID='rooms-list-view-create-channel' />
|
||||||
},
|
</CustomHeaderButtons>
|
||||||
blurOnUnmount: true
|
)
|
||||||
|
)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
navigation: PropTypes.object,
|
||||||
userId: PropTypes.string,
|
userId: PropTypes.string,
|
||||||
baseUrl: PropTypes.string,
|
baseUrl: PropTypes.string,
|
||||||
server: PropTypes.string,
|
server: PropTypes.string,
|
||||||
|
@ -116,12 +108,12 @@ export default class RoomsListView extends LoggedView {
|
||||||
showFavorites: PropTypes.bool,
|
showFavorites: PropTypes.bool,
|
||||||
showUnread: PropTypes.bool,
|
showUnread: PropTypes.bool,
|
||||||
useRealName: PropTypes.bool,
|
useRealName: PropTypes.bool,
|
||||||
appState: PropTypes.string,
|
// appState: PropTypes.string,
|
||||||
toggleSortDropdown: PropTypes.func,
|
toggleSortDropdown: PropTypes.func,
|
||||||
openSearchHeader: PropTypes.func,
|
openSearchHeader: PropTypes.func,
|
||||||
closeSearchHeader: PropTypes.func,
|
closeSearchHeader: PropTypes.func,
|
||||||
appStart: PropTypes.func,
|
appStart: PropTypes.func
|
||||||
roomsRequest: PropTypes.func
|
// roomsRequest: PropTypes.func
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -140,12 +132,15 @@ export default class RoomsListView extends LoggedView {
|
||||||
direct: [],
|
direct: [],
|
||||||
livechat: []
|
livechat: []
|
||||||
};
|
};
|
||||||
Navigation.events().bindComponent(this);
|
Orientation.unlockAllOrientations();
|
||||||
BackHandler.addEventListener('hardwareBackPress', this.handleBackPress);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.getSubscriptions();
|
this.getSubscriptions();
|
||||||
|
const { navigation } = this.props;
|
||||||
|
navigation.setParams({
|
||||||
|
onPressItem: this._onPressItem, initSearchingAndroid: this.initSearchingAndroid, cancelSearchingAndroid: this.cancelSearchingAndroid
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
|
@ -222,7 +217,7 @@ export default class RoomsListView extends LoggedView {
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
const {
|
const {
|
||||||
sortBy, groupByType, showFavorites, showUnread, appState, roomsRequest
|
sortBy, groupByType, showFavorites, showUnread
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
if (!(
|
if (!(
|
||||||
|
@ -232,9 +227,11 @@ export default class RoomsListView extends LoggedView {
|
||||||
&& (prevProps.showUnread === showUnread)
|
&& (prevProps.showUnread === showUnread)
|
||||||
)) {
|
)) {
|
||||||
this.getSubscriptions();
|
this.getSubscriptions();
|
||||||
} else if (appState === 'foreground' && appState !== prevProps.appState) {
|
|
||||||
roomsRequest();
|
|
||||||
}
|
}
|
||||||
|
// removed for now... we may not need it anymore
|
||||||
|
// else if (appState === 'foreground' && appState !== prevProps.appState) {
|
||||||
|
// // roomsRequest();
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
|
@ -245,52 +242,6 @@ export default class RoomsListView extends LoggedView {
|
||||||
this.removeListener(this.privateGroup);
|
this.removeListener(this.privateGroup);
|
||||||
this.removeListener(this.direct);
|
this.removeListener(this.direct);
|
||||||
this.removeListener(this.livechat);
|
this.removeListener(this.livechat);
|
||||||
BackHandler.removeEventListener('hardwareBackPress', this.handleBackPress);
|
|
||||||
}
|
|
||||||
|
|
||||||
navigationButtonPressed = ({ buttonId }) => {
|
|
||||||
if (buttonId === 'newMessage') {
|
|
||||||
Navigation.showModal({
|
|
||||||
stack: {
|
|
||||||
children: [{
|
|
||||||
component: {
|
|
||||||
name: 'NewMessageView',
|
|
||||||
passProps: {
|
|
||||||
onPressItem: this._onPressItem
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
topBar: {
|
|
||||||
title: {
|
|
||||||
text: I18n.t('New_Message')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if (buttonId === 'settings') {
|
|
||||||
Navigation.showModal({
|
|
||||||
stack: {
|
|
||||||
children: [{
|
|
||||||
component: {
|
|
||||||
name: 'SidebarView',
|
|
||||||
options: {
|
|
||||||
topBar: {
|
|
||||||
title: {
|
|
||||||
text: I18n.t('Settings')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if (buttonId === 'search') {
|
|
||||||
this.initSearchingAndroid();
|
|
||||||
} else if (buttonId === 'back') {
|
|
||||||
this.cancelSearchingAndroid();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internalSetState = (...args) => {
|
internalSetState = (...args) => {
|
||||||
|
@ -394,32 +345,18 @@ export default class RoomsListView extends LoggedView {
|
||||||
}
|
}
|
||||||
|
|
||||||
initSearchingAndroid = () => {
|
initSearchingAndroid = () => {
|
||||||
const { openSearchHeader } = this.props;
|
const { openSearchHeader, navigation } = this.props;
|
||||||
this.setState({ searching: true });
|
this.setState({ searching: true });
|
||||||
|
navigation.setParams({ searching: true });
|
||||||
openSearchHeader();
|
openSearchHeader();
|
||||||
Navigation.mergeOptions('RoomsListView', {
|
|
||||||
topBar: {
|
|
||||||
leftButtons: [{
|
|
||||||
id: 'back',
|
|
||||||
icon: Icons.getSource('close'),
|
|
||||||
testID: 'rooms-list-view-cancel-search'
|
|
||||||
}],
|
|
||||||
rightButtons: []
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cancelSearchingAndroid = () => {
|
cancelSearchingAndroid = () => {
|
||||||
if (isAndroid) {
|
if (isAndroid) {
|
||||||
const { closeSearchHeader } = this.props;
|
const { closeSearchHeader, navigation } = this.props;
|
||||||
this.setState({ searching: false });
|
this.setState({ searching: false });
|
||||||
|
navigation.setParams({ searching: false });
|
||||||
closeSearchHeader();
|
closeSearchHeader();
|
||||||
Navigation.mergeOptions('RoomsListView', {
|
|
||||||
topBar: {
|
|
||||||
leftButtons,
|
|
||||||
rightButtons
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.internalSetState({ search: [] });
|
this.internalSetState({ search: [] });
|
||||||
Keyboard.dismiss();
|
Keyboard.dismiss();
|
||||||
}
|
}
|
||||||
|
@ -450,14 +387,8 @@ export default class RoomsListView extends LoggedView {
|
||||||
|
|
||||||
goRoom = ({ rid, name, t }) => {
|
goRoom = ({ rid, name, t }) => {
|
||||||
this.cancelSearchingAndroid();
|
this.cancelSearchingAndroid();
|
||||||
Navigation.push('RoomsListView', {
|
const { navigation } = this.props;
|
||||||
component: {
|
navigation.navigate('RoomView', { rid, name, t });
|
||||||
name: 'RoomView',
|
|
||||||
passProps: {
|
|
||||||
rid, name, t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_onPressItem = async(item = {}) => {
|
_onPressItem = async(item = {}) => {
|
||||||
|
@ -690,6 +621,7 @@ export default class RoomsListView extends LoggedView {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SafeAreaView style={styles.container} testID='rooms-list-view' forceInset={{ bottom: 'never' }}>
|
<SafeAreaView style={styles.container} testID='rooms-list-view' forceInset={{ bottom: 'never' }}>
|
||||||
|
<StatusBar />
|
||||||
{this.renderScroll()}
|
{this.renderScroll()}
|
||||||
{showSortDropdown
|
{showSortDropdown
|
||||||
? (
|
? (
|
||||||
|
@ -705,9 +637,11 @@ export default class RoomsListView extends LoggedView {
|
||||||
}
|
}
|
||||||
{showServerDropdown ? <ServerDropdown navigator={navigator} /> : null}
|
{showServerDropdown ? <ServerDropdown navigator={navigator} /> : null}
|
||||||
<ConnectionBadge />
|
<ConnectionBadge />
|
||||||
|
<NavigationEvents
|
||||||
|
onDidFocus={() => BackHandler.addEventListener('hardwareBackPress', this.handleBackPress)}
|
||||||
|
onWillBlur={() => BackHandler.removeEventListener('hardwareBackPress', this.handleBackPress)}
|
||||||
|
/>
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.disableYellowBox = true;
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { View, FlatList, Text } from 'react-native';
|
import { View, FlatList, Text } from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import SafeAreaView from 'react-native-safe-area-view';
|
import { SafeAreaView } from 'react-navigation';
|
||||||
import equal from 'deep-equal';
|
import equal from 'deep-equal';
|
||||||
|
|
||||||
import LoggedView from '../View';
|
import LoggedView from '../View';
|
||||||
|
@ -15,6 +15,7 @@ import RocketChat from '../../lib/rocketchat';
|
||||||
import Message from '../../containers/message/Message';
|
import Message from '../../containers/message/Message';
|
||||||
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
|
import StatusBar from '../../containers/StatusBar';
|
||||||
|
|
||||||
@connect(state => ({
|
@connect(state => ({
|
||||||
baseUrl: state.settings.Site_Url || state.server ? state.server.server : '',
|
baseUrl: state.settings.Site_Url || state.server ? state.server.server : '',
|
||||||
|
@ -27,18 +28,12 @@ import I18n from '../../i18n';
|
||||||
}))
|
}))
|
||||||
/** @extends React.Component */
|
/** @extends React.Component */
|
||||||
export default class SearchMessagesView extends LoggedView {
|
export default class SearchMessagesView extends LoggedView {
|
||||||
static options() {
|
static navigationOptions = {
|
||||||
return {
|
title: I18n.t('Search')
|
||||||
topBar: {
|
|
||||||
title: {
|
|
||||||
text: I18n.t('Search')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
rid: PropTypes.string,
|
navigation: PropTypes.object,
|
||||||
user: PropTypes.object,
|
user: PropTypes.object,
|
||||||
baseUrl: PropTypes.string,
|
baseUrl: PropTypes.string,
|
||||||
customEmojis: PropTypes.object
|
customEmojis: PropTypes.object
|
||||||
|
@ -77,7 +72,8 @@ export default class SearchMessagesView extends LoggedView {
|
||||||
|
|
||||||
// eslint-disable-next-line react/sort-comp
|
// eslint-disable-next-line react/sort-comp
|
||||||
search = debounce(async(searchText) => {
|
search = debounce(async(searchText) => {
|
||||||
const { rid } = this.props;
|
const { navigation } = this.props;
|
||||||
|
const rid = navigation.getParam('rid');
|
||||||
this.setState({ searchText, loading: true, messages: [] });
|
this.setState({ searchText, loading: true, messages: [] });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -142,6 +138,7 @@ export default class SearchMessagesView extends LoggedView {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<SafeAreaView style={styles.container} testID='search-messages-view' forceInset={{ bottom: 'never' }}>
|
<SafeAreaView style={styles.container} testID='search-messages-view' forceInset={{ bottom: 'never' }}>
|
||||||
|
<StatusBar />
|
||||||
<View style={styles.searchContainer}>
|
<View style={styles.searchContainer}>
|
||||||
<RCTextInput
|
<RCTextInput
|
||||||
inputRef={(e) => { this.name = e; }}
|
inputRef={(e) => { this.name = e; }}
|
||||||
|
|
|
@ -4,10 +4,9 @@ import {
|
||||||
View, StyleSheet, FlatList, LayoutAnimation
|
View, StyleSheet, FlatList, LayoutAnimation
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import SafeAreaView from 'react-native-safe-area-view';
|
import { SafeAreaView } from 'react-navigation';
|
||||||
import equal from 'deep-equal';
|
import equal from 'deep-equal';
|
||||||
|
|
||||||
import Navigation from '../lib/Navigation';
|
|
||||||
import {
|
import {
|
||||||
addUser as addUserAction, removeUser as removeUserAction, reset as resetAction, setLoading as setLoadingAction
|
addUser as addUserAction, removeUser as removeUserAction, reset as resetAction, setLoading as setLoadingAction
|
||||||
} from '../actions/selectedUsers';
|
} from '../actions/selectedUsers';
|
||||||
|
@ -19,9 +18,11 @@ import debounce from '../utils/debounce';
|
||||||
import LoggedView from './View';
|
import LoggedView from './View';
|
||||||
import I18n from '../i18n';
|
import I18n from '../i18n';
|
||||||
import log from '../utils/log';
|
import log from '../utils/log';
|
||||||
import { isIOS, isAndroid } from '../utils/deviceInfo';
|
import { isIOS } from '../utils/deviceInfo';
|
||||||
import SearchBox from '../containers/SearchBox';
|
import SearchBox from '../containers/SearchBox';
|
||||||
import sharedStyles from './Styles';
|
import sharedStyles from './Styles';
|
||||||
|
import { Item, CustomHeaderButtons } from '../containers/HeaderButton';
|
||||||
|
import StatusBar from '../containers/StatusBar';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
safeAreaView: {
|
safeAreaView: {
|
||||||
|
@ -52,23 +53,21 @@ const styles = StyleSheet.create({
|
||||||
}))
|
}))
|
||||||
/** @extends React.Component */
|
/** @extends React.Component */
|
||||||
export default class SelectedUsersView extends LoggedView {
|
export default class SelectedUsersView extends LoggedView {
|
||||||
static options() {
|
static navigationOptions = ({ navigation }) => {
|
||||||
|
const title = navigation.getParam('title');
|
||||||
|
const nextAction = navigation.getParam('nextAction', () => {});
|
||||||
return {
|
return {
|
||||||
topBar: {
|
title,
|
||||||
rightButtons: [{
|
headerRight: (
|
||||||
id: 'create',
|
<CustomHeaderButtons>
|
||||||
text: I18n.t('Next'),
|
<Item title={I18n.t('Next')} onPress={nextAction} testID='selected-users-view-submit' />
|
||||||
testID: 'selected-users-view-submit',
|
</CustomHeaderButtons>
|
||||||
color: isAndroid ? '#FFF' : undefined
|
)
|
||||||
}]
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
componentId: PropTypes.string,
|
navigation: PropTypes.object,
|
||||||
rid: PropTypes.string,
|
|
||||||
nextAction: PropTypes.string.isRequired,
|
|
||||||
baseUrl: PropTypes.string,
|
baseUrl: PropTypes.string,
|
||||||
addUser: PropTypes.func.isRequired,
|
addUser: PropTypes.func.isRequired,
|
||||||
removeUser: PropTypes.func.isRequired,
|
removeUser: PropTypes.func.isRequired,
|
||||||
|
@ -89,7 +88,11 @@ export default class SelectedUsersView extends LoggedView {
|
||||||
search: []
|
search: []
|
||||||
};
|
};
|
||||||
this.data.addListener(this.updateState);
|
this.data.addListener(this.updateState);
|
||||||
Navigation.events().bindComponent(this);
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
const { navigation } = this.props;
|
||||||
|
navigation.setParams({ nextAction: this.nextAction });
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
|
@ -118,27 +121,22 @@ export default class SelectedUsersView extends LoggedView {
|
||||||
this.search(text);
|
this.search(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
navigationButtonPressed = async({ buttonId }) => {
|
nextAction = async() => {
|
||||||
if (buttonId === 'create') {
|
const { navigation, setLoadingInvite } = this.props;
|
||||||
const { nextAction, setLoadingInvite } = this.props;
|
const nextActionID = navigation.getParam('nextActionID');
|
||||||
if (nextAction === 'CREATE_CHANNEL') {
|
if (nextActionID === 'CREATE_CHANNEL') {
|
||||||
const { componentId } = this.props;
|
navigation.navigate('CreateChannelView');
|
||||||
Navigation.push(componentId, {
|
} else {
|
||||||
component: {
|
const rid = navigation.getParam('rid');
|
||||||
name: 'CreateChannelView'
|
try {
|
||||||
}
|
setLoadingInvite(true);
|
||||||
});
|
await RocketChat.addUsersToRoom(rid);
|
||||||
} else {
|
navigation.pop();
|
||||||
const { rid, componentId } = this.props;
|
// Navigation.pop(componentId);
|
||||||
try {
|
} catch (e) {
|
||||||
setLoadingInvite(true);
|
log('RoomActions Add User', e);
|
||||||
await RocketChat.addUsersToRoom(rid);
|
} finally {
|
||||||
Navigation.pop(componentId);
|
setLoadingInvite(false);
|
||||||
} catch (e) {
|
|
||||||
log('RoomActions Add User', e);
|
|
||||||
} finally {
|
|
||||||
setLoadingInvite(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -275,6 +273,7 @@ export default class SelectedUsersView extends LoggedView {
|
||||||
const { loading } = this.props;
|
const { loading } = this.props;
|
||||||
return (
|
return (
|
||||||
<SafeAreaView style={styles.safeAreaView} testID='select-users-view' forceInset={{ bottom: 'never' }}>
|
<SafeAreaView style={styles.safeAreaView} testID='select-users-view' forceInset={{ bottom: 'never' }}>
|
||||||
|
<StatusBar />
|
||||||
{this.renderList()}
|
{this.renderList()}
|
||||||
<Loading visible={loading} />
|
<Loading visible={loading} />
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
|
|
|
@ -4,9 +4,9 @@ import {
|
||||||
Text, ScrollView, StyleSheet
|
Text, ScrollView, StyleSheet
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import SafeAreaView from 'react-native-safe-area-view';
|
import { SafeAreaView } from 'react-navigation';
|
||||||
|
import Orientation from 'react-native-orientation-locker';
|
||||||
|
|
||||||
import Navigation from '../lib/Navigation';
|
|
||||||
import { loginRequest as loginRequestAction } from '../actions/login';
|
import { loginRequest as loginRequestAction } from '../actions/login';
|
||||||
import TextInput from '../containers/TextInput';
|
import TextInput from '../containers/TextInput';
|
||||||
import Button from '../containers/Button';
|
import Button from '../containers/Button';
|
||||||
|
@ -15,8 +15,8 @@ import sharedStyles from './Styles';
|
||||||
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
||||||
import LoggedView from './View';
|
import LoggedView from './View';
|
||||||
import I18n from '../i18n';
|
import I18n from '../i18n';
|
||||||
import { DARK_HEADER } from '../constants/headerOptions';
|
|
||||||
import RocketChat from '../lib/rocketchat';
|
import RocketChat from '../lib/rocketchat';
|
||||||
|
import StatusBar from '../containers/StatusBar';
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
loginTitle: {
|
loginTitle: {
|
||||||
|
@ -33,14 +33,15 @@ const styles = StyleSheet.create({
|
||||||
}))
|
}))
|
||||||
/** @extends React.Component */
|
/** @extends React.Component */
|
||||||
export default class SetUsernameView extends LoggedView {
|
export default class SetUsernameView extends LoggedView {
|
||||||
static options() {
|
static navigationOptions = ({ navigation }) => {
|
||||||
|
const title = navigation.getParam('title');
|
||||||
return {
|
return {
|
||||||
...DARK_HEADER
|
title
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
componentId: PropTypes.string,
|
navigation: PropTypes.object,
|
||||||
server: PropTypes.string,
|
server: PropTypes.string,
|
||||||
userId: PropTypes.string,
|
userId: PropTypes.string,
|
||||||
loginRequest: PropTypes.func,
|
loginRequest: PropTypes.func,
|
||||||
|
@ -53,14 +54,9 @@ export default class SetUsernameView extends LoggedView {
|
||||||
username: '',
|
username: '',
|
||||||
saving: false
|
saving: false
|
||||||
};
|
};
|
||||||
const { componentId, server } = this.props;
|
const { server } = this.props;
|
||||||
Navigation.mergeOptions(componentId, {
|
props.navigation.setParams({ title: server });
|
||||||
topBar: {
|
Orientation.lockToPortrait();
|
||||||
title: {
|
|
||||||
text: server
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
|
@ -112,6 +108,7 @@ export default class SetUsernameView extends LoggedView {
|
||||||
const { username, saving } = this.state;
|
const { username, saving } = this.state;
|
||||||
return (
|
return (
|
||||||
<KeyboardView contentContainerStyle={sharedStyles.container}>
|
<KeyboardView contentContainerStyle={sharedStyles.container}>
|
||||||
|
<StatusBar />
|
||||||
<ScrollView {...scrollPersistTaps} contentContainerStyle={sharedStyles.containerScrollView}>
|
<ScrollView {...scrollPersistTaps} contentContainerStyle={sharedStyles.containerScrollView}>
|
||||||
<SafeAreaView style={sharedStyles.container} testID='set-username-view' forceInset={{ bottom: 'never' }}>
|
<SafeAreaView style={sharedStyles.container} testID='set-username-view' forceInset={{ bottom: 'never' }}>
|
||||||
<Text style={[sharedStyles.loginTitle, sharedStyles.textBold, styles.loginTitle]}>{I18n.t('Username')}</Text>
|
<Text style={[sharedStyles.loginTitle, sharedStyles.textBold, styles.loginTitle]}>{I18n.t('Username')}</Text>
|
||||||
|
@ -120,7 +117,7 @@ export default class SetUsernameView extends LoggedView {
|
||||||
inputRef={e => this.usernameInput = e}
|
inputRef={e => this.usernameInput = e}
|
||||||
placeholder={I18n.t('Username')}
|
placeholder={I18n.t('Username')}
|
||||||
returnKeyType='send'
|
returnKeyType='send'
|
||||||
iconLeft='mention'
|
iconLeft='at'
|
||||||
onChangeText={value => this.setState({ username: value })}
|
onChangeText={value => this.setState({ username: value })}
|
||||||
value={username}
|
value={username}
|
||||||
onSubmitEditing={this.submit}
|
onSubmitEditing={this.submit}
|
||||||
|
|
|
@ -3,9 +3,8 @@ import PropTypes from 'prop-types';
|
||||||
import { View, ScrollView } from 'react-native';
|
import { View, ScrollView } from 'react-native';
|
||||||
import RNPickerSelect from 'react-native-picker-select';
|
import RNPickerSelect from 'react-native-picker-select';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import SafeAreaView from 'react-native-safe-area-view';
|
import { SafeAreaView } from 'react-navigation';
|
||||||
|
|
||||||
import Navigation from '../../lib/Navigation';
|
|
||||||
import LoggedView from '../View';
|
import LoggedView from '../View';
|
||||||
import RocketChat from '../../lib/rocketchat';
|
import RocketChat from '../../lib/rocketchat';
|
||||||
import KeyboardView from '../../presentation/KeyboardView';
|
import KeyboardView from '../../presentation/KeyboardView';
|
||||||
|
@ -18,6 +17,8 @@ import Loading from '../../containers/Loading';
|
||||||
import { showErrorAlert, showToast } from '../../utils/info';
|
import { showErrorAlert, showToast } from '../../utils/info';
|
||||||
import log from '../../utils/log';
|
import log from '../../utils/log';
|
||||||
import { setUser as setUserAction } from '../../actions/login';
|
import { setUser as setUserAction } from '../../actions/login';
|
||||||
|
import { DrawerButton } from '../../containers/HeaderButton';
|
||||||
|
import StatusBar from '../../containers/StatusBar';
|
||||||
|
|
||||||
@connect(state => ({
|
@connect(state => ({
|
||||||
userLanguage: state.login.user && state.login.user.language
|
userLanguage: state.login.user && state.login.user.language
|
||||||
|
@ -26,15 +27,10 @@ import { setUser as setUserAction } from '../../actions/login';
|
||||||
}))
|
}))
|
||||||
/** @extends React.Component */
|
/** @extends React.Component */
|
||||||
export default class SettingsView extends LoggedView {
|
export default class SettingsView extends LoggedView {
|
||||||
static options() {
|
static navigationOptions = ({ navigation }) => ({
|
||||||
return {
|
headerLeft: <DrawerButton navigation={navigation} />,
|
||||||
topBar: {
|
title: I18n.t('Settings')
|
||||||
title: {
|
})
|
||||||
text: I18n.t('Settings')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
componentId: PropTypes.string,
|
componentId: PropTypes.string,
|
||||||
|
@ -124,17 +120,6 @@ export default class SettingsView extends LoggedView {
|
||||||
this.setState({ saving: false });
|
this.setState({ saving: false });
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
showToast(I18n.t('Preferences_saved'));
|
showToast(I18n.t('Preferences_saved'));
|
||||||
|
|
||||||
if (params.language) {
|
|
||||||
const { componentId } = this.props;
|
|
||||||
Navigation.mergeOptions(componentId, {
|
|
||||||
topBar: {
|
|
||||||
title: {
|
|
||||||
text: I18n.t('Settings')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, 300);
|
}, 300);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.setState({ saving: false });
|
this.setState({ saving: false });
|
||||||
|
@ -154,6 +139,7 @@ export default class SettingsView extends LoggedView {
|
||||||
contentContainerStyle={sharedStyles.container}
|
contentContainerStyle={sharedStyles.container}
|
||||||
keyboardVerticalOffset={128}
|
keyboardVerticalOffset={128}
|
||||||
>
|
>
|
||||||
|
<StatusBar />
|
||||||
<ScrollView
|
<ScrollView
|
||||||
contentContainerStyle={sharedStyles.containerScrollView}
|
contentContainerStyle={sharedStyles.containerScrollView}
|
||||||
testID='settings-view-list'
|
testID='settings-view-list'
|
||||||
|
|
|
@ -1,366 +0,0 @@
|
||||||
import React, { Component } from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import {
|
|
||||||
ScrollView, Text, View, StyleSheet, FlatList, LayoutAnimation, SafeAreaView, Image
|
|
||||||
} from 'react-native';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import equal from 'deep-equal';
|
|
||||||
|
|
||||||
import Navigation from '../lib/Navigation';
|
|
||||||
import { logout as logoutAction } from '../actions/login';
|
|
||||||
import Avatar from '../containers/Avatar';
|
|
||||||
import StatusContainer from '../containers/Status';
|
|
||||||
import Status from '../containers/Status/Status';
|
|
||||||
import Touch from '../utils/touch';
|
|
||||||
import RocketChat from '../lib/rocketchat';
|
|
||||||
import log from '../utils/log';
|
|
||||||
import I18n from '../i18n';
|
|
||||||
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
|
||||||
import { getReadableVersion, isIOS, isAndroid } from '../utils/deviceInfo';
|
|
||||||
import Icons, { CustomIcon } from '../lib/Icons';
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
container: {
|
|
||||||
flex: 1,
|
|
||||||
backgroundColor: '#fff'
|
|
||||||
},
|
|
||||||
item: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'center'
|
|
||||||
},
|
|
||||||
itemLeft: {
|
|
||||||
marginHorizontal: 10,
|
|
||||||
width: 30,
|
|
||||||
alignItems: 'center'
|
|
||||||
},
|
|
||||||
itemCenter: {
|
|
||||||
flex: 1
|
|
||||||
},
|
|
||||||
itemText: {
|
|
||||||
marginVertical: 16,
|
|
||||||
fontWeight: 'bold',
|
|
||||||
color: '#292E35'
|
|
||||||
},
|
|
||||||
separator: {
|
|
||||||
borderBottomWidth: StyleSheet.hairlineWidth,
|
|
||||||
borderColor: '#ddd',
|
|
||||||
marginVertical: 4
|
|
||||||
},
|
|
||||||
header: {
|
|
||||||
paddingVertical: 16,
|
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'center'
|
|
||||||
},
|
|
||||||
headerTextContainer: {
|
|
||||||
flex: 1,
|
|
||||||
flexDirection: 'column',
|
|
||||||
alignItems: 'flex-start'
|
|
||||||
},
|
|
||||||
headerUsername: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'center'
|
|
||||||
},
|
|
||||||
avatar: {
|
|
||||||
marginHorizontal: 10
|
|
||||||
},
|
|
||||||
status: {
|
|
||||||
marginRight: 5
|
|
||||||
},
|
|
||||||
currentServerText: {
|
|
||||||
fontWeight: 'bold'
|
|
||||||
},
|
|
||||||
version: {
|
|
||||||
marginHorizontal: 5,
|
|
||||||
marginBottom: 5,
|
|
||||||
fontWeight: '600',
|
|
||||||
color: '#292E35',
|
|
||||||
fontSize: 13
|
|
||||||
},
|
|
||||||
disclosureContainer: {
|
|
||||||
marginLeft: 6,
|
|
||||||
marginRight: 9,
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center'
|
|
||||||
},
|
|
||||||
disclosureIndicator: {
|
|
||||||
width: 20,
|
|
||||||
height: 20
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const keyExtractor = item => item.id;
|
|
||||||
|
|
||||||
@connect(state => ({
|
|
||||||
Site_Name: state.settings.Site_Name,
|
|
||||||
user: {
|
|
||||||
id: state.login.user && state.login.user.id,
|
|
||||||
language: state.login.user && state.login.user.language,
|
|
||||||
status: state.login.user && state.login.user.status,
|
|
||||||
username: state.login.user && state.login.user.username,
|
|
||||||
token: state.login.user && state.login.user.token
|
|
||||||
},
|
|
||||||
baseUrl: state.settings.Site_Url || state.server ? state.server.server : ''
|
|
||||||
}), dispatch => ({
|
|
||||||
logout: () => dispatch(logoutAction())
|
|
||||||
}))
|
|
||||||
export default class Sidebar extends Component {
|
|
||||||
static options() {
|
|
||||||
return {
|
|
||||||
topBar: {
|
|
||||||
leftButtons: [{
|
|
||||||
id: 'cancel',
|
|
||||||
icon: isAndroid ? Icons.getSource('close', false) : undefined,
|
|
||||||
systemItem: 'cancel'
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
baseUrl: PropTypes.string,
|
|
||||||
componentId: PropTypes.string,
|
|
||||||
Site_Name: PropTypes.string.isRequired,
|
|
||||||
user: PropTypes.object,
|
|
||||||
logout: PropTypes.func.isRequired
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
showStatus: false,
|
|
||||||
status: []
|
|
||||||
};
|
|
||||||
Navigation.events().bindComponent(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.setStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
|
||||||
const { user } = this.props;
|
|
||||||
if (nextProps.user && user && user.language !== nextProps.user.language) {
|
|
||||||
this.setStatus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
|
||||||
const { status, showStatus } = this.state;
|
|
||||||
const { Site_Name, user, baseUrl } = this.props;
|
|
||||||
if (nextState.showStatus !== showStatus) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (nextProps.Site_Name !== Site_Name) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (nextProps.Site_Name !== Site_Name) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (nextProps.baseUrl !== baseUrl) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (nextProps.user && user) {
|
|
||||||
if (nextProps.user.language !== user.language) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (nextProps.user.status !== user.status) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (nextProps.user.username !== user.username) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!equal(nextState.status, status)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
navigationButtonPressed = ({ buttonId }) => {
|
|
||||||
if (buttonId === 'cancel') {
|
|
||||||
const { componentId } = this.props;
|
|
||||||
Navigation.dismissModal(componentId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setStatus = () => {
|
|
||||||
this.setState({
|
|
||||||
status: [{
|
|
||||||
id: 'online',
|
|
||||||
name: I18n.t('Online')
|
|
||||||
}, {
|
|
||||||
id: 'busy',
|
|
||||||
name: I18n.t('Busy')
|
|
||||||
}, {
|
|
||||||
id: 'away',
|
|
||||||
name: I18n.t('Away')
|
|
||||||
}, {
|
|
||||||
id: 'offline',
|
|
||||||
name: I18n.t('Invisible')
|
|
||||||
}]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleStatus = () => {
|
|
||||||
LayoutAnimation.easeInEaseOut();
|
|
||||||
this.setState(prevState => ({ showStatus: !prevState.showStatus }));
|
|
||||||
}
|
|
||||||
|
|
||||||
sidebarNavigate = (route) => {
|
|
||||||
const { componentId } = this.props;
|
|
||||||
Navigation.push(componentId, {
|
|
||||||
component: {
|
|
||||||
name: route
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
logout = () => {
|
|
||||||
const { componentId, logout } = this.props;
|
|
||||||
Navigation.dismissModal(componentId);
|
|
||||||
logout();
|
|
||||||
}
|
|
||||||
|
|
||||||
renderSeparator = key => <View key={key} style={styles.separator} />;
|
|
||||||
|
|
||||||
renderItem = ({
|
|
||||||
text, left, onPress, testID, disclosure
|
|
||||||
}) => (
|
|
||||||
<Touch
|
|
||||||
key={text}
|
|
||||||
onPress={onPress}
|
|
||||||
underlayColor='rgba(255, 255, 255, 0.5)'
|
|
||||||
activeOpacity={0.3}
|
|
||||||
testID={testID}
|
|
||||||
>
|
|
||||||
<View style={styles.item}>
|
|
||||||
<View style={styles.itemLeft}>
|
|
||||||
{left}
|
|
||||||
</View>
|
|
||||||
<View style={styles.itemCenter}>
|
|
||||||
<Text style={styles.itemText}>
|
|
||||||
{text}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
{disclosure ? this.renderDisclosure() : null}
|
|
||||||
</View>
|
|
||||||
</Touch>
|
|
||||||
)
|
|
||||||
|
|
||||||
renderStatusItem = ({ item }) => {
|
|
||||||
const { user } = this.props;
|
|
||||||
return (
|
|
||||||
this.renderItem({
|
|
||||||
text: item.name,
|
|
||||||
left: <Status style={styles.status} size={12} status={item.id} />,
|
|
||||||
current: user.status === item.id,
|
|
||||||
onPress: () => {
|
|
||||||
this.toggleStatus();
|
|
||||||
if (user.status !== item.id) {
|
|
||||||
try {
|
|
||||||
RocketChat.setUserPresenceDefaultStatus(item.id);
|
|
||||||
} catch (e) {
|
|
||||||
log('setUserPresenceDefaultStatus', e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove it after https://github.com/RocketChat/Rocket.Chat.ReactNative/pull/643
|
|
||||||
renderDisclosure = () => {
|
|
||||||
if (isIOS) {
|
|
||||||
return (
|
|
||||||
<View style={styles.disclosureContainer}>
|
|
||||||
<Image source={{ uri: 'disclosure_indicator' }} style={styles.disclosureIndicator} />
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
renderNavigation = () => (
|
|
||||||
[
|
|
||||||
this.renderItem({
|
|
||||||
text: I18n.t('Profile'),
|
|
||||||
left: <CustomIcon name='user' size={20} color='#292E35' />,
|
|
||||||
onPress: () => this.sidebarNavigate('ProfileView'),
|
|
||||||
testID: 'sidebar-profile',
|
|
||||||
disclosure: true
|
|
||||||
}),
|
|
||||||
this.renderItem({
|
|
||||||
text: I18n.t('Settings'),
|
|
||||||
left: <CustomIcon name='cog' size={20} color='#292E35' />,
|
|
||||||
onPress: () => this.sidebarNavigate('SettingsView'),
|
|
||||||
testID: 'sidebar-settings',
|
|
||||||
disclosure: true
|
|
||||||
}),
|
|
||||||
this.renderSeparator('separator-logout'),
|
|
||||||
this.renderItem({
|
|
||||||
text: I18n.t('Logout'),
|
|
||||||
left: <CustomIcon name='sign-out' size={20} color='#292E35' />,
|
|
||||||
onPress: () => this.logout(),
|
|
||||||
testID: 'sidebar-logout'
|
|
||||||
})
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
renderStatus = () => {
|
|
||||||
const { status } = this.state;
|
|
||||||
const { user } = this.props;
|
|
||||||
return (
|
|
||||||
<FlatList
|
|
||||||
key='status-list'
|
|
||||||
data={status}
|
|
||||||
extraData={user}
|
|
||||||
renderItem={this.renderStatusItem}
|
|
||||||
keyExtractor={keyExtractor}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { showStatus } = this.state;
|
|
||||||
const { user, Site_Name, baseUrl } = this.props;
|
|
||||||
|
|
||||||
if (!user) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<SafeAreaView testID='sidebar-view' style={styles.container}>
|
|
||||||
<ScrollView style={styles.container} {...scrollPersistTaps}>
|
|
||||||
<Touch
|
|
||||||
onPress={() => this.toggleStatus()}
|
|
||||||
underlayColor='rgba(255, 255, 255, 0.5)'
|
|
||||||
activeOpacity={0.3}
|
|
||||||
testID='sidebar-toggle-status'
|
|
||||||
>
|
|
||||||
<View style={styles.header}>
|
|
||||||
<Avatar
|
|
||||||
text={user.username}
|
|
||||||
size={30}
|
|
||||||
style={styles.avatar}
|
|
||||||
baseUrl={baseUrl}
|
|
||||||
user={user}
|
|
||||||
/>
|
|
||||||
<View style={styles.headerTextContainer}>
|
|
||||||
<View style={styles.headerUsername}>
|
|
||||||
<StatusContainer style={styles.status} size={12} id={user.id} />
|
|
||||||
<Text numberOfLines={1}>{user.username}</Text>
|
|
||||||
</View>
|
|
||||||
<Text style={styles.currentServerText} numberOfLines={1}>{Site_Name}</Text>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</Touch>
|
|
||||||
|
|
||||||
{this.renderSeparator('separator-header')}
|
|
||||||
|
|
||||||
{!showStatus ? this.renderNavigation() : null}
|
|
||||||
{showStatus ? this.renderStatus() : null}
|
|
||||||
</ScrollView>
|
|
||||||
<Text style={styles.version}>
|
|
||||||
{getReadableVersion}
|
|
||||||
</Text>
|
|
||||||
</SafeAreaView>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { View, Text } from 'react-native';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { RectButton } from 'react-native-gesture-handler';
|
||||||
|
|
||||||
|
import styles from './styles';
|
||||||
|
|
||||||
|
const Item = React.memo(({
|
||||||
|
left, text, onPress, testID, current
|
||||||
|
}) => (
|
||||||
|
<RectButton
|
||||||
|
key={testID}
|
||||||
|
testID={testID}
|
||||||
|
onPress={onPress}
|
||||||
|
underlayColor='#292E35'
|
||||||
|
activeOpacity={0.1}
|
||||||
|
style={[styles.item, current && styles.itemCurrent]}
|
||||||
|
>
|
||||||
|
<View style={styles.itemLeft}>
|
||||||
|
{left}
|
||||||
|
</View>
|
||||||
|
<View style={styles.itemCenter}>
|
||||||
|
<Text style={styles.itemText}>
|
||||||
|
{text}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</RectButton>
|
||||||
|
));
|
||||||
|
|
||||||
|
Item.propTypes = {
|
||||||
|
left: PropTypes.element,
|
||||||
|
text: PropTypes.string,
|
||||||
|
current: PropTypes.bool,
|
||||||
|
onPress: PropTypes.func,
|
||||||
|
testID: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Item;
|
|
@ -0,0 +1,255 @@
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import {
|
||||||
|
ScrollView, Text, View, FlatList, LayoutAnimation, SafeAreaView
|
||||||
|
} from 'react-native';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import equal from 'deep-equal';
|
||||||
|
import { RectButton } from 'react-native-gesture-handler';
|
||||||
|
|
||||||
|
import { logout as logoutAction } from '../../actions/login';
|
||||||
|
import Avatar from '../../containers/Avatar';
|
||||||
|
import StatusContainer from '../../containers/Status';
|
||||||
|
import Status from '../../containers/Status/Status';
|
||||||
|
import RocketChat from '../../lib/rocketchat';
|
||||||
|
import log from '../../utils/log';
|
||||||
|
import I18n from '../../i18n';
|
||||||
|
import scrollPersistTaps from '../../utils/scrollPersistTaps';
|
||||||
|
import { getReadableVersion } from '../../utils/deviceInfo';
|
||||||
|
import { CustomIcon } from '../../lib/Icons';
|
||||||
|
import styles from './styles';
|
||||||
|
import SidebarItem from './SidebarItem';
|
||||||
|
|
||||||
|
const keyExtractor = item => item.id;
|
||||||
|
|
||||||
|
const Separator = React.memo(() => <View style={styles.separator} />);
|
||||||
|
|
||||||
|
@connect(state => ({
|
||||||
|
Site_Name: state.settings.Site_Name,
|
||||||
|
user: {
|
||||||
|
id: state.login.user && state.login.user.id,
|
||||||
|
language: state.login.user && state.login.user.language,
|
||||||
|
status: state.login.user && state.login.user.status,
|
||||||
|
username: state.login.user && state.login.user.username,
|
||||||
|
token: state.login.user && state.login.user.token
|
||||||
|
},
|
||||||
|
baseUrl: state.settings.Site_Url || state.server ? state.server.server : ''
|
||||||
|
}), dispatch => ({
|
||||||
|
logout: () => dispatch(logoutAction())
|
||||||
|
}))
|
||||||
|
export default class Sidebar extends Component {
|
||||||
|
static propTypes = {
|
||||||
|
baseUrl: PropTypes.string,
|
||||||
|
navigation: PropTypes.object,
|
||||||
|
Site_Name: PropTypes.string.isRequired,
|
||||||
|
user: PropTypes.object,
|
||||||
|
logout: PropTypes.func.isRequired,
|
||||||
|
activeItemKey: PropTypes.string
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
showStatus: false,
|
||||||
|
status: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.setStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
const { user } = this.props;
|
||||||
|
if (nextProps.user && user && user.language !== nextProps.user.language) {
|
||||||
|
this.setStatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
|
const { status, showStatus } = this.state;
|
||||||
|
const {
|
||||||
|
Site_Name, user, baseUrl, activeItemKey
|
||||||
|
} = this.props;
|
||||||
|
if (nextState.showStatus !== showStatus) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (nextProps.Site_Name !== Site_Name) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (nextProps.Site_Name !== Site_Name) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (nextProps.baseUrl !== baseUrl) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (nextProps.activeItemKey !== activeItemKey) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (nextProps.user && user) {
|
||||||
|
if (nextProps.user.language !== user.language) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (nextProps.user.status !== user.status) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (nextProps.user.username !== user.username) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!equal(nextState.status, status)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
setStatus = () => {
|
||||||
|
this.setState({
|
||||||
|
status: [{
|
||||||
|
id: 'online',
|
||||||
|
name: I18n.t('Online')
|
||||||
|
}, {
|
||||||
|
id: 'busy',
|
||||||
|
name: I18n.t('Busy')
|
||||||
|
}, {
|
||||||
|
id: 'away',
|
||||||
|
name: I18n.t('Away')
|
||||||
|
}, {
|
||||||
|
id: 'offline',
|
||||||
|
name: I18n.t('Invisible')
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleStatus = () => {
|
||||||
|
LayoutAnimation.easeInEaseOut();
|
||||||
|
this.setState(prevState => ({ showStatus: !prevState.showStatus }));
|
||||||
|
}
|
||||||
|
|
||||||
|
sidebarNavigate = (route) => {
|
||||||
|
const { navigation } = this.props;
|
||||||
|
navigation.navigate(route);
|
||||||
|
}
|
||||||
|
|
||||||
|
logout = () => {
|
||||||
|
const { logout } = this.props;
|
||||||
|
logout();
|
||||||
|
}
|
||||||
|
|
||||||
|
renderStatusItem = ({ item }) => {
|
||||||
|
const { user } = this.props;
|
||||||
|
return (
|
||||||
|
<SidebarItem
|
||||||
|
text={item.name}
|
||||||
|
left={<Status style={styles.status} size={12} status={item.id} />}
|
||||||
|
current={user.status === item.id}
|
||||||
|
onPress={() => {
|
||||||
|
this.toggleStatus();
|
||||||
|
if (user.status !== item.id) {
|
||||||
|
try {
|
||||||
|
RocketChat.setUserPresenceDefaultStatus(item.id);
|
||||||
|
} catch (e) {
|
||||||
|
log('setUserPresenceDefaultStatus', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderNavigation = () => {
|
||||||
|
const { activeItemKey } = this.props;
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<SidebarItem
|
||||||
|
text={I18n.t('Chats')}
|
||||||
|
left={<CustomIcon name='chat' size={20} color='#292E35' />}
|
||||||
|
onPress={() => this.sidebarNavigate('RoomsListView')}
|
||||||
|
testID='sidebar-chats'
|
||||||
|
current={activeItemKey === 'ChatsStack'}
|
||||||
|
/>
|
||||||
|
<SidebarItem
|
||||||
|
text={I18n.t('Profile')}
|
||||||
|
left={<CustomIcon name='user' size={20} color='#292E35' />}
|
||||||
|
onPress={() => this.sidebarNavigate('ProfileView')}
|
||||||
|
testID='sidebar-profile'
|
||||||
|
current={activeItemKey === 'ProfileStack'}
|
||||||
|
/>
|
||||||
|
<SidebarItem
|
||||||
|
text={I18n.t('Settings')}
|
||||||
|
left={<CustomIcon name='cog' size={20} color='#292E35' />}
|
||||||
|
onPress={() => this.sidebarNavigate('SettingsView')}
|
||||||
|
testID='sidebar-settings'
|
||||||
|
current={activeItemKey === 'SettingsStack'}
|
||||||
|
/>
|
||||||
|
<Separator key='separator-logout' />
|
||||||
|
<SidebarItem
|
||||||
|
text={I18n.t('Logout')}
|
||||||
|
left={<CustomIcon name='sign-out' size={20} color='#292E35' />}
|
||||||
|
onPress={this.logout}
|
||||||
|
testID='sidebar-logout'
|
||||||
|
/>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderStatus = () => {
|
||||||
|
const { status } = this.state;
|
||||||
|
const { user } = this.props;
|
||||||
|
return (
|
||||||
|
<FlatList
|
||||||
|
key='status-list'
|
||||||
|
data={status}
|
||||||
|
extraData={user}
|
||||||
|
renderItem={this.renderStatusItem}
|
||||||
|
keyExtractor={keyExtractor}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { showStatus } = this.state;
|
||||||
|
const { user, Site_Name, baseUrl } = this.props;
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<SafeAreaView testID='sidebar-view' style={styles.container}>
|
||||||
|
<ScrollView style={styles.container} {...scrollPersistTaps}>
|
||||||
|
<RectButton
|
||||||
|
onPress={this.toggleStatus}
|
||||||
|
underlayColor='#292E35'
|
||||||
|
activeOpacity={0.1}
|
||||||
|
testID='sidebar-toggle-status'
|
||||||
|
style={styles.header}
|
||||||
|
>
|
||||||
|
<Avatar
|
||||||
|
text={user.username}
|
||||||
|
size={30}
|
||||||
|
style={styles.avatar}
|
||||||
|
baseUrl={baseUrl}
|
||||||
|
user={user}
|
||||||
|
/>
|
||||||
|
<View style={styles.headerTextContainer}>
|
||||||
|
<View style={styles.headerUsername}>
|
||||||
|
<StatusContainer style={styles.status} size={12} id={user.id} />
|
||||||
|
<Text numberOfLines={1}>{user.username}</Text>
|
||||||
|
</View>
|
||||||
|
<Text style={styles.currentServerText} numberOfLines={1}>{Site_Name}</Text>
|
||||||
|
</View>
|
||||||
|
<CustomIcon name='arrow-down' size={20} style={[styles.headerIcon, showStatus && styles.inverted]} />
|
||||||
|
</RectButton>
|
||||||
|
|
||||||
|
<Separator key='separator-header' />
|
||||||
|
|
||||||
|
{!showStatus ? this.renderNavigation() : null}
|
||||||
|
{showStatus ? this.renderStatus() : null}
|
||||||
|
</ScrollView>
|
||||||
|
<Text style={styles.version}>
|
||||||
|
{getReadableVersion}
|
||||||
|
</Text>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
import { StyleSheet } from 'react-native';
|
||||||
|
|
||||||
|
export default StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: '#fff'
|
||||||
|
},
|
||||||
|
item: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center'
|
||||||
|
},
|
||||||
|
itemCurrent: {
|
||||||
|
backgroundColor: '#E1E5E8'
|
||||||
|
},
|
||||||
|
itemLeft: {
|
||||||
|
marginHorizontal: 10,
|
||||||
|
width: 30,
|
||||||
|
alignItems: 'center'
|
||||||
|
},
|
||||||
|
itemCenter: {
|
||||||
|
flex: 1
|
||||||
|
},
|
||||||
|
itemText: {
|
||||||
|
marginVertical: 16,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: '#292E35'
|
||||||
|
},
|
||||||
|
separator: {
|
||||||
|
borderBottomWidth: StyleSheet.hairlineWidth,
|
||||||
|
borderColor: '#E1E5E8',
|
||||||
|
marginVertical: 4
|
||||||
|
},
|
||||||
|
header: {
|
||||||
|
paddingVertical: 16,
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center'
|
||||||
|
},
|
||||||
|
headerTextContainer: {
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: 'column',
|
||||||
|
alignItems: 'flex-start'
|
||||||
|
},
|
||||||
|
headerUsername: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center'
|
||||||
|
},
|
||||||
|
headerIcon: {
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
color: '#292E35'
|
||||||
|
},
|
||||||
|
avatar: {
|
||||||
|
marginHorizontal: 10
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
marginRight: 5
|
||||||
|
},
|
||||||
|
currentServerText: {
|
||||||
|
fontWeight: 'bold'
|
||||||
|
},
|
||||||
|
version: {
|
||||||
|
marginHorizontal: 5,
|
||||||
|
marginBottom: 5,
|
||||||
|
fontWeight: '600',
|
||||||
|
color: '#292E35',
|
||||||
|
fontSize: 13
|
||||||
|
},
|
||||||
|
inverted: {
|
||||||
|
transform: [{ scaleY: -1 }]
|
||||||
|
}
|
||||||
|
});
|
|
@ -1,150 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { FlatList, View, Text } from 'react-native';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import SafeAreaView from 'react-native-safe-area-view';
|
|
||||||
import equal from 'deep-equal';
|
|
||||||
|
|
||||||
import { openSnippetedMessages as openSnippetedMessagesAction, closeSnippetedMessages as closeSnippetedMessagesAction } from '../../actions/snippetedMessages';
|
|
||||||
import LoggedView from '../View';
|
|
||||||
import styles from './styles';
|
|
||||||
import Message from '../../containers/message';
|
|
||||||
import RCActivityIndicator from '../../containers/ActivityIndicator';
|
|
||||||
import I18n from '../../i18n';
|
|
||||||
|
|
||||||
@connect(state => ({
|
|
||||||
messages: state.snippetedMessages.messages,
|
|
||||||
ready: state.snippetedMessages.ready,
|
|
||||||
user: {
|
|
||||||
id: state.login.user && state.login.user.id,
|
|
||||||
username: state.login.user && state.login.user.username,
|
|
||||||
token: state.login.user && state.login.user.token
|
|
||||||
}
|
|
||||||
}), dispatch => ({
|
|
||||||
openSnippetedMessages: (rid, limit) => dispatch(openSnippetedMessagesAction(rid, limit)),
|
|
||||||
closeSnippetedMessages: () => dispatch(closeSnippetedMessagesAction())
|
|
||||||
}))
|
|
||||||
/** @extends React.Component */
|
|
||||||
export default class SnippetedMessagesView extends LoggedView {
|
|
||||||
static options() {
|
|
||||||
return {
|
|
||||||
topBar: {
|
|
||||||
title: {
|
|
||||||
text: I18n.t('Snippets')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
rid: PropTypes.string,
|
|
||||||
messages: PropTypes.array,
|
|
||||||
ready: PropTypes.bool,
|
|
||||||
user: PropTypes.object,
|
|
||||||
openSnippetedMessages: PropTypes.func,
|
|
||||||
closeSnippetedMessages: PropTypes.func
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super('SnippetedMessagesView', props);
|
|
||||||
this.state = {
|
|
||||||
loading: true,
|
|
||||||
loadingMore: false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.limit = 20;
|
|
||||||
this.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
|
||||||
const { ready } = this.props;
|
|
||||||
if (nextProps.ready && nextProps.ready !== ready) {
|
|
||||||
this.setState({ loading: false, loadingMore: false });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
|
||||||
const { loading, loadingMore } = this.state;
|
|
||||||
const { messages, ready } = this.props;
|
|
||||||
if (nextState.loading !== loading) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (nextState.loadingMore !== loadingMore) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (nextProps.ready !== ready) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!equal(nextState.messages, messages)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
const { closeSnippetedMessages } = this.props;
|
|
||||||
closeSnippetedMessages();
|
|
||||||
}
|
|
||||||
|
|
||||||
load = () => {
|
|
||||||
const { rid, openSnippetedMessages } = this.props;
|
|
||||||
openSnippetedMessages(rid, this.limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
moreData = () => {
|
|
||||||
const { loadingMore } = this.state;
|
|
||||||
const { messages } = this.props;
|
|
||||||
if (messages.length < this.limit) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!loadingMore) {
|
|
||||||
this.setState({ loadingMore: true });
|
|
||||||
this.limit += 20;
|
|
||||||
this.load();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
renderEmpty = () => (
|
|
||||||
<View style={styles.listEmptyContainer} testID='snippeted-messages-view'>
|
|
||||||
<Text>{I18n.t('No_snippeted_messages')}</Text>
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
|
|
||||||
renderItem = ({ item }) => {
|
|
||||||
const { user } = this.props;
|
|
||||||
return (
|
|
||||||
<Message
|
|
||||||
item={item}
|
|
||||||
style={styles.message}
|
|
||||||
reactions={item.reactions}
|
|
||||||
user={user}
|
|
||||||
customTimeFormat='MMM Do YYYY, h:mm:ss a'
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { loading, loadingMore } = this.state;
|
|
||||||
const { messages, ready } = this.props;
|
|
||||||
|
|
||||||
if (ready && messages.length === 0) {
|
|
||||||
return this.renderEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<SafeAreaView style={styles.list} testID='snippeted-messages-view' forceInset={{ bottom: 'never' }}>
|
|
||||||
<FlatList
|
|
||||||
data={messages}
|
|
||||||
renderItem={this.renderItem}
|
|
||||||
style={styles.list}
|
|
||||||
keyExtractor={item => item._id}
|
|
||||||
onEndReached={this.moreData}
|
|
||||||
ListHeaderComponent={loading ? <RCActivityIndicator /> : null}
|
|
||||||
ListFooterComponent={loadingMore ? <RCActivityIndicator /> : null}
|
|
||||||
/>
|
|
||||||
</SafeAreaView>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
import { StyleSheet } from 'react-native';
|
|
||||||
|
|
||||||
export default StyleSheet.create({
|
|
||||||
list: {
|
|
||||||
flex: 1,
|
|
||||||
backgroundColor: '#ffffff'
|
|
||||||
},
|
|
||||||
message: {
|
|
||||||
transform: [{ scaleY: 1 }]
|
|
||||||
},
|
|
||||||
listEmptyContainer: {
|
|
||||||
flex: 1,
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
backgroundColor: '#ffffff'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
||||||
import { FlatList, View, Text } from 'react-native';
|
import { FlatList, View, Text } from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import ActionSheet from 'react-native-action-sheet';
|
import ActionSheet from 'react-native-action-sheet';
|
||||||
import SafeAreaView from 'react-native-safe-area-view';
|
import { SafeAreaView } from 'react-navigation';
|
||||||
import equal from 'deep-equal';
|
import equal from 'deep-equal';
|
||||||
|
|
||||||
import LoggedView from '../View';
|
import LoggedView from '../View';
|
||||||
|
@ -12,6 +12,7 @@ import Message from '../../containers/message/Message';
|
||||||
import RCActivityIndicator from '../../containers/ActivityIndicator';
|
import RCActivityIndicator from '../../containers/ActivityIndicator';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
import RocketChat from '../../lib/rocketchat';
|
import RocketChat from '../../lib/rocketchat';
|
||||||
|
import StatusBar from '../../containers/StatusBar';
|
||||||
|
|
||||||
const STAR_INDEX = 0;
|
const STAR_INDEX = 0;
|
||||||
const CANCEL_INDEX = 1;
|
const CANCEL_INDEX = 1;
|
||||||
|
@ -29,14 +30,8 @@ const options = [I18n.t('Unstar'), I18n.t('Cancel')];
|
||||||
}))
|
}))
|
||||||
/** @extends React.Component */
|
/** @extends React.Component */
|
||||||
export default class StarredMessagesView extends LoggedView {
|
export default class StarredMessagesView extends LoggedView {
|
||||||
static options() {
|
static navigationOptions = {
|
||||||
return {
|
title: I18n.t('Starred')
|
||||||
topBar: {
|
|
||||||
title: {
|
|
||||||
text: I18n.t('Starred')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
@ -175,6 +170,7 @@ export default class StarredMessagesView extends LoggedView {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SafeAreaView style={styles.list} testID='starred-messages-view' forceInset={{ bottom: 'never' }}>
|
<SafeAreaView style={styles.list} testID='starred-messages-view' forceInset={{ bottom: 'never' }}>
|
||||||
|
<StatusBar />
|
||||||
<FlatList
|
<FlatList
|
||||||
data={messages}
|
data={messages}
|
||||||
renderItem={this.renderItem}
|
renderItem={this.renderItem}
|
||||||
|
|
|
@ -2,29 +2,20 @@ import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { WebView } from 'react-native';
|
import { WebView } from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import SafeAreaView from 'react-native-safe-area-view';
|
import { SafeAreaView } from 'react-navigation';
|
||||||
|
|
||||||
import styles from './Styles';
|
import styles from './Styles';
|
||||||
import LoggedView from './View';
|
import LoggedView from './View';
|
||||||
import { DARK_HEADER } from '../constants/headerOptions';
|
|
||||||
import I18n from '../i18n';
|
import I18n from '../i18n';
|
||||||
|
import StatusBar from '../containers/StatusBar';
|
||||||
|
|
||||||
@connect(state => ({
|
@connect(state => ({
|
||||||
termsService: state.settings.Layout_Terms_of_Service
|
termsService: state.settings.Layout_Terms_of_Service
|
||||||
}))
|
}))
|
||||||
/** @extends React.Component */
|
/** @extends React.Component */
|
||||||
export default class TermsServiceView extends LoggedView {
|
export default class TermsServiceView extends LoggedView {
|
||||||
static options() {
|
static navigationOptions = {
|
||||||
return {
|
title: I18n.t('Terms_of_Service')
|
||||||
...DARK_HEADER,
|
|
||||||
topBar: {
|
|
||||||
...DARK_HEADER.topBar,
|
|
||||||
title: {
|
|
||||||
...DARK_HEADER.topBar.title,
|
|
||||||
text: I18n.t('Terms_of_Service')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
@ -39,6 +30,7 @@ export default class TermsServiceView extends LoggedView {
|
||||||
const { termsService } = this.props;
|
const { termsService } = this.props;
|
||||||
return (
|
return (
|
||||||
<SafeAreaView style={styles.container} testID='terms-view'>
|
<SafeAreaView style={styles.container} testID='terms-view'>
|
||||||
|
<StatusBar />
|
||||||
<WebView originWhitelist={['*']} source={{ html: termsService, baseUrl: '' }} />
|
<WebView originWhitelist={['*']} source={{ html: termsService, baseUrl: '' }} />
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
);
|
);
|
||||||
|
|
|
@ -32,7 +32,7 @@ describe('Create room screen', () => {
|
||||||
|
|
||||||
describe('Usage', async() => {
|
describe('Usage', async() => {
|
||||||
it('should back to rooms list', async() => {
|
it('should back to rooms list', async() => {
|
||||||
await element(by.text('Cancel')).tap();
|
await element(by.id('new-message-view-close')).tap();
|
||||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||||
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
||||||
await element(by.id('rooms-list-view-create-channel')).tap();
|
await element(by.id('rooms-list-view-create-channel')).tap();
|
||||||
|
|
|
@ -86,11 +86,6 @@ describe('Room actions screen', () => {
|
||||||
await expect(element(by.id('room-actions-pinned'))).toBeVisible();
|
await expect(element(by.id('room-actions-pinned'))).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have snippeted', async() => {
|
|
||||||
await waitFor(element(by.id('room-actions-snippeted'))).toBeVisible().whileElement(by.id('room-actions-list')).scroll(scrollDown, 'down');
|
|
||||||
await expect(element(by.id('room-actions-snippeted'))).toBeVisible();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have notifications', async() => {
|
it('should have notifications', async() => {
|
||||||
await waitFor(element(by.id('room-actions-notifications'))).toBeVisible().whileElement(by.id('room-actions-list')).scroll(scrollDown, 'down');
|
await waitFor(element(by.id('room-actions-notifications'))).toBeVisible().whileElement(by.id('room-actions-list')).scroll(scrollDown, 'down');
|
||||||
await expect(element(by.id('room-actions-notifications'))).toBeVisible();
|
await expect(element(by.id('room-actions-notifications'))).toBeVisible();
|
||||||
|
@ -161,11 +156,6 @@ describe('Room actions screen', () => {
|
||||||
await expect(element(by.id('room-actions-pinned'))).toBeVisible();
|
await expect(element(by.id('room-actions-pinned'))).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have snippeted', async() => {
|
|
||||||
await waitFor(element(by.id('room-actions-snippeted'))).toBeVisible().whileElement(by.id('room-actions-list')).scroll(scrollDown, 'down');
|
|
||||||
await expect(element(by.id('room-actions-snippeted'))).toBeVisible();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have notifications', async() => {
|
it('should have notifications', async() => {
|
||||||
await waitFor(element(by.id('room-actions-notifications'))).toBeVisible().whileElement(by.id('room-actions-list')).scroll(scrollDown, 'down');
|
await waitFor(element(by.id('room-actions-notifications'))).toBeVisible().whileElement(by.id('room-actions-list')).scroll(scrollDown, 'down');
|
||||||
await expect(element(by.id('room-actions-notifications'))).toBeVisible();
|
await expect(element(by.id('room-actions-notifications'))).toBeVisible();
|
||||||
|
|
|
@ -122,10 +122,6 @@ describe('Join public room', () => {
|
||||||
await expect(element(by.id('room-actions-pinned'))).toBeVisible();
|
await expect(element(by.id('room-actions-pinned'))).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have snippeted', async() => {
|
|
||||||
await expect(element(by.id('room-actions-snippeted'))).toBeVisible();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not have notifications', async() => {
|
it('should not have notifications', async() => {
|
||||||
await expect(element(by.id('room-actions-notifications'))).toBeNotVisible();
|
await expect(element(by.id('room-actions-notifications'))).toBeNotVisible();
|
||||||
});
|
});
|
||||||
|
@ -172,7 +168,6 @@ describe('Join public room', () => {
|
||||||
await element(by.id('room-actions-list')).swipe('up');
|
await element(by.id('room-actions-list')).swipe('up');
|
||||||
await expect(element(by.id('room-actions-share'))).toBeVisible();
|
await expect(element(by.id('room-actions-share'))).toBeVisible();
|
||||||
await expect(element(by.id('room-actions-pinned'))).toBeVisible();
|
await expect(element(by.id('room-actions-pinned'))).toBeVisible();
|
||||||
await expect(element(by.id('room-actions-snippeted'))).toBeVisible();
|
|
||||||
await expect(element(by.id('room-actions-notifications'))).toBeVisible();
|
await expect(element(by.id('room-actions-notifications'))).toBeVisible();
|
||||||
await expect(element(by.id('room-actions-leave-channel'))).toBeVisible();
|
await expect(element(by.id('room-actions-leave-channel'))).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
|
@ -44,7 +44,7 @@ async function logout() {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function tapBack() {
|
async function tapBack() {
|
||||||
await element(by.type('_UIModernBarButton').withAncestor(by.type('_UIBackButtonContainerView'))).tap();
|
await element(by.id('header-back')).atIndex(0).tap();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function sleep(ms) {
|
async function sleep(ms) {
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
import './app/ReactotronConfig';
|
|
||||||
import './app/push';
|
|
||||||
import App from './app/index';
|
|
||||||
|
|
||||||
// eslint-disable-next-line
|
|
||||||
const app = new App();
|
|
|
@ -1,6 +0,0 @@
|
||||||
import './app/ReactotronConfig';
|
|
||||||
import './app/push';
|
|
||||||
import App from './app/index';
|
|
||||||
|
|
||||||
// eslint-disable-next-line
|
|
||||||
const app = new App();
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import './app/ReactotronConfig';
|
||||||
|
import { AppRegistry } from 'react-native';
|
||||||
|
import App from './app/index';
|
||||||
|
import { name as appName } from './app.json';
|
||||||
|
|
||||||
|
AppRegistry.registerComponent(appName, () => App);
|
||||||
|
|
||||||
|
// For storybook, comment everything above and uncomment below
|
||||||
|
// import './storybook';
|
|
@ -26,6 +26,12 @@ target 'RocketChatRN' do
|
||||||
pod 'RNImageCropPicker', :path => '../node_modules/react-native-image-crop-picker'
|
pod 'RNImageCropPicker', :path => '../node_modules/react-native-image-crop-picker'
|
||||||
pod 'RNDeviceInfo', :path => '../node_modules/react-native-device-info'
|
pod 'RNDeviceInfo', :path => '../node_modules/react-native-device-info'
|
||||||
|
|
||||||
|
pod 'RNScreens', :path => '../node_modules/react-native-screens'
|
||||||
|
|
||||||
|
pod 'react-native-splash-screen', :path => '../node_modules/react-native-splash-screen'
|
||||||
|
|
||||||
|
pod 'react-native-orientation-locker', :path => '../node_modules/react-native-orientation-locker'
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
post_install do |installer|
|
post_install do |installer|
|
||||||
|
|
|
@ -2,6 +2,10 @@ PODS:
|
||||||
- QBImagePickerController (3.4.0)
|
- QBImagePickerController (3.4.0)
|
||||||
- React (0.58.6):
|
- React (0.58.6):
|
||||||
- React/Core (= 0.58.6)
|
- React/Core (= 0.58.6)
|
||||||
|
- react-native-orientation-locker (1.1.3):
|
||||||
|
- React
|
||||||
|
- react-native-splash-screen (3.2.0):
|
||||||
|
- React
|
||||||
- React/Core (0.58.6):
|
- React/Core (0.58.6):
|
||||||
- yoga (= 0.58.6.React)
|
- yoga (= 0.58.6.React)
|
||||||
- React/fishhook (0.58.6)
|
- React/fishhook (0.58.6)
|
||||||
|
@ -36,10 +40,14 @@ PODS:
|
||||||
- QBImagePickerController
|
- QBImagePickerController
|
||||||
- React/Core
|
- React/Core
|
||||||
- RSKImageCropper
|
- RSKImageCropper
|
||||||
|
- RNScreens (1.0.0-alpha.22):
|
||||||
|
- React
|
||||||
- RSKImageCropper (2.2.1)
|
- RSKImageCropper (2.2.1)
|
||||||
- yoga (0.58.6.React)
|
- yoga (0.58.6.React)
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
|
- react-native-orientation-locker (from `../node_modules/react-native-orientation-locker`)
|
||||||
|
- react-native-splash-screen (from `../node_modules/react-native-splash-screen`)
|
||||||
- React/Core (from `../node_modules/react-native`)
|
- React/Core (from `../node_modules/react-native`)
|
||||||
- React/RCTActionSheet (from `../node_modules/react-native`)
|
- React/RCTActionSheet (from `../node_modules/react-native`)
|
||||||
- React/RCTAnimation (from `../node_modules/react-native`)
|
- React/RCTAnimation (from `../node_modules/react-native`)
|
||||||
|
@ -53,6 +61,7 @@ DEPENDENCIES:
|
||||||
- React/RCTWebSocket (from `../node_modules/react-native`)
|
- React/RCTWebSocket (from `../node_modules/react-native`)
|
||||||
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
|
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
|
||||||
- RNImageCropPicker (from `../node_modules/react-native-image-crop-picker`)
|
- RNImageCropPicker (from `../node_modules/react-native-image-crop-picker`)
|
||||||
|
- RNScreens (from `../node_modules/react-native-screens`)
|
||||||
- yoga (from `../node_modules/react-native/ReactCommon/yoga/yoga.podspec`)
|
- yoga (from `../node_modules/react-native/ReactCommon/yoga/yoga.podspec`)
|
||||||
|
|
||||||
SPEC REPOS:
|
SPEC REPOS:
|
||||||
|
@ -63,21 +72,30 @@ SPEC REPOS:
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
React:
|
React:
|
||||||
:path: "../node_modules/react-native"
|
:path: "../node_modules/react-native"
|
||||||
|
react-native-orientation-locker:
|
||||||
|
:path: "../node_modules/react-native-orientation-locker"
|
||||||
|
react-native-splash-screen:
|
||||||
|
:path: "../node_modules/react-native-splash-screen"
|
||||||
RNDeviceInfo:
|
RNDeviceInfo:
|
||||||
:path: "../node_modules/react-native-device-info"
|
:path: "../node_modules/react-native-device-info"
|
||||||
RNImageCropPicker:
|
RNImageCropPicker:
|
||||||
:path: "../node_modules/react-native-image-crop-picker"
|
:path: "../node_modules/react-native-image-crop-picker"
|
||||||
|
RNScreens:
|
||||||
|
:path: "../node_modules/react-native-screens"
|
||||||
yoga:
|
yoga:
|
||||||
:path: "../node_modules/react-native/ReactCommon/yoga/yoga.podspec"
|
:path: "../node_modules/react-native/ReactCommon/yoga/yoga.podspec"
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
QBImagePickerController: d54cf93db6decf26baf6ed3472f336ef35cae022
|
QBImagePickerController: d54cf93db6decf26baf6ed3472f336ef35cae022
|
||||||
React: 130b87b2d5e2baac646954282cab87be986d98fc
|
React: 130b87b2d5e2baac646954282cab87be986d98fc
|
||||||
|
react-native-orientation-locker: 8878845713f8d52f2a520ec3c3b0c9348e08e32c
|
||||||
|
react-native-splash-screen: 200d11d188e2e78cea3ad319964f6142b6384865
|
||||||
RNDeviceInfo: e7c5fcde13d40e161d8a27f6c5dc69c638936002
|
RNDeviceInfo: e7c5fcde13d40e161d8a27f6c5dc69c638936002
|
||||||
RNImageCropPicker: e608efe182652dc8690268cb99cb5a201f2b5ea3
|
RNImageCropPicker: e608efe182652dc8690268cb99cb5a201f2b5ea3
|
||||||
|
RNScreens: 720a9e6968beb73e8196239801e887d8401f86ed
|
||||||
RSKImageCropper: 98296ad26b41753f796b6898d015509598f13d97
|
RSKImageCropper: 98296ad26b41753f796b6898d015509598f13d97
|
||||||
yoga: 32d7ef1081951e9a35a4c72a7be797598b138a48
|
yoga: 32d7ef1081951e9a35a4c72a7be797598b138a48
|
||||||
|
|
||||||
PODFILE CHECKSUM: da5e520837501713de2c32adbff219ab7fc5c0fa
|
PODFILE CHECKSUM: ad284b28235f7bcda110a24095b5e2b5718cf7e2
|
||||||
|
|
||||||
COCOAPODS: 1.6.0
|
COCOAPODS: 1.6.0
|
||||||
|
|