packages/@fbcmobile-ui/Components/Toolbar.js (120 lines of code) (raw):
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
'use strict';
import type {ViewStyleProp} from 'react-native/Libraries/StyleSheet/StyleSheet';
import * as React from 'react';
import NavigationService from '@fbcmobile/ui/Services/NavigationService';
import RNShake from 'react-native-shake';
import ScrollViewWithBottomBar from '@fbcmobile/ui/Components/Core/ScrollViewWithBottomBar';
import fbt from 'fbt';
import {ApplicationStyles} from '@fbcmobile/ui/Theme';
import {I18nManager, StyleSheet, View} from 'react-native';
import {Toolbar as MToolbar} from 'react-native-material-ui';
import {captureScreen} from 'react-native-view-shot';
type MenuElement = {|
+node: React.Node,
+onClick?: () => void,
|};
type Props = {|
+title: string,
+children?: React.Node,
+leftElement?: string,
+searchable?: boolean,
+onRefreshClicked?: () => void,
+onIconClicked: () => void,
+onSearchClicked?: () => void,
+bottomBarContent?: React.Node,
+extraRightElement?: ?MenuElement,
+showExtraActions?: boolean,
+style?: ViewStyleProp,
|};
const Toolbar = (props: Props) => {
const {
title,
children,
onRefreshClicked,
onIconClicked,
onSearchClicked,
bottomBarContent,
extraRightElement,
leftElement = 'menu',
searchable = true,
showExtraActions = true,
} = props;
React.useEffect(() => {
RNShake.addEventListener('ShakeEvent', () => {
screenshotAndReportBug();
});
return () => {
RNShake.removeEventListener('ShakeEvent');
};
}, []);
const screenshotAndReportBug = () => {
captureScreen({
format: 'png',
result: 'data-uri',
quality: 1,
snapshotContentContainer: false,
}).then(
uri => {
NavigationService.navigate('BugReportScreen', {
photoData: uri,
});
},
_ =>
NavigationService.alert(
'error',
fbt('Screenshot Failed', 'Alert title saying screenshot failed'),
fbt(
'An error occurred while taking a screenshot for the bug report. Please try again later.',
'Error dialog text shown when a screenshot failed',
),
),
);
};
let actions = searchable ? ['search'] : [];
if (extraRightElement) {
actions = [extraRightElement.node, ...actions];
}
return (
<View style={[styles.root, props.style]}>
<MToolbar
style={ApplicationStyles.screen.toolbar}
leftElement={
leftElement === 'arrow-back' && I18nManager.isRTL
? 'arrow-forward'
: leftElement
}
onLeftElementPress={onIconClicked}
centerElement={title}
rightElement={{
actions,
menu: showExtraActions
? {
icon: 'more-vert',
labels: [
fbt('Refresh', 'Menu item text').toString(),
fbt('Report Bug', 'Menu item text').toString(),
],
}
: null,
}}
onRightElementPress={e => {
if (e.action === 'menu') {
switch (true) {
case e.index === 0:
onRefreshClicked && onRefreshClicked();
break;
case e.index === 1:
screenshotAndReportBug();
break;
}
} else if (e.action === 'search') {
onSearchClicked && onSearchClicked();
} else if (e.action === extraRightElement?.node) {
extraRightElement?.onClick && extraRightElement.onClick();
}
}}
/>
<ScrollViewWithBottomBar bottomBar={bottomBarContent}>
{children}
</ScrollViewWithBottomBar>
</View>
);
};
const styles = StyleSheet.create({
root: {
height: '100%',
display: 'flex',
},
});
export default Toolbar;