@olea-bps/base 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (268) hide show
  1. package/components/AppBar/index.js +84 -0
  2. package/components/AppBar/styles.js +27 -0
  3. package/components/BookDetail/index.js +268 -0
  4. package/components/BookDetail/styles.js +124 -0
  5. package/components/ComponentJobsFilter/index.js +188 -0
  6. package/components/ComponentJobsFilter/styles.js +12 -0
  7. package/components/ConnectivityWarning/index.js +65 -0
  8. package/components/ConnectivityWarning/styles.js +19 -0
  9. package/components/ContactDetail/index.js +232 -0
  10. package/components/ContactDetail/styles.js +32 -0
  11. package/components/CourseDetail/index.js +357 -0
  12. package/components/CourseDetail/styles.js +59 -0
  13. package/components/CourseDetailDialog/index.js +169 -0
  14. package/components/CourseDetailDialog/styles.js +116 -0
  15. package/components/CourseInfo/index.js +219 -0
  16. package/components/CourseInfo/styles.js +40 -0
  17. package/components/DevelopmentDialog/index.js +214 -0
  18. package/components/DevelopmentDialog/styles.js +10 -0
  19. package/components/EventCodeInput/index.js +149 -0
  20. package/components/EventCodeInput/styles.js +108 -0
  21. package/components/FlexMenuEntry/index.js +84 -0
  22. package/components/FlexMenuEntry/styles.js +27 -0
  23. package/components/MainMenuEntry/index.js +88 -0
  24. package/components/MainMenuEntry/styles.js +28 -0
  25. package/components/MealItem/index.js +87 -0
  26. package/components/MealItem/styles.js +84 -0
  27. package/components/MensaMenu/index.js +305 -0
  28. package/components/MensaMenu/styles.js +94 -0
  29. package/components/MensaSlider/index.js +188 -0
  30. package/components/MensaSlider/styles.js +53 -0
  31. package/components/Modal/index.js +106 -0
  32. package/components/Modal/styles.js +8 -0
  33. package/components/NewsDetail/index.js +377 -0
  34. package/components/NewsDetail/styles.js +77 -0
  35. package/components/NewsList/index.js +120 -0
  36. package/components/NewsList/styles.js +19 -0
  37. package/components/NewsListItem/index.js +89 -0
  38. package/components/NewsListItem/styles.js +32 -0
  39. package/components/OtherCourses/index.js +152 -0
  40. package/components/OtherCourses/styles.js +10 -0
  41. package/components/PtsDeparture/index.js +140 -0
  42. package/components/PtsDeparture/styles.js +7 -0
  43. package/components/PtsStation/index.js +186 -0
  44. package/components/PtsStation/styles.js +47 -0
  45. package/components/QuickLinks/index.js +127 -0
  46. package/components/QuickLinks/styles.js +45 -0
  47. package/components/RoomDetail/index.js +281 -0
  48. package/components/RoomDetail/styles.js +56 -0
  49. package/components/ScaledImage/index.js +92 -0
  50. package/components/SearchResults/index.js +362 -0
  51. package/components/SearchResults/styles.js +59 -0
  52. package/components/SettingSection/index.js +54 -0
  53. package/components/SettingSection/styles.js +15 -0
  54. package/components/SettingsDialog/index.js +52 -0
  55. package/components/SettingsDialog/styles.js +12 -0
  56. package/components/SettingsDialogRadio/index.js +66 -0
  57. package/components/SettingsDialogRadio/styles.js +7 -0
  58. package/components/SettingsDialogSelect/index.js +73 -0
  59. package/components/SettingsDialogSelect/styles.js +7 -0
  60. package/components/TimetableCodeInput/index.js +205 -0
  61. package/components/TimetableCodeInput/styles.js +28 -0
  62. package/components/TimetableDay/index.js +252 -0
  63. package/components/TimetableDay/styles.js +103 -0
  64. package/components/TimetableEvent/index.js +163 -0
  65. package/components/TimetableEvent/styles.js +108 -0
  66. package/components/TimetableList/index.js +180 -0
  67. package/components/TimetableList/styles.js +106 -0
  68. package/components/TimetableMonth/index.js +156 -0
  69. package/components/TimetableMonth/styles.js +29 -0
  70. package/components/TimetableWeek/index.js +230 -0
  71. package/components/TimetableWeek/styles.js +58 -0
  72. package/components/TopNews/index.js +282 -0
  73. package/components/TopNews/styles.js +125 -0
  74. package/components/TopNewsHtwk/index.js +279 -0
  75. package/components/TopNewsHtwk/styles.js +142 -0
  76. package/components/WebView/index.js +108 -0
  77. package/components/WebView/styles.js +11 -0
  78. package/context/context-callmanager/TucCallManager.js +74 -0
  79. package/context/context-callmanager/index.js +128 -0
  80. package/context/context-canteen/AsistServerApiProvider.js +126 -0
  81. package/context/context-canteen/CollektorVersion2ApiProvider.js +100 -0
  82. package/context/context-canteen/index.js +692 -0
  83. package/context/context-connectivity/index.js +85 -0
  84. package/context/context-event/AsistServerClient.js +82 -0
  85. package/context/context-event/index.js +205 -0
  86. package/context/context-flex-menu/AsistServerApiProvider.js +0 -0
  87. package/context/context-flex-menu/CollectorVersion2ApiProvider.js +32 -0
  88. package/context/context-flex-menu/index.js +160 -0
  89. package/context/context-info-dialog/CollektorVersion2ApiProvider.js +53 -0
  90. package/context/context-info-dialog/ProviderErrors.js +22 -0
  91. package/context/context-info-dialog/index.js +190 -0
  92. package/context/context-mails/MailService.js +147 -0
  93. package/context/context-mails/TucUnseenApiProvider.js +65 -0
  94. package/context/context-mails/index.js +131 -0
  95. package/context/context-news/CollektorVersion2ApiProvider.js +68 -0
  96. package/context/context-news/index.js +155 -0
  97. package/context/context-public-transport-ticket/CollektorVersion2ApiProvider.js +45 -0
  98. package/context/context-public-transport-ticket/ProviderErrors.js +11 -0
  99. package/context/context-public-transport-ticket/index.js +175 -0
  100. package/context/context-timetable/CollectorVersion2ApiProvider.js +102 -0
  101. package/context/context-timetable/ProviderErrors.js +22 -0
  102. package/context/context-timetable/TimetableService.js +357 -0
  103. package/context/context-timetable/index.js +215 -0
  104. package/context/context-user/index.js +586 -0
  105. package/index.js +178 -0
  106. package/libraries/base-api-provider/hooks.js +24 -0
  107. package/libraries/base-api-provider/http-api-provider.js +168 -0
  108. package/libraries/base-api-provider/index.js +20 -0
  109. package/libraries/core/api/canteens.js +88 -0
  110. package/libraries/core/api/corona.js +45 -0
  111. package/libraries/core/api/courses.js +54 -0
  112. package/libraries/core/api/device.js +98 -0
  113. package/libraries/core/api/feed.js +144 -0
  114. package/libraries/core/api/feedback.js +123 -0
  115. package/libraries/core/api/jobs.js +48 -0
  116. package/libraries/core/api/library.js +67 -0
  117. package/libraries/core/api/lostfound.js +77 -0
  118. package/libraries/core/api/occupancy.js +44 -0
  119. package/libraries/core/api/officehours.js +25 -0
  120. package/libraries/core/api/poi.js +25 -0
  121. package/libraries/core/api/pts.js +68 -0
  122. package/libraries/core/api/rooms.js +31 -0
  123. package/libraries/core/api/survey.js +121 -0
  124. package/libraries/core/api/telephone.js +32 -0
  125. package/libraries/core/api/tucrooms.js +31 -0
  126. package/libraries/core/constants/actions.js +75 -0
  127. package/libraries/core/constants/api.js +146 -0
  128. package/libraries/core/constants/enums.js +5 -0
  129. package/libraries/core/helper/date.js +9 -0
  130. package/libraries/core/helper/format.helper.js +2 -0
  131. package/libraries/core/index.js +60 -0
  132. package/libraries/core/redux/actions/notifications.js +6 -0
  133. package/libraries/core/redux/actions/setting.js +75 -0
  134. package/libraries/core/redux/actions/state.js +74 -0
  135. package/libraries/core/redux/asyncDispatch.js +27 -0
  136. package/libraries/core/redux/reducers/api.js +190 -0
  137. package/libraries/core/redux/reducers/index.js +32 -0
  138. package/libraries/core/redux/reducers/notifications.js +16 -0
  139. package/libraries/core/redux/reducers/setting.js +99 -0
  140. package/libraries/core/redux/reducers/state.js +122 -0
  141. package/libraries/core/redux/selectors.js +123 -0
  142. package/libraries/core/redux/store.js +40 -0
  143. package/libraries/core/services/data.js +96 -0
  144. package/libraries/core/services/root-navigation.js +36 -0
  145. package/libraries/core/services/search.js +175 -0
  146. package/libraries/core-plugins/enums/replaceTypes.js +53 -0
  147. package/libraries/core-plugins/index.js +21 -0
  148. package/libraries/core-plugins/redux/actions/plugin.js +13 -0
  149. package/libraries/core-plugins/redux/reducers/plugin.js +210 -0
  150. package/libraries/icons-openasist/index.js +143 -0
  151. package/libraries/notifications/index.js +268 -0
  152. package/libraries/notifications/services/subscriber.service.js +123 -0
  153. package/libraries/react-native-webview-autoheight/README.md +47 -0
  154. package/libraries/react-native-webview-autoheight/index.js +140 -0
  155. package/libraries/react-native-webview-autoheight/package.json +37 -0
  156. package/libraries/react-native-webview-autoheight/utils.js +268 -0
  157. package/libraries/redux-offline/.eslintignore +1 -0
  158. package/libraries/redux-offline/.github/ISSUE_TEMPLATE/redux-offline-core-issues-template.md +25 -0
  159. package/libraries/redux-offline/.prettierrc +6 -0
  160. package/libraries/redux-offline/LICENSE +21 -0
  161. package/libraries/redux-offline/README.md +133 -0
  162. package/libraries/redux-offline/flow-typed/npm/redux-logger_vx.x.x.js +109 -0
  163. package/libraries/redux-offline/flow-typed/npm/redux_v4.x.x.js +100 -0
  164. package/libraries/redux-offline/lib/actions.js +46 -0
  165. package/libraries/redux-offline/lib/config.js +15 -0
  166. package/libraries/redux-offline/lib/constants.js +17 -0
  167. package/libraries/redux-offline/lib/defaults/defaultCommit.js +11 -0
  168. package/libraries/redux-offline/lib/defaults/defaultRollback.js +11 -0
  169. package/libraries/redux-offline/lib/defaults/detectNetwork.js +33 -0
  170. package/libraries/redux-offline/lib/defaults/detectNetwork.native.js +211 -0
  171. package/libraries/redux-offline/lib/defaults/discard.js +18 -0
  172. package/libraries/redux-offline/lib/defaults/effect.js +87 -0
  173. package/libraries/redux-offline/lib/defaults/index.js +32 -0
  174. package/libraries/redux-offline/lib/defaults/offlineStateLens.js +24 -0
  175. package/libraries/redux-offline/lib/defaults/persist.js +9 -0
  176. package/libraries/redux-offline/lib/defaults/persist.native.js +17 -0
  177. package/libraries/redux-offline/lib/defaults/persistAutoRehydrate.js +8 -0
  178. package/libraries/redux-offline/lib/defaults/queue.js +27 -0
  179. package/libraries/redux-offline/lib/defaults/retry.js +29 -0
  180. package/libraries/redux-offline/lib/index.js +115 -0
  181. package/libraries/redux-offline/lib/middleware.js +56 -0
  182. package/libraries/redux-offline/lib/offlineActionTracker.js +43 -0
  183. package/libraries/redux-offline/lib/send.js +112 -0
  184. package/libraries/redux-offline/lib/types.js +3 -0
  185. package/libraries/redux-offline/lib/updater.js +111 -0
  186. package/libraries/redux-offline/package.json +69 -0
  187. package/libraries/redux-offline/src/__tests__/defaults/discard.js +22 -0
  188. package/libraries/redux-offline/src/__tests__/defaults/effect.js +118 -0
  189. package/libraries/redux-offline/src/__tests__/index.js +116 -0
  190. package/libraries/redux-offline/src/__tests__/middleware.js +185 -0
  191. package/libraries/redux-offline/src/__tests__/offlineActionTracker.js +54 -0
  192. package/libraries/redux-offline/src/__tests__/send.js +208 -0
  193. package/libraries/redux-offline/src/actions.js +36 -0
  194. package/libraries/redux-offline/src/config.js +9 -0
  195. package/libraries/redux-offline/src/constants.js +18 -0
  196. package/libraries/redux-offline/src/defaults/defaultCommit.js +7 -0
  197. package/libraries/redux-offline/src/defaults/defaultRollback.js +7 -0
  198. package/libraries/redux-offline/src/defaults/detectNetwork.js +16 -0
  199. package/libraries/redux-offline/src/defaults/detectNetwork.native.js +148 -0
  200. package/libraries/redux-offline/src/defaults/discard.js +19 -0
  201. package/libraries/redux-offline/src/defaults/effect.js +86 -0
  202. package/libraries/redux-offline/src/defaults/index.js +25 -0
  203. package/libraries/redux-offline/src/defaults/offlineStateLens.js +11 -0
  204. package/libraries/redux-offline/src/defaults/persist.js +4 -0
  205. package/libraries/redux-offline/src/defaults/persist.native.js +9 -0
  206. package/libraries/redux-offline/src/defaults/persistAutoRehydrate.js +4 -0
  207. package/libraries/redux-offline/src/defaults/queue.js +20 -0
  208. package/libraries/redux-offline/src/defaults/retry.js +18 -0
  209. package/libraries/redux-offline/src/index.js +138 -0
  210. package/libraries/redux-offline/src/middleware.js +52 -0
  211. package/libraries/redux-offline/src/offlineActionTracker.js +40 -0
  212. package/libraries/redux-offline/src/send.js +111 -0
  213. package/libraries/redux-offline/src/types.js +127 -0
  214. package/libraries/redux-offline/src/updater.js +141 -0
  215. package/libraries/redux-offline/typings.d.ts +150 -0
  216. package/libraries/redux-offline/yarn.lock +6460 -0
  217. package/libraries/stored-state/index.js +155 -0
  218. package/package.json +68 -0
  219. package/views/Callmanager/index.js +148 -0
  220. package/views/Callmanager/styles.js +62 -0
  221. package/views/Canteens/index.js +383 -0
  222. package/views/Canteens/styles.js +89 -0
  223. package/views/Dashboard/index.js +176 -0
  224. package/views/Dashboard/styles.js +16 -0
  225. package/views/DashboardHtwk/index.js +197 -0
  226. package/views/DashboardHtwk/styles.js +24 -0
  227. package/views/Event/index.js +373 -0
  228. package/views/Event/styles.js +63 -0
  229. package/views/FeedList/index.js +165 -0
  230. package/views/FeedList/styles.js +15 -0
  231. package/views/FeedNews/index.js +243 -0
  232. package/views/FeedNews/styles.js +32 -0
  233. package/views/Flexmenu/index.js +185 -0
  234. package/views/Flexmenu/styles.js +62 -0
  235. package/views/FlexmenuWebview/index.js +167 -0
  236. package/views/FlexmenuWebview/styles.js +16 -0
  237. package/views/Howhy/index.js +151 -0
  238. package/views/Howhy/styles.js +11 -0
  239. package/views/Jobs/index.js +217 -0
  240. package/views/Jobs/styles.js +41 -0
  241. package/views/MainMenu/index.js +283 -0
  242. package/views/MainMenu/styles.js +36 -0
  243. package/views/NewsTabbar/index.js +164 -0
  244. package/views/NewsTabbar/styles.js +27 -0
  245. package/views/Opal/index.js +136 -0
  246. package/views/Opal/styles.js +11 -0
  247. package/views/PublicTransportTicket/index.js +173 -0
  248. package/views/PublicTransportTicket/styles.js +17 -0
  249. package/views/Search/index.js +186 -0
  250. package/views/Search/styles.js +67 -0
  251. package/views/SettingsAccessibility/index.js +148 -0
  252. package/views/SettingsAccessibility/styles.js +13 -0
  253. package/views/SettingsAppInfo/index.js +86 -0
  254. package/views/SettingsAppInfo/styles.js +18 -0
  255. package/views/SettingsCanteens/index.js +249 -0
  256. package/views/SettingsCanteens/styles.js +33 -0
  257. package/views/SettingsGeneral/index.js +173 -0
  258. package/views/SettingsGeneral/styles.js +28 -0
  259. package/views/SettingsNotifications/index.js +204 -0
  260. package/views/SettingsNotifications/styles.js +38 -0
  261. package/views/SettingsUser/index.js +170 -0
  262. package/views/SettingsUser/styles.js +17 -0
  263. package/views/TimetableCalendar/index.js +387 -0
  264. package/views/TimetableCalendar/styles.js +121 -0
  265. package/views/TimetableList/index.js +402 -0
  266. package/views/TimetableList/styles.js +55 -0
  267. package/views/Webviews/index.js +158 -0
  268. package/views/Webviews/styles.js +11 -0
