Files
mattermost-mobile/app/screens/navigation.ts
2021-07-11 07:52:44 -04:00

502 lines
13 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {Appearance, DeviceEventEmitter, Keyboard, Platform} from 'react-native';
import {Layout, Navigation, Options, OptionsModalPresentationStyle} from 'react-native-navigation';
import merge from 'deepmerge';
import {Navigation as NavigationConstants, Preferences, Screens} from '@constants';
import EphemeralStore from '@store/ephemeral_store';
import type {LaunchProps} from '@typings/launch';
function getThemeFromState() {
if (Appearance.getColorScheme() === 'dark') {
return Preferences.THEMES.windows10;
}
return Preferences.THEMES.default;
}
export function resetToChannel(passProps = {}) {
const theme = getThemeFromState();
EphemeralStore.clearNavigationComponents();
const stack = {
children: [{
component: {
id: Screens.CHANNEL,
name: Screens.CHANNEL,
passProps,
options: {
layout: {
componentBackgroundColor: theme.centerChannelBg,
},
statusBar: {
visible: true,
},
topBar: {
visible: false,
height: 0,
background: {
color: theme.sidebarHeaderBg,
},
backButton: {
visible: false,
color: theme.sidebarHeaderTextColor,
},
},
},
},
}],
};
let platformStack: Layout = {stack};
if (Platform.OS === 'android') {
platformStack = {
sideMenu: {
left: {
component: {
id: Screens.MAIN_SIDEBAR,
name: Screens.MAIN_SIDEBAR,
},
},
center: {
stack,
},
right: {
component: {
id: Screens.SETTINGS_SIDEBAR,
name: Screens.SETTINGS_SIDEBAR,
},
},
},
};
}
Navigation.setRoot({
root: {
...platformStack,
},
});
}
export function resetToSelectServer(passProps: LaunchProps) {
const theme = getThemeFromState();
EphemeralStore.clearNavigationComponents();
const children = [{
component: {
id: Screens.SERVER,
name: Screens.SERVER,
passProps: {
...passProps,
theme,
},
options: {
layout: {
backgroundColor: theme.centerChannelBg,
componentBackgroundColor: theme.centerChannelBg,
},
statusBar: {
visible: true,
},
topBar: {
backButton: {
color: theme.sidebarHeaderTextColor,
title: '',
},
background: {
color: theme.sidebarHeaderBg,
},
visible: false,
height: 0,
},
},
},
}];
Navigation.setRoot({
root: {
stack: {
children,
},
},
});
}
export function resetToTeams(name: string, title: string, passProps = {}, options = {}) {
const theme = getThemeFromState();
const defaultOptions = {
layout: {
componentBackgroundColor: theme.centerChannelBg,
},
statusBar: {
visible: true,
},
topBar: {
visible: true,
title: {
color: theme.sidebarHeaderTextColor,
text: title,
},
backButton: {
color: theme.sidebarHeaderTextColor,
title: '',
},
background: {
color: theme.sidebarHeaderBg,
},
},
};
EphemeralStore.clearNavigationComponents();
Navigation.setRoot({
root: {
stack: {
children: [{
component: {
id: name,
name,
passProps,
options: merge(defaultOptions, options),
},
}],
},
},
});
}
export function goToScreen(name: string, title: string, passProps = {}, options = {}) {
const theme = getThemeFromState();
const componentId = EphemeralStore.getNavigationTopComponentId();
const defaultOptions = {
layout: {
componentBackgroundColor: theme.centerChannelBg,
},
popGesture: true,
sideMenu: {
left: {enabled: false},
right: {enabled: false},
},
topBar: {
animate: true,
visible: true,
backButton: {
color: theme.sidebarHeaderTextColor,
title: '',
testID: 'screen.back.button',
},
background: {
color: theme.sidebarHeaderBg,
},
title: {
color: theme.sidebarHeaderTextColor,
text: title,
},
},
};
Navigation.push(componentId, {
component: {
id: name,
name,
passProps,
options: merge(defaultOptions, options),
},
});
}
export function popTopScreen(screenId?: string) {
if (screenId) {
Navigation.pop(screenId);
} else {
const componentId = EphemeralStore.getNavigationTopComponentId();
Navigation.pop(componentId);
}
}
export async function popToRoot() {
const componentId = EphemeralStore.getNavigationTopComponentId();
try {
await Navigation.popToRoot(componentId);
} catch (error) {
// RNN returns a promise rejection if there are no screens
// atop the root screen to pop. We'll do nothing in this case.
}
}
export async function dismissAllModalsAndPopToRoot() {
await dismissAllModals();
await popToRoot();
DeviceEventEmitter.emit(NavigationConstants.NAVIGATION_DISMISS_AND_POP_TO_ROOT);
}
export function showModal(name: string, title: string, passProps = {}, options = {}) {
const theme = getThemeFromState();
const modalPresentationStyle: OptionsModalPresentationStyle = Platform.OS === 'ios' ? OptionsModalPresentationStyle.pageSheet : OptionsModalPresentationStyle.none;
const defaultOptions: Options = {
modalPresentationStyle,
layout: {
componentBackgroundColor: theme.centerChannelBg,
},
statusBar: {
visible: true,
},
topBar: {
animate: true,
visible: true,
backButton: {
color: theme.sidebarHeaderTextColor,
title: '',
},
background: {
color: theme.sidebarHeaderBg,
},
title: {
color: theme.sidebarHeaderTextColor,
text: title,
},
leftButtonColor: theme.sidebarHeaderTextColor,
rightButtonColor: theme.sidebarHeaderTextColor,
},
};
EphemeralStore.addNavigationModal(name);
Navigation.showModal({
stack: {
children: [{
component: {
id: name,
name,
passProps,
options: merge(defaultOptions, options),
},
}],
},
});
}
export function showModalOverCurrentContext(name: string, passProps = {}, options = {}) {
const title = '';
let animations;
switch (Platform.OS) {
case 'android':
animations = {
showModal: {
waitForRender: true,
alpha: {
from: 0,
to: 1,
duration: 250,
},
},
dismissModal: {
alpha: {
from: 1,
to: 0,
duration: 250,
},
},
};
break;
default:
animations = {
showModal: {
enter: {
enabled: false,
},
exit: {
enabled: false,
},
},
dismissModal: {
enter: {
enabled: false,
},
exit: {
enabled: false,
},
},
};
break;
}
const defaultOptions = {
modalPresentationStyle: 'overCurrentContext',
layout: {
backgroundColor: 'transparent',
componentBackgroundColor: 'transparent',
},
topBar: {
visible: false,
height: 0,
},
animations,
};
const mergeOptions = merge(defaultOptions, options);
showModal(name, title, passProps, mergeOptions);
}
export function showSearchModal(initialValue = '') {
const name = 'Search';
const title = '';
const passProps = {initialValue};
const options = {
topBar: {
visible: false,
height: 0,
},
...Platform.select({
ios: {
modalPresentationStyle: 'pageSheet',
},
}),
};
showModal(name, title, passProps, options);
}
export async function dismissModal(options = {}) {
if (!EphemeralStore.hasModalsOpened()) {
return;
}
const componentId = EphemeralStore.getNavigationTopComponentId();
try {
await Navigation.dismissModal(componentId, options);
EphemeralStore.removeNavigationModal(componentId);
} catch (error) {
// RNN returns a promise rejection if there is no modal to
// dismiss. We'll do nothing in this case.
}
}
export async function dismissAllModals(options = {}) {
if (!EphemeralStore.hasModalsOpened()) {
return;
}
try {
await Navigation.dismissAllModals(options);
EphemeralStore.clearNavigationModals();
} catch (error) {
// RNN returns a promise rejection if there are no modals to
// dismiss. We'll do nothing in this case.
}
}
export function setButtons(componentId: string, buttons = {leftButtons: [], rightButtons: []}) {
const options = {
topBar: {
...buttons,
},
};
mergeNavigationOptions(componentId, options);
}
export function mergeNavigationOptions(componentId: string, options: Options) {
Navigation.mergeOptions(componentId, options);
}
export function showOverlay(name: string, passProps = {}, options = {}) {
const defaultOptions = {
layout: {
backgroundColor: 'transparent',
componentBackgroundColor: 'transparent',
},
overlay: {
interceptTouchOutside: false,
},
};
Navigation.showOverlay({
component: {
name,
passProps,
options: merge(defaultOptions, options),
},
});
}
export async function dismissOverlay(componentId: string) {
try {
await Navigation.dismissOverlay(componentId);
} catch (error) {
// RNN returns a promise rejection if there is no modal with
// this componentId to dismiss. We'll do nothing in this case.
}
}
export function openMainSideMenu() {
if (Platform.OS === 'ios') {
return;
}
const componentId = EphemeralStore.getNavigationTopComponentId();
Keyboard.dismiss();
Navigation.mergeOptions(componentId, {
sideMenu: {
left: {visible: true},
},
});
}
export function closeMainSideMenu() {
if (Platform.OS === 'ios') {
return;
}
Keyboard.dismiss();
Navigation.mergeOptions(Screens.CHANNEL, {
sideMenu: {
left: {visible: false},
},
});
}
export function enableMainSideMenu(enabled: boolean, visible = true) {
if (Platform.OS === 'ios') {
return;
}
Navigation.mergeOptions(Screens.CHANNEL, {
sideMenu: {
left: {enabled, visible},
},
});
}
export function openSettingsSideMenu() {
if (Platform.OS === 'ios') {
return;
}
Keyboard.dismiss();
Navigation.mergeOptions(Screens.CHANNEL, {
sideMenu: {
right: {visible: true},
},
});
}
export function closeSettingsSideMenu() {
if (Platform.OS === 'ios') {
return;
}
Keyboard.dismiss();
Navigation.mergeOptions(Screens.CHANNEL, {
sideMenu: {
right: {visible: false},
},
});
}