Skip to content

Feat/drawer left toggle #844

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jul 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 76 additions & 41 deletions demo/src/screens/componentScreens/DrawerScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import {
Drawer,
Text,
Button,
Avatar
Avatar,
Badge
} from 'react-native-ui-lib'; //eslint-disable-line
import {gestureHandlerRootHOC} from 'react-native-gesture-handler';
import conversations from '../../data/conversations';
Expand Down Expand Up @@ -46,7 +47,8 @@ class DrawerScreen extends Component {
showRightItems: true,
fullSwipeRight: true,
showLeftItem: true,
fullSwipeLeft: true
fullSwipeLeft: true,
unread: true
};
}

Expand All @@ -56,7 +58,7 @@ class DrawerScreen extends Component {
}
}

onFullSwipe = () => {
deleteItem = () => {
// TODO: consider including this functionality as part of the drawer component
setTimeout(() => {
LayoutAnimation.configureNext({
Expand All @@ -75,6 +77,14 @@ class DrawerScreen extends Component {
}, 200);
};

toggleReadState = () => {
this.setState({unread: !this.state.unread}); // setState will close the Drawer
}

triggerLeftToggleHaptic = () => {
// console.warn('haptic trigger here');
}

showItem = () => {
this.setState({hideItem: false});
};
Expand All @@ -89,6 +99,11 @@ class DrawerScreen extends Component {
this.ref.openLeftFull();
}
};
toggleLeftDrawer = () => {
if (this.ref) {
this.ref.toggleLeft();
}
};
openRightDrawer = () => {
if (this.ref) {
this.ref.openRight();
Expand All @@ -110,38 +125,50 @@ class DrawerScreen extends Component {
<View center marginB-s4>
<Text text70>Actions</Text>
<View row>
<Button
onPress={this.openLeftDrawer}
label="Open left"
style={{margin: 3}}
size={'xSmall'}
/>
<Button
onPress={this.closeDrawer}
label="Close"
style={{margin: 3}}
size={'xSmall'}
/>
<Button
onPress={this.openRightDrawer}
label="Open right"
style={{margin: 3}}
size={'xSmall'}
/>
</View>
<View row>
<Button
onPress={this.openLeftDrawerFull}
label="Open left full"
style={{margin: 3}}
size={'xSmall'}
/>
<Button
onPress={this.openRightDrawerFull}
label="Open right full"
style={{margin: 3}}
size={'xSmall'}
/>
<View>
<Button
onPress={this.openLeftDrawer}
label="Open left"
style={{margin: 3}}
size={'xSmall'}
/>
<Button
onPress={this.openLeftDrawerFull}
label="Full left swipe"
style={{margin: 3}}
size={'xSmall'}
/>
<Button
onPress={this.toggleLeftDrawer}
label="Left toggle"
style={{margin: 3}}
size={'xSmall'}
/>
</View>

<View marginH-20>
<Button
onPress={this.closeDrawer}
label="Close"
style={{margin: 3}}
size={'xSmall'}
/>
</View>

<View>
<Button
onPress={this.openRightDrawer}
label="Open right"
style={{margin: 3}}
size={'xSmall'}
/>
<Button
onPress={this.openRightDrawerFull}
label="Full right swipe"
style={{margin: 3}}
size={'xSmall'}
/>
</View>
</View>
</View>
);
Expand All @@ -157,9 +184,10 @@ class DrawerScreen extends Component {
centerV
style={{borderBottomWidth: 1, borderColor: Colors.grey60}}
>
<Avatar source={{uri: conversations[0].thumbnail}} />
{this.state.unread && <Badge size={'pimpleBig'} backgroundColor={Colors.purple30} containerStyle={{marginRight: 8}}/>}
<Avatar source={{uri: conversations[0].thumbnail}}/>
<View marginL-20>
<Text text70R>{conversations[0].name}</Text>
<Text text70R={!this.state.unread} text70BO={this.state.unread}>{conversations[0].name}</Text>
<Text text80 marginT-2>
{conversations[0].text}
</Text>
Expand All @@ -186,16 +214,23 @@ class DrawerScreen extends Component {
bounciness,
ref: (component) => (this.ref = component),
fullSwipeRight,
onFullSwipeRight: this.onFullSwipe,
onFullSwipeRight: this.deleteItem,
fullSwipeLeft,
onWillFullSwipeLeft: this.onFullSwipe
onWillFullSwipeLeft: this.deleteItem,
onToggleSwipeLeft: this.toggleReadState,
leftToggleHapticTrigger: this.triggerLeftToggleHaptic
};
if (showRightItems) {
drawerProps.rightItems = [ITEMS.read, ITEMS.archive];
drawerProps.rightItems = [{...ITEMS.delete, onPress: this.deleteItem}, ITEMS.archive];
}

if (showLeftItem) {
drawerProps.leftItem = ITEMS.delete;
drawerProps.leftItem = {
icon: require('../../assets/icons/mail.png'),
text: this.state.unread ? 'Read' : 'Unread',
background: this.state.unread ? Colors.green30 : Colors.purple30,
onPress: this.toggleReadState
};
}

return (
Expand Down
43 changes: 37 additions & 6 deletions src/components/drawer/Swipeable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {Constants} from '../../helpers';


const DRAG_TOSS = 0.05;
const LEFT_TOGGLE_THRESHOLD = 0.6;

// Math.sign polyfill for iOS 8.x
if (!Math.sign) {
Expand Down Expand Up @@ -43,6 +44,7 @@ export type PropType = {
onSwipeableWillOpen?: Function,
onSwipeableWillClose?: Function,
onFullSwipeLeft?: Function,
onToggleSwipeLeft?: Function,
onWillFullSwipeLeft?: Function,
onFullSwipeRight?: Function,
onWillFullSwipeRight?: Function,
Expand Down Expand Up @@ -88,6 +90,7 @@ export default class Swipeable extends Component<PropType, StateType> {
// 1 -> closing to the left
// -1 -> closing to the right
this.rowState = 0;
this.dragFired = false;

this.state = {
dragX,
Expand All @@ -101,10 +104,25 @@ export default class Swipeable extends Component<PropType, StateType> {
this._updateAnimatedEvent(props, this.state);

this._onGestureEvent = Animated.event([{nativeEvent: {translationX: dragX}}], {
useNativeDriver: props.useNativeAnimations
useNativeDriver: props.useNativeAnimations,
listener: this._handleDrag
});
}

_handleDrag = (e) => {
const {onToggleSwipeLeft} = this.props;

if (onToggleSwipeLeft && !this.dragFired) {
const {rowWidth, leftWidth} = this.state;
const x = e.nativeEvent.translationX;
const threshold = rowWidth * LEFT_TOGGLE_THRESHOLD;
if (x >= threshold && x < threshold + 10) {
this.dragFired = true;
onToggleSwipeLeft({rowWidth, leftWidth, dragX: x});
}
}
}

// TODO: change to componentDidUpdate
UNSAFE_componentWillUpdate(props: PropType, state: StateType) {
if (
Expand Down Expand Up @@ -197,14 +215,18 @@ export default class Swipeable extends Component<PropType, StateType> {
const {leftWidth = 0, rowWidth = 0} = this.state;
const {rightOffset = rowWidth} = this.state;
const rightWidth = rowWidth - rightOffset;
const {fullSwipeLeft, fullSwipeRight, friction, leftThreshold = leftWidth / 2, rightThreshold = rightWidth / 2, fullLeftThreshold, fullRightThreshold} = this.props;
const {fullSwipeLeft, fullSwipeRight, friction, leftThreshold = leftWidth / 2, rightThreshold = rightWidth / 2, fullLeftThreshold, fullRightThreshold, onToggleSwipeLeft} = this.props;

const startOffsetX = this._currentOffset() + dragX / friction;
const translationX = (dragX + DRAG_TOSS * velocityX) / friction;

let toValue = 0;
if (this.rowState === 0) {
if (fullSwipeLeft && translationX > rowWidth * fullLeftThreshold) {
if (onToggleSwipeLeft && translationX > leftWidth) {
if (!this.dragFired) {
toValue = rowWidth * LEFT_TOGGLE_THRESHOLD;
}
} else if (fullSwipeLeft && translationX > rowWidth * fullLeftThreshold) {
toValue = rowWidth;
} else if (fullSwipeRight && translationX < -rowWidth * fullRightThreshold) {
toValue = -rowWidth;
Expand All @@ -229,7 +251,7 @@ export default class Swipeable extends Component<PropType, StateType> {
};

_animateRow = (fromValue, toValue, velocityX) => {
const {dragX, rowTranslation, rowWidth} = this.state;
const {dragX, rowTranslation, rowWidth, leftWidth} = this.state;
const {
useNativeAnimations,
animationOptions,
Expand All @@ -242,6 +264,8 @@ export default class Swipeable extends Component<PropType, StateType> {
onSwipeableWillClose,
onSwipeableWillOpen,
onFullSwipeLeft,
fullSwipeLeft,
onToggleSwipeLeft,
onWillFullSwipeLeft,
onFullSwipeRight,
onWillFullSwipeRight
Expand All @@ -260,7 +284,7 @@ export default class Swipeable extends Component<PropType, StateType> {
useNativeDriver: useNativeAnimations,
...animationOptions
}).start(({finished}) => {
if (finished) {
if (finished) {
if (toValue === rowWidth && onFullSwipeLeft) {
onFullSwipeLeft();
} else if (toValue === -rowWidth && onFullSwipeRight) {
Expand All @@ -279,7 +303,9 @@ export default class Swipeable extends Component<PropType, StateType> {
}
});

if (toValue === rowWidth && onWillFullSwipeLeft) {
if (toValue === rowWidth * LEFT_TOGGLE_THRESHOLD && onToggleSwipeLeft) {
onToggleSwipeLeft({rowWidth, leftWidth});
} else if (toValue === rowWidth && onWillFullSwipeLeft) {
onWillFullSwipeLeft()
} else if (toValue === -rowWidth && onWillFullSwipeRight) {
onWillFullSwipeRight()
Expand Down Expand Up @@ -323,6 +349,11 @@ export default class Swipeable extends Component<PropType, StateType> {
this._animateRow(this._currentOffset(), rowWidth);
};

toggleLeft = () => {
const {rowWidth} = this.state;
this._animateRow(this._currentOffset(), rowWidth * LEFT_TOGGLE_THRESHOLD);
};

openRight = () => {
const {rowWidth = 0} = this.state;
const {rightOffset = rowWidth} = this.state;
Expand Down
Loading