@@ -0,0 +1,36 @@
1
+ import {
2
+ OFFLINE_STATUS_CHANGED,
3
+ OFFLINE_SCHEDULE_RETRY,
4
+ OFFLINE_COMPLETE_RETRY,
5
+ OFFLINE_BUSY
6
+ } from './constants';
7
+
8
+ export const networkStatusChanged = params => {
9
+ let payload;
10
+ if (typeof params === 'object') {
11
+ payload = params;
12
+ } else {
13
+ payload = { online: params };
14
+ }
15
+ return {
16
+ type: OFFLINE_STATUS_CHANGED,
17
+ payload
18
+ };
19
+ };
20
+
21
+ export const scheduleRetry = (delay = 0) => ({
22
+ type: OFFLINE_SCHEDULE_RETRY,
23
+ payload: {
24
+ delay
25
+ }
26
+ });
27
+
28
+ export const completeRetry = action => ({
29
+ type: OFFLINE_COMPLETE_RETRY,
30
+ payload: action
31
+ });
32
+
33
+ export const busy = isBusy => ({
34
+ type: OFFLINE_BUSY,
35
+ payload: { busy: isBusy }
36
+ });
@@ -0,0 +1,9 @@
1
+ // @flow
2
+ /* global $Shape */
3
+ import type { Config } from './types';
4
+ import defaults from './defaults';
5
+
6
+ export const applyDefaults = (config: $Shape<Config> = {}): Config => ({
7
+ ...defaults,
8
+ ...config
9
+ });
@@ -0,0 +1,18 @@
1
+ // @flow
2
+ // Literal ACTION typing allows to ensure a stricter type than string
3
+
4
+ export const OFFLINE_STATUS_CHANGED: 'Offline/STATUS_CHANGED' =
5
+ 'Offline/STATUS_CHANGED';
6
+ export const OFFLINE_SCHEDULE_RETRY: 'Offline/SCHEDULE_RETRY' =
7
+ 'Offline/SCHEDULE_RETRY';
8
+ export const OFFLINE_COMPLETE_RETRY: 'Offline/COMPLETE_RETRY' =
9
+ 'Offline/COMPLETE_RETRY';
10
+ export const OFFLINE_SEND: 'Offline/SEND' = 'Offline/SEND';
11
+ export const OFFLINE_BUSY: 'Offline/BUSY' = 'Offline/BUSY';
12
+ export const RESET_STATE: 'Offline/RESET_STATE' = 'Offline/RESET_STATE';
13
+ export const PERSIST_REHYDRATE: 'persist/REHYDRATE' = 'persist/REHYDRATE';
14
+ export const JS_ERROR: 'Offline/JS_ERROR' = 'Offline/JS_ERROR';
15
+ export const DEFAULT_COMMIT: 'Offline/DEFAULT_COMMIT' =
16
+ 'Offline/DEFAULT_COMMIT';
17
+ export const DEFAULT_ROLLBACK: 'Offline/DEFAULT_ROLLBACK' =
18
+ 'Offline/DEFAULT_ROLLBACK';
@@ -0,0 +1,7 @@
1
+ import { DEFAULT_COMMIT } from '../constants';
2
+
3
+ const defaultCommit = {
4
+ type: DEFAULT_COMMIT
5
+ };
6
+
7
+ export default defaultCommit;
@@ -0,0 +1,7 @@
1
+ import { DEFAULT_ROLLBACK } from '../constants';
2
+
3
+ const defaultRollback = {
4
+ type: DEFAULT_ROLLBACK
5
+ };
6
+
7
+ export default defaultRollback;
@@ -0,0 +1,16 @@
1
+ const handle = (callback, online) => {
2
+ // NetInfo is not supported in browsers, hence we only pass online status
3
+ if (window.requestAnimationFrame) {
4
+ window.requestAnimationFrame(() => callback({ online }));
5
+ } else {
6
+ setTimeout(() => callback({ online }), 0);
7
+ }
8
+ };
9
+
10
+ export default callback => {
11
+ if (typeof window !== 'undefined' && window.addEventListener) {
12
+ window.addEventListener('online', () => handle(callback, true));
13
+ window.addEventListener('offline', () => handle(callback, false));
14
+ handle(callback, window.navigator.onLine);
15
+ }
16
+ };
@@ -0,0 +1,148 @@
1
+ /* eslint no-underscore-dangle: 0 */
2
+ import { AppState } from 'react-native'; // eslint-disable-line
3
+ import NetInfo from '@react-native-community/netinfo'; // eslint-disable-line
4
+
5
+ class DetectNetwork {
6
+ constructor(callback) {
7
+ this._reach = null;
8
+ this._isConnected = null;
9
+ this._isConnectionExpensive = null;
10
+ this._callback = callback;
11
+ this._shouldInitUpdateReach = true;
12
+
13
+ this._init();
14
+ this._addListeners();
15
+ }
16
+
17
+ /**
18
+ * Check props for changes
19
+ * @param {string} reach - connection reachability.
20
+ * - Cross-platform: [none, wifi, cellular, unknown]
21
+ * - Android: [bluetooth, ethernet, wimax]
22
+ * @returns {boolean} - Whether the connection reachability or the connection props have changed
23
+ * @private
24
+ */
25
+ _hasChanged = reach => {
26
+ if (this._reach !== reach) {
27
+ return true;
28
+ }
29
+ if (this._isConnected !== this._getConnection(reach)) {
30
+ return true;
31
+ }
32
+ return false;
33
+ };
34
+
35
+ /**
36
+ * Sets the connection reachability prop
37
+ * @param {string} reach - connection reachability.
38
+ * - Cross-platform: [none, wifi, cellular, unknown]
39
+ * - Android: [bluetooth, ethernet, wimax]
40
+ * @returns {void}
41
+ * @private
42
+ */
43
+ _setReach = reach => {
44
+ this._reach = reach;
45
+ this._isConnected = this._getConnection(reach);
46
+ };
47
+
48
+ /**
49
+ * Gets the isConnected prop depending on the connection reachability's value
50
+ * @param {string} reach - connection reachability.
51
+ * - Cross-platform: [none, wifi, cellular, unknown]
52
+ * - Android: [bluetooth, ethernet, wimax]
53
+ * @returns {void}
54
+ * @private
55
+ */
56
+ _getConnection = reach => reach !== 'none' && reach !== 'unknown';
57
+
58
+ /**
59
+ * Sets the isConnectionExpensive prop
60
+ * @returns {Promise.<void>} Resolves to true if connection is expensive,
61
+ * false if not, and null if not supported.
62
+ * @private
63
+ */
64
+ _setIsConnectionExpensive = async () => {
65
+ try {
66
+ const { details } = await NetInfo.fetch();
67
+ this._isConnectionExpensive = details.isConnectionExpensive;
68
+ } catch (err) {
69
+ // err means that isConnectionExpensive is not supported in iOS
70
+ this._isConnectionExpensive = null;
71
+ }
72
+ };
73
+
74
+ /**
75
+ * Sets the shouldInitUpdateReach flag
76
+ * @param {boolean} shouldUpdate - Whether the init method should update the reach prop
77
+ * @returns {void}
78
+ * @private
79
+ */
80
+ _setShouldInitUpdateReach = shouldUpdate => {
81
+ this._shouldInitUpdateReach = shouldUpdate;
82
+ };
83
+
84
+ /**
85
+ * Fetches and sets the connection reachability and the isConnected props,
86
+ * if neither of the AppState and NetInfo event listeners have been called
87
+ * @returns {Promise.<void>} Resolves when the props have been
88
+ * initialized and update.
89
+ * @private
90
+ */
91
+ _init = async () => {
92
+ const connectionInfo = await NetInfo.fetch();
93
+ if (this._shouldInitUpdateReach) {
94
+ this._update(connectionInfo.type);
95
+ }
96
+ };
97
+
98
+ /**
99
+ * Check changes on props and store and dispatch if neccesary
100
+ * @param {string} reach - connection reachability.
101
+ * - Cross-platform: [none, wifi, cellular, unknown]
102
+ * - Android: [bluetooth, ethernet, wimax]
103
+ * @returns {void}
104
+ * @private
105
+ */
106
+ _update = reach => {
107
+ if (this._hasChanged(reach)) {
108
+ this._setReach(reach);
109
+ this._dispatch();
110
+ }
111
+ };
112
+
113
+ /**
114
+ * Adds listeners for when connection reachability and app state changes to update props
115
+ * @returns {void}
116
+ * @private
117
+ */
118
+ _addListeners() {
119
+ NetInfo.addEventListener(connectionInfo => {
120
+ this._setShouldInitUpdateReach(false);
121
+ this._update(connectionInfo.type);
122
+ });
123
+ AppState.addEventListener('change', async () => {
124
+ this._setShouldInitUpdateReach(false);
125
+ const connectionInfo = await NetInfo.fetch();
126
+ this._update(connectionInfo.type);
127
+ });
128
+ }
129
+
130
+ /**
131
+ * Executes the given callback to update redux's store with the new internal props
132
+ * @returns {Promise.<void>} Resolves after fetching the isConnectionExpensive
133
+ * and dispatches actions
134
+ * @private
135
+ */
136
+ _dispatch = async () => {
137
+ await this._setIsConnectionExpensive();
138
+ this._callback({
139
+ online: this._isConnected,
140
+ netInfo: {
141
+ isConnectionExpensive: this._isConnectionExpensive,
142
+ reach: this._reach
143
+ }
144
+ });
145
+ };
146
+ }
147
+
148
+ export default callback => new DetectNetwork(callback);
@@ -0,0 +1,19 @@
1
+ // @flow
2
+
3
+ import type { OfflineAction } from '../types';
4
+ import { NetworkError } from './effect';
5
+
6
+ export default (
7
+ error: typeof NetworkError,
8
+ action: OfflineAction,
9
+ _retries: number = 0 // eslint-disable-line no-unused-vars
10
+ ): boolean => {
11
+ // not a network error -> discard
12
+ if (!('status' in error)) {
13
+ return true;
14
+ }
15
+
16
+ // discard http 4xx errors
17
+ // $FlowFixMe
18
+ return error.status >= 400 && error.status < 500;
19
+ };
@@ -0,0 +1,86 @@
1
+ // @flow
2
+
3
+ import type { OfflineAction } from '../types';
4
+
5
+ export function NetworkError(response: {} | string, status: number) {
6
+ this.name = 'NetworkError';
7
+ this.status = status;
8
+ this.response = response;
9
+ }
10
+
11
+ // $FlowFixMe
12
+ NetworkError.prototype = Error.prototype;
13
+
14
+ const tryParseJSON = (json: string): ?{} => {
15
+ if (!json) {
16
+ return null;
17
+ }
18
+ try {
19
+ return JSON.parse(json);
20
+ } catch (e) {
21
+ throw new Error(`Failed to parse unexpected JSON response: ${json}`);
22
+ }
23
+ };
24
+
25
+ const getResponseBody = (res: any): Promise<{} | string> => {
26
+ const contentType = res.headers.get('content-type') || false;
27
+ if (contentType && contentType.indexOf('json') >= 0) {
28
+ return res.text().then(tryParseJSON);
29
+ }
30
+ return res.text();
31
+ };
32
+
33
+ export const getHeaders = (headers: {
34
+ [string]: string
35
+ }): { [string]: string } => {
36
+ const {
37
+ 'Content-Type': contentTypeCapitalized,
38
+ 'content-type': contentTypeLowerCase,
39
+ ...restOfHeaders
40
+ } = headers || {};
41
+ const contentType =
42
+ contentTypeCapitalized || contentTypeLowerCase || 'application/json';
43
+ return { ...restOfHeaders, 'content-type': contentType };
44
+ };
45
+
46
+ export const getFormData = (object: {}) => {
47
+ const formData = new FormData();
48
+ Object.keys(object).forEach(key => {
49
+ Object.keys(object[key]).forEach(innerObj => {
50
+ const newObj = object[key][innerObj];
51
+ formData.append(newObj[0], newObj[1]);
52
+ });
53
+ });
54
+
55
+ return formData;
56
+ };
57
+
58
+ // eslint-disable-next-line no-unused-vars
59
+ export default (effect: any, _action: OfflineAction): Promise<any> => {
60
+ const { url, json, ...options } = effect;
61
+ const headers = getHeaders(options.headers);
62
+
63
+ if (
64
+ !(options.body instanceof FormData) &&
65
+ Object.prototype.hasOwnProperty.call(headers, 'content-type') &&
66
+ headers['content-type'].toLowerCase().includes('multipart/form-data')
67
+ ) {
68
+ options.body = getFormData(options.body);
69
+ }
70
+
71
+ if (json !== null && json !== undefined) {
72
+ try {
73
+ options.body = JSON.stringify(json);
74
+ } catch (e) {
75
+ return Promise.reject(e);
76
+ }
77
+ }
78
+ return fetch(url, { ...options, headers }).then(res => {
79
+ if (res.ok) {
80
+ return getResponseBody(res);
81
+ }
82
+ return getResponseBody(res).then(body => {
83
+ throw new NetworkError(body || '', res.status);
84
+ });
85
+ });
86
+ };
@@ -0,0 +1,25 @@
1
+ import persist from './persist';
2
+ import detectNetwork from './detectNetwork';
3
+ import effect from './effect';
4
+ import retry from './retry';
5
+ import discard from './discard';
6
+ import defaultCommit from './defaultCommit';
7
+ import defaultRollback from './defaultRollback';
8
+ import persistAutoRehydrate from './persistAutoRehydrate';
9
+ import offlineStateLens from './offlineStateLens';
10
+ import queue from './queue';
11
+
12
+ export default {
13
+ rehydrate: true, // backward compatibility, TODO remove in the next breaking change version
14
+ persist,
15
+ detectNetwork,
16
+ effect,
17
+ retry,
18
+ discard,
19
+ defaultCommit,
20
+ defaultRollback,
21
+ persistAutoRehydrate,
22
+ offlineStateLens,
23
+ queue,
24
+ returnPromises: false
25
+ };
@@ -0,0 +1,11 @@
1
+ // @flow
2
+ export default (state: any) => {
3
+ const { offline, ...rest } = state;
4
+ return {
5
+ get: offline,
6
+ set: (offlineState: any) =>
7
+ typeof offlineState === 'undefined'
8
+ ? rest
9
+ : { offline: offlineState, ...rest }
10
+ };
11
+ };
@@ -0,0 +1,4 @@
1
+ // flow
2
+ import { persistStore } from 'redux-persist';
3
+
4
+ export default persistStore;
@@ -0,0 +1,9 @@
1
+ // @flow
2
+ // $FlowIgnore
3
+ import { persistStore } from 'redux-persist';
4
+ // $FlowIgnore
5
+ import AsyncStorage from '@react-native-async-storage/async-storage';
6
+
7
+ export default (store: any, options: {}, callback: any) =>
8
+ // $FlowFixMe
9
+ persistStore(store, callback);
@@ -0,0 +1,4 @@
1
+ // @flow
2
+ import { autoRehydrate } from 'redux-persist';
3
+
4
+ export default autoRehydrate;
@@ -0,0 +1,20 @@
1
+ /* eslint-disable no-unused-vars */
2
+
3
+ function enqueue(array, item, context) {
4
+ return [...array, item];
5
+ }
6
+
7
+ function dequeue(array, item, context) {
8
+ const [, ...rest] = array;
9
+ return rest;
10
+ }
11
+
12
+ function peek(array, item, context) {
13
+ return array[0];
14
+ }
15
+
16
+ export default {
17
+ enqueue,
18
+ dequeue,
19
+ peek
20
+ };
@@ -0,0 +1,18 @@
1
+ // @flow
2
+ import type { OfflineAction } from '../types';
3
+
4
+ const decaySchedule = [
5
+ 1000, // After 1 seconds
6
+ 1000 * 5, // After 5 seconds
7
+ 1000 * 15, // After 15 seconds
8
+ 1000 * 30, // After 30 seconds
9
+ 1000 * 60, // After 1 minute
10
+ 1000 * 60 * 3, // After 3 minutes
11
+ 1000 * 60 * 5, // After 5 minutes
12
+ 1000 * 60 * 10, // After 10 minutes
13
+ 1000 * 60 * 30, // After 30 minutes
14
+ 1000 * 60 * 60 // After 1 hour
15
+ ];
16
+
17
+ export default (action: OfflineAction, retries: number): ?number =>
18
+ decaySchedule[retries] || null;
@@ -0,0 +1,138 @@
1
+ // @flow
2
+ /* global $Shape */
3
+ import { applyMiddleware, compose } from 'redux';
4
+ import type { Config } from './types';
5
+ import { createOfflineMiddleware } from './middleware';
6
+ import { enhanceReducer } from './updater';
7
+ import { applyDefaults } from './config';
8
+ import { networkStatusChanged } from './actions';
9
+ import offlineActionTracker from './offlineActionTracker';
10
+
11
+ // @TODO: Take createStore as config?
12
+ const warnIfNotReduxAction = (config: $Shape<Config>, key: string) => {
13
+ const maybeAction = config[key];
14
+
15
+ const isNotReduxAction =
16
+ maybeAction === null ||
17
+ typeof maybeAction !== 'object' ||
18
+ typeof maybeAction.type !== 'string' ||
19
+ maybeAction.type === '';
20
+
21
+ if (isNotReduxAction && console.warn) {
22
+ const msg =
23
+ `${key} must be a proper redux action, ` +
24
+ `i.e. it must be an object and have a non-empty string type. ` +
25
+ `Instead you provided: ${JSON.stringify(maybeAction, null, 2)}`;
26
+ console.warn(msg);
27
+ }
28
+ };
29
+
30
+ export const offline = (userConfig: $Shape<Config> = {}) => (
31
+ createStore: any
32
+ ) => (reducer: any, preloadedState: any, enhancer: any = x => x) => {
33
+ const config = applyDefaults(userConfig);
34
+
35
+ warnIfNotReduxAction(config, 'defaultCommit');
36
+ warnIfNotReduxAction(config, 'defaultRollback');
37
+
38
+ // toggle experimental returned promises
39
+ config.offlineActionTracker = config.returnPromises
40
+ ? offlineActionTracker.withPromises
41
+ : offlineActionTracker.withoutPromises;
42
+ delete config.returnPromises;
43
+
44
+ // wraps userland reducer with a top-level
45
+ // reducer that handles offline state updating
46
+ const offlineReducer = enhanceReducer(reducer, config);
47
+
48
+ // $FlowFixMe
49
+ const offlineMiddleware = applyMiddleware(createOfflineMiddleware(config));
50
+
51
+ // create autoRehydrate enhancer if required
52
+ const offlineEnhancer =
53
+ config.persist && config.rehydrate && config.persistAutoRehydrate
54
+ ? compose(offlineMiddleware, config.persistAutoRehydrate())
55
+ : offlineMiddleware;
56
+
57
+ // create store
58
+ const store = offlineEnhancer(createStore)(
59
+ offlineReducer,
60
+ preloadedState,
61
+ enhancer
62
+ );
63
+
64
+ const baseReplaceReducer = store.replaceReducer.bind(store);
65
+ // $FlowFixMe
66
+ store.replaceReducer = function replaceReducer(nextReducer) {
67
+ return baseReplaceReducer(enhanceReducer(nextReducer, config));
68
+ };
69
+
70
+ // launch store persistor
71
+ if (config.persist) {
72
+ config.persist(store, config.persistOptions, config.persistCallback);
73
+ }
74
+
75
+ // launch network detector
76
+ if (config.detectNetwork) {
77
+ config.detectNetwork(online => {
78
+ store.dispatch(networkStatusChanged(online));
79
+ });
80
+ }
81
+
82
+ return store;
83
+ };
84
+
85
+ export const createOffline = (userConfig: $Shape<Config> = {}) => {
86
+ const config = applyDefaults(userConfig);
87
+
88
+ // toggle experimental returned promises
89
+ config.offlineActionTracker = config.returnPromises
90
+ ? offlineActionTracker.withPromises
91
+ : offlineActionTracker.withoutPromises;
92
+ delete config.returnPromises;
93
+
94
+ warnIfNotReduxAction(config, 'defaultCommit');
95
+ warnIfNotReduxAction(config, 'defaultRollback');
96
+
97
+ const enhanceStore = (next: any) => (
98
+ reducer: any,
99
+ preloadedState: any,
100
+ enhancer: any
101
+ ) => {
102
+ // create autoRehydrate enhancer if required
103
+ const createStore =
104
+ config.persist && config.rehydrate && config.persistAutoRehydrate
105
+ ? config.persistAutoRehydrate()(next)
106
+ : next;
107
+
108
+ // create store
109
+ const store = createStore(reducer, preloadedState, enhancer);
110
+
111
+ const baseReplaceReducer = store.replaceReducer.bind(store);
112
+ store.replaceReducer = function replaceReducer(nextReducer) {
113
+ return baseReplaceReducer(enhanceReducer(nextReducer, config));
114
+ };
115
+
116
+ // launch store persistor
117
+ if (config.persist) {
118
+ config.persist(store, config.persistOptions, config.persistCallback);
119
+ }
120
+
121
+ // launch network detector
122
+ if (config.detectNetwork) {
123
+ config.detectNetwork(online => {
124
+ store.dispatch(networkStatusChanged(online));
125
+ });
126
+ }
127
+
128
+ return store;
129
+ };
130
+
131
+ return {
132
+ middleware: createOfflineMiddleware(config),
133
+ enhanceReducer(reducer: any) {
134
+ return enhanceReducer(reducer, config);
135
+ },
136
+ enhanceStore
137
+ };
138
+ };
@@ -0,0 +1,52 @@
1
+ // @flow
2
+
3
+ import type { AppState, Config } from './types';
4
+ import { OFFLINE_SEND, OFFLINE_SCHEDULE_RETRY } from './constants';
5
+ import { completeRetry } from './actions';
6
+ import send from './send';
7
+
8
+ const after = (timeout = 0) =>
9
+ new Promise(resolve => setTimeout(resolve, timeout));
10
+
11
+ export const createOfflineMiddleware = (config: Config) => (store: any) => (
12
+ next: any
13
+ ) => (action: any) => {
14
+ // allow other middleware to do their things
15
+ const result = next(action);
16
+ let promise;
17
+
18
+ // find any actions to send, if any
19
+ const state: AppState = store.getState();
20
+ const offline = config.offlineStateLens(state).get;
21
+ const context = { offline };
22
+ const offlineAction = config.queue.peek(offline.outbox, action, context);
23
+
24
+ // create promise to return on enqueue offline action
25
+ if (action.meta && action.meta.offline) {
26
+ const { registerAction } = config.offlineActionTracker;
27
+ promise = registerAction(offline.lastTransaction);
28
+ }
29
+
30
+ // if there are any actions in the queue that we are not
31
+ // yet processing, send those actions
32
+ if (
33
+ offlineAction &&
34
+ !offline.busy &&
35
+ !offline.retryScheduled &&
36
+ offline.online
37
+ ) {
38
+ send(offlineAction, store.dispatch, config, offline.retryCount);
39
+ }
40
+
41
+ if (action.type === OFFLINE_SCHEDULE_RETRY) {
42
+ after(action.payload.delay).then(() => {
43
+ store.dispatch(completeRetry(offlineAction));
44
+ });
45
+ }
46
+
47
+ if (action.type === OFFLINE_SEND && offlineAction && !offline.busy) {
48
+ send(offlineAction, store.dispatch, config, offline.retryCount);
49
+ }
50
+
51
+ return promise || result;
52
+ };
@@ -0,0 +1,40 @@
1
+ const subscriptions = {};
2
+
3
+ function registerAction(transaction) {
4
+ return new Promise((resolve, reject) => {
5
+ subscriptions[transaction] = { resolve, reject };
6
+ });
7
+ }
8
+
9
+ function resolveAction(transaction, value) {
10
+ const subscription = subscriptions[transaction];
11
+ if (subscription) {
12
+ subscription.resolve(value);
13
+ delete subscriptions[transaction];
14
+ }
15
+ }
16
+
17
+ function rejectAction(transaction, error) {
18
+ const subscription = subscriptions[transaction];
19
+ if (subscription) {
20
+ subscription.reject(error);
21
+ delete subscriptions[transaction];
22
+ }
23
+ }
24
+
25
+ const withPromises = {
26
+ registerAction,
27
+ resolveAction,
28
+ rejectAction
29
+ };
30
+
31
+ const withoutPromises = {
32
+ registerAction() {},
33
+ resolveAction() {},
34
+ rejectAction() {}
35
+ };
36
+
37
+ export default {
38
+ withPromises,
39
+ withoutPromises
40
+ };