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",
|
||||
"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": {
|
||||
"title": "Planex",
|
||||
"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": {
|
||||
"title": "More services!",
|
||||
"text": "You can do much more with CAMPUS, explore the app to find out"
|
||||
|
|
|
@ -372,32 +372,24 @@
|
|||
},
|
||||
"intro": {
|
||||
"slideMain": {
|
||||
"title": "Bienvenue sur CAMPUS",
|
||||
"text": "La nouvelle appli à consulter pendant la pause café pour être au courant de la vie du campus !"
|
||||
},
|
||||
"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 !"
|
||||
"title": "Bienvenue sur CAMPUS !",
|
||||
"text": "L'appli du campus de l'INSA Toulouse ! Laisse toi guider pour comprendre tout ce que tu peux faire."
|
||||
},
|
||||
"slidePlanex": {
|
||||
"title": "Planex",
|
||||
"text": "Vérifiez votre prochain cours sur CAMPUS avec un emploi du temps adapté mobile"
|
||||
"title": "Planex tout beau",
|
||||
"text": "Regarde ton emploi du temps et celui de tes amis avec un Planex adapté mobile !"
|
||||
},
|
||||
"slideRU": {
|
||||
"title": "Menu du RU",
|
||||
"text": "Pour ceux qui ont faim, vérifiez le menu du RU de la semaine !"
|
||||
"slideEvents": {
|
||||
"title": "Plein d'infos",
|
||||
"text": "Sois au courant de tout ce qui se passe sur le campus, de la vente de crêpes jusqu'aux concerts Enfoiros !"
|
||||
},
|
||||
"slideServices": {
|
||||
"title": "Encore plus de services !",
|
||||
"text": "CAMPUS vous permet de faire bien plus, explorez l'appli pour savoir quoi"
|
||||
"title": "Et plus encore !",
|
||||
"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": {
|
||||
"title": "Fait 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 !"
|
||||
"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 tes retours sont les bienvenus !"
|
||||
},
|
||||
"updateSlide0": {
|
||||
"title": "Nouveau dans cette mise à jour !",
|
||||
|
|
|
@ -2,26 +2,46 @@
|
|||
|
||||
import * as React from 'react';
|
||||
import * as Animatable from "react-native-animatable";
|
||||
import {Image, View} from "react-native-animatable";
|
||||
import {Image, TouchableWithoutFeedback, View} from "react-native";
|
||||
|
||||
type Props = {
|
||||
size: number,
|
||||
emotion: number,
|
||||
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_EYES_NORMAL = require("../../../assets/mascot/mascot_eyes_normal.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_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_SUNGLASSES = require("../../../assets/mascot/mascot_sunglasses.png");
|
||||
|
||||
export const EYE_STYLE = {
|
||||
NORMAL: 0,
|
||||
GIRLY: 2,
|
||||
CUTE: 3,
|
||||
WINK: 4,
|
||||
HEART: 5,
|
||||
ANGRY: 6,
|
||||
}
|
||||
|
||||
const GLASSES_STYLE = {
|
||||
NORMAL: 0,
|
||||
COOl: 1
|
||||
}
|
||||
|
||||
export const MASCOT_STYLE = {
|
||||
|
@ -31,30 +51,96 @@ export const MASCOT_STYLE = {
|
|||
WINK: 3,
|
||||
CUTE: 4,
|
||||
INTELLO: 5,
|
||||
LOVE: 6,
|
||||
COOL: 7,
|
||||
ANGRY: 8,
|
||||
};
|
||||
|
||||
|
||||
class Mascot extends React.Component<Props> {
|
||||
class Mascot extends React.Component<Props, State> {
|
||||
|
||||
static defaultProps = {
|
||||
animated: false
|
||||
state = {
|
||||
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) {
|
||||
super(props);
|
||||
this.viewRef = React.createRef();
|
||||
this.eyeList = {};
|
||||
this.glassesList = {};
|
||||
this.eyeList[EYE_STYLE.NORMAL] = MASCOT_EYES_NORMAL;
|
||||
this.eyeList[EYE_STYLE.GIRLY] = MASCOT_EYES_GIRLY;
|
||||
this.eyeList[EYE_STYLE.CUTE] = MASCOT_EYES_CUTE;
|
||||
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
|
||||
key={"glasses"}
|
||||
source={MASCOT_GLASSES}
|
||||
source={glasses != null ? glasses : this.glassesList[GLASSES_STYLE.NORMAL]}
|
||||
style={{
|
||||
position: "absolute",
|
||||
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];
|
||||
return <Image
|
||||
key={isRight ? "right" : "left"}
|
||||
|
@ -76,6 +162,7 @@ class Mascot extends React.Component<Props> {
|
|||
left: isRight ? "-11%" : "11%",
|
||||
width: this.props.size,
|
||||
height: this.props.size,
|
||||
transform: [{rotateY: rotation}]
|
||||
}}
|
||||
/>
|
||||
}
|
||||
|
@ -85,10 +172,10 @@ class Mascot extends React.Component<Props> {
|
|||
final.push(<View
|
||||
key={"container"}
|
||||
style={{
|
||||
position: "absolute",
|
||||
width: this.props.size,
|
||||
height: this.props.size,
|
||||
}}/>);
|
||||
position: "absolute",
|
||||
width: this.props.size,
|
||||
height: this.props.size,
|
||||
}}/>);
|
||||
if (emotion === MASCOT_STYLE.CUTE) {
|
||||
final.push(this.getEye(EYE_STYLE.CUTE, true));
|
||||
final.push(this.getEye(EYE_STYLE.CUTE, false));
|
||||
|
@ -101,13 +188,21 @@ class Mascot extends React.Component<Props> {
|
|||
} else if (emotion === MASCOT_STYLE.WINK) {
|
||||
final.push(this.getEye(EYE_STYLE.WINK, true));
|
||||
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 {
|
||||
final.push(this.getEye(EYE_STYLE.NORMAL, true));
|
||||
final.push(this.getEye(EYE_STYLE.NORMAL, false));
|
||||
}
|
||||
|
||||
if (emotion === MASCOT_STYLE.INTELLO) {
|
||||
final.push(this.getGlasses())
|
||||
if (emotion === MASCOT_STYLE.INTELLO) { // Needs to have normal eyes behind the glasses
|
||||
final.push(this.getGlasses(GLASSES_STYLE.NORMAL));
|
||||
}
|
||||
final.push(<View key={"container2"}/>);
|
||||
return final;
|
||||
|
@ -115,31 +210,37 @@ class Mascot extends React.Component<Props> {
|
|||
|
||||
render() {
|
||||
const size = this.props.size;
|
||||
const entryAnimation = this.props.animated ? this.props.entryAnimation : null;
|
||||
const loopAnimation = this.props.animated ? this.props.loopAnimation : null;
|
||||
return (
|
||||
<Animatable.View
|
||||
style={{
|
||||
width: size,
|
||||
height: size,
|
||||
}}
|
||||
useNativeDriver={true}
|
||||
animation={this.props.animated ? "rubberBand" : null}
|
||||
duration={2000}
|
||||
{...entryAnimation}
|
||||
>
|
||||
<View
|
||||
useNativeDriver={true}
|
||||
animation={this.props.animated ? "swing" : null}
|
||||
duration={2000}
|
||||
iterationCount={"infinite"}
|
||||
<TouchableWithoutFeedback
|
||||
onPress={() => this.onPress(this.viewRef)}
|
||||
onLongPress={() => this.onLongPress(this.viewRef)}
|
||||
>
|
||||
<Image
|
||||
source={MASCOT_IMAGE}
|
||||
style={{
|
||||
width: size,
|
||||
height: size,
|
||||
}}
|
||||
/>
|
||||
{this.getEyes(this.props.emotion)}
|
||||
</View>
|
||||
<Animatable.View
|
||||
ref={this.viewRef}
|
||||
>
|
||||
<Animatable.View
|
||||
{...loopAnimation}
|
||||
>
|
||||
<Image
|
||||
source={MASCOT_IMAGE}
|
||||
style={{
|
||||
width: size,
|
||||
height: size,
|
||||
}}
|
||||
/>
|
||||
{this.getEyes(this.state.currentEmotion)}
|
||||
</Animatable.View>
|
||||
</Animatable.View>
|
||||
</TouchableWithoutFeedback>
|
||||
</Animatable.View>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
// @flow
|
||||
|
||||
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 {Text} from "react-native-paper";
|
||||
import i18n from 'i18n-js';
|
||||
import AppIntroSlider from "react-native-app-intro-slider";
|
||||
import Update from "../../constants/Update";
|
||||
import ThemeManager from "../../managers/ThemeManager";
|
||||
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 = {
|
||||
onDone: Function,
|
||||
|
@ -16,17 +19,34 @@ type Props = {
|
|||
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
|
||||
*/
|
||||
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>;
|
||||
updateSlides: Array<Object>;
|
||||
aprilFoolsSlides: Array<Object>;
|
||||
currentSlides: Array<Object>;
|
||||
sliderRef: { current: null | AppIntroSlider };
|
||||
|
||||
introSlides: Array<Slide>;
|
||||
updateSlides: Array<Slide>;
|
||||
aprilFoolsSlides: Array<Slide>;
|
||||
currentSlides: Array<Slide>;
|
||||
|
||||
/**
|
||||
* Generates intro slides
|
||||
|
@ -36,53 +56,44 @@ export default class CustomIntroSlider extends React.Component<Props> {
|
|||
this.sliderRef = React.createRef();
|
||||
this.introSlides = [
|
||||
{
|
||||
key: 'main',
|
||||
key: '0', // Mascot
|
||||
title: i18n.t('intro.slideMain.title'),
|
||||
text: i18n.t('intro.slideMain.text'),
|
||||
image: require('../../../assets/splash.png'),
|
||||
colors: ['#be1522', '#740d15'],
|
||||
view: this.getWelcomeView,
|
||||
mascotStyle: MASCOT_STYLE.NORMAL,
|
||||
colors: ['#be1522', '#57080e'],
|
||||
},
|
||||
{
|
||||
key: 'Planex',
|
||||
key: '1',
|
||||
title: i18n.t('intro.slidePlanex.title'),
|
||||
text: i18n.t('intro.slidePlanex.text'),
|
||||
icon: 'timetable',
|
||||
colors: ['#e77020', '#803e12'],
|
||||
view: () => this.getIconView("calendar-clock"),
|
||||
mascotStyle: MASCOT_STYLE.INTELLO,
|
||||
colors: ['#be1522', '#57080e'],
|
||||
},
|
||||
{
|
||||
key: 'RU',
|
||||
title: i18n.t('intro.slideRU.title'),
|
||||
text: i18n.t('intro.slideRU.text'),
|
||||
icon: 'silverware-fork-knife',
|
||||
colors: ['#dcac18', '#8b6a15'],
|
||||
},
|
||||
{
|
||||
key: 'events',
|
||||
key: '2',
|
||||
title: i18n.t('intro.slideEvents.title'),
|
||||
text: i18n.t('intro.slideEvents.text'),
|
||||
icon: 'calendar-range',
|
||||
colors: ['#41a006', '#095c03'],
|
||||
view: () => this.getIconView("calendar-star",),
|
||||
mascotStyle: MASCOT_STYLE.HAPPY,
|
||||
colors: ['#be1522', '#57080e'],
|
||||
},
|
||||
{
|
||||
key: 'proxiwash',
|
||||
title: i18n.t('intro.slideProxiwash.title'),
|
||||
text: i18n.t('intro.slideProxiwash.text'),
|
||||
icon: 'washing-machine',
|
||||
colors: ['#1fa5ee', '#06537d'],
|
||||
},
|
||||
{
|
||||
key: 'services',
|
||||
key: '3',
|
||||
title: i18n.t('intro.slideServices.title'),
|
||||
text: i18n.t('intro.slideServices.text'),
|
||||
icon: 'view-dashboard-variant',
|
||||
colors: ['#6737c1', '#281a5a'],
|
||||
view: () => this.getIconView("view-dashboard-variant",),
|
||||
mascotStyle: MASCOT_STYLE.CUTE,
|
||||
colors: ['#be1522', '#57080e'],
|
||||
},
|
||||
{
|
||||
key: 'done',
|
||||
key: '4',
|
||||
title: i18n.t('intro.slideDone.title'),
|
||||
text: i18n.t('intro.slideDone.text'),
|
||||
icon: 'account-heart',
|
||||
colors: ['#b837c1', '#501a5a'],
|
||||
view: () => this.getIconView("account-heart",),
|
||||
mascotStyle: MASCOT_STYLE.COOL,
|
||||
colors: ['#9c165b', '#3e042b'],
|
||||
},
|
||||
];
|
||||
this.updateSlides = [];
|
||||
|
@ -103,50 +114,127 @@ export default class CustomIntroSlider extends React.Component<Props> {
|
|||
key: '1',
|
||||
title: i18n.t('intro.aprilFoolsSlide.title'),
|
||||
text: i18n.t('intro.aprilFoolsSlide.text'),
|
||||
icon: 'fish',
|
||||
view: () => <View/>,
|
||||
mascotStyle: MASCOT_STYLE.NORMAL,
|
||||
colors: ['#e01928', '#be1522'],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render item to be used for the intro introSlides
|
||||
*
|
||||
* @param item The item to be displayed
|
||||
* @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 (
|
||||
<LinearGradient
|
||||
style={[
|
||||
styles.mainContent,
|
||||
dimensions,
|
||||
dimensions
|
||||
]}
|
||||
colors={item.colors}
|
||||
start={{x: 0, y: 0.1}}
|
||||
end={{x: 0.1, y: 1}}
|
||||
>
|
||||
{item.image !== undefined ?
|
||||
<View style={styles.image}>
|
||||
<Image
|
||||
source={item.image}
|
||||
resizeMode={"contain"}
|
||||
style={{width: '100%', height: '100%'}}
|
||||
/>
|
||||
</View>
|
||||
: <MaterialCommunityIcons
|
||||
name={item.icon}
|
||||
color={'#fff'}
|
||||
size={200}/>}
|
||||
<View style={{marginTop: 20}}>
|
||||
<Text style={styles.title}>{item.title}</Text>
|
||||
<Text style={styles.text}>{item.text}</Text>
|
||||
</View>
|
||||
{this.state.currentSlide === index
|
||||
? <View style={{height: "100%", flex: 1}}>
|
||||
<View style={{flex: 1}}>
|
||||
{item.view()}
|
||||
</View>
|
||||
<Animatable.View
|
||||
animation={"fadeIn"}>
|
||||
{index !== 0
|
||||
? <Animatable.View
|
||||
animation={"pulse"}
|
||||
iterationCount={"infinite"}
|
||||
duration={2000}
|
||||
style={{
|
||||
marginLeft: 30,
|
||||
marginBottom: 0,
|
||||
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>
|
||||
);
|
||||
}
|
||||
|
||||
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) {
|
||||
if (Platform.OS === 'android')
|
||||
StatusBar.setBackgroundColor(color, true);
|
||||
|
@ -154,12 +242,13 @@ export default class CustomIntroSlider extends React.Component<Props> {
|
|||
|
||||
onSlideChange = (index: number, lastIndex: number) => {
|
||||
this.setStatusBarColor(this.currentSlides[index].colors[0]);
|
||||
this.setState({currentSlide: index});
|
||||
};
|
||||
|
||||
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)
|
||||
this.sliderRef.current.goToSlide(this.currentSlides.length-1);
|
||||
this.sliderRef.current.goToSlide(this.currentSlides.length - 1);
|
||||
}
|
||||
|
||||
onDone = () => {
|
||||
|
@ -167,6 +256,42 @@ export default class CustomIntroSlider extends React.Component<Props> {
|
|||
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() {
|
||||
this.currentSlides = this.introSlides;
|
||||
if (this.props.isUpdate)
|
||||
|
@ -177,16 +302,16 @@ export default class CustomIntroSlider extends React.Component<Props> {
|
|||
return (
|
||||
<AppIntroSlider
|
||||
ref={this.sliderRef}
|
||||
renderItem={CustomIntroSlider.getIntroRenderItem}
|
||||
data={this.currentSlides}
|
||||
extraData={this.state.currentSlide}
|
||||
|
||||
renderItem={this.getIntroRenderItem}
|
||||
renderNextButton={this.renderNextButton}
|
||||
renderDoneButton={this.renderDoneButton}
|
||||
|
||||
onDone={this.onDone}
|
||||
bottomButton
|
||||
showSkipButton
|
||||
onSlideChange={this.onSlideChange}
|
||||
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({
|
||||
mainContent: {
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
paddingBottom: 100
|
||||
},
|
||||
image: {
|
||||
width: 300,
|
||||
height: 300,
|
||||
marginBottom: -50,
|
||||
paddingBottom: 100,
|
||||
},
|
||||
text: {
|
||||
color: 'rgba(255, 255, 255, 0.8)',
|
||||
|
@ -219,4 +336,10 @@ const styles = StyleSheet.create({
|
|||
textAlign: 'center',
|
||||
marginBottom: 16,
|
||||
},
|
||||
center: {
|
||||
marginTop: 'auto',
|
||||
marginBottom: 'auto',
|
||||
marginRight: 'auto',
|
||||
marginLeft: 'auto',
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue