@olea-bps/views 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 (52) hide show
  1. package/Callmanager/index.js +148 -0
  2. package/Callmanager/styles.js +62 -0
  3. package/Canteens/index.js +383 -0
  4. package/Canteens/styles.js +89 -0
  5. package/Dashboard/index.js +176 -0
  6. package/Dashboard/styles.js +16 -0
  7. package/DashboardHtwk/index.js +197 -0
  8. package/DashboardHtwk/styles.js +24 -0
  9. package/Event/index.js +369 -0
  10. package/Event/styles.js +63 -0
  11. package/FeedList/index.js +165 -0
  12. package/FeedList/styles.js +15 -0
  13. package/FeedNews/index.js +243 -0
  14. package/FeedNews/styles.js +32 -0
  15. package/Flexmenu/index.js +185 -0
  16. package/Flexmenu/styles.js +62 -0
  17. package/FlexmenuWebview/index.js +167 -0
  18. package/FlexmenuWebview/styles.js +16 -0
  19. package/Howhy/index.js +151 -0
  20. package/Howhy/styles.js +11 -0
  21. package/Jobs/index.js +217 -0
  22. package/Jobs/styles.js +41 -0
  23. package/MainMenu/index.js +329 -0
  24. package/MainMenu/styles.js +36 -0
  25. package/NewsTabbar/index.js +164 -0
  26. package/NewsTabbar/styles.js +27 -0
  27. package/Opal/index.js +136 -0
  28. package/Opal/styles.js +11 -0
  29. package/PublicTransportTicket/index.js +173 -0
  30. package/PublicTransportTicket/styles.js +17 -0
  31. package/Search/index.js +186 -0
  32. package/Search/styles.js +67 -0
  33. package/SettingsAccessibility/index.js +148 -0
  34. package/SettingsAccessibility/styles.js +13 -0
  35. package/SettingsAppInfo/index.js +86 -0
  36. package/SettingsAppInfo/styles.js +18 -0
  37. package/SettingsCanteens/index.js +249 -0
  38. package/SettingsCanteens/styles.js +33 -0
  39. package/SettingsGeneral/index.js +173 -0
  40. package/SettingsGeneral/styles.js +28 -0
  41. package/SettingsNotifications/index.js +204 -0
  42. package/SettingsNotifications/styles.js +38 -0
  43. package/SettingsUser/index.js +170 -0
  44. package/SettingsUser/styles.js +17 -0
  45. package/TimetableCalendar/index.js +322 -0
  46. package/TimetableCalendar/styles.js +117 -0
  47. package/TimetableList/index.js +397 -0
  48. package/TimetableList/styles.js +55 -0
  49. package/Webviews/index.js +158 -0
  50. package/Webviews/styles.js +11 -0
  51. package/index.js +25 -0
  52. package/package.json +41 -0
