forked from vergnet/application-amicale
Updated intro slides to make them shorter and include the mascot
This commit is contained in:
parent
90d1437248
commit
434d8b6565
4 changed files with 340 additions and 132 deletions
|
@ -379,18 +379,10 @@
|
||||||
"title": "Stay up to date",
|
"title": "Stay up to date",
|
||||||
"text": "CAMPUS allows you to be aware of any event occurring on the campus, from pancake sales to Enfoiros concerts!"
|
"text": "CAMPUS allows you to be aware of any event occurring on the campus, from pancake sales to Enfoiros concerts!"
|
||||||
},
|
},
|
||||||
"slideProxiwash": {
|
|
||||||
"title": "Never forget your laundry",
|
|
||||||
"text": "CAMPUS will inform you on the availability of washing machines and will remind you just before yours finishes!"
|
|
||||||
},
|
|
||||||
"slidePlanex": {
|
"slidePlanex": {
|
||||||
"title": "Planex",
|
"title": "Planex",
|
||||||
"text": "Lookup your next course on CAMPUS with a mobile friendly timetable"
|
"text": "Lookup your next course on CAMPUS with a mobile friendly timetable"
|
||||||
},
|
},
|
||||||
"slideRU": {
|
|
||||||
"title": "RU Menu",
|
|
||||||
"text": "For the hungry, check this week's menu!"
|
|
||||||
},
|
|
||||||
"slideServices": {
|
"slideServices": {
|
||||||
"title": "More services!",
|
"title": "More services!",
|
||||||
"text": "You can do much more with CAMPUS, explore the app to find out"
|
"text": "You can do much more with CAMPUS, explore the app to find out"
|
||||||
|
|
|
@ -372,32 +372,24 @@
|
||||||
},
|
},
|
||||||
"intro": {
|
"intro": {
|
||||||
"slideMain": {
|
"slideMain": {
|
||||||
"title": "Bienvenue sur CAMPUS",
|
"title": "Bienvenue sur CAMPUS !",
|
||||||
"text": "La nouvelle appli à consulter pendant la pause café pour être au courant de la vie du campus !"
|
"text": "L'appli du campus de l'INSA Toulouse ! Laisse toi guider pour comprendre tout ce que tu peux faire."
|
||||||
},
|
|
||||||
"slideEvents": {
|
|
||||||
"title": "Restez informés",
|
|
||||||
"text": "CAMPUS vous permet d'être au courant de tous les événements qui ont lieu sur le campus, de la vente de crêpes jusqu'aux concerts enfoiros !"
|
|
||||||
},
|
|
||||||
"slideProxiwash": {
|
|
||||||
"title": "N'oubliez plus votre linge !",
|
|
||||||
"text": "CAMPUS vous informe de la disponibilité des machines et vous permet d'être notifié lorsque la vôtre se termine bientôt !"
|
|
||||||
},
|
},
|
||||||
"slidePlanex": {
|
"slidePlanex": {
|
||||||
"title": "Planex",
|
"title": "Planex tout beau",
|
||||||
"text": "Vérifiez votre prochain cours sur CAMPUS avec un emploi du temps adapté mobile"
|
"text": "Regarde ton emploi du temps et celui de tes amis avec un Planex adapté mobile !"
|
||||||
},
|
},
|
||||||
"slideRU": {
|
"slideEvents": {
|
||||||
"title": "Menu du RU",
|
"title": "Plein d'infos",
|
||||||
"text": "Pour ceux qui ont faim, vérifiez le menu du RU de la semaine !"
|
"text": "Sois au courant de tout ce qui se passe sur le campus, de la vente de crêpes jusqu'aux concerts Enfoiros !"
|
||||||
},
|
},
|
||||||
"slideServices": {
|
"slideServices": {
|
||||||
"title": "Encore plus de services !",
|
"title": "Et plus encore !",
|
||||||
"text": "CAMPUS vous permet de faire bien plus, explorez l'appli pour savoir quoi"
|
"text": "Tu peux faire bien plus avec CAMPUS, mais je n'ai pas le temps de tout dire ici. Balade toi sur l'appli pour tout découvrir !"
|
||||||
},
|
},
|
||||||
"slideDone": {
|
"slideDone": {
|
||||||
"title": "Fait par un étudiant",
|
"title": "Réalisé par un étudiant",
|
||||||
"text": "Cette appli à été réalisée par un seul étudiant (avec un peu d'aide par-ci par-là), donc tous les retours sont les bienvenus !"
|
"text": "Cette appli à été réalisée par un seul étudiant (avec un peu d'aide par-ci par-là), donc tes retours sont les bienvenus !"
|
||||||
},
|
},
|
||||||
"updateSlide0": {
|
"updateSlide0": {
|
||||||
"title": "Nouveau dans cette mise à jour !",
|
"title": "Nouveau dans cette mise à jour !",
|
||||||
|
|
|
@ -2,26 +2,46 @@
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import * as Animatable from "react-native-animatable";
|
import * as Animatable from "react-native-animatable";
|
||||||
import {Image, View} from "react-native-animatable";
|
import {Image, TouchableWithoutFeedback, View} from "react-native";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
size: number,
|
size: number,
|
||||||
emotion: number,
|
emotion: number,
|
||||||
animated: boolean,
|
animated: boolean,
|
||||||
|
entryAnimation: Animatable.AnimatableProperties | null,
|
||||||
|
loopAnimation: Animatable.AnimatableProperties | null,
|
||||||
|
onPress?: (viewRef: AnimatableViewRef) => null,
|
||||||
|
onLongPress?: (viewRef: AnimatableViewRef) => null,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type State = {
|
||||||
|
currentEmotion: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AnimatableViewRef = {current: null | Animatable.View};
|
||||||
|
|
||||||
const MASCOT_IMAGE = require("../../../assets/mascot/mascot.png");
|
const MASCOT_IMAGE = require("../../../assets/mascot/mascot.png");
|
||||||
const MASCOT_EYES_NORMAL = require("../../../assets/mascot/mascot_eyes_normal.png");
|
const MASCOT_EYES_NORMAL = require("../../../assets/mascot/mascot_eyes_normal.png");
|
||||||
const MASCOT_EYES_GIRLY = require("../../../assets/mascot/mascot_eyes_girly.png");
|
const MASCOT_EYES_GIRLY = require("../../../assets/mascot/mascot_eyes_girly.png");
|
||||||
const MASCOT_EYES_CUTE = require("../../../assets/mascot/mascot_eyes_cute.png");
|
const MASCOT_EYES_CUTE = require("../../../assets/mascot/mascot_eyes_cute.png");
|
||||||
const MASCOT_EYES_WINK = require("../../../assets/mascot/mascot_eyes_wink.png");
|
const MASCOT_EYES_WINK = require("../../../assets/mascot/mascot_eyes_wink.png");
|
||||||
|
const MASCOT_EYES_HEART = require("../../../assets/mascot/mascot_eyes_heart.png");
|
||||||
|
const MASCOT_EYES_ANGRY = require("../../../assets/mascot/mascot_eyes_angry.png");
|
||||||
const MASCOT_GLASSES = require("../../../assets/mascot/mascot_glasses.png");
|
const MASCOT_GLASSES = require("../../../assets/mascot/mascot_glasses.png");
|
||||||
|
const MASCOT_SUNGLASSES = require("../../../assets/mascot/mascot_sunglasses.png");
|
||||||
|
|
||||||
export const EYE_STYLE = {
|
export const EYE_STYLE = {
|
||||||
NORMAL: 0,
|
NORMAL: 0,
|
||||||
GIRLY: 2,
|
GIRLY: 2,
|
||||||
CUTE: 3,
|
CUTE: 3,
|
||||||
WINK: 4,
|
WINK: 4,
|
||||||
|
HEART: 5,
|
||||||
|
ANGRY: 6,
|
||||||
|
}
|
||||||
|
|
||||||
|
const GLASSES_STYLE = {
|
||||||
|
NORMAL: 0,
|
||||||
|
COOl: 1
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MASCOT_STYLE = {
|
export const MASCOT_STYLE = {
|
||||||
|
@ -31,30 +51,96 @@ export const MASCOT_STYLE = {
|
||||||
WINK: 3,
|
WINK: 3,
|
||||||
CUTE: 4,
|
CUTE: 4,
|
||||||
INTELLO: 5,
|
INTELLO: 5,
|
||||||
|
LOVE: 6,
|
||||||
|
COOL: 7,
|
||||||
|
ANGRY: 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Mascot extends React.Component<Props> {
|
class Mascot extends React.Component<Props, State> {
|
||||||
|
|
||||||
static defaultProps = {
|
state = {
|
||||||
animated: false
|
currentEmotion: this.props.emotion
|
||||||
}
|
}
|
||||||
|
|
||||||
eyeList: { [key: number]: number | string }
|
static defaultProps = {
|
||||||
|
animated: false,
|
||||||
|
entryAnimation: {
|
||||||
|
useNativeDriver: true,
|
||||||
|
animation: "rubberBand",
|
||||||
|
duration: 2000,
|
||||||
|
},
|
||||||
|
loopAnimation: {
|
||||||
|
useNativeDriver: true,
|
||||||
|
animation: "swing",
|
||||||
|
duration: 2000,
|
||||||
|
iterationDelay: 250,
|
||||||
|
iterationCount: "infinite",
|
||||||
|
},
|
||||||
|
clickAnimation: {
|
||||||
|
useNativeDriver: true,
|
||||||
|
animation: "rubberBand",
|
||||||
|
duration: 2000,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
viewRef: AnimatableViewRef;
|
||||||
|
eyeList: { [key: number]: number | string };
|
||||||
|
glassesList: { [key: number]: number | string };
|
||||||
|
|
||||||
|
onPress: (viewRef: AnimatableViewRef) => null;
|
||||||
|
onLongPress: (viewRef: AnimatableViewRef) => null;
|
||||||
|
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
this.viewRef = React.createRef();
|
||||||
this.eyeList = {};
|
this.eyeList = {};
|
||||||
|
this.glassesList = {};
|
||||||
this.eyeList[EYE_STYLE.NORMAL] = MASCOT_EYES_NORMAL;
|
this.eyeList[EYE_STYLE.NORMAL] = MASCOT_EYES_NORMAL;
|
||||||
this.eyeList[EYE_STYLE.GIRLY] = MASCOT_EYES_GIRLY;
|
this.eyeList[EYE_STYLE.GIRLY] = MASCOT_EYES_GIRLY;
|
||||||
this.eyeList[EYE_STYLE.CUTE] = MASCOT_EYES_CUTE;
|
this.eyeList[EYE_STYLE.CUTE] = MASCOT_EYES_CUTE;
|
||||||
this.eyeList[EYE_STYLE.WINK] = MASCOT_EYES_WINK;
|
this.eyeList[EYE_STYLE.WINK] = MASCOT_EYES_WINK;
|
||||||
|
this.eyeList[EYE_STYLE.HEART] = MASCOT_EYES_HEART;
|
||||||
|
this.eyeList[EYE_STYLE.ANGRY] = MASCOT_EYES_ANGRY;
|
||||||
|
|
||||||
|
this.glassesList[GLASSES_STYLE.NORMAL] = MASCOT_GLASSES;
|
||||||
|
this.glassesList[GLASSES_STYLE.COOl] = MASCOT_SUNGLASSES;
|
||||||
|
|
||||||
|
if (this.props.onPress == null) {
|
||||||
|
this.onPress = (viewRef: AnimatableViewRef) => {
|
||||||
|
if (viewRef.current != null) {
|
||||||
|
this.setState({currentEmotion: MASCOT_STYLE.LOVE});
|
||||||
|
viewRef.current.rubberBand(1500).then(() => {
|
||||||
|
this.setState({currentEmotion: this.props.emotion});
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
this.onPress = this.props.onPress;
|
||||||
|
|
||||||
|
if (this.props.onLongPress == null) {
|
||||||
|
this.onLongPress = (viewRef: AnimatableViewRef) => {
|
||||||
|
if (viewRef.current != null) {
|
||||||
|
this.setState({currentEmotion: MASCOT_STYLE.ANGRY});
|
||||||
|
viewRef.current.tada(1000).then(() => {
|
||||||
|
this.setState({currentEmotion: this.props.emotion});
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
this.onLongPress = this.props.onLongPress;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getGlasses() {
|
getGlasses(style: number) {
|
||||||
|
const glasses = this.glassesList[style];
|
||||||
return <Image
|
return <Image
|
||||||
key={"glasses"}
|
key={"glasses"}
|
||||||
source={MASCOT_GLASSES}
|
source={glasses != null ? glasses : this.glassesList[GLASSES_STYLE.NORMAL]}
|
||||||
style={{
|
style={{
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
top: "15%",
|
top: "15%",
|
||||||
|
@ -65,7 +151,7 @@ class Mascot extends React.Component<Props> {
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
|
||||||
getEye(style: number, isRight: boolean) {
|
getEye(style: number, isRight: boolean, rotation: string="0deg") {
|
||||||
const eye = this.eyeList[style];
|
const eye = this.eyeList[style];
|
||||||
return <Image
|
return <Image
|
||||||
key={isRight ? "right" : "left"}
|
key={isRight ? "right" : "left"}
|
||||||
|
@ -76,6 +162,7 @@ class Mascot extends React.Component<Props> {
|
||||||
left: isRight ? "-11%" : "11%",
|
left: isRight ? "-11%" : "11%",
|
||||||
width: this.props.size,
|
width: this.props.size,
|
||||||
height: this.props.size,
|
height: this.props.size,
|
||||||
|
transform: [{rotateY: rotation}]
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
@ -85,10 +172,10 @@ class Mascot extends React.Component<Props> {
|
||||||
final.push(<View
|
final.push(<View
|
||||||
key={"container"}
|
key={"container"}
|
||||||
style={{
|
style={{
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
width: this.props.size,
|
width: this.props.size,
|
||||||
height: this.props.size,
|
height: this.props.size,
|
||||||
}}/>);
|
}}/>);
|
||||||
if (emotion === MASCOT_STYLE.CUTE) {
|
if (emotion === MASCOT_STYLE.CUTE) {
|
||||||
final.push(this.getEye(EYE_STYLE.CUTE, true));
|
final.push(this.getEye(EYE_STYLE.CUTE, true));
|
||||||
final.push(this.getEye(EYE_STYLE.CUTE, false));
|
final.push(this.getEye(EYE_STYLE.CUTE, false));
|
||||||
|
@ -101,13 +188,21 @@ class Mascot extends React.Component<Props> {
|
||||||
} else if (emotion === MASCOT_STYLE.WINK) {
|
} else if (emotion === MASCOT_STYLE.WINK) {
|
||||||
final.push(this.getEye(EYE_STYLE.WINK, true));
|
final.push(this.getEye(EYE_STYLE.WINK, true));
|
||||||
final.push(this.getEye(EYE_STYLE.NORMAL, false));
|
final.push(this.getEye(EYE_STYLE.NORMAL, false));
|
||||||
|
} else if (emotion === MASCOT_STYLE.LOVE) {
|
||||||
|
final.push(this.getEye(EYE_STYLE.HEART, true));
|
||||||
|
final.push(this.getEye(EYE_STYLE.HEART, false));
|
||||||
|
} else if (emotion === MASCOT_STYLE.ANGRY) {
|
||||||
|
final.push(this.getEye(EYE_STYLE.ANGRY, true));
|
||||||
|
final.push(this.getEye(EYE_STYLE.ANGRY, false, "180deg"));
|
||||||
|
} else if (emotion === MASCOT_STYLE.COOL) {
|
||||||
|
final.push(this.getGlasses(GLASSES_STYLE.COOl));
|
||||||
} else {
|
} else {
|
||||||
final.push(this.getEye(EYE_STYLE.NORMAL, true));
|
final.push(this.getEye(EYE_STYLE.NORMAL, true));
|
||||||
final.push(this.getEye(EYE_STYLE.NORMAL, false));
|
final.push(this.getEye(EYE_STYLE.NORMAL, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (emotion === MASCOT_STYLE.INTELLO) {
|
if (emotion === MASCOT_STYLE.INTELLO) { // Needs to have normal eyes behind the glasses
|
||||||
final.push(this.getGlasses())
|
final.push(this.getGlasses(GLASSES_STYLE.NORMAL));
|
||||||
}
|
}
|
||||||
final.push(<View key={"container2"}/>);
|
final.push(<View key={"container2"}/>);
|
||||||
return final;
|
return final;
|
||||||
|
@ -115,31 +210,37 @@ class Mascot extends React.Component<Props> {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const size = this.props.size;
|
const size = this.props.size;
|
||||||
|
const entryAnimation = this.props.animated ? this.props.entryAnimation : null;
|
||||||
|
const loopAnimation = this.props.animated ? this.props.loopAnimation : null;
|
||||||
return (
|
return (
|
||||||
<Animatable.View
|
<Animatable.View
|
||||||
style={{
|
style={{
|
||||||
width: size,
|
width: size,
|
||||||
height: size,
|
height: size,
|
||||||
}}
|
}}
|
||||||
useNativeDriver={true}
|
{...entryAnimation}
|
||||||
animation={this.props.animated ? "rubberBand" : null}
|
|
||||||
duration={2000}
|
|
||||||
>
|
>
|
||||||
<View
|
<TouchableWithoutFeedback
|
||||||
useNativeDriver={true}
|
onPress={() => this.onPress(this.viewRef)}
|
||||||
animation={this.props.animated ? "swing" : null}
|
onLongPress={() => this.onLongPress(this.viewRef)}
|
||||||
duration={2000}
|
|
||||||
iterationCount={"infinite"}
|
|
||||||
>
|
>
|
||||||
<Image
|
<Animatable.View
|
||||||
source={MASCOT_IMAGE}
|
ref={this.viewRef}
|
||||||
style={{
|
>
|
||||||
width: size,
|
<Animatable.View
|
||||||
height: size,
|
{...loopAnimation}
|
||||||
}}
|
>
|
||||||
/>
|
<Image
|
||||||
{this.getEyes(this.props.emotion)}
|
source={MASCOT_IMAGE}
|
||||||
</View>
|
style={{
|
||||||
|
width: size,
|
||||||
|
height: size,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{this.getEyes(this.state.currentEmotion)}
|
||||||
|
</Animatable.View>
|
||||||
|
</Animatable.View>
|
||||||
|
</TouchableWithoutFeedback>
|
||||||
</Animatable.View>
|
</Animatable.View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {Image, Platform, StatusBar, StyleSheet, View} from "react-native";
|
import {Platform, StatusBar, StyleSheet, View} from "react-native";
|
||||||
|
import type {MaterialCommunityIconsGlyphs} from "react-native-vector-icons/MaterialCommunityIcons";
|
||||||
import MaterialCommunityIcons from "react-native-vector-icons/MaterialCommunityIcons";
|
import MaterialCommunityIcons from "react-native-vector-icons/MaterialCommunityIcons";
|
||||||
import {Text} from "react-native-paper";
|
|
||||||
import i18n from 'i18n-js';
|
import i18n from 'i18n-js';
|
||||||
import AppIntroSlider from "react-native-app-intro-slider";
|
import AppIntroSlider from "react-native-app-intro-slider";
|
||||||
import Update from "../../constants/Update";
|
import Update from "../../constants/Update";
|
||||||
import ThemeManager from "../../managers/ThemeManager";
|
import ThemeManager from "../../managers/ThemeManager";
|
||||||
import LinearGradient from 'react-native-linear-gradient';
|
import LinearGradient from 'react-native-linear-gradient';
|
||||||
|
import Mascot, {MASCOT_STYLE} from "../Mascot/Mascot";
|
||||||
|
import * as Animatable from "react-native-animatable";
|
||||||
|
import {Card} from "react-native-paper";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onDone: Function,
|
onDone: Function,
|
||||||
|
@ -16,17 +19,34 @@ type Props = {
|
||||||
isAprilFools: boolean,
|
isAprilFools: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type State = {
|
||||||
|
currentSlide: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
type Slide = {
|
||||||
|
key: string,
|
||||||
|
title: string,
|
||||||
|
text: string,
|
||||||
|
view: () => React.Node,
|
||||||
|
mascotStyle: number,
|
||||||
|
colors: [string, string]
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class used to create intro slides
|
* Class used to create intro slides
|
||||||
*/
|
*/
|
||||||
export default class CustomIntroSlider extends React.Component<Props> {
|
export default class CustomIntroSlider extends React.Component<Props, State> {
|
||||||
|
|
||||||
sliderRef: {current: null | AppIntroSlider};
|
state = {
|
||||||
|
currentSlide: 0,
|
||||||
|
}
|
||||||
|
|
||||||
introSlides: Array<Object>;
|
sliderRef: { current: null | AppIntroSlider };
|
||||||
updateSlides: Array<Object>;
|
|
||||||
aprilFoolsSlides: Array<Object>;
|
introSlides: Array<Slide>;
|
||||||
currentSlides: Array<Object>;
|
updateSlides: Array<Slide>;
|
||||||
|
aprilFoolsSlides: Array<Slide>;
|
||||||
|
currentSlides: Array<Slide>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates intro slides
|
* Generates intro slides
|
||||||
|
@ -36,53 +56,44 @@ export default class CustomIntroSlider extends React.Component<Props> {
|
||||||
this.sliderRef = React.createRef();
|
this.sliderRef = React.createRef();
|
||||||
this.introSlides = [
|
this.introSlides = [
|
||||||
{
|
{
|
||||||
key: 'main',
|
key: '0', // Mascot
|
||||||
title: i18n.t('intro.slideMain.title'),
|
title: i18n.t('intro.slideMain.title'),
|
||||||
text: i18n.t('intro.slideMain.text'),
|
text: i18n.t('intro.slideMain.text'),
|
||||||
image: require('../../../assets/splash.png'),
|
view: this.getWelcomeView,
|
||||||
colors: ['#be1522', '#740d15'],
|
mascotStyle: MASCOT_STYLE.NORMAL,
|
||||||
|
colors: ['#be1522', '#57080e'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'Planex',
|
key: '1',
|
||||||
title: i18n.t('intro.slidePlanex.title'),
|
title: i18n.t('intro.slidePlanex.title'),
|
||||||
text: i18n.t('intro.slidePlanex.text'),
|
text: i18n.t('intro.slidePlanex.text'),
|
||||||
icon: 'timetable',
|
view: () => this.getIconView("calendar-clock"),
|
||||||
colors: ['#e77020', '#803e12'],
|
mascotStyle: MASCOT_STYLE.INTELLO,
|
||||||
|
colors: ['#be1522', '#57080e'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'RU',
|
key: '2',
|
||||||
title: i18n.t('intro.slideRU.title'),
|
|
||||||
text: i18n.t('intro.slideRU.text'),
|
|
||||||
icon: 'silverware-fork-knife',
|
|
||||||
colors: ['#dcac18', '#8b6a15'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'events',
|
|
||||||
title: i18n.t('intro.slideEvents.title'),
|
title: i18n.t('intro.slideEvents.title'),
|
||||||
text: i18n.t('intro.slideEvents.text'),
|
text: i18n.t('intro.slideEvents.text'),
|
||||||
icon: 'calendar-range',
|
view: () => this.getIconView("calendar-star",),
|
||||||
colors: ['#41a006', '#095c03'],
|
mascotStyle: MASCOT_STYLE.HAPPY,
|
||||||
|
colors: ['#be1522', '#57080e'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'proxiwash',
|
key: '3',
|
||||||
title: i18n.t('intro.slideProxiwash.title'),
|
|
||||||
text: i18n.t('intro.slideProxiwash.text'),
|
|
||||||
icon: 'washing-machine',
|
|
||||||
colors: ['#1fa5ee', '#06537d'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'services',
|
|
||||||
title: i18n.t('intro.slideServices.title'),
|
title: i18n.t('intro.slideServices.title'),
|
||||||
text: i18n.t('intro.slideServices.text'),
|
text: i18n.t('intro.slideServices.text'),
|
||||||
icon: 'view-dashboard-variant',
|
view: () => this.getIconView("view-dashboard-variant",),
|
||||||
colors: ['#6737c1', '#281a5a'],
|
mascotStyle: MASCOT_STYLE.CUTE,
|
||||||
|
colors: ['#be1522', '#57080e'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'done',
|
key: '4',
|
||||||
title: i18n.t('intro.slideDone.title'),
|
title: i18n.t('intro.slideDone.title'),
|
||||||
text: i18n.t('intro.slideDone.text'),
|
text: i18n.t('intro.slideDone.text'),
|
||||||
icon: 'account-heart',
|
view: () => this.getIconView("account-heart",),
|
||||||
colors: ['#b837c1', '#501a5a'],
|
mascotStyle: MASCOT_STYLE.COOL,
|
||||||
|
colors: ['#9c165b', '#3e042b'],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
this.updateSlides = [];
|
this.updateSlides = [];
|
||||||
|
@ -103,50 +114,127 @@ export default class CustomIntroSlider extends React.Component<Props> {
|
||||||
key: '1',
|
key: '1',
|
||||||
title: i18n.t('intro.aprilFoolsSlide.title'),
|
title: i18n.t('intro.aprilFoolsSlide.title'),
|
||||||
text: i18n.t('intro.aprilFoolsSlide.text'),
|
text: i18n.t('intro.aprilFoolsSlide.text'),
|
||||||
icon: 'fish',
|
view: () => <View/>,
|
||||||
|
mascotStyle: MASCOT_STYLE.NORMAL,
|
||||||
colors: ['#e01928', '#be1522'],
|
colors: ['#e01928', '#be1522'],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render item to be used for the intro introSlides
|
* Render item to be used for the intro introSlides
|
||||||
*
|
*
|
||||||
* @param item The item to be displayed
|
* @param item The item to be displayed
|
||||||
* @param dimensions Dimensions of the item
|
* @param dimensions Dimensions of the item
|
||||||
*/
|
*/
|
||||||
static getIntroRenderItem({item, dimensions}: Object) {
|
getIntroRenderItem = ({item, dimensions}: { item: Slide, dimensions: { width: number, height: number } }) => {
|
||||||
|
const index = parseInt(item.key);
|
||||||
return (
|
return (
|
||||||
<LinearGradient
|
<LinearGradient
|
||||||
style={[
|
style={[
|
||||||
styles.mainContent,
|
styles.mainContent,
|
||||||
dimensions,
|
dimensions
|
||||||
]}
|
]}
|
||||||
colors={item.colors}
|
colors={item.colors}
|
||||||
start={{x: 0, y: 0.1}}
|
start={{x: 0, y: 0.1}}
|
||||||
end={{x: 0.1, y: 1}}
|
end={{x: 0.1, y: 1}}
|
||||||
>
|
>
|
||||||
{item.image !== undefined ?
|
{this.state.currentSlide === index
|
||||||
<View style={styles.image}>
|
? <View style={{height: "100%", flex: 1}}>
|
||||||
<Image
|
<View style={{flex: 1}}>
|
||||||
source={item.image}
|
{item.view()}
|
||||||
resizeMode={"contain"}
|
</View>
|
||||||
style={{width: '100%', height: '100%'}}
|
<Animatable.View
|
||||||
/>
|
animation={"fadeIn"}>
|
||||||
</View>
|
{index !== 0
|
||||||
: <MaterialCommunityIcons
|
? <Animatable.View
|
||||||
name={item.icon}
|
animation={"pulse"}
|
||||||
color={'#fff'}
|
iterationCount={"infinite"}
|
||||||
size={200}/>}
|
duration={2000}
|
||||||
<View style={{marginTop: 20}}>
|
style={{
|
||||||
<Text style={styles.title}>{item.title}</Text>
|
marginLeft: 30,
|
||||||
<Text style={styles.text}>{item.text}</Text>
|
marginBottom: 0,
|
||||||
</View>
|
width: 80
|
||||||
|
}}>
|
||||||
|
<Mascot emotion={item.mascotStyle} size={80}/>
|
||||||
|
</Animatable.View> : null}
|
||||||
|
|
||||||
|
<View style={{
|
||||||
|
marginLeft: 50,
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
borderLeftWidth: 20,
|
||||||
|
borderRightWidth: 0,
|
||||||
|
borderBottomWidth: 20,
|
||||||
|
borderStyle: 'solid',
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
borderLeftColor: 'transparent',
|
||||||
|
borderRightColor: 'transparent',
|
||||||
|
borderBottomColor: "rgba(0,0,0,0.60)",
|
||||||
|
}}/>
|
||||||
|
<Card style={{
|
||||||
|
backgroundColor: "rgba(0,0,0,0.38)",
|
||||||
|
marginHorizontal: 20,
|
||||||
|
borderColor: "rgba(0,0,0,0.60)",
|
||||||
|
borderWidth: 4,
|
||||||
|
borderRadius: 10,
|
||||||
|
}}>
|
||||||
|
<Card.Content>
|
||||||
|
<Animatable.Text
|
||||||
|
animation={"fadeIn"}
|
||||||
|
delay={100}
|
||||||
|
style={styles.title}>
|
||||||
|
{item.title}
|
||||||
|
</Animatable.Text>
|
||||||
|
<Animatable.Text
|
||||||
|
animation={"fadeIn"}
|
||||||
|
delay={200}
|
||||||
|
style={styles.text}>
|
||||||
|
{item.text}
|
||||||
|
</Animatable.Text>
|
||||||
|
</Card.Content>
|
||||||
|
</Card>
|
||||||
|
</Animatable.View>
|
||||||
|
</View> : null}
|
||||||
</LinearGradient>
|
</LinearGradient>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getWelcomeView = () => {
|
||||||
|
return (
|
||||||
|
<View style={{flex: 1}}>
|
||||||
|
<View
|
||||||
|
style={styles.center}>
|
||||||
|
<Mascot
|
||||||
|
size={250}
|
||||||
|
emotion={MASCOT_STYLE.NORMAL}
|
||||||
|
animated={true}
|
||||||
|
entryAnimation={{
|
||||||
|
animation: "bounceIn",
|
||||||
|
duration: 2000,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
getIconView(icon: MaterialCommunityIconsGlyphs) {
|
||||||
|
return (
|
||||||
|
<View style={{flex: 1}}>
|
||||||
|
<Animatable.View
|
||||||
|
style={styles.center}
|
||||||
|
animation={"fadeIn"}
|
||||||
|
>
|
||||||
|
<MaterialCommunityIcons
|
||||||
|
name={icon}
|
||||||
|
color={'#fff'}
|
||||||
|
size={200}/>
|
||||||
|
</Animatable.View>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
setStatusBarColor(color: string) {
|
setStatusBarColor(color: string) {
|
||||||
if (Platform.OS === 'android')
|
if (Platform.OS === 'android')
|
||||||
StatusBar.setBackgroundColor(color, true);
|
StatusBar.setBackgroundColor(color, true);
|
||||||
|
@ -154,12 +242,13 @@ export default class CustomIntroSlider extends React.Component<Props> {
|
||||||
|
|
||||||
onSlideChange = (index: number, lastIndex: number) => {
|
onSlideChange = (index: number, lastIndex: number) => {
|
||||||
this.setStatusBarColor(this.currentSlides[index].colors[0]);
|
this.setStatusBarColor(this.currentSlides[index].colors[0]);
|
||||||
|
this.setState({currentSlide: index});
|
||||||
};
|
};
|
||||||
|
|
||||||
onSkip = () => {
|
onSkip = () => {
|
||||||
this.setStatusBarColor(this.currentSlides[this.currentSlides.length-1].colors[0]);
|
this.setStatusBarColor(this.currentSlides[this.currentSlides.length - 1].colors[0]);
|
||||||
if (this.sliderRef.current != null)
|
if (this.sliderRef.current != null)
|
||||||
this.sliderRef.current.goToSlide(this.currentSlides.length-1);
|
this.sliderRef.current.goToSlide(this.currentSlides.length - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
onDone = () => {
|
onDone = () => {
|
||||||
|
@ -167,6 +256,42 @@ export default class CustomIntroSlider extends React.Component<Props> {
|
||||||
this.props.onDone();
|
this.props.onDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderNextButton = () => {
|
||||||
|
return (
|
||||||
|
<Animatable.View
|
||||||
|
animation={"fadeIn"}
|
||||||
|
|
||||||
|
style={{
|
||||||
|
borderRadius: 25,
|
||||||
|
padding: 5,
|
||||||
|
backgroundColor: "rgba(0,0,0,0.2)"
|
||||||
|
}}>
|
||||||
|
<MaterialCommunityIcons
|
||||||
|
name={"arrow-right"}
|
||||||
|
color={'#fff'}
|
||||||
|
size={40}/>
|
||||||
|
</Animatable.View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderDoneButton = () => {
|
||||||
|
return (
|
||||||
|
<Animatable.View
|
||||||
|
animation={"bounceIn"}
|
||||||
|
|
||||||
|
style={{
|
||||||
|
borderRadius: 25,
|
||||||
|
padding: 5,
|
||||||
|
backgroundColor: "rgb(190,21,34)"
|
||||||
|
}}>
|
||||||
|
<MaterialCommunityIcons
|
||||||
|
name={"check"}
|
||||||
|
color={'#fff'}
|
||||||
|
size={40}/>
|
||||||
|
</Animatable.View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
this.currentSlides = this.introSlides;
|
this.currentSlides = this.introSlides;
|
||||||
if (this.props.isUpdate)
|
if (this.props.isUpdate)
|
||||||
|
@ -177,16 +302,16 @@ export default class CustomIntroSlider extends React.Component<Props> {
|
||||||
return (
|
return (
|
||||||
<AppIntroSlider
|
<AppIntroSlider
|
||||||
ref={this.sliderRef}
|
ref={this.sliderRef}
|
||||||
renderItem={CustomIntroSlider.getIntroRenderItem}
|
|
||||||
data={this.currentSlides}
|
data={this.currentSlides}
|
||||||
|
extraData={this.state.currentSlide}
|
||||||
|
|
||||||
|
renderItem={this.getIntroRenderItem}
|
||||||
|
renderNextButton={this.renderNextButton}
|
||||||
|
renderDoneButton={this.renderDoneButton}
|
||||||
|
|
||||||
onDone={this.onDone}
|
onDone={this.onDone}
|
||||||
bottomButton
|
|
||||||
showSkipButton
|
|
||||||
onSlideChange={this.onSlideChange}
|
onSlideChange={this.onSlideChange}
|
||||||
onSkip={this.onSkip}
|
onSkip={this.onSkip}
|
||||||
skipLabel={i18n.t('intro.buttons.skip')}
|
|
||||||
doneLabel={i18n.t('intro.buttons.done')}
|
|
||||||
nextLabel={i18n.t('intro.buttons.next')}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -196,15 +321,7 @@ export default class CustomIntroSlider extends React.Component<Props> {
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
mainContent: {
|
mainContent: {
|
||||||
flex: 1,
|
paddingBottom: 100,
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
paddingBottom: 100
|
|
||||||
},
|
|
||||||
image: {
|
|
||||||
width: 300,
|
|
||||||
height: 300,
|
|
||||||
marginBottom: -50,
|
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
color: 'rgba(255, 255, 255, 0.8)',
|
color: 'rgba(255, 255, 255, 0.8)',
|
||||||
|
@ -219,4 +336,10 @@ const styles = StyleSheet.create({
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
marginBottom: 16,
|
marginBottom: 16,
|
||||||
},
|
},
|
||||||
|
center: {
|
||||||
|
marginTop: 'auto',
|
||||||
|
marginBottom: 'auto',
|
||||||
|
marginRight: 'auto',
|
||||||
|
marginLeft: 'auto',
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue