diff --git a/src/components/Mascot/Mascot.js b/src/components/Mascot/Mascot.tsx
similarity index 75%
rename from src/components/Mascot/Mascot.js
rename to src/components/Mascot/Mascot.tsx
index 7ea5b49..6ad77d6 100644
--- a/src/components/Mascot/Mascot.js
+++ b/src/components/Mascot/Mascot.tsx
@@ -17,27 +17,27 @@
* along with Campus INSAT. If not, see .
*/
-// @flow
-
import * as React from 'react';
import * as Animatable from 'react-native-animatable';
-import {Image, TouchableWithoutFeedback, View} from 'react-native';
-import type {ViewStyle} from 'react-native/Libraries/StyleSheet/StyleSheet';
+import {Image, TouchableWithoutFeedback, View, ViewStyle} from 'react-native';
+import {AnimatableProperties} from 'react-native-animatable';
-export type AnimatableViewRefType = {current: null | Animatable.View};
+export type AnimatableViewRefType = {
+ current: null | (typeof Animatable.View & View);
+};
type PropsType = {
- emotion?: number,
- animated?: boolean,
- style?: ViewStyle | null,
- entryAnimation?: Animatable.AnimatableProperties | null,
- loopAnimation?: Animatable.AnimatableProperties | null,
- onPress?: null | ((viewRef: AnimatableViewRefType) => void),
- onLongPress?: null | ((viewRef: AnimatableViewRefType) => void),
+ emotion?: MASCOT_STYLE;
+ animated?: boolean;
+ style?: ViewStyle;
+ entryAnimation?: AnimatableProperties;
+ loopAnimation?: AnimatableProperties;
+ onPress?: null | ((viewRef: AnimatableViewRefType) => void);
+ onLongPress?: null | ((viewRef: AnimatableViewRefType) => void);
};
type StateType = {
- currentEmotion: number,
+ currentEmotion: MASCOT_STYLE;
};
const MASCOT_IMAGE = require('../../../assets/mascot/mascot.png');
@@ -50,32 +50,32 @@ 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,
-};
+enum EYE_STYLE {
+ NORMAL,
+ GIRLY,
+ CUTE,
+ WINK,
+ HEART,
+ ANGRY,
+}
-const GLASSES_STYLE = {
- NORMAL: 0,
- COOl: 1,
-};
+enum GLASSES_STYLE {
+ NORMAL,
+ COOl,
+}
-export const MASCOT_STYLE = {
- NORMAL: 0,
- HAPPY: 1,
- GIRLY: 2,
- WINK: 3,
- CUTE: 4,
- INTELLO: 5,
- LOVE: 6,
- COOL: 7,
- ANGRY: 8,
- RANDOM: 999,
-};
+export enum MASCOT_STYLE {
+ NORMAL,
+ HAPPY,
+ GIRLY,
+ WINK,
+ CUTE,
+ INTELLO,
+ LOVE,
+ COOL,
+ ANGRY,
+ RANDOM = 999,
+}
class Mascot extends React.Component {
static defaultProps = {
@@ -100,9 +100,9 @@ class Mascot extends React.Component {
viewRef: AnimatableViewRefType;
- eyeList: {[key: number]: number | string};
+ eyeList: {[key in EYE_STYLE]: number};
- glassesList: {[key: number]: number | string};
+ glassesList: {[key in GLASSES_STYLE]: number};
onPress: (viewRef: AnimatableViewRefType) => void;
@@ -113,23 +113,25 @@ class Mascot extends React.Component {
constructor(props: PropsType) {
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.eyeList = {
+ [EYE_STYLE.NORMAL]: MASCOT_EYES_NORMAL,
+ [EYE_STYLE.GIRLY]: MASCOT_EYES_GIRLY,
+ [EYE_STYLE.CUTE]: MASCOT_EYES_CUTE,
+ [EYE_STYLE.WINK]: MASCOT_EYES_WINK,
+ [EYE_STYLE.HEART]: MASCOT_EYES_HEART,
+ [EYE_STYLE.ANGRY]: MASCOT_EYES_ANGRY,
+ };
+ this.glassesList = {
+ [GLASSES_STYLE.NORMAL]: MASCOT_GLASSES,
+ [GLASSES_STYLE.COOl]: MASCOT_SUNGLASSES,
+ };
+ this.initialEmotion = props.emotion
+ ? props.emotion
+ : Mascot.defaultProps.emotion;
- this.glassesList[GLASSES_STYLE.NORMAL] = MASCOT_GLASSES;
- this.glassesList[GLASSES_STYLE.COOl] = MASCOT_SUNGLASSES;
-
- this.initialEmotion =
- props.emotion != null ? props.emotion : Mascot.defaultProps.emotion;
-
- if (this.initialEmotion === MASCOT_STYLE.RANDOM)
+ if (this.initialEmotion === MASCOT_STYLE.RANDOM) {
this.initialEmotion = Math.floor(Math.random() * MASCOT_STYLE.ANGRY) + 1;
+ }
this.state = {
currentEmotion: this.initialEmotion,
@@ -138,29 +140,33 @@ class Mascot extends React.Component {
if (props.onPress == null) {
this.onPress = (viewRef: AnimatableViewRefType) => {
const ref = viewRef.current;
- if (ref != null) {
+ if (ref && ref.rubberBand) {
this.setState({currentEmotion: MASCOT_STYLE.LOVE});
ref.rubberBand(1500).then(() => {
this.setState({currentEmotion: this.initialEmotion});
});
}
};
- } else this.onPress = props.onPress;
+ } else {
+ this.onPress = props.onPress;
+ }
if (props.onLongPress == null) {
this.onLongPress = (viewRef: AnimatableViewRefType) => {
const ref = viewRef.current;
- if (ref != null) {
+ if (ref && ref.tada) {
this.setState({currentEmotion: MASCOT_STYLE.ANGRY});
ref.tada(1000).then(() => {
this.setState({currentEmotion: this.initialEmotion});
});
}
};
- } else this.onLongPress = props.onLongPress;
+ } else {
+ this.onLongPress = props.onLongPress;
+ }
}
- getGlasses(style: number): React.Node {
+ getGlasses(style: GLASSES_STYLE) {
const glasses = this.glassesList[style];
return (
{
);
}
- getEye(
- style: number,
- isRight: boolean,
- rotation: string = '0deg',
- ): React.Node {
+ getEye(style: EYE_STYLE, isRight: boolean, rotation: string = '0deg') {
const eye = this.eyeList[style];
return (
{
);
}
- getEyes(emotion: number): React.Node {
+ getEyes(emotion: MASCOT_STYLE) {
const final = [];
final.push(
{
return final;
}
- render(): React.Node {
+ render() {
const {props, state} = this;
const entryAnimation = props.animated ? props.entryAnimation : null;
const loopAnimation = props.animated ? props.loopAnimation : null;
@@ -256,7 +258,6 @@ class Mascot extends React.Component {
aspectRatio: 1,
...props.style,
}}
- // eslint-disable-next-line react/jsx-props-no-spreading
{...entryAnimation}>
{
@@ -266,9 +267,7 @@ class Mascot extends React.Component {
this.onLongPress(this.viewRef);
}}>
-
+
.
*/
-// @flow
-
import * as React from 'react';
import {
Avatar,
@@ -37,48 +35,42 @@ import {
View,
} from 'react-native';
import Mascot from './Mascot';
-import type {CustomThemeType} from '../../managers/ThemeManager';
import SpeechArrow from './SpeechArrow';
import AsyncStorageManager from '../../managers/AsyncStorageManager';
type PropsType = {
- theme: CustomThemeType,
- icon: string,
- title: string,
- message: string,
+ theme: ReactNativePaper.Theme;
+ icon: string;
+ title: string;
+ message: string;
buttons: {
- action: {
- message: string,
- icon: string | null,
- color: string | null,
- onPress?: () => void,
- },
- cancel: {
- message: string,
- icon: string | null,
- color: string | null,
- onPress?: () => void,
- },
- },
- emotion: number,
- visible?: boolean,
- prefKey?: string,
+ action?: {
+ message: string;
+ icon?: string;
+ color?: string;
+ onPress?: () => void;
+ };
+ cancel?: {
+ message: string;
+ icon?: string;
+ color?: string;
+ onPress?: () => void;
+ };
+ };
+ emotion: number;
+ visible?: boolean;
+ prefKey?: string;
};
type StateType = {
- shouldRenderDialog: boolean, // Used to stop rendering after hide animation
- dialogVisible: boolean,
+ shouldRenderDialog: boolean; // Used to stop rendering after hide animation
+ dialogVisible: boolean;
};
/**
* Component used to display a popup with the mascot.
*/
class MascotPopup extends React.Component {
- static defaultProps = {
- visible: null,
- prefKey: null,
- };
-
mascotSize: number;
windowWidth: number;
@@ -112,7 +104,7 @@ class MascotPopup extends React.Component {
}
}
- componentDidMount(): * {
+ componentDidMount() {
BackHandler.addEventListener(
'hardwareBackPress',
this.onBackButtonPressAndroid,
@@ -146,14 +138,20 @@ class MascotPopup extends React.Component {
if (state.dialogVisible) {
const {cancel} = props.buttons;
const {action} = props.buttons;
- if (cancel != null) this.onDismiss(cancel.onPress);
- else this.onDismiss(action.onPress);
+ if (cancel) {
+ this.onDismiss(cancel.onPress);
+ } else if (action) {
+ this.onDismiss(action.onPress);
+ } else {
+ this.onDismiss();
+ }
+
return true;
}
return false;
};
- getSpeechBubble(): React.Node {
+ getSpeechBubble() {
const {state, props} = this;
return (
{
title={props.title}
left={
props.icon != null
- ? (): React.Node => (
+ ? () => (
{
icon={props.icon}
/>
)
- : null
+ : undefined
}
/>
{
);
}
- getMascot(): React.Node {
+ getMascot() {
const {props, state} = this;
return (
{
);
}
- getButtons(): React.Node {
+ getButtons() {
const {props} = this;
const {action} = props.buttons;
const {cancel} = props.buttons;
@@ -270,12 +268,12 @@ class MascotPopup extends React.Component {
);
}
- getBackground(): React.Node {
+ getBackground() {
const {props, state} = this;
return (
{
- this.onDismiss(props.buttons.cancel.onPress);
+ this.onDismiss(props.buttons.cancel?.onPress);
}}>
{
AsyncStorageManager.set(prefKey, false);
this.setState({dialogVisible: false});
}
- if (callback != null) callback();
+ if (callback != null) {
+ callback();
+ }
};
- render(): React.Node {
+ render() {
const {shouldRenderDialog} = this.state;
if (shouldRenderDialog) {
return (
diff --git a/src/components/Mascot/SpeechArrow.js b/src/components/Mascot/SpeechArrow.js
deleted file mode 100644
index b336878..0000000
--- a/src/components/Mascot/SpeechArrow.js
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2019 - 2020 Arnaud Vergnet.
- *
- * This file is part of Campus INSAT.
- *
- * Campus INSAT is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Campus INSAT is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Campus INSAT. If not, see .
- */
-
-// @flow
-
-import * as React from 'react';
-import {View} from 'react-native';
-import type {ViewStyle} from 'react-native/Libraries/StyleSheet/StyleSheet';
-
-type PropsType = {
- style?: ViewStyle | null,
- size: number,
- color: string,
-};
-
-export default class SpeechArrow extends React.Component {
- static defaultProps = {
- style: null,
- };
-
- shouldComponentUpdate(): boolean {
- return false;
- }
-
- render(): React.Node {
- const {props} = this;
- return (
-
-
-
- );
- }
-}
diff --git a/src/constants/PaperStyles.js b/src/components/Mascot/SpeechArrow.tsx
similarity index 52%
rename from src/constants/PaperStyles.js
rename to src/components/Mascot/SpeechArrow.tsx
index 28a29d8..464a193 100644
--- a/src/constants/PaperStyles.js
+++ b/src/components/Mascot/SpeechArrow.tsx
@@ -17,15 +17,32 @@
* along with Campus INSAT. If not, see .
*/
-// @flow
+import * as React from 'react';
+import {View, ViewStyle} from 'react-native';
-import type {ViewStyleProp} from 'react-native/Libraries/StyleSheet/StyleSheet';
-
-export type ListIconPropsType = {
- color: string,
- style: ViewStyleProp,
+type PropsType = {
+ style?: ViewStyle;
+ size: number;
+ color: string;
};
-export type CardTitleIconPropsType = {
- size: number,
-};
+export default function SpeechArrow(props: PropsType) {
+ return (
+
+
+
+ );
+}