Bladeren bron

[RN] Change default WelcomeScreen tab and persist user choice

master
Bettenbuk Zoltan 7 jaren geleden
bovenliggende
commit
dcfebf746f

+ 35
- 20
react/features/base/react/components/native/AbstractPagedList.js Bestand weergeven

23
      */
23
      */
24
     dispatch: Function,
24
     dispatch: Function,
25
 
25
 
26
+    /**
27
+     * Callback to execute on page change.
28
+     */
29
+    onSelectPage: ?Function,
30
+
26
     /**
31
     /**
27
      * The pages of the PagedList component to be rendered.
32
      * The pages of the PagedList component to be rendered.
28
      * Note: page.component may be undefined and then they don't need to be
33
      * Note: page.component may be undefined and then they don't need to be
61
     }
66
     }
62
 
67
 
63
     /**
68
     /**
64
-     * Implements React {@code Component}'s componentWillReceiveProps.
69
+     * Implements React's {@code Component} componentDidMount.
65
      *
70
      *
66
      * @inheritdoc
71
      * @inheritdoc
67
      */
72
      */
68
-    componentWillReceiveProps(newProps: Props) {
69
-        const { defaultPage } = newProps;
70
-
71
-        if (defaultPage !== this.props.defaultPage) {
72
-            // Default page changed due to a redux update. This is likely to
73
-            // happen after APP_WILL_MOUNT. So we update the active tab.
74
-            this._platformSpecificPageSelect(defaultPage);
75
-        }
73
+    componentDidMount() {
74
+        this._maybeRefreshActivePage();
76
     }
75
     }
77
 
76
 
78
     /**
77
     /**
119
         this._selectPage(pageIndex);
118
         this._selectPage(pageIndex);
120
     }
119
     }
121
 
120
 
121
+    _maybeRefreshActivePage: () => void
122
+
123
+    /**
124
+     * Components that this PagedList displays may have a refresh function to
125
+     * refresh its content when displayed (or based on custom logic). This
126
+     * function invokes this logic if it's present.
127
+     *
128
+     * @private
129
+     * @returns {void}
130
+     */
131
+    _maybeRefreshActivePage() {
132
+        const selectedPage = this.props.pages[this.state.pageIndex];
133
+
134
+        if (selectedPage && selectedPage.component) {
135
+            const { refresh } = selectedPage.component;
136
+
137
+            typeof refresh === 'function' && refresh(this.props.dispatch);
138
+        }
139
+    }
140
+
122
     _renderPagedList: boolean => React$Node;
141
     _renderPagedList: boolean => React$Node;
123
 
142
 
124
     _selectPage: number => void;
143
     _selectPage: number => void;
133
     _selectPage(pageIndex: number) {
152
     _selectPage(pageIndex: number) {
134
         const validatedPageIndex = this._validatePageIndex(pageIndex);
153
         const validatedPageIndex = this._validatePageIndex(pageIndex);
135
 
154
 
136
-        this.setState({
137
-            pageIndex: validatedPageIndex
138
-        });
139
-
140
-        // The page's Component may have a refresh(dispatch) function which we
141
-        // invoke when the page is selected.
142
-        const selectedPage = this.props.pages[validatedPageIndex];
155
+        const { onSelectPage } = this.props;
143
 
156
 
144
-        if (selectedPage && selectedPage.component) {
145
-            const { refresh } = selectedPage.component;
146
-
147
-            typeof refresh === 'function' && refresh(this.props.dispatch);
157
+        if (typeof onSelectPage === 'function') {
158
+            onSelectPage(validatedPageIndex);
148
         }
159
         }
160
+
161
+        this.setState({
162
+            pageIndex: validatedPageIndex
163
+        }, () => this._maybeRefreshActivePage());
149
     }
164
     }
150
 
165
 
151
     _validatePageIndex: number => number
166
     _validatePageIndex: number => number

+ 24
- 21
react/features/calendar-sync/components/MeetingList.native.js Bestand weergeven

96
      * @inheritdoc
