diff --git a/src/components/Custom/AnimatedBottomBar.js b/src/components/Custom/AnimatedBottomBar.js new file mode 100644 index 0000000..1970416 --- /dev/null +++ b/src/components/Custom/AnimatedBottomBar.js @@ -0,0 +1,64 @@ +// @flow + +import * as React from 'react'; +import {StyleSheet} from "react-native"; +import {IconButton, withTheme} from "react-native-paper"; +import {AnimatedValue} from "react-native-reanimated"; +import AutoHideComponent from "./AutoHideComponent"; + +type Props = { + theme: Object, +} + +type State = { + fabPosition: AnimatedValue +} + +class AnimatedBottomBar extends React.Component { + + ref: Object; + + constructor() { + super(); + this.ref = React.createRef(); + } + + onScroll = (event: Object) => { + this.ref.current.onScroll(event); + }; + + render() { + return ( + + console.log('previous')}/> + console.log('next')}/> + + ); + } +} + +const styles = StyleSheet.create({ + bottom: { + flexDirection: 'row', + justifyContent: 'flex-end', + alignItems: 'center', + position: 'absolute', + left: 0, + bottom: 0, + width: '100%', + height: 100, + }, +}); + +export default withTheme(AnimatedBottomBar); diff --git a/src/components/Custom/AnimatedFAB.js b/src/components/Custom/AnimatedFAB.js new file mode 100644 index 0000000..db918db --- /dev/null +++ b/src/components/Custom/AnimatedFAB.js @@ -0,0 +1,52 @@ +// @flow + +import * as React from 'react'; +import {StyleSheet} from "react-native"; +import {FAB} from "react-native-paper"; +import {AnimatedValue} from "react-native-reanimated"; +import AutoHideComponent from "./AutoHideComponent"; + +type Props = { + icon: string, + onPress: Function, +} + +type State = { + fabPosition: AnimatedValue +} + +export default class AnimatedFAB extends React.Component { + + ref: Object; + + constructor() { + super(); + this.ref = React.createRef(); + } + + onScroll = (event: Object) => { + this.ref.current.onScroll(event); + }; + + render() { + return ( + + + + ); + } +} + +const styles = StyleSheet.create({ + fab: { + position: 'absolute', + margin: 16, + right: 0, + bottom: 0, + }, +}); diff --git a/src/components/Custom/AutoHideComponent.js b/src/components/Custom/AutoHideComponent.js new file mode 100644 index 0000000..3d2a51b --- /dev/null +++ b/src/components/Custom/AutoHideComponent.js @@ -0,0 +1,74 @@ +// @flow + +import * as React from 'react'; +import {Animated} from 'react-native' +import {AnimatedValue} from "react-native-reanimated"; + +type Props = { + children: React.Node, + style: Object, +} + +type State = { + fabPosition: AnimatedValue +} + +export default class AutoHideComponent extends React.Component { + + isAnimationDownPlaying: boolean; + isAnimationUpPlaying: boolean; + + downAnimation; + upAnimation; + + state = { + fabPosition: new Animated.Value(0), + }; + + constructor() { + super(); + } + + onScroll({nativeEvent}: Object) { + if (nativeEvent.velocity.y > 0.2) { // Go down + if (!this.isAnimationDownPlaying) { + this.isAnimationDownPlaying = true; + if (this.isAnimationUpPlaying) + this.upAnimation.stop(); + this.downAnimation = Animated.spring(this.state.fabPosition, { + toValue: 100, + duration: 50, + useNativeDriver: true, + }); + this.downAnimation.start(() => { + this.isAnimationDownPlaying = false + }); + } + } else if (nativeEvent.velocity.y < -0.2) { // Go up + if (!this.isAnimationUpPlaying) { + this.isAnimationUpPlaying = true; + if (this.isAnimationDownPlaying) + this.downAnimation.stop(); + this.upAnimation = Animated.spring(this.state.fabPosition, { + toValue: 0, + duration: 50, + useNativeDriver: true, + }); + this.upAnimation.start(() => { + this.isAnimationUpPlaying = false + }); + } + } + } + + render() { + return ( + + {this.props.children} + + ); + } +} \ No newline at end of file diff --git a/src/components/Screens/WebViewScreen.js b/src/components/Screens/WebViewScreen.js index 929ae4d..ee0c4f2 100644 --- a/src/components/Screens/WebViewScreen.js +++ b/src/components/Screens/WebViewScreen.js @@ -18,6 +18,7 @@ type Props = { customJS: string, collapsibleStack: Object, onMessage: Function, + onScroll: Function, } const AnimatedWebView = Animated.createAnimatedComponent(WebView); @@ -155,7 +156,7 @@ class WebViewScreen extends React.PureComponent { } render() { - const {containerPaddingTop, onScroll} = this.props.collapsibleStack; + const {containerPaddingTop, onScrollWithListener} = this.props.collapsibleStack; const customJS = this.getJavascriptPadding(containerPaddingTop); return ( { }} onMessage={this.props.onMessage} // Animations - onScroll={onScroll} + onScroll={onScrollWithListener(this.props.onScroll)} /> ); } diff --git a/src/screens/HomeScreen.js b/src/screens/HomeScreen.js index 38e8085..2277908 100644 --- a/src/screens/HomeScreen.js +++ b/src/screens/HomeScreen.js @@ -1,11 +1,11 @@ // @flow import * as React from 'react'; -import {Animated, FlatList, StyleSheet, View} from 'react-native'; +import {Animated, FlatList, View} from 'react-native'; import i18n from "i18n-js"; import DashboardItem from "../components/Home/EventDashboardItem"; import WebSectionList from "../components/Lists/WebSectionList"; -import {FAB, withTheme} from 'react-native-paper'; +import {withTheme} from 'react-native-paper'; import FeedItem from "../components/Home/FeedItem"; import SquareDashboardItem from "../components/Home/SmallDashboardItem"; import PreviewEventDashboardItem from "../components/Home/PreviewEventDashboardItem"; @@ -15,6 +15,7 @@ import ConnectionManager from "../managers/ConnectionManager"; import {CommonActions} from '@react-navigation/native'; import MaterialHeaderButtons, {Item} from "../components/Custom/HeaderButton"; import {AnimatedValue} from "react-native-reanimated"; +import AnimatedFAB from "../components/Custom/AnimatedFAB"; // import DATA from "../dashboard_data.json"; @@ -27,8 +28,6 @@ const SECTIONS_ID = [ 'news_feed' ]; -const AnimatedFAB = Animated.createAnimatedComponent(FAB); - const REFRESH_TIME = 1000 * 20; // Refresh every 20 seconds type Props = { @@ -38,7 +37,6 @@ type Props = { } type State = { - showFab: boolean, fabPosition: AnimatedValue } @@ -50,23 +48,18 @@ class HomeScreen extends React.Component { colors: Object; isLoggedIn: boolean | null; - isAnimationDownPlaying: boolean; - isAnimationUpPlaying: boolean; - downAnimation; - upAnimation; + fabRef: Object; state = { - showFab: true, fabPosition: new Animated.Value(0), }; constructor(props) { super(props); this.colors = props.theme.colors; - this.isAnimationDownPlaying = false; - this.isAnimationUpPlaying = false; this.isLoggedIn = null; + this.fabRef = React.createRef(); } /** @@ -460,36 +453,8 @@ class HomeScreen extends React.Component { openScanner = () => this.props.navigation.navigate("scanner"); - onScroll = ({nativeEvent}: Object) => { - if (nativeEvent.velocity.y > 0.2) { // Go down - if (!this.isAnimationDownPlaying) { - this.isAnimationDownPlaying = true; - if (this.isAnimationUpPlaying) - this.upAnimation.stop(); - this.downAnimation = Animated.spring(this.state.fabPosition, { - toValue: 100, - duration: 50, - useNativeDriver: true, - }); - this.downAnimation.start(() => { - this.isAnimationDownPlaying = false - }); - } - } else if (nativeEvent.velocity.y < -0.2) { // Go up - if (!this.isAnimationUpPlaying) { - this.isAnimationUpPlaying = true; - if (this.isAnimationDownPlaying) - this.downAnimation.stop(); - this.upAnimation = Animated.spring(this.state.fabPosition, { - toValue: 0, - duration: 50, - useNativeDriver: true, - }); - this.upAnimation.start(() => { - this.isAnimationUpPlaying = false - }); - } - } + onScroll = (event: Object) => { + this.fabRef.current.onScroll(event); }; render() { @@ -507,10 +472,7 @@ class HomeScreen extends React.Component { onScroll={this.onScroll} /> @@ -519,13 +481,4 @@ class HomeScreen extends React.Component { } } -const styles = StyleSheet.create({ - fab: { - position: 'absolute', - margin: 16, - right: 0, - bottom: 0, - }, -}); - export default withTheme(HomeScreen); diff --git a/src/screens/Websites/PlanexScreen.js b/src/screens/Websites/PlanexScreen.js index 3c80667..3d86f50 100644 --- a/src/screens/Websites/PlanexScreen.js +++ b/src/screens/Websites/PlanexScreen.js @@ -3,7 +3,7 @@ import * as React from 'react'; import ThemeManager from "../../managers/ThemeManager"; import WebViewScreen from "../../components/Screens/WebViewScreen"; -import {Avatar, Banner} from "react-native-paper"; +import {Avatar, Banner, withTheme} from "react-native-paper"; import i18n from "i18n-js"; import {View} from "react-native"; import AsyncStorageManager from "../../managers/AsyncStorageManager"; @@ -11,9 +11,11 @@ import AlertDialog from "../../components/Dialog/AlertDialog"; import {withCollapsible} from "../../utils/withCollapsible"; import {dateToString, getTimeOnlyString} from "../../utils/Planning"; import DateManager from "../../managers/DateManager"; +import AnimatedBottomBar from "../../components/Custom/AnimatedBottomBar"; type Props = { navigation: Object, + theme: Object, collapsibleStack: Object, } @@ -115,6 +117,7 @@ const LISTEN_TO_MESSAGES = class PlanexScreen extends React.Component { webScreenRef: Object; + barRef: Object; customInjectedJS: string; onHideBanner: Function; @@ -134,6 +137,7 @@ class PlanexScreen extends React.Component { constructor() { super(); this.webScreenRef = React.createRef(); + this.barRef = React.createRef(); this.customInjectedJS = "$(document).ready(function() {" + OBSERVE_MUTATIONS_INJECTED + @@ -174,9 +178,8 @@ class PlanexScreen extends React.Component { this.props.navigation.navigate('settings'); } - sendMessage = () => { - let data= 'coucou' - this.webScreenRef.current.postMessage(data); + sendMessage = (msg: string) => { + this.webScreenRef.current.postMessage(msg); } onMessage = (event: Object) => { @@ -202,6 +205,10 @@ class PlanexScreen extends React.Component { }); }; + onScroll = (event: Object) => { + this.barRef.current.onScroll(event); + }; + render() { const nav = this.props.navigation; const {containerPaddingTop} = this.props.collapsibleStack; @@ -243,10 +250,12 @@ class PlanexScreen extends React.Component { url={PLANEX_URL} customJS={this.customInjectedJS} onMessage={this.onMessage} + onScroll={this.onScroll} /> + ); } } -export default withCollapsible(PlanexScreen); \ No newline at end of file +export default withCollapsible(withTheme(PlanexScreen)); \ No newline at end of file