mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-23 15:09:33 +01:00
add a custom SideMenu to replace drawer navigator
This commit is contained in:
@@ -4,8 +4,9 @@ import ScrollableTabView from 'react-native-scrollable-tab-view';
|
||||
import ContextMenu from './src/components/ContextMenu';
|
||||
import {DialogManager} from './src/components/DialogManager';
|
||||
import {DummyText} from './src/components/DummyText';
|
||||
import {Menu} from './src/components/Menu';
|
||||
import SideMenu from './src/components/SideMenu';
|
||||
import {Toast} from './src/components/Toast';
|
||||
import {NavigationStack} from './src/navigation/Drawer';
|
||||
import {NavigatorStack} from './src/navigation/NavigatorStack';
|
||||
import {useTracked} from './src/provider';
|
||||
import {Actions} from './src/provider/Actions';
|
||||
@@ -23,24 +24,30 @@ import {
|
||||
eOpenFullscreenEditor,
|
||||
eOpenSideMenu,
|
||||
} from './src/utils/Events';
|
||||
import {editorRef, tabBarRef} from './src/utils/Refs';
|
||||
import {editorRef, sideMenuRef, tabBarRef} from './src/utils/Refs';
|
||||
import {EditorWrapper} from './src/views/Editor/EditorWrapper';
|
||||
import {getIntent, getNote, post} from './src/views/Editor/Functions';
|
||||
|
||||
let {width, height} = Dimensions.get('window');
|
||||
let movedAway = true;
|
||||
let layoutTimer = null;
|
||||
|
||||
const onChangeTab = async (obj) => {
|
||||
console.log(obj.i,obj.from,'tab changed')
|
||||
if (obj.i === 1) {
|
||||
eSendEvent(eCloseSideMenu);
|
||||
sideMenuRef.current?.setGestureEnabled(false);
|
||||
if (getIntent()) return;
|
||||
movedAway = false;
|
||||
if (!editing.currentlyEditing || !getNote()) {
|
||||
eSendEvent(eOnLoadNote, {type: 'new'});
|
||||
editing.currentlyEditing = true;
|
||||
}
|
||||
} else {
|
||||
if (obj.from === 1) {
|
||||
movedAway = true;
|
||||
editing.currentlyEditing = false;
|
||||
post('blur');
|
||||
eSendEvent(eOpenSideMenu);
|
||||
}
|
||||
sideMenuRef.current?.setGestureEnabled(true);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -103,83 +110,127 @@ const AppStack = React.memo(
|
||||
}, []);
|
||||
|
||||
const _onLayout = async (event) => {
|
||||
console.log(editing.currentlyEditing);
|
||||
if (editing.currentlyEditing) return;
|
||||
let size = event?.nativeEvent?.layout;
|
||||
if (!size) return;
|
||||
setDimensions({
|
||||
width: size.width,
|
||||
height: size.height,
|
||||
});
|
||||
setWidthHeight(size);
|
||||
DDS.setSize(size);
|
||||
DDS.checkSmallTab(size.width > size.height ? 'LANDSCAPE' : 'PORTRAIT');
|
||||
if (DDS.isLargeTablet()) {
|
||||
setMode('tablet');
|
||||
dispatch({type: Actions.FULLSCREEN, state: false});
|
||||
editorRef.current?.setNativeProps({
|
||||
style: {
|
||||
position: 'relative',
|
||||
width: size.width * 0.55,
|
||||
zIndex: null,
|
||||
paddingHorizontal: 0,
|
||||
},
|
||||
});
|
||||
} else if (DDS.isSmallTab) {
|
||||
setMode('smallTablet');
|
||||
dispatch({type: Actions.FULLSCREEN, state: false});
|
||||
editorRef.current?.setNativeProps({
|
||||
style: {
|
||||
position: 'relative',
|
||||
width: size.width,
|
||||
zIndex: null,
|
||||
paddingHorizontal: 0,
|
||||
},
|
||||
});
|
||||
|
||||
if (editing.currentlyEditing) {
|
||||
tabBarRef.current?.goToPage(1);
|
||||
}
|
||||
} else {
|
||||
setMode('mobile');
|
||||
dispatch({type: Actions.FULLSCREEN, state: false});
|
||||
editorRef.current?.setNativeProps({
|
||||
style: {
|
||||
position: 'relative',
|
||||
width: size.width,
|
||||
zIndex: null,
|
||||
paddingHorizontal: 0,
|
||||
},
|
||||
});
|
||||
if (editing.currentlyEditing) {
|
||||
tabBarRef.current?.goToPage(1);
|
||||
}
|
||||
if (layoutTimer) {
|
||||
clearTimeout(layoutTimer);
|
||||
layoutTimer = null;
|
||||
}
|
||||
let size = event?.nativeEvent?.layout;
|
||||
if (!size || (size.width === dimensions.width && mode !== null)) {
|
||||
return;
|
||||
}
|
||||
layoutTimer = setTimeout(async () => {
|
||||
eSendEvent(eCloseSideMenu);
|
||||
setDimensions({
|
||||
width: size.width,
|
||||
height: size.height,
|
||||
});
|
||||
setWidthHeight(size);
|
||||
DDS.setSize(size);
|
||||
console.log(size.width, size.height);
|
||||
DDS.checkSmallTab(size.width > size.height ? 'LANDSCAPE' : 'PORTRAIT');
|
||||
|
||||
if (DDS.isLargeTablet()) {
|
||||
setMode('tablet');
|
||||
sideMenuRef.current?.setGestureEnabled(false);
|
||||
dispatch({type: Actions.DEVICE_MODE, state: 'tablet'});
|
||||
dispatch({type: Actions.FULLSCREEN, state: false});
|
||||
editorRef.current?.setNativeProps({
|
||||
style: {
|
||||
position: 'relative',
|
||||
width: size.width * 0.55,
|
||||
zIndex: null,
|
||||
paddingHorizontal: 0,
|
||||
},
|
||||
});
|
||||
} else if (DDS.isSmallTab) {
|
||||
setMode('smallTablet');
|
||||
dispatch({type: Actions.DEVICE_MODE, state: 'smallTablet'});
|
||||
dispatch({type: Actions.FULLSCREEN, state: false});
|
||||
sideMenuRef.current?.setGestureEnabled(false);
|
||||
editorRef.current?.setNativeProps({
|
||||
style: {
|
||||
position: 'relative',
|
||||
width: size.width,
|
||||
zIndex: null,
|
||||
paddingHorizontal: 0,
|
||||
},
|
||||
});
|
||||
|
||||
if (editing.currentlyEditing && !movedAway) {
|
||||
tabBarRef.current?.goToPage(1);
|
||||
}
|
||||
} else {
|
||||
sideMenuRef.current?.setGestureEnabled(true);
|
||||
setMode('mobile');
|
||||
dispatch({type: Actions.DEVICE_MODE, state: 'mobile'});
|
||||
dispatch({type: Actions.FULLSCREEN, state: false});
|
||||
editorRef.current?.setNativeProps({
|
||||
style: {
|
||||
position: 'relative',
|
||||
width: size.width,
|
||||
zIndex: null,
|
||||
paddingHorizontal: 0,
|
||||
},
|
||||
});
|
||||
if (editing.currentlyEditing && !movedAway) {
|
||||
tabBarRef.current?.goToPage(1);
|
||||
}
|
||||
}
|
||||
|
||||
eSendEvent(eOpenSideMenu);
|
||||
}, 500);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<View
|
||||
style={{
|
||||
position: 'absolute',
|
||||
width: '400%',
|
||||
height: '400%',
|
||||
backgroundColor: colors.bg,
|
||||
}}
|
||||
/>
|
||||
<SideMenu
|
||||
ref={sideMenuRef}
|
||||
containerStyle={{
|
||||
backgroundColor: colors.bg,
|
||||
}}
|
||||
menu={mode === 'mobile' ? <Menu /> : null}>
|
||||
<ScrollableTabView
|
||||
ref={tabBarRef}
|
||||
style={{
|
||||
zIndex:2
|
||||
zIndex: 1,
|
||||
}}
|
||||
initialPage={0}
|
||||
prerenderingSiblingsNumber={Infinity}
|
||||
onChangeTab={onChangeTab}
|
||||
renderTabBar={() => <></>}>
|
||||
|
||||
{ mode !== 'tablet' && (
|
||||
<NavigationStack component={NavigatorStack} />
|
||||
{mode && mode !== 'tablet' && (
|
||||
<View
|
||||
style={{
|
||||
width: dimensions.width,
|
||||
height: '100%',
|
||||
borderRightColor: colors.nav,
|
||||
borderRightWidth: 1,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-start',
|
||||
}}>
|
||||
{mode && mode === 'smallTablet' && (
|
||||
<View
|
||||
style={{
|
||||
height: '100%',
|
||||
width: dimensions.width * 0.35,
|
||||
}}>
|
||||
<Menu />
|
||||
</View>
|
||||
)}
|
||||
|
||||
<View
|
||||
style={{
|
||||
height: '100%',
|
||||
width:
|
||||
mode === 'mobile'
|
||||
? dimensions.width
|
||||
: dimensions.width * 0.65,
|
||||
}}>
|
||||
<NavigatorStack />
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
|
||||
<View
|
||||
style={{
|
||||
width: '100%',
|
||||
@@ -195,16 +246,35 @@ const AppStack = React.memo(
|
||||
height: '100%',
|
||||
borderRightColor: colors.nav,
|
||||
borderRightWidth: 1,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
}}>
|
||||
<NavigationStack component={NavigatorStack} />
|
||||
<View
|
||||
style={{
|
||||
height: '100%',
|
||||
width: dimensions.width * 0.15,
|
||||
}}>
|
||||
<Menu />
|
||||
</View>
|
||||
|
||||
<View
|
||||
style={{
|
||||
height: '100%',
|
||||
width: dimensions.width * 0.3,
|
||||
}}>
|
||||
<NavigatorStack />
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
|
||||
<EditorWrapper dimensions={dimensions} />
|
||||
{mode && <EditorWrapper dimensions={dimensions} />}
|
||||
</View>
|
||||
</ScrollableTabView>
|
||||
</>
|
||||
</SideMenu>
|
||||
);
|
||||
},
|
||||
() => true,
|
||||
);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import React from 'react';
|
||||
import { useTracked } from '../../provider';
|
||||
import { DDS } from '../../services/DeviceDetection';
|
||||
import {useTracked} from '../../provider';
|
||||
import {DDS} from '../../services/DeviceDetection';
|
||||
import NavigationService from '../../services/Navigation';
|
||||
import { SIZE } from '../../utils/SizeUtils';
|
||||
import { ActionIcon } from '../ActionIcon';
|
||||
import {sideMenuRef} from '../../utils/Refs';
|
||||
import {SIZE} from '../../utils/SizeUtils';
|
||||
import {ActionIcon} from '../ActionIcon';
|
||||
|
||||
export const HeaderLeftMenu = () => {
|
||||
const [state] = useTracked();
|
||||
const {colors, headerMenuState, currentScreen} = state;
|
||||
const {colors, headerMenuState, currentScreen, deviceMode} = state;
|
||||
|
||||
const onLeftButtonPress = () => {
|
||||
if (headerMenuState) {
|
||||
NavigationService.openDrawer();
|
||||
sideMenuRef.current?.openMenu(true);
|
||||
return;
|
||||
}
|
||||
NavigationService.goBack();
|
||||
@@ -19,7 +20,7 @@ export const HeaderLeftMenu = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
{!DDS.isTab || currentScreen === 'search' ? (
|
||||
{deviceMode === 'mobile' || currentScreen === 'search' ? (
|
||||
<ActionIcon
|
||||
testID="left_menu_button"
|
||||
customStyle={{
|
||||
|
||||
@@ -9,6 +9,7 @@ import { PressableButton } from '../PressableButton';
|
||||
import {COLORS_NOTE} from "../../utils/Colors";
|
||||
import {SIZE, WEIGHT} from "../../utils/SizeUtils";
|
||||
import Paragraph from '../Typography/Paragraph';
|
||||
import { sideMenuRef } from '../../utils/Refs';
|
||||
|
||||
export const ColorSection = ({noTextMode}) => {
|
||||
const [state, dispatch] = useTracked();
|
||||
@@ -45,7 +46,7 @@ export const ColorSection = ({noTextMode}) => {
|
||||
|
||||
NavigationService.navigate('NotesPage', params);
|
||||
eSendEvent(refreshNotesPage, params);
|
||||
NavigationService.closeDrawer();
|
||||
sideMenuRef.current?.openMenu(false);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -7,6 +7,7 @@ import {DDS} from '../../services/DeviceDetection';
|
||||
import {eSendEvent} from '../../services/EventManager';
|
||||
import NavigationService from '../../services/Navigation';
|
||||
import {eClearSearch} from '../../utils/Events';
|
||||
import { sideMenuRef } from '../../utils/Refs';
|
||||
import {SIZE} from '../../utils/SizeUtils';
|
||||
import {PressableButton} from '../PressableButton';
|
||||
import Paragraph from '../Typography/Paragraph';
|
||||
@@ -34,7 +35,7 @@ export const MenuListItem = ({item, index, noTextMode, ignore, testID}) => {
|
||||
NavigationService.navigate(item.name);
|
||||
}
|
||||
if (item.close) {
|
||||
NavigationService.closeDrawer();
|
||||
sideMenuRef.current?.openMenu(false)
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import {Actions} from '../../provider/Actions';
|
||||
import {eSendEvent} from '../../services/EventManager';
|
||||
import NavigationService from '../../services/Navigation';
|
||||
import {refreshNotesPage} from '../../utils/Events';
|
||||
import { sideMenuRef } from '../../utils/Refs';
|
||||
import {SIZE, WEIGHT} from '../../utils/SizeUtils';
|
||||
import {PressableButton} from '../PressableButton';
|
||||
import Paragraph from '../Typography/Paragraph';
|
||||
@@ -36,7 +37,7 @@ export const TagsSection = () => {
|
||||
});
|
||||
NavigationService.navigate('NotesPage', params);
|
||||
eSendEvent(refreshNotesPage, params);
|
||||
NavigationService.closeDrawer();
|
||||
sideMenuRef.current?.openMenu(false)
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
326
apps/mobile/src/components/SideMenu.js
Normal file
326
apps/mobile/src/components/SideMenu.js
Normal file
@@ -0,0 +1,326 @@
|
||||
// @flow
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import {
|
||||
Dimensions,
|
||||
PanResponder,
|
||||
TouchableWithoutFeedback,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import Animated, {Easing} from 'react-native-reanimated';
|
||||
|
||||
import styles from './styles';
|
||||
|
||||
const deviceScreen = Dimensions.get('window');
|
||||
const barrierForward = deviceScreen.width / 5;
|
||||
|
||||
function shouldOpenMenu(dx) {
|
||||
return dx > barrierForward;
|
||||
}
|
||||
|
||||
export default class SideMenu extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.prevLeft = 0;
|
||||
this.isOpen = !!props.isOpen;
|
||||
this.isGestureEnabled = true;
|
||||
this.overlay;
|
||||
this.opacity = new Animated.Value(0);
|
||||
|
||||
const initialMenuPositionMultiplier =
|
||||
props.menuPosition === 'right' ? -1 : 1;
|
||||
const openOffsetMenuPercentage = props.openMenuOffset / deviceScreen.width;
|
||||
const hiddenMenuOffsetPercentage =
|
||||
props.hiddenMenuOffset / deviceScreen.width;
|
||||
const left = new Animated.Value(
|
||||
props.isOpen
|
||||
? props.openMenuOffset * initialMenuPositionMultiplier
|
||||
: props.hiddenMenuOffset,
|
||||
);
|
||||
|
||||
this.onLayoutChange = this.onLayoutChange.bind(this);
|
||||
this.onStartShouldSetResponderCapture = props.onStartShouldSetResponderCapture.bind(
|
||||
this,
|
||||
);
|
||||
this.onMoveShouldSetPanResponder = this.handleMoveShouldSetPanResponder.bind(
|
||||
this,
|
||||
);
|
||||
this.onPanResponderMove = this.handlePanResponderMove.bind(this);
|
||||
this.onPanResponderRelease = this.handlePanResponderEnd.bind(this);
|
||||
this.onPanResponderTerminate = this.handlePanResponderEnd.bind(this);
|
||||
|
||||
this.state = {
|
||||
width: deviceScreen.width,
|
||||
height: deviceScreen.height,
|
||||
openOffsetMenuPercentage,
|
||||
openMenuOffset: deviceScreen.width * openOffsetMenuPercentage,
|
||||
hiddenMenuOffsetPercentage,
|
||||
hiddenMenuOffset: deviceScreen.width * hiddenMenuOffsetPercentage,
|
||||
left,
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
onLayoutChange(e) {
|
||||
const {width, height} = e.nativeEvent.layout;
|
||||
const openMenuOffset = width * this.state.openOffsetMenuPercentage;
|
||||
const hiddenMenuOffset = width * this.state.hiddenMenuOffsetPercentage;
|
||||
this.setState({width, height, openMenuOffset, hiddenMenuOffset});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get content view. This view will be rendered over menu
|
||||
* @return {React.Component}
|
||||
*/
|
||||
getContentView() {
|
||||
//let overlay = null;
|
||||
|
||||
const {width, height} = this.state;
|
||||
const ref = (sideMenu) => (this.sideMenu = sideMenu);
|
||||
const style = [
|
||||
styles.frontView,
|
||||
{width, height},
|
||||
this.props.animationStyle(this.state.left),
|
||||
this.props.containerStyle
|
||||
];
|
||||
|
||||
return (
|
||||
<Animated.View style={style} ref={ref} {...this.responder.panHandlers}>
|
||||
{this.props.children}
|
||||
|
||||
<TouchableWithoutFeedback onPress={() => this.openMenu(false)}>
|
||||
<Animated.View
|
||||
ref={(ref) => (this.overlay = ref)}
|
||||
onTouchStart={() => {}}
|
||||
style={{
|
||||
display: 'none',
|
||||
position: 'relative',
|
||||
top: 0,
|
||||
right: 0,
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
backgroundColor: 'black',
|
||||
opacity: this.opacity,
|
||||
zIndex: 1,
|
||||
}}
|
||||
/>
|
||||
</TouchableWithoutFeedback>
|
||||
</Animated.View>
|
||||
);
|
||||
}
|
||||
|
||||
changeOpacity(opacity) {
|
||||
if (opacity === 0.5) {
|
||||
this.overlay.setNativeProps({
|
||||
style: {
|
||||
display: 'flex',
|
||||
position: 'absolute',
|
||||
zIndex: 999,
|
||||
},
|
||||
});
|
||||
}
|
||||
Animated.timing(this.opacity, {
|
||||
toValue: opacity,
|
||||
duration: 200,
|
||||
easing: Easing.inOut(Easing.ease),
|
||||
}).start(() => {
|
||||
if (opacity < 0.5) {
|
||||
this.overlay.setNativeProps({
|
||||
style: {
|
||||
display: 'none',
|
||||
position: 'relative',
|
||||
zIndex: -1,
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
moveLeft(offset) {
|
||||
const newOffset = this.menuPositionMultiplier() * offset;
|
||||
Animated.timing(this.state.left, {
|
||||
toValue: newOffset,
|
||||
duration: 200,
|
||||
easing: Easing.elastic(0.5),
|
||||
}).start();
|
||||
this.prevLeft = newOffset;
|
||||
}
|
||||
|
||||
menuPositionMultiplier() {
|
||||
return this.props.menuPosition === 'right' ? -1 : 1;
|
||||
}
|
||||
|
||||
handlePanResponderMove(e, gestureState) {
|
||||
if (this.state.left.__getValue() * this.menuPositionMultiplier() >= 0) {
|
||||
let newLeft = this.prevLeft + gestureState.dx;
|
||||
if (newLeft >= this.props.openMenuOffset || newLeft < 0) return;
|
||||
if (
|
||||
!this.props.bounceBackOnOverdraw &&
|
||||
Math.abs(newLeft) > this.state.openMenuOffset
|
||||
) {
|
||||
newLeft = this.menuPositionMultiplier() * this.state.openMenuOffset;
|
||||
}
|
||||
this.state.left.setValue(newLeft);
|
||||
this.props.onMove(newLeft);
|
||||
let o = newLeft / this.props.openMenuOffset;
|
||||
this.opacity.setValue(o * 0.5);
|
||||
|
||||
this.overlay.setNativeProps({
|
||||
style: {
|
||||
display: 'flex',
|
||||
position: 'absolute',
|
||||
zIndex: 999,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handlePanResponderEnd(e, gestureState) {
|
||||
const offsetLeft =
|
||||
this.menuPositionMultiplier() *
|
||||
(this.state.left.__getValue() + gestureState.dx);
|
||||
|
||||
this.openMenu(shouldOpenMenu(offsetLeft));
|
||||
}
|
||||
|
||||
handleMoveShouldSetPanResponder(e, gestureState) {
|
||||
if (this.gesturesAreEnabled()) {
|
||||
const x = Math.round(Math.abs(gestureState.dx));
|
||||
const y = Math.round(Math.abs(gestureState.dy));
|
||||
|
||||
const touchMoved = x > this.props.toleranceX && y < this.props.toleranceY;
|
||||
|
||||
if (this.isOpen) {
|
||||
return touchMoved;
|
||||
}
|
||||
|
||||
const withinEdgeHitWidth =
|
||||
this.props.menuPosition === 'right'
|
||||
? gestureState.moveX > deviceScreen.width - this.props.edgeHitWidth
|
||||
: gestureState.moveX < this.props.edgeHitWidth;
|
||||
|
||||
const swipingToOpen = this.menuPositionMultiplier() * gestureState.dx > 0;
|
||||
return withinEdgeHitWidth && touchMoved && swipingToOpen;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
openMenu(isOpen) {
|
||||
const {hiddenMenuOffset, openMenuOffset} = this.state;
|
||||
this.changeOpacity(isOpen ? 0.5 : 0);
|
||||
this.moveLeft(isOpen ? openMenuOffset : hiddenMenuOffset);
|
||||
|
||||
this.isOpen = isOpen;
|
||||
|
||||
this.forceUpdate();
|
||||
this.props.onChange(isOpen);
|
||||
}
|
||||
|
||||
setGestureEnabled(enabled) {
|
||||
this.isGestureEnabled = enabled;
|
||||
}
|
||||
|
||||
gesturesAreEnabled() {
|
||||
return this.isGestureEnabled;
|
||||
}
|
||||
|
||||
UNSAFE_componentWillMount() {
|
||||
this.responder = PanResponder.create({
|
||||
onStartShouldSetResponderCapture: this.onStartShouldSetResponderCapture,
|
||||
onMoveShouldSetPanResponder: this.onMoveShouldSetPanResponder,
|
||||
onPanResponderMove: this.onPanResponderMove,
|
||||
onPanResponderRelease: this.onPanResponderRelease,
|
||||
onPanResponderTerminate: this.onPanResponderTerminate,
|
||||
});
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
//eSubscribeEvent(eSendSideMenuOverlayRef, this._getOverlayViewRef);
|
||||
}
|
||||
componentWillUnmount() {
|
||||
//eUnSubscribeEvent(eSendSideMenuOverlayRef, this._getOverlayViewRef);
|
||||
}
|
||||
|
||||
_getOverlayViewRef = (data) => {
|
||||
//this.overlayViewRef = data.ref;
|
||||
};
|
||||
|
||||
render() {
|
||||
const boundryStyle =
|
||||
this.props.menuPosition === 'right'
|
||||
? {left: this.state.width - this.state.openMenuOffset}
|
||||
: {right: this.state.width - this.state.openMenuOffset};
|
||||
|
||||
const menu = (
|
||||
<View style={[styles.menu, boundryStyle]}>
|
||||
{this.props.isFullscreen ? null : this.props.menu}
|
||||
</View>
|
||||
);
|
||||
|
||||
return (
|
||||
<View style={styles.container} onLayout={this.onLayoutChange}>
|
||||
{menu}
|
||||
|
||||
{this.getContentView()}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
SideMenu.propTypes = {
|
||||
edgeHitWidth: PropTypes.number,
|
||||
toleranceX: PropTypes.number,
|
||||
toleranceY: PropTypes.number,
|
||||
menuPosition: PropTypes.oneOf(['left', 'right']),
|
||||
onChange: PropTypes.func,
|
||||
onMove: PropTypes.func,
|
||||
children: PropTypes.node,
|
||||
menu: PropTypes.node,
|
||||
openMenuOffset: PropTypes.number,
|
||||
hiddenMenuOffset: PropTypes.number,
|
||||
animationStyle: PropTypes.func,
|
||||
disableGestures: PropTypes.oneOfType([PropTypes.func, PropTypes.bool]),
|
||||
animationFunction: PropTypes.func,
|
||||
onStartShouldSetResponderCapture: PropTypes.func,
|
||||
isOpen: PropTypes.bool,
|
||||
bounceBackOnOverdraw: PropTypes.bool,
|
||||
autoClosing: PropTypes.bool,
|
||||
};
|
||||
|
||||
SideMenu.defaultProps = {
|
||||
toleranceY: 10,
|
||||
toleranceX: 10,
|
||||
edgeHitWidth: 60,
|
||||
children: null,
|
||||
menu: null,
|
||||
openMenuOffset: deviceScreen.width * (2 / 3),
|
||||
disableGestures: false,
|
||||
menuPosition: 'left',
|
||||
hiddenMenuOffset: 0,
|
||||
onMove: () => {},
|
||||
onStartShouldSetResponderCapture: () => true,
|
||||
onChange: () => {},
|
||||
onSliding: () => {},
|
||||
animationStyle: (value) => ({
|
||||
transform: [
|
||||
{
|
||||
translateX: value,
|
||||
},
|
||||
],
|
||||
}),
|
||||
animationFunction: (prop, value) =>
|
||||
Animated.timing(prop, {
|
||||
toValue: value,
|
||||
duration: 300,
|
||||
easing: Easing.elastic(0.5),
|
||||
}),
|
||||
isOpen: false,
|
||||
bounceBackOnOverdraw: true,
|
||||
autoClosing: true,
|
||||
};
|
||||
34
apps/mobile/src/components/styles.js
Normal file
34
apps/mobile/src/components/styles.js
Normal file
@@ -0,0 +1,34 @@
|
||||
// @flow
|
||||
|
||||
import {StyleSheet} from 'react-native';
|
||||
|
||||
const absoluteStretch = {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
};
|
||||
|
||||
export default StyleSheet.create({
|
||||
container: {
|
||||
...absoluteStretch,
|
||||
justifyContent: 'center',
|
||||
},
|
||||
menu: {
|
||||
...absoluteStretch,
|
||||
},
|
||||
frontView: {
|
||||
flex: 1,
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
top: 0,
|
||||
backgroundColor: 'transparent',
|
||||
overflow: 'hidden',
|
||||
},
|
||||
overlay: {
|
||||
...absoluteStretch,
|
||||
backgroundColor: 'black',
|
||||
opacity: 0,
|
||||
},
|
||||
});
|
||||
@@ -1,15 +1,12 @@
|
||||
import {createDrawerNavigator} from '@react-navigation/drawer';
|
||||
import {NavigationContainer} from '@react-navigation/native';
|
||||
import * as React from 'react';
|
||||
import {Menu} from '../components/Menu';
|
||||
import {DDS} from '../services/DeviceDetection';
|
||||
import {eSubscribeEvent, eUnSubscribeEvent} from '../services/EventManager';
|
||||
import {eCloseSideMenu, eOpenSideMenu} from '../utils/Events';
|
||||
import {NavigationContainer} from '@react-navigation/native';
|
||||
import {sideMenuRef} from '../utils/Refs';
|
||||
import {Dimensions} from 'react-native';
|
||||
import {NavigatorStack} from './NavigatorStack';
|
||||
import {Menu} from '../components/Menu';
|
||||
import NavigationService from '../services/Navigation';
|
||||
import {createDrawerNavigator} from '@react-navigation/drawer';
|
||||
import {DDS} from '../services/DeviceDetection';
|
||||
import { dWidth } from '../utils';
|
||||
|
||||
const Drawer = createDrawerNavigator();
|
||||
|
||||
@@ -38,16 +35,17 @@ export const NavigationStack = ({component = NavigatorStack}) => {
|
||||
<Drawer.Navigator
|
||||
screenOptions={{
|
||||
swipeEnabled: locked ? false : true,
|
||||
|
||||
}}
|
||||
drawerStyle={{
|
||||
width:
|
||||
DDS.isLargeTablet()
|
||||
? DDS.width * 0.15
|
||||
: DDS.isSmallTab
|
||||
? "30%"
|
||||
: "65%",
|
||||
width: DDS.isLargeTablet()
|
||||
? DDS.width * 0.15
|
||||
: DDS.isSmallTab
|
||||
? '30%'
|
||||
: '65%',
|
||||
borderRightWidth: 0,
|
||||
}}
|
||||
|
||||
edgeWidth={200}
|
||||
drawerType={DDS.isTab || DDS.isSmallTab ? 'permanent' : 'slide'}
|
||||
drawerContent={DrawerComponent}
|
||||
@@ -58,10 +56,6 @@ export const NavigationStack = ({component = NavigatorStack}) => {
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
|
||||
const DrawerComponent = () => {
|
||||
return (
|
||||
<Menu />
|
||||
);
|
||||
return <Menu />;
|
||||
};
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
import {NavigationContainer} from '@react-navigation/native';
|
||||
import {createStackNavigator} from '@react-navigation/stack';
|
||||
import { NavigationContainer } from '@react-navigation/native';
|
||||
import { createStackNavigator } from '@react-navigation/stack';
|
||||
import * as React from 'react';
|
||||
import {Animated} from 'react-native';
|
||||
import { Animated } from 'react-native';
|
||||
import Container from '../components/Container';
|
||||
import {useTracked} from '../provider';
|
||||
import {DDS} from '../services/DeviceDetection';
|
||||
import {rootNavigatorRef} from '../utils/Refs';
|
||||
import { useTracked } from '../provider';
|
||||
import { rootNavigatorRef } from '../utils/Refs';
|
||||
import Favorites from '../views/Favorites';
|
||||
import Folders from '../views/Folders';
|
||||
import Home from '../views/Home';
|
||||
import Notebook from '../views/Notebook';
|
||||
import Notes from '../views/Notes';
|
||||
import {Search} from '../views/Search';
|
||||
import { Search } from '../views/Search';
|
||||
import Settings from '../views/Settings';
|
||||
import Tags from '../views/Tags';
|
||||
import Trash from '../views/Trash';
|
||||
@@ -66,7 +65,6 @@ export const NavigatorStack = React.memo(
|
||||
() => {
|
||||
const [state] = useTracked();
|
||||
const {settings} = state;
|
||||
|
||||
|
||||
return (
|
||||
<Container root={true}>
|
||||
|
||||
@@ -29,5 +29,6 @@ export const Actions = {
|
||||
HEADER_TEXT_STATE:'headerTextState',
|
||||
MESSAGE_BOARD_STATE:'messageBoardState',
|
||||
LOADING:"loading",
|
||||
FULLSCREEN:"fullscreen"
|
||||
FULLSCREEN:"fullscreen",
|
||||
DEVICE_MODE:"deviceMode"
|
||||
};
|
||||
|
||||
@@ -33,6 +33,7 @@ export const defaultState = {
|
||||
privacyScreen: false,
|
||||
},
|
||||
currentScreen: 'home',
|
||||
deviceMode:null,
|
||||
colors: {
|
||||
night: false,
|
||||
bg: 'white',
|
||||
|
||||
@@ -248,6 +248,12 @@ export const reducer = (state, action) => {
|
||||
fullscreen: action.state,
|
||||
};
|
||||
}
|
||||
case Actions.DEVICE_MODE: {
|
||||
return {
|
||||
...state,
|
||||
deviceMode: action.state,
|
||||
};
|
||||
}
|
||||
default:
|
||||
throw new Error('unknown action type');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user