96
      * @inheritdoc
97
      */
97
      */
98
     render() {
98
     render() {
99
-        const { disabled } = this.props;
99
+        const { _authorization, disabled } = this.props;
100
 
100
 
101
         return (
101
         return (
102
             <NavigateSectionList
102
             <NavigateSectionList
103
                 disabled = { disabled }
103
                 disabled = { disabled }
104
                 onPress = { this._onPress }
104
                 onPress = { this._onPress }
105
                 onRefresh = { this._onRefresh }
105
                 onRefresh = { this._onRefresh }
106
-                renderListEmptyComponent = { this._getRenderListEmptyComponent }
106
+
107
+                // If we don't provide a list specific renderListEmptyComponent,
108
+                // then the default empty component of the NavigateSectionList
109
+                // will be rendered, which (atm) is a simple "Pull to refresh"
110
+                // message.
111
+                renderListEmptyComponent
112
+                    = { _authorization === 'denied'
113
+                        ? this._getRenderListEmptyComponent() : undefined }
107
                 sections = { this._toDisplayableList() } />
114
                 sections = { this._toDisplayableList() } />
108
         );
115
         );
109
     }
116
     }
115
      * of the default one in the {@link NavigateSectionList}.
122
      * of the default one in the {@link NavigateSectionList}.
116
      *
123
      *
117
      * @private
124
      * @private
118
-     * @returns {Component}
125
+     * @returns {Function}
119
      */
126
      */
120
     _getRenderListEmptyComponent() {
127
     _getRenderListEmptyComponent() {
121
-        const { _authorization, t } = this.props;
128
+        const { t } = this.props;
122
 
129
 
123
-        if (_authorization === 'denied') {
124
-            return (
125
-                <View style = { styles.noPermissionMessageView }>
126
-                    <Text style = { styles.noPermissionMessageText }>
127
-                        { t('calendarSync.permissionMessage') }
130
+        return (
131
+            <View style = { styles.noPermissionMessageView }>
132
+                <Text style = { styles.noPermissionMessageText }>
133
+                    { t('calendarSync.permissionMessage') }
134
+                </Text>
135
+                <TouchableOpacity
136
+                    onPress = { openSettings }
137
+                    style = { styles.noPermissionMessageButton } >
138
+                    <Text style = { styles.noPermissionMessageButtonText }>
139
+                        { t('calendarSync.permissionButton') }
128
                     </Text>
140
                     </Text>
129
-                    <TouchableOpacity
130
-                        onPress = { openSettings }
131
-                        style = { styles.noPermissionMessageButton } >
132
-                        <Text style = { styles.noPermissionMessageButtonText }>
133
-                            { t('calendarSync.permissionButton') }
134
-                        </Text>
135
-                    </TouchableOpacity>
136
-                </View>
137
-            );
138
-        }
139
-
140
-        return null;
141
+                </TouchableOpacity>
142
+            </View>
143
+        );
141
     }
144
     }
142
 
145
 
143
     _onPress: string => Function;
146
     _onPress: string => Function;

+ 1
- 1
react/features/calendar-sync/reducer.js Bestand weergeven

45
         case SET_CALENDAR_AUTHORIZATION:
45
         case SET_CALENDAR_AUTHORIZATION:
46
             return {
46
             return {
47
                 ...state,
47
                 ...state,
48
-                authorization: action.status
48
+                authorization: action.authorization
49
             };
49
             };
50
 
50
 
51
         case SET_CALENDAR_EVENTS:
51
         case SET_CALENDAR_EVENTS:

+ 14
- 0
react/features/welcome/actionTypes.js Bestand weergeven

1
+// @flow
2
+
1
 /**
3
 /**
2
  * The type of the (redux) action which sets the visibility of
4
  * The type of the (redux) action which sets the visibility of
3
  * {@link WelcomePageSideBar}.
5
  * {@link WelcomePageSideBar}.
8
  * }
10
  * }
9
  */
11
  */
