Application Android et IOS pour l'amicale des élèves
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AnimatedBottomBar.js 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. // @flow
  2. import * as React from 'react';
  3. import {StyleSheet, View} from 'react-native';
  4. import {FAB, IconButton, Surface, withTheme} from 'react-native-paper';
  5. import * as Animatable from 'react-native-animatable';
  6. import {StackNavigationProp} from '@react-navigation/stack';
  7. import AutoHideHandler from '../../utils/AutoHideHandler';
  8. import CustomTabBar from '../Tabbar/CustomTabBar';
  9. import type {CustomThemeType} from '../../managers/ThemeManager';
  10. import type {OnScrollType} from '../../utils/AutoHideHandler';
  11. const AnimatedFAB = Animatable.createAnimatableComponent(FAB);
  12. type PropsType = {
  13. navigation: StackNavigationProp,
  14. theme: CustomThemeType,
  15. onPress: (action: string, data?: string) => void,
  16. seekAttention: boolean,
  17. };
  18. type StateType = {
  19. currentMode: string,
  20. };
  21. const DISPLAY_MODES = {
  22. DAY: 'agendaDay',
  23. WEEK: 'agendaWeek',
  24. MONTH: 'month',
  25. };
  26. const styles = StyleSheet.create({
  27. container: {
  28. position: 'absolute',
  29. left: '5%',
  30. width: '90%',
  31. },
  32. surface: {
  33. position: 'relative',
  34. flexDirection: 'row',
  35. justifyContent: 'space-between',
  36. alignItems: 'center',
  37. borderRadius: 50,
  38. elevation: 2,
  39. },
  40. fabContainer: {
  41. position: 'absolute',
  42. left: 0,
  43. right: 0,
  44. alignItems: 'center',
  45. width: '100%',
  46. height: '100%',
  47. },
  48. fab: {
  49. position: 'absolute',
  50. alignSelf: 'center',
  51. top: '-25%',
  52. },
  53. });
  54. class AnimatedBottomBar extends React.Component<PropsType, StateType> {
  55. ref: {current: null | Animatable.View};
  56. hideHandler: AutoHideHandler;
  57. displayModeIcons: {[key: string]: string};
  58. constructor() {
  59. super();
  60. this.state = {
  61. currentMode: DISPLAY_MODES.WEEK,
  62. };
  63. this.ref = React.createRef();
  64. this.hideHandler = new AutoHideHandler(false);
  65. this.hideHandler.addListener(this.onHideChange);
  66. this.displayModeIcons = {};
  67. this.displayModeIcons[DISPLAY_MODES.DAY] = 'calendar-text';
  68. this.displayModeIcons[DISPLAY_MODES.WEEK] = 'calendar-week';
  69. this.displayModeIcons[DISPLAY_MODES.MONTH] = 'calendar-range';
  70. }
  71. shouldComponentUpdate(nextProps: PropsType, nextState: StateType): boolean {
  72. const {props, state} = this;
  73. return (
  74. nextProps.seekAttention !== props.seekAttention ||
  75. nextState.currentMode !== state.currentMode
  76. );
  77. }
  78. onHideChange = (shouldHide: boolean) => {
  79. if (this.ref.current != null) {
  80. if (shouldHide) this.ref.current.fadeOutDown(500);
  81. else this.ref.current.fadeInUp(500);
  82. }
  83. };
  84. onScroll = (event: OnScrollType) => {
  85. this.hideHandler.onScroll(event);
  86. };
  87. changeDisplayMode = () => {
  88. const {props, state} = this;
  89. let newMode;
  90. switch (state.currentMode) {
  91. case DISPLAY_MODES.DAY:
  92. newMode = DISPLAY_MODES.WEEK;
  93. break;
  94. case DISPLAY_MODES.WEEK:
  95. newMode = DISPLAY_MODES.MONTH;
  96. break;
  97. case DISPLAY_MODES.MONTH:
  98. newMode = DISPLAY_MODES.DAY;
  99. break;
  100. default:
  101. newMode = DISPLAY_MODES.WEEK;
  102. break;
  103. }
  104. this.setState({currentMode: newMode});
  105. props.onPress('changeView', newMode);
  106. };
  107. render(): React.Node {
  108. const {props, state} = this;
  109. const buttonColor = props.theme.colors.primary;
  110. return (
  111. <Animatable.View
  112. ref={this.ref}
  113. useNativeDriver
  114. style={{
  115. ...styles.container,
  116. bottom: 10 + CustomTabBar.TAB_BAR_HEIGHT,
  117. }}>
  118. <Surface style={styles.surface}>
  119. <View style={styles.fabContainer}>
  120. <AnimatedFAB
  121. animation={props.seekAttention ? 'bounce' : undefined}
  122. easing="ease-out"
  123. iterationDelay={500}
  124. iterationCount="infinite"
  125. useNativeDriver
  126. style={styles.fab}
  127. icon="account-clock"
  128. onPress={(): void => props.navigation.navigate('group-select')}
  129. />
  130. </View>
  131. <View style={{flexDirection: 'row'}}>
  132. <IconButton
  133. icon={this.displayModeIcons[state.currentMode]}
  134. color={buttonColor}
  135. onPress={this.changeDisplayMode}
  136. />
  137. <IconButton
  138. icon="clock-in"
  139. color={buttonColor}
  140. style={{marginLeft: 5}}
  141. onPress={(): void => props.onPress('today')}
  142. />
  143. </View>
  144. <View style={{flexDirection: 'row'}}>
  145. <IconButton
  146. icon="chevron-left"
  147. color={buttonColor}
  148. onPress={(): void => props.onPress('prev')}
  149. />
  150. <IconButton
  151. icon="chevron-right"
  152. color={buttonColor}
  153. style={{marginLeft: 5}}
  154. onPress={(): void => props.onPress('next')}
  155. />
  156. </View>
  157. </Surface>
  158. </Animatable.View>
  159. );
  160. }
  161. }
  162. export default withTheme(AnimatedBottomBar);