Browse Source

Update game to use TypeScript

Arnaud Vergnet 3 years ago
parent
commit
fde9a12ef9

src/screens/Game/Shapes/BaseShape.js → src/screens/Game/Shapes/BaseShape.ts View File

@@ -19,11 +19,9 @@
19 19
 
20 20
 // @flow
21 21
 
22
-import type {CustomThemeType} from '../../../managers/ThemeManager';
23
-
24 22
 export type CoordinatesType = {
25
-  x: number,
26
-  y: number,
23
+  x: number;
24
+  y: number;
27 25
 };
28 26
 
29 27
 export type ShapeType = Array<Array<number>>;
@@ -40,14 +38,15 @@ export default class BaseShape {
40 38
 
41 39
   position: CoordinatesType;
42 40
 
43
-  theme: CustomThemeType;
41
+  theme: ReactNativePaper.Theme;
44 42
 
45 43
   /**
46 44
    * Prevent instantiation if classname is BaseShape to force class to be abstract
47 45
    */
48
-  constructor(theme: CustomThemeType) {
49
-    if (this.constructor === BaseShape)
46
+  constructor(theme: ReactNativePaper.Theme) {
47
+    if (this.constructor === BaseShape) {
50 48
       throw new Error("Abstract class can't be instantiated");
49
+    }
51 50
     this.theme = theme;
52 51
     this.#rotation = 0;
53 52
     this.position = {x: 0, y: 0};
@@ -58,7 +57,6 @@ export default class BaseShape {
58 57
    * Gets this shape's color.
59 58
    * Must be implemented by child class
60 59
    */
61
-  // eslint-disable-next-line class-methods-use-this
62 60
   getColor(): string {
63 61
     throw new Error("Method 'getColor()' must be implemented");
64 62
   }
@@ -69,7 +67,6 @@ export default class BaseShape {
69 67
    *
70 68
    * Used by tests to read private fields
71 69
    */
72
-  // eslint-disable-next-line class-methods-use-this
73 70
   getShapes(): Array<ShapeType> {
74 71
     throw new Error("Method 'getShapes()' must be implemented");
75 72
   }
@@ -98,7 +95,9 @@ export default class BaseShape {
98 95
               x: this.position.x + col,
99 96
               y: this.position.y + row,
100 97
             });
101
-          } else coordinates.push({x: col, y: row});
98
+          } else {
99
+            coordinates.push({x: col, y: row});
100
+          }
102 101
         }
103 102
       }
104 103
     }
