* Remove fix for MM-9233 * MM-15774 Add native code to support RNN v2 on iOS * Android changes for RNN v2 upgrade The activity visibility handling of NotificationsLifecycleFacade is no longer needed in RNN v2. I've moved the lifecycle callbacks we use for handling managed config into ManagedActivityLifecycleCallbacks.java and registered them in MainApplication's onCreate. Also, I've moved and updated the loading and getting of the managed config into MainApplication * Update moduleNames and modulePaths * Use TAG in restrictionsReceiver * Set launch screen onCreate * Comment out registerActivityLifecycleCallbacks for now * Remove setSoftInputMode call as it's handled in the manifest * Remove clearHostOnActivityDestroy as that fix is no longer needed * Rename to canLaunchEntry * Remove replacement of super.onBackPressed() * Remove react-navigation from packager files
315 lines
9.9 KiB
JavaScript
315 lines
9.9 KiB
JavaScript
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
/* eslint-disable global-require*/
|
|
import {Linking, NativeModules, Platform, Text} from 'react-native';
|
|
import AsyncStorage from '@react-native-community/async-storage';
|
|
import {setGenericPassword, getGenericPassword, resetGenericPassword} from 'react-native-keychain';
|
|
|
|
import {loadMe} from 'mattermost-redux/actions/users';
|
|
import {Client4} from 'mattermost-redux/client';
|
|
|
|
import {resetToChannel, resetToSelectServer} from 'app/actions/navigation';
|
|
import {setDeepLinkURL} from 'app/actions/views/root';
|
|
import tracker from 'app/utils/time_tracker';
|
|
import {getCurrentLocale} from 'app/selectors/i18n';
|
|
|
|
import {getTranslations as getLocalTranslations} from 'app/i18n';
|
|
import {store, handleManagedConfig, initializeModules} from 'app/mattermost';
|
|
import avoidNativeBridge from 'app/utils/avoid_native_bridge';
|
|
import {setCSRFFromCookie} from 'app/utils/security';
|
|
|
|
const {Initialization} = NativeModules;
|
|
|
|
const TOOLBAR_BACKGROUND = 'TOOLBAR_BACKGROUND';
|
|
const TOOLBAR_TEXT_COLOR = 'TOOLBAR_TEXT_COLOR';
|
|
const APP_BACKGROUND = 'APP_BACKGROUND';
|
|
|
|
export default class App {
|
|
constructor() {
|
|
// Usage: app.js
|
|
this.shouldRelaunchWhenActive = false;
|
|
this.inBackgroundSince = null;
|
|
|
|
// Usage: screen/entry.js
|
|
this.startAppFromPushNotification = false;
|
|
this.isNotificationsConfigured = false;
|
|
this.allowOtherServers = true;
|
|
this.canLaunchEntry = true;
|
|
this.emmEnabled = false;
|
|
this.performingEMMAuthentication = false;
|
|
this.translations = null;
|
|
this.toolbarBackground = null;
|
|
this.toolbarTextColor = null;
|
|
this.appBackground = null;
|
|
|
|
// Usage utils/push_notifications.js
|
|
this.replyNotificationData = null;
|
|
this.deviceToken = null;
|
|
|
|
// Usage credentials
|
|
this.currentUserId = null;
|
|
this.token = null;
|
|
this.url = null;
|
|
|
|
// Usage deeplinking
|
|
Linking.addEventListener('url', this.handleDeepLink);
|
|
|
|
this.setFontFamily();
|
|
this.getStartupThemes();
|
|
this.getAppCredentials();
|
|
}
|
|
|
|
setFontFamily = () => {
|
|
// Set a global font for Android
|
|
if (Platform.OS === 'android') {
|
|
const defaultFontFamily = {
|
|
style: {
|
|
fontFamily: 'Roboto',
|
|
},
|
|
};
|
|
const TextRender = Text.render;
|
|
const initialDefaultProps = Text.defaultProps;
|
|
Text.defaultProps = {
|
|
...initialDefaultProps,
|
|
...defaultFontFamily,
|
|
};
|
|
Text.render = function render(props, ...args) {
|
|
const oldProps = props;
|
|
let newProps = {...props, style: [defaultFontFamily.style, props.style]};
|
|
try {
|
|
return Reflect.apply(TextRender, this, [newProps, ...args]);
|
|
} finally {
|
|
newProps = oldProps;
|
|
}
|
|
};
|
|
}
|
|
};
|
|
|
|
getTranslations = () => {
|
|
if (this.translations) {
|
|
return this.translations;
|
|
}
|
|
|
|
const state = store.getState();
|
|
const locale = getCurrentLocale(state);
|
|
|
|
this.translations = getLocalTranslations(locale);
|
|
return this.translations;
|
|
};
|
|
|
|
getAppCredentials = async () => {
|
|
try {
|
|
const credentials = await avoidNativeBridge(
|
|
() => {
|
|
return Initialization.credentialsExist;
|
|
},
|
|
() => {
|
|
return Initialization.credentials;
|
|
},
|
|
() => {
|
|
this.waitForRehydration = true;
|
|
return getGenericPassword();
|
|
}
|
|
);
|
|
|
|
if (credentials) {
|
|
const usernameParsed = credentials.username.split(',');
|
|
const passwordParsed = credentials.password.split(',');
|
|
|
|
// username == deviceToken, currentUserId
|
|
// password == token, url
|
|
if (usernameParsed.length === 2 && passwordParsed.length === 2) {
|
|
const [deviceToken, currentUserId] = usernameParsed;
|
|
const [token, url] = passwordParsed;
|
|
|
|
// if for any case the url and the token aren't valid proceed with re-hydration
|
|
if (url && url !== 'undefined' && token && token !== 'undefined') {
|
|
this.deviceToken = deviceToken;
|
|
this.currentUserId = currentUserId;
|
|
this.token = token;
|
|
this.url = url;
|
|
Client4.setUrl(url);
|
|
Client4.setToken(token);
|
|
await setCSRFFromCookie(url);
|
|
} else {
|
|
this.waitForRehydration = true;
|
|
}
|
|
}
|
|
} else {
|
|
this.waitForRehydration = false;
|
|
}
|
|
} catch (error) {
|
|
return null;
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
getStartupThemes = async () => {
|
|
try {
|
|
const [
|
|
toolbarBackground,
|
|
toolbarTextColor,
|
|
appBackground,
|
|
] = await avoidNativeBridge(
|
|
() => {
|
|
return Initialization.themesExist;
|
|
},
|
|
() => {
|
|
return [
|
|
Initialization.toolbarBackground,
|
|
Initialization.toolbarTextColor,
|
|
Initialization.appBackground,
|
|
];
|
|
},
|
|
() => {
|
|
return Promise.all([
|
|
AsyncStorage.getItem(TOOLBAR_BACKGROUND),
|
|
AsyncStorage.getItem(TOOLBAR_TEXT_COLOR),
|
|
AsyncStorage.getItem(APP_BACKGROUND),
|
|
]);
|
|
}
|
|
);
|
|
|
|
if (toolbarBackground) {
|
|
this.toolbarBackground = toolbarBackground;
|
|
this.toolbarTextColor = toolbarTextColor;
|
|
this.appBackground = appBackground;
|
|
}
|
|
} catch (error) {
|
|
return null;
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
setPerformingEMMAuthentication = (authenticating) => {
|
|
this.performingEMMAuthentication = authenticating;
|
|
};
|
|
|
|
setAppCredentials = (deviceToken, currentUserId, token, url) => {
|
|
if (!currentUserId) {
|
|
return;
|
|
}
|
|
|
|
const username = `${deviceToken}, ${currentUserId}`;
|
|
const password = `${token},${url}`;
|
|
|
|
if (this.waitForRehydration) {
|
|
this.waitForRehydration = false;
|
|
this.token = token;
|
|
this.url = url;
|
|
}
|
|
|
|
// Only save to keychain if the url and token are set
|
|
if (url && token) {
|
|
try {
|
|
setGenericPassword(username, password);
|
|
} catch (e) {
|
|
console.warn('could not set credentials', e); //eslint-disable-line no-console
|
|
}
|
|
}
|
|
};
|
|
|
|
setStartupThemes = (toolbarBackground, toolbarTextColor, appBackground) => {
|
|
AsyncStorage.setItem(TOOLBAR_BACKGROUND, toolbarBackground);
|
|
AsyncStorage.setItem(TOOLBAR_TEXT_COLOR, toolbarTextColor);
|
|
AsyncStorage.setItem(APP_BACKGROUND, appBackground);
|
|
};
|
|
|
|
setStartAppFromPushNotification = (startAppFromPushNotification) => {
|
|
this.startAppFromPushNotification = startAppFromPushNotification;
|
|
};
|
|
|
|
setIsNotificationsConfigured = (isNotificationsConfigured) => {
|
|
this.isNotificationsConfigured = isNotificationsConfigured;
|
|
};
|
|
|
|
setAllowOtherServers = (allowOtherServers) => {
|
|
this.allowOtherServers = allowOtherServers;
|
|
};
|
|
|
|
setAppStarted = (appStarted) => {
|
|
this.appStarted = appStarted;
|
|
};
|
|
|
|
setEMMEnabled = (emmEnabled) => {
|
|
this.emmEnabled = emmEnabled;
|
|
};
|
|
|
|
setDeviceToken = (deviceToken) => {
|
|
this.deviceToken = deviceToken;
|
|
};
|
|
|
|
setReplyNotificationData = (replyNotificationData) => {
|
|
this.replyNotificationData = replyNotificationData;
|
|
};
|
|
|
|
setInBackgroundSince = (inBackgroundSince) => {
|
|
this.inBackgroundSince = inBackgroundSince;
|
|
};
|
|
|
|
setShouldRelaunchWhenActive = (shouldRelaunchWhenActive) => {
|
|
this.shouldRelaunchWhenActive = shouldRelaunchWhenActive;
|
|
};
|
|
|
|
clearNativeCache = () => {
|
|
resetGenericPassword();
|
|
AsyncStorage.multiRemove([
|
|
TOOLBAR_BACKGROUND,
|
|
TOOLBAR_TEXT_COLOR,
|
|
APP_BACKGROUND,
|
|
]);
|
|
};
|
|
|
|
handleDeepLink = (event) => {
|
|
const {url} = event;
|
|
store.dispatch(setDeepLinkURL(url));
|
|
}
|
|
|
|
launchApp = async () => {
|
|
const shouldStart = await handleManagedConfig();
|
|
if (shouldStart) {
|
|
this.startApp();
|
|
}
|
|
};
|
|
|
|
startApp = () => {
|
|
if (this.waitForRehydration) {
|
|
return;
|
|
}
|
|
|
|
const {dispatch} = store;
|
|
|
|
Linking.getInitialURL().then((url) => {
|
|
dispatch(setDeepLinkURL(url));
|
|
});
|
|
|
|
let screen = 'SelectServer';
|
|
if (this.token && this.url) {
|
|
screen = 'Channel';
|
|
tracker.initialLoad = Date.now();
|
|
|
|
try {
|
|
dispatch(loadMe());
|
|
} catch (e) {
|
|
// Fall through since we should have a previous version of the current user because we have a token
|
|
console.warn('Failed to load current user when starting on Channel screen', e); // eslint-disable-line no-console
|
|
}
|
|
}
|
|
|
|
switch (screen) {
|
|
case 'SelectServer':
|
|
dispatch(resetToSelectServer(this.allowOtherServers));
|
|
break;
|
|
case 'Channel':
|
|
dispatch(resetToChannel());
|
|
break;
|
|
}
|
|
|
|
initializeModules();
|
|
|
|
this.setAppStarted(true);
|
|
}
|
|
}
|