Update navigation library (#501)
* v2 * Working on Android 0.57.3 * Drawer working * Removing v1 navigator * - Splash screen - Icons changed * Deeplink * Remove EventEmitter from CreateChannelView * Android search * Android notifications * OAuth * Fix search props * Lint and tests fixed * Fix android build * Improvements on iPhone X* usage * Fix detox * Fix android build * Room.f added to RoomView.shouldComponentUpdate * Animations on RoomsListView and RoomView * Fix topbar buttons on Android
|
@ -129,6 +129,7 @@ module.exports = {
|
|||
"global-require": "off",
|
||||
"react-native/no-unused-styles": 2,
|
||||
"react/jsx-one-expression-per-line": 0,
|
||||
"require-await": 2,
|
||||
"func-names": 0
|
||||
},
|
||||
"globals": {
|
||||
|
|
|
@ -12,7 +12,7 @@ import RoomItem from '../app/presentation/RoomItem';
|
|||
// Note: test renderer must be required after react-native.
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
const date = new Date(2017, 10, 10, 10);
|
||||
const date = '2017-10-10T10:00:00Z';
|
||||
const onPress = () => {};
|
||||
|
||||
it('renders correctly', () => {
|
||||
|
|
|
@ -106,7 +106,7 @@ android {
|
|||
ndk {
|
||||
abiFilters "armeabi-v7a", "x86"
|
||||
}
|
||||
missingDimensionStrategy "RNN.reactNativeVersion", "reactNative55"
|
||||
missingDimensionStrategy "RNN.reactNativeVersion", "reactNative57"
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
multiDexEnabled true
|
||||
}
|
||||
|
@ -215,7 +215,7 @@ dependencies {
|
|||
implementation 'com.facebook.fresco:animated-gif:1.10.0'
|
||||
implementation 'com.facebook.fresco:animated-webp:1.10.0'
|
||||
implementation 'com.facebook.fresco:webpsupport:1.10.0'
|
||||
implementation('com.crashlytics.sdk.android:crashlytics:2.9.2@aar') {
|
||||
implementation('com.crashlytics.sdk.android:crashlytics:2.9.5@aar') {
|
||||
transitive = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,15 +3,38 @@ package chat.rocket.reactnative;
|
|||
import android.graphics.drawable.Drawable;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.widget.LinearLayout;
|
||||
import com.reactnativenavigation.controllers.SplashActivity;
|
||||
// import com.reactnativenavigation.controllers.SplashActivity;
|
||||
import com.reactnativenavigation.NavigationActivity;
|
||||
import android.view.View;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
public class MainActivity extends NavigationActivity {
|
||||
|
||||
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);
|
||||
public void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
setIntent(intent);
|
||||
}
|
||||
|
||||
return splash;
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
View view = new View(this);
|
||||
view.setBackgroundResource(R.drawable.launch_screen_bitmap);
|
||||
setContentView(view);
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -13,9 +13,12 @@ import com.facebook.react.ReactPackage;
|
|||
import com.facebook.react.shell.MainReactPackage;
|
||||
import com.oblador.vectoricons.VectorIconsPackage;
|
||||
import com.reactnativenavigation.NavigationApplication;
|
||||
import com.facebook.react.ReactNativeHost;
|
||||
import com.remobile.toast.RCTToastPackage;
|
||||
import com.rnim.rn.audio.ReactNativeAudioPackage;
|
||||
import com.smixx.fabric.FabricPackage;
|
||||
import com.reactnativenavigation.react.NavigationReactNativeHost;
|
||||
import com.reactnativenavigation.react.ReactGateway;
|
||||
import com.wix.reactnativekeyboardinput.KeyboardInputPackage;
|
||||
import com.wix.reactnativenotifications.RNNotificationsPackage;
|
||||
import com.wix.reactnativenotifications.core.AppLaunchHelper;
|
||||
|
@ -34,17 +37,28 @@ import io.realm.react.RealmReactPackage;
|
|||
|
||||
public class MainApplication extends NavigationApplication implements INotificationsApplication {
|
||||
|
||||
private NotificationsLifecycleFacade notificationsLifecycleFacade;
|
||||
// private NotificationsLifecycleFacade notificationsLifecycleFacade;
|
||||
|
||||
@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
|
||||
public String getJSMainModuleName() {
|
||||
protected String getJSMainModuleName() {
|
||||
return "index.android";
|
||||
}
|
||||
};
|
||||
return new ReactGateway(this, isDebug(), host);
|
||||
}
|
||||
|
||||
|
||||
protected List<ReactPackage> getPackages() {
|
||||
// Add additional packages you require here
|
||||
|
@ -79,11 +93,6 @@ public class MainApplication extends NavigationApplication implements INotificat
|
|||
public void onCreate() {
|
||||
super.onCreate();
|
||||
Fabric.with(this, new Crashlytics());
|
||||
|
||||
// Create an object of the custom facade impl
|
||||
notificationsLifecycleFacade = new NotificationsLifecycleFacade();
|
||||
// Attach it to react-native-navigation
|
||||
setActivityCallbacks(notificationsLifecycleFacade);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -91,7 +100,7 @@ public class MainApplication extends NavigationApplication implements INotificat
|
|||
return new CustomPushNotification(
|
||||
context,
|
||||
bundle,
|
||||
notificationsLifecycleFacade, // Instead of defaultFacade!!!
|
||||
defaultFacade,
|
||||
defaultAppLaunchHelper,
|
||||
new JsIOHelper()
|
||||
);
|
||||
|
|
|
@ -1,91 +0,0 @@
|
|||
package chat.rocket.reactnative;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.util.Log;
|
||||
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.reactnativenavigation.NavigationApplication;
|
||||
import com.reactnativenavigation.controllers.ActivityCallbacks;
|
||||
import com.reactnativenavigation.react.ReactGateway;
|
||||
import com.wix.reactnativenotifications.core.AppLifecycleFacade;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
public class NotificationsLifecycleFacade extends ActivityCallbacks implements AppLifecycleFacade {
|
||||
|
||||
private static final String TAG = NotificationsLifecycleFacade.class.getSimpleName();
|
||||
|
||||
private Activity mVisibleActivity;
|
||||
private Set<AppVisibilityListener> mListeners = new CopyOnWriteArraySet<>();
|
||||
|
||||
@Override
|
||||
public void onActivityResumed(Activity activity) {
|
||||
switchToVisible(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityPaused(Activity activity) {
|
||||
switchToInvisible(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityStopped(Activity activity) {
|
||||
switchToInvisible(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityDestroyed(Activity activity) {
|
||||
switchToInvisible(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReactInitialized() {
|
||||
return NavigationApplication.instance.isReactContextInitialized();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReactContext getRunningReactContext() {
|
||||
final ReactGateway reactGateway = NavigationApplication.instance.getReactGateway();
|
||||
if (reactGateway == null || !reactGateway.isInitialized()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return reactGateway.getReactContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAppVisible() {
|
||||
return mVisibleActivity != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void addVisibilityListener(AppVisibilityListener listener) {
|
||||
mListeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void removeVisibilityListener(AppVisibilityListener listener) {
|
||||
mListeners.remove(listener);
|
||||
}
|
||||
|
||||
private synchronized void switchToVisible(Activity activity) {
|
||||
if (mVisibleActivity == null) {
|
||||
mVisibleActivity = activity;
|
||||
Log.d(TAG, "Activity is now visible ("+activity+")");
|
||||
for (AppVisibilityListener listener : mListeners) {
|
||||
listener.onAppVisible();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void switchToInvisible(Activity activity) {
|
||||
if (mVisibleActivity == activity) {
|
||||
mVisibleActivity = null;
|
||||
Log.d(TAG, "Activity is now NOT visible ("+activity+")");
|
||||
for (AppVisibilityListener listener : mListeners) {
|
||||
listener.onAppNotVisible();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 867 B After Width: | Height: | Size: 647 B |
Before Width: | Height: | Size: 722 B After Width: | Height: | Size: 664 B |
Before Width: | Height: | Size: 883 B After Width: | Height: | Size: 711 B |
Before Width: | Height: | Size: 591 B After Width: | Height: | Size: 441 B |
Before Width: | Height: | Size: 396 B After Width: | Height: | Size: 445 B |
Before Width: | Height: | Size: 568 B After Width: | Height: | Size: 459 B |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 893 B |
Before Width: | Height: | Size: 715 B After Width: | Height: | Size: 878 B |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 815 B |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 1.6 KiB |
|
@ -2,9 +2,9 @@
|
|||
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
mavenLocal()
|
||||
mavenCentral()
|
||||
google()
|
||||
// mavenCentral()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
|
@ -19,12 +19,12 @@ buildscript {
|
|||
allprojects {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
// mavenCentral()
|
||||
google()
|
||||
maven {
|
||||
url 'https://maven.google.com'
|
||||
}
|
||||
jcenter()
|
||||
// maven {
|
||||
// url 'https://maven.google.com'
|
||||
// }
|
||||
maven { url "https://jitpack.io" }
|
||||
maven {
|
||||
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
|
||||
|
@ -37,14 +37,22 @@ allprojects {
|
|||
}
|
||||
}
|
||||
|
||||
subprojects {
|
||||
subprojects { subproject ->
|
||||
afterEvaluate {
|
||||
if ((subproject.plugins.hasPlugin('android') || subproject.plugins.hasPlugin('android-library'))) {
|
||||
android {
|
||||
compileSdkVersion 27
|
||||
buildToolsVersion "27.0.3"
|
||||
defaultConfig {
|
||||
targetSdkVersion 27
|
||||
}
|
||||
variantFilter { variant ->
|
||||
def names = variant.flavors*.name
|
||||
if (names.contains("reactNative51") || names.contains("reactNative55") || names.contains("reactNative56") || names.contains("reactNative57WixFork")) {
|
||||
setIgnore(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,7 +26,7 @@ project(':react-native-vector-icons').projectDir = new File(rootProject.projectD
|
|||
include ':realm'
|
||||
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/android/app/')
|
||||
project(':react-native-navigation').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-navigation/lib/android/app/')
|
||||
include ':reactnativenotifications'
|
||||
project(':reactnativenotifications').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-notifications/android')
|
||||
include ':app'
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
import { Navigation } from 'react-native-navigation';
|
||||
|
||||
const DRAWER_ID = 'Sidebar';
|
||||
|
||||
class Drawer {
|
||||
constructor() {
|
||||
this.visible = false;
|
||||
|
||||
Navigation.events().registerComponentDidAppearListener(({ componentId }) => {
|
||||
if (componentId === DRAWER_ID) {
|
||||
this.visible = true;
|
||||
}
|
||||
});
|
||||
|
||||
Navigation.events().registerComponentDidDisappearListener(({ componentId }) => {
|
||||
if (componentId === DRAWER_ID) {
|
||||
this.visible = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
toggle() {
|
||||
try {
|
||||
const visibility = !this.visible;
|
||||
Navigation.mergeOptions(DRAWER_ID, {
|
||||
sideMenu: {
|
||||
left: {
|
||||
visible: visibility
|
||||
}
|
||||
}
|
||||
});
|
||||
this.visible = visibility;
|
||||
} catch (error) {
|
||||
console.warn(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new Drawer();
|
|
@ -9,15 +9,15 @@ const icons = {
|
|||
[`${ prefix }-star`]: [25, Ionicons, 'star'],
|
||||
[`${ prefix }-star-outline`]: [25, Ionicons, 'starOutline'],
|
||||
[`${ prefix }-more`]: [25, Ionicons, 'more'],
|
||||
[isIOS ? 'ios-create' : 'md-create']: [30, Ionicons, 'create'],
|
||||
[`${ prefix }-close`]: [30, Ionicons, 'close']
|
||||
[isIOS ? 'ios-create' : 'md-create']: [25, Ionicons, 'create'],
|
||||
[`${ prefix }-close`]: [25, Ionicons, 'close']
|
||||
};
|
||||
|
||||
const iconsMap = {};
|
||||
const iconsLoaded = async() => {
|
||||
const promises = Object.keys(icons).map((icon) => {
|
||||
const Provider = icons[icon][1];
|
||||
return Provider.getImageSource(icon, icons[icon][0]);
|
||||
return Provider.getImageSource(icon, icons[icon][0], '#FFF');
|
||||
});
|
||||
const sources = await Promise.all(promises);
|
||||
Object.keys(icons).forEach((icon, i) => (iconsMap[icons[icon][2]] = sources[i]));
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
class NavigationActionsClass {
|
||||
setNavigator(navigator) {
|
||||
this.navigator = navigator;
|
||||
}
|
||||
|
||||
push = params => this.navigator && this.navigator.push(params)
|
||||
|
||||
pop = params => this.navigator && this.navigator.pop(params)
|
||||
|
||||
popToRoot = params => this.navigator && this.navigator.popToRoot(params)
|
||||
|
||||
resetTo = params => this.navigator && this.navigator.resetTo(params)
|
||||
|
||||
toggleDrawer = params => this.navigator && this.navigator.toggleDrawer(params)
|
||||
|
||||
dismissModal = params => this.navigator && this.navigator.dismissModal(params)
|
||||
}
|
||||
|
||||
export const NavigationActions = new NavigationActionsClass();
|
|
@ -39,7 +39,9 @@ export const ROOMS = createRequestTypes('ROOMS', [
|
|||
'CLOSE_SERVER_DROPDOWN',
|
||||
'TOGGLE_SERVER_DROPDOWN',
|
||||
'CLOSE_SORT_DROPDOWN',
|
||||
'TOGGLE_SORT_DROPDOWN'
|
||||
'TOGGLE_SORT_DROPDOWN',
|
||||
'OPEN_SEARCH_HEADER',
|
||||
'CLOSE_SEARCH_HEADER'
|
||||
]);
|
||||
export const ROOM = createRequestTypes('ROOM', [
|
||||
'ADD_USER_TYPING',
|
||||
|
@ -81,7 +83,6 @@ export const MESSAGES = createRequestTypes('MESSAGES', [
|
|||
]);
|
||||
export const CREATE_CHANNEL = createRequestTypes('CREATE_CHANNEL', [...defaultTypes]);
|
||||
export const SELECTED_USERS = createRequestTypes('SELECTED_USERS', ['ADD_USER', 'REMOVE_USER', 'RESET', 'SET_LOADING']);
|
||||
export const NAVIGATION = createRequestTypes('NAVIGATION', ['SET']);
|
||||
export const SERVER = createRequestTypes('SERVER', [
|
||||
...defaultTypes,
|
||||
'SELECT_SUCCESS',
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
import * as types from './actionsTypes';
|
||||
|
||||
export default function setNavigation(navigator = {}) {
|
||||
return {
|
||||
type: types.NAVIGATION.SET,
|
||||
navigator
|
||||
};
|
||||
}
|
|
@ -50,3 +50,15 @@ export function toggleSortDropdown() {
|
|||
type: types.ROOMS.TOGGLE_SORT_DROPDOWN
|
||||
};
|
||||
}
|
||||
|
||||
export function openSearchHeader() {
|
||||
return {
|
||||
type: types.ROOMS.OPEN_SEARCH_HEADER
|
||||
};
|
||||
}
|
||||
|
||||
export function closeSearchHeader() {
|
||||
return {
|
||||
type: types.ROOMS.CLOSE_SEARCH_HEADER
|
||||
};
|
||||
}
|
||||
|
|
|
@ -245,7 +245,7 @@ export default class MessageActions extends React.Component {
|
|||
showToast(I18n.t('Copied_to_clipboard'));
|
||||
}
|
||||
|
||||
handleShare = async() => {
|
||||
handleShare = () => {
|
||||
const { actionMessage } = this.props;
|
||||
Share.share({
|
||||
message: actionMessage.msg.content.replace(/<(?:.|\n)*?>/gm, '')
|
||||
|
|
|
@ -5,6 +5,7 @@ import {
|
|||
} from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import Icon from 'react-native-vector-icons/MaterialIcons';
|
||||
import { Navigation } from 'react-native-navigation';
|
||||
|
||||
import { appStart as appStartAction } from '../actions';
|
||||
import { logout as logoutAction } from '../actions/login';
|
||||
|
@ -15,9 +16,10 @@ import { STATUS_COLORS } from '../constants/colors';
|
|||
import RocketChat from '../lib/rocketchat';
|
||||
import log from '../utils/log';
|
||||
import I18n from '../i18n';
|
||||
import { NavigationActions } from '../Navigation';
|
||||
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
||||
import DeviceInfo from '../utils/deviceInfo';
|
||||
import Drawer from '../Drawer';
|
||||
import EventEmitter from '../utils/events';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
@ -38,6 +40,9 @@ const styles = StyleSheet.create({
|
|||
fontWeight: 'bold',
|
||||
color: '#292E35'
|
||||
},
|
||||
itemSelected: {
|
||||
backgroundColor: '#F7F8FA'
|
||||
},
|
||||
separator: {
|
||||
borderBottomWidth: StyleSheet.hairlineWidth,
|
||||
borderColor: '#ddd',
|
||||
|
@ -95,7 +100,7 @@ const keyExtractor = item => item.id;
|
|||
export default class Sidebar extends Component {
|
||||
static propTypes = {
|
||||
baseUrl: PropTypes.string,
|
||||
navigator: PropTypes.object,
|
||||
componentId: PropTypes.string,
|
||||
server: PropTypes.string.isRequired,
|
||||
user: PropTypes.object,
|
||||
logout: PropTypes.func.isRequired,
|
||||
|
@ -105,12 +110,15 @@ export default class Sidebar extends Component {
|
|||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
showStatus: false
|
||||
showStatus: false,
|
||||
currentStack: 'RoomsListView'
|
||||
};
|
||||
Navigation.events().bindComponent(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.setStatus();
|
||||
EventEmitter.addEventListener('ChangeStack', this.handleChangeStack);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
|
@ -120,6 +128,22 @@ export default class Sidebar extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
EventEmitter.removeListener('ChangeStack', this.handleChangeStack);
|
||||
}
|
||||
|
||||
handleChangeStack = (event) => {
|
||||
const { stack } = event;
|
||||
this.setStack(stack);
|
||||
}
|
||||
|
||||
navigationButtonPressed = ({ buttonId }) => {
|
||||
if (buttonId === 'cancel') {
|
||||
const { componentId } = this.props;
|
||||
Navigation.dismissModal(componentId);
|
||||
}
|
||||
}
|
||||
|
||||
setStatus = () => {
|
||||
setTimeout(() => {
|
||||
this.setState({
|
||||
|
@ -140,13 +164,21 @@ export default class Sidebar extends Component {
|
|||
});
|
||||
}
|
||||
|
||||
closeDrawer = () => {
|
||||
const { navigator } = this.props;
|
||||
navigator.toggleDrawer({
|
||||
side: 'left',
|
||||
animated: true,
|
||||
to: 'close'
|
||||
setStack = (stack) => {
|
||||
const { currentStack } = this.state;
|
||||
if (currentStack !== stack) {
|
||||
Navigation.setStackRoot('AppRoot', {
|
||||
component: {
|
||||
id: stack,
|
||||
name: stack
|
||||
}
|
||||
});
|
||||
this.setState({ currentStack: stack });
|
||||
}
|
||||
}
|
||||
|
||||
closeDrawer = () => {
|
||||
Drawer.toggle();
|
||||
}
|
||||
|
||||
toggleStatus = () => {
|
||||
|
@ -154,15 +186,15 @@ export default class Sidebar extends Component {
|
|||
this.setState(prevState => ({ showStatus: !prevState.showStatus }));
|
||||
}
|
||||
|
||||
sidebarNavigate = (screen, title) => {
|
||||
sidebarNavigate = (stack) => {
|
||||
this.closeDrawer();
|
||||
NavigationActions.resetTo({ screen, title });
|
||||
this.setStack(stack);
|
||||
}
|
||||
|
||||
renderSeparator = key => <View key={key} style={styles.separator} />;
|
||||
|
||||
renderItem = ({
|
||||
text, left, onPress, testID
|
||||
text, left, onPress, testID, current
|
||||
}) => (
|
||||
<Touch
|
||||
key={text}
|
||||
|
@ -171,7 +203,7 @@ export default class Sidebar extends Component {
|
|||
activeOpacity={0.3}
|
||||
testID={testID}
|
||||
>
|
||||
<View style={styles.item}>
|
||||
<View style={[styles.item, current && styles.itemSelected]}>
|
||||
<View style={styles.itemLeft}>
|
||||
{left}
|
||||
</View>
|
||||
|
@ -188,7 +220,7 @@ export default class Sidebar extends Component {
|
|||
this.renderItem({
|
||||
text: item.name,
|
||||
left: <View style={[styles.status, { backgroundColor: STATUS_COLORS[item.id] }]} />,
|
||||
selected: user.status === item.id,
|
||||
current: user.status === item.id,
|
||||
onPress: () => {
|
||||
this.closeDrawer();
|
||||
this.toggleStatus();
|
||||
|
@ -205,26 +237,30 @@ export default class Sidebar extends Component {
|
|||
}
|
||||
|
||||
renderNavigation = () => {
|
||||
const { currentStack } = this.state;
|
||||
const { logout } = this.props;
|
||||
return (
|
||||
[
|
||||
this.renderItem({
|
||||
text: I18n.t('Chats'),
|
||||
left: <Icon name='chat-bubble' size={20} />,
|
||||
onPress: () => this.sidebarNavigate('RoomsListView', I18n.t('Messages')),
|
||||
testID: 'sidebar-chats'
|
||||
onPress: () => this.sidebarNavigate('RoomsListView'),
|
||||
testID: 'sidebar-chats',
|
||||
current: currentStack === 'RoomsListView'
|
||||
}),
|
||||
this.renderItem({
|
||||
text: I18n.t('Profile'),
|
||||
left: <Icon name='person' size={20} />,
|
||||
onPress: () => this.sidebarNavigate('ProfileView', I18n.t('Profile')),
|
||||
testID: 'sidebar-profile'
|
||||
onPress: () => this.sidebarNavigate('ProfileView'),
|
||||
testID: 'sidebar-profile',
|
||||
current: currentStack === 'ProfileView'
|
||||
}),
|
||||
this.renderItem({
|
||||
text: I18n.t('Settings'),
|
||||
left: <Icon name='settings' size={20} />,
|
||||
onPress: () => this.sidebarNavigate('SettingsView', I18n.t('Settings')),
|
||||
testID: 'sidebar-settings'
|
||||
onPress: () => this.sidebarNavigate('SettingsView'),
|
||||
testID: 'sidebar-settings',
|
||||
current: currentStack === 'SettingsView'
|
||||
}),
|
||||
this.renderSeparator('separator-logout'),
|
||||
this.renderItem({
|
||||
|
|
77
app/index.js
|
@ -1,5 +1,5 @@
|
|||
import { Component } from 'react';
|
||||
import { Linking } from 'react-native';
|
||||
import { Linking, Platform, Dimensions } from 'react-native';
|
||||
import { Navigation } from 'react-native-navigation';
|
||||
|
||||
import store from './lib/createStore';
|
||||
|
@ -8,35 +8,51 @@ import { iconsLoaded } from './Icons';
|
|||
import { registerScreens } from './views';
|
||||
import { deepLinkingOpen } from './actions/deepLinking';
|
||||
import parseQuery from './lib/methods/helpers/parseQuery';
|
||||
import I18n from './i18n';
|
||||
import { initializePushNotifications } from './push';
|
||||
|
||||
const isAndroid = () => Platform.OS === 'android';
|
||||
|
||||
const startLogged = () => {
|
||||
Navigation.startSingleScreenApp({
|
||||
screen: {
|
||||
screen: 'RoomsListView',
|
||||
title: I18n.t('Messages')
|
||||
},
|
||||
drawer: {
|
||||
Navigation.setRoot({
|
||||
root: {
|
||||
sideMenu: {
|
||||
left: {
|
||||
screen: 'Sidebar'
|
||||
component: {
|
||||
id: 'Sidebar',
|
||||
name: 'Sidebar'
|
||||
}
|
||||
},
|
||||
animationType: 'fade'
|
||||
center: {
|
||||
stack: {
|
||||
id: 'AppRoot',
|
||||
children: [{
|
||||
component: {
|
||||
id: 'RoomsListView',
|
||||
name: 'RoomsListView'
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const startNotLogged = () => {
|
||||
Navigation.startSingleScreenApp({
|
||||
screen: {
|
||||
screen: 'OnboardingView',
|
||||
navigatorStyle: {
|
||||
navBarHidden: true
|
||||
Navigation.setRoot({
|
||||
root: {
|
||||
stack: {
|
||||
children: [{
|
||||
component: {
|
||||
name: 'OnboardingView'
|
||||
}
|
||||
}],
|
||||
options: {
|
||||
layout: {
|
||||
orientation: ['portrait']
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
animationType: 'fade',
|
||||
appStyle: {
|
||||
orientation: 'portrait'
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -63,6 +79,29 @@ export default class App extends Component {
|
|||
store.subscribe(this.onStoreUpdate.bind(this));
|
||||
initializePushNotifications();
|
||||
|
||||
Navigation.events().registerAppLaunchedListener(() => {
|
||||
Navigation.setDefaultOptions({
|
||||
topBar: {
|
||||
backButton: {
|
||||
icon: { uri: 'back', scale: Dimensions.get('window').scale }
|
||||
},
|
||||
title: {
|
||||
color: isAndroid() ? '#FFF' : undefined
|
||||
},
|
||||
background: {
|
||||
color: isAndroid() ? '#2F343D' : undefined
|
||||
},
|
||||
buttonColor: '#FFF'
|
||||
},
|
||||
sideMenu: {
|
||||
left: {
|
||||
enabled: false
|
||||
}
|
||||
}
|
||||
});
|
||||
store.dispatch(appInit());
|
||||
store.subscribe(this.onStoreUpdate.bind(this));
|
||||
});
|
||||
Linking
|
||||
.getInitialURL()
|
||||
.then(url => handleOpenURL({ url }))
|
||||
|
|
|
@ -31,7 +31,7 @@ const getRoomDpp = async function() {
|
|||
}
|
||||
};
|
||||
|
||||
export default async function() {
|
||||
export default function() {
|
||||
const { database: db } = database;
|
||||
|
||||
return new Promise(async(resolve, reject) => {
|
||||
|
|
|
@ -34,7 +34,7 @@ async function loadMessagesForRoomDDP(...args) {
|
|||
}
|
||||
}
|
||||
|
||||
export default async function loadMessagesForRoom(...args) {
|
||||
export default function loadMessagesForRoom(...args) {
|
||||
const { database: db } = database;
|
||||
return new Promise(async(resolve, reject) => {
|
||||
try {
|
||||
|
|
|
@ -25,7 +25,7 @@ async function loadMissedMessagesDDP(...args) {
|
|||
}
|
||||
}
|
||||
|
||||
export default async function loadMissedMessages(...args) {
|
||||
export default function loadMissedMessages(...args) {
|
||||
const { database: db } = database;
|
||||
return new Promise(async(resolve, reject) => {
|
||||
try {
|
||||
|
|
|
@ -23,7 +23,7 @@ const stop = () => {
|
|||
clearTimeout(timer);
|
||||
};
|
||||
|
||||
export default async function subscribeRoom({ rid, t }) {
|
||||
export default function subscribeRoom({ rid, t }) {
|
||||
if (promises) {
|
||||
promises.then(unsubscribe);
|
||||
promises = false;
|
||||
|
|
|
@ -151,17 +151,19 @@ const RocketChat = {
|
|||
}
|
||||
},
|
||||
connect(url, login) {
|
||||
return new Promise(async() => {
|
||||
return new Promise(() => {
|
||||
if (this.ddp) {
|
||||
RocketChat.disconnect();
|
||||
this.ddp = null;
|
||||
}
|
||||
|
||||
SDK.api.setBaseUrl(url);
|
||||
|
||||
if (login) {
|
||||
SDK.api.setAuth({ authToken: login.token, userId: login.id });
|
||||
RocketChat.setApiUser({ userId: login.id, authToken: login.token });
|
||||
}
|
||||
|
||||
SDK.api.setBaseUrl(url);
|
||||
SDK.driver.connect({ host: url, useSsl: true }, (err, ddp) => {
|
||||
if (err) {
|
||||
return console.warn(err);
|
||||
|
@ -191,11 +193,7 @@ const RocketChat = {
|
|||
// SDK.driver.on('background', () => this.getRooms().catch(e => log('background getRooms', e)));
|
||||
|
||||
SDK.driver.on('logged', protectedFunction((error, user) => {
|
||||
SDK.api.setAuth({ authToken: user.token, userId: user.id });
|
||||
SDK.api.currentLogin = {
|
||||
userId: user.id,
|
||||
authToken: user.token
|
||||
};
|
||||
RocketChat.setApiUser({ userId: user.id, authToken: user.token });
|
||||
this.loginSuccess(user);
|
||||
this.getRooms().catch(e => log('logged getRooms', e));
|
||||
this.subscribeRooms(user.id);
|
||||
|
@ -506,13 +504,12 @@ const RocketChat = {
|
|||
} catch (error) {
|
||||
console.warn(error);
|
||||
}
|
||||
SDK.api.setAuth({ authToken: null, userId: null });
|
||||
SDK.api.currentLogin = {
|
||||
userId: null,
|
||||
authToken: null
|
||||
};
|
||||
RocketChat.setApiUser({ userId: null, authToken: null });
|
||||
},
|
||||
setApiUser({ userId, authToken }) {
|
||||
SDK.api.setAuth({ userId, authToken });
|
||||
SDK.api.currentLogin = { userId, authToken };
|
||||
},
|
||||
|
||||
registerPushToken(userId) {
|
||||
const deviceToken = getDeviceToken();
|
||||
if (deviceToken) {
|
||||
|
@ -566,6 +563,8 @@ const RocketChat = {
|
|||
data = data.filtered('t != $0', 'd');
|
||||
}
|
||||
data = data.slice(0, 7);
|
||||
const array = Array.from(data);
|
||||
data = JSON.parse(JSON.stringify(array));
|
||||
|
||||
const usernames = data.map(sub => sub.name);
|
||||
try {
|
||||
|
|
|
@ -3,8 +3,8 @@ import { CREATE_CHANNEL } from '../actions/actionsTypes';
|
|||
const initialState = {
|
||||
isFetching: false,
|
||||
failure: false,
|
||||
result: '',
|
||||
error: ''
|
||||
result: {},
|
||||
error: {}
|
||||
};
|
||||
|
||||
export default function messages(state = initialState, action) {
|
||||
|
@ -14,7 +14,7 @@ export default function messages(state = initialState, action) {
|
|||
...state,
|
||||
isFetching: true,
|
||||
failure: false,
|
||||
error: ''
|
||||
error: {}
|
||||
};
|
||||
case CREATE_CHANNEL.SUCCESS:
|
||||
return {
|
||||
|
|
|
@ -6,7 +6,6 @@ import messages from './messages';
|
|||
import room from './room';
|
||||
import rooms from './rooms';
|
||||
import server from './server';
|
||||
import navigator from './navigator';
|
||||
import selectedUsers from './selectedUsers';
|
||||
import createChannel from './createChannel';
|
||||
import app from './app';
|
||||
|
@ -26,7 +25,6 @@ export default combineReducers({
|
|||
meteor,
|
||||
messages,
|
||||
server,
|
||||
navigator,
|
||||
selectedUsers,
|
||||
createChannel,
|
||||
app,
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
import * as types from '../actions/actionsTypes';
|
||||
|
||||
const initialState = {};
|
||||
|
||||
export default function navigations(state = initialState, action) {
|
||||
switch (action.type) {
|
||||
case types.NAVIGATION.SET:
|
||||
return action.navigator;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
|
@ -6,7 +6,8 @@ const initialState = {
|
|||
searchText: '',
|
||||
showServerDropdown: false,
|
||||
closeServerDropdown: false,
|
||||
showSortDropdown: false
|
||||
showSortDropdown: false,
|
||||
showSearchHeader: false
|
||||
};
|
||||
|
||||
export default function login(state = initialState, action) {
|
||||
|
@ -53,6 +54,16 @@ export default function login(state = initialState, action) {
|
|||
...state,
|
||||
showSortDropdown: !state.showSortDropdown
|
||||
};
|
||||
case types.ROOMS.OPEN_SEARCH_HEADER:
|
||||
return {
|
||||
...state,
|
||||
showSearchHeader: true
|
||||
};
|
||||
case types.ROOMS.CLOSE_SEARCH_HEADER:
|
||||
return {
|
||||
...state,
|
||||
showSearchHeader: false
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
import { delay } from 'redux-saga';
|
||||
import {
|
||||
select, put, call, take, takeLatest
|
||||
} from 'redux-saga/effects';
|
||||
import { NavigationActions } from '../Navigation';
|
||||
|
||||
import { CREATE_CHANNEL, LOGIN } from '../actions/actionsTypes';
|
||||
import { createChannelSuccess, createChannelFailure } from '../actions/createChannel';
|
||||
|
@ -20,16 +18,6 @@ const handleRequest = function* handleRequest({ data }) {
|
|||
}
|
||||
const result = yield call(create, data);
|
||||
yield put(createChannelSuccess(result));
|
||||
yield delay(300);
|
||||
const { rid, name } = result;
|
||||
NavigationActions.dismissModal();
|
||||
yield delay(600);
|
||||
NavigationActions.push({
|
||||
screen: 'RoomView',
|
||||
title: name,
|
||||
backButtonTitle: '',
|
||||
passProps: { rid }
|
||||
});
|
||||
} catch (err) {
|
||||
yield put(createChannelFailure(err));
|
||||
}
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
import { AsyncStorage } from 'react-native';
|
||||
import { delay } from 'redux-saga';
|
||||
import {
|
||||
takeLatest, take, select, put
|
||||
} from 'redux-saga/effects';
|
||||
import { Navigation } from 'react-native-navigation';
|
||||
|
||||
import * as types from '../actions/actionsTypes';
|
||||
import { appStart } from '../actions';
|
||||
import { selectServerRequest } from '../actions/server';
|
||||
import database from '../lib/realm';
|
||||
import RocketChat from '../lib/rocketchat';
|
||||
import { NavigationActions } from '../Navigation';
|
||||
import EventEmitter from '../utils/events';
|
||||
|
||||
const navigate = function* go({ params, sameServer = true }) {
|
||||
if (!sameServer) {
|
||||
|
@ -17,12 +19,16 @@ const navigate = function* go({ params, sameServer = true }) {
|
|||
if (params.rid) {
|
||||
const canOpenRoom = yield RocketChat.canOpenRoom(params);
|
||||
if (canOpenRoom) {
|
||||
return NavigationActions.push({
|
||||
screen: 'RoomView',
|
||||
backButtonTitle: '',
|
||||
// Make sure current stack is RoomsListView before navigate to RoomView
|
||||
EventEmitter.emit('ChangeStack', { stack: 'RoomsListView' });
|
||||
yield Navigation.popToRoot('RoomsListView');
|
||||
Navigation.push('RoomsListView', {
|
||||
component: {
|
||||
name: 'RoomView',
|
||||
passProps: {
|
||||
rid: params.rid
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -66,17 +72,14 @@ const handleOpen = function* handleOpen({ params }) {
|
|||
} else { // if deep link is from a different server
|
||||
// search if deep link's server already exists
|
||||
const servers = yield database.databases.serversDB.objects('servers').filtered('id = $0', host); // TODO: need better test
|
||||
if (servers.length) {
|
||||
const deepLinkServer = servers[0].id;
|
||||
if (!token) {
|
||||
yield put(appStart('outside'));
|
||||
} else {
|
||||
yield put(selectServerRequest(deepLinkServer));
|
||||
if (servers.length && token) {
|
||||
yield put(selectServerRequest(host));
|
||||
yield take(types.METEOR.REQUEST);
|
||||
yield navigate({ params, sameServer: false });
|
||||
}
|
||||
} else {
|
||||
yield put(selectServerRequest(host));
|
||||
yield put(appStart('outside'));
|
||||
yield delay(1000);
|
||||
EventEmitter.emit('NewServer', { server: host });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -3,6 +3,7 @@ import { delay } from 'redux-saga';
|
|||
import {
|
||||
put, call, take, takeLatest, select, all
|
||||
} from 'redux-saga/effects';
|
||||
import { Navigation } from 'react-native-navigation';
|
||||
|
||||
import * as types from '../actions/actionsTypes';
|
||||
import { appStart } from '../actions';
|
||||
|
@ -25,7 +26,6 @@ import {
|
|||
import RocketChat from '../lib/rocketchat';
|
||||
import log from '../utils/log';
|
||||
import I18n from '../i18n';
|
||||
import { NavigationActions } from '../Navigation';
|
||||
|
||||
const getUser = state => state.login.user;
|
||||
const getServer = state => state.server.server;
|
||||
|
@ -48,7 +48,7 @@ const handleLoginSuccess = function* handleLoginSuccess() {
|
|||
} else {
|
||||
yield delay(300);
|
||||
if (adding) {
|
||||
NavigationActions.dismissModal();
|
||||
yield Navigation.dismissAllModals();
|
||||
} else {
|
||||
yield put(appStart('inside'));
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { delay } from 'redux-saga';
|
||||
import { takeLatest, put, call } from 'redux-saga/effects';
|
||||
import { Navigation } from 'react-native-navigation';
|
||||
|
||||
import { MESSAGES } from '../actions/actionsTypes';
|
||||
import {
|
||||
|
@ -18,7 +19,6 @@ import {
|
|||
import RocketChat from '../lib/rocketchat';
|
||||
import database from '../lib/realm';
|
||||
import log from '../utils/log';
|
||||
import { NavigationActions } from '../Navigation';
|
||||
|
||||
const deleteMessage = message => RocketChat.deleteMessage(message);
|
||||
const editMessage = message => RocketChat.editMessage(message);
|
||||
|
@ -76,13 +76,21 @@ const handleTogglePinRequest = function* handleTogglePinRequest({ message }) {
|
|||
};
|
||||
|
||||
const goRoom = function* goRoom({ rid, name }) {
|
||||
NavigationActions.popToRoot();
|
||||
yield delay(1000);
|
||||
NavigationActions.push({
|
||||
screen: 'RoomView',
|
||||
title: name,
|
||||
backButtonTitle: '',
|
||||
passProps: { rid }
|
||||
yield Navigation.popToRoot('RoomsListView');
|
||||
Navigation.push('RoomsListView', {
|
||||
component: {
|
||||
name: 'RoomView',
|
||||
passProps: {
|
||||
rid
|
||||
},
|
||||
options: {
|
||||
topBar: {
|
||||
title: {
|
||||
text: name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import {
|
|||
} from 'redux-saga/effects';
|
||||
import { delay } from 'redux-saga';
|
||||
import { BACKGROUND } from 'redux-enhancer-react-native-appstate';
|
||||
import { Navigation } from 'react-native-navigation';
|
||||
|
||||
import * as types from '../actions/actionsTypes';
|
||||
// import { roomsSuccess, roomsFailure } from '../actions/rooms';
|
||||
|
@ -13,7 +14,6 @@ import RocketChat from '../lib/rocketchat';
|
|||
import database from '../lib/realm';
|
||||
import log from '../utils/log';
|
||||
import I18n from '../i18n';
|
||||
import { NavigationActions } from '../Navigation';
|
||||
|
||||
const leaveRoom = rid => RocketChat.leaveRoom(rid);
|
||||
const eraseRoom = rid => RocketChat.eraseRoom(rid);
|
||||
|
@ -141,9 +141,8 @@ const updateLastOpen = function* updateLastOpen() {
|
|||
yield put(setLastOpen());
|
||||
};
|
||||
|
||||
const goRoomsListAndDelete = function* goRoomsListAndDelete(rid) {
|
||||
NavigationActions.popToRoot();
|
||||
yield delay(1000);
|
||||
const goRoomsListAndDelete = function* goRoomsListAndDelete(rid, type) {
|
||||
yield Navigation.popToRoot(type === 'erase' ? 'RoomActionsView' : 'RoomInfoEditView');
|
||||
try {
|
||||
database.write(() => {
|
||||
const messages = database.objects('messages').filtered('rid = $0', rid);
|
||||
|
@ -160,7 +159,7 @@ const handleLeaveRoom = function* handleLeaveRoom({ rid }) {
|
|||
try {
|
||||
sub.stop();
|
||||
yield call(leaveRoom, rid);
|
||||
yield goRoomsListAndDelete(rid);
|
||||
yield goRoomsListAndDelete(rid, 'delete');
|
||||
} catch (e) {
|
||||
if (e.error === 'error-you-are-last-owner') {
|
||||
Alert.alert(I18n.t(e.error));
|
||||
|
@ -174,7 +173,7 @@ const handleEraseRoom = function* handleEraseRoom({ rid }) {
|
|||
try {
|
||||
sub.stop();
|
||||
yield call(eraseRoom, rid);
|
||||
yield goRoomsListAndDelete(rid);
|
||||
yield goRoomsListAndDelete(rid, 'erase');
|
||||
} catch (e) {
|
||||
Alert.alert(I18n.t('There_was_an_error_while_action', { action: I18n.t('erasing_room') }));
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ import { AsyncStorage } from 'react-native';
|
|||
import { Navigation } from 'react-native-navigation';
|
||||
import { Provider } from 'react-redux';
|
||||
|
||||
import { NavigationActions } from '../Navigation';
|
||||
import { SERVER } from '../actions/actionsTypes';
|
||||
import * as actions from '../actions';
|
||||
import { connectRequest } from '../actions/connect';
|
||||
|
@ -50,11 +49,23 @@ const handleServerRequest = function* handleServerRequest({ server }) {
|
|||
try {
|
||||
if (LoginSignupView == null) {
|
||||
LoginSignupView = require('../views/LoginSignupView').default;
|
||||
Navigation.registerComponent('LoginSignupView', () => LoginSignupView, store, Provider);
|
||||
Navigation.registerComponentWithRedux('LoginSignupView', () => LoginSignupView, Provider, store);
|
||||
}
|
||||
|
||||
yield call(validate, server);
|
||||
yield call(NavigationActions.push, { screen: 'LoginSignupView', title: server, backButtonTitle: '' });
|
||||
yield Navigation.push('NewServerView', {
|
||||
component: {
|
||||
name: 'LoginSignupView',
|
||||
options: {
|
||||
topBar: {
|
||||
title: {
|
||||
text: server
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
database.databases.serversDB.write(() => {
|
||||
database.databases.serversDB.create('servers', { id: server }, true);
|
||||
});
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
import log from './log';
|
||||
|
||||
class EventEmitter {
|
||||
constructor() {
|
||||
this.events = {};
|
||||
}
|
||||
|
||||
addEventListener(event, listener) {
|
||||
if (typeof this.events[event] !== 'object') {
|
||||
this.events[event] = [];
|
||||
}
|
||||
this.events[event].push(listener);
|
||||
return listener;
|
||||
}
|
||||
|
||||
removeListener(event, listener) {
|
||||
if (typeof this.events[event] === 'object') {
|
||||
const idx = this.events[event].indexOf(listener);
|
||||
if (idx > -1) {
|
||||
this.events[event].splice(idx, 1);
|
||||
}
|
||||
if (this.events[event].length === 0) {
|
||||
delete this.events[event];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
emit(event, ...args) {
|
||||
if (typeof this.events[event] === 'object') {
|
||||
this.events[event].forEach((listener) => {
|
||||
try {
|
||||
listener.apply(this, args);
|
||||
} catch (e) {
|
||||
log('EventEmitter.emit', e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const events = new EventEmitter();
|
||||
export default events;
|
|
@ -2,8 +2,10 @@ import React from 'react';
|
|||
import { connect } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
View, Text, Switch, SafeAreaView, ScrollView, TextInput, StyleSheet, FlatList, Platform
|
||||
View, Text, Switch, ScrollView, TextInput, StyleSheet, FlatList, Platform
|
||||
} from 'react-native';
|
||||
import { Navigation } from 'react-native-navigation';
|
||||
import SafeAreaView from 'react-native-safe-area-view';
|
||||
|
||||
import Loading from '../containers/Loading';
|
||||
import LoggedView from './View';
|
||||
|
@ -72,7 +74,10 @@ const styles = StyleSheet.create({
|
|||
|
||||
@connect(state => ({
|
||||
baseUrl: state.settings.Site_Url || state.server ? state.server.server : '',
|
||||
createChannel: state.createChannel,
|
||||
error: state.createChannel.error,
|
||||
failure: state.createChannel.failure,
|
||||
isFetching: state.createChannel.isFetching,
|
||||
result: state.createChannel.result,
|
||||
users: state.selectedUsers.users
|
||||
}), dispatch => ({
|
||||
create: data => dispatch(createChannelRequestAction(data)),
|
||||
|
@ -81,11 +86,14 @@ const styles = StyleSheet.create({
|
|||
/** @extends React.Component */
|
||||
export default class CreateChannelView extends LoggedView {
|
||||
static propTypes = {
|
||||
navigator: PropTypes.object,
|
||||
componentId: PropTypes.string,
|
||||
baseUrl: PropTypes.string,
|
||||
create: PropTypes.func.isRequired,
|
||||
removeUser: PropTypes.func.isRequired,
|
||||
createChannel: PropTypes.object.isRequired,
|
||||
error: PropTypes.object,
|
||||
failure: PropTypes.bool,
|
||||
isFetching: PropTypes.bool,
|
||||
result: PropTypes.object,
|
||||
users: PropTypes.array.isRequired
|
||||
};
|
||||
|
||||
|
@ -97,7 +105,7 @@ export default class CreateChannelView extends LoggedView {
|
|||
readOnly: false,
|
||||
broadcast: false
|
||||
};
|
||||
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this));
|
||||
Navigation.events().bindComponent(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
@ -107,46 +115,70 @@ export default class CreateChannelView extends LoggedView {
|
|||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const { createChannel } = this.props;
|
||||
const {
|
||||
isFetching, failure, error, result, componentId
|
||||
} = this.props;
|
||||
|
||||
if (createChannel.error && prevProps.createChannel.error !== createChannel.error) {
|
||||
setTimeout(() => {
|
||||
const msg = createChannel.error.reason || I18n.t('There_was_an_error_while_action', { action: I18n.t('creating_channel') });
|
||||
if (!isFetching && isFetching !== prevProps.isFetching) {
|
||||
setTimeout(async() => {
|
||||
if (failure) {
|
||||
const msg = error.reason || I18n.t('There_was_an_error_while_action', { action: I18n.t('creating_channel') });
|
||||
showErrorAlert(msg);
|
||||
} else {
|
||||
const { rid, name } = result;
|
||||
await Navigation.dismissModal(componentId);
|
||||
Navigation.push('RoomsListView', {
|
||||
component: {
|
||||
name: 'RoomView',
|
||||
passProps: {
|
||||
rid
|
||||
},
|
||||
options: {
|
||||
topBar: {
|
||||
title: {
|
||||
text: name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
|
||||
onChangeText = (channelName) => {
|
||||
const { navigator } = this.props;
|
||||
|
||||
const { componentId } = this.props;
|
||||
const rightButtons = [];
|
||||
if (channelName.trim().length > 0) {
|
||||
rightButtons.push({
|
||||
id: 'create',
|
||||
title: 'Create',
|
||||
testID: 'create-channel-submit'
|
||||
text: 'Create',
|
||||
testID: 'create-channel-submit',
|
||||
color: Platform.OS === 'android' ? '#FFF' : undefined
|
||||
});
|
||||
}
|
||||
navigator.setButtons({ rightButtons });
|
||||
Navigation.mergeOptions(componentId, {
|
||||
topBar: {
|
||||
rightButtons
|
||||
}
|
||||
});
|
||||
this.setState({ channelName });
|
||||
}
|
||||
|
||||
async onNavigatorEvent(event) {
|
||||
if (event.type === 'NavBarButtonPress') {
|
||||
if (event.id === 'create') {
|
||||
navigationButtonPressed = ({ buttonId }) => {
|
||||
if (buttonId === 'create') {
|
||||
this.submit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
submit = () => {
|
||||
const {
|
||||
channelName, type, readOnly, broadcast
|
||||
} = this.state;
|
||||
const { users: usersProps, createChannel, create } = this.props;
|
||||
const { users: usersProps, isFetching, create } = this.props;
|
||||
|
||||
if (!channelName.trim() || createChannel.isFetching) {
|
||||
if (!channelName.trim() || isFetching) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -256,7 +288,7 @@ export default class CreateChannelView extends LoggedView {
|
|||
|
||||
render() {
|
||||
const { channelName } = this.state;
|
||||
const { users, createChannel } = this.props;
|
||||
const { users, isFetching } = this.props;
|
||||
const userCount = users.length;
|
||||
|
||||
return (
|
||||
|
@ -264,7 +296,7 @@ export default class CreateChannelView extends LoggedView {
|
|||
contentContainerStyle={[sharedStyles.container, styles.container]}
|
||||
keyboardVerticalOffset={128}
|
||||
>
|
||||
<SafeAreaView testID='create-channel-view' style={styles.container}>
|
||||
<SafeAreaView testID='create-channel-view' style={styles.container} forceInset={{ bottom: 'never' }}>
|
||||
<ScrollView {...scrollPersistTaps}>
|
||||
<View style={sharedStyles.separatorVertical}>
|
||||
<TextInput
|
||||
|
@ -292,7 +324,7 @@ export default class CreateChannelView extends LoggedView {
|
|||
<Text style={styles.invitedCount}>{userCount === 1 ? I18n.t('1_user') : I18n.t('N_users', { n: userCount })}</Text>
|
||||
</View>
|
||||
{this.renderInvitedList()}
|
||||
<Loading visible={createChannel.isFetching} />
|
||||
<Loading visible={isFetching} />
|
||||
</ScrollView>
|
||||
</SafeAreaView>
|
||||
</KeyboardView>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
Text, View, SafeAreaView, ScrollView
|
||||
} from 'react-native';
|
||||
import { Text, View, ScrollView } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import { Navigation } from 'react-native-navigation';
|
||||
import SafeAreaView from 'react-native-safe-area-view';
|
||||
|
||||
import LoggedView from './View';
|
||||
import { forgotPasswordInit as forgotPasswordInitAction, forgotPasswordRequest as forgotPasswordRequestAction } from '../actions/login';
|
||||
|
@ -25,7 +25,7 @@ import I18n from '../i18n';
|
|||
/** @extends React.Component */
|
||||
export default class ForgotPasswordView extends LoggedView {
|
||||
static propTypes = {
|
||||
navigator: PropTypes.object,
|
||||
componentId: PropTypes.string,
|
||||
forgotPasswordInit: PropTypes.func.isRequired,
|
||||
forgotPasswordRequest: PropTypes.func.isRequired,
|
||||
login: PropTypes.object
|
||||
|
@ -46,9 +46,9 @@ export default class ForgotPasswordView extends LoggedView {
|
|||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
const { login, navigator } = this.props;
|
||||
const { login, componentId } = this.props;
|
||||
if (login.success) {
|
||||
navigator.pop();
|
||||
Navigation.pop(componentId);
|
||||
setTimeout(() => {
|
||||
showErrorAlert(I18n.t('Forgot_password_If_this_email_is_registered'), I18n.t('Alert'));
|
||||
});
|
||||
|
@ -84,7 +84,7 @@ export default class ForgotPasswordView extends LoggedView {
|
|||
keyboardVerticalOffset={128}
|
||||
>
|
||||
<ScrollView {...scrollPersistTaps} contentContainerStyle={styles.containerScrollView}>
|
||||
<SafeAreaView style={styles.container} testID='forgot-password-view'>
|
||||
<SafeAreaView style={styles.container} testID='forgot-password-view' forceInset={{ bottom: 'never' }}>
|
||||
<View>
|
||||
<TextInput
|
||||
inputStyle={invalidEmail ? { borderColor: 'red' } : {}}
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
Text, View, ScrollView, TouchableOpacity, LayoutAnimation, Image, StyleSheet, SafeAreaView
|
||||
Text, View, ScrollView, TouchableOpacity, LayoutAnimation, Image, StyleSheet
|
||||
} from 'react-native';
|
||||
import { connect, Provider } from 'react-redux';
|
||||
import { Navigation } from 'react-native-navigation';
|
||||
import Icon from 'react-native-vector-icons/FontAwesome';
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
import { Base64 } from 'js-base64';
|
||||
import SafeAreaView from 'react-native-safe-area-view';
|
||||
|
||||
import { open as openAction, close as closeAction } from '../actions/login';
|
||||
import LoggedView from './View';
|
||||
|
@ -71,7 +72,7 @@ let RegisterView = null;
|
|||
/** @extends React.Component */
|
||||
export default class LoginSignupView extends LoggedView {
|
||||
static propTypes = {
|
||||
navigator: PropTypes.object,
|
||||
componentId: PropTypes.string,
|
||||
open: PropTypes.func.isRequired,
|
||||
close: PropTypes.func.isRequired,
|
||||
isFetching: PropTypes.bool,
|
||||
|
@ -189,15 +190,26 @@ export default class LoginSignupView extends LoggedView {
|
|||
openOAuth = (oAuthUrl) => {
|
||||
if (OAuthView == null) {
|
||||
OAuthView = require('./OAuthView').default;
|
||||
Navigation.registerComponent('OAuthView', () => OAuthView, store, Provider);
|
||||
Navigation.registerComponentWithRedux('OAuthView', () => OAuthView, Provider, store);
|
||||
}
|
||||
|
||||
const { navigator } = this.props;
|
||||
navigator.showModal({
|
||||
screen: 'OAuthView',
|
||||
title: 'OAuth',
|
||||
Navigation.showModal({
|
||||
stack: {
|
||||
children: [{
|
||||
component: {
|
||||
name: 'OAuthView',
|
||||
passProps: {
|
||||
oAuthUrl
|
||||
},
|
||||
options: {
|
||||
topBar: {
|
||||
title: {
|
||||
text: 'OAuth'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -205,28 +217,42 @@ export default class LoginSignupView extends LoggedView {
|
|||
login = () => {
|
||||
if (LoginView == null) {
|
||||
LoginView = require('./LoginView').default;
|
||||
Navigation.registerComponent('LoginView', () => LoginView, store, Provider);
|
||||
Navigation.registerComponentWithRedux('LoginView', () => LoginView, Provider, store);
|
||||
}
|
||||
|
||||
const { navigator, server } = this.props;
|
||||
navigator.push({
|
||||
screen: 'LoginView',
|
||||
title: server,
|
||||
backButtonTitle: ''
|
||||
const { componentId, server } = this.props;
|
||||
Navigation.push(componentId, {
|
||||
component: {
|
||||
name: 'LoginView',
|
||||
options: {
|
||||
topBar: {
|
||||
title: {
|
||||
text: server
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
register = () => {
|
||||
if (RegisterView == null) {
|
||||
RegisterView = require('./RegisterView').default;
|
||||
Navigation.registerComponent('RegisterView', () => RegisterView, store, Provider);
|
||||
Navigation.registerComponentWithRedux('RegisterView', () => RegisterView, Provider, store);
|
||||
}
|
||||
|
||||
const { navigator, server } = this.props;
|
||||
navigator.push({
|
||||
screen: 'RegisterView',
|
||||
title: server,
|
||||
backButtonTitle: ''
|
||||
const { componentId, server } = this.props;
|
||||
Navigation.push(componentId, {
|
||||
component: {
|
||||
name: 'RegisterView',
|
||||
options: {
|
||||
topBar: {
|
||||
title: {
|
||||
text: server
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -335,7 +361,7 @@ export default class LoginSignupView extends LoggedView {
|
|||
style={[sharedStyles.container, sharedStyles.containerScrollView]}
|
||||
{...scrollPersistTaps}
|
||||
>
|
||||
<SafeAreaView style={sharedStyles.container} testID='welcome-view'>
|
||||
<SafeAreaView style={sharedStyles.container} testID='welcome-view' forceInset={{ bottom: 'never' }}>
|
||||
<View style={styles.container}>
|
||||
<Text style={[sharedStyles.loginText, styles.header, { color: '#81848A' }]}>{I18n.t('Welcome_title_pt_1')}</Text>
|
||||
<Text style={[sharedStyles.loginText, styles.header]}>{I18n.t('Welcome_title_pt_2')}</Text>
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
Keyboard, Text, ScrollView, View, SafeAreaView
|
||||
Keyboard, Text, ScrollView, View
|
||||
} from 'react-native';
|
||||
import { connect, Provider } from 'react-redux';
|
||||
import { Navigation } from 'react-native-navigation';
|
||||
import { Answers } from 'react-native-fabric';
|
||||
import SafeAreaView from 'react-native-safe-area-view';
|
||||
|
||||
import RocketChat from '../lib/rocketchat';
|
||||
import KeyboardView from '../presentation/KeyboardView';
|
||||
|
@ -35,7 +36,7 @@ let ForgotPasswordView = null;
|
|||
/** @extends React.Component */
|
||||
export default class LoginView extends LoggedView {
|
||||
static propTypes = {
|
||||
navigator: PropTypes.object,
|
||||
componentId: PropTypes.string,
|
||||
loginSubmit: PropTypes.func.isRequired,
|
||||
login: PropTypes.object,
|
||||
server: PropTypes.string,
|
||||
|
@ -76,28 +77,42 @@ export default class LoginView extends LoggedView {
|
|||
register = () => {
|
||||
if (RegisterView == null) {
|
||||
RegisterView = require('./RegisterView').default;
|
||||
Navigation.registerComponent('RegisterView', () => RegisterView, store, Provider);
|
||||
Navigation.registerComponentWithRedux('RegisterView', () => RegisterView, Provider, store);
|
||||
}
|
||||
|
||||
const { navigator, server } = this.props;
|
||||
navigator.push({
|
||||
screen: 'RegisterView',
|
||||
title: server,
|
||||
backButtonTitle: ''
|
||||
const { componentId, server } = this.props;
|
||||
Navigation.push(componentId, {
|
||||
component: {
|
||||
name: 'RegisterView',
|
||||
options: {
|
||||
topBar: {
|
||||
title: {
|
||||
text: server
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
forgotPassword = () => {
|
||||
if (ForgotPasswordView == null) {
|
||||
ForgotPasswordView = require('./ForgotPasswordView').default;
|
||||
Navigation.registerComponent('ForgotPasswordView', () => ForgotPasswordView, store, Provider);
|
||||
Navigation.registerComponentWithRedux('ForgotPasswordView', () => ForgotPasswordView, Provider, store);
|
||||
}
|
||||
|
||||
const { navigator } = this.props;
|
||||
navigator.push({
|
||||
screen: 'ForgotPasswordView',
|
||||
title: I18n.t('Forgot_Password'),
|
||||
backButtonTitle: ''
|
||||
const { componentId } = this.props;
|
||||
Navigation.push(componentId, {
|
||||
component: {
|
||||
name: 'ForgotPasswordView',
|
||||
options: {
|
||||
topBar: {
|
||||
title: {
|
||||
text: I18n.t('Forgot_Password')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -132,7 +147,7 @@ export default class LoginView extends LoggedView {
|
|||
key='login-view'
|
||||
>
|
||||
<ScrollView {...scrollPersistTaps} contentContainerStyle={styles.containerScrollView}>
|
||||
<SafeAreaView style={styles.container} testID='login-view'>
|
||||
<SafeAreaView style={styles.container} testID='login-view' forceInset={{ bottom: 'never' }}>
|
||||
<Text style={[styles.loginText, styles.loginTitle]}>Login</Text>
|
||||
<TextInput
|
||||
label={I18n.t('Username')}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
FlatList, View, Text, SafeAreaView
|
||||
} from 'react-native';
|
||||
import { FlatList, View, Text } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import SafeAreaView from 'react-native-safe-area-view';
|
||||
|
||||
import { openMentionedMessages as openMentionedMessagesAction, closeMentionedMessages as closeMentionedMessagesAction } from '../../actions/mentionedMessages';
|
||||
import LoggedView from '../View';
|
||||
|
@ -26,6 +25,16 @@ import I18n from '../../i18n';
|
|||
}))
|
||||
/** @extends React.Component */
|
||||
export default class MentionedMessagesView extends LoggedView {
|
||||
static options() {
|
||||
return {
|
||||
topBar: {
|
||||
title: {
|
||||
text: I18n.t('Mentions')
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
rid: PropTypes.string,
|
||||
messages: PropTypes.array,
|
||||
|
@ -106,7 +115,7 @@ export default class MentionedMessagesView extends LoggedView {
|
|||
}
|
||||
|
||||
return (
|
||||
<SafeAreaView style={styles.list} testID='mentioned-messages-view'>
|
||||
<SafeAreaView style={styles.list} testID='mentioned-messages-view' forceInset={{ bottom: 'never' }}>
|
||||
<FlatList
|
||||
data={messages}
|
||||
renderItem={this.renderItem}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
View, StyleSheet, SafeAreaView, FlatList, Text, Platform, Image
|
||||
View, StyleSheet, FlatList, Text, Platform, Image, Dimensions
|
||||
} from 'react-native';
|
||||
import { connect, Provider } from 'react-redux';
|
||||
import { Navigation } from 'react-native-navigation';
|
||||
import SafeAreaView from 'react-native-safe-area-view';
|
||||
|
||||
import database from '../lib/realm';
|
||||
import RocketChat from '../lib/rocketchat';
|
||||
|
@ -52,15 +53,20 @@ let SelectedUsersView = null;
|
|||
}))
|
||||
/** @extends React.Component */
|
||||
export default class NewMessageView extends LoggedView {
|
||||
static navigatorButtons = {
|
||||
static options() {
|
||||
return {
|
||||
topBar: {
|
||||
leftButtons: [{
|
||||
id: 'cancel',
|
||||
title: I18n.t('Cancel')
|
||||
icon: Platform.OS === 'android' ? { uri: 'back', scale: Dimensions.get('window').scale } : undefined,
|
||||
text: Platform.OS === 'ios' ? I18n.t('Cancel') : undefined
|
||||
}]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
navigator: PropTypes.object,
|
||||
componentId: PropTypes.string,
|
||||
baseUrl: PropTypes.string,
|
||||
onPressItem: PropTypes.func.isRequired
|
||||
};
|
||||
|
@ -72,7 +78,7 @@ export default class NewMessageView extends LoggedView {
|
|||
search: []
|
||||
};
|
||||
this.data.addListener(this.updateState);
|
||||
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this));
|
||||
Navigation.events().bindComponent(this);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
|
@ -80,27 +86,29 @@ export default class NewMessageView extends LoggedView {
|
|||
this.data.removeAllListeners();
|
||||
}
|
||||
|
||||
async onNavigatorEvent(event) {
|
||||
const { navigator } = this.props;
|
||||
if (event.type === 'NavBarButtonPress') {
|
||||
if (event.id === 'cancel') {
|
||||
navigator.dismissModal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onSearchChangeText(text) {
|
||||
this.search(text);
|
||||
}
|
||||
|
||||
onPressItem = (item) => {
|
||||
const { navigator, onPressItem } = this.props;
|
||||
navigator.dismissModal();
|
||||
const { onPressItem } = this.props;
|
||||
this.dismiss();
|
||||
setTimeout(() => {
|
||||
onPressItem(item);
|
||||
}, 600);
|
||||
}
|
||||
|
||||
navigationButtonPressed = ({ buttonId }) => {
|
||||
if (buttonId === 'cancel') {
|
||||
this.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
dismiss = () => {
|
||||
const { componentId } = this.props;
|
||||
Navigation.dismissModal(componentId);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line react/sort-comp
|
||||
updateState = debounce(() => {
|
||||
this.forceUpdate();
|
||||
|
@ -116,16 +124,23 @@ export default class NewMessageView extends LoggedView {
|
|||
createChannel = () => {
|
||||
if (SelectedUsersView == null) {
|
||||
SelectedUsersView = require('./SelectedUsersView').default;
|
||||
Navigation.registerComponent('SelectedUsersView', () => SelectedUsersView, store, Provider);
|
||||
Navigation.registerComponentWithRedux('SelectedUsersView', () => SelectedUsersView, Provider, store);
|
||||
}
|
||||
|
||||
const { navigator } = this.props;
|
||||
navigator.push({
|
||||
screen: 'SelectedUsersView',
|
||||
title: I18n.t('Select_Users'),
|
||||
backButtonTitle: '',
|
||||
const { componentId } = this.props;
|
||||
Navigation.push(componentId, {
|
||||
component: {
|
||||
name: 'SelectedUsersView',
|
||||
passProps: {
|
||||
nextAction: 'CREATE_CHANNEL'
|
||||
},
|
||||
options: {
|
||||
topBar: {
|
||||
title: {
|
||||
text: I18n.t('Select_Users')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -186,7 +201,7 @@ export default class NewMessageView extends LoggedView {
|
|||
}
|
||||
|
||||
render = () => (
|
||||
<SafeAreaView style={styles.safeAreaView} testID='new-message-view'>
|
||||
<SafeAreaView style={styles.safeAreaView} testID='new-message-view' forceInset={{ bottom: 'never' }}>
|
||||
{this.renderList()}
|
||||
</SafeAreaView>
|
||||
);
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
Text, ScrollView, Keyboard, SafeAreaView, Image, Alert, StyleSheet, TouchableOpacity
|
||||
Text, ScrollView, Keyboard, Image, Alert, StyleSheet, TouchableOpacity
|
||||
} from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import Icon from 'react-native-vector-icons/Ionicons';
|
||||
import { Navigation } from 'react-native-navigation';
|
||||
import SafeAreaView from 'react-native-safe-area-view';
|
||||
|
||||
import { serverRequest } from '../actions/server';
|
||||
import sharedStyles from './Styles';
|
||||
|
@ -60,8 +62,17 @@ const defaultServer = 'https://open.rocket.chat';
|
|||
}))
|
||||
/** @extends React.Component */
|
||||
export default class NewServerView extends LoggedView {
|
||||
static options() {
|
||||
return {
|
||||
topBar: {
|
||||
visible: false,
|
||||
drawBehind: true
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
navigator: PropTypes.object,
|
||||
componentId: PropTypes.string,
|
||||
server: PropTypes.string,
|
||||
connecting: PropTypes.bool.isRequired,
|
||||
failure: PropTypes.bool.isRequired,
|
||||
|
@ -73,6 +84,7 @@ export default class NewServerView extends LoggedView {
|
|||
this.state = {
|
||||
text: ''
|
||||
};
|
||||
Navigation.events().bindComponent(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
@ -128,7 +140,7 @@ export default class NewServerView extends LoggedView {
|
|||
}
|
||||
|
||||
renderBack = () => {
|
||||
const { navigator } = this.props;
|
||||
const { componentId } = this.props;
|
||||
|
||||
let top = 15;
|
||||
if (DeviceInfo.getBrand() === 'Apple') {
|
||||
|
@ -138,7 +150,7 @@ export default class NewServerView extends LoggedView {
|
|||
return (
|
||||
<TouchableOpacity
|
||||
style={[styles.backButton, { top }]}
|
||||
onPress={() => navigator.pop()}
|
||||
onPress={() => Navigation.pop(componentId)}
|
||||
>
|
||||
<Icon
|
||||
name='ios-arrow-back'
|
||||
|
@ -159,7 +171,7 @@ export default class NewServerView extends LoggedView {
|
|||
key='login-view'
|
||||
>
|
||||
<ScrollView {...scrollPersistTaps} contentContainerStyle={sharedStyles.containerScrollView}>
|
||||
<SafeAreaView style={sharedStyles.container} testID='new-server-view'>
|
||||
<SafeAreaView style={sharedStyles.container} testID='new-server-view' forceInset={{ bottom: 'never' }}>
|
||||
<Image style={styles.image} source={{ uri: 'new_server' }} />
|
||||
<Text style={styles.title}>{I18n.t('Sign_in_your_server')}</Text>
|
||||
<TextInput
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { WebView, Platform } from 'react-native';
|
||||
import { WebView, Platform, Dimensions } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import { Navigation } from 'react-native-navigation';
|
||||
|
||||
import RocketChat from '../lib/rocketchat';
|
||||
import I18n from '../i18n';
|
||||
|
@ -13,15 +14,20 @@ const userAgent = Platform.OS === 'ios' ? 'UserAgent' : userAgentAndroid;
|
|||
server: state.server.server
|
||||
}))
|
||||
export default class OAuthView extends React.PureComponent {
|
||||
static navigatorButtons = {
|
||||
static options() {
|
||||
return {
|
||||
topBar: {
|
||||
leftButtons: [{
|
||||
id: 'cancel',
|
||||
title: I18n.t('Cancel')
|
||||
icon: Platform.OS === 'android' ? { uri: 'back', scale: Dimensions.get('window').scale } : undefined,
|
||||
text: Platform.OS === 'ios' ? I18n.t('Cancel') : undefined
|
||||
}]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
navigator: PropTypes.object,
|
||||
componentId: PropTypes.string,
|
||||
oAuthUrl: PropTypes.string,
|
||||
server: PropTypes.string
|
||||
}
|
||||
|
@ -29,16 +35,18 @@ export default class OAuthView extends React.PureComponent {
|
|||
constructor(props) {
|
||||
super(props);
|
||||
this.redirectRegex = new RegExp(`(?=.*(${ props.server }))(?=.*(credentialToken))(?=.*(credentialSecret))`, 'g');
|
||||
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this));
|
||||
Navigation.events().bindComponent(this);
|
||||
}
|
||||
|
||||
onNavigatorEvent(event) {
|
||||
const { navigator } = this.props;
|
||||
if (event.type === 'NavBarButtonPress') {
|
||||
if (event.id === 'close') {
|
||||
navigator.dismissModal();
|
||||
navigationButtonPressed = ({ buttonId }) => {
|
||||
if (buttonId === 'cancel') {
|
||||
this.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
dismiss = () => {
|
||||
const { componentId } = this.props;
|
||||
Navigation.dismissModal(componentId);
|
||||
}
|
||||
|
||||
login = async(params) => {
|
||||
|
@ -50,7 +58,7 @@ export default class OAuthView extends React.PureComponent {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { oAuthUrl, navigator } = this.props;
|
||||
const { oAuthUrl } = this.props;
|
||||
return (
|
||||
<WebView
|
||||
source={{ uri: oAuthUrl }}
|
||||
|
@ -61,7 +69,7 @@ export default class OAuthView extends React.PureComponent {
|
|||
const parts = url.split('#');
|
||||
const credentials = JSON.parse(parts[1]);
|
||||
this.login({ oauth: { ...credentials } });
|
||||
navigator.dismissModal();
|
||||
this.dismiss();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import React from 'react';
|
||||
import {
|
||||
View, Text, Image, SafeAreaView, TouchableOpacity
|
||||
View, Text, Image, TouchableOpacity
|
||||
} from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
import Icon from 'react-native-vector-icons/MaterialIcons';
|
||||
import { connect, Provider } from 'react-redux';
|
||||
import { Navigation } from 'react-native-navigation';
|
||||
import SafeAreaView from 'react-native-safe-area-view';
|
||||
|
||||
import { selectServerRequest, serverInitAdd, serverFinishAdd } from '../../actions/server';
|
||||
import I18n from '../../i18n';
|
||||
|
@ -15,6 +16,7 @@ import styles from './styles';
|
|||
import LoggedView from '../View';
|
||||
import DeviceInfo from '../../utils/deviceInfo';
|
||||
import store from '../../lib/createStore';
|
||||
import EventEmitter from '../../utils/events';
|
||||
|
||||
let NewServerView = null;
|
||||
|
||||
|
@ -28,8 +30,17 @@ let NewServerView = null;
|
|||
}))
|
||||
/** @extends React.Component */
|
||||
export default class OnboardingView extends LoggedView {
|
||||
static options() {
|
||||
return {
|
||||
topBar: {
|
||||
visible: false,
|
||||
drawBehind: true
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
navigator: PropTypes.object,
|
||||
componentId: PropTypes.string,
|
||||
previousServer: PropTypes.string,
|
||||
adding: PropTypes.bool,
|
||||
selectServer: PropTypes.func.isRequired,
|
||||
|
@ -39,7 +50,7 @@ export default class OnboardingView extends LoggedView {
|
|||
}
|
||||
|
||||
constructor(props) {
|
||||
super('CreateChannelView', props);
|
||||
super('OnboardingView', props);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
@ -47,6 +58,7 @@ export default class OnboardingView extends LoggedView {
|
|||
if (previousServer) {
|
||||
initAdd();
|
||||
}
|
||||
EventEmitter.addEventListener('NewServer', this.handleNewServerEvent);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
|
@ -59,46 +71,48 @@ export default class OnboardingView extends LoggedView {
|
|||
}
|
||||
finishAdd();
|
||||
}
|
||||
EventEmitter.removeListener('NewServer', this.handleNewServerEvent);
|
||||
}
|
||||
|
||||
close = () => {
|
||||
const { navigator } = this.props;
|
||||
navigator.dismissModal();
|
||||
const { componentId } = this.props;
|
||||
Navigation.dismissModal(componentId);
|
||||
}
|
||||
|
||||
newServer = (server) => {
|
||||
if (NewServerView == null) {
|
||||
NewServerView = require('../NewServerView').default;
|
||||
Navigation.registerComponentWithRedux('NewServerView', () => NewServerView, Provider, store);
|
||||
}
|
||||
|
||||
const { componentId } = this.props;
|
||||
Navigation.push(componentId, {
|
||||
component: {
|
||||
id: 'NewServerView',
|
||||
name: 'NewServerView',
|
||||
passProps: {
|
||||
server
|
||||
},
|
||||
options: {
|
||||
topBar: {
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
handleNewServerEvent = (event) => {
|
||||
const { server } = event;
|
||||
this.newServer(server);
|
||||
}
|
||||
|
||||
connectServer = () => {
|
||||
if (NewServerView == null) {
|
||||
NewServerView = require('../NewServerView').default;
|
||||
Navigation.registerComponent('NewServerView', () => NewServerView, store, Provider);
|
||||
}
|
||||
|
||||
const { navigator } = this.props;
|
||||
navigator.push({
|
||||
screen: 'NewServerView',
|
||||
backButtonTitle: '',
|
||||
navigatorStyle: {
|
||||
navBarHidden: true
|
||||
}
|
||||
});
|
||||
this.newServer();
|
||||
}
|
||||
|
||||
joinCommunity = () => {
|
||||
if (NewServerView == null) {
|
||||
NewServerView = require('../NewServerView').default;
|
||||
Navigation.registerComponent('NewServerView', () => NewServerView, store, Provider);
|
||||
}
|
||||
|
||||
const { navigator } = this.props;
|
||||
navigator.push({
|
||||
screen: 'NewServerView',
|
||||
backButtonTitle: '',
|
||||
passProps: {
|
||||
server: 'https://open.rocket.chat'
|
||||
},
|
||||
navigatorStyle: {
|
||||
navBarHidden: true
|
||||
}
|
||||
});
|
||||
this.newServer('https://open.rocket.chat');
|
||||
}
|
||||
|
||||
createWorkspace = () => {
|
||||
|
@ -132,7 +146,7 @@ export default class OnboardingView extends LoggedView {
|
|||
|
||||
render() {
|
||||
return (
|
||||
<SafeAreaView style={styles.container} testID='onboarding-view'>
|
||||
<SafeAreaView style={styles.container} testID='onboarding-view' forceInset={{ bottom: 'never' }}>
|
||||
<Image style={styles.onboarding} source={{ uri: 'onboarding' }} />
|
||||
<Text style={styles.title}>{I18n.t('Welcome_to_RocketChat')}</Text>
|
||||
<Text style={styles.subtitle}>{I18n.t('Open_Source_Communication')}</Text>
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
FlatList, View, Text, SafeAreaView
|
||||
} from 'react-native';
|
||||
import { FlatList, View, Text } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import ActionSheet from 'react-native-actionsheet';
|
||||
import SafeAreaView from 'react-native-safe-area-view';
|
||||
|
||||
import { openPinnedMessages as openPinnedMessagesAction, closePinnedMessages as closePinnedMessagesAction } from '../../actions/pinnedMessages';
|
||||
import { togglePinRequest as togglePinRequestAction } from '../../actions/messages';
|
||||
|
@ -33,6 +32,16 @@ const options = [I18n.t('Unpin'), I18n.t('Cancel')];
|
|||
}))
|
||||
/** @extends React.Component */
|
||||
export default class PinnedMessagesView extends LoggedView {
|
||||
static options() {
|
||||
return {
|
||||
topBar: {
|
||||
title: {
|
||||
text: I18n.t('Pinned')
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
rid: PropTypes.string,
|
||||
messages: PropTypes.array,
|
||||
|
@ -136,7 +145,7 @@ export default class PinnedMessagesView extends LoggedView {
|
|||
}
|
||||
|
||||
return (
|
||||
<SafeAreaView style={styles.list} testID='pinned-messages-view'>
|
||||
<SafeAreaView style={styles.list} testID='pinned-messages-view' forceInset={{ bottom: 'never' }}>
|
||||
<FlatList
|
||||
data={messages}
|
||||
renderItem={this.renderItem}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { WebView, SafeAreaView } from 'react-native';
|
||||
import { WebView } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import SafeAreaView from 'react-native-safe-area-view';
|
||||
|
||||
import styles from './Styles';
|
||||
import LoggedView from './View';
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
View, ScrollView, SafeAreaView, Keyboard, Dimensions
|
||||
View, ScrollView, Keyboard, Dimensions
|
||||
} from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import Dialog from 'react-native-dialog';
|
||||
|
@ -9,6 +9,8 @@ import SHA256 from 'js-sha256';
|
|||
import Icon from 'react-native-vector-icons/MaterialIcons';
|
||||
import ImagePicker from 'react-native-image-crop-picker';
|
||||
import RNPickerSelect from 'react-native-picker-select';
|
||||
import { Navigation } from 'react-native-navigation';
|
||||
import SafeAreaView from 'react-native-safe-area-view';
|
||||
|
||||
import LoggedView from '../View';
|
||||
import KeyboardView from '../../presentation/KeyboardView';
|
||||
|
@ -24,6 +26,7 @@ import I18n from '../../i18n';
|
|||
import Button from '../../containers/Button';
|
||||
import Avatar from '../../containers/Avatar';
|
||||
import Touch from '../../utils/touch';
|
||||
import Drawer from '../../Drawer';
|
||||
|
||||
@connect(state => ({
|
||||
user: {
|
||||
|
@ -37,9 +40,29 @@ import Touch from '../../utils/touch';
|
|||
}))
|
||||
/** @extends React.Component */
|
||||
export default class ProfileView extends LoggedView {
|
||||
static options() {
|
||||
return {
|
||||
topBar: {
|
||||
leftButtons: [{
|
||||
id: 'settings',
|
||||
icon: { uri: 'settings', scale: Dimensions.get('window').scale },
|
||||
testID: 'rooms-list-view-sidebar'
|
||||
}],
|
||||
title: {
|
||||
text: I18n.t('Profile')
|
||||
}
|
||||
},
|
||||
sideMenu: {
|
||||
left: {
|
||||
enabled: true
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
baseUrl: PropTypes.string,
|
||||
navigator: PropTypes.object,
|
||||
componentId: PropTypes.string,
|
||||
user: PropTypes.object,
|
||||
Accounts_CustomFields: PropTypes.string
|
||||
}
|
||||
|
@ -59,29 +82,12 @@ export default class ProfileView extends LoggedView {
|
|||
avatarSuggestions: {},
|
||||
customFields: {}
|
||||
};
|
||||
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this));
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
const { navigator } = this.props;
|
||||
navigator.setButtons({
|
||||
leftButtons: [{
|
||||
id: 'settings',
|
||||
icon: { uri: 'settings', scale: Dimensions.get('window').scale }
|
||||
}]
|
||||
});
|
||||
Navigation.events().bindComponent(this);
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
const { navigator } = this.props;
|
||||
|
||||
this.init();
|
||||
|
||||
navigator.setDrawerEnabled({
|
||||
side: 'left',
|
||||
enabled: true
|
||||
});
|
||||
|
||||
try {
|
||||
const result = await RocketChat.getAvatarSuggestion();
|
||||
this.setState({ avatarSuggestions: result });
|
||||
|
@ -97,15 +103,9 @@ export default class ProfileView extends LoggedView {
|
|||
}
|
||||
}
|
||||
|
||||
onNavigatorEvent(event) {
|
||||
const { navigator } = this.props;
|
||||
|
||||
if (event.type === 'NavBarButtonPress') {
|
||||
if (event.id === 'settings') {
|
||||
navigator.toggleDrawer({
|
||||
side: 'left'
|
||||
});
|
||||
}
|
||||
navigationButtonPressed = ({ buttonId }) => {
|
||||
if (buttonId === 'settings') {
|
||||
Drawer.toggle();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -396,7 +396,7 @@ export default class ProfileView extends LoggedView {
|
|||
testID='profile-view-list'
|
||||
{...scrollPersistTaps}
|
||||
>
|
||||
<SafeAreaView style={sharedStyles.container} testID='profile-view'>
|
||||
<SafeAreaView style={sharedStyles.container} testID='profile-view' forceInset={{ bottom: 'never' }}>
|
||||
<View style={styles.avatarContainer} testID='profile-view-avatar'>
|
||||
<Avatar
|
||||
text={username}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
Keyboard, Text, View, ScrollView, SafeAreaView
|
||||
Keyboard, Text, View, ScrollView
|
||||
} from 'react-native';
|
||||
import { connect, Provider } from 'react-redux';
|
||||
import { Navigation } from 'react-native-navigation';
|
||||
import SafeAreaView from 'react-native-safe-area-view';
|
||||
|
||||
import { registerSubmit as registerSubmitAction, setUsernameSubmit as setUsernameSubmitAction } from '../actions/login';
|
||||
import TextInput from '../containers/TextInput';
|
||||
|
@ -35,7 +36,7 @@ let PrivacyPolicyView = null;
|
|||
/** @extends React.Component */
|
||||
export default class RegisterView extends LoggedView {
|
||||
static propTypes = {
|
||||
navigator: PropTypes.object,
|
||||
componentId: PropTypes.string,
|
||||
server: PropTypes.string,
|
||||
registerSubmit: PropTypes.func.isRequired,
|
||||
setUsernameSubmit: PropTypes.func,
|
||||
|
@ -104,28 +105,42 @@ export default class RegisterView extends LoggedView {
|
|||
termsService = () => {
|
||||
if (TermsServiceView == null) {
|
||||
TermsServiceView = require('./TermsServiceView').default;
|
||||
Navigation.registerComponent('TermsServiceView', () => TermsServiceView, store, Provider);
|
||||
Navigation.registerComponentWithRedux('TermsServiceView', () => TermsServiceView, Provider, store);
|
||||
}
|
||||
|
||||
const { navigator } = this.props;
|
||||
navigator.push({
|
||||
screen: 'TermsServiceView',
|
||||
title: I18n.t('Terms_of_Service'),
|
||||
backButtonTitle: ''
|
||||
const { componentId } = this.props;
|
||||
Navigation.push(componentId, {
|
||||
component: {
|
||||
name: 'TermsServiceView',
|
||||
options: {
|
||||
topBar: {
|
||||
title: {
|
||||
text: I18n.t('Terms_of_Service')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
privacyPolicy = () => {
|
||||
if (PrivacyPolicyView == null) {
|
||||
PrivacyPolicyView = require('./PrivacyPolicyView').default;
|
||||
Navigation.registerComponent('PrivacyPolicyView', () => PrivacyPolicyView, store, Provider);
|
||||
Navigation.registerComponentWithRedux('PrivacyPolicyView', () => PrivacyPolicyView, Provider, store);
|
||||
}
|
||||
|
||||
const { navigator } = this.props;
|
||||
navigator.push({
|
||||
screen: 'PrivacyPolicyView',
|
||||
title: I18n.t('Privacy_Policy'),
|
||||
backButtonTitle: ''
|
||||
const { componentId } = this.props;
|
||||
Navigation.push(componentId, {
|
||||
component: {
|
||||
name: 'PrivacyPolicyView',
|
||||
options: {
|
||||
topBar: {
|
||||
title: {
|
||||
text: I18n.t('Privacy_Policy')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -244,7 +259,7 @@ export default class RegisterView extends LoggedView {
|
|||
return (
|
||||
<KeyboardView contentContainerStyle={styles.container}>
|
||||
<ScrollView {...scrollPersistTaps} contentContainerStyle={styles.containerScrollView}>
|
||||
<SafeAreaView style={styles.container} testID='register-view'>
|
||||
<SafeAreaView style={styles.container} testID='register-view' forceInset={{ bottom: 'never' }}>
|
||||
<Text style={[styles.loginText, styles.loginTitle]}>{I18n.t('Sign_Up')}</Text>
|
||||
{this._renderRegister()}
|
||||
{this._renderUsername()}
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
View, SectionList, Text, Alert, SafeAreaView
|
||||
View, SectionList, Text, Alert
|
||||
} from 'react-native';
|
||||
import Icon from 'react-native-vector-icons/Ionicons';
|
||||
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
|
||||
import { connect, Provider } from 'react-redux';
|
||||
import { Navigation } from 'react-native-navigation';
|
||||
import { gestureHandlerRootHOC } from 'react-native-gesture-handler';
|
||||
import SafeAreaView from 'react-native-safe-area-view';
|
||||
|
||||
import { leaveRoom as leaveRoomAction } from '../../actions/room';
|
||||
import LoggedView from '../View';
|
||||
|
@ -37,10 +38,20 @@ const modules = {};
|
|||
}))
|
||||
/** @extends React.Component */
|
||||
export default class RoomActionsView extends LoggedView {
|
||||
static options() {
|
||||
return {
|
||||
topBar: {
|
||||
title: {
|
||||
text: I18n.t('Actions')
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
baseUrl: PropTypes.string,
|
||||
rid: PropTypes.string,
|
||||
navigator: PropTypes.object,
|
||||
componentId: PropTypes.string,
|
||||
userId: PropTypes.string,
|
||||
username: PropTypes.string,
|
||||
leaveRoom: PropTypes.func
|
||||
|
@ -69,18 +80,22 @@ export default class RoomActionsView extends LoggedView {
|
|||
}
|
||||
|
||||
onPressTouchable = (item) => {
|
||||
const { navigator } = this.props;
|
||||
|
||||
if (item.route) {
|
||||
if (modules[item.route] == null) {
|
||||
modules[item.route] = item.require();
|
||||
Navigation.registerComponent(item.route, () => gestureHandlerRootHOC(modules[item.route]), store, Provider);
|
||||
Navigation.registerComponentWithRedux(item.route, () => gestureHandlerRootHOC(modules[item.route]), Provider, store);
|
||||
}
|
||||
navigator.push({
|
||||
screen: item.route,
|
||||
title: item.name,
|
||||
passProps: item.params,
|
||||
backButtonTitle: ''
|
||||
|
||||
const { componentId } = this.props;
|
||||
Navigation.push(componentId, {
|
||||
component: {
|
||||
name: item.route,
|
||||
passProps: item.params
|
||||
}
|
||||
// screen: item.route,
|
||||
// title: item.name,
|
||||
// passProps: item.params,
|
||||
// backButtonTitle: ''
|
||||
});
|
||||
}
|
||||
if (item.event) {
|
||||
|
@ -325,7 +340,7 @@ export default class RoomActionsView extends LoggedView {
|
|||
this.setState({ room: this.rooms[0] || {} });
|
||||
}
|
||||
|
||||
toggleBlockUser = async() => {
|
||||
toggleBlockUser = () => {
|
||||
const { room } = this.state;
|
||||
const { rid, blocker } = room;
|
||||
const { member } = this.state;
|
||||
|
@ -440,7 +455,7 @@ export default class RoomActionsView extends LoggedView {
|
|||
|
||||
render() {
|
||||
return (
|
||||
<SafeAreaView style={styles.container} testID='room-actions-view'>
|
||||
<SafeAreaView style={styles.container} testID='room-actions-view' forceInset={{ bottom: 'never' }}>
|
||||
<SectionList
|
||||
style={styles.container}
|
||||
stickySectionHeadersEnabled={false}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
FlatList, View, Text, SafeAreaView
|
||||
} from 'react-native';
|
||||
import { FlatList, View, Text } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import SafeAreaView from 'react-native-safe-area-view';
|
||||
|
||||
import { openRoomFiles as openRoomFilesAction, closeRoomFiles as closeRoomFilesAction } from '../../actions/roomFiles';
|
||||
import LoggedView from '../View';
|
||||
|
@ -26,6 +25,16 @@ import I18n from '../../i18n';
|
|||
}))
|
||||
/** @extends React.Component */
|
||||
export default class RoomFilesView extends LoggedView {
|
||||
static options() {
|
||||
return {
|
||||
topBar: {
|
||||
title: {
|
||||
text: I18n.t('Files')
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
rid: PropTypes.string,
|
||||
messages: PropTypes.array,
|
||||
|
@ -106,7 +115,7 @@ export default class RoomFilesView extends LoggedView {
|
|||
|
||||
const { loading, loadingMore } = this.state;
|
||||
return (
|
||||
<SafeAreaView style={styles.list} testID='room-files-view'>
|
||||
<SafeAreaView style={styles.list} testID='room-files-view' forceInset={{ bottom: 'never' }}>
|
||||
<FlatList
|
||||
data={messages}
|
||||
renderItem={this.renderItem}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
Text, View, ScrollView, TouchableOpacity, SafeAreaView, Keyboard, Alert
|
||||
Text, View, ScrollView, TouchableOpacity, Keyboard, Alert
|
||||
} from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import SafeAreaView from 'react-native-safe-area-view';
|
||||
|
||||
import { eraseRoom as eraseRoomAction } from '../../actions/room';
|
||||
import LoggedView from '../View';
|
||||
|
@ -41,6 +42,16 @@ const PERMISSIONS_ARRAY = [
|
|||
}))
|
||||
/** @extends React.Component */
|
||||
export default class RoomInfoEditView extends LoggedView {
|
||||
static options() {
|
||||
return {
|
||||
topBar: {
|
||||
title: {
|
||||
text: I18n.t('Room_Info_Edit')
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
rid: PropTypes.string,
|
||||
eraseRoom: PropTypes.func
|
||||
|
@ -277,7 +288,7 @@ export default class RoomInfoEditView extends LoggedView {
|
|||
testID='room-info-edit-view-list'
|
||||
{...scrollPersistTaps}
|
||||
>
|
||||
<SafeAreaView style={sharedStyles.container} testID='room-info-edit-view'>
|
||||
<SafeAreaView style={sharedStyles.container} testID='room-info-edit-view' forceInset={{ bottom: 'never' }}>
|
||||
<RCTextInput
|
||||
inputRef={(e) => { this.name = e; }}
|
||||
label={I18n.t('Name')}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
View, Text, ScrollView, SafeAreaView
|
||||
} from 'react-native';
|
||||
import { View, Text, ScrollView } from 'react-native';
|
||||
import { connect, Provider } from 'react-redux';
|
||||
import moment from 'moment';
|
||||
import { Navigation } from 'react-native-navigation';
|
||||
import SafeAreaView from 'react-native-safe-area-view';
|
||||
|
||||
import LoggedView from '../View';
|
||||
import Status from '../../containers/status';
|
||||
|
@ -45,8 +44,18 @@ let RoomInfoEditView = null;
|
|||
}))
|
||||
/** @extends React.Component */
|
||||
export default class RoomInfoView extends LoggedView {
|
||||
static options() {
|
||||
return {
|
||||
topBar: {
|
||||
title: {
|
||||
text: I18n.t('Room_Info')
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
navigator: PropTypes.object,
|
||||
componentId: PropTypes.string,
|
||||
rid: PropTypes.string,
|
||||
userId: PropTypes.string,
|
||||
baseUrl: PropTypes.string,
|
||||
|
@ -67,12 +76,27 @@ export default class RoomInfoView extends LoggedView {
|
|||
roomUser: {},
|
||||
roles: []
|
||||
};
|
||||
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this));
|
||||
Navigation.events().bindComponent(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.updateRoom();
|
||||
this.rooms.addListener(this.updateRoom);
|
||||
|
||||
const [room] = this.rooms;
|
||||
const { componentId } = this.props;
|
||||
const permissions = RocketChat.hasPermission([PERMISSION_EDIT_ROOM], room.rid);
|
||||
if (permissions[PERMISSION_EDIT_ROOM]) {
|
||||
Navigation.mergeOptions(componentId, {
|
||||
topBar: {
|
||||
rightButtons: [{
|
||||
id: 'edit',
|
||||
icon: iconsMap.create,
|
||||
testID: 'room-info-view-edit-button'
|
||||
}]
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
|
@ -80,24 +104,23 @@ export default class RoomInfoView extends LoggedView {
|
|||
this.sub.unsubscribe();
|
||||
}
|
||||
|
||||
onNavigatorEvent(event) {
|
||||
const { rid, navigator } = this.props;
|
||||
if (event.type === 'NavBarButtonPress') {
|
||||
if (event.id === 'edit') {
|
||||
navigationButtonPressed = ({ buttonId }) => {
|
||||
const { rid, componentId } = this.props;
|
||||
if (buttonId === 'edit') {
|
||||
if (RoomInfoEditView == null) {
|
||||
RoomInfoEditView = require('../RoomInfoEditView').default;
|
||||
Navigation.registerComponent('RoomInfoEditView', () => RoomInfoEditView, store, Provider);
|
||||
Navigation.registerComponentWithRedux('RoomInfoEditView', () => RoomInfoEditView, Provider, store);
|
||||
}
|
||||
|
||||
navigator.push({
|
||||
screen: 'RoomInfoEditView',
|
||||
title: I18n.t('Room_Info_Edit'),
|
||||
backButtonTitle: '',
|
||||
Navigation.push(componentId, {
|
||||
component: {
|
||||
id: 'RoomInfoEditView',
|
||||
name: 'RoomInfoEditView',
|
||||
passProps: {
|
||||
rid
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,7 +139,7 @@ export default class RoomInfoView extends LoggedView {
|
|||
}
|
||||
|
||||
updateRoom = async() => {
|
||||
const { userId, activeUsers, navigator } = this.props;
|
||||
const { userId, activeUsers } = this.props;
|
||||
|
||||
const [room] = this.rooms;
|
||||
this.setState({ room });
|
||||
|
@ -146,22 +169,6 @@ export default class RoomInfoView extends LoggedView {
|
|||
} catch (e) {
|
||||
log('RoomInfoView.componentDidMount', e);
|
||||
}
|
||||
} else {
|
||||
const isVisible = await navigator.screenIsCurrentlyVisible();
|
||||
|
||||
if (!isVisible) {
|
||||
return;
|
||||
}
|
||||
const permissions = RocketChat.hasPermission([PERMISSION_EDIT_ROOM], room.rid);
|
||||
if (permissions[PERMISSION_EDIT_ROOM]) {
|
||||
navigator.setButtons({
|
||||
rightButtons: [{
|
||||
id: 'edit',
|
||||
icon: iconsMap.create,
|
||||
testID: 'room-info-view-edit-button'
|
||||
}]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -278,7 +285,7 @@ export default class RoomInfoView extends LoggedView {
|
|||
}
|
||||
return (
|
||||
<ScrollView style={styles.scroll}>
|
||||
<SafeAreaView style={styles.container} testID='room-info-view'>
|
||||
<SafeAreaView style={styles.container} testID='room-info-view' forceInset={{ bottom: 'never' }}>
|
||||
<View style={styles.avatarContainer}>
|
||||
{this.renderAvatar(room, roomUser)}
|
||||
<View style={styles.roomTitleContainer}>{ getRoomTitle(room) }</View>
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
FlatList, View, Vibration, SafeAreaView
|
||||
FlatList, View, Vibration, Platform
|
||||
} from 'react-native';
|
||||
import ActionSheet from 'react-native-actionsheet';
|
||||
import { connect } from 'react-redux';
|
||||
import { Navigation } from 'react-native-navigation';
|
||||
import SafeAreaView from 'react-native-safe-area-view';
|
||||
|
||||
import LoggedView from '../View';
|
||||
import styles from './styles';
|
||||
|
@ -22,16 +24,24 @@ import SearchBox from '../../containers/SearchBox';
|
|||
}))
|
||||
/** @extends React.Component */
|
||||
export default class RoomMembersView extends LoggedView {
|
||||
static navigatorButtons = {
|
||||
static options() {
|
||||
return {
|
||||
topBar: {
|
||||
title: {
|
||||
text: I18n.t('Members')
|
||||
},
|
||||
rightButtons: [{
|
||||
title: 'All',
|
||||
id: 'toggleOnline',
|
||||
testID: 'room-members-view-toggle-status'
|
||||
text: I18n.t('Online'),
|
||||
testID: 'room-members-view-toggle-status',
|
||||
color: Platform.OS === 'android' ? '#FFF' : undefined
|
||||
}]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
navigator: PropTypes.object,
|
||||
componentId: PropTypes.string,
|
||||
rid: PropTypes.string,
|
||||
members: PropTypes.array,
|
||||
baseUrl: PropTypes.string
|
||||
|
@ -39,7 +49,6 @@ export default class RoomMembersView extends LoggedView {
|
|||
|
||||
constructor(props) {
|
||||
super('MentionedMessagesView', props);
|
||||
const { navigator } = this.props;
|
||||
|
||||
this.CANCEL_INDEX = 0;
|
||||
this.MUTE_INDEX = 1;
|
||||
|
@ -56,7 +65,7 @@ export default class RoomMembersView extends LoggedView {
|
|||
userLongPressed: {},
|
||||
room: {}
|
||||
};
|
||||
navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this));
|
||||
Navigation.events().bindComponent(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
@ -67,30 +76,30 @@ export default class RoomMembersView extends LoggedView {
|
|||
this.rooms.removeAllListeners();
|
||||
}
|
||||
|
||||
async onNavigatorEvent(event) {
|
||||
navigationButtonPressed = async({ buttonId }) => {
|
||||
const { rid, allUsers } = this.state;
|
||||
const { navigator } = this.props;
|
||||
const { componentId } = this.props;
|
||||
|
||||
if (event.type === 'NavBarButtonPress') {
|
||||
if (event.id === 'toggleOnline') {
|
||||
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'
|
||||
}]
|
||||
}
|
||||
});
|
||||
const allUsersFilter = !allUsers;
|
||||
const membersResult = await RocketChat.getRoomMembers(rid, allUsersFilter);
|
||||
const members = membersResult.records;
|
||||
this.setState({ allUsers: allUsersFilter, members });
|
||||
navigator.setButtons({
|
||||
rightButtons: [{
|
||||
title: allUsers ? I18n.t('Online') : I18n.t('All'),
|
||||
id: 'toggleOnline',
|
||||
testID: 'room-members-view-toggle-status'
|
||||
}]
|
||||
});
|
||||
} catch (e) {
|
||||
log('RoomMembers.onNavigationButtonPressed', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onSearchChangeText = (text) => {
|
||||
const { members } = this.state;
|
||||
|
@ -143,17 +152,24 @@ export default class RoomMembersView extends LoggedView {
|
|||
await this.setState({ room });
|
||||
}
|
||||
|
||||
goRoom = ({ rid, name }) => {
|
||||
const { navigator } = this.props;
|
||||
navigator.popToRoot();
|
||||
setTimeout(() => {
|
||||
navigator.push({
|
||||
screen: 'RoomView',
|
||||
title: name,
|
||||
backButtonTitle: '',
|
||||
passProps: { rid }
|
||||
goRoom = async({ rid, name }) => {
|
||||
const { componentId } = this.props;
|
||||
await Navigation.popToRoot(componentId);
|
||||
Navigation.push('RoomsListView', {
|
||||
component: {
|
||||
name: 'RoomView',
|
||||
passProps: {
|
||||
rid
|
||||
},
|
||||
options: {
|
||||
topBar: {
|
||||
title: {
|
||||
text: name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
handleMute = async() => {
|
||||
|
@ -200,7 +216,7 @@ export default class RoomMembersView extends LoggedView {
|
|||
render() {
|
||||
const { filtering, members, membersFiltered } = this.state;
|
||||
return (
|
||||
<SafeAreaView style={styles.list} testID='room-members-view'>
|
||||
<SafeAreaView style={styles.list} testID='room-members-view' forceInset={{ bottom: 'never' }}>
|
||||
<FlatList
|
||||
data={filtering ? membersFiltered : members}
|
||||
renderItem={this.renderItem}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
Text, View, LayoutAnimation, ActivityIndicator, SafeAreaView
|
||||
Text, View, LayoutAnimation, ActivityIndicator
|
||||
} from 'react-native';
|
||||
import { connect, Provider } from 'react-redux';
|
||||
import { RectButton } from 'react-native-gesture-handler';
|
||||
import { Navigation } from 'react-native-navigation';
|
||||
import SafeAreaView from 'react-native-safe-area-view';
|
||||
|
||||
import { openRoom as openRoomAction, closeRoom as closeRoomAction, setLastOpen as setLastOpenAction } from '../../actions/room';
|
||||
import { toggleReactionPicker as toggleReactionPickerAction, actionsShow as actionsShowAction } from '../../actions/messages';
|
||||
|
@ -47,8 +48,24 @@ let RoomActionsView = null;
|
|||
}))
|
||||
/** @extends React.Component */
|
||||
export default class RoomView extends LoggedView {
|
||||
static options() {
|
||||
return {
|
||||
topBar: {
|
||||
rightButtons: [{
|
||||
id: 'more',
|
||||
testID: 'room-view-header-actions',
|
||||
icon: iconsMap.more
|
||||
}, {
|
||||
id: 'star',
|
||||
testID: 'room-view-header-star',
|
||||
icon: iconsMap.starOutline
|
||||
}]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
navigator: PropTypes.object,
|
||||
componentId: PropTypes.string,
|
||||
openRoom: PropTypes.func.isRequired,
|
||||
setLastOpen: PropTypes.func.isRequired,
|
||||
user: PropTypes.shape({
|
||||
|
@ -76,35 +93,13 @@ export default class RoomView extends LoggedView {
|
|||
end: false
|
||||
};
|
||||
this.onReactionPress = this.onReactionPress.bind(this);
|
||||
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this));
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
const { navigator } = this.props;
|
||||
|
||||
navigator.setButtons({
|
||||
rightButtons: [{
|
||||
id: 'more',
|
||||
testID: 'room-view-header-actions',
|
||||
icon: iconsMap.more
|
||||
}, {
|
||||
id: 'star',
|
||||
testID: 'room-view-header-star',
|
||||
icon: iconsMap.starOutline
|
||||
}]
|
||||
});
|
||||
Navigation.events().bindComponent(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { navigator } = this.props;
|
||||
|
||||
this.updateRoom();
|
||||
this.rooms.addListener(this.updateRoom);
|
||||
navigator.setDrawerEnabled({
|
||||
side: 'left',
|
||||
enabled: false
|
||||
});
|
||||
this.setState({ loaded: true });
|
||||
this.internalSetState({ loaded: true });
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
|
@ -115,6 +110,8 @@ export default class RoomView extends LoggedView {
|
|||
|
||||
if (room.ro !== nextState.room.ro) {
|
||||
return true;
|
||||
} else if (room.f !== nextState.room.f) {
|
||||
return true;
|
||||
} else if (loaded !== nextState.loaded) {
|
||||
return true;
|
||||
} else if (joined !== nextState.joined) {
|
||||
|
@ -129,10 +126,11 @@ export default class RoomView extends LoggedView {
|
|||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
const { room } = this.state;
|
||||
const { navigator } = this.props;
|
||||
const { componentId } = this.props;
|
||||
|
||||
if (prevState.room.f !== room.f) {
|
||||
navigator.setButtons({
|
||||
Navigation.mergeOptions(componentId, {
|
||||
topBar: {
|
||||
rightButtons: [{
|
||||
id: 'more',
|
||||
testID: 'room-view-header-actions',
|
||||
|
@ -142,6 +140,7 @@ export default class RoomView extends LoggedView {
|
|||
testID: 'room-view-header-star',
|
||||
icon: room.f ? iconsMap.star : iconsMap.starOutline
|
||||
}]
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -153,39 +152,9 @@ export default class RoomView extends LoggedView {
|
|||
closeRoom();
|
||||
}
|
||||
|
||||
onNavigatorEvent(event) {
|
||||
const { room } = this.state;
|
||||
const { rid, f } = room;
|
||||
const { navigator } = this.props;
|
||||
|
||||
if (event.type === 'NavBarButtonPress') {
|
||||
if (event.id === 'more') {
|
||||
if (RoomActionsView == null) {
|
||||
RoomActionsView = require('../RoomActionsView').default;
|
||||
Navigation.registerComponent('RoomActionsView', () => RoomActionsView, store, Provider);
|
||||
}
|
||||
|
||||
navigator.push({
|
||||
screen: 'RoomActionsView',
|
||||
title: I18n.t('Actions'),
|
||||
backButtonTitle: '',
|
||||
passProps: {
|
||||
rid
|
||||
}
|
||||
});
|
||||
} else if (event.id === 'star') {
|
||||
try {
|
||||
RocketChat.toggleFavorite(rid, f);
|
||||
} catch (e) {
|
||||
log('toggleFavorite', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onEndReached = debounce((lastRowData) => {
|
||||
if (!lastRowData) {
|
||||
this.setState({ end: true });
|
||||
this.internalSetState({ end: true });
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -193,7 +162,7 @@ export default class RoomView extends LoggedView {
|
|||
const { room } = this.state;
|
||||
try {
|
||||
const result = await RocketChat.loadMessagesForRoom({ rid: this.rid, t: room.t, latest: lastRowData.ts });
|
||||
this.setState({ end: result < 20 });
|
||||
this.internalSetState({ end: result < 20 });
|
||||
} catch (e) {
|
||||
log('RoomView.onEndReached', e);
|
||||
}
|
||||
|
@ -218,16 +187,57 @@ export default class RoomView extends LoggedView {
|
|||
}
|
||||
};
|
||||
|
||||
updateRoom = async() => {
|
||||
const { navigator, openRoom, setLastOpen } = this.props;
|
||||
internalSetState = (...args) => {
|
||||
LayoutAnimation.easeInEaseOut();
|
||||
this.setState(...args);
|
||||
}
|
||||
|
||||
navigationButtonPressed = ({ buttonId }) => {
|
||||
const { room } = this.state;
|
||||
const { rid, f } = room;
|
||||
const { componentId } = this.props;
|
||||
|
||||
if (buttonId === 'more') {
|
||||
if (RoomActionsView == null) {
|
||||
RoomActionsView = require('../RoomActionsView').default;
|
||||
Navigation.registerComponentWithRedux('RoomActionsView', () => RoomActionsView, Provider, store);
|
||||
}
|
||||
|
||||
Navigation.push(componentId, {
|
||||
component: {
|
||||
id: 'RoomActionsView',
|
||||
name: 'RoomActionsView',
|
||||
passProps: {
|
||||
rid
|
||||
}
|
||||
}
|
||||
});
|
||||
} else if (buttonId === 'star') {
|
||||
try {
|
||||
RocketChat.toggleFavorite(rid, f);
|
||||
} catch (e) {
|
||||
log('toggleFavorite', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateRoom = () => {
|
||||
const { componentId, openRoom, setLastOpen } = this.props;
|
||||
|
||||
if (this.rooms.length > 0) {
|
||||
const { room: prevRoom } = this.state;
|
||||
const room = JSON.parse(JSON.stringify(this.rooms[0] || {}));
|
||||
this.setState({ room });
|
||||
LayoutAnimation.easeInEaseOut();
|
||||
this.internalSetState({ room });
|
||||
|
||||
if (!prevRoom.rid) {
|
||||
navigator.setTitle({ title: room.name });
|
||||
Navigation.mergeOptions(componentId, {
|
||||
topBar: {
|
||||
title: {
|
||||
text: room.name
|
||||
}
|
||||
}
|
||||
});
|
||||
openRoom({
|
||||
...room
|
||||
});
|
||||
|
@ -239,7 +249,7 @@ export default class RoomView extends LoggedView {
|
|||
}
|
||||
} else {
|
||||
openRoom({ rid: this.rid });
|
||||
this.setState({ joined: false });
|
||||
this.internalSetState({ joined: false });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -255,7 +265,7 @@ export default class RoomView extends LoggedView {
|
|||
const { rid } = this.props;
|
||||
try {
|
||||
await RocketChat.joinRoom(rid);
|
||||
this.setState({
|
||||
this.internalSetState({
|
||||
joined: true
|
||||
});
|
||||
} catch (e) {
|
||||
|
@ -380,7 +390,7 @@ export default class RoomView extends LoggedView {
|
|||
const { user, showActions, showErrorActions } = this.props;
|
||||
|
||||
return (
|
||||
<SafeAreaView style={styles.container} testID='room-view'>
|
||||
<SafeAreaView style={styles.container} testID='room-view' forceInset={{ bottom: 'never' }}>
|
||||
{this.renderList()}
|
||||
{room._id && showActions
|
||||
? <MessageActions room={room} user={user} />
|
||||
|
|
|
@ -3,6 +3,7 @@ import {
|
|||
Text, View, TouchableOpacity, Image, StyleSheet
|
||||
} from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
import { TextInput } from 'react-native-gesture-handler';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
@ -28,7 +29,23 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
const Header = ({ onPress, serverName, showServerDropdown }) => (
|
||||
const Header = ({
|
||||
onPress, serverName, showServerDropdown, setSearchInputRef, showSearchHeader, onSearchChangeText
|
||||
}) => {
|
||||
if (showSearchHeader) {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<TextInput
|
||||
ref={setSearchInputRef}
|
||||
style={styles.server}
|
||||
placeholder='Search'
|
||||
placeholderTextColor='rgba(255, 255, 255, 0.5)'
|
||||
onChangeText={onSearchChangeText}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<TouchableOpacity onPress={onPress} testID='rooms-list-header-server-dropdown-button'>
|
||||
<View style={styles.button}>
|
||||
|
@ -38,11 +55,15 @@ const Header = ({ onPress, serverName, showServerDropdown }) => (
|
|||
</TouchableOpacity>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
Header.propTypes = {
|
||||
showServerDropdown: PropTypes.bool.isRequired,
|
||||
showSearchHeader: PropTypes.bool.isRequired,
|
||||
onPress: PropTypes.func.isRequired,
|
||||
serverName: PropTypes.string,
|
||||
showServerDropdown: PropTypes.bool.isRequired
|
||||
onSearchChangeText: PropTypes.func.isRequired,
|
||||
setSearchInputRef: PropTypes.func.isRequired,
|
||||
serverName: PropTypes.string
|
||||
};
|
||||
|
||||
Header.defaultProps = {
|
||||
|
|
|
@ -2,26 +2,46 @@ import React, { Component } from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { toggleServerDropdown, closeServerDropdown, closeSortDropdown } from '../../../actions/rooms';
|
||||
import {
|
||||
toggleServerDropdown, closeServerDropdown, closeSortDropdown, setSearch as setSearchAction
|
||||
} from '../../../actions/rooms';
|
||||
import Header from './Header';
|
||||
|
||||
@connect(state => ({
|
||||
showServerDropdown: state.rooms.showServerDropdown,
|
||||
showSortDropdown: state.rooms.showSortDropdown,
|
||||
showSearchHeader: state.rooms.showSearchHeader,
|
||||
serverName: state.settings.Site_Name
|
||||
}), dispatch => ({
|
||||
close: () => dispatch(closeServerDropdown()),
|
||||
open: () => dispatch(toggleServerDropdown()),
|
||||
closeSort: () => dispatch(closeSortDropdown())
|
||||
closeSort: () => dispatch(closeSortDropdown()),
|
||||
setSearch: searchText => dispatch(setSearchAction(searchText))
|
||||
}))
|
||||
export default class RoomsListHeaderView extends Component {
|
||||
static propTypes = {
|
||||
showServerDropdown: PropTypes.bool,
|
||||
showSortDropdown: PropTypes.bool,
|
||||
showSearchHeader: PropTypes.bool,
|
||||
serverName: PropTypes.string,
|
||||
open: PropTypes.func,
|
||||
close: PropTypes.func,
|
||||
closeSort: PropTypes.func
|
||||
closeSort: PropTypes.func,
|
||||
setSearch: PropTypes.func
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const { showSearchHeader } = this.props;
|
||||
if (showSearchHeader && prevProps.showSearchHeader !== showSearchHeader) {
|
||||
setTimeout(() => {
|
||||
this.searchInputRef.focus();
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
|
||||
onSearchChangeText = (text) => {
|
||||
const { setSearch } = this.props;
|
||||
setSearch(text.trim());
|
||||
}
|
||||
|
||||
onPress = () => {
|
||||
|
@ -40,13 +60,21 @@ export default class RoomsListHeaderView extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
setSearchInputRef = (ref) => {
|
||||
this.searchInputRef = ref;
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
const { serverName, showServerDropdown } = this.props;
|
||||
const { serverName, showServerDropdown, showSearchHeader } = this.props;
|
||||
return (
|
||||
<Header
|
||||
onPress={this.onPress}
|
||||
serverName={serverName}
|
||||
showServerDropdown={showServerDropdown}
|
||||
showSearchHeader={showSearchHeader}
|
||||
setSearchInputRef={this.setSearchInputRef}
|
||||
onSearchChangeText={text => this.onSearchChangeText(text)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import {
|
|||
View, Text, Animated, Easing, TouchableWithoutFeedback, TouchableOpacity, FlatList, Image, AsyncStorage
|
||||
} from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect, Provider } from 'react-redux';
|
||||
import { connect } from 'react-redux';
|
||||
import { Navigation } from 'react-native-navigation';
|
||||
import * as SDK from '@rocket.chat/sdk';
|
||||
|
||||
|
@ -15,13 +15,11 @@ import database from '../../lib/realm';
|
|||
import Touch from '../../utils/touch';
|
||||
import RocketChat from '../../lib/rocketchat';
|
||||
import I18n from '../../i18n';
|
||||
import store from '../../lib/createStore';
|
||||
import EventEmitter from '../../utils/events';
|
||||
|
||||
const ROW_HEIGHT = 68;
|
||||
const ANIMATION_DURATION = 200;
|
||||
|
||||
let NewServerView = null;
|
||||
|
||||
@connect(state => ({
|
||||
closeServerDropdown: state.rooms.closeServerDropdown,
|
||||
server: state.server.server
|
||||
|
@ -32,7 +30,6 @@ let NewServerView = null;
|
|||
}))
|
||||
export default class ServerDropdown extends Component {
|
||||
static propTypes = {
|
||||
navigator: PropTypes.object,
|
||||
closeServerDropdown: PropTypes.bool,
|
||||
server: PropTypes.string,
|
||||
toggleServerDropdown: PropTypes.func,
|
||||
|
@ -88,26 +85,36 @@ export default class ServerDropdown extends Component {
|
|||
}
|
||||
|
||||
addServer = () => {
|
||||
const { navigator, server } = this.props;
|
||||
const { server } = this.props;
|
||||
|
||||
this.close();
|
||||
setTimeout(() => {
|
||||
navigator.showModal({
|
||||
screen: 'OnboardingView',
|
||||
Navigation.showModal({
|
||||
stack: {
|
||||
children: [{
|
||||
component: {
|
||||
name: 'OnboardingView',
|
||||
passProps: {
|
||||
previousServer: server
|
||||
},
|
||||
navigatorStyle: {
|
||||
navBarHidden: true,
|
||||
options: {
|
||||
topBar: {
|
||||
visible: false
|
||||
},
|
||||
layout: {
|
||||
orientation: 'portrait'
|
||||
}
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
});
|
||||
}, ANIMATION_DURATION);
|
||||
}
|
||||
|
||||
select = async(server) => {
|
||||
const {
|
||||
server: currentServer, selectServerRequest, appStart, navigator
|
||||
server: currentServer, selectServerRequest, appStart
|
||||
} = this.props;
|
||||
|
||||
this.close();
|
||||
|
@ -120,21 +127,8 @@ export default class ServerDropdown extends Component {
|
|||
} catch (error) {
|
||||
console.warn(error);
|
||||
}
|
||||
if (NewServerView == null) {
|
||||
NewServerView = require('../NewServerView').default;
|
||||
Navigation.registerComponent('NewServerView', () => NewServerView, store, Provider);
|
||||
}
|
||||
setTimeout(() => {
|
||||
navigator.push({
|
||||
screen: 'NewServerView',
|
||||
backButtonTitle: '',
|
||||
passProps: {
|
||||
server
|
||||
},
|
||||
navigatorStyle: {
|
||||
navBarHidden: true
|
||||
}
|
||||
});
|
||||
EventEmitter.emit('NewServer', { server });
|
||||
}, 1000);
|
||||
} else {
|
||||
selectServerRequest(server);
|
||||
|
|
|
@ -54,7 +54,7 @@ export default class Sort extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
setSortPreference = async(param) => {
|
||||
setSortPreference = (param) => {
|
||||
const { setSortPreference } = this.props;
|
||||
|
||||
try {
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
Platform, View, FlatList, BackHandler, ActivityIndicator, SafeAreaView, Text, Image, Dimensions, ScrollView, Keyboard
|
||||
Platform, View, FlatList, BackHandler, ActivityIndicator, Text, Image, Dimensions, ScrollView, Keyboard, LayoutAnimation
|
||||
} from 'react-native';
|
||||
import { connect, Provider } from 'react-redux';
|
||||
import { isEqual } from 'lodash';
|
||||
import { Navigation } from 'react-native-navigation';
|
||||
import SafeAreaView from 'react-native-safe-area-view';
|
||||
|
||||
import SearchBox from '../../containers/SearchBox';
|
||||
import ConnectionBadge from '../../containers/ConnectionBadge';
|
||||
|
@ -19,8 +20,9 @@ import I18n from '../../i18n';
|
|||
import SortDropdown from './SortDropdown';
|
||||
import ServerDropdown from './ServerDropdown';
|
||||
import Touch from '../../utils/touch';
|
||||
import { toggleSortDropdown as toggleSortDropdownAction } from '../../actions/rooms';
|
||||
import { toggleSortDropdown as toggleSortDropdownAction, openSearchHeader as openSearchHeaderAction, closeSearchHeader as closeSearchHeaderAction } from '../../actions/rooms';
|
||||
import store from '../../lib/createStore';
|
||||
import Drawer from '../../Drawer';
|
||||
|
||||
const ROW_HEIGHT = 70;
|
||||
const SCROLL_OFFSET = 56;
|
||||
|
@ -63,24 +65,33 @@ let NewMessageView = null;
|
|||
showUnread: state.sortPreferences.showUnread,
|
||||
useRealName: state.settings.UI_Use_Real_Name
|
||||
}), dispatch => ({
|
||||
toggleSortDropdown: () => dispatch(toggleSortDropdownAction())
|
||||
toggleSortDropdown: () => dispatch(toggleSortDropdownAction()),
|
||||
openSearchHeader: () => dispatch(openSearchHeaderAction()),
|
||||
closeSearchHeader: () => dispatch(closeSearchHeaderAction())
|
||||
}))
|
||||
/** @extends React.Component */
|
||||
export default class RoomsListView extends LoggedView {
|
||||
static navigatorButtons = {
|
||||
leftButtons, rightButtons
|
||||
static options() {
|
||||
return {
|
||||
topBar: {
|
||||
leftButtons,
|
||||
rightButtons,
|
||||
title: {
|
||||
component: {
|
||||
name: 'RoomsListHeaderView',
|
||||
alignment: isAndroid() ? 'left' : 'center'
|
||||
}
|
||||
|
||||
static navigatorStyle = {
|
||||
navBarCustomView: 'RoomsListHeaderView',
|
||||
navBarComponentAlignment: 'fill',
|
||||
navBarBackgroundColor: isAndroid() ? '#2F343D' : undefined,
|
||||
navBarTextColor: isAndroid() ? '#FFF' : undefined,
|
||||
navBarButtonColor: isAndroid() ? '#FFF' : undefined
|
||||
}
|
||||
},
|
||||
sideMenu: {
|
||||
left: {
|
||||
enabled: true
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
navigator: PropTypes.object,
|
||||
userId: PropTypes.string,
|
||||
baseUrl: PropTypes.string,
|
||||
server: PropTypes.string,
|
||||
|
@ -93,7 +104,9 @@ export default class RoomsListView extends LoggedView {
|
|||
showFavorites: PropTypes.bool,
|
||||
showUnread: PropTypes.bool,
|
||||
useRealName: PropTypes.bool,
|
||||
toggleSortDropdown: PropTypes.func
|
||||
toggleSortDropdown: PropTypes.func,
|
||||
openSearchHeader: PropTypes.func,
|
||||
closeSearchHeader: PropTypes.func
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
|
@ -111,11 +124,7 @@ export default class RoomsListView extends LoggedView {
|
|||
direct: [],
|
||||
livechat: []
|
||||
};
|
||||
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this));
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.initDefaultHeader();
|
||||
Navigation.events().bindComponent(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
@ -127,7 +136,7 @@ export default class RoomsListView extends LoggedView {
|
|||
|
||||
if (nextProps.server && loadingServer !== nextProps.loadingServer) {
|
||||
if (nextProps.loadingServer) {
|
||||
this.setState({ loading: true });
|
||||
this.internalSetState({ loading: true });
|
||||
} else {
|
||||
this.getSubscriptions();
|
||||
}
|
||||
|
@ -169,37 +178,44 @@ export default class RoomsListView extends LoggedView {
|
|||
}
|
||||
}
|
||||
|
||||
onNavigatorEvent(event) {
|
||||
const { navigator } = this.props;
|
||||
if (event.type === 'NavBarButtonPress') {
|
||||
if (event.id === 'newMessage') {
|
||||
navigationButtonPressed = ({ buttonId }) => {
|
||||
if (buttonId === 'newMessage') {
|
||||
if (NewMessageView == null) {
|
||||
NewMessageView = require('../NewMessageView').default;
|
||||
Navigation.registerComponent('NewMessageView', () => NewMessageView, store, Provider);
|
||||
Navigation.registerComponentWithRedux('NewMessageView', () => NewMessageView, Provider, store);
|
||||
}
|
||||
|
||||
navigator.showModal({
|
||||
screen: 'NewMessageView',
|
||||
title: I18n.t('New_Message'),
|
||||
Navigation.showModal({
|
||||
stack: {
|
||||
children: [{
|
||||
component: {
|
||||
name: 'NewMessageView',
|
||||
passProps: {
|
||||
onPressItem: this._onPressItem
|
||||
},
|
||||
options: {
|
||||
topBar: {
|
||||
title: {
|
||||
text: I18n.t('New_Message')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
});
|
||||
} else if (event.id === 'settings') {
|
||||
navigator.toggleDrawer({
|
||||
side: 'left'
|
||||
});
|
||||
} else if (event.id === 'search') {
|
||||
} else if (buttonId === 'settings') {
|
||||
Drawer.toggle();
|
||||
} else if (buttonId === 'search') {
|
||||
this.initSearchingAndroid();
|
||||
} else if (event.id === 'cancelSearch' || event.id === 'back') {
|
||||
} else if (buttonId === 'back') {
|
||||
this.cancelSearchingAndroid();
|
||||
}
|
||||
} else if (event.type === 'ScreenChangedEvent' && event.id === 'didAppear') {
|
||||
navigator.setDrawerEnabled({
|
||||
side: 'left',
|
||||
enabled: true
|
||||
});
|
||||
}
|
||||
|
||||
internalSetState = (...args) => {
|
||||
LayoutAnimation.easeInEaseOut();
|
||||
this.setState(...args);
|
||||
}
|
||||
|
||||
getSubscriptions = () => {
|
||||
|
@ -227,7 +243,7 @@ export default class RoomsListView extends LoggedView {
|
|||
this.unread = this.data.filtered('archived != true && open == true').filtered('(unread > 0 || alert == true)');
|
||||
unread = this.removeRealmInstance(this.unread);
|
||||
setTimeout(() => {
|
||||
this.unread.addListener(() => this.setState({ unread: this.removeRealmInstance(this.unread) }));
|
||||
this.unread.addListener(() => this.internalSetState({ unread: this.removeRealmInstance(this.unread) }));
|
||||
});
|
||||
} else {
|
||||
this.removeListener(unread);
|
||||
|
@ -237,7 +253,7 @@ export default class RoomsListView extends LoggedView {
|
|||
this.favorites = this.data.filtered('f == true');
|
||||
favorites = this.removeRealmInstance(this.favorites);
|
||||
setTimeout(() => {
|
||||
this.favorites.addListener(() => this.setState({ favorites: this.removeRealmInstance(this.favorites) }));
|
||||
this.favorites.addListener(() => this.internalSetState({ favorites: this.removeRealmInstance(this.favorites) }));
|
||||
});
|
||||
} else {
|
||||
this.removeListener(favorites);
|
||||
|
@ -261,10 +277,10 @@ export default class RoomsListView extends LoggedView {
|
|||
livechat = this.removeRealmInstance(this.livechat);
|
||||
|
||||
setTimeout(() => {
|
||||
this.channels.addListener(() => this.setState({ channels: this.removeRealmInstance(this.channels) }));
|
||||
this.privateGroup.addListener(() => this.setState({ privateGroup: this.removeRealmInstance(this.privateGroup) }));
|
||||
this.direct.addListener(() => this.setState({ direct: this.removeRealmInstance(this.direct) }));
|
||||
this.livechat.addListener(() => this.setState({ livechat: this.removeRealmInstance(this.livechat) }));
|
||||
this.channels.addListener(() => this.internalSetState({ channels: this.removeRealmInstance(this.channels) }));
|
||||
this.privateGroup.addListener(() => this.internalSetState({ privateGroup: this.removeRealmInstance(this.privateGroup) }));
|
||||
this.direct.addListener(() => this.internalSetState({ direct: this.removeRealmInstance(this.direct) }));
|
||||
this.livechat.addListener(() => this.internalSetState({ livechat: this.removeRealmInstance(this.livechat) }));
|
||||
});
|
||||
this.removeListener(this.chats);
|
||||
} else {
|
||||
|
@ -278,7 +294,7 @@ export default class RoomsListView extends LoggedView {
|
|||
|
||||
setTimeout(() => {
|
||||
this.chats.addListener(() => {
|
||||
this.setState({ chats: this.removeRealmInstance(this.chats) });
|
||||
this.internalSetState({ chats: this.removeRealmInstance(this.chats) });
|
||||
});
|
||||
});
|
||||
this.removeListener(this.channels);
|
||||
|
@ -288,12 +304,12 @@ export default class RoomsListView extends LoggedView {
|
|||
}
|
||||
|
||||
// setState
|
||||
this.setState({
|
||||
this.internalSetState({
|
||||
chats, unread, favorites, channels, privateGroup, direct, livechat
|
||||
});
|
||||
}
|
||||
this.timeout = setTimeout(() => {
|
||||
this.setState({ loading: false });
|
||||
this.internalSetState({ loading: false });
|
||||
}, 200);
|
||||
}
|
||||
|
||||
|
@ -308,46 +324,41 @@ export default class RoomsListView extends LoggedView {
|
|||
}
|
||||
}
|
||||
|
||||
initDefaultHeader = () => {
|
||||
const { navigator } = this.props;
|
||||
navigator.setButtons({ leftButtons, rightButtons });
|
||||
navigator.setStyle({
|
||||
navBarCustomView: 'RoomsListHeaderView',
|
||||
navBarComponentAlignment: 'fill',
|
||||
navBarBackgroundColor: isAndroid() ? '#2F343D' : undefined,
|
||||
navBarTextColor: isAndroid() ? '#FFF' : undefined,
|
||||
navBarButtonColor: isAndroid() ? '#FFF' : undefined
|
||||
});
|
||||
}
|
||||
|
||||
initSearchingAndroid = () => {
|
||||
const { navigator } = this.props;
|
||||
navigator.setButtons({
|
||||
const { openSearchHeader } = this.props;
|
||||
openSearchHeader();
|
||||
Navigation.mergeOptions('RoomsListView', {
|
||||
topBar: {
|
||||
leftButtons: [{
|
||||
id: 'cancelSearch',
|
||||
icon: { uri: 'back', scale: Dimensions.get('window').scale }
|
||||
id: 'back',
|
||||
icon: { uri: 'back', scale: Dimensions.get('window').scale },
|
||||
testID: 'rooms-list-view-cancel-search'
|
||||
}],
|
||||
rightButtons: []
|
||||
});
|
||||
navigator.setStyle({
|
||||
navBarCustomView: 'RoomsListSearchView',
|
||||
navBarComponentAlignment: 'fill'
|
||||
}
|
||||
});
|
||||
BackHandler.addEventListener('hardwareBackPress', this.handleBackPress);
|
||||
}
|
||||
|
||||
// this is necessary during development (enables Cmd + r)
|
||||
hasActiveDB = () => database && database.databases && database.databases.activeDB;
|
||||
|
||||
cancelSearchingAndroid = () => {
|
||||
if (Platform.OS === 'android') {
|
||||
this.setState({ search: [] });
|
||||
this.initDefaultHeader();
|
||||
const { closeSearchHeader } = this.props;
|
||||
closeSearchHeader();
|
||||
Navigation.mergeOptions('RoomsListView', {
|
||||
topBar: {
|
||||
leftButtons,
|
||||
rightButtons
|
||||
}
|
||||
});
|
||||
this.internalSetState({ search: [] });
|
||||
Keyboard.dismiss();
|
||||
BackHandler.removeEventListener('hardwareBackPress', this.handleBackPress);
|
||||
}
|
||||
}
|
||||
|
||||
// this is necessary during development (enables Cmd + r)
|
||||
hasActiveDB = () => database && database.databases && database.databases.activeDB;
|
||||
|
||||
handleBackPress = () => {
|
||||
this.cancelSearchingAndroid();
|
||||
return true;
|
||||
|
@ -357,18 +368,26 @@ export default class RoomsListView extends LoggedView {
|
|||
|
||||
search = async(text) => {
|
||||
const result = await RocketChat.search({ text });
|
||||
this.setState({
|
||||
this.internalSetState({
|
||||
search: result
|
||||
});
|
||||
}
|
||||
|
||||
goRoom = (rid, name) => {
|
||||
const { navigator } = this.props;
|
||||
navigator.push({
|
||||
screen: 'RoomView',
|
||||
title: name,
|
||||
backButtonTitle: '',
|
||||
passProps: { rid }
|
||||
Navigation.push('RoomsListView', {
|
||||
component: {
|
||||
name: 'RoomView',
|
||||
passProps: {
|
||||
rid
|
||||
},
|
||||
options: {
|
||||
topBar: {
|
||||
title: {
|
||||
text: name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
this.cancelSearchingAndroid();
|
||||
}
|
||||
|
@ -559,11 +578,11 @@ export default class RoomsListView extends LoggedView {
|
|||
|
||||
render = () => {
|
||||
const {
|
||||
sortBy, groupByType, showFavorites, showUnread, showServerDropdown, showSortDropdown, navigator
|
||||
sortBy, groupByType, showFavorites, showUnread, showServerDropdown, showSortDropdown
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<SafeAreaView style={styles.container} testID='rooms-list-view'>
|
||||
<SafeAreaView style={styles.container} testID='rooms-list-view' forceInset={{ bottom: 'never' }}>
|
||||
{this.renderScroll()}
|
||||
{showSortDropdown
|
||||
? (
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { View, FlatList, SafeAreaView } from 'react-native';
|
||||
import { View, FlatList } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import SafeAreaView from 'react-native-safe-area-view';
|
||||
|
||||
import LoggedView from '../View';
|
||||
import RCTextInput from '../../containers/TextInput';
|
||||
|
@ -26,9 +27,19 @@ import I18n from '../../i18n';
|
|||
}))
|
||||
/** @extends React.Component */
|
||||
export default class SearchMessagesView extends LoggedView {
|
||||
static options() {
|
||||
return {
|
||||
topBar: {
|
||||
title: {
|
||||
text: I18n.t('Search')
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
rid: PropTypes.string,
|
||||
navigator: PropTypes.object,
|
||||
componentId: PropTypes.string,
|
||||
user: PropTypes.object,
|
||||
baseUrl: PropTypes.string
|
||||
}
|
||||
|
@ -120,7 +131,7 @@ export default class SearchMessagesView extends LoggedView {
|
|||
render() {
|
||||
const { searching, loadingMore, messages } = this.state;
|
||||
return (
|
||||
<SafeAreaView style={styles.container} testID='search-messages-view'>
|
||||
<SafeAreaView style={styles.container} testID='search-messages-view' forceInset={{ bottom: 'never' }}>
|
||||
<View style={styles.searchContainer}>
|
||||
<RCTextInput
|
||||
inputRef={(e) => { this.name = e; }}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
View, StyleSheet, SafeAreaView, FlatList, LayoutAnimation, Platform
|
||||
View, StyleSheet, FlatList, LayoutAnimation, Platform
|
||||
} from 'react-native';
|
||||
import { connect, Provider } from 'react-redux';
|
||||
import { Navigation } from 'react-native-navigation';
|
||||
import SafeAreaView from 'react-native-safe-area-view';
|
||||
|
||||
import {
|
||||
addUser as addUserAction, removeUser as removeUserAction, reset as resetAction, setLoading as setLoadingAction
|
||||
|
@ -49,7 +50,7 @@ let CreateChannelView = null;
|
|||
/** @extends React.Component */
|
||||
export default class SelectedUsersView extends LoggedView {
|
||||
static propTypes = {
|
||||
navigator: PropTypes.object,
|
||||
componentId: PropTypes.string,
|
||||
rid: PropTypes.string,
|
||||
nextAction: PropTypes.string.isRequired,
|
||||
baseUrl: PropTypes.string,
|
||||
|
@ -68,35 +69,27 @@ export default class SelectedUsersView extends LoggedView {
|
|||
search: []
|
||||
};
|
||||
this.data.addListener(this.updateState);
|
||||
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this));
|
||||
Navigation.events().bindComponent(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { navigator } = this.props;
|
||||
navigator.setDrawerEnabled({
|
||||
side: 'left',
|
||||
enabled: false
|
||||
});
|
||||
}
|
||||
|
||||
async componentDidUpdate(prevProps) {
|
||||
const { navigator, users } = this.props;
|
||||
const isVisible = await navigator.screenIsCurrentlyVisible();
|
||||
|
||||
if (!isVisible) {
|
||||
return;
|
||||
}
|
||||
componentDidUpdate(prevProps) {
|
||||
const { componentId, users } = this.props;
|
||||
if (prevProps.users.length !== users.length) {
|
||||
const { length } = users;
|
||||
const rightButtons = [];
|
||||
if (length > 0) {
|
||||
rightButtons.push({
|
||||
id: 'create',
|
||||
title: I18n.t('Next'),
|
||||
testID: 'selected-users-view-submit'
|
||||
text: I18n.t('Next'),
|
||||
testID: 'selected-users-view-submit',
|
||||
color: Platform.OS === 'android' ? '#FFF' : undefined
|
||||
});
|
||||
}
|
||||
navigator.setButtons({ rightButtons });
|
||||
Navigation.mergeOptions(componentId, {
|
||||
topBar: {
|
||||
rightButtons
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,27 +100,39 @@ export default class SelectedUsersView extends LoggedView {
|
|||
reset();
|
||||
}
|
||||
|
||||
async onNavigatorEvent(event) {
|
||||
if (event.type === 'NavBarButtonPress') {
|
||||
if (event.id === 'create') {
|
||||
const { nextAction, setLoadingInvite, navigator } = this.props;
|
||||
if (nextAction === 'CREATE_CHANNEL') {
|
||||
if (CreateChannelView == null) {
|
||||
CreateChannelView = require('./CreateChannelView').default;
|
||||
Navigation.registerComponent('CreateChannelView', () => CreateChannelView, store, Provider);
|
||||
onSearchChangeText(text) {
|
||||
this.search(text);
|
||||
}
|
||||
|
||||
navigator.push({
|
||||
screen: 'CreateChannelView',
|
||||
title: I18n.t('Create_Channel'),
|
||||
backButtonTitle: ''
|
||||
navigationButtonPressed = async({ buttonId }) => {
|
||||
if (buttonId === 'create') {
|
||||
const { nextAction, setLoadingInvite } = this.props;
|
||||
if (nextAction === 'CREATE_CHANNEL') {
|
||||
const { componentId } = this.props;
|
||||
|
||||
if (CreateChannelView == null) {
|
||||
CreateChannelView = require('./CreateChannelView').default;
|
||||
Navigation.registerComponentWithRedux('CreateChannelView', () => CreateChannelView, Provider, store);
|
||||
}
|
||||
|
||||
Navigation.push(componentId, {
|
||||
component: {
|
||||
name: 'CreateChannelView',
|
||||
options: {
|
||||
topBar: {
|
||||
title: {
|
||||
text: I18n.t('Create_Channel')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
const { rid } = this.props;
|
||||
const { rid, componentId } = this.props;
|
||||
try {
|
||||
setLoadingInvite(true);
|
||||
await RocketChat.addUsersToRoom(rid);
|
||||
navigator.pop();
|
||||
Navigation.pop(componentId);
|
||||
} catch (e) {
|
||||
log('RoomActions Add User', e);
|
||||
} finally {
|
||||
|
@ -136,11 +141,6 @@ export default class SelectedUsersView extends LoggedView {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onSearchChangeText(text) {
|
||||
this.search(text);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line react/sort-comp
|
||||
updateState = debounce(() => {
|
||||
|
@ -271,7 +271,7 @@ export default class SelectedUsersView extends LoggedView {
|
|||
render = () => {
|
||||
const { loading } = this.props;
|
||||
return (
|
||||
<SafeAreaView style={styles.safeAreaView} testID='select-users-view'>
|
||||
<SafeAreaView style={styles.safeAreaView} testID='select-users-view' forceInset={{ bottom: 'never' }}>
|
||||
{this.renderList()}
|
||||
<Loading visible={loading} />
|
||||
</SafeAreaView>
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
View, ScrollView, SafeAreaView, Dimensions
|
||||
} from 'react-native';
|
||||
import { View, ScrollView, Dimensions } from 'react-native';
|
||||
import RNPickerSelect from 'react-native-picker-select';
|
||||
import { connect } from 'react-redux';
|
||||
import { Navigation } from 'react-native-navigation';
|
||||
import SafeAreaView from 'react-native-safe-area-view';
|
||||
|
||||
import LoggedView from '../View';
|
||||
import RocketChat from '../../lib/rocketchat';
|
||||
|
@ -18,6 +18,7 @@ import Loading from '../../containers/Loading';
|
|||
import { showErrorAlert, showToast } from '../../utils/info';
|
||||
import log from '../../utils/log';
|
||||
import { setUser as setUserAction } from '../../actions/login';
|
||||
import Drawer from '../../Drawer';
|
||||
|
||||
@connect(state => ({
|
||||
userLanguage: state.login.user && state.login.user.language
|
||||
|
@ -26,8 +27,28 @@ import { setUser as setUserAction } from '../../actions/login';
|
|||
}))
|
||||
/** @extends React.Component */
|
||||
export default class SettingsView extends LoggedView {
|
||||
static options() {
|
||||
return {
|
||||
topBar: {
|
||||
leftButtons: [{
|
||||
id: 'settings',
|
||||
icon: { uri: 'settings', scale: Dimensions.get('window').scale },
|
||||
testID: 'rooms-list-view-sidebar'
|
||||
}],
|
||||
title: {
|
||||
text: I18n.t('Settings')
|
||||
}
|
||||
},
|
||||
sideMenu: {
|
||||
left: {
|
||||
enabled: true
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
navigator: PropTypes.object,
|
||||
componentId: PropTypes.string,
|
||||
userLanguage: PropTypes.string,
|
||||
setUser: PropTypes.func
|
||||
}
|
||||
|
@ -49,35 +70,12 @@ export default class SettingsView extends LoggedView {
|
|||
}],
|
||||
saving: false
|
||||
};
|
||||
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this));
|
||||
Navigation.events().bindComponent(this);
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
const { navigator } = this.props;
|
||||
navigator.setButtons({
|
||||
leftButtons: [{
|
||||
id: 'settings',
|
||||
icon: { uri: 'settings', scale: Dimensions.get('window').scale }
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { navigator } = this.props;
|
||||
navigator.setDrawerEnabled({
|
||||
side: 'left',
|
||||
enabled: true
|
||||
});
|
||||
}
|
||||
|
||||
onNavigatorEvent(event) {
|
||||
const { navigator } = this.props;
|
||||
if (event.type === 'NavBarButtonPress') {
|
||||
if (event.id === 'settings') {
|
||||
navigator.toggleDrawer({
|
||||
side: 'left'
|
||||
});
|
||||
}
|
||||
navigationButtonPressed = ({ buttonId }) => {
|
||||
if (buttonId === 'settings') {
|
||||
Drawer.toggle();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,7 +98,7 @@ export default class SettingsView extends LoggedView {
|
|||
this.setState({ saving: true });
|
||||
|
||||
const { language } = this.state;
|
||||
const { userLanguage, setUser, navigator } = this.props;
|
||||
const { userLanguage, setUser } = this.props;
|
||||
|
||||
if (!this.formIsChanged()) {
|
||||
return;
|
||||
|
@ -122,7 +120,14 @@ export default class SettingsView extends LoggedView {
|
|||
showToast(I18n.t('Preferences_saved'));
|
||||
|
||||
if (params.language) {
|
||||
navigator.setTitle({ title: I18n.t('Settings') });
|
||||
const { componentId } = this.props;
|
||||
Navigation.mergeOptions(componentId, {
|
||||
topBar: {
|
||||
title: {
|
||||
text: I18n.t('Settings')
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}, 300);
|
||||
} catch (e) {
|
||||
|
@ -148,7 +153,7 @@ export default class SettingsView extends LoggedView {
|
|||
testID='settings-view-list'
|
||||
{...scrollPersistTaps}
|
||||
>
|
||||
<SafeAreaView style={sharedStyles.container} testID='settings-view'>
|
||||
<SafeAreaView style={sharedStyles.container} testID='settings-view' forceInset={{ bottom: 'never' }}>
|
||||
<RNPickerSelect
|
||||
items={languages}
|
||||
onValueChange={(value) => {
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
FlatList, View, Text, SafeAreaView
|
||||
} from 'react-native';
|
||||
import { FlatList, View, Text } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import SafeAreaView from 'react-native-safe-area-view';
|
||||
|
||||
import { openSnippetedMessages as openSnippetedMessagesAction, closeSnippetedMessages as closeSnippetedMessagesAction } from '../../actions/snippetedMessages';
|
||||
import LoggedView from '../View';
|
||||
|
@ -26,6 +25,16 @@ import I18n from '../../i18n';
|
|||
}))
|
||||
/** @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,
|
||||
|
@ -106,7 +115,7 @@ export default class SnippetedMessagesView extends LoggedView {
|
|||
}
|
||||
|
||||
return (
|
||||
<SafeAreaView style={styles.list} testID='snippeted-messages-view'>
|
||||
<SafeAreaView style={styles.list} testID='snippeted-messages-view' forceInset={{ bottom: 'never' }}>
|
||||
<FlatList
|
||||
data={messages}
|
||||
renderItem={this.renderItem}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
FlatList, View, Text, SafeAreaView
|
||||
} from 'react-native';
|
||||
import { FlatList, View, Text } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import ActionSheet from 'react-native-actionsheet';
|
||||
import SafeAreaView from 'react-native-safe-area-view';
|
||||
|
||||
import { openStarredMessages as openStarredMessagesAction, closeStarredMessages as closeStarredMessagesAction } from '../../actions/starredMessages';
|
||||
import { toggleStarRequest as toggleStarRequestAction } from '../../actions/messages';
|
||||
|
@ -33,6 +32,16 @@ const options = [I18n.t('Unstar'), I18n.t('Cancel')];
|
|||
}))
|
||||
/** @extends React.Component */
|
||||
export default class StarredMessagesView extends LoggedView {
|
||||
static options() {
|
||||
return {
|
||||
topBar: {
|
||||
title: {
|
||||
text: I18n.t('Starred')
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
rid: PropTypes.string,
|
||||
messages: PropTypes.array,
|
||||
|
@ -136,7 +145,7 @@ export default class StarredMessagesView extends LoggedView {
|
|||
}
|
||||
|
||||
return (
|
||||
<SafeAreaView style={styles.list} testID='starred-messages-view'>
|
||||
<SafeAreaView style={styles.list} testID='starred-messages-view' forceInset={{ bottom: 'never' }}>
|
||||
<FlatList
|
||||
data={messages}
|
||||
renderItem={this.renderItem}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { WebView, SafeAreaView } from 'react-native';
|
||||
import { WebView } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import SafeAreaView from 'react-native-safe-area-view';
|
||||
|
||||
import styles from './Styles';
|
||||
import LoggedView from './View';
|
||||
|
|
|
@ -1,26 +1,10 @@
|
|||
import React from 'react';
|
||||
import { Platform } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Answers } from 'react-native-fabric';
|
||||
import { NavigationActions } from '../Navigation';
|
||||
|
||||
const isAndroid = () => Platform.OS === 'android';
|
||||
|
||||
/** @extends React.Component */
|
||||
export default class extends React.Component {
|
||||
static navigatorStyle = {
|
||||
navBarBackgroundColor: isAndroid() ? '#2F343D' : undefined,
|
||||
navBarTextColor: isAndroid() ? '#FFF' : undefined,
|
||||
navBarButtonColor: isAndroid() ? '#FFF' : undefined
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
navigator: PropTypes.object
|
||||
}
|
||||
|
||||
constructor(name, props) {
|
||||
super(props);
|
||||
NavigationActions.setNavigator(props.navigator);
|
||||
Answers.logContentView(name);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,19 +5,17 @@ import { gestureHandlerRootHOC } from 'react-native-gesture-handler';
|
|||
import OnboardingView from './OnboardingView';
|
||||
import ProfileView from './ProfileView';
|
||||
import RoomsListHeaderView from './RoomsListView/Header';
|
||||
import RoomsListSearchView from './RoomsListView/Search';
|
||||
import RoomsListView from './RoomsListView';
|
||||
import RoomView from './RoomView';
|
||||
import SettingsView from './SettingsView';
|
||||
import Sidebar from '../containers/Sidebar';
|
||||
|
||||
export const registerScreens = (store) => {
|
||||
Navigation.registerComponent('OnboardingView', () => OnboardingView, store, Provider);
|
||||
Navigation.registerComponent('ProfileView', () => ProfileView, store, Provider);
|
||||
Navigation.registerComponent('RoomsListHeaderView', () => RoomsListHeaderView, store, Provider);
|
||||
Navigation.registerComponent('RoomsListSearchView', () => RoomsListSearchView, store, Provider);
|
||||
Navigation.registerComponent('RoomsListView', () => gestureHandlerRootHOC(RoomsListView), store, Provider);
|
||||
Navigation.registerComponent('RoomView', () => gestureHandlerRootHOC(RoomView), store, Provider);
|
||||
Navigation.registerComponent('SettingsView', () => SettingsView, store, Provider);
|
||||
Navigation.registerComponent('Sidebar', () => Sidebar, store, Provider);
|
||||
Navigation.registerComponentWithRedux('OnboardingView', () => OnboardingView, Provider, store);
|
||||
Navigation.registerComponentWithRedux('ProfileView', () => ProfileView, Provider, store);
|
||||
Navigation.registerComponentWithRedux('RoomsListHeaderView', () => RoomsListHeaderView, Provider, store);
|
||||
Navigation.registerComponentWithRedux('RoomsListView', () => gestureHandlerRootHOC(RoomsListView), Provider, store);
|
||||
Navigation.registerComponentWithRedux('RoomView', () => gestureHandlerRootHOC(RoomView), Provider, store);
|
||||
Navigation.registerComponentWithRedux('SettingsView', () => SettingsView, Provider, store);
|
||||
Navigation.registerComponentWithRedux('Sidebar', () => Sidebar, Provider, store);
|
||||
};
|
||||
|
|
|
@ -52,7 +52,7 @@ describe('Rooms list screen', () => {
|
|||
await expect(element(by.id('room-view'))).toBeVisible();
|
||||
await waitFor(element(by.text('rocket.cat'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text('rocket.cat'))).toBeVisible();
|
||||
await tapBack(2);
|
||||
await tapBack();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
||||
await element(by.id('rooms-list-view-search')).replaceText('');
|
||||
|
|
|
@ -32,7 +32,7 @@ describe('Create room screen', () => {
|
|||
|
||||
describe('Usage', async() => {
|
||||
it('should back to rooms list', async() => {
|
||||
await tapBack();
|
||||
await element(by.text('Cancel')).tap();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
||||
await element(by.id('rooms-list-view-create-channel')).tap();
|
||||
|
@ -48,7 +48,7 @@ describe('Create room screen', () => {
|
|||
await expect(element(by.id('room-view'))).toBeVisible();
|
||||
await waitFor(element(by.text('rocket.cat'))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text('rocket.cat'))).toBeVisible();
|
||||
await tapBack(2);
|
||||
await tapBack();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id('rooms-list-view-create-channel')).tap();
|
||||
});
|
||||
|
@ -120,7 +120,7 @@ describe('Create room screen', () => {
|
|||
await expect(element(by.id('room-view'))).toBeVisible();
|
||||
await waitFor(element(by.text(`public${ data.random }`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text(`public${ data.random }`))).toBeVisible();
|
||||
await tapBack(2);
|
||||
await tapBack();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await waitFor(element(by.id(`rooms-list-view-item-public${ data.random }`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.id(`rooms-list-view-item-public${ data.random }`))).toBeVisible();
|
||||
|
@ -143,7 +143,7 @@ describe('Create room screen', () => {
|
|||
await expect(element(by.id('room-view'))).toBeVisible();
|
||||
await waitFor(element(by.text(`private${ data.random }`))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text(`private${ data.random }`))).toBeVisible();
|
||||
await tapBack(2);
|
||||
await tapBack();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await element(by.id('rooms-list-view-search')).replaceText(`private${ data.random }`);
|
||||
await waitFor(element(by.id(`rooms-list-view-item-private${ data.random }`))).toBeVisible().withTimeout(60000);
|
||||
|
|
|
@ -75,7 +75,7 @@ describe('Room screen', () => {
|
|||
describe('Usage', async() => {
|
||||
describe('Header', async() => {
|
||||
it('should back to rooms list', async() => {
|
||||
await tapBack(2);
|
||||
await tapBack();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
||||
await navigateToRoom();
|
||||
|
@ -290,7 +290,7 @@ describe('Room screen', () => {
|
|||
|
||||
after(async() => {
|
||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(5000);
|
||||
await tapBack(2);
|
||||
await tapBack();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
||||
});
|
||||
|
|
|
@ -23,8 +23,8 @@ async function navigateToRoomActions(type) {
|
|||
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(5000);
|
||||
}
|
||||
|
||||
async function backToActions(index = 0) {
|
||||
await tapBack(index);
|
||||
async function backToActions() {
|
||||
await tapBack();
|
||||
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('room-actions-view'))).toBeVisible();
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ async function backToActions(index = 0) {
|
|||
async function backToRoomsList() {
|
||||
await tapBack();
|
||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(2000);
|
||||
await tapBack(2);
|
||||
await tapBack();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
}
|
||||
|
||||
|
@ -367,7 +367,7 @@ describe('Room actions screen', () => {
|
|||
await expect(element(by.id('room-view'))).toBeVisible();
|
||||
await waitFor(element(by.text(data.alternateUser))).toBeVisible().withTimeout(60000);
|
||||
await expect(element(by.text(data.alternateUser))).toBeVisible();
|
||||
await tapBack(2);
|
||||
await tapBack();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
});
|
||||
|
||||
|
|
|
@ -32,11 +32,11 @@ describe('Broadcast room', () => {
|
|||
await waitFor(element(by.id('room-info-view'))).toBeVisible().withTimeout(2000);
|
||||
await waitFor(element(by.id('room-info-view-broadcast'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('room-info-view-broadcast'))).toBeVisible();
|
||||
await tapBack(1);
|
||||
await tapBack();
|
||||
await waitFor(element(by.id('room-actions-view'))).toBeVisible().withTimeout(2000);
|
||||
await tapBack();
|
||||
await waitFor(element(by.id('room-view'))).toBeVisible().withTimeout(2000);
|
||||
// await tapBack(2);
|
||||
// await tapBack();
|
||||
// await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
// await waitFor(element(by.id(`rooms-list-view-item-broadcast${ data.random }`))).toExist().withTimeout(60000);
|
||||
// await expect(element(by.id(`rooms-list-view-item-broadcast${ data.random }`))).toExist();
|
||||
|
@ -53,7 +53,7 @@ describe('Broadcast room', () => {
|
|||
});
|
||||
|
||||
it('should login as user without write message authorization and enter room', async() => {
|
||||
await tapBack(2);
|
||||
await tapBack();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await expect(element(by.id('rooms-list-view'))).toBeVisible();
|
||||
await logout();
|
||||
|
@ -110,7 +110,7 @@ describe('Broadcast room', () => {
|
|||
|
||||
after(async() => {
|
||||
// log back as main test user and left screen on RoomsListView
|
||||
await tapBack(2);
|
||||
await tapBack();
|
||||
await waitFor(element(by.id('rooms-list-view'))).toBeVisible().withTimeout(2000);
|
||||
await logout();
|
||||
await navigateToLogin();
|
||||
|
|
|
@ -36,8 +36,8 @@ async function logout() {
|
|||
await expect(element(by.id('onboarding-view'))).toBeVisible();
|
||||
}
|
||||
|
||||
async function tapBack(index) {
|
||||
await element(by.type('_UIModernBarButton')).atIndex(index || 0).tap();
|
||||
async function tapBack() {
|
||||
await element(by.type('_UIModernBarButton').withAncestor(by.type('_UIBackButtonContainerView'))).tap();
|
||||
}
|
||||
|
||||
async function sleep(ms) {
|
||||
|
|
|
@ -54,8 +54,8 @@
|
|||
7A309C9C20724870000C6B13 /* Fabric.sh in Resources */ = {isa = PBXBuildFile; fileRef = 7A309C9B20724870000C6B13 /* Fabric.sh */; };
|
||||
7A32C246206D791D001C80E9 /* Fabric.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A32C20F206D791D001C80E9 /* Fabric.framework */; };
|
||||
7A32C247206D791D001C80E9 /* Crashlytics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A32C245206D791D001C80E9 /* Crashlytics.framework */; };
|
||||
7A3562E620E1569000A4CF66 /* libReactNativeNavigation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A3562E520E1567900A4CF66 /* libReactNativeNavigation.a */; };
|
||||
7A430E4F20238C46008F55BC /* libRCTCustomInputController.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A430E1E20238C02008F55BC /* libRCTCustomInputController.a */; };
|
||||
7A807B55215EC60500A4348D /* libReactNativeNavigation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A807B52215EC5E500A4348D /* libReactNativeNavigation.a */; };
|
||||
7A8DEB5A20ED0BEC00C5DCE4 /* libRNNotifications.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A8DEB5220ED0BDE00C5DCE4 /* libRNNotifications.a */; };
|
||||
7AFB806E205AE65700D004E7 /* libRCTToast.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7AFB804C205AE63100D004E7 /* libRCTToast.a */; };
|
||||
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; };
|
||||
|
@ -308,13 +308,6 @@
|
|||
remoteGlobalIDString = 6463C84C1EBA12A60095B8CD;
|
||||
remoteInfo = "SMXCrashlytics-tvOS";
|
||||
};
|
||||
7A3562E420E1567900A4CF66 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 7A3562E020E1567900A4CF66 /* ReactNativeNavigation.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = D8AFADBD1BEE6F3F00A4592D;
|
||||
remoteInfo = ReactNativeNavigation;
|
||||
};
|
||||
7A430E1D20238C02008F55BC /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 7A430E1620238C01008F55BC /* RCTCustomInputController.xcodeproj */;
|
||||
|
@ -357,6 +350,20 @@
|
|||
remoteGlobalIDString = 641E28441F0EEC8500443AF6;
|
||||
remoteInfo = "RCTVideo-tvOS";
|
||||
};
|
||||
7A807B51215EC5E500A4348D /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 7A807B4C215EC5E400A4348D /* ReactNativeNavigation.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = D8AFADBD1BEE6F3F00A4592D;
|
||||
remoteInfo = ReactNativeNavigation;
|
||||
};
|
||||
7A807B53215EC5E500A4348D /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 7A807B4C215EC5E400A4348D /* ReactNativeNavigation.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 7B49FEBB1E95090800DEB3EA;
|
||||
remoteInfo = ReactNativeNavigationTests;
|
||||
};
|
||||
7A8C915220F39A8000C8F5EE /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 0B82BCC462E84F308C5B5CD1 /* RNFetchBlob.xcodeproj */;
|
||||
|
@ -541,8 +548,8 @@
|
|||
7A30DA4B2D474348824CD05B /* FontAwesome.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = FontAwesome.ttf; path = "../node_modules/react-native-vector-icons/Fonts/FontAwesome.ttf"; sourceTree = "<group>"; };
|
||||
7A32C20F206D791D001C80E9 /* Fabric.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Fabric.framework; path = "../../../../Downloads/com.crashlytics.ios-manual/Fabric.framework"; sourceTree = "<group>"; };
|
||||
7A32C245206D791D001C80E9 /* Crashlytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Crashlytics.framework; path = "../../../../Downloads/com.crashlytics.ios-manual/Crashlytics.framework"; sourceTree = "<group>"; };
|
||||
7A3562E020E1567900A4CF66 /* ReactNativeNavigation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ReactNativeNavigation.xcodeproj; path = "../node_modules/react-native-navigation/ios/ReactNativeNavigation.xcodeproj"; sourceTree = "<group>"; };
|
||||
7A430E1620238C01008F55BC /* RCTCustomInputController.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTCustomInputController.xcodeproj; path = "../node_modules/react-native-keyboard-input/lib/ios/RCTCustomInputController.xcodeproj"; sourceTree = "<group>"; };
|
||||
7A807B4C215EC5E400A4348D /* ReactNativeNavigation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ReactNativeNavigation.xcodeproj; path = "../node_modules/react-native-navigation/lib/ios/ReactNativeNavigation.xcodeproj"; sourceTree = "<group>"; };
|
||||
7A8DEB1B20ED0BDE00C5DCE4 /* RNNotifications.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RNNotifications.xcodeproj; path = "../node_modules/react-native-notifications/RNNotifications/RNNotifications.xcodeproj"; sourceTree = "<group>"; };
|
||||
7AFB8035205AE63000D004E7 /* RCTToast.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTToast.xcodeproj; path = "../node_modules/@remobile/react-native-toast/ios/RCTToast.xcodeproj"; sourceTree = "<group>"; };
|
||||
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = "<group>"; };
|
||||
|
@ -583,8 +590,8 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
7A807B55215EC60500A4348D /* libReactNativeNavigation.a in Frameworks */,
|
||||
7A8DEB5A20ED0BEC00C5DCE4 /* libRNNotifications.a in Frameworks */,
|
||||
7A3562E620E1569000A4CF66 /* libReactNativeNavigation.a in Frameworks */,
|
||||
7A2D202320726F1400D0AA04 /* libSMXCrashlytics.a in Frameworks */,
|
||||
7AFB806E205AE65700D004E7 /* libRCTToast.a in Frameworks */,
|
||||
B8971BB2202A093B0000D245 /* libKeyboardTrackingView.a in Frameworks */,
|
||||
|
@ -806,14 +813,6 @@
|
|||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7A3562E120E1567900A4CF66 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7A3562E520E1567900A4CF66 /* libReactNativeNavigation.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7A430E1720238C01008F55BC /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -848,6 +847,15 @@
|
|||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7A807B4D215EC5E400A4348D /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7A807B52215EC5E500A4348D /* libReactNativeNavigation.a */,
|
||||
7A807B54215EC5E500A4348D /* ReactNativeNavigationTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7A8C912120F39A8000C8F5EE /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -883,8 +891,8 @@
|
|||
832341AE1AAA6A7D00B99B32 /* Libraries */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7A807B4C215EC5E400A4348D /* ReactNativeNavigation.xcodeproj */,
|
||||
7A8DEB1B20ED0BDE00C5DCE4 /* RNNotifications.xcodeproj */,
|
||||
7A3562E020E1567900A4CF66 /* ReactNativeNavigation.xcodeproj */,
|
||||
7A2D1FE620726EF600D0AA04 /* SMXCrashlytics.xcodeproj */,
|
||||
7AFB8035205AE63000D004E7 /* RCTToast.xcodeproj */,
|
||||
B8971BAC202A091D0000D245 /* KeyboardTrackingView.xcodeproj */,
|
||||
|
@ -1240,8 +1248,8 @@
|
|||
ProjectRef = 146833FF1AC3E56700842450 /* React.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 7A3562E120E1567900A4CF66 /* Products */;
|
||||
ProjectRef = 7A3562E020E1567900A4CF66 /* ReactNativeNavigation.xcodeproj */;
|
||||
ProductGroup = 7A807B4D215EC5E400A4348D /* Products */;
|
||||
ProjectRef = 7A807B4C215EC5E400A4348D /* ReactNativeNavigation.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 607D60ED1F325B7D00F639C4 /* Products */;
|
||||
|
@ -1508,13 +1516,6 @@
|
|||
remoteRef = 7A2D202020726EF600D0AA04 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
7A3562E520E1567900A4CF66 /* libReactNativeNavigation.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libReactNativeNavigation.a;
|
||||
remoteRef = 7A3562E420E1567900A4CF66 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
7A430E1E20238C02008F55BC /* libRCTCustomInputController.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
|
@ -1557,6 +1558,20 @@
|
|||
remoteRef = 7A7F5C9A1FCC982500024129 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
7A807B52215EC5E500A4348D /* libReactNativeNavigation.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libReactNativeNavigation.a;
|
||||
remoteRef = 7A807B51215EC5E500A4348D /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
7A807B54215EC5E500A4348D /* ReactNativeNavigationTests.xctest */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = wrapper.cfbundle;
|
||||
path = ReactNativeNavigationTests.xctest;
|
||||
remoteRef = 7A807B53215EC5E500A4348D /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
7A8C915320F39A8000C8F5EE /* libRNFetchBlob.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
#import <Fabric/Fabric.h>
|
||||
#import <Crashlytics/Crashlytics.h>
|
||||
#import <React/RCTLinkingManager.h>
|
||||
#import "RCCManager.h"
|
||||
//#import "RCCManager.h"
|
||||
#import <ReactNativeNavigation/ReactNativeNavigation.h>
|
||||
#import "RNNotifications.h"
|
||||
|
||||
|
||||
|
@ -30,9 +31,11 @@
|
|||
jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
|
||||
#endif
|
||||
|
||||
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
||||
self.window.backgroundColor = [UIColor whiteColor];
|
||||
[[RCCManager sharedInstance] initBridgeWithBundleURL:jsCodeLocation launchOptions:launchOptions];
|
||||
[ReactNativeNavigation bootstrap:jsCodeLocation launchOptions:launchOptions];
|
||||
|
||||
// self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
||||
// self.window.backgroundColor = [UIColor whiteColor];
|
||||
// [[RCCManager sharedInstance] initBridgeWithBundleURL:jsCodeLocation launchOptions:launchOptions];
|
||||
|
||||
// RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
|
||||
// moduleName:@"RocketChatRN"
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "back.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "back@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "back@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 409 B |
After Width: | Height: | Size: 718 B |
After Width: | Height: | Size: 1.1 KiB |
|
@ -17191,9 +17191,8 @@
|
|||
}
|
||||
},
|
||||
"react-native-fabric": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/react-native-fabric/-/react-native-fabric-0.5.2.tgz",
|
||||
"integrity": "sha512-uarBq3XtADCJIGwzeHMzG7LCTfElGuqUj4UqMxsWbPsXaYForfNw+EMkEQ+6eBq/a2k4PKfuVQXQAC7rfgo/Vg=="
|
||||
"version": "github:corymsmith/react-native-fabric#523a4edab3b2bf55ea9eeea2cf0dde82c5c29dd4",
|
||||
"from": "github:corymsmith/react-native-fabric#523a4edab3b2bf55ea9eeea2cf0dde82c5c29dd4"
|
||||
},
|
||||
"react-native-fast-image": {
|
||||
"version": "5.0.11",
|
||||
|
@ -17317,10 +17316,34 @@
|
|||
}
|
||||
},
|
||||
"react-native-navigation": {
|
||||
"version": "git+https://github.com/RocketChat/react-native-navigation.git#f7e36cda91404884851b1cb4e95fc34cdf2ef1dc",
|
||||
"from": "git+https://github.com/RocketChat/react-native-navigation.git",
|
||||
"version": "2.0.2588",
|
||||
"resolved": "https://registry.npmjs.org/react-native-navigation/-/react-native-navigation-2.0.2588.tgz",
|
||||
"integrity": "sha512-ljVz3RWNv8Cj2vRcedkWAUuMbDac9ZduBRgYPCQ3GXFVhmpthLSaZLWuMfqqkpznHyPGy0kwEG+XX6Z93cqemw==",
|
||||
"requires": {
|
||||
"lodash": "4.x.x"
|
||||
"hoist-non-react-statics": "3.x.x",
|
||||
"lodash": "4.x.x",
|
||||
"prop-types": "15.x.x",
|
||||
"react-lifecycles-compat": "2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"hoist-non-react-statics": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.0.1.tgz",
|
||||
"integrity": "sha512-1kXwPsOi0OGQIZNVMPvgWJ9tSnGMiMfJdihqEzrPEXlHOBh9AAHXX/QYmAJTXztnz/K+PQ8ryCb4eGaN6HlGbQ==",
|
||||
"requires": {
|
||||
"react-is": "^16.3.2"
|
||||
}
|
||||
},
|
||||
"react-is": {
|
||||
"version": "16.5.2",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.5.2.tgz",
|
||||
"integrity": "sha512-hSl7E6l25GTjNEZATqZIuWOgSnpXb3kD0DVCujmg46K5zLxsbiKaaT6VO9slkSBDPZfYs30lwfJwbOFOnoEnKQ=="
|
||||
},
|
||||
"react-lifecycles-compat": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-2.0.0.tgz",
|
||||
"integrity": "sha512-txfpPCQYiazVdcbMRhatqWKcAxJweUu2wDXvts5/7Wyp6+Y9cHojqXHsLPEckzutfHlxZhG8Oiundbmp8Fd6eQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-native-notifications": {
|
||||
|
@ -17373,6 +17396,21 @@
|
|||
"resolved": "https://registry.npmjs.org/react-native-safari-view/-/react-native-safari-view-2.1.0.tgz",
|
||||
"integrity": "sha1-HgzRLGK855vBdZx+KBZGsIthyVk="
|
||||
},
|
||||
"react-native-safe-area-view": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-safe-area-view/-/react-native-safe-area-view-0.11.0.tgz",
|
||||
"integrity": "sha512-N3nElaahu1Me2ltnfc9acpgt1znm6pi8DSadKy79kvdzKwvVIzw0IXueA/Hjr51eCW1BsfNw7D1SgBT9U6qEkA==",
|
||||
"requires": {
|
||||
"hoist-non-react-statics": "^2.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"hoist-non-react-statics": {
|
||||
"version": "2.5.5",
|
||||
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz",
|
||||
"integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-native-scrollable-tab-view": {
|
||||
"version": "git+https://github.com/skv-headless/react-native-scrollable-tab-view.git#2419c25a03f0fb346af8ce2c39fca869f259e716",
|
||||
"from": "git+https://github.com/skv-headless/react-native-scrollable-tab-view.git",
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
"react-native-audio": "^4.2.2",
|
||||
"react-native-device-info": "^0.24.0",
|
||||
"react-native-dialog": "^5.4.0",
|
||||
"react-native-fabric": "^0.5.2",
|
||||
"react-native-fabric": "github:corymsmith/react-native-fabric#523a4edab3b2bf55ea9eeea2cf0dde82c5c29dd4",
|
||||
"react-native-fast-image": "^5.0.11",
|
||||
"react-native-gesture-handler": "^1.0.8",
|
||||
"react-native-i18n": "^2.0.15",
|
||||
|
@ -52,12 +52,13 @@
|
|||
"react-native-markdown-renderer": "^3.2.8",
|
||||
"react-native-meteor": "^1.4.0",
|
||||
"react-native-modal": "^6.5.0",
|
||||
"react-native-navigation": "git+https://github.com/RocketChat/react-native-navigation.git",
|
||||
"react-native-navigation": "^2.0.2588",
|
||||
"react-native-notifications": "^1.1.20",
|
||||
"react-native-optimized-flatlist": "^1.0.4",
|
||||
"react-native-picker-select": "^4.4.0",
|
||||
"react-native-responsive-ui": "^1.1.1",
|
||||
"react-native-safari-view": "^2.1.0",
|
||||
"react-native-safe-area-view": "^0.11.0",
|
||||
"react-native-scrollable-tab-view": "git+https://github.com/skv-headless/react-native-scrollable-tab-view.git",
|
||||
"react-native-slider": "^0.11.0",
|
||||
"react-native-vector-icons": "^5.0.0",
|
||||
|
|