From 4a0195762d7986cf73dbcdcf1c030a9449127bf1 Mon Sep 17 00:00:00 2001 From: Rajarshee Chatterjee Date: Wed, 25 Aug 2021 08:52:51 +0530 Subject: [PATCH] Cross fade --- src/components/Common/CrossFadeView.js | 110 ++++++++++++ .../Chapter/components/ChapterAppbar.js | 30 ++-- .../Chapter/components/ChapterFooter.js | 11 +- .../Chapter/components/VerticalScrollbar.js | 162 +++++++++--------- src/screens/Novel/Novel.js | 25 +-- 5 files changed, 230 insertions(+), 108 deletions(-) create mode 100644 src/components/Common/CrossFadeView.js diff --git a/src/components/Common/CrossFadeView.js b/src/components/Common/CrossFadeView.js new file mode 100644 index 00000000..c75f5271 --- /dev/null +++ b/src/components/Common/CrossFadeView.js @@ -0,0 +1,110 @@ +import PropTypes from "prop-types"; +import React, { PureComponent, Children } from "react"; +import { View, Animated, StyleSheet } from "react-native"; + +export default class FadeView extends PureComponent { + static defaultProps = { + animationDuration: 225, + + active: false, + removeHiddenSubviews: true, + }; + + static propTypes = { + animationDuration: PropTypes.number, + + active: PropTypes.bool, + removeHiddenSubviews: PropTypes.bool, + + children: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.node), + PropTypes.node, + ]), + }; + + constructor(props) { + super(props); + + this.renderChild = this.renderChild.bind(this); + this.mounted = false; + + let { active } = this.props; + + this.state = { + progress: new Animated.Value(Number(active)), + animating: false, + }; + } + + componentDidMount() { + this.mounted = true; + } + + componentWillUnmount() { + this.mounted = false; + } + + componentWillReceiveProps({ active, animationDuration }) { + let { progress } = this.state; + + if (active ^ this.props.active) { + this.setState({ animating: true }); + + Animated.timing(progress, { + toValue: Number(active), + duration: animationDuration, + useNativeDriver: true, + }).start(() => { + if (this.mounted) { + this.setState({ animating: false }); + } + }); + } + } + + renderChild(child, index) { + let { active, removeHiddenSubviews } = this.props; + let { animating, progress } = this.state; + + let opacity = progress.interpolate({ + inputRange: [0, 1], + outputRange: index ? [0, 1] : [1, 0], + }); + + let hidden = active ^ !!index; + + if (removeHiddenSubviews) { + if (!animating && hidden) { + return null; + } + } + + let pointerEvents = hidden ? "none" : "box-none"; + + return ( + + {child} + + ); + } + + render() { + let { children, ...props } = this.props; + + return ( + {Children.map(children, this.renderChild)} + ); + } +} + +const styles = StyleSheet.create({ + container: { + // ...StyleSheet.absoluteFillObject, + flexDirection: "row", + justifyContent: "center", + alignItems: "center", + }, +}); diff --git a/src/screens/Chapter/components/ChapterAppbar.js b/src/screens/Chapter/components/ChapterAppbar.js index 4b4c4b79..f2ca0b42 100644 --- a/src/screens/Chapter/components/ChapterAppbar.js +++ b/src/screens/Chapter/components/ChapterAppbar.js @@ -2,6 +2,7 @@ import React, { useState } from "react"; import { View } from "react-native"; import { Appbar } from "react-native-paper"; +import FadeView from "../../../components/Common/CrossFadeView"; import { bookmarkChapterAction } from "../../../redux/novel/novel.actions"; const ChapterAppbar = ({ @@ -16,19 +17,20 @@ const ChapterAppbar = ({ }) => { const [bookmarked, setBookmarked] = useState(bookmark); - if (hide) { - return null; - } else { - return ( + return ( + - ); - } + + ); }; export default ChapterAppbar; diff --git a/src/screens/Chapter/components/ChapterFooter.js b/src/screens/Chapter/components/ChapterFooter.js index fa94e840..fefc27ec 100644 --- a/src/screens/Chapter/components/ChapterFooter.js +++ b/src/screens/Chapter/components/ChapterFooter.js @@ -1,6 +1,7 @@ import React from "react"; import { Pressable, StyleSheet, View } from "react-native"; import { IconButton } from "react-native-paper"; +import FadeView from "../../../components/Common/CrossFadeView"; const ChapterFooter = ({ hide, @@ -22,10 +23,8 @@ const ChapterFooter = ({ radius: 50, }; - if (hide) { - return null; - } else { - return ( + return ( + - ); - } + + ); }; export default ChapterFooter; diff --git a/src/screens/Chapter/components/VerticalScrollbar.js b/src/screens/Chapter/components/VerticalScrollbar.js index 3d8fd5b0..621d4b4a 100644 --- a/src/screens/Chapter/components/VerticalScrollbar.js +++ b/src/screens/Chapter/components/VerticalScrollbar.js @@ -3,6 +3,7 @@ import { Dimensions, View, Text, StyleSheet } from "react-native"; import Slider from "@react-native-community/slider"; import { getDeviceOrientation } from "../../../services/utils/helpers"; +import FadeView from "../../../components/Common/CrossFadeView"; const VerticalScrollbar = ({ theme, @@ -22,84 +23,95 @@ const VerticalScrollbar = ({ setLoading(false); }; - if (hide) { - return null; - } else if (getDeviceOrientation() === "potrait") { + if (getDeviceOrientation() === "potrait") { return ( - - - {scrollPercentage} - - - - 100 - - + + {scrollPercentage} + + + + 100 + + + ); } else { return ( - - - {scrollPercentage} - - - - 100 - - + + + + {scrollPercentage} + + + + 100 + + + ); } }; @@ -108,11 +120,6 @@ export default VerticalScrollbar; const styles = StyleSheet.create({ verticalSliderContainer: { - position: "absolute", - zIndex: 2, - right: -(Dimensions.get("window").width / 2) + 40, - bottom: 300, - backgroundColor: "rgba(0,0,0,0.7)", flexDirection: "row", justifyContent: "flex-end", alignItems: "center", @@ -124,7 +131,6 @@ const styles = StyleSheet.create({ position: "absolute", zIndex: 2, bottom: 100, - backgroundColor: "rgba(0,0,0,0.7)", flexDirection: "row", justifyContent: "flex-end", alignItems: "center", diff --git a/src/screens/Novel/Novel.js b/src/screens/Novel/Novel.js index 0df48c96..33e45c77 100644 --- a/src/screens/Novel/Novel.js +++ b/src/screens/Novel/Novel.js @@ -44,6 +44,7 @@ import JumpToChapterModal from "./components/JumpToChapterModal"; import { Actionbar } from "../../components/Actionbar/Actionbar"; import EditInfoModal from "./components/EditInfoModal"; import { setCustomNovelCover } from "../../database/queries/NovelQueries"; +import FadeView from "../../components/Common/CrossFadeView"; const Novel = ({ route, navigation }) => { const item = route.params; @@ -198,26 +199,29 @@ const Novel = ({ route, navigation }) => { { backgroundColor: theme.colorPrimaryDark }, ]} > - {selected.length > 0 ? ( + { - setSelected([]); - }} + onPress={() => setSelected([])} /> { }} /> - ) : ( + + {selected.length == 0 && (