mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-23 06:59:31 +01:00
refactor
This commit is contained in:
@@ -1,13 +1,16 @@
|
||||
import React, {useState} from 'react';
|
||||
import React, {Component} from 'react';
|
||||
import {
|
||||
View,
|
||||
TouchableOpacity,
|
||||
Dimensions,
|
||||
ScrollView,
|
||||
Modal,
|
||||
KeyboardAvoidingView,
|
||||
Platform,
|
||||
} from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
import {styles} from './styles';
|
||||
let scrollViewRef;
|
||||
|
||||
const deviceHeight = Dimensions.get('window').height;
|
||||
|
||||
const getElevation = elevation => {
|
||||
@@ -20,198 +23,276 @@ const getElevation = elevation => {
|
||||
};
|
||||
};
|
||||
|
||||
const ActionSheet = ({
|
||||
ref,
|
||||
children = <View />,
|
||||
animated = true,
|
||||
animationType = 'fade',
|
||||
closeOnPressBack = true,
|
||||
gestureEnabled = true,
|
||||
bounceOnOpen = true,
|
||||
bounceOffset = 20,
|
||||
springOffset = 50,
|
||||
elevation = 5,
|
||||
initialOffsetFromBottom = 0.6,
|
||||
indicatorColor = 'gray',
|
||||
customStyles = {backgroundColor: 'white'},
|
||||
overlayColor = 'rgba(0,0,0,0.3)',
|
||||
onClose = () => {},
|
||||
onOpen = () => {},
|
||||
}) => {
|
||||
const [modalVisible, setModalVisible] = useState(false);
|
||||
const [scrollable, setScrollable] = useState(false);
|
||||
const [layoutHasCalled, setLayoutHasCalled] = useState(false);
|
||||
export default class ActionSheet extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
modalVisible: false,
|
||||
scrollable: false,
|
||||
layoutHasCalled: false,
|
||||
};
|
||||
this.customComponentHeight;
|
||||
this.prevScroll;
|
||||
this.scrollAnimationEndValue;
|
||||
this.hasBounced;
|
||||
this.scrollViewRef;
|
||||
}
|
||||
|
||||
ActionSheet.customComponentHeight;
|
||||
ActionSheet.prevScroll;
|
||||
ActionSheet.scrollAnimationEndValue;
|
||||
ActionSheet.hasBounced;
|
||||
|
||||
const _setModalVisible = () => {
|
||||
if (!modalVisible) {
|
||||
setModalVisible(true);
|
||||
if (gestureEnabled) {
|
||||
setScrollable(true);
|
||||
}
|
||||
_setModalVisible = () => {
|
||||
if (!this.state.modalVisible) {
|
||||
this.setState({
|
||||
modalVisible: true,
|
||||
scrollable: this.props.gestureEnabled,
|
||||
});
|
||||
} else {
|
||||
_hideModal();
|
||||
this._hideModal();
|
||||
}
|
||||
};
|
||||
|
||||
const _hideModal = () => {
|
||||
_scrollTo(0);
|
||||
_hideModal = () => {
|
||||
this._scrollTo(0);
|
||||
setTimeout(() => {
|
||||
setLayoutHasCalled(false);
|
||||
setModalVisible(false);
|
||||
ActionSheet.customComponentHeight = null;
|
||||
ActionSheet.prevScroll = null;
|
||||
ActionSheet.scrollAnimationEndValue = null;
|
||||
ActionSheet.hasBounced = null;
|
||||
if (typeof onClose === 'function') onClose();
|
||||
this.setState(
|
||||
{
|
||||
modalVisible: false,
|
||||
layoutHasCalled: false,
|
||||
},
|
||||
() => {
|
||||
if (typeof this.props.onClose === 'function') this.props.onClose();
|
||||
},
|
||||
);
|
||||
}, 150);
|
||||
};
|
||||
|
||||
const _showModal = event => {
|
||||
if (layoutHasCalled) {
|
||||
_showModal = event => {
|
||||
let {gestureEnabled, bounceOffset, initialOffsetFromBottom} = this.props;
|
||||
let addFactor = deviceHeight * 0.1;
|
||||
let height = event.nativeEvent.layout.height;
|
||||
console.log('layout called again');
|
||||
if (this.state.layoutHasCalled) {
|
||||
let diff;
|
||||
if (height > this.customComponentHeight) {
|
||||
diff = height - this.customComponentHeight;
|
||||
this._scrollTo(this.prevScroll + diff);
|
||||
console.log(this.prevScroll);
|
||||
this.customComponentHeight = height;
|
||||
} else {
|
||||
diff = this.customComponentHeight - height;
|
||||
this._scrollTo(this.prevScroll - diff);
|
||||
this.customComponentHeight = height;
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
ActionSheet.customComponentHeight = event.nativeEvent.layout.height;
|
||||
let addFactor = deviceHeight * 0.1;
|
||||
_scrollTo(
|
||||
this.customComponentHeight = height;
|
||||
|
||||
this._scrollTo(
|
||||
gestureEnabled
|
||||
? ActionSheet.customComponentHeight * initialOffsetFromBottom +
|
||||
? this.customComponentHeight * initialOffsetFromBottom +
|
||||
addFactor +
|
||||
bounceOffset
|
||||
: ActionSheet.customComponentHeight + bounceOffset,
|
||||
: this.customComponentHeight + bounceOffset,
|
||||
);
|
||||
|
||||
setLayoutHasCalled(true);
|
||||
this.setState({
|
||||
layoutHasCalled: true,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const _onScrollBeginDrag = event => {
|
||||
_onScrollBeginDrag = event => {
|
||||
let verticalOffset = event.nativeEvent.contentOffset.y;
|
||||
ActionSheet.prevScroll = verticalOffset;
|
||||
|
||||
this.prevScroll = verticalOffset;
|
||||
};
|
||||
|
||||
const _onScrollEndDrag = event => {
|
||||
_onScrollEndDrag = event => {
|
||||
let {springOffset} = this.props;
|
||||
|
||||
let verticalOffset = event.nativeEvent.contentOffset.y;
|
||||
|
||||
if (ActionSheet.prevScroll < verticalOffset) {
|
||||
if (verticalOffset - ActionSheet.prevScroll > springOffset * 0.75) {
|
||||
if (this.prevScroll < verticalOffset) {
|
||||
if (verticalOffset - this.prevScroll > springOffset * 0.75) {
|
||||
let addFactor = deviceHeight * 0.1;
|
||||
_scrollTo(ActionSheet.customComponentHeight + addFactor);
|
||||
this._scrollTo(this.customComponentHeight + addFactor);
|
||||
} else {
|
||||
_scrollTo(ActionSheet.prevScroll);
|
||||
this._scrollTo(this.prevScroll);
|
||||
}
|
||||
} else {
|
||||
if (ActionSheet.prevScroll - verticalOffset > springOffset) {
|
||||
_hideModal();
|
||||
if (this.prevScroll - verticalOffset > springOffset) {
|
||||
this._hideModal();
|
||||
} else {
|
||||
_scrollTo(ActionSheet.prevScroll);
|
||||
this._scrollTo(this.prevScroll);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const _scrollTo = (y, bouncing) => {
|
||||
_scrollTo = (y, bouncing) => {
|
||||
let {bounceOffset, bounceOnOpen} = this.props;
|
||||
|
||||
this.hasBounced = false;
|
||||
if (!bouncing && bounceOnOpen) {
|
||||
ActionSheet.scrollAnimationEndValue = y + bounceOffset;
|
||||
this.scrollAnimationEndValue = y + bounceOffset;
|
||||
} else {
|
||||
ActionSheet.scrollAnimationEndValue = y;
|
||||
this.scrollAnimationEndValue = y;
|
||||
}
|
||||
ActionSheet.hasBounced = false;
|
||||
scrollViewRef.scrollTo({
|
||||
|
||||
this.scrollViewRef.scrollTo({
|
||||
x: 0,
|
||||
y: ActionSheet.scrollAnimationEndValue,
|
||||
y: this.scrollAnimationEndValue,
|
||||
animated: true,
|
||||
});
|
||||
};
|
||||
|
||||
const _onTouchMove = () => {
|
||||
setScrollable(false);
|
||||
_onTouchMove = () => {
|
||||
this._hideModal();
|
||||
this.setState({
|
||||
scrollable: false,
|
||||
});
|
||||
};
|
||||
|
||||
const _onTouchStart = () => {
|
||||
setScrollable(false);
|
||||
_onTouchStart = () => {
|
||||
this._hideModal();
|
||||
this.setState({
|
||||
scrollable: false,
|
||||
});
|
||||
};
|
||||
|
||||
const _onTouchEnd = () => {
|
||||
if (gestureEnabled) {
|
||||
setScrollable(true);
|
||||
_onTouchEnd = () => {
|
||||
if (this.props.gestureEnabled) {
|
||||
this.setState({
|
||||
scrollable: true,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const _onScrollEndAnimation = () => {
|
||||
if (!ActionSheet.hasBounced) {
|
||||
_scrollTo(ActionSheet.scrollAnimationEndValue - bounceOffset, true);
|
||||
ActionSheet.hasBounced = true;
|
||||
_onScrollEndAnimation = event => {
|
||||
this.prevScroll = event.nativeEvent.contentOffset.y;
|
||||
|
||||
let {bounceOffset, bounceOnOpen} = this.props;
|
||||
if (!this.hasBounced && bounceOnOpen) {
|
||||
this._scrollTo(this.scrollAnimationEndValue - bounceOffset, true);
|
||||
this.hasBounced = true;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
ref={ref}
|
||||
visible={modalVisible}
|
||||
animationType={animationType}
|
||||
animated={animated}
|
||||
onShow={() => onOpen}
|
||||
onRequestClose={() => {
|
||||
if (closeOnPressBack) _hideModal();
|
||||
}}
|
||||
transparent={true}>
|
||||
<View style={[styles.parentContainer, {backgroundColor: overlayColor}]}>
|
||||
<ScrollView
|
||||
bounces={false}
|
||||
ref={ref => (scrollViewRef = ref)}
|
||||
showsVerticalScrollIndicator={false}
|
||||
scrollEnabled={scrollable}
|
||||
onScrollBeginDrag={_onScrollBeginDrag}
|
||||
onScrollEndDrag={_onScrollEndDrag}
|
||||
onMomentumScrollEnd={() => {
|
||||
if (bounceOnOpen) {
|
||||
_onScrollEndAnimation();
|
||||
}
|
||||
}}
|
||||
onScrollAnimationEnd={_onScrollEndAnimation}
|
||||
onTouchEnd={_onTouchEnd}
|
||||
overScrollMode="always"
|
||||
style={[styles.scrollview]}>
|
||||
<View
|
||||
onTouchMove={_onTouchMove}
|
||||
onTouchStart={_onTouchStart}
|
||||
onTouchEnd={_onTouchEnd}
|
||||
render() {
|
||||
let {scrollable, modalVisible} = this.state;
|
||||
let {
|
||||
animationType,
|
||||
animated,
|
||||
onOpen,
|
||||
closeOnPressBack,
|
||||
overlayColor,
|
||||
bounceOnOpen,
|
||||
gestureEnabled,
|
||||
elevation,
|
||||
indicatorColor,
|
||||
children,
|
||||
customStyles,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<Modal
|
||||
visible={modalVisible}
|
||||
animationType={animationType}
|
||||
animated={animated}
|
||||
onShow={() => onOpen}
|
||||
onRequestClose={() => {
|
||||
if (closeOnPressBack) this._hideModal();
|
||||
}}
|
||||
transparent={true}>
|
||||
<View style={[styles.parentContainer, {backgroundColor: overlayColor}]}>
|
||||
<KeyboardAvoidingView
|
||||
style={{
|
||||
height: deviceHeight * 1.1,
|
||||
width: '100%',
|
||||
}}>
|
||||
<TouchableOpacity
|
||||
onPress={_hideModal}
|
||||
onLongPress={_hideModal}
|
||||
style={{
|
||||
height: deviceHeight,
|
||||
width: '100%',
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
<View
|
||||
onLayout={_showModal}
|
||||
style={[
|
||||
styles.container,
|
||||
customStyles,
|
||||
{...getElevation(elevation)},
|
||||
]}>
|
||||
{gestureEnabled ? (
|
||||
}}
|
||||
enabled={Platform.OS === 'ios' ? true : false}
|
||||
behavior="position">
|
||||
<ScrollView
|
||||
bounces={false}
|
||||
ref={ref => (this.scrollViewRef = ref)}
|
||||
showsVerticalScrollIndicator={false}
|
||||
scrollEnabled={scrollable}
|
||||
onScrollBeginDrag={this._onScrollBeginDrag}
|
||||
onScrollEndDrag={this._onScrollEndDrag}
|
||||
onMomentumScrollEnd={this._onScrollEndAnimation}
|
||||
onScrollAnimationEnd={this._onScrollEndAnimation}
|
||||
onTouchEnd={this._onTouchEnd}
|
||||
overScrollMode="always"
|
||||
style={[styles.scrollview]}>
|
||||
<View
|
||||
style={[styles.indicator, {backgroundColor: indicatorColor}]}
|
||||
/>
|
||||
) : null}
|
||||
onTouchMove={this._onTouchMove}
|
||||
onTouchStart={this._onTouchStart}
|
||||
onTouchEnd={this._onTouchEnd}
|
||||
style={{
|
||||
height: deviceHeight * 1.1,
|
||||
width: '100%',
|
||||
}}>
|
||||
<TouchableOpacity
|
||||
onPress={this._hideModal}
|
||||
onLongPress={this._hideModal}
|
||||
style={{
|
||||
height: deviceHeight,
|
||||
width: '100%',
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
<View
|
||||
onLayout={this._showModal}
|
||||
style={[
|
||||
styles.container,
|
||||
customStyles,
|
||||
{...getElevation(elevation)},
|
||||
]}>
|
||||
{gestureEnabled ? (
|
||||
<View
|
||||
style={[
|
||||
styles.indicator,
|
||||
{backgroundColor: indicatorColor},
|
||||
]}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
{children}
|
||||
</View>
|
||||
</ScrollView>
|
||||
</View>
|
||||
</Modal>
|
||||
);
|
||||
{children}
|
||||
</View>
|
||||
</ScrollView>
|
||||
</KeyboardAvoidingView>
|
||||
</View>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ActionSheet.defaultProps = {
|
||||
children: <View />,
|
||||
animated: true,
|
||||
animationType: 'fade',
|
||||
closeOnPressBack: true,
|
||||
gestureEnabled: true,
|
||||
bounceOnOpen: true,
|
||||
bounceOffset: 20,
|
||||
springOffset: 50,
|
||||
elevation: 5,
|
||||
initialOffsetFromBottom: 0.6,
|
||||
indicatorColor: 'gray',
|
||||
customStyles: {},
|
||||
overlayColor: 'rgba(0,0,0,0.3)',
|
||||
onClose: () => {},
|
||||
onOpen: () => {},
|
||||
};
|
||||
ActionSheet.propTypes = {
|
||||
children: PropTypes.node,
|
||||
animated: PropTypes.bool,
|
||||
animationType: PropTypes.oneOf(['none', 'slide', 'fade']),
|
||||
closeOnPressBack: PropTypes.bool,
|
||||
gestureEnabled: PropTypes.bool,
|
||||
bounceOnOpen: PropTypes.bool,
|
||||
bounceOffset: PropTypes.number,
|
||||
springOffset: PropTypes.number,
|
||||
elevation: PropTypes.number,
|
||||
initialOffsetFromBottom: PropTypes.number,
|
||||
indicatorColor: PropTypes.string,
|
||||
customStyles: PropTypes.object,
|
||||
overlayColor: PropTypes.string,
|
||||
onClose: PropTypes.func,
|
||||
onOpen: PropTypes.func,
|
||||
};
|
||||
|
||||
export default ActionSheet;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, {useState} from 'react';
|
||||
import React, {useState, useEffect} from 'react';
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
@@ -28,7 +28,7 @@ const h = Dimensions.get('window').height;
|
||||
let tagsInputRef;
|
||||
export const ActionSheetComponent = ({
|
||||
close = () => {},
|
||||
item = {},
|
||||
item,
|
||||
setWillRefresh = value => {},
|
||||
hasColors = false,
|
||||
hasTags = false,
|
||||
@@ -39,6 +39,10 @@ export const ActionSheetComponent = ({
|
||||
const [focused, setFocused] = useState(false);
|
||||
const [note, setNote] = useState(item ? item : {});
|
||||
|
||||
useEffect(() => {
|
||||
setNote({...item});
|
||||
}, [item]);
|
||||
|
||||
let tagToAdd = null;
|
||||
let backPressCount = 0;
|
||||
|
||||
@@ -257,6 +261,10 @@ export const ActionSheetComponent = ({
|
||||
|
||||
return (
|
||||
<View
|
||||
onLayout={() => {
|
||||
console.log(item);
|
||||
setNote({...item});
|
||||
}}
|
||||
style={{
|
||||
paddingBottom: 15,
|
||||
backgroundColor: colors.bg,
|
||||
|
||||
Reference in New Issue
Block a user