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.

CustomIntroSlider.js 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. // @flow
  2. import * as React from 'react';
  3. import {Platform, StatusBar, StyleSheet, View} from "react-native";
  4. import type {MaterialCommunityIconsGlyphs} from "react-native-vector-icons/MaterialCommunityIcons";
  5. import MaterialCommunityIcons from "react-native-vector-icons/MaterialCommunityIcons";
  6. import i18n from 'i18n-js';
  7. import AppIntroSlider from "react-native-app-intro-slider";
  8. import Update from "../../constants/Update";
  9. import ThemeManager from "../../managers/ThemeManager";
  10. import LinearGradient from 'react-native-linear-gradient';
  11. import Mascot, {MASCOT_STYLE} from "../Mascot/Mascot";
  12. import * as Animatable from "react-native-animatable";
  13. import {Card} from "react-native-paper";
  14. type Props = {
  15. onDone: Function,
  16. isUpdate: boolean,
  17. isAprilFools: boolean,
  18. };
  19. type State = {
  20. currentSlide: number,
  21. }
  22. type Slide = {
  23. key: string,
  24. title: string,
  25. text: string,
  26. view: () => React.Node,
  27. mascotStyle: number,
  28. colors: [string, string]
  29. };
  30. /**
  31. * Class used to create intro slides
  32. */
  33. export default class CustomIntroSlider extends React.Component<Props, State> {
  34. state = {
  35. currentSlide: 0,
  36. }
  37. sliderRef: { current: null | AppIntroSlider };
  38. introSlides: Array<Slide>;
  39. updateSlides: Array<Slide>;
  40. aprilFoolsSlides: Array<Slide>;
  41. currentSlides: Array<Slide>;
  42. /**
  43. * Generates intro slides
  44. */
  45. constructor() {
  46. super();
  47. this.sliderRef = React.createRef();
  48. this.introSlides = [
  49. {
  50. key: '0', // Mascot
  51. title: i18n.t('intro.slideMain.title'),
  52. text: i18n.t('intro.slideMain.text'),
  53. view: this.getWelcomeView,
  54. mascotStyle: MASCOT_STYLE.NORMAL,
  55. colors: ['#be1522', '#57080e'],
  56. },
  57. {
  58. key: '1',
  59. title: i18n.t('intro.slidePlanex.title'),
  60. text: i18n.t('intro.slidePlanex.text'),
  61. view: () => this.getIconView("calendar-clock"),
  62. mascotStyle: MASCOT_STYLE.INTELLO,
  63. colors: ['#be1522', '#57080e'],
  64. },
  65. {
  66. key: '2',
  67. title: i18n.t('intro.slideEvents.title'),
  68. text: i18n.t('intro.slideEvents.text'),
  69. view: () => this.getIconView("calendar-star",),
  70. mascotStyle: MASCOT_STYLE.HAPPY,
  71. colors: ['#be1522', '#57080e'],
  72. },
  73. {
  74. key: '3',
  75. title: i18n.t('intro.slideServices.title'),
  76. text: i18n.t('intro.slideServices.text'),
  77. view: () => this.getIconView("view-dashboard-variant",),
  78. mascotStyle: MASCOT_STYLE.CUTE,
  79. colors: ['#be1522', '#57080e'],
  80. },
  81. {
  82. key: '4',
  83. title: i18n.t('intro.slideDone.title'),
  84. text: i18n.t('intro.slideDone.text'),
  85. view: () => this.getIconView("account-heart",),
  86. mascotStyle: MASCOT_STYLE.COOL,
  87. colors: ['#9c165b', '#3e042b'],
  88. },
  89. ];
  90. this.updateSlides = [];
  91. for (let i = 0; i < Update.slidesNumber; i++) {
  92. this.updateSlides.push(
  93. {
  94. key: i.toString(),
  95. title: Update.getInstance().titleList[i],
  96. text: Update.getInstance().descriptionList[i],
  97. icon: Update.iconList[i],
  98. colors: Update.colorsList[i],
  99. },
  100. );
  101. }
  102. this.aprilFoolsSlides = [
  103. {
  104. key: '1',
  105. title: i18n.t('intro.aprilFoolsSlide.title'),
  106. text: i18n.t('intro.aprilFoolsSlide.text'),
  107. view: () => <View/>,
  108. mascotStyle: MASCOT_STYLE.NORMAL,
  109. colors: ['#e01928', '#be1522'],
  110. },
  111. ];
  112. }
  113. /**
  114. * Render item to be used for the intro introSlides
  115. *
  116. * @param item The item to be displayed
  117. * @param dimensions Dimensions of the item
  118. */
  119. getIntroRenderItem = ({item, dimensions}: { item: Slide, dimensions: { width: number, height: number } }) => {
  120. const index = parseInt(item.key);
  121. return (
  122. <LinearGradient
  123. style={[
  124. styles.mainContent,
  125. dimensions
  126. ]}
  127. colors={item.colors}
  128. start={{x: 0, y: 0.1}}
  129. end={{x: 0.1, y: 1}}
  130. >
  131. {this.state.currentSlide === index
  132. ? <View style={{height: "100%", flex: 1}}>
  133. <View style={{flex: 1}}>
  134. {item.view()}
  135. </View>
  136. <Animatable.View
  137. animation={"fadeIn"}>
  138. {index !== 0
  139. ? <Animatable.View
  140. animation={"pulse"}
  141. iterationCount={"infinite"}
  142. duration={2000}
  143. style={{
  144. marginLeft: 30,
  145. marginBottom: 0,
  146. width: 80
  147. }}>
  148. <Mascot emotion={item.mascotStyle} size={80}/>
  149. </Animatable.View> : null}
  150. <View style={{
  151. marginLeft: 50,
  152. width: 0,
  153. height: 0,
  154. borderLeftWidth: 20,
  155. borderRightWidth: 0,
  156. borderBottomWidth: 20,
  157. borderStyle: 'solid',
  158. backgroundColor: 'transparent',
  159. borderLeftColor: 'transparent',
  160. borderRightColor: 'transparent',
  161. borderBottomColor: "rgba(0,0,0,0.60)",
  162. }}/>
  163. <Card style={{
  164. backgroundColor: "rgba(0,0,0,0.38)",
  165. marginHorizontal: 20,
  166. borderColor: "rgba(0,0,0,0.60)",
  167. borderWidth: 4,
  168. borderRadius: 10,
  169. }}>
  170. <Card.Content>
  171. <Animatable.Text
  172. animation={"fadeIn"}
  173. delay={100}
  174. style={styles.title}>
  175. {item.title}
  176. </Animatable.Text>
  177. <Animatable.Text
  178. animation={"fadeIn"}
  179. delay={200}
  180. style={styles.text}>
  181. {item.text}
  182. </Animatable.Text>
  183. </Card.Content>
  184. </Card>
  185. </Animatable.View>
  186. </View> : null}
  187. </LinearGradient>
  188. );
  189. }
  190. getWelcomeView = () => {
  191. return (
  192. <View style={{flex: 1}}>
  193. <View
  194. style={styles.center}>
  195. <Mascot
  196. size={250}
  197. emotion={MASCOT_STYLE.NORMAL}
  198. animated={true}
  199. entryAnimation={{
  200. animation: "bounceIn",
  201. duration: 2000,
  202. }}
  203. />
  204. </View>
  205. </View>
  206. )
  207. }
  208. getIconView(icon: MaterialCommunityIconsGlyphs) {
  209. return (
  210. <View style={{flex: 1}}>
  211. <Animatable.View
  212. style={styles.center}
  213. animation={"fadeIn"}
  214. >
  215. <MaterialCommunityIcons
  216. name={icon}
  217. color={'#fff'}
  218. size={200}/>
  219. </Animatable.View>
  220. </View>
  221. )
  222. }
  223. setStatusBarColor(color: string) {
  224. if (Platform.OS === 'android')
  225. StatusBar.setBackgroundColor(color, true);
  226. }
  227. onSlideChange = (index: number, lastIndex: number) => {
  228. this.setStatusBarColor(this.currentSlides[index].colors[0]);
  229. this.setState({currentSlide: index});
  230. };
  231. onSkip = () => {
  232. this.setStatusBarColor(this.currentSlides[this.currentSlides.length - 1].colors[0]);
  233. if (this.sliderRef.current != null)
  234. this.sliderRef.current.goToSlide(this.currentSlides.length - 1);
  235. }
  236. onDone = () => {
  237. this.setStatusBarColor(ThemeManager.getCurrentTheme().colors.surface);
  238. this.props.onDone();
  239. }
  240. renderNextButton = () => {
  241. return (
  242. <Animatable.View
  243. animation={"fadeIn"}
  244. style={{
  245. borderRadius: 25,
  246. padding: 5,
  247. backgroundColor: "rgba(0,0,0,0.2)"
  248. }}>
  249. <MaterialCommunityIcons
  250. name={"arrow-right"}
  251. color={'#fff'}
  252. size={40}/>
  253. </Animatable.View>
  254. )
  255. }
  256. renderDoneButton = () => {
  257. return (
  258. <Animatable.View
  259. animation={"bounceIn"}
  260. style={{
  261. borderRadius: 25,
  262. padding: 5,
  263. backgroundColor: "rgb(190,21,34)"
  264. }}>
  265. <MaterialCommunityIcons
  266. name={"check"}
  267. color={'#fff'}
  268. size={40}/>
  269. </Animatable.View>
  270. )
  271. }
  272. render() {
  273. this.currentSlides = this.introSlides;
  274. if (this.props.isUpdate)
  275. this.currentSlides = this.updateSlides;
  276. else if (this.props.isAprilFools)
  277. this.currentSlides = this.aprilFoolsSlides;
  278. this.setStatusBarColor(this.currentSlides[0].colors[0]);
  279. return (
  280. <AppIntroSlider
  281. ref={this.sliderRef}
  282. data={this.currentSlides}
  283. extraData={this.state.currentSlide}
  284. renderItem={this.getIntroRenderItem}
  285. renderNextButton={this.renderNextButton}
  286. renderDoneButton={this.renderDoneButton}
  287. onDone={this.onDone}
  288. onSlideChange={this.onSlideChange}
  289. onSkip={this.onSkip}
  290. />
  291. );
  292. }
  293. }
  294. const styles = StyleSheet.create({
  295. mainContent: {
  296. paddingBottom: 100,
  297. },
  298. text: {
  299. color: 'rgba(255, 255, 255, 0.8)',
  300. backgroundColor: 'transparent',
  301. textAlign: 'center',
  302. paddingHorizontal: 16,
  303. },
  304. title: {
  305. fontSize: 22,
  306. color: 'white',
  307. backgroundColor: 'transparent',
  308. textAlign: 'center',
  309. marginBottom: 16,
  310. },
  311. center: {
  312. marginTop: 'auto',
  313. marginBottom: 'auto',
  314. marginRight: 'auto',
  315. marginLeft: 'auto',
  316. }
  317. });