10
 export const SET_SIDEBAR_VISIBLE = Symbol('SET_SIDEBAR_VISIBLE');
12
 export const SET_SIDEBAR_VISIBLE = Symbol('SET_SIDEBAR_VISIBLE');
13
+
14
+/**
15
+ * Action to update the default page index of the {@code WelcomePageLists}
16
+ * component.
17
+ *
18
+ * {
19
+ *     type: SET_WELCOME_PAGE_LIST_DEFAULT_PAGE,
20
+ *     pageIndex: number
21
+ * }
22
+ */
23
+export const SET_WELCOME_PAGE_LIST_DEFAULT_PAGE
24
+    = Symbol('SET_WELCOME_PAGE_LIST_DEFAULT_PAGE');

+ 21
- 1
react/features/welcome/actions.js Bestand weergeven

1
 // @flow
1
 // @flow
2
 
2
 
3
-import { SET_SIDEBAR_VISIBLE } from './actionTypes';
3
+import {
4
+    SET_SIDEBAR_VISIBLE,
5
+    SET_WELCOME_PAGE_LIST_DEFAULT_PAGE
6
+} from './actionTypes';
7
+
8
+/**
9
+ * Action to update the default page index of the {@code WelcomePageLists}
10
+ * component.
11
+ *
12
+ * @param {number} pageIndex - The index of the selected page.
13
+ * @returns {{
14
+ *     type: SET_WELCOME_PAGE_LIST_DEFAULT_PAGE,
15
+ *     pageIndex: number
16
+ * }}
17
+ */
18
+export function setWelcomePageListDefaultPage(pageIndex: number) {
19
+    return {
20
+        type: SET_WELCOME_PAGE_LIST_DEFAULT_PAGE,
21
+        pageIndex
22
+    };
23
+}
4
 
24
 
5
 /**
25
 /**
6
  * Sets the visibility of {@link WelcomePageSideBar}.
26
  * Sets the visibility of {@link WelcomePageSideBar}.

+ 40
- 7
react/features/welcome/components/WelcomePageLists.js Bestand weergeven

9
 import { MeetingList } from '../../calendar-sync';
9
 import { MeetingList } from '../../calendar-sync';
10
 import { RecentList } from '../../recent-list';
10
 import { RecentList } from '../../recent-list';
11
 
11
 
12
+import { setWelcomePageListDefaultPage } from '../actions';
13
+
12
 type Props = {
14
 type Props = {
13
 
15
 
14
     /**
16
     /**
15
-     * True if the calendar feature has fetched entries, false otherwise
17
+     * The stored default page index.
16
      */
18
      */
17
-    _hasCalendarEntries: boolean,
19
+    _defaultPage: number,
18
 
20
 
19
     /**
21
     /**
20
      * Renders the lists disabled.
22
      * Renders the lists disabled.
21
      */
23
      */
22
     disabled: boolean,
24
     disabled: boolean,
23
 
25
 
26
+    /**
27
+     * The Redux dispatch function.
28
+     */
29
+    dispatch: Function,
30
+
24
     /**
31
     /**
25
      * The i18n translate function.
32
      * The i18n translate function.
26
      */
33
      */
72
             icon: isAndroid ? 'event_note' : IOS_CALENDAR_ICON,
79
             icon: isAndroid ? 'event_note' : IOS_CALENDAR_ICON,
73
             title: t('welcomepage.calendar')
80
             title: t('welcomepage.calendar')
74
         } ];
81
         } ];
82
+
83
+        this._onSelectPage = this._onSelectPage.bind(this);
75
     }
84
     }
76
 
85
 
77
     /**
86
     /**
80
      * @inheritdoc
89
      * @inheritdoc
81
      */
90
      */
