|
@@ -1,32 +1,39 @@
|
1
|
|
-// @flow
|
|
1
|
+/* eslint-disable lines-around-comment */
|
2
|
2
|
|
3
|
3
|
import React, { Component } from 'react';
|
|
4
|
+import { WithTranslation } from 'react-i18next';
|
4
|
5
|
import { Platform } from 'react-native';
|
5
|
|
-import { SafeAreaView } from 'react-native-safe-area-context';
|
|
6
|
+import { Edge, SafeAreaView } from 'react-native-safe-area-context';
|
6
|
7
|
|
7
|
|
-import { connect } from '../../../base/redux';
|
|
8
|
+import { IReduxState } from '../../../app/types';
|
|
9
|
+import { connect } from '../../../base/redux/functions';
|
8
|
10
|
import { hideNotification } from '../../actions';
|
9
|
11
|
import { areThereNotifications } from '../../functions';
|
10
|
12
|
import NotificationsTransition from '../NotificationsTransition';
|
11
|
13
|
|
12
|
14
|
import Notification from './Notification';
|
|
15
|
+// @ts-ignore
|
|
16
|
+import styles from './styles';
|
13
|
17
|
|
14
|
18
|
|
15
|
|
-type Props = {
|
|
19
|
+interface IProps extends WithTranslation {
|
16
|
20
|
|
17
|
21
|
/**
|
18
|
22
|
* The notifications to be displayed, with the first index being the
|
19
|
23
|
* notification at the top and the rest shown below it in order.
|
20
|
24
|
*/
|
21
|
|
- _notifications: Array<Object>,
|
|
25
|
+ _notifications: Array<Object>;
|
22
|
26
|
|
23
|
27
|
/**
|
24
|
28
|
* Invoked to update the redux store in order to remove notifications.
|
25
|
29
|
*/
|
26
|
|
- dispatch: Function,
|
|
30
|
+ dispatch: Function;
|
27
|
31
|
|
28
|
|
- toolboxVisible: boolean
|
29
|
|
-};
|
|
32
|
+ /**
|
|
33
|
+ * Checks toolbox visibility.
|
|
34
|
+ */
|
|
35
|
+ toolboxVisible: boolean;
|
|
36
|
+}
|
30
|
37
|
|
31
|
38
|
/**
|
32
|
39
|
* Implements a React {@link Component} which displays notifications and handles
|
|
@@ -35,19 +42,19 @@ type Props = {
|
35
|
42
|
*
|
36
|
43
|
* @augments {Component}
|
37
|
44
|
*/
|
38
|
|
-class NotificationsContainer extends Component<Props> {
|
|
45
|
+class NotificationsContainer extends Component<IProps> {
|
39
|
46
|
|
40
|
47
|
/**
|
41
|
48
|
* A timeout id returned by setTimeout.
|
42
|
49
|
*/
|
43
|
|
- _notificationDismissTimeout: ?TimeoutID;
|
|
50
|
+ _notificationDismissTimeout: any;
|
44
|
51
|
|
45
|
52
|
/**
|
46
|
53
|
* Initializes a new {@code NotificationsContainer} instance.
|
47
|
54
|
*
|
48
|
55
|
* @inheritdoc
|
49
|
56
|
*/
|
50
|
|
- constructor(props: Props) {
|
|
57
|
+ constructor(props: IProps) {
|
51
|
58
|
super(props);
|
52
|
59
|
|
53
|
60
|
/**
|
|
@@ -70,6 +77,7 @@ class NotificationsContainer extends Component<Props> {
|
70
|
77
|
*/
|
71
|
78
|
componentDidMount() {
|
72
|
79
|
// Set the initial dismiss timeout (if any)
|
|
80
|
+ // @ts-ignore
|
73
|
81
|
this._manageDismissTimeout();
|
74
|
82
|
}
|
75
|
83
|
|
|
@@ -78,37 +86,36 @@ class NotificationsContainer extends Component<Props> {
|
78
|
86
|
*
|
79
|
87
|
* @inheritdoc
|
80
|
88
|
*/
|
81
|
|
- componentDidUpdate(prevProps: Props) {
|
|
89
|
+ componentDidUpdate(prevProps: IProps) {
|
82
|
90
|
this._manageDismissTimeout(prevProps);
|
83
|
91
|
}
|
84
|
92
|
|
85
|
93
|
/**
|
86
|
94
|
* Sets/clears the dismiss timeout for the top notification.
|
87
|
95
|
*
|
88
|
|
- * @param {P} [prevProps] - The previous properties (if called from
|
|
96
|
+ * @param {IProps} [prevProps] - The previous properties (if called from
|
89
|
97
|
* {@code componentDidUpdate}).
|
90
|
98
|
* @returns {void}
|
91
|
99
|
* @private
|
92
|
100
|
*/
|
93
|
|
- _manageDismissTimeout(prevProps: ?Props) {
|
|
101
|
+ _manageDismissTimeout(prevProps: IProps) {
|
94
|
102
|
const { _notifications } = this.props;
|
95
|
103
|
|
96
|
104
|
if (_notifications.length) {
|
97
|
105
|
const notification = _notifications[0];
|
98
|
|
- const previousNotification
|
99
|
|
- = prevProps && prevProps._notifications.length
|
100
|
|
- ? prevProps._notifications[0]
|
101
|
|
- : undefined;
|
|
106
|
+ const previousNotification = prevProps?._notifications.length
|
|
107
|
+ ? prevProps._notifications[0] : undefined;
|
102
|
108
|
|
103
|
109
|
if (notification !== previousNotification) {
|
104
|
110
|
this._clearNotificationDismissTimeout();
|
105
|
111
|
|
106
|
|
- if (notification && notification.timeout) {
|
107
|
|
- const {
|
108
|
|
- timeout,
|
109
|
|
- uid
|
110
|
|
- } = notification;
|
|
112
|
+ // @ts-ignore
|
|
113
|
+ if (notification?.timeout) {
|
111
|
114
|
|
|
115
|
+ // @ts-ignore
|
|
116
|
+ const { timeout, uid } = notification;
|
|
117
|
+
|
|
118
|
+ // @ts-ignore
|
112
|
119
|
this._notificationDismissTimeout = setTimeout(() => {
|
113
|
120
|
// Perform a no-op if a timeout is not specified.
|
114
|
121
|
this._onDismissed(uid);
|
|
@@ -142,21 +149,20 @@ class NotificationsContainer extends Component<Props> {
|
142
|
149
|
this._notificationDismissTimeout = null;
|
143
|
150
|
}
|
144
|
151
|
|
145
|
|
- _onDismissed: number => void;
|
146
|
|
-
|
147
|
152
|
/**
|
148
|
153
|
* Emits an action to remove the notification from the redux store so it
|
149
|
154
|
* stops displaying.
|
150
|
155
|
*
|
151
|
|
- * @param {number} uid - The id of the notification to be removed.
|
|
156
|
+ * @param {Object} uid - The id of the notification to be removed.
|
152
|
157
|
* @private
|
153
|
158
|
* @returns {void}
|
154
|
159
|
*/
|
155
|
|
- _onDismissed(uid) {
|
|
160
|
+ _onDismissed(uid: any) {
|
156
|
161
|
const { _notifications } = this.props;
|
157
|
162
|
|
158
|
163
|
// Clear the timeout only if it's the top notification that's being
|
159
|
164
|
// dismissed (the timeout is set only for the top one).
|
|
165
|
+ // @ts-ignore
|
160
|
166
|
if (!_notifications.length || _notifications[0].uid === uid) {
|
161
|
167
|
this._clearNotificationDismissTimeout();
|
162
|
168
|
}
|
|
@@ -171,20 +177,23 @@ class NotificationsContainer extends Component<Props> {
|
171
|
177
|
*/
|
172
|
178
|
render() {
|
173
|
179
|
const { _notifications, toolboxVisible } = this.props;
|
174
|
|
- const bottomEdge = Platform.OS === 'ios' && !toolboxVisible;
|
|
180
|
+ const notificationsContainerStyle
|
|
181
|
+ = toolboxVisible ? styles.withToolbox : styles.withoutToolbox;
|
175
|
182
|
|
176
|
183
|
return (
|
177
|
184
|
<SafeAreaView
|
178
|
|
- edges = { [ bottomEdge && 'bottom', 'left', 'right' ].filter(Boolean) }>
|
|
185
|
+ edges = { [ Platform.OS === 'ios' && 'bottom', 'left', 'right' ].filter(Boolean) as Edge[] }
|
|
186
|
+ style = { notificationsContainerStyle as any }>
|
179
|
187
|
<NotificationsTransition>
|
180
|
188
|
{
|
181
|
|
- _notifications.map((notification, index) => {
|
|
189
|
+ _notifications.map(notification => {
|
|
190
|
+ // @ts-ignore
|
182
|
191
|
const { props, uid } = notification;
|
183
|
192
|
|
184
|
193
|
return (
|
185
|
194
|
<Notification
|
186
|
195
|
{ ...props }
|
187
|
|
- key = { index }
|
|
196
|
+ key = { uid }
|
188
|
197
|
onDismissed = { this._onDismissed }
|
189
|
198
|
uid = { uid } />
|
190
|
199
|
);
|
|
@@ -194,8 +203,6 @@ class NotificationsContainer extends Component<Props> {
|
194
|
203
|
</SafeAreaView>
|
195
|
204
|
);
|
196
|
205
|
}
|
197
|
|
-
|
198
|
|
- _onDismissed: number => void;
|
199
|
206
|
}
|
200
|
207
|
|
201
|
208
|
/**
|
|
@@ -206,7 +213,7 @@ class NotificationsContainer extends Component<Props> {
|
206
|
213
|
* @private
|
207
|
214
|
* @returns {Props}
|
208
|
215
|
*/
|
209
|
|
-export function mapStateToProps(state: Object) {
|
|
216
|
+export function mapStateToProps(state: IReduxState) {
|
210
|
217
|
const { notifications } = state['features/notifications'];
|
211
|
218
|
const _visible = areThereNotifications(state);
|
212
|
219
|
|