package/Event/index.js ADDED
@@ -0,0 +1,369 @@
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 { useState, useMemo, useEffect, useCallback } from 'react';
16
+ import {
17
+ ActivityIndicator,
18
+ Dimensions,
19
+ SafeAreaView,
20
+ ScrollView,
21
+ StyleSheet,
22
+ Text,
23
+ View,
24
+ } from 'react-native';
25
+
26
+ import { useTranslation } from 'react-i18next';
27
+ import { Appbar, useTheme } from 'react-native-paper';
28
+ import { AccordionList } from 'accordion-collapse-react-native';
29
+ import { TabView, TabBar, SceneMap } from 'react-native-tab-view';
30
+ import { useNavigation } from '@react-navigation/native';
31
+
32
+ import moment from 'moment';
33
+ import { DateTime } from 'luxon';
34
+
35
+ import EventContextProvider, { usePersonalEvents, usePersonalEventsCode, useEvents } from '@olea-bps/context-event';
36
+ import { AppBar as AppbarComponent } from '@olea-bps/components';
37
+ import IconsOpenasist from '@olea-bps/icons-openasist';
38
+ import { EventCodeInput as EventCodeInputComponent } from '@olea-bps/components';
39
+ import { TimetableEvent as TimetableEventComponent } from '@olea-bps/components'
40
+
41
+ import componentStyles from './styles';
42
+
43
+ /**
44
+ * @param {*} allEvents List of events
45
+ * @param {*} start Startingpoint of the timeslot-list/start of the event-day
46
+ * @param {*} end Endpoint of the timeslot-list/end of the event-day
47
+ * @param {*} length length of the single timeslots
48
+ * @returns a list of objects for each timeslot including start(startTs), end(endTs) and a list(events) of events for that timeslot
49
+ * startTs and endTs are moment().js-elements/modified date-time-elements while events will contain the event-objects for this timeslot
50
+ */
51
+ function generateTimeslots(allEvents, start, end, length) {
52
+
53
+ const timeslotList = [];
54
+ /*
55
+ For-Loop that loops from the start to the end in increments provided by length
56
+ So that there are timeslots from the start to the end of the event day
57
+ */
58
+ for (let timeSlot = moment(start); timeSlot.isSameOrBefore(end); timeSlot.add(length, 'hours')) {
59
+ // Define start and end(start + length) for each timeslot
60
+ var timeslotStart = moment(timeSlot);
61
+ var timeslotEnd = moment(timeSlot).add(length, 'hours');
62
+
63
+ /*
64
+ Use the build in filter()-Method to find all events in the given timeslot, so between timeslotStart and timeslotEnd
65
+ The timeslotStart and timeslotEnd are defined in the yyyy-MM-ddTHH:mm:ssZ-format in order to be able to compare them directly to the
66
+ start and end-prop in the event-Objects
67
+ A event will be sorted in the current timeslot, if the value of the start prop is between the start and end of the current timeslot
68
+ This is due to also include events that start in one timeslot and end in another timeslot
69
+ */
70
+ var eventsInTimeslot = allEvents.filter(
71
+ currentEvent =>
72
+ moment(currentEvent.begin).isSameOrAfter(timeslotStart)
73
+ &&
74
+ moment(currentEvent.begin).isBefore(timeslotEnd)
75
+ );
76
+
77
+ // If there are any Event-objects in the given timeslot, the event have to be sorted in the correct order
78
+ if (eventsInTimeslot.length > 0) {
79
+ // After that, push the current timeslot-object into the timeslotList
80
+ timeslotList.push({ startTs: timeslotStart.format('HH:mm'), endTs: timeslotEnd.format('HH:mm'), eventsTs: eventsInTimeslot })
81
+ }
82
+ }
83
+
84
+ return timeslotList;
85
+ }
86
+
87
+ /**
88
+ * Event View
89
+ *
90
+ * Parameters:
91
+ * - none
92
+ *
93
+ * Navigation-Parameters:
94
+ * - none
95
+ */
96
+
97
+ /**
98
+ * Die Funktion erzeugt einen Header für die jeweilige Liste, der eine Kurzbezeichnung und ein Icon zur Identifikation beinhaltet
99
+ *
100
+ * @param {object} props beinhaltet styles, themes und weitere props
101
+ * @param {boolean} props.isExpanded Flag das signalisiert, ob die aktuelle Liste geöffnet ist oder nicht
102
+ * @param {string} props.startTime Startzeit der Liste
103
+ * @param {string} props.endTime Endzeit der Liste
104
+ */
105
+ function TimeslotAccordionHeader({ startTime, endTime, theme: { colors, themeStyles }, styles, isExpanded, t }) {
106
+ return (
107
+ <View style={styles.header}>
108
+ <View style={[themeStyles.cardLeftIcon, { marginStart: 5 }]}>
109
+ <IconsOpenasist icon={('info')} size={25} color={colors.icon} />
110
+ </View>
111
+ <Text style={styles.headerText}>{`${startTime} ${t('event:type.to')} ${endTime} ${t('event:type.oclock')}`}</Text>
112
+ <View style={styles.arrowIcon}>
113
+ <IconsOpenasist icon={isExpanded ? 'up' : 'down'} size={20} color={colors.grayLight5} />
114
+ </View>
115
+ </View>
116
+ );
117
+ }
118
+
119
+ /**
120
+ * @param {object} props beinhaltet styles, themes und weitere props
121
+ * @param {Array} props.items Die Liste von Events vom aktuellen Tab
122
+ * @return eine Scrollview, welche eine Liste von TimeTableEventComponent enthält
123
+ */
124
+ function EventList({ items: events = [], styles }) {
125
+ const { t } = useTranslation();
126
+
127
+ return (
128
+ <ScrollView>
129
+ {
130
+ events
131
+ ?.map(
132
+ (event) => {
133
+ const startTime = DateTime.fromISO(event.begin).toLocaleString(DateTime.TIME_24_SIMPLE);
134
+ const endTime = DateTime.fromISO(event.end).toLocaleString(DateTime.TIME_24_SIMPLE);
135
+
136
+ return (
137
+ <TimetableEventComponent
138
+ key={event.id}
139
+ type={event?.type ? t(`event:type:${event.type}`) : null}
140
+ title={event?.title}
141
+ location={event?.location}
142
+ locationUrl={event?.locationUrl}
143
+ description={event?.description}
144
+ times={{ start: startTime, end: endTime }} />
145
+ );
146
+ }
147
+ )
148
+ ?? null
149
+ }
150
+ </ScrollView>
151
+ );
152
+ }
153
+
154
+ /***
155
+ * Hook-Component welche eine Accordionliste mit dem entsprechenden Inhalt generiert. Inklusive Header.
156
+ *
157
+ * @param props beinhaltet styles, themes und weitere props
158
+ */
159
+ function EventTimeslotList() {
160
+ const componentName = EventTimeslotList.name;
161
+ const theme = useTheme();
162
+ const [events, refreshEvents] = useEvents();
163
+
164
+ const styles = useMemo(
165
+ () => StyleSheet.create(componentStyles(theme)),
166
+ [theme, componentStyles]
167
+ );
168
+
169
+ const timeslots = useMemo(
170
+ () => {
171
+ if (Array.isArray(events) && events.length > 0) {
172
+ // get the value of the start-prop of the earliest-event
173
+ const earliestEvent = events.reduce((previousEvent, currentEvent) => { return currentEvent.begin < previousEvent.begin ? currentEvent : previousEvent });
174
+ // get the value of the end-prop of the latest-event
175
+ const latestEvent = events.reduce((previousEvent, currentEvent) => { return currentEvent.end > previousEvent.end ? currentEvent : previousEvent });
176
+ return generateTimeslots(events, earliestEvent.begin, latestEvent.end, 1.5);
177
+
178
+ } else if (Array.isArray(events) && events.length === 0) {
179
+ return [];
180
+
181
+ } else {
182
+ console.debug(componentName, ':', 'No events to Generate timeslots');
183
+ return null;
184
+ }
185
+ },
186
+ [events, generateTimeslots]
187
+ );
188
+
189
+ useEffect(
190
+ () => {
191
+ refreshEvents();
192
+ },
193
+ [refreshEvents]
194
+ );
195
+
196
+ return Array.isArray(timeslots)
197
+ ? timeslots.length > 0
198
+ ? <AccordionList
199
+ list={timeslots}
200
+ header={
201
+ (timeslot, index, isExpanded) => <TimeslotAccordionHeader startTime={timeslot.startTs} endTime={timeslot.endTs} styles={styles} isExpanded={isExpanded} />
202
+ }
203
+ body={
204
+ (timeslot) => <EventList items={timeslot.eventsTs} styles={styles} />
205
+ }
206
+ />
207
+ : <View style={styles.content}>
208
+ <Text>
209
+ Es werden gerade keine Veranstalltungen angeboten
210
+ </Text>
211
+ </View>
212
+ : <View style={styles.content}>
213
+ <Text>{t('canteen:notAvailable')}</Text>
214
+ <ActivityIndicator style={styles.activity} size='large' color={theme.colors.loadingIndicator} />
215
+ </View>
216
+
217
+ }
218
+
219
+ function SelectedEventList() {
220
+ const componentName = SelectedEventList.name;
221
+ const theme = useTheme();
222
+
223
+ const [personalEvents, refreshPersonalEvents] = usePersonalEvents();
224
+
225
+ const styles = useMemo(
226
+ () => StyleSheet.create(componentStyles(theme)),
227
+ [theme, componentStyles]
228
+ );
229
+
230
+ useEffect(
231
+ () => {
232
+ refreshPersonalEvents();
233
+ },
234
+ [refreshPersonalEvents]
235
+ )
236
+
237
+ return (
238
+ <EventList
239
+ styles={styles}
240
+ items={personalEvents}
241
+ />
242
+ )
243
+ }
244
+
245
+ const TabViewScenes = SceneMap({
246
+ all_events: EventTimeslotList,
247
+ personal_events: SelectedEventList,
248
+ });
249
+
250
+
251
+ export default function EventsView(props) {
252
+
253
+ const [personalEventsCode] = usePersonalEventsCode();
254
+ const theme = useTheme();
255
+ const { colors, themeStyles } = theme;
256
+ const { t } = useTranslation();
257
+ const navigation = useNavigation();
258
+
259
+ const [showCodeInput, setShowCodeInput] = useState(personalEventsCode ? false : true);
260
+ const [tabIndex, setTabIndex] = useState(0);
261
+
262
+ const tabRoutes = useMemo(
263
+ () =>
264
+ [
265
+ {
266
+ key: 'personal_events',
267
+ title: t('event:tabs.selected'),
268
+ accessibilityLabel: t('accessibility:event.selected'),
269
+ },
270
+ {
271
+ key: 'all_events',
272
+ title: t('event:tabs.all'),
273
+ accessibilityLabel: t('accessibility:event.all'),
274
+ }
275
+ ],
276
+ [t]
277
+ );
278
+
279
+
280
+ const styles = useMemo(
281
+ () => StyleSheet.create(componentStyles(theme)),
282
+ [theme]
283
+ )
284
+
285
+ const leftAction = useMemo(
286
+ () => (
287
+ <Appbar.Action
288
+ icon={props => <IconsOpenasist {...props} icon={'back'} color={colors.primaryText} />}
289
+ onPress={() => {
290
+ navigation.goBack();
291
+ }} />
292
+ ),
293
+ [colors, navigation]
294
+ )
295
+
296
+ const rightAction = useMemo(
297
+ () => (
298
+ <Appbar.Action
299
+ icon={showCodeInput ? 'table' : 'table-plus'}
300
+ color={colors.appbarIconColor}
301
+ onPress={() => setShowCodeInput(showCodeInput => !showCodeInput)}
302
+ />
303
+ ),
304
+ [showCodeInput, setShowCodeInput, colors]
305
+ )
306
+
307
+ const closeCodeInput = useCallback(
308
+ () => setShowCodeInput(false),
309
+ [setShowCodeInput]
310
+ );
311
+
312
+ const closeCodeInputAndShowPersonalEvents = useCallback(
313
+ () => {
314
+ setTabIndex(tabRoutes.findIndex(route => route.key === 'personal_events'));
315
+ setShowCodeInput(false);
316
+ },
317
+ [tabRoutes, setShowCodeInput, setTabIndex]
318
+ );
319
+
320
+
321
+ return (
322
+ <SafeAreaView style={[styles.container, themeStyles.appSafeAreaContainer]}>
323
+ <View>
324
+ <AppbarComponent {...props}
325
+ title={t('menu:titles.event')}
326
+ leftAction={leftAction}
327
+ rightAction={rightAction}
328
+ />
329
+ </View>
330
+ {
331
+ showCodeInput
332
+ ? <EventCodeInputComponent {...props}
333
+ onClose={closeCodeInput}
334
+ onPersonalEventsImported={closeCodeInputAndShowPersonalEvents}
335
+ />
336
+ : <View style={themeStyles.container}>
337
+ <TabView
338
+ index={tabIndex}
339
+ navigationState={{ index: tabIndex, routes: tabRoutes }}
340
+ initialLayout={{ height: 0, width: Dimensions.get('window').width }}
341
+ onIndexChange={setTabIndex}
342
+ renderTabBar={props =>
343
+ <TabBar
344
+ {...props}
345
+ style={themeStyles.tabs}
346
+ labelStyle={themeStyles.tab}
347
+ activeColor={themeStyles.tabs.activeColor}
348
+ inactiveColor={themeStyles.tabs.inactiveColor}
349
+ indicatorStyle={themeStyles.tabIndicator}
350
+ tabStyle={{ paddingHorizontal: 20 }}
351
+ />
352
+ }
353
+ renderScene={TabViewScenes}
354
+ />
355
+ </View>
356
+ }
357
+ </SafeAreaView>
358
+ );
359
+ }
360
+
361
+ export function APIProvidetEventsView(props) {
362
+ return (
363
+ <EventContextProvider>
364
+ <EventsView
365
+ {...props}
366
+ />
367
+ </EventContextProvider>
368
+ )
369
+ }
@@ -0,0 +1,63 @@
1
+ export default function(theme) {
2
+ return {
3
+ activity: {
4
+ padding: 20
5
+ },
6
+ arrowIcon: {
7
+ marginStart: 'auto',
8
+ marginEnd: 10,
9
+ },
10
+ companyCity:{
11
+ fontSize: theme.fontSizes.s,
12
+ paddingTop: theme.paddings.xsmall,
13
+ color: theme.colors.secondaryText
14
+ },
15
+ container: {
16
+ flex: 1,
17
+ backgroundColor: theme.colors.background,
18
+ },
19
+ containerErrorMsg: {
20
+ flex: 1,
21
+ justifyContent: 'center',
22
+ alignContent: 'center',
23
+ alignItems: 'center',
24
+ margin: theme.paddings.default,
25
+ },
26
+ content: {
27
+ backgroundColor: theme.colors.background,
28
+ flex: 1,
29
+ padding: "2%",
30
+ },
31
+ date:{
32
+ fontSize: theme.fontSizes.s,
33
+ paddingTop: theme.paddings.xsmall
34
+ },
35
+ header: {
36
+ backgroundColor: theme.colors.background,
37
+ padding: 10,
38
+ flexDirection: "row",
39
+ justifyContent: 'flex-start',
40
+ alignItems: 'center',
41
+ },
42
+ headerText: {
43
+ fontSize: theme.fontSizes.l,
44
+ ...theme.fonts.light,
45
+ marginTop: 10,
46
+ marginBottom: 10
47
+ },
48
+ innerContainer: {
49
+ padding: 40,
50
+ marginTop: 200
51
+ },
52
+ title:{
53
+ fontSize: theme.fontSizes.xxl,
54
+ color: theme.colors.jobsTitleColor
55
+ },
56
+ titleNoJobs:{
57
+ fontSize: theme.fontSizes.xxl,
58
+ color: theme.colors.jobsTitleColor,
59
+ textAlign: 'center',
60
+ marginBottom: theme.paddings.default
61
+ },
62
+ }
63
+ };
@@ -0,0 +1,165 @@
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
+ ActivityIndicator,
18
+ FlatList,
19
+ SafeAreaView,
20
+ StyleSheet,
21
+ Text,
22
+ TouchableOpacity,
23
+ View
24
+ } from 'react-native';
25
+ import {connect} from 'react-redux'
26
+ import {withTheme} from "react-native-paper";
27
+ import {withTranslation} from "react-i18next";
28
+
29
+ import merge from 'lodash/merge';
30
+
31
+ import {onUpdateRefreshing} from "@olea-bps/core";
32
+
33
+
34
+ import componentStyles from "./styles";
35
+ import { AppBar as AppbarComponent } from '@olea-bps/components';
36
+ import IconsOpenasist from "@olea-bps/icons-openasist";
37
+
38
+ /**
39
+ * Feed List View
40
+ *
41
+ * Shows a list of news feeds
42
+ *
43
+ * Parameters:
44
+ * - none
45
+ *
46
+ * Navigation-Parameters:
47
+ * - none
48
+ */
49
+ class FeedListView extends React.Component {
50
+ static navigationOptions = {
51
+ header: null
52
+ };
53
+
54
+ // Styles of this component
55
+ styles;
56
+
57
+ constructor(props) {
58
+ super(props);
59
+
60
+ // ------------------------------------------------------------------------
61
+ // PLUGIN FUNCTIONALITY
62
+ // ------------------------------------------------------------------------
63
+
64
+ const {pluginStyles,theme} = this.props;
65
+ this.styles = componentStyles(theme);
66
+
67
+ if (pluginStyles) {
68
+ this.styles = merge(this.styles, pluginStyles);
69
+ }
70
+
71
+ this.styles = StyleSheet.create(this.styles);
72
+
73
+ // ------------------------------------------------------------------------
74
+ }
75
+
76
+ /**
77
+ * Render a feed
78
+ *
79
+ * @returns {Array}
80
+ *
81
+ * @private
82
+ */
83
+ _renderFeed = ({item}) => {
84
+ const {themeStyles, colors} = this.props.theme;
85
+
86
+ return (
87
+ <TouchableOpacity style={themeStyles.card} onPress={() => {this.props.navigation.navigate('FeedNews', {feedId: item.feedid, feedTitle: item.title})}}>
88
+ <View style={[themeStyles.cardContent, this.styles.cardContent]}>
89
+ <Text style={[themeStyles.cardTitle, this.styles.cardTitle]}>{item.title}</Text>
90
+ <Text style={[themeStyles.cardSubTitle, this.styles.cardSubTitle]}>{item.desc}</Text>
91
+ </View>
92
+ <View style={themeStyles.cardRightIcon}>
93
+ <IconsOpenasist icon={"forward"} size={25} color={colors.messages.icon} />
94
+ </View>
95
+ </TouchableOpacity>
96
+ );
97
+ };
98
+
99
+
100
+ /**
101
+ * Key Extractor for unique item key
102
+ *
103
+ * @param item
104
+ * @param index
105
+ * @returns {*}
106
+ * @private
107
+ */
108
+ _keyExtractor = (item, index) => {
109
+ return 'feed_' + ((item.feedid) ? item.feedid : ((item.title) ? item.title : index));
110
+ };
111
+
112
+
113
+ render() {
114
+ // ------------------------------------------------------------------------
115
+ // PLUGIN FUNCTIONALITY
116
+ // ------------------------------------------------------------------------
117
+ const PluginComponent = this.props.pluginComponent;
118
+ if (PluginComponent) {
119
+ return <PluginComponent/>;
120
+ }
121
+ // ------------------------------------------------------------------------
122
+
123
+ const {feeds, theme: {colors, paddings, themeStyles}, t} = this.props;
124
+
125
+ return (
126
+ <SafeAreaView style={[this.styles.container, themeStyles.appSafeAreaContainer]}>
127
+ <AppbarComponent {...this.props} title={t('news:feeds')}/>
128
+ <View style={themeStyles.container}>
129
+ {!feeds ?
130
+ <ActivityIndicator style={this.styles.activity} size="large" color={colors.loadingIndicator} /> :
131
+ <FlatList
132
+ data={feeds.sort((a,b) => {
133
+ if(a.feedid < b.feedid){
134
+ return -1;
135
+ } else if (a.feedid > b.feedid) {
136
+ return 1;
137
+ }
138
+ return 0;
139
+ })}
140
+ extraData={this.state}
141
+ keyExtractor={this._keyExtractor}
142
+ renderItem={this._renderFeed}
143
+ initialNumToRender={6}
144
+ getItemLayout={(data, index) => (
145
+ {length: 50, offset: 50 * index, index}
146
+ )}
147
+ contentContainerStyle={{paddingBottom: paddings.default}}
148
+ style={this.styles.innerContainer}
149
+ />}
150
+ </View>
151
+ </SafeAreaView>
152
+ );
153
+ }
154
+ }
155
+
156
+ const mapStateToProps = state => {
157
+ return {
158
+ pluginComponent: state.pluginReducer.feedList.component,
159
+ pluginStyles: state.pluginReducer.feedList.styles,
160
+ feeds: state.apiReducer.feeds
161
+ };
162
+ };
163
+
164
+
165
+ export default connect(mapStateToProps, {onUpdateRefreshing})(withTranslation()(withTheme(FeedListView)))
@@ -0,0 +1,15 @@
1
+ export default function(theme) {
2
+ return {
3
+ container: {
4
+ flex: 1
5
+ },
6
+ innerContainer: {
7
+ flex: 1
8
+ },
9
+ cardContent: {
10
+ paddingLeft: theme.paddings.large,
11
+ paddingTop: theme.paddings.small,
12
+ paddingBottom: theme.paddings.small
13
+ }
14
+ }
15
+ };