diff --git a/android/app/src/main/java/com/mattermost/rnbeta/NotificationsLifecycleFacade.java b/android/app/src/main/java/com/mattermost/rnbeta/NotificationsLifecycleFacade.java
index 66568d287..17a1f6d07 100644
--- a/android/app/src/main/java/com/mattermost/rnbeta/NotificationsLifecycleFacade.java
+++ b/android/app/src/main/java/com/mattermost/rnbeta/NotificationsLifecycleFacade.java
@@ -39,12 +39,11 @@ public class NotificationsLifecycleFacade extends ActivityCallbacks implements A
private final BroadcastReceiver restrictionsReceiver = new BroadcastReceiver() {
@Override public void onReceive(Context context, Intent intent) {
-
- if (mVisibleActivity != null) {
+ if (context != null) {
// Get the current configuration bundle
RestrictionsManager myRestrictionsMgr =
- (RestrictionsManager) mVisibleActivity
- .getSystemService(Context.RESTRICTIONS_SERVICE);
+ (RestrictionsManager) context
+ .getSystemService(Context.RESTRICTIONS_SERVICE);
managedConfig = myRestrictionsMgr.getApplicationRestrictions();
// Check current configuration settings, change your app's UI and
@@ -66,11 +65,11 @@ public class NotificationsLifecycleFacade extends ActivityCallbacks implements A
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
MattermostManagedModule managedModule = MattermostManagedModule.getInstance();
- if (managedModule != null && managedModule.isBlurAppScreenEnabled()) {
+ if (managedModule != null && managedModule.isBlurAppScreenEnabled() && activity != null) {
activity.getWindow().setFlags(LayoutParams.FLAG_SECURE,
LayoutParams.FLAG_SECURE);
}
- if (managedConfig!= null && managedConfig.size() > 0) {
+ if (managedConfig!= null && managedConfig.size() > 0 && activity != null) {
activity.registerReceiver(restrictionsReceiver, restrictionsFilter);
}
}
@@ -79,9 +78,11 @@ public class NotificationsLifecycleFacade extends ActivityCallbacks implements A
public void onActivityResumed(Activity activity) {
switchToVisible(activity);
- if (managedConfig != null && managedConfig.size() > 0) {
+ ReactContext ctx = getRunningReactContext();
+ if (managedConfig != null && managedConfig.size() > 0 && ctx != null) {
+
RestrictionsManager myRestrictionsMgr =
- (RestrictionsManager) activity
+ (RestrictionsManager) ctx
.getSystemService(Context.RESTRICTIONS_SERVICE);
Bundle newConfig = myRestrictionsMgr.getApplicationRestrictions();
@@ -174,13 +175,15 @@ public class NotificationsLifecycleFacade extends ActivityCallbacks implements A
}
}
- public synchronized void LoadManagedConfig(Activity activity) {
- RestrictionsManager myRestrictionsMgr =
- (RestrictionsManager) activity
- .getSystemService(Context.RESTRICTIONS_SERVICE);
+ public synchronized void LoadManagedConfig(ReactContext ctx) {
+ if (ctx != null) {
+ RestrictionsManager myRestrictionsMgr =
+ (RestrictionsManager) ctx
+ .getSystemService(Context.RESTRICTIONS_SERVICE);
- managedConfig = myRestrictionsMgr.getApplicationRestrictions();
- myRestrictionsMgr = null;
+ managedConfig = myRestrictionsMgr.getApplicationRestrictions();
+ myRestrictionsMgr = null;
+ }
}
public synchronized Bundle getManagedConfig() {
@@ -188,8 +191,10 @@ public class NotificationsLifecycleFacade extends ActivityCallbacks implements A
return managedConfig;
}
- if (mVisibleActivity != null) {
- LoadManagedConfig(mVisibleActivity);
+ ReactContext ctx = getRunningReactContext();
+
+ if (ctx != null) {
+ LoadManagedConfig(ctx);
return managedConfig;
}
@@ -198,9 +203,11 @@ public class NotificationsLifecycleFacade extends ActivityCallbacks implements A
public void sendConfigChanged(Bundle config) {
Object result = Arguments.fromBundle(config);
- getRunningReactContext().
- getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).
- emit("managedConfigDidChange", result);
+ ReactContext ctx = getRunningReactContext();
+ if (ctx != null) {
+ ctx.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).
+ emit("managedConfigDidChange", result);
+ }
}
private boolean equalBundles(Bundle one, Bundle two) {
diff --git a/app/actions/views/channel.js b/app/actions/views/channel.js
index 0301dee2f..d43dd914d 100644
--- a/app/actions/views/channel.js
+++ b/app/actions/views/channel.js
@@ -470,7 +470,8 @@ export function increasePostVisibility(channelId, focusedPostId) {
// Check if we already have the posts that we want to show
if (!focusedPostId) {
- const loadedPostCount = state.entities.posts.postsInChannel[channelId].length;
+ const postsInChannel = state.entities.posts.postsInChannel[channelId] || [];
+ const loadedPostCount = postsInChannel.length;
const desiredPostVisibility = currentPostVisibility + ViewTypes.POST_VISIBILITY_CHUNK_SIZE;
if (loadedPostCount >= desiredPostVisibility) {
diff --git a/app/actions/views/login.js b/app/actions/views/login.js
index eb69aa0e6..f798f9d39 100644
--- a/app/actions/views/login.js
+++ b/app/actions/views/login.js
@@ -3,7 +3,7 @@
import {getDataRetentionPolicy} from 'mattermost-redux/actions/general';
import {GeneralTypes} from 'mattermost-redux/action_types';
-import {Client, Client4} from 'mattermost-redux/client';
+import {Client4} from 'mattermost-redux/client';
import {ViewTypes} from 'app/constants';
@@ -39,9 +39,6 @@ export function handleSuccessfulLogin() {
}
}, getState);
- Client.setToken(token);
- Client.setUrl(url);
-
if (config.DataRetentionEnableMessageDeletion && config.DataRetentionEnableMessageDeletion === 'true' &&
license.IsLicensed === 'true' && license.DataRetention === 'true') {
getDataRetentionPolicy()(dispatch, getState);
diff --git a/app/components/root/index.js b/app/components/root/index.js
index d13e6a873..55dc149ff 100644
--- a/app/components/root/index.js
+++ b/app/components/root/index.js
@@ -3,7 +3,7 @@
import {connect} from 'react-redux';
-import {Client, Client4} from 'mattermost-redux/client';
+import {Client4} from 'mattermost-redux/client';
import {getCurrentChannelId} from 'mattermost-redux/selectors/entities/channels';
import {getCurrentUrl} from 'mattermost-redux/selectors/entities/general';
@@ -15,7 +15,6 @@ import Root from './root';
function mapStateToProps(state) {
const locale = getCurrentLocale(state);
- Client.setLocale(locale);
Client4.setAcceptLanguage(locale);
return {
diff --git a/app/mattermost.js b/app/mattermost.js
index c672344ad..d0ef66517 100644
--- a/app/mattermost.js
+++ b/app/mattermost.js
@@ -23,9 +23,9 @@ import {General} from 'mattermost-redux/constants';
import {setAppState, setDeviceToken, setServerVersion} from 'mattermost-redux/actions/general';
import {markChannelAsRead} from 'mattermost-redux/actions/channels';
import {logError} from 'mattermost-redux/actions/errors';
-import {logout} from 'mattermost-redux/actions/users';
+import {loadMe, logout} from 'mattermost-redux/actions/users';
import {close as closeWebSocket} from 'mattermost-redux/actions/websocket';
-import {Client, Client4} from 'mattermost-redux/client';
+import {Client4} from 'mattermost-redux/client';
import EventEmitter from 'mattermost-redux/utils/event_emitter';
import {
@@ -53,58 +53,41 @@ import mattermostBucket from 'app/mattermost_bucket';
import mattermostManaged from 'app/mattermost_managed';
import {deleteFileCache} from 'app/utils/file';
import {init as initAnalytics} from 'app/utils/segment';
-import {
- captureException,
- initializeSentry,
- LOGGER_JAVASCRIPT,
- LOGGER_NATIVE
-} from 'app/utils/sentry';
+import {captureException, initializeSentry, LOGGER_JAVASCRIPT, LOGGER_NATIVE} from 'app/utils/sentry';
+import tracker from 'app/utils/time_tracker';
import {stripTrailingSlashes} from 'app/utils/url';
-import Config from 'assets/config';
+import LocalConfig from 'assets/config';
const {StatusBarManager} = NativeModules;
const AUTHENTICATION_TIMEOUT = 5 * 60 * 1000;
export default class Mattermost {
constructor() {
- if (Platform.OS === 'android') {
- // This is to remove the warnings for the scaleY property used in android.
- // The property is necessary because some Android devices won't render the posts
- // properly if we use transform: {scaleY: -1} in the stylesheet.
- console.ignoredYellowBox = ['`scaleY`']; //eslint-disable-line
- }
this.isConfigured = false;
this.allowOtherServers = true;
+ this.startAppFromPushNotification = false;
+ this.emmEnabled = false;
+ Client4.setUserAgent(DeviceInfo.getUserAgent());
Orientation.unlockAllOrientations();
-
initializeSentry();
-
this.store = configureStore(initialState);
+ registerScreens(this.store, Provider);
+
this.unsubscribeFromStore = this.store.subscribe(this.listenForHydration);
AppState.addEventListener('change', this.handleAppStateChange);
- EventEmitter.on(General.CONFIG_CHANGED, this.handleConfigChanged);
- EventEmitter.on(NavigationTypes.NAVIGATION_RESET, this.handleReset);
- EventEmitter.on(General.DEFAULT_CHANNEL, this.handleResetDisplayName);
+ EventEmitter.on(General.CONFIG_CHANGED, this.handleServerConfigChanged);
+ EventEmitter.on(NavigationTypes.NAVIGATION_RESET, this.handleLogout);
+ EventEmitter.on(General.DEFAULT_CHANNEL, this.handleResetChannelDisplayName);
EventEmitter.on(NavigationTypes.RESTART_APP, this.restartApp);
Orientation.addOrientationListener(this.orientationDidChange);
mattermostManaged.addEventListener('managedConfigDidChange', this.handleManagedConfig);
- this.handleAppStateChange(AppState.currentState);
- Client4.setUserAgent(DeviceInfo.getUserAgent());
-
if (Platform.OS === 'ios') {
StatusBarSizeIOS.addEventListener('willChange', this.handleStatusBarHeightChange);
- StatusBarManager.getHeight(
- (data) => {
- this.handleStatusBarHeightChange(data.height);
- }
- );
}
- registerScreens(this.store, Provider);
-
setJSExceptionHandler(this.errorHandler, false);
setNativeExceptionHandler(this.nativeErrorHandler, false);
}
@@ -115,7 +98,10 @@ export default class Mattermost {
const intl = this.getIntl();
closeWebSocket()(this.store.dispatch, this.store.getState);
- logError(e)(this.store.dispatch);
+
+ if (Client4.getUrl()) {
+ logError(e)(this.store.dispatch);
+ }
if (isFatal) {
Alert.alert(
@@ -151,7 +137,7 @@ export default class Mattermost {
};
configureAnalytics = (config) => {
- if (config && config.DiagnosticsEnabled === 'true' && config.DiagnosticId && Config.SegmentApiKey) {
+ if (config && config.DiagnosticsEnabled === 'true' && config.DiagnosticId && LocalConfig.SegmentApiKey) {
initAnalytics(config);
} else {
global.analytics = null;
@@ -172,37 +158,39 @@ export default class Mattermost {
handleAppStateChange = async (appState) => {
const {dispatch, getState} = this.store;
const isActive = appState === 'active';
+
setAppState(isActive)(dispatch, getState);
- if (isActive && this.shouldRelaunchonActive) {
+ if (isActive && this.shouldRelaunchWhenActive) {
+ // This handles when the app was started in the background
+ // cause of an iOS push notification reply
this.launchApp();
- this.shouldRelaunchonActive = false;
- } else {
+ this.shouldRelaunchWhenActive = false;
+ } else if (!isActive && !this.inBackgroundSince) {
+ // When the app is sent to the background we set the time when that happens
+ // and perform a data clean up to improve on performance
+ this.inBackgroundSince = Date.now();
+ dispatch({type: ViewTypes.DATA_CLEANUP, payload: getState()});
+ } else if (isActive && this.inBackgroundSince && (Date.now() - this.inBackgroundSince) >= AUTHENTICATION_TIMEOUT && this.emmEnabled) {
+ // Once the app becomes active after more than 5 minutes in the background and is controlled by an EMM
try {
- if (!isActive && !this.inBackgroundSince) {
- this.inBackgroundSince = Date.now();
- dispatch({type: ViewTypes.DATA_CLEANUP, payload: getState()});
- } else if (isActive && this.inBackgroundSince && (Date.now() - this.inBackgroundSince) >= AUTHENTICATION_TIMEOUT) {
- this.inBackgroundSince = null;
-
- if (this.mdmEnabled) {
- const config = await mattermostManaged.getConfig();
- const authNeeded = config.inAppPinCode && config.inAppPinCode === 'true';
- if (authNeeded) {
- const authenticated = await this.handleAuthentication(config.vendor);
- if (!authenticated) {
- mattermostManaged.quitApp();
- }
- }
+ const config = await mattermostManaged.getConfig();
+ const authNeeded = config.inAppPinCode && config.inAppPinCode === 'true';
+ if (authNeeded) {
+ const authenticated = await this.handleAuthentication(config.vendor);
+ if (!authenticated) {
+ mattermostManaged.quitApp();
}
- } else if (isActive) {
- this.inBackgroundSince = null;
- Keyboard.dismiss();
}
} catch (error) {
// do nothing
}
}
+
+ if (isActive) {
+ this.inBackgroundSince = null;
+ Keyboard.dismiss();
+ }
};
handleAuthentication = async (vendor) => {
@@ -211,7 +199,7 @@ export default class Mattermost {
const intl = this.getIntl();
if (isSecured) {
try {
- mattermostBucket.set('emm', vendor, Config.AppGroupId);
+ mattermostBucket.set('emm', vendor, LocalConfig.AppGroupId);
await mattermostManaged.authenticate({
reason: intl.formatMessage({
id: 'mobile.managed.secured_by',
@@ -229,20 +217,20 @@ export default class Mattermost {
return true;
};
- handleConfigChanged = async (serverVersion) => {
+ handleServerConfigChanged = async (serverVersion) => {
const {dispatch, getState} = this.store;
const version = serverVersion.match(/^[0-9]*.[0-9]*.[0-9]*(-[a-zA-Z0-9.-]*)?/g)[0];
const intl = this.getIntl();
const state = getState();
if (serverVersion) {
- if (semver.valid(version) && semver.lt(version, Config.MinServerVersion)) {
+ if (semver.valid(version) && semver.lt(version, LocalConfig.MinServerVersion)) {
Alert.alert(
intl.formatMessage({id: 'mobile.server_upgrade.title', defaultMessage: 'Server upgrade required'}),
intl.formatMessage({id: 'mobile.server_upgrade.description', defaultMessage: '\nA server upgrade is required to use the Mattermost app. Please ask your System Administrator for details.\n'}),
[{
text: intl.formatMessage({id: 'mobile.server_upgrade.button', defaultMessage: 'OK'}),
- onPress: this.handleVersionUpgrade
+ onPress: this.handleServerVersionUpgradeNeeded
}],
{cancelable: false}
);
@@ -265,15 +253,15 @@ export default class Mattermost {
let serverUrl = null;
let username = null;
- if (Config.AutoSelectServerUrl) {
- handleServerUrlChanged(Config.DefaultServerUrl)(dispatch, getState);
+ if (LocalConfig.AutoSelectServerUrl) {
+ handleServerUrlChanged(LocalConfig.DefaultServerUrl)(dispatch, getState);
this.allowOtherServers = false;
}
try {
const config = await mattermostManaged.getConfig();
- if (config) {
- this.mdmEnabled = true;
+ if (config && Object.keys(config).length) {
+ this.emmEnabled = true;
authNeeded = config.inAppPinCode && config.inAppPinCode === 'true';
blurApplicationScreen = config.blurApplicationScreen && config.blurApplicationScreen === 'true';
jailbreakProtection = config.jailbreakProtection && config.jailbreakProtection === 'true';
@@ -287,74 +275,72 @@ export default class Mattermost {
this.allowOtherServers = false;
}
}
+
+ if (jailbreakProtection) {
+ const isTrusted = mattermostManaged.isTrustedDevice();
+
+ if (!isTrusted) {
+ const intl = this.getIntl();
+ Alert.alert(
+ intl.formatMessage({
+ id: 'mobile.managed.blocked_by',
+ defaultMessage: 'Blocked by {vendor}'
+ }, {vendor}),
+ intl.formatMessage({
+ id: 'mobile.managed.jailbreak',
+ defaultMessage: 'Jailbroken devices are not trusted by {vendor}, please exit the app.'
+ }, {vendor}),
+ [{
+ text: intl.formatMessage({id: 'mobile.managed.exit', defaultMessage: 'Exit'}),
+ style: 'destructive',
+ onPress: () => {
+ mattermostManaged.quitApp();
+ }
+ }],
+ {cancelable: false}
+ );
+ return false;
+ }
+ }
+
+ if (authNeeded && !serverConfig) {
+ if (Platform.OS === 'android') {
+ //Start a fake app as we need at least one activity for android
+ await this.startFakeApp();
+ }
+ const authenticated = await this.handleAuthentication(vendor);
+ if (!authenticated) {
+ return false;
+ }
+ }
+
+ if (blurApplicationScreen) {
+ mattermostManaged.blurAppScreen(true);
+ }
+
+ if (serverUrl) {
+ handleServerUrlChanged(serverUrl)(dispatch, getState);
+ }
+
+ if (username) {
+ handleLoginIdChanged(username)(dispatch, getState);
+ }
}
} catch (error) {
return true;
}
- if (this.mdmEnabled) {
- if (jailbreakProtection) {
- const isTrusted = mattermostManaged.isTrustedDevice();
-
- if (!isTrusted) {
- const intl = this.getIntl();
- Alert.alert(
- intl.formatMessage({
- id: 'mobile.managed.blocked_by',
- defaultMessage: 'Blocked by {vendor}'
- }, {vendor}),
- intl.formatMessage({
- id: 'mobile.managed.jailbreak',
- defaultMessage: 'Jailbroken devices are not trusted by {vendor}, please exit the app.'
- }, {vendor}),
- [{
- text: intl.formatMessage({id: 'mobile.managed.exit', defaultMessage: 'Exit'}),
- style: 'destructive',
- onPress: () => {
- mattermostManaged.quitApp();
- }
- }],
- {cancelable: false}
- );
- return false;
- }
- }
-
- if (authNeeded && !serverConfig) {
- if (Platform.OS === 'android') {
- //Start a fake app as we need at least one activity for android
- await this.startFakeApp();
- }
- const authenticated = await this.handleAuthentication(vendor);
- if (!authenticated) {
- return false;
- }
- }
-
- if (blurApplicationScreen) {
- mattermostManaged.blurAppScreen(true);
- }
-
- if (serverUrl) {
- handleServerUrlChanged(serverUrl)(dispatch, getState);
- }
-
- if (username) {
- handleLoginIdChanged(username)(dispatch, getState);
- }
- }
-
return true;
};
- handleReset = () => {
+ handleLogout = () => {
this.appStarted = false;
deleteFileCache();
this.resetBadgeAndVersion();
this.startApp('fade');
};
- handleResetDisplayName = (displayName) => {
+ handleResetChannelDisplayName = (displayName) => {
this.store.dispatch(setChannelDisplayName(displayName));
};
@@ -362,48 +348,65 @@ export default class Mattermost {
this.store.dispatch(setStatusBarHeight(nextStatusBarHeight));
};
- handleVersionUpgrade = async () => {
+ handleServerVersionUpgradeNeeded = async () => {
const {dispatch, getState} = this.store;
- Client4.serverVersion = '';
- PushNotifications.setApplicationIconBadgeNumber(0);
+ this.resetBadgeAndVersion();
if (getState().entities.general.credentials.token) {
InteractionManager.runAfterInteractions(() => {
logout()(dispatch, getState);
});
- } else {
- this.resetBadgeAndVersion();
}
};
// We need to wait for hydration to occur before load the router.
listenForHydration = () => {
- const state = this.store.getState();
+ const {dispatch, getState} = this.store;
+ const state = getState();
if (!this.isConfigured) {
this.configurePushNotifications();
}
if (state.views.root.hydrationComplete) {
+ const orientation = Orientation.getInitialOrientation();
+ const {credentials, config} = state.entities.general;
+ const {currentUserId} = state.entities.users;
+ const isNotActive = AppState.currentState !== 'active';
+ const notification = PushNotifications.getNotification();
+
this.unsubscribeFromStore();
- const orientation = Orientation.getInitialOrientation();
+ if (this.deviceToken) {
+ // If the deviceToken is set we need to dispatch it to the redux store
+ setDeviceToken(this.deviceToken)(dispatch, getState);
+ }
+
if (orientation) {
this.orientationDidChange(orientation);
}
- const {config} = state.entities.general;
if (config) {
this.configureAnalytics(config);
}
- const {currentUserId} = state.entities.users;
+ if (credentials.token && credentials.url) {
+ Client4.setToken(credentials.token);
+ Client4.setUrl(stripTrailingSlashes(credentials.url));
+ }
+
if (currentUserId) {
Client4.setUserId(currentUserId);
}
- const isNotActive = AppState.currentState !== 'active';
- const notification = PushNotifications.getNotification();
+ if (Platform.OS === 'ios') {
+ StatusBarManager.getHeight(
+ (data) => {
+ this.handleStatusBarHeightChange(data.height);
+ }
+ );
+ }
+
if (notification || this.replyNotificationData) {
// If we have a notification means that the app was started cause of a reply
// and the app was not sitting in the background nor opened
@@ -416,6 +419,10 @@ export default class Mattermost {
if (Platform.OS === 'android') {
// In case of Android we need to handle the bridge being initialized by HeadlessJS
Promise.resolve(Navigation.isAppLaunched()).then((appLaunched) => {
+ if (this.startAppFromPushNotification) {
+ return;
+ }
+
if (appLaunched) {
this.launchApp(); // App is launched -> show UI
} else {
@@ -424,7 +431,7 @@ export default class Mattermost {
});
} else if (isNotActive) {
// for IOS replying from push notification starts the app in the background
- this.shouldRelaunchonActive = true;
+ this.shouldRelaunchWhenActive = true;
this.startFakeApp();
} else {
this.launchApp();
@@ -445,19 +452,23 @@ export default class Mattermost {
prefix = General.PUSH_NOTIFY_ANDROID_REACT_NATIVE;
}
- setDeviceToken(`${prefix}:${data.token}`)(dispatch, getState);
+ const state = getState();
+ const token = `${prefix}:${data.token}`;
+ if (state.views.root.hydrationComplete) {
+ setDeviceToken(token)(dispatch, getState);
+ } else {
+ this.deviceToken = token;
+ }
};
onPushNotification = (deviceNotification) => {
const {dispatch, getState} = this.store;
const state = getState();
const {token, url} = state.entities.general.credentials;
- let startAppFromPushNotification = false;
// mark the app as started as soon as possible
- if (token && url && !this.appStarted) {
- this.appStarted = true;
- startAppFromPushNotification = true;
+ if (!this.appStarted && Platform.OS !== 'ios') {
+ this.startAppFromPushNotification = true;
}
const {data, foreground, message, userInfo, userInteraction} = deviceNotification;
@@ -476,18 +487,16 @@ export default class Mattermost {
EventEmitter.emit(ViewTypes.NOTIFICATION_IN_APP, notification);
} else if (userInteraction && !notification.localNotification) {
EventEmitter.emit('close_channel_drawer');
- if (startAppFromPushNotification) {
- Client.setToken(token);
+ if (this.startAppFromPushNotification) {
Client4.setToken(token);
Client4.setUrl(stripTrailingSlashes(url));
- Client.setUrl(stripTrailingSlashes(url));
}
InteractionManager.runAfterInteractions(async () => {
await loadFromPushNotification(notification)(dispatch, getState);
- if (startAppFromPushNotification) {
- this.startAppFromPushNotification();
+ if (this.startAppFromPushNotification) {
+ this.launchApp();
} else {
EventEmitter.emit(ViewTypes.NOTIFICATION_TAPPED);
}
@@ -516,7 +525,7 @@ export default class Mattermost {
Client4.setUrl(state.entities.general.credentials.url);
}
- if (!Client.getToken()) {
+ if (!Client4.getToken()) {
// Make sure the Client has the server token set
Client4.setToken(state.entities.general.credentials.token);
}
@@ -554,9 +563,7 @@ export default class Mattermost {
resetBadgeAndVersion = () => {
const {dispatch, getState} = this.store;
Client4.serverVersion = '';
- Client.serverVersion = '';
- Client.token = null;
- Client4.userId = '';
+ Client4.setUserId('');
PushNotifications.setApplicationIconBadgeNumber(0);
PushNotifications.cancelAllLocalNotifications();
setServerVersion('')(dispatch, getState);
@@ -567,6 +574,7 @@ export default class Mattermost {
const {dispatch, getState} = this.store;
await loadConfigAndLicense()(dispatch, getState);
+ await loadMe()(dispatch, getState);
this.appStarted = false;
this.startApp('fade');
};
@@ -588,18 +596,29 @@ export default class Mattermost {
statusBarHidden: false,
statusBarHideWithNavBar: false
}
- },
- passProps: {
- justInit: true
}
});
};
startApp = (animationType = 'none') => {
if (!this.appStarted) {
+ const {dispatch, getState} = this.store;
+ const {entities} = getState();
+ let screen = 'SelectServer';
+
+ if (entities) {
+ const {credentials} = entities.general;
+
+ if (credentials.token && credentials.url) {
+ screen = 'Channel';
+ tracker.initialLoad = Date.now();
+ loadMe()(dispatch, getState);
+ }
+ }
+
Navigation.startSingleScreenApp({
screen: {
- screen: 'Root',
+ screen,
navigatorStyle: {
navBarHidden: true,
statusBarHidden: false,
@@ -617,28 +636,7 @@ export default class Mattermost {
});
this.appStarted = true;
+ this.startAppFromPushNotification = false;
}
};
-
- startAppFromPushNotification = () => {
- Navigation.startSingleScreenApp({
- screen: {
- screen: 'Channel',
- navigatorStyle: {
- navBarHidden: true,
- statusBarHidden: false,
- statusBarHideWithNavBar: false,
- screenBackgroundColor: 'transparent'
- }
- },
- passProps: {
- allowOtherServers: this.allowOtherServers
- },
- appStyle: {
- orientation: 'auto'
- },
- animationType: 'none'
- });
- this.appStarted = false;
- };
}
diff --git a/app/screens/channel/channel.js b/app/screens/channel/channel.js
index 1f05bf966..556fa9352 100644
--- a/app/screens/channel/channel.js
+++ b/app/screens/channel/channel.js
@@ -60,6 +60,8 @@ class Channel extends PureComponent {
if (this.props.currentTeamId) {
this.loadChannels(this.props.currentTeamId);
+ } else {
+ this.props.actions.selectFirstAvailableTeam();
}
}
diff --git a/app/screens/index.js b/app/screens/index.js
index 6488414b6..053d1f428 100644
--- a/app/screens/index.js
+++ b/app/screens/index.js
@@ -22,7 +22,6 @@ import EditChannel from 'app/screens/edit_channel';
import EditPost from 'app/screens/edit_post';
import EditProfile from 'app/screens/edit_profile';
import ImagePreview from 'app/screens/image_preview';
-import LoadTeam from 'app/screens/load_team';
import Login from 'app/screens/login';
import LoginOptions from 'app/screens/login_options';
import Mfa from 'app/screens/mfa';
@@ -78,7 +77,6 @@ export function registerScreens(store, Provider) {
Navigation.registerComponent('EditPost', () => wrapWithContextProvider(EditPost), store, Provider);
Navigation.registerComponent('EditProfile', () => wrapWithContextProvider(EditProfile), store, Provider);
Navigation.registerComponent('ImagePreview', () => wrapWithContextProvider(ImagePreview), store, Provider);
- Navigation.registerComponent('LoadTeam', () => wrapWithContextProvider(LoadTeam, false), store, Provider);
Navigation.registerComponent('Login', () => wrapWithContextProvider(Login), store, Provider);
Navigation.registerComponent('LoginOptions', () => wrapWithContextProvider(LoginOptions), store, Provider);
Navigation.registerComponent('MFA', () => wrapWithContextProvider(Mfa), store, Provider);
diff --git a/app/screens/load_team/index.js b/app/screens/load_team/index.js
deleted file mode 100644
index d34c0aeef..000000000
--- a/app/screens/load_team/index.js
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
-// See License.txt for license information.
-
-import {bindActionCreators} from 'redux';
-import {connect} from 'react-redux';
-
-import {getTeams} from 'mattermost-redux/actions/teams';
-import {getCurrentTeam} from 'mattermost-redux/selectors/entities/teams';
-
-import {handleTeamChange} from 'app/actions/views/select_team';
-import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
-
-import LoadTeam from './load_team';
-
-function mapStateToProps(state) {
- return {
- config: state.entities.general.config,
- theme: getTheme(state),
- teams: state.entities.teams.teams,
- currentTeam: getCurrentTeam(state),
- myMembers: state.entities.teams.myMembers,
- notification: state.views.notification
- };
-}
-
-function mapDispatchToProps(dispatch) {
- return {
- actions: bindActionCreators({
- getTeams,
- handleTeamChange
- }, dispatch)
- };
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(LoadTeam);
diff --git a/app/screens/load_team/load_team.js b/app/screens/load_team/load_team.js
deleted file mode 100644
index dcd2706c0..000000000
--- a/app/screens/load_team/load_team.js
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
-// See License.txt for license information.
-
-import {PureComponent} from 'react';
-import PropTypes from 'prop-types';
-
-import EventEmitter from 'mattermost-redux/utils/event_emitter';
-
-import {NavigationTypes} from 'app/constants';
-
-export default class LoadTeam extends PureComponent {
- static propTypes = {
- actions: PropTypes.shape({
- getTeams: PropTypes.func.isRequired,
- handleTeamChange: PropTypes.func.isRequired
- }).isRequired,
- currentTeam: PropTypes.object,
- myMembers: PropTypes.object.isRequired,
- navigator: PropTypes.object,
- teams: PropTypes.object.isRequired,
- theme: PropTypes.object.isRequired
- };
-
- componentDidMount() {
- const {currentTeam, myMembers, teams} = this.props;
- if (currentTeam && myMembers[currentTeam.id]) {
- return this.onSelectTeam(currentTeam);
- }
-
- return this.selectFirstTeam(teams, myMembers);
- }
-
- selectFirstTeam(allTeams, myMembers) {
- const teams = Object.keys(myMembers).map((key) => allTeams[key]);
- const firstTeam = Object.values(teams).sort((a, b) => a.display_name.localeCompare(b.display_name))[0];
-
- if (firstTeam) {
- this.onSelectTeam(firstTeam);
- } else {
- const {getTeams} = this.props.actions;
- getTeams().then(() => {
- EventEmitter.emit(NavigationTypes.NAVIGATION_NO_TEAMS);
- });
- }
- }
-
- onSelectTeam(team) {
- const {handleTeamChange} = this.props.actions;
- handleTeamChange(team.id).then(this.goToChannelView);
- }
-
- goToChannelView = () => {
- const {navigator, theme} = this.props;
-
- navigator.resetTo({
- screen: 'Channel',
- animated: true,
- animationType: 'fade',
- navigatorStyle: {
- navBarHidden: true,
- statusBarHidden: false,
- statusBarHideWithNavBar: false,
- screenBackgroundColor: theme.centerChannelBg
- }
- });
- };
-
- render() {
- return null;
- }
-}
diff --git a/app/screens/login/login.js b/app/screens/login/login.js
index 9f234431b..062b92577 100644
--- a/app/screens/login/login.js
+++ b/app/screens/login/login.js
@@ -77,7 +77,7 @@ class Login extends PureComponent {
}
goToLoadTeam = (expiresAt) => {
- const {intl, navigator, theme} = this.props;
+ const {intl, navigator} = this.props;
tracker.initialLoad = Date.now();
if (expiresAt) {
@@ -94,17 +94,17 @@ class Login extends PureComponent {
}
navigator.resetTo({
- screen: 'LoadTeam',
+ screen: 'Channel',
title: '',
animated: false,
backButtonTitle: '',
navigatorStyle: {
+ animated: true,
+ animationType: 'fade',
+ navBarHidden: true,
statusBarHidden: false,
statusBarHideWithNavBar: false,
- navBarTextColor: theme.sidebarHeaderTextColor,
- navBarBackgroundColor: theme.sidebarHeaderBg,
- navBarButtonColor: theme.sidebarHeaderTextColor,
- screenBackgroundColor: theme.centerChannelBg
+ screenBackgroundColor: 'transparent'
}
});
};
diff --git a/app/screens/root/index.js b/app/screens/root/index.js
index e6ec7ecc7..49e2db631 100644
--- a/app/screens/root/index.js
+++ b/app/screens/root/index.js
@@ -1,29 +1,12 @@
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-import {bindActionCreators} from 'redux';
-import {connect} from 'react-redux';
+import React from 'react';
-import {loadMe} from 'mattermost-redux/actions/users';
-import {getCurrentUser} from 'mattermost-redux/selectors/entities/users';
-import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
+import Loading from 'app/components/loading';
-import Root from './root';
-
-function mapStateToProps(state) {
- return {
- currentUser: getCurrentUser(state),
- credentials: state.entities.general.credentials,
- theme: getTheme(state)
- };
+function Root() {
+ return ;
}
-function mapDispatchToProps(dispatch) {
- return {
- actions: bindActionCreators({
- loadMe
- }, dispatch)
- };
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(Root);
+export default Root;
diff --git a/app/screens/root/root.js b/app/screens/root/root.js
deleted file mode 100644
index 395e50666..000000000
--- a/app/screens/root/root.js
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
-// See License.txt for license information.
-
-import React, {Component} from 'react';
-import PropTypes from 'prop-types';
-
-import {Client, Client4} from 'mattermost-redux/client';
-
-import Loading from 'app/components/loading';
-import {stripTrailingSlashes} from 'app/utils/url';
-import tracker from 'app/utils/time_tracker';
-
-export default class Root extends Component {
- static propTypes = {
- actions: PropTypes.shape({
- loadMe: PropTypes.func.isRequired
- }).isRequired,
- allowOtherServers: PropTypes.bool,
- currentUser: PropTypes.object,
- credentials: PropTypes.object,
- justInit: PropTypes.bool,
- navigator: PropTypes.object,
- theme: PropTypes.object
- };
-
- shouldComponentUpdate(nextProps) {
- if (nextProps.credentials !== this.props.credentials) {
- return true;
- }
- return false;
- }
-
- componentDidMount() {
- if (!this.props.justInit) {
- this.loadStoreAndScene();
- }
- }
-
- goToLoadTeam = () => {
- const {navigator, theme} = this.props;
- tracker.initialLoad = Date.now();
- navigator.resetTo({
- screen: 'LoadTeam',
- title: '',
- animated: true,
- animationType: 'fade',
- backButtonTitle: '',
- navigatorStyle: {
- statusBarHidden: false,
- statusBarHideWithNavBar: false,
- navBarTextColor: theme.sidebarHeaderTextColor,
- navBarBackgroundColor: theme.sidebarHeaderBg,
- navBarButtonColor: theme.sidebarHeaderTextColor,
- screenBackgroundColor: theme.centerChannelBg
- }
- });
- };
-
- goToSelectServer = () => {
- const {allowOtherServers, navigator} = this.props;
-
- navigator.resetTo({
- screen: 'SelectServer',
- animated: true,
- animationType: 'fade',
- navigatorStyle: {
- navBarHidden: true,
- navBarBackgroundColor: 'black',
- statusBarHidden: false,
- statusBarHideWithNavBar: false
- },
- passProps: {
- allowOtherServers
- }
- });
- };
-
- loadStoreAndScene = () => {
- const {actions, currentUser, credentials} = this.props;
- const {loadMe} = actions;
- if (credentials.token && credentials.url) {
- Client.setToken(credentials.token);
- Client4.setToken(credentials.token);
- Client4.setUrl(stripTrailingSlashes(credentials.url));
- Client.setUrl(stripTrailingSlashes(credentials.url));
-
- if (currentUser) {
- loadMe();
- this.goToLoadTeam();
- } else {
- loadMe().then(this.goToLoadTeam).catch(this.goToLoadTeam);
- }
- } else {
- this.goToSelectServer();
- }
- };
-
- render() {
- return ;
- }
-}
diff --git a/app/screens/select_server/select_server.js b/app/screens/select_server/select_server.js
index d23973cc9..71e121701 100644
--- a/app/screens/select_server/select_server.js
+++ b/app/screens/select_server/select_server.js
@@ -19,7 +19,7 @@ import {
import Button from 'react-native-button';
import urlParse from 'url-parse';
-import {Client, Client4} from 'mattermost-redux/client';
+import {Client4} from 'mattermost-redux/client';
import Config from 'assets/config';
import ErrorText from 'app/components/error_text';
@@ -224,7 +224,6 @@ class SelectServer extends PureComponent {
});
Client4.setUrl(url);
- Client.setUrl(url);
handleServerUrlChanged(url);
let cancel = false;
diff --git a/app/screens/sso/sso.js b/app/screens/sso/sso.js
index e9053eb3a..a1b1b8dc0 100644
--- a/app/screens/sso/sso.js
+++ b/app/screens/sso/sso.js
@@ -82,7 +82,7 @@ class SSO extends PureComponent {
}
goToLoadTeam = (expiresAt) => {
- const {intl, navigator, theme} = this.props;
+ const {intl, navigator} = this.props;
tracker.initialLoad = Date.now();
if (expiresAt) {
@@ -99,17 +99,17 @@ class SSO extends PureComponent {
}
navigator.resetTo({
- screen: 'LoadTeam',
+ screen: 'Channel',
title: '',
animated: false,
backButtonTitle: '',
navigatorStyle: {
+ animated: true,
+ animationType: 'fade',
+ navBarHidden: true,
statusBarHidden: false,
statusBarHideWithNavBar: false,
- navBarTextColor: theme.sidebarHeaderTextColor,
- navBarBackgroundColor: theme.sidebarHeaderBg,
- navBarButtonColor: theme.sidebarHeaderTextColor,
- screenBackgroundColor: theme.centerChannelBg
+ screenBackgroundColor: 'transparent'
}
});
};