@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,282 @@
1
+ /**
2
+ * Licensed under the Apache License, Version 2.0 (the "License");
3
+ * you may not use this file except in compliance with the License.
4
+ * You may obtain a copy of the License at
5
+ *
6
+ * http://www.apache.org/licenses/LICENSE-2.0
7
+ *
8
+ * Unless required by applicable law or agreed to in writing, software
9
+ * distributed under the License is distributed on an "AS IS" BASIS,
10
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ * See the License for the specific language governing permissions and
12
+ * limitations under the License.
13
+ */
14
+
15
+ import React from 'react';
16
+ import {
17
+ Animated,
18
+ Dimensions,
19
+ StyleSheet,
20
+ Text,
21
+ TouchableOpacity,
22
+ View
23
+ } from 'react-native';
24
+
25
+ import {connect} from 'react-redux';
26
+ import {withTheme} from "react-native-paper";
27
+
28
+ import merge from 'lodash/merge';
29
+ import NetInfo from '@react-native-community/netinfo';
30
+
31
+ import componentStyles from "./styles";
32
+ import PropTypes from "prop-types";
33
+ import {withTranslation} from "react-i18next";
34
+ import { handleHtmlEntities } from '../../libraries/core/helper/format.helper';
35
+
36
+
37
+
38
+ /**
39
+ * Top News Component
40
+ *
41
+ * Shows a single news item with the name and the logo of the university.
42
+ *
43
+ * Parameters:
44
+ * - animationRange: Animation Range for animation of the dashboard view
45
+ *
46
+ * Navigation-Parameters:
47
+ * - none
48
+ */
49
+ class TopNewsComponent extends React.Component {
50
+
51
+ static propTypes = {
52
+ animationRange: PropTypes.any
53
+ };
54
+
55
+ // Styles of this component
56
+ styles;
57
+
58
+ animateHeader = null;
59
+ animateBackground = null;
60
+ topNews = null;
61
+ hasConnection = true;
62
+ netInfoUnsubscribe = null;
63
+
64
+ constructor(props) {
65
+ super(props);
66
+
67
+ // ------------------------------------------------------------------------
68
+ // PLUGIN FUNCTIONALITY
69
+ // ------------------------------------------------------------------------
70
+
71
+ const { pluginStyles,theme } = this.props;
72
+ this.styles = componentStyles(theme);
73
+
74
+ if(pluginStyles) {
75
+ this.styles = merge(this.styles, pluginStyles);
76
+ }
77
+
78
+ this.styles = StyleSheet.create(this.styles);
79
+ // ------------------------------------------------------------------------
80
+
81
+ const height = Dimensions.get('window').height;
82
+
83
+ this.animateHeader = {
84
+ transform: [{
85
+ translateY: this.props.animationRange.interpolate({
86
+ inputRange: [0, 1],
87
+ outputRange: [0, height / 8],
88
+ })
89
+ }]
90
+ };
91
+
92
+ this.animateLogo = {
93
+ transform: [{
94
+ translateY: this.props.animationRange.interpolate({
95
+ inputRange: [0, 1],
96
+ outputRange: [30, (height / 50)],
97
+ })
98
+ },
99
+ {
100
+ scale: this.props.animationRange.interpolate({
101
+ inputRange: [0, 1],
102
+ outputRange: [1, .4],
103
+ })
104
+ }]
105
+ };
106
+
107
+ this.animateBackground = {
108
+ transform: [{
109
+ translateY: this.props.animationRange.interpolate({
110
+ inputRange: [0, 1],
111
+ outputRange: [0, height / 7],
112
+ extrapolate: 'clamp'
113
+ })
114
+ }]
115
+ };
116
+
117
+ this.netInfoUnsubscribe = NetInfo.addEventListener(state => {
118
+ this.hasConnection = state.isInternetReachable && state.isConnected;
119
+ });
120
+ }
121
+
122
+ componentWillUnmount() {
123
+ if(this.netInfoUnsubscribe) {
124
+ this.netInfoUnsubscribe();
125
+ }
126
+ }
127
+
128
+ render() {
129
+
130
+ // ------------------------------------------------------------------------
131
+ // PLUGIN FUNCTIONALITY
132
+ // ------------------------------------------------------------------------
133
+ const PluginComponent = this.props.pluginComponent;
134
+ if (PluginComponent) {
135
+ return <PluginComponent />;
136
+ }
137
+ // ------------------------------------------------------------------------
138
+
139
+
140
+ const {feeds, t} = this.props;
141
+ const {colors, appSettings} = this.props.theme;
142
+ let topNews = this.props.topNews;
143
+
144
+ if(!Array.isArray(topNews)) {
145
+ topNews = [];
146
+ }
147
+
148
+ let topItem = null;
149
+ let imageSrc = null;
150
+ let feedTitle = null;
151
+ if(topNews[0]) {
152
+ topItem = topNews[0];
153
+ if(topItem.imageUrl) {
154
+ imageSrc = {uri: topItem.imageUrl};
155
+ }
156
+ }
157
+
158
+ if(feeds && topItem && topItem.originFeedId) {
159
+ const feed = feeds.filter(feed => feed.feedid === topItem.originFeedId)[0];
160
+
161
+ if(feed && feed.title) {
162
+ feedTitle = feed.title.toUpperCase();
163
+ }
164
+ }
165
+
166
+ if(!imageSrc)
167
+ imageSrc = appSettings.header;
168
+
169
+
170
+ // Top News available
171
+ this.topNews = topItem;
172
+
173
+ // Notice about "." in accessibilityLabels: This will set a short break in the sound output, like in a normal sentence.
174
+
175
+ return (
176
+ <View style={{overflow:'hidden'}}>
177
+ <View stlyle={this.styles.backgroundImageWrapper}>
178
+ <TouchableOpacity
179
+ onPress={
180
+ topItem?.link ?? null
181
+ ? () => { this._handlePressNews(topItem) }
182
+ : null
183
+ }
184
+ >
185
+ <Animated.Image
186
+ source={imageSrc}
187
+ resizeMode="cover"
188
+ fadeDuration={0}
189
+ style={[this.styles.newsImage, this.animateBackground]}
190
+ accessible={true}
191
+ accessibilityLabel={
192
+ !topItem && !this.hasConnection
193
+ ? t('home:noConnectionTitle')
194
+ : (!topItem ? t('home:noItemTitle') : handleHtmlEntities(topItem.title))
195
+ }
196
+ accessibilityHint={!topItem ? '' : t('accessibility:topNewsHint')}
197
+ />
198
+ </TouchableOpacity>
199
+ </View>
200
+
201
+ {
202
+ (!topItem && !this.hasConnection) ? (
203
+ <Animated.View style={[this.styles.newsItem]}
204
+ accessible={true}
205
+ accessibilityLabel={t('home:noConnectionTitle')}>
206
+ <Text
207
+ style={this.styles.newsItemCategory}>{t('home:noConnectionSubtitle').toUpperCase()}</Text>
208
+ <Text style={this.styles.newsItemTitle}>{t('home:noConnectionTitle')}</Text>
209
+ <Text style={this.styles.newsItemText}>{t('home:noConnectionText')}</Text>
210
+ <View style={this.styles.newsItemActionbar}>
211
+ <Text style={this.styles.newsItemDate}></Text>
212
+ </View>
213
+ </Animated.View>
214
+ ) : ((!topItem) ? (
215
+ <Animated.View style={[this.styles.newsItem]}
216
+ accessible={true}
217
+ accessibilityLabel={t('home:noItemTitle')}>
218
+ <Text style={this.styles.newsItemCategory}>{t('home:noItemSubtitle').toUpperCase()}</Text>
219
+ <Text style={this.styles.newsItemTitle}>{t('home:noItemTitle')}</Text>
220
+ <Text style={this.styles.newsItemText}>{t('home:noItemText')}</Text>
221
+ <View style={this.styles.newsItemActionbar}>
222
+ <Text style={this.styles.newsItemDate}/>
223
+ </View>
224
+ </Animated.View>
225
+ ) : (topItem?.shortDesc
226
+ ? <TouchableOpacity
227
+ style={this.styles.newsItem}
228
+ onPress={() => {this._handlePressNews(topItem)}}
229
+ accessible={true}
230
+ accessibilityLabel={handleHtmlEntities(topItem.title)}
231
+ accessibilityHint={t('accessibility:topNewsHint')}>
232
+ <View>
233
+ {feedTitle && <Text style={this.styles.newsItemCategory}>{feedTitle}</Text>}
234
+ <Text style={this.styles.newsItemTitle}>{handleHtmlEntities(topItem.title)}</Text>
235
+ <Text style={this.styles.newsItemText}>{handleHtmlEntities(topItem.shortDesc)} ... <Text style={this.styles.newsItemReadMore}>{t('home:readMore')}</Text></Text>
236
+ <View style={this.styles.newsItemActionbar}>
237
+ {topItem?.author != null
238
+ ? <Text style={this.styles.newsItemAuthor}>{handleHtmlEntities(topItem.author)}</Text>
239
+ : null
240
+ }
241
+ </View>
242
+ </View>
243
+ </TouchableOpacity>
244
+ : null
245
+ ))
246
+ }
247
+ </View>
248
+ );
249
+ }
250
+
251
+
252
+ /**
253
+ * User has pressed the news item card.
254
+ * Shows the news details in a modal window.
255
+ *
256
+ * @param news
257
+ *
258
+ * @private
259
+ */
260
+ _handlePressNews = (news) => {
261
+ if (news) {
262
+ this.props.navigation.navigate(
263
+ 'TopNewsDetail',
264
+ {
265
+ news: {...news, 'feedId': 0},
266
+ newsType: "Default"
267
+ });
268
+ }
269
+ }
270
+ }
271
+
272
+
273
+ const mapStateToProps = state => {
274
+ return {
275
+ pluginComponent: state.pluginReducer.topNews.component,
276
+ pluginStyles: state.pluginReducer.topNews.styles,
277
+ topNews: state.apiReducer.topNews,
278
+ feeds: state.apiReducer.feeds
279
+ };
280
+ };
281
+
282
+ export default connect(mapStateToProps, null)(withTranslation()(withTheme(TopNewsComponent)))
@@ -0,0 +1,125 @@
1
+ import {Platform, Dimensions} from "react-native";
2
+
3
+ export default function(theme) {
4
+ const width = Dimensions.get('window').width;
5
+ const height = Dimensions.get('window').height;
6
+ const headerImageHeight = height / 2;
7
+ return {
8
+ appHeader: {
9
+ flex: 1,
10
+ flexDirection: 'row',
11
+ alignItems: 'baseline',
12
+ },
13
+ appHeaderSearchButton: {
14
+ position: 'absolute',
15
+ top: Platform.OS === 'ios' ? theme.paddings.default : theme.paddings.xlarge,
16
+ right: theme.paddings.default
17
+
18
+ },
19
+ appHeaderSearch: {},
20
+ appHeaderContainer: {
21
+ flex: 1,
22
+ justifyContent: 'center',
23
+ alignContent: 'center',
24
+ alignItems: 'center',
25
+ height: headerImageHeight,
26
+ },
27
+ universityTitle: {
28
+ marginTop: theme.paddings.large,
29
+ marginLeft: theme.paddings.default,
30
+ color: theme.colors.primaryText,
31
+ fontSize: theme.fontSizes.universityTitle,
32
+ ...theme.fonts.bold,
33
+ lineHeight: theme.lineHeights.xxl,
34
+ textAlign: 'left',
35
+ alignSelf: 'flex-start',
36
+ marginBottom: theme.paddings.small
37
+ },
38
+ newsImage: {
39
+ aspectRatio: 16/9,
40
+ width: width
41
+ },
42
+ backgroundImageWrapper: {
43
+ height: headerImageHeight,
44
+ width: width,
45
+ marginTop: 0,
46
+ backgroundColor: theme.colors.primary,
47
+ position:'relative',
48
+ overflow: 'hidden'
49
+ },
50
+ backgroundImage: {
51
+ position:'absolute',
52
+ top: -10,
53
+ left: 0,
54
+ right: 0,
55
+ bottom: 0
56
+ },
57
+ imageOverlay: {
58
+ height: headerImageHeight,
59
+ width: width,
60
+ flex: 1
61
+ },
62
+ newsItem: {
63
+ backgroundColor: theme.colors.background,
64
+ paddingHorizontal: theme.paddings.default,
65
+ paddingTop: theme.paddings.default
66
+ },
67
+ newsItemCategory: {
68
+ marginBottom: 5,
69
+ fontSize: theme.fontSizes.s
70
+ },
71
+ newsItemTitle: {
72
+ ...theme.fonts.bold,
73
+ fontSize: theme.fontSizes.xxl,
74
+ lineHeight: theme.lineHeights.titleBigger,
75
+ marginBottom: theme.paddings.small,
76
+ },
77
+ newsItemText: {
78
+ ...theme.fonts.regular,
79
+ fontSize: theme.fontSizes.m,
80
+ lineHeight: theme.lineHeights.s
81
+ },
82
+ newsItemReadMore: {
83
+ textDecorationLine: 'underline'
84
+ },
85
+ newsItemActionbar: {
86
+ borderBottomColor: theme.colors.accent,
87
+ borderBottomWidth: 1,
88
+ //borderStyle: 'dotted', // TODO Not available on iOS at the moment (also dashed)
89
+ borderStyle: 'solid',
90
+ paddingBottom: theme.paddings.small,
91
+ marginTop: theme.paddings.small,
92
+ flex: 1,
93
+ flexDirection: 'row'
94
+ },
95
+ newsItemDate: {
96
+ fontSize: theme.fontSizes.s,
97
+ ...theme.fonts.bold,
98
+ color: theme.colors.subtitle,
99
+ flex: 1,
100
+ alignItems: 'center',
101
+ alignSelf: 'center',
102
+ flexDirection: 'row',
103
+ },
104
+ newsItemAuthor: {
105
+ fontSize: theme.fontSizes.s,
106
+ ...theme.fonts.bold,
107
+ color: theme.colors.subtitle,
108
+ flex: 1,
109
+ alignItems: 'center',
110
+ alignSelf: 'center',
111
+ flexDirection: 'row',
112
+ },
113
+ newsItemActions: {
114
+ flex: 1,
115
+ alignItems: 'flex-end',
116
+ justifyContent: 'flex-end'
117
+ },
118
+ newsItemAction: {
119
+ marginRight: -4
120
+ },
121
+ modalContainer: {
122
+ flex: 1
123
+ },
124
+ }
125
+ };
@@ -0,0 +1,279 @@
1
+ /**
2
+ * Licensed under the Apache License, Version 2.0 (the "License");
3
+ * you may not use this file except in compliance with the License.
4
+ * You may obtain a copy of the License at
5
+ *
6
+ * http://www.apache.org/licenses/LICENSE-2.0
7
+ *
8
+ * Unless required by applicable law or agreed to in writing, software
9
+ * distributed under the License is distributed on an "AS IS" BASIS,
10
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ * See the License for the specific language governing permissions and
12
+ * limitations under the License.
13
+ */
14
+
15
+ import React from 'react';
16
+ import {
17
+ Animated,
18
+ Dimensions,
19
+ StyleSheet,
20
+ Text,
21
+ TouchableOpacity,
22
+ View
23
+ } from 'react-native';
24
+
25
+ import {connect} from 'react-redux';
26
+ import {withTheme} from "react-native-paper";
27
+
28
+ import merge from 'lodash/merge';
29
+ import NetInfo from '@react-native-community/netinfo';
30
+
31
+ import componentStyles from "./styles";
32
+ import PropTypes from "prop-types";
33
+ import {withTranslation} from "react-i18next";
34
+ import { handleHtmlEntities } from '../../libraries/core/helper/format.helper';
35
+
36
+
37
+
38
+ /**
39
+ * Top News Component
40
+ *
41
+ * Shows a single news item with the name and the logo of the university.
42
+ *
43
+ * Parameters:
44
+ * - animationRange: Animation Range for animation of the dashboard view
45
+ *
46
+ * Navigation-Parameters:
47
+ * - none
48
+ */
49
+ class TopNewsComponent extends React.Component {
50
+
51
+ static propTypes = {
52
+ animationRange: PropTypes.any
53
+ };
54
+
55
+ // Styles of this component
56
+ styles;
57
+
58
+ animateHeader = null;
59
+ animateBackground = null;
60
+ topNews = null;
61
+ hasConnection = true;
62
+ netInfoUnsubscribe = null;
63
+
64
+ constructor(props) {
65
+ super(props);
66
+
67
+ // ------------------------------------------------------------------------
68
+ // PLUGIN FUNCTIONALITY
69
+ // ------------------------------------------------------------------------
70
+
71
+ const { pluginStyles,theme } = this.props;
72
+ this.styles = componentStyles(theme);
73
+
74
+ if(pluginStyles) {
75
+ this.styles = merge(this.styles, pluginStyles);
76
+ }
77
+
78
+ this.styles = StyleSheet.create(this.styles);
79
+ // ------------------------------------------------------------------------
80
+
81
+ const height = Dimensions.get('window').height;
82
+
83
+ this.animateHeader = {
84
+ transform: [{
85
+ translateY: this.props.animationRange.interpolate({
86
+ inputRange: [0, 1],
87
+ outputRange: [0, height / 8],
88
+ })
89
+ }]
90
+ };
91
+
92
+ this.animateLogo = {
93
+ transform: [{
94
+ translateY: this.props.animationRange.interpolate({
95
+ inputRange: [0, 1],
96
+ outputRange: [30, (height / 50)],
97
+ })
98
+ },
99
+ {
100
+ scale: this.props.animationRange.interpolate({
101
+ inputRange: [0, 1],
102
+ outputRange: [1, .4],
103
+ })
104
+ }]
105
+ };
106
+
107
+ this.animateBackground = {
108
+ transform: [{
109
+ translateY: this.props.animationRange.interpolate({
110
+ inputRange: [0, 1],
111
+ outputRange: [0, height / 7],
112
+ extrapolate: 'clamp'
113
+ })
114
+ }]
115
+ };
116
+
117
+ this.netInfoUnsubscribe = NetInfo.addEventListener(state => {
118
+ this.hasConnection = state.isInternetReachable && state.isConnected;
119
+ });
120
+ }
121
+
122
+ componentWillUnmount() {
123
+ if(this.netInfoUnsubscribe) {
124
+ this.netInfoUnsubscribe();
125
+ }
126
+ }
127
+
128
+ render() {
129
+
130
+ // ------------------------------------------------------------------------
131
+ // PLUGIN FUNCTIONALITY
132
+ // ------------------------------------------------------------------------
133
+ const PluginComponent = this.props.pluginComponent;
134
+ if (PluginComponent) {
135
+ return <PluginComponent />;
136
+ }
137
+ // ------------------------------------------------------------------------
138
+
139
+
140
+ const {feeds, t} = this.props;
141
+ const {appSettings} = this.props.theme;
142
+ let topNews = this.props.topNews;
143
+
144
+ if(!Array.isArray(topNews)) {
145
+ topNews = [];
146
+ }
147
+
148
+ let topItem = null;
149
+ let imageSrc = null;
150
+ let feedTitle = null;
151
+ if(topNews[0]) {
152
+ topItem = topNews[0];
153
+ if(topItem.imageUrl) {
154
+ imageSrc = {uri: topItem.imageUrl};
155
+ }
156
+ }
157
+
158
+ if(feeds && topItem && topItem.originFeedId) {
159
+ const feed = feeds.filter(feed => feed.feedid === topItem.originFeedId)[0];
160
+
161
+ if(feed && feed.title) {
162
+ feedTitle = feed.title.toUpperCase();
163
+ }
164
+ }
165
+
166
+ if(!imageSrc)
167
+ imageSrc = appSettings.header;
168
+
169
+
170
+ // Top News available
171
+ this.topNews = topItem;
172
+
173
+ // Notice about "." in accessibilityLabels: This will set a short break in the sound output, like in a normal sentence.
174
+
175
+ return (
176
+ <View style={{overflow: 'hidden'}}>
177
+ <Animated.View
178
+ style={[this.styles.universityIconWrapper, this.animateBackground]}>
179
+ <Animated.Image
180
+ source={appSettings.logo}
181
+ resizeMode="contain"
182
+ fadeDuration={1000}
183
+ style={[this.styles.universityIcon]}/>
184
+ </Animated.View>
185
+ <TouchableOpacity
186
+ onPress={() => this._handlePressNews(topItem)}
187
+ >
188
+ <Animated.View stlyle={[this.styles.backgroundImageWrapper, this.animateBackground]}>
189
+ <Animated.Image
190
+ source={imageSrc}
191
+ resizeMode="cover"
192
+ fadeDuration={10}
193
+ style={[this.styles.newsImage]}
194
+ accessible={true}
195
+ accessibilityLabel={
196
+ !topItem && !this.hasConnection ?
197
+ t('home:noConnectionTitle')
198
+ : (!topItem ? t('home:noItemTitle') : handleHtmlEntities(topItem.title))}
199
+ accessibilityHint={!topItem ? '' : t('accessibility:topNewsHint')}
200
+ />
201
+ </Animated.View>
202
+
203
+ {
204
+ (!topItem && !this.hasConnection) ? (
205
+ <Animated.View style={[this.styles.newsItem]}
206
+ accessible={true}
207
+ accessibilityLabel={t('home:noConnectionTitle')}>
208
+ <Text style={this.styles.newsItemTitle}>{t('home:noConnectionTitle')}</Text>
209
+ <Text style={this.styles.newsItemText}>{t('home:noConnectionText')}</Text>
210
+ <View style={this.styles.newsItemActionbar}>
211
+ <Text style={this.styles.newsItemDate}/>
212
+ </View>
213
+ </Animated.View>
214
+ ) : ((!topItem) ? (
215
+ <Animated.View style={[this.styles.newsItem]}
216
+ accessible={true}
217
+ accessibilityLabel={t('home:noItemTitle')}>
218
+ <Text style={this.styles.newsItemTitle}>{t('home:noItemTitle')}</Text>
219
+ <Text style={this.styles.newsItemText}>{t('home:noItemText')}</Text>
220
+ <View style={this.styles.newsItemActionbar}>
221
+ <Text style={this.styles.newsItemDate}/>
222
+ </View>
223
+ </Animated.View>
224
+ ) : (
225
+ <View
226
+ style={this.styles.newsItem}
227
+ accessible={true}
228
+ accessibilityLabel={handleHtmlEntities(topItem.title)}
229
+ accessibilityHint={t('accessibility:topNewsHint')}
230
+ >
231
+ {feedTitle && <Text style={this.styles.newsItemCategory}>{feedTitle}</Text>}
232
+ <Text style={this.styles.newsItemTitle}>{handleHtmlEntities(topItem.title)}</Text>
233
+ {topItem.shortDesc &&
234
+ <Text style={this.styles.newsItemText}>{handleHtmlEntities(topItem.shortDesc)}</Text>
235
+ }
236
+ {topItem.author &&
237
+ <Text style={this.styles.newsItemAuthor}>{handleHtmlEntities(topItem.author)}</Text>
238
+ }
239
+ <View style={this.styles.newsItemActionbar} />
240
+ </View>
241
+ ))
242
+ }
243
+ </TouchableOpacity>
244
+ </View>
245
+ );
246
+ }
247
+
248
+
249
+ /**
250
+ * User has pressed the news item card.
251
+ * Shows the news details in a modal window.
252
+ *
253
+ * @param news
254
+ *
255
+ * @private
256
+ */
257
+ _handlePressNews = (news) => {
258
+ if (news) {
259
+ this.props.navigation.navigate(
260
+ 'TopNewsDetail',
261
+ {
262
+ news: {...news, 'feedId': 0},
263
+ newsType: "Default"
264
+ });
265
+ }
266
+ }
267
+ }
268
+
269
+
270
+ const mapStateToProps = state => {
271
+ return {
272
+ pluginComponent: state.pluginReducer.topNews.component,
273
+ pluginStyles: state.pluginReducer.topNews.styles,
274
+ topNews: state.apiReducer.topNews,
275
+ feeds: state.apiReducer.feeds
276
+ };
277
+ };
278
+
279
+ export default connect(mapStateToProps, null)(withTranslation()(withTheme(TopNewsComponent)))