@@ -111,10 +110,16 @@ export default class BaseShape {
111 110
    * @param isForward Should we rotate clockwise?
112 111
    */
113 112
   rotate(isForward: boolean) {
114
-    if (isForward) this.#rotation += 1;
115
-    else this.#rotation -= 1;
116
-    if (this.#rotation > 3) this.#rotation = 0;
117
-    else if (this.#rotation < 0) this.#rotation = 3;
113
+    if (isForward) {
114
+      this.#rotation += 1;
115
+    } else {
116
+      this.#rotation -= 1;
117
+    }
118
+    if (this.#rotation > 3) {
119
+      this.#rotation = 0;
120
+    } else if (this.#rotation < 0) {
121
+      this.#rotation = 3;
122
+    }
118 123
     this.#currentShape = this.getShapes()[this.#rotation];
119 124
   }
120 125
 

src/screens/Game/Shapes/ShapeI.js → src/screens/Game/Shapes/ShapeI.ts View File

@@ -17,14 +17,11 @@
17 17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18 18
  */
19 19
 
20
-// @flow
21
-
22 20
 import BaseShape from './BaseShape';
23
-import type {CustomThemeType} from '../../../managers/ThemeManager';
24 21
 import type {ShapeType} from './BaseShape';
25 22
 
26 23
 export default class ShapeI extends BaseShape {
27
-  constructor(theme: CustomThemeType) {
24
+  constructor(theme: ReactNativePaper.Theme) {
28 25
     super(theme);
29 26
     this.position.x = 3;
30 27
   }
@@ -33,7 +30,6 @@ export default class ShapeI extends BaseShape {
33 30
     return this.theme.colors.tetrisI;
34 31
   }
35 32
 
36
-  // eslint-disable-next-line class-methods-use-this
37 33
   getShapes(): Array<ShapeType> {
38 34
     return [
39 35
       [

src/screens/Game/Shapes/ShapeJ.js → src/screens/Game/Shapes/ShapeJ.ts View File

@@ -17,14 +17,11 @@
17 17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18 18
  */
19 19
 
20
-// @flow
21
-
22 20
 import BaseShape from './BaseShape';
23
-import type {CustomThemeType} from '../../../managers/ThemeManager';
24 21
 import type {ShapeType} from './BaseShape';
25 22
 
26 23
 export default class ShapeJ extends BaseShape {
27
-  constructor(theme: CustomThemeType) {
24
+  constructor(theme: ReactNativePaper.Theme) {
28 25
     super(theme);
29 26
     this.position.x = 3;
30 27
   }
@@ -33,7 +30,6 @@ export default class ShapeJ extends BaseShape {
33 30
     return this.theme.colors.tetrisJ;
34 31
   }
35 32
 
36
-  // eslint-disable-next-line class-methods-use-this
37 33
   getShapes(): Array<ShapeType> {
38 34
     return [
39 35
       [

src/screens/Game/Shapes/ShapeL.js → src/screens/Game/Shapes/ShapeL.ts View File

@@ -17,14 +17,11 @@
17 17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18 18
  */
19 19
 
20
-// @flow
21
-
22 20
 import BaseShape from './BaseShape';
23
-import type {CustomThemeType} from '../../../managers/ThemeManager';
24 21
 import type {ShapeType} from './BaseShape';
25 22
 
26 23
 export default class ShapeL extends BaseShape {
27
-  constructor(theme: CustomThemeType) {
24
+  constructor(theme: ReactNativePaper.Theme) {
28 25
     super(theme);
29 26
     this.position.x = 3;
30 27
   }
@@ -33,7 +30,6 @@ export default class ShapeL extends BaseShape {
33 30
     return this.theme.colors.tetrisL;
34 31
   }
35 32
 
36
-  // eslint-disable-next-line class-methods-use-this
37 33
   getShapes(): Array<ShapeType> {
38 34
     return [
39 35
       [

src/screens/Game/Shapes/ShapeO.js → src/screens/Game/Shapes/ShapeO.ts View File

@@ -17,14 +17,11 @@
17 17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18 18
  */
19 19
 
20
-// @flow
21
-
22 20
 import BaseShape from './BaseShape';
23
-import type {CustomThemeType} from '../../../managers/ThemeManager';
24 21
 import type {ShapeType} from './BaseShape';
25 22
 
26 23
 export default class ShapeO extends BaseShape {
27
-  constructor(theme: CustomThemeType) {
24
+  constructor(theme: ReactNativePaper.Theme) {
28 25
     super(theme);
29 26
     this.position.x = 4;
30 27
   }
@@ -33,7 +30,6 @@ export default class ShapeO extends BaseShape {
33 30
     return this.theme.colors.tetrisO;
34 31
   }
35 32
 
36
-  // eslint-disable-next-line class-methods-use-this
37 33
   getShapes(): Array<ShapeType> {
38 34
     return [
39 35
       [

src/screens/Game/Shapes/ShapeS.js → src/screens/Game/Shapes/ShapeS.ts View File

@@ -17,14 +17,11 @@
17 17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18 18
  */
19 19
 
20
-// @flow
21
-
22 20
 import BaseShape from './BaseShape';
23
-import type {CustomThemeType} from '../../../managers/ThemeManager';
24 21
 import type {ShapeType} from './BaseShape';
25 22
 
26 23
 export default class ShapeS extends BaseShape {
27
-  constructor(theme: CustomThemeType) {
24
+  constructor(theme: ReactNativePaper.Theme) {
28 25
     super(theme);
29 26
     this.position.x = 3;
30 27
   }
@@ -33,7 +30,6 @@ export default class ShapeS extends BaseShape {
33 30
     return this.theme.colors.tetrisS;
34 31
   }
35 32
 
36
-  // eslint-disable-next-line class-methods-use-this
37 33
   getShapes(): Array<ShapeType> {
38 34
     return [
39 35
       [

src/screens/Game/Shapes/ShapeT.js → src/screens/Game/Shapes/ShapeT.ts View File

@@ -17,14 +17,11 @@
17 17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18 18
  */
19 19
 
20
-// @flow
21
-
22 20
 import BaseShape from './BaseShape';
23
-import type {CustomThemeType} from '../../../managers/ThemeManager';
24 21
 import type {ShapeType} from './BaseShape';
25 22
 
26 23
 export default class ShapeT extends BaseShape {
27
-  constructor(theme: CustomThemeType) {
24
+  constructor(theme: ReactNativePaper.Theme) {
28 25
     super(theme);
29 26
     this.position.x = 3;
30 27
   }
@@ -33,7 +30,6 @@ export default class ShapeT extends BaseShape {
33 30
     return this.theme.colors.tetrisT;
34 31
   }
35 32
 
36
-  // eslint-disable-next-line class-methods-use-this
37 33
   getShapes(): Array<ShapeType> {
38 34
     return [
39 35
       [

src/screens/Game/Shapes/ShapeZ.js → src/screens/Game/Shapes/ShapeZ.ts View File

@@ -17,14 +17,11 @@
17 17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18 18
  */
19 19
 
20
-// @flow
21
-
22 20
 import BaseShape from './BaseShape';
23
-import type {CustomThemeType} from '../../../managers/ThemeManager';
24 21
 import type {ShapeType} from './BaseShape';
25 22
 
26 23
 export default class ShapeZ extends BaseShape {
27
-  constructor(theme: CustomThemeType) {
24
+  constructor(theme: ReactNativePaper.Theme) {
28 25
     super(theme);
29 26
     this.position.x = 3;
30 27
   }
@@ -33,7 +30,6 @@ export default class ShapeZ extends BaseShape {
33 30
     return this.theme.colors.tetrisZ;
34 31
   }
35 32
 
36
-  // eslint-disable-next-line class-methods-use-this
37 33
   getShapes(): Array<ShapeType> {
38 34
     return [
39 35
       [

src/screens/Game/components/CellComponent.js → src/screens/Game/components/CellComponent.tsx View File

@@ -17,35 +17,29 @@
17 17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18 18
  */
19 19
 
20
-// @flow
21
-
22 20
 import * as React from 'react';
23 21
 import {View} from 'react-native';
24
-import {withTheme} from 'react-native-paper';
25 22
 
26
-export type CellType = {color: string, isEmpty: boolean, key: string};
23
+export type CellType = {color: string; isEmpty: boolean; key: string};
27 24
 
28 25
 type PropsType = {
29
-  cell: CellType,
26
+  cell: CellType;
30 27
 };
31 28
 
32
-class CellComponent extends React.PureComponent<PropsType> {
33
-  render(): React.Node {
34
-    const {props} = this;
35
-    const item = props.cell;
36
-    return (
37
-      <View
38
-        style={{
39
-          flex: 1,
40
-          backgroundColor: item.isEmpty ? 'transparent' : item.color,
41
-          borderColor: 'transparent',
42
-          borderRadius: 4,
43
-          borderWidth: 1,
44
-          aspectRatio: 1,
45
-        }}
46
-      />
47
-    );
48
-  }
29
+function CellComponent(props: PropsType) {
30
+  const item = props.cell;
31
+  return (
32
+    <View
33
+      style={{
34
+        flex: 1,
35
+        backgroundColor: item.isEmpty ? 'transparent' : item.color,
36
+        borderColor: 'transparent',
37
+        borderRadius: 4,
38
+        borderWidth: 1,
39
+        aspectRatio: 1,
40
+      }}
41
+    />
42
+  );
49 43
 }
50 44
 
51
-export default withTheme(CellComponent);
45
+export default CellComponent;

+ 0
- 76
src/screens/Game/components/GridComponent.js View File

@@ -1,76 +0,0 @@
1
-/*
2
- * Copyright (c) 2019 - 2020 Arnaud Vergnet.
3
- *
4
- * This file is part of Campus INSAT.
5
- *
6
- * Campus INSAT is free software: you can redistribute it and/or modify
7
- *  it under the terms of the GNU General Public License as published by
8
- * the Free Software Foundation, either version 3 of the License, or
9
- * (at your option) any later version.
10
- *
11
- * Campus INSAT is distributed in the hope that it will be useful,
12
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
- * GNU General Public License for more details.
15
- *
16
- * You should have received a copy of the GNU General Public License
17
- * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18
- */
19
-
20
-// @flow
21
-
22
-import * as React from 'react';
23
-import {View} from 'react-native';
24
-import {withTheme} from 'react-native-paper';
25
-import type {ViewStyle} from 'react-native/Libraries/StyleSheet/StyleSheet';
26
-import type {CellType} from './CellComponent';
27
-import CellComponent from './CellComponent';
28
-
29
-export type GridType = Array<Array<CellComponent>>;
30
-
31
-type PropsType = {
32
-  grid: Array<Array<CellType>>,
33
-  height: number,
34
-  width: number,
35
-  style: ViewStyle,
36
-};
37
-
38
-class GridComponent extends React.Component<PropsType> {
39
-  getRow(rowNumber: number): React.Node {
40
-    const {grid} = this.props;
41
-    return (
42
-      <View style={{flexDirection: 'row'}} key={rowNumber.toString()}>
43
-        {grid[rowNumber].map(this.getCellRender)}
44
-      </View>
45
-    );
46
-  }
47
-
48
-  getCellRender = (item: CellType): React.Node => {
49
-    return <CellComponent cell={item} key={item.key} />;
50
-  };
51
-
52
-  getGrid(): React.Node {
53
-    const {height} = this.props;
54
-    const rows = [];
55
-    for (let i = 0; i < height; i += 1) {
56
-      rows.push(this.getRow(i));
57
-    }
58
-    return rows;
59
-  }
60
-
61
-  render(): React.Node {
62
-    const {style, width, height} = this.props;
63
-    return (
64
-      <View
65
-        style={{
66
-          aspectRatio: width / height,
67
-          borderRadius: 4,
68
-          ...style,
69
-        }}>
70
-        {this.getGrid()}
71
-      </View>
72
-    );
73
-  }
74
-}
75
-
76
-export default withTheme(GridComponent);

+ 68
- 0
src/screens/Game/components/GridComponent.tsx View File

@@ -0,0 +1,68 @@
1
+/*
2
+ * Copyright (c) 2019 - 2020 Arnaud Vergnet.
3
+ *
4
+ * This file is part of Campus INSAT.
5
+ *
6
+ * Campus INSAT is free software: you can redistribute it and/or modify
7
+ *  it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * Campus INSAT is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License
17
+ * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18
+ */
19
+
20
+import * as React from 'react';
21
+import {View, ViewStyle} from 'react-native';
22
+import type {CellType} from './CellComponent';
23
+import CellComponent from './CellComponent';
24
+
25
+export type GridType = Array<Array<CellType>>;
26
+
27
+type PropsType = {
28
+  grid: GridType;
29
+  height: number;
30
+  width: number;
31
+  style: ViewStyle;
32
+};
33
+
34
+const getCellRender = (item: CellType) => {
35
+  return <CellComponent cell={item} key={item.key} />;
36
+};
37
+
38
+function getRow(grid: GridType, rowNumber: number) {
39
+  return (
40
+    <View style={{flexDirection: 'row'}} key={rowNumber.toString()}>
41
+      {grid[rowNumber].map(getCellRender)}
42
+    </View>
43
+  );
44
+}
45
+
46
+function getGrid(grid: GridType, height: number) {
47
+  const rows = [];
48
+  for (let i = 0; i < height; i += 1) {
49
+    rows.push(getRow(grid, i));
50
+  }
51
+  return rows;
52
+}
53
+
54
+function GridComponent(props: PropsType) {
55
+  const {style, width, height, grid} = props;
56
+  return (
57
+    <View
58
+      style={{
59
+        aspectRatio: width / height,
60
+        borderRadius: 4,
61
+        ...style,
62
+      }}>
63
+      {getGrid(grid, height)}
64
+    </View>
65
+  );
66
+}
67
+
68
+export default GridComponent;

src/screens/Game/components/Preview.js → src/screens/Game/components/Preview.tsx View File

@@ -17,53 +17,48 @@
17 17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18 18
  */
19 19
 
20
-// @flow
21
-
22 20
 import * as React from 'react';
23
-import {View} from 'react-native';
24
-import {withTheme} from 'react-native-paper';
25
-import type {ViewStyle} from 'react-native/Libraries/StyleSheet/StyleSheet';
21
+import {View, ViewStyle} from 'react-native';
26 22
 import type {GridType} from './GridComponent';
27 23
 import GridComponent from './GridComponent';
28 24
 
29 25
 type PropsType = {
30
-  items: Array<GridType>,
31
-  style: ViewStyle,
26
+  items: Array<GridType>;
27
+  style: ViewStyle;
32 28
 };
33 29
 
34
-class Preview extends React.PureComponent<PropsType> {
35
-  getGrids(): React.Node {
36
-    const {items} = this.props;
37
-    const grids = [];
38
-    items.forEach((item: GridType, index: number) => {
39
-      grids.push(Preview.getGridRender(item, index));
40
-    });
41
-    return grids;
42
-  }
30
+function getGridRender(item: GridType, index: number) {
31
+  return (
32
+    <GridComponent
33
+      width={item[0].length}
34
+      height={item.length}
35
+      grid={item}
36
+      style={{
37
+        marginRight: 5,
38
+        marginLeft: 5,
39
+        marginBottom: 5,
40
+      }}
41
+      key={index.toString()}
42
+    />
43
+  );
44
+}
43 45
 
44
-  static getGridRender(item: GridType, index: number): React.Node {
45
-    return (
46
-      <GridComponent
47
-        width={item[0].length}
48
-        height={item.length}
49
-        grid={item}
50
-        style={{
51
-          marginRight: 5,
52
-          marginLeft: 5,
53
-          marginBottom: 5,
54
-        }}
55
-        key={index.toString()}
56
-      />
57
-    );
58
-  }
46
+function getGrids(items: Array<GridType>) {
47
+  const grids: Array<React.ReactNode> = [];
48
+  items.forEach((item: GridType, index: number) => {
49
+    grids.push(getGridRender(item, index));
50
+  });
51
+  return grids;
52
+}
59 53
 
60
-  render(): React.Node {
54
+class Preview extends React.PureComponent<PropsType> {
55
+  render() {
61 56
     const {style, items} = this.props;
62 57
     if (items.length > 0) {
63
-      return <View style={style}>{this.getGrids()}</View>;
58
+      return <View style={style}>{getGrids(items)}</View>;
64 59
     }
65 60
     return null;
66 61
   }
67 62
 }
68 63
 
69
-export default withTheme(Preview);
64
+export default Preview;

src/screens/Game/logic/GameLogic.js → src/screens/Game/logic/GameLogic.ts View File

@@ -17,12 +17,9 @@
17 17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18 18
  */
19 19
 
20
-// @flow
21
-
22 20
 import Piece from './Piece';
23 21
 import ScoreManager from './ScoreManager';
24 22
 import GridManager from './GridManager';
25
-import type {CustomThemeType} from '../../../managers/ThemeManager';
26 23
 import type {GridType} from '../components/GridComponent';
27 24
 
28 25
 export type TickCallbackType = (
@@ -58,15 +55,15 @@ export default class GameLogic {
58 55
 
59 56
   gameTime: number;
60 57
 
61
-  currentObject: Piece;
58
+  currentObject?: Piece;
62 59
 
63 60
   gameTick: number;
64 61
 
65
-  gameTickInterval: IntervalID;
62
+  gameTickInterval?: NodeJS.Timeout;
66 63
 
67
-  gameTimeInterval: IntervalID;
64
+  gameTimeInterval?: NodeJS.Timeout;
68 65
 
69
-  pressInInterval: TimeoutID;
66
+  pressInInterval?: NodeJS.Timeout;
70 67
 
71 68
   isPressedIn: boolean;
72 69
 
@@ -78,15 +75,19 @@ export default class GameLogic {
78 75
 
79 76
   nextPiecesCount: number;
80 77
 
81
-  tickCallback: TickCallbackType;
78
+  tickCallback?: TickCallbackType;
79
+
80
+  clockCallback?: ClockCallbackType;
82 81
 
83
-  clockCallback: ClockCallbackType;
82
+  endCallback?: EndCallbackType;
84 83
 
85
-  endCallback: EndCallbackType;
84
+  theme: ReactNativePaper.Theme;
86 85
 
87
-  theme: CustomThemeType;
86
+  constructor(height: number, width: number, theme: ReactNativePaper.Theme) {
87
+    this.gameTime = 0;
88
+    this.gameTick = 0;
89
+    this.isPressedIn = false;
88 90
 
89
-  constructor(height: number, width: number, theme: CustomThemeType) {
90 91
     this.height = height;
91 92
     this.width = width;
92 93
     this.gameRunning = false;
@@ -121,12 +122,16 @@ export default class GameLogic {
121 122
   }
122 123
 
123 124
   onFreeze = () => {
124
-    this.gridManager.freezeTetromino(this.currentObject, this.scoreManager);
125
+    if (this.currentObject) {
126
+      this.gridManager.freezeTetromino(this.currentObject, this.scoreManager);
127
+    }
125 128
     this.createTetromino();
126 129
   };
127 130
 
128 131
   setNewGameTick(level: number) {
129
-    if (level >= GameLogic.levelTicks.length) return;
132
+    if (level >= GameLogic.levelTicks.length) {
133
+      return;
134
+    }
130 135
     this.gameTick = GameLogic.levelTicks[level];
131 136
     this.stopTick();
132 137
     this.startTick();
@@ -145,11 +150,15 @@ export default class GameLogic {
145 150
   }
146 151
 
147 152
   stopClock() {
148
-    clearInterval(this.gameTimeInterval);
153
+    if (this.gameTimeInterval) {
154
+      clearInterval(this.gameTimeInterval);
155
+    }
149 156
   }
150 157
 
151 158
   stopTick() {
152
-    clearInterval(this.gameTickInterval);
159
+    if (this.gameTickInterval) {
160
+      clearInterval(this.gameTickInterval);
161
+    }
153 162
   }
154 163
 
155 164
   stopGameTime() {
@@ -162,27 +171,34 @@ export default class GameLogic {
162 171
     this.startTick();
163 172
   }
164 173
 
165
-  onTick(callback: TickCallbackType) {
166
-    this.currentObject.tryMove(
167
-      0,
168
-      1,
169
-      this.gridManager.getCurrentGrid(),
170
-      this.getWidth(),
171
-      this.getHeight(),
172
-      this.onFreeze,
173
-    );
174
-    callback(
175
-      this.scoreManager.getScore(),
176
-      this.scoreManager.getLevel(),
177
-      this.gridManager.getCurrentGrid(),
178
-    );
179
-    if (this.scoreManager.canLevelUp())
174
+  onTick(callback?: TickCallbackType) {
175
+    if (this.currentObject) {
176
+      this.currentObject.tryMove(
177
+        0,
178
+        1,
179
+        this.gridManager.getCurrentGrid(),
180
+        this.getWidth(),
181
+        this.getHeight(),
182
+        this.onFreeze,
183
+      );
184
+    }
185
+    if (callback) {
186
+      callback(
187
+        this.scoreManager.getScore(),
188
+        this.scoreManager.getLevel(),
189
+        this.gridManager.getCurrentGrid(),
190
+      );
191
+    }
192
+    if (this.scoreManager.canLevelUp()) {
180 193
       this.setNewGameTick(this.scoreManager.getLevel());
194
+    }
181 195
   }
182 196
 
183
-  onClock(callback: ClockCallbackType) {
197
+  onClock(callback?: ClockCallbackType) {
184 198
     this.gameTime += 1;
185
-    callback(this.gameTime);
199
+    if (callback) {
200
+      callback(this.gameTime);
201
+    }
186 202
   }
187 203
 
188 204
   canUseInput(): boolean {
@@ -210,15 +226,19 @@ export default class GameLogic {
210 226
     x: number,
211 227
     y: number,
212 228
   ) {
213
-    if (!this.canUseInput() || !this.isPressedIn) return;
214
-    const moved = this.currentObject.tryMove(
215
-      x,
216
-      y,
217
-      this.gridManager.getCurrentGrid(),
218
-      this.getWidth(),
219
-      this.getHeight(),
220
-      this.onFreeze,
221
-    );
229
+    if (!this.canUseInput() || !this.isPressedIn) {
230
+      return;
231
+    }
232
+    const moved =
233
+      this.currentObject &&
234
+      this.currentObject.tryMove(
235
+        x,
236
+        y,
237
+        this.gridManager.getCurrentGrid(),
238
+        this.getWidth(),
239
+        this.getHeight(),
240
+        this.onFreeze,
241
+      );
222 242
     if (moved) {
223 243
       if (y === 1) {
224 244
         this.scoreManager.incrementScore();
@@ -226,7 +246,9 @@ export default class GameLogic {
226 246
           this.gridManager.getCurrentGrid(),
227 247
           this.scoreManager.getScore(),
228 248
         );
229
-      } else callback(this.gridManager.getCurrentGrid());
249
+      } else {
250
+        callback(this.gridManager.getCurrentGrid());
251
+      }
230 252
     }
231 253
     this.pressInInterval = setTimeout(
232 254
       () => {
@@ -238,20 +260,26 @@ export default class GameLogic {
238 260
 
239 261
   pressedOut() {
240 262
     this.isPressedIn = false;
241
-    clearTimeout(this.pressInInterval);
263
+    if (this.pressInInterval) {
264
+      clearTimeout(this.pressInInterval);
265
+    }
242 266
   }
243 267
 
244 268
   rotatePressed(callback: MovementCallbackType) {
245
-    if (!this.canUseInput()) return;
269
+    if (!this.canUseInput()) {
270
+      return;
271
+    }
246 272
 
247 273
     if (
274
+      this.currentObject &&
248 275
       this.currentObject.tryRotate(
249 276
         this.gridManager.getCurrentGrid(),
250 277
         this.getWidth(),
251 278
         this.getHeight(),
252 279
       )
253
-    )
280
+    ) {
254 281
       callback(this.gridManager.getCurrentGrid());
282
+    }
255 283
   }
256 284
 
257 285
   getNextPiecesPreviews(): Array<GridType> {
@@ -266,7 +294,10 @@ export default class GameLogic {
266 294
   }
267 295
 
268 296
   recoverNextPiece() {
269
-    this.currentObject = this.nextPieces.shift();
297
+    const next = this.nextPieces.shift();
298
+    if (next) {
299
+      this.currentObject = next;
300
+    }
270 301
     this.generateNextPieces();
271 302
   }
272 303
 
@@ -280,27 +311,36 @@ export default class GameLogic {
280 311
     this.pressedOut();
281 312
     this.recoverNextPiece();
282 313
     if (
314
+      this.currentObject &&
283 315
       !this.currentObject.isPositionValid(
284 316
         this.gridManager.getCurrentGrid(),
285 317
         this.getWidth(),
286 318
         this.getHeight(),
287 319
       )
288
-    )
320
+    ) {
289 321
       this.endGame(false);
322
+    }
290 323
   }
291 324
 
292 325
   togglePause() {
293
-    if (!this.gameRunning) return;
326
+    if (!this.gameRunning) {
327
+      return;
328
+    }
294 329
     this.gamePaused = !this.gamePaused;
295
-    if (this.gamePaused) this.stopGameTime();
296
-    else this.startGameTime();
330
+    if (this.gamePaused) {
331
+      this.stopGameTime();
332
+    } else {
333
+      this.startGameTime();
334
+    }
297 335
   }
298 336
 
299 337
   endGame(isRestart: boolean) {
300 338
     this.gameRunning = false;
301 339
     this.gamePaused = false;
302 340
     this.stopGameTime();
303
-    this.endCallback(this.gameTime, this.scoreManager.getScore(), isRestart);
341
+    if (this.endCallback) {
342
+      this.endCallback(this.gameTime, this.scoreManager.getScore(), isRestart);
343
+    }
304 344
   }
305 345
 
306 346
   startGame(
@@ -308,7 +348,9 @@ export default class GameLogic {
308 348
     clockCallback: ClockCallbackType,
309 349
     endCallback: EndCallbackType,
310 350
   ) {
311
-    if (this.gameRunning) this.endGame(true);
351
+    if (this.gameRunning) {
352
+      this.endGame(true);
353
+    }
312 354
     this.gameRunning = true;
313 355
     this.gamePaused = false;
314 356
     this.gameTime = 0;

src/screens/Game/logic/GridManager.js → src/screens/Game/logic/GridManager.ts View File

@@ -17,14 +17,11 @@
17 17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18 18
  */
19 19
 
20
-// @flow
21
-
22 20
 import Piece from './Piece';
23 21
 import ScoreManager from './ScoreManager';
24 22
 import type {CoordinatesType} from '../Shapes/BaseShape';
25 23
 import type {GridType} from '../components/GridComponent';
26 24
 import type {CellType} from '../components/CellComponent';
27
-import type {CustomThemeType} from '../../../managers/ThemeManager';
28 25
 
29 26
 /**
30 27
  * Class used to manage the game grid
@@ -32,7 +29,7 @@ import type {CustomThemeType} from '../../../managers/ThemeManager';
32 29
 export default class GridManager {
33 30
   #currentGrid: GridType;
34 31
 
35
-  #theme: CustomThemeType;
32
+  #theme: ReactNativePaper.Theme;
36 33
 
37 34
   /**
38 35
    * Initializes a grid of the given size
@@ -41,7 +38,7 @@ export default class GridManager {
41 38
    * @param height The grid height
42 39
    * @param theme Object containing current theme
43 40
    */
44
-  constructor(width: number, height: number, theme: CustomThemeType) {
41
+  constructor(width: number, height: number, theme: ReactNativePaper.Theme) {
45 42
     this.#theme = theme;
46 43
     this.#currentGrid = this.getEmptyGrid(height, width);
47 44
   }
@@ -121,7 +118,9 @@ export default class GridManager {
121 118
           break;
122 119
         }
123 120
       }
124
-      if (isLineFull && rows.indexOf(pos[i].y) === -1) rows.push(pos[i].y);
121
+      if (isLineFull && rows.indexOf(pos[i].y) === -1) {
122
+        rows.push(pos[i].y);
123
+      }
125 124
     }
126 125
     return rows;
127 126
   }

src/screens/Game/logic/Piece.js → src/screens/Game/logic/Piece.ts View File

@@ -17,8 +17,6 @@
17 17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18 18
  */
19 19
 
20
-// @flow
21
-
22 20
 import ShapeL from '../Shapes/ShapeL';
23 21
 import ShapeI from '../Shapes/ShapeI';
24 22
 import ShapeJ from '../Shapes/ShapeJ';
@@ -29,7 +27,6 @@ import ShapeZ from '../Shapes/ShapeZ';
29 27
 import type {CoordinatesType} from '../Shapes/BaseShape';
30 28
 import BaseShape from '../Shapes/BaseShape';
31 29
 import type {GridType} from '../components/GridComponent';
32
-import type {CustomThemeType} from '../../../managers/ThemeManager';
33 30
 
34 31
 /**
35 32
  * Class used as an abstraction layer for shapes.
@@ -41,14 +38,14 @@ export default class Piece {
41 38
 
42 39
   currentShape: BaseShape;
43 40
 
44
-  theme: CustomThemeType;
41
+  theme: ReactNativePaper.Theme;
45 42
 
46 43
   /**
47 44
    * Initializes this piece's color and shape
48 45
    *
49 46
    * @param theme Object containing current theme
50 47
    */
51
-  constructor(theme: CustomThemeType) {
48
+  constructor(theme: ReactNativePaper.Theme) {
52 49
     this.currentShape = this.getRandomShape(theme);
53 50
     this.theme = theme;
54 51
   }
@@ -58,7 +55,7 @@ export default class Piece {
58 55
    *
59 56
    * @param theme Object containing current theme
60 57
    */
61
-  getRandomShape(theme: CustomThemeType): BaseShape {
58
+  getRandomShape(theme: ReactNativePaper.Theme): BaseShape {
62 59
     return new this.shapes[Math.floor(Math.random() * 7)](theme);
63 60
   }
64 61
 
@@ -72,7 +69,6 @@ export default class Piece {
72 69
       true,
73 70
     );
74 71
     pos.forEach((coordinates: CoordinatesType) => {
75
-      // eslint-disable-next-line no-param-reassign
76 72
       grid[coordinates.y][coordinates.x] = {
77 73
         color: this.theme.colors.tetrisBackground,
78 74
         isEmpty: true,
@@ -92,7 +88,6 @@ export default class Piece {
92 88
       !isPreview,
93 89
     );
94 90
     pos.forEach((coordinates: CoordinatesType) => {
95
-      // eslint-disable-next-line no-param-reassign
96 91
       grid[coordinates.y][coordinates.x] = {
97 92
         color: this.currentShape.getColor(),
98 93
         isEmpty: false,
@@ -150,21 +145,35 @@ export default class Piece {
150 145
   ): boolean {
151 146
     let newX = x;
152 147
     let newY = y;
153
-    if (x > 1) newX = 1; // Prevent moving from more than one tile
154
-    if (x < -1) newX = -1;
155
-    if (y > 1) newY = 1;
156
-    if (y < -1) newY = -1;
157
-    if (x !== 0 && y !== 0) newY = 0; // Prevent diagonal movement
148
+    if (x > 1) {
149
+      newX = 1;
150
+    } // Prevent moving from more than one tile
151
+    if (x < -1) {
152
+      newX = -1;
153
+    }
154
+    if (y > 1) {
155
+      newY = 1;
156
+    }
157
+    if (y < -1) {
158
+      newY = -1;
159
+    }
160
+    if (x !== 0 && y !== 0) {
161
+      newY = 0;
162
+    } // Prevent diagonal movement
158 163
 
159 164
     this.removeFromGrid(grid);
160 165
     this.currentShape.move(newX, newY);
161 166
     const isValid = this.isPositionValid(grid, width, height);
162 167
 
163
-    if (!isValid) this.currentShape.move(-newX, -newY);
168
+    if (!isValid) {
169
+      this.currentShape.move(-newX, -newY);
170
+    }
164 171
 
165 172
     const shouldFreeze = !isValid && newY !== 0;
166 173
     this.toGrid(grid, false);
167
-    if (shouldFreeze) freezeCallback();
174
+    if (shouldFreeze) {
175
+      freezeCallback();
176
+    }
168 177
     return isValid;
169 178
   }
170 179
 

src/screens/Game/logic/ScoreManager.js → src/screens/Game/logic/ScoreManager.ts View File

@@ -17,8 +17,6 @@
17 17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18 18
  */
19 19
 
20
-// @flow
21
-
22 20
 /**
23 21
  * Class used to manage game score
24 22
  */
@@ -83,7 +81,9 @@ export default class ScoreManager {
83 81
    * @param numberRemoved The number of lines removed at the same time
84 82
    */
85 83
   addLinesRemovedPoints(numberRemoved: number) {
86
-    if (numberRemoved < 1 || numberRemoved > 4) return;
84
+    if (numberRemoved < 1 || numberRemoved > 4) {
85
+      return;
86
+    }
87 87
     this.#score +=
88 88
       this.#scoreLinesModifier[numberRemoved - 1] * (this.#level + 1);
89 89
     switch (numberRemoved) {

src/screens/Game/screens/GameMainScreen.js → src/screens/Game/screens/GameMainScreen.tsx View File

@@ -17,8 +17,6 @@
17 17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18 18
  */
19 19
 
20
-// @flow
21
-
22 20
 import * as React from 'react';
23 21
 import {View} from 'react-native';
24 22
 import {Caption, IconButton, Text, withTheme} from 'react-native-paper';
@@ -32,27 +30,26 @@ import Preview from '../components/Preview';
32 30
 import MaterialHeaderButtons, {
33 31
   Item,
34 32
 } from '../../../components/Overrides/CustomHeaderButton';
35
-import type {CustomThemeType} from '../../../managers/ThemeManager';
36 33
 import type {OptionsDialogButtonType} from '../../../components/Dialogs/OptionsDialog';
37 34
 import OptionsDialog from '../../../components/Dialogs/OptionsDialog';
38 35
 
39 36
 type PropsType = {
40
-  navigation: StackNavigationProp,
41
-  route: {params: {highScore: number}},
42
-  theme: CustomThemeType,
37
+  navigation: StackNavigationProp<any>;
38
+  route: {params: {highScore: number}};
39
+  theme: ReactNativePaper.Theme;
43 40
 };
44 41
 
45 42
 type StateType = {
46
-  grid: GridType,
47
-  gameTime: number,
48
-  gameScore: number,
49
-  gameLevel: number,
43
+  grid: GridType;
44
+  gameTime: number;
45
+  gameScore: number;
46
+  gameLevel: number;
50 47
 
51
-  dialogVisible: boolean,
52
-  dialogTitle: string,
53
-  dialogMessage: string,
54
-  dialogButtons: Array<OptionsDialogButtonType>,
55
-  onDialogDismiss: () => void,
48
+  dialogVisible: boolean;
49
+  dialogTitle: string;
50
+  dialogMessage: string;
51
+  dialogButtons: Array<OptionsDialogButtonType>;
52
+  onDialogDismiss: () => void;
56 53
 };
57 54
 
58 55
 class GameMainScreen extends React.Component<PropsType, StateType> {
@@ -62,11 +59,13 @@ class GameMainScreen extends React.Component<PropsType, StateType> {
62 59
     date.setMinutes(0);
63 60
     date.setSeconds(seconds);
64 61
     let format;
65
-    if (date.getHours())
62
+    if (date.getHours()) {
66 63
       format = `${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`;
67
-    else if (date.getMinutes())
64
+    } else if (date.getMinutes()) {
68 65
       format = `${date.getMinutes()}:${date.getSeconds()}`;
69
-    else format = date.getSeconds().toString();
66
+    } else {
67
+      format = date.getSeconds().toString();
68
+    }
70 69
     return format;
71 70
   }
72 71
 
@@ -76,6 +75,7 @@ class GameMainScreen extends React.Component<PropsType, StateType> {
76 75
 
77 76
   constructor(props: PropsType) {
78 77
     super(props);
78
+    this.highScore = null;
79 79
     this.logic = new GameLogic(20, 10, props.theme);
80 80
     this.state = {
81 81
       grid: this.logic.getCurrentGrid(),
@@ -88,8 +88,9 @@ class GameMainScreen extends React.Component<PropsType, StateType> {
88 88
       dialogButtons: [],
89 89
       onDialogDismiss: () => {},
90 90
     };
91
-    if (props.route.params != null)
91
+    if (props.route.params != null) {
92 92
       this.highScore = props.route.params.highScore;
93
+    }
93 94
   }
94 95
 
95 96
   componentDidMount() {
@@ -104,7 +105,7 @@ class GameMainScreen extends React.Component<PropsType, StateType> {
104 105
     this.logic.endGame(true);
105 106
   }
106 107
 
107
-  getRightButton = (): React.Node => {
108
+  getRightButton = () => {
108 109
     return (
109 110
       <MaterialHeaderButtons>
110 111
         <Item title="pause" iconName="pause" onPress={this.togglePause} />
@@ -136,15 +137,16 @@ class GameMainScreen extends React.Component<PropsType, StateType> {
136 137
       gameTime: time,
137 138
       gameScore: score,
138 139
     });
139
-    if (!isRestart)
140
+    if (!isRestart) {
140 141
       props.navigation.replace('game-start', {
141 142
         score: state.gameScore,
142 143
         level: state.gameLevel,
143 144
         time: state.gameTime,
144 145
       });
146
+    }
145 147
   };
146 148
 
147
-  getStatusIcons(): React.Node {
149
+  getStatusIcons() {
148 150
     const {props, state} = this;
149 151
     return (
150 152
       <View
@@ -219,7 +221,7 @@ class GameMainScreen extends React.Component<PropsType, StateType> {
219 221
     );
220 222
   }
221 223
 
222
-  getScoreIcon(): React.Node {
224
+  getScoreIcon() {
223 225
     const {props, state} = this;
224 226
     const highScore =
225 227
       this.highScore == null || state.gameScore > this.highScore
@@ -285,7 +287,7 @@ class GameMainScreen extends React.Component<PropsType, StateType> {
285 287
     );
286 288
   }
287 289
 
288
-  getControlButtons(): React.Node {
290
+  getControlButtons() {
289 291
     const {props} = this;
290 292
     return (
291 293
       <View
@@ -353,8 +355,8 @@ class GameMainScreen extends React.Component<PropsType, StateType> {
353 355
 
354 356
   updateGridScore = (newGrid: GridType, score?: number) => {
355 357
     this.setState((prevState: StateType): {
356
-      grid: GridType,
357
-      gameScore: number,
358
+      grid: GridType;
359
+      gameScore: number;
358 360
     } => ({
359 361
       grid: newGrid,
360 362
       gameScore: score != null ? score : prevState.gameScore,
@@ -363,7 +365,9 @@ class GameMainScreen extends React.Component<PropsType, StateType> {
363 365
 
364 366
   togglePause = () => {
365 367
     this.logic.togglePause();
366
-    if (this.logic.isGamePaused()) this.showPausePopup();
368
+    if (this.logic.isGamePaused()) {
369
+      this.showPausePopup();
370
+    }
367 371
   };
368 372
 
369 373
   showPausePopup = () => {
@@ -415,7 +419,7 @@ class GameMainScreen extends React.Component<PropsType, StateType> {
415 419
     this.logic.startGame(this.onTick, this.onClock, this.onGameEnd);
416 420
   };
417 421
 
418
-  render(): React.Node {
422
+  render() {
419 423
     const {props, state} = this;
420 424
     return (
421 425
       <View style={{flex: 1}}>

src/screens/Game/screens/GameStartScreen.js → src/screens/Game/screens/GameStartScreen.tsx View File

@@ -17,8 +17,6 @@
17 17
  * along with Campus INSAT.  If not, see <https://www.gnu.org/licenses/>.
18 18
  */
19 19
 
20
-// @flow
21
-
22 20
 import * as React from 'react';
23 21
 import {StackNavigationProp} from '@react-navigation/stack';
24 22
 import {
@@ -35,7 +33,6 @@ import i18n from 'i18n-js';
35 33
 import * as Animatable from 'react-native-animatable';
36 34
 import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
37 35
 import LinearGradient from 'react-native-linear-gradient';
38
-import type {CustomThemeType} from '../../../managers/ThemeManager';
39 36
 import Mascot, {MASCOT_STYLE} from '../../../components/Mascot/Mascot';
40 37
 import MascotPopup from '../../../components/Mascot/MascotPopup';
41 38
 import AsyncStorageManager from '../../../managers/AsyncStorageManager';
@@ -47,17 +44,17 @@ import SpeechArrow from '../../../components/Mascot/SpeechArrow';
47 44
 import CollapsibleScrollView from '../../../components/Collapsible/CollapsibleScrollView';
48 45
 
49 46
 type GameStatsType = {
50
-  score: number,
51
-  level: number,
52
-  time: number,
47
+  score: number;
48
+  level: number;
49
+  time: number;
53 50
 };
54 51
 
55 52
 type PropsType = {
56
-  navigation: StackNavigationProp,
53
+  navigation: StackNavigationProp<any>;
57 54
   route: {
58
-    params: GameStatsType,
59
-  },
60
-  theme: CustomThemeType,
55
+    params: GameStatsType;
56
+  };
57
+  theme: ReactNativePaper.Theme;
61 58
 };
62 59
 
63 60
 class GameStartScreen extends React.Component<PropsType> {
@@ -65,21 +62,24 @@ class GameStartScreen extends React.Component<PropsType> {
65 62
 
66 63
   scores: Array<number>;
67 64
 
68
-  gameStats: GameStatsType | null;
65
+  gameStats?: GameStatsType;
69 66
 
70 67
   isHighScore: boolean;
71 68
 
72 69
   constructor(props: PropsType) {
73 70
     super(props);
71
+    this.isHighScore = false;
74 72
     this.gridManager = new GridManager(4, 4, props.theme);
75 73
     this.scores = AsyncStorageManager.getObject(
76 74
       AsyncStorageManager.PREFERENCES.gameScores.key,
77 75
     );
78 76
     this.scores.sort((a: number, b: number): number => b - a);
79
-    if (props.route.params != null) this.recoverGameScore();
77
+    if (props.route.params != null) {
78
+      this.recoverGameScore();
79
+    }
80 80
   }
81 81
 
82
-  getPiecesBackground(): React.Node {
82
+  getPiecesBackground() {
83 83
     const {theme} = this.props;
84 84
     const gridList = [];
85 85
     for (let i = 0; i < 18; i += 1) {
@@ -94,7 +94,7 @@ class GameStartScreen extends React.Component<PropsType> {
94 94
           width: '100%',
95 95
           height: '100%',
96 96
         }}>
97
-        {gridList.map((item: GridType, index: number): React.Node => {
97
+        {gridList.map((item: GridType, index: number) => {
98 98
           const size = 10 + Math.floor(Math.random() * 30);
99 99
           const top = Math.floor(Math.random() * 100);
100 100
           const rot = Math.floor(Math.random() * 360);
@@ -129,7 +129,7 @@ class GameStartScreen extends React.Component<PropsType> {
129 129
     );
130 130
   }
131 131
 
132
-  getPostGameContent(stats: GameStatsType): React.Node {
132
+  getPostGameContent(stats: GameStatsType) {
133 133
     const {props} = this;
134 134
     return (
135 135
       <View
@@ -141,8 +141,8 @@ class GameStartScreen extends React.Component<PropsType> {
141 141
           animated={this.isHighScore}
142 142
           style={{
143 143
             width: this.isHighScore ? '50%' : '30%',
144
-            marginLeft: this.isHighScore ? 'auto' : null,
145
-            marginRight: this.isHighScore ? 'auto' : null,
144
+            marginLeft: this.isHighScore ? 'auto' : undefined,
145
+            marginRight: this.isHighScore ? 'auto' : undefined,
146 146
           }}
147 147
         />
148 148
         <SpeechArrow
@@ -235,7 +235,7 @@ class GameStartScreen extends React.Component<PropsType> {
235 235
     );
236 236
   }
237 237
 
238
-  getWelcomeText(): React.Node {
238
+  getWelcomeText() {
239 239
     const {props} = this;
240 240
     return (
241 241
       <View>
@@ -281,7 +281,7 @@ class GameStartScreen extends React.Component<PropsType> {
281 281
     );
282 282
   }
283 283
 
284
-  getPodiumRender(place: 1 | 2 | 3, score: string): React.Node {
284
+  getPodiumRender(place: 1 | 2 | 3, score: string) {
285 285
     const {props} = this;
286 286
     let icon = 'podium-gold';
287 287
     let color = props.theme.colors.gameGold;
@@ -338,7 +338,7 @@ class GameStartScreen extends React.Component<PropsType> {
338 338
         <Text
339 339
           style={{
340 340
             textAlign: 'center',
341
-            fontWeight: place === 1 ? 'bold' : null,
341
+            fontWeight: place === 1 ? 'bold' : undefined,
342 342
             fontSize,
343 343
           }}>
344 344
           {score}
@@ -347,7 +347,7 @@ class GameStartScreen extends React.Component<PropsType> {
347 347
     );
348 348
   }
349 349
 
350
-  getTopScoresRender(): React.Node {
350
+  getTopScoresRender() {
351 351
     const gold = this.scores.length > 0 ? this.scores[0] : '-';
352 352
     const silver = this.scores.length > 1 ? this.scores[1] : '-';
353 353
     const bronze = this.scores.length > 2 ? this.scores[2] : '-';
@@ -371,7 +371,7 @@ class GameStartScreen extends React.Component<PropsType> {
371 371
     );
372 372
   }
373 373
 
374
-  getMainContent(): React.Node {
374
+  getMainContent() {
375 375
     const {props} = this;
376 376
     return (
377 377
       <View style={{flex: 1}}>
@@ -415,7 +415,9 @@ class GameStartScreen extends React.Component<PropsType> {
415 415
           break;
416 416
         }
417 417
       }
418
-      if (this.scores.length > 3) this.scores.splice(3, 1);
418
+      if (this.scores.length > 3) {
419
+        this.scores.splice(3, 1);
420
+      }
419 421
       AsyncStorageManager.set(
420 422
         AsyncStorageManager.PREFERENCES.gameScores.key,
421 423
         this.scores,
@@ -423,7 +425,7 @@ class GameStartScreen extends React.Component<PropsType> {
423 425
     }
424 426
   }
425 427
 
426
-  render(): React.Node {
428
+  render() {
427 429
     const {props} = this;
428 430
     return (
429 431
       <View style={{flex: 1}}>
@@ -444,7 +446,6 @@ class GameStartScreen extends React.Component<PropsType> {
444 446
               message={i18n.t('screens.game.mascotDialog.message')}
445 447
               icon="gamepad-variant"
446 448
               buttons={{
447
-                action: null,
448 449
                 cancel: {
449 450
                   message: i18n.t('screens.game.mascotDialog.button'),
450 451
                   icon: 'check',

Loading…
Cancel
Save