82
     render() {
91
     render() {
83
-        const { disabled, _hasCalendarEntries } = this.props;
92
+        const { disabled, _defaultPage } = this.props;
93
+
94
+        if (typeof _defaultPage === 'undefined') {
95
+            return null;
96
+        }
84
 
97
 
85
         return (
98
         return (
86
             <PagedList
99
             <PagedList
87
-                defaultPage = { _hasCalendarEntries ? 1 : 0 }
100
+                defaultPage = { _defaultPage }
88
                 disabled = { disabled }
101
                 disabled = { disabled }
102
+                onSelectPage = { this._onSelectPage }
89
                 pages = { this.pages } />
103
                 pages = { this.pages } />
90
         );
104
         );
91
     }
105
     }
106
+
107
+    _onSelectPage: number => void
108
+
109
+    /**
110
+     * Callback for the {@code PagedList} page select action.
111
+     *
112
+     * @private
113
+     * @param {number} pageIndex - The index of the selected page.
114
+     * @returns {void}
115
+     */
116
+    _onSelectPage(pageIndex) {
117
+        const { dispatch } = this.props;
118
+
119
+        dispatch(setWelcomePageListDefaultPage(pageIndex));
120
+    }
92
 }
121
 }
93
 
122
 
94
 /**
123
 /**
98
  * @param {Object} state - The redux state.
127
  * @param {Object} state - The redux state.
99
  * @protected
128
  * @protected
100
  * @returns {{
129
  * @returns {{
101
- *     _hasCalendarEntries: boolean
130
+ *     _hasRecentListEntries: boolean
102
  * }}
131
  * }}
103
  */
132
  */
104
 function _mapStateToProps(state: Object) {
133
 function _mapStateToProps(state: Object) {
105
-    const { events } = state['features/calendar-sync'];
134
+    const { defaultPage } = state['features/welcome'];
135
+    const recentList = state['features/recent-list'];
136
+    const _hasRecentListEntries = Boolean(recentList && recentList.length);
106
 
137
 
107
     return {
138
     return {
108
-        _hasCalendarEntries: Boolean(events && events.length)
139
+        _defaultPage: defaultPage === 'undefined'
140
+            ? _hasRecentListEntries ? 0 : 1
141
+            : defaultPage
109
     };
142
     };
110
 }
143
 }
111
 
144
 

+ 24
- 2
react/features/welcome/reducer.js Bestand weergeven

1
 // @flow
1
 // @flow
2
 
2
 
3
 import { ReducerRegistry } from '../base/redux';
3
 import { ReducerRegistry } from '../base/redux';
4
-import { SET_SIDEBAR_VISIBLE } from './actionTypes';
4
+import { PersistenceRegistry } from '../base/storage';
5
+import {
6
+    SET_SIDEBAR_VISIBLE,
7
+    SET_WELCOME_PAGE_LIST_DEFAULT_PAGE
8
+} from './actionTypes';
9
+
10
+/**
11
+ * The Redux store name this feature uses.
12
+ */
13
+const STORE_NAME = 'features/welcome';
14
+
15
+/**
16
+ * Sets up the persistence of the feature {@code features/welcome}.
17
+ */
18
+PersistenceRegistry.register(STORE_NAME, {
19
+    defaultPage: true
20
+});
5
 
21
 
6
 /**
22
 /**
7
  * Reduces redux actions for the purposes of {@code features/welcome}.
23
  * Reduces redux actions for the purposes of {@code features/welcome}.
8
  */
24
  */
9
-ReducerRegistry.register('features/welcome', (state = {}, action) => {
25
+ReducerRegistry.register(STORE_NAME, (state = {}, action) => {
10
     switch (action.type) {
26
     switch (action.type) {
11
     case SET_SIDEBAR_VISIBLE:
27
     case SET_SIDEBAR_VISIBLE:
12
         return {
28
         return {
14
             sideBarVisible: action.visible
30
             sideBarVisible: action.visible
15
         };
31
         };
16
 
32
 
33
+    case SET_WELCOME_PAGE_LIST_DEFAULT_PAGE:
34
+        return {
35
+            ...state,
36
+            defaultPage: action.pageIndex
37
+        };
38
+
17
     default:
39
     default:
18
         return state;
40
         return state;
19
     }
41
     }

Laden…
Annuleren
Opslaan