@quintype/native-components 2.20.32-beta.1 → 2.20.32-beta.2
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.
- package/CHANGELOG.md +0 -8
- package/package.json +2 -3
- package/src/Icons/FallBackIcon/index.js +15 -7
- package/src/components/CollectionCard/index.js +20 -10
- package/src/components/CollectionTitle/index.js +17 -34
- package/src/components/CollectionTitle/styles.js +9 -12
- package/src/components/PrimaryStoryCard/index.js +54 -49
- package/src/components/PrimaryStoryCard/styles.js +24 -27
- package/src/components/RelatedStoriesCard/index.js +4 -13
- package/src/components/ResponsiveImage/index.js +1 -1
- package/src/components/SecondaryStoryCard/index.js +43 -48
- package/src/components/SecondaryStoryCard/styles.js +17 -32
- package/src/components/Story/index.js +0 -20
- package/src/components/StoryHeader/index.js +1 -4
- package/src/components/YouTubePlayer/index.js +0 -2
- package/src/components/index.js +0 -5
- package/src/components/CollectionCardNew/index.js +0 -84
- package/src/components/CollectionTitleNew/index.js +0 -44
- package/src/components/CollectionTitleNew/styles.js +0 -19
- package/src/components/PrimaryStoryCardNew/index.js +0 -155
- package/src/components/PrimaryStoryCardNew/styles.js +0 -63
- package/src/components/Rating/index.js +0 -50
- package/src/components/Rating/styles.js +0 -21
- package/src/components/SecondaryStoryCardNew/index.js +0 -157
- package/src/components/SecondaryStoryCardNew/styles.js +0 -64
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { throttle } from 'lodash';
|
|
2
|
-
import get from 'lodash/get';
|
|
1
|
+
import { get, isNull, throttle } from 'lodash';
|
|
3
2
|
import PropTypes from 'prop-types';
|
|
4
|
-
import React, { useContext } from 'react';
|
|
3
|
+
import React, { useContext, memo, useState, useEffect } from 'react';
|
|
5
4
|
import {
|
|
6
|
-
Image,
|
|
7
5
|
StyleSheet,
|
|
8
6
|
TouchableOpacity,
|
|
9
7
|
View,
|
|
@@ -19,28 +17,29 @@ import {
|
|
|
19
17
|
} from '../../utils';
|
|
20
18
|
import { getStoryHeadline } from '../../utils/story';
|
|
21
19
|
import { ResponsiveImage, Text } from '../index';
|
|
22
|
-
import {
|
|
20
|
+
import { storyStyles } from './styles';
|
|
23
21
|
import {
|
|
24
22
|
COMP_GENERAL_CONSTANTS,
|
|
25
23
|
COMP_CONTENT_CONSTANTS,
|
|
26
24
|
} from '../../constants/component-constants';
|
|
25
|
+
import PremiumIcons from '../../Icons/PremiumIcons/index';
|
|
27
26
|
|
|
28
|
-
|
|
27
|
+
const SecondaryStoryCardNewBase = (props) => {
|
|
28
|
+
const { story = {} } = props;
|
|
29
29
|
const { theme } = useContext(AppTheme);
|
|
30
|
-
const translate = get(theme, ['translate'], (word) => word);
|
|
31
|
-
|
|
32
30
|
const {
|
|
33
31
|
locale,
|
|
32
|
+
DARK_MODE,
|
|
34
33
|
COLORS,
|
|
35
34
|
reverseTimeAdverbPosition,
|
|
36
35
|
enableReadTimeOnStoryCards,
|
|
37
36
|
DATE_TIME_FORMAT,
|
|
37
|
+
premiumIcon,
|
|
38
|
+
FONT_SIZE
|
|
38
39
|
} = theme;
|
|
39
|
-
const styles = secStoryCardStyles(theme);
|
|
40
|
-
const { story = {} } = props;
|
|
41
|
-
|
|
42
|
-
const DATE_FORMAT = DATE_TIME_FORMAT.dateFormat;
|
|
43
40
|
|
|
41
|
+
const translate = get(theme, ['translate'], (word) => word);
|
|
42
|
+
const styles = storyStyles(theme, DARK_MODE);
|
|
44
43
|
const containerStyle = StyleSheet.flatten([
|
|
45
44
|
styles.container,
|
|
46
45
|
{ paddingHorizontal: props.horizontalPadding },
|
|
@@ -49,17 +48,16 @@ export const SecondaryStoryCard = (props) => {
|
|
|
49
48
|
styles.headline,
|
|
50
49
|
props.headlineStyle,
|
|
51
50
|
]);
|
|
52
|
-
const
|
|
53
|
-
styles.
|
|
54
|
-
props.
|
|
51
|
+
const timestampStyle = StyleSheet.flatten([
|
|
52
|
+
styles.timestamp,
|
|
53
|
+
props.timestampStyle,
|
|
55
54
|
]);
|
|
56
|
-
const iconStyles = StyleSheet.flatten([styles.iconStyles, props.iconStyle]);
|
|
57
55
|
|
|
58
|
-
const
|
|
59
|
-
const authorName = name ? `${translate('By')} ${name} | ` : '';
|
|
56
|
+
const DATE_FORMAT = DATE_TIME_FORMAT.dateFormat;
|
|
60
57
|
const readTime = enableReadTimeOnStoryCards && story['read-time']
|
|
61
|
-
? `${story['read-time']} ${translate('min read')}`
|
|
58
|
+
? `${story['read-time']} ${translate('min read')} · `
|
|
62
59
|
: '';
|
|
60
|
+
const isPremiumStory = story['access'] === 'subscription';
|
|
63
61
|
|
|
64
62
|
const throttledOnpress = throttle(props.onPress, 1000);
|
|
65
63
|
|
|
@@ -104,59 +102,56 @@ export const SecondaryStoryCard = (props) => {
|
|
|
104
102
|
cdn={props.cdn || ''}
|
|
105
103
|
imageWidth={props.imageWidth}
|
|
106
104
|
>
|
|
107
|
-
<Text style={styles.xminContainer}>
|
|
108
|
-
{readTime && (
|
|
109
|
-
<View style={styles.xmin}>
|
|
110
|
-
<Text style={styles.xminText}>{readTime}</Text>
|
|
111
|
-
</View>
|
|
112
|
-
)}
|
|
113
|
-
</Text>
|
|
114
105
|
<View style={styles.storyTypeContainer}>{showStoryType()}</View>
|
|
115
106
|
</ResponsiveImage>
|
|
116
|
-
<View style={styles.
|
|
107
|
+
<View style={styles.headlineAndTimestampBlockContainer}>
|
|
108
|
+
<View style={{display:'flex', flexDirection:'row'}}>
|
|
117
109
|
<Text
|
|
118
110
|
primary
|
|
119
|
-
numberOfLines={
|
|
111
|
+
numberOfLines={2}
|
|
120
112
|
ellipsizeMode="tail"
|
|
121
113
|
style={headlineStyle}
|
|
122
114
|
testID={COMP_GENERAL_CONSTANTS.secondaryStoryHeadline}
|
|
123
115
|
>
|
|
116
|
+
{isPremiumStory && premiumIcon !=='none' && <PremiumIcons style={styles.premiumIcon} name={premiumIcon} color={COLORS.primary} size={FONT_SIZE.h4} />}
|
|
117
|
+
{isPremiumStory && premiumIcon !=='none' && ' '}
|
|
124
118
|
{getStoryHeadline(story)?.trim()}
|
|
125
119
|
</Text>
|
|
126
|
-
<View style={styles.authorAndIconContainer}>
|
|
127
|
-
<Text
|
|
128
|
-
style={authorTextStyle}
|
|
129
|
-
numberOfLines={2}
|
|
130
|
-
testID={COMP_CONTENT_CONSTANTS.authorName}
|
|
131
|
-
>
|
|
132
|
-
{authorName
|
|
133
|
-
+ getTimeForStoryCards(
|
|
134
|
-
story['published-at'],
|
|
135
|
-
DATE_FORMAT,
|
|
136
|
-
locale,
|
|
137
|
-
translate,
|
|
138
|
-
reverseTimeAdverbPosition,
|
|
139
|
-
)}
|
|
140
|
-
</Text>
|
|
141
|
-
<View style={iconStyles}>{props.iconComponent}</View>
|
|
142
120
|
</View>
|
|
121
|
+
<Text
|
|
122
|
+
style={timestampStyle}
|
|
123
|
+
numberOfLines={2}
|
|
124
|
+
// TODO: Add corrected testID here
|
|
125
|
+
testID={COMP_CONTENT_CONSTANTS.publishedDate}
|
|
126
|
+
>
|
|
127
|
+
{readTime
|
|
128
|
+
+ getTimeForStoryCards(
|
|
129
|
+
story['published-at'],
|
|
130
|
+
DATE_FORMAT,
|
|
131
|
+
locale,
|
|
132
|
+
translate,
|
|
133
|
+
reverseTimeAdverbPosition,
|
|
134
|
+
)}
|
|
135
|
+
</Text>
|
|
143
136
|
</View>
|
|
137
|
+
<View style={styles.icon}>{props.iconComponent}</View>
|
|
144
138
|
</TouchableOpacity>
|
|
145
139
|
);
|
|
146
140
|
};
|
|
147
141
|
|
|
148
|
-
|
|
142
|
+
SecondaryStoryCardNewBase.propTypes = TouchableOpacityProps && {
|
|
149
143
|
cdn: PropTypes.string.isRequired,
|
|
150
|
-
imageStyle: Image.style,
|
|
151
144
|
imageWidth: PropTypes.number,
|
|
152
145
|
headlineStyle: TextStyle,
|
|
153
|
-
|
|
146
|
+
timestampStyle: TextStyle,
|
|
154
147
|
story: PropTypes.any.isRequired,
|
|
155
148
|
iconComponent: PropTypes.element,
|
|
156
149
|
horizontalPadding: PropTypes.number,
|
|
157
150
|
};
|
|
158
151
|
|
|
159
|
-
|
|
152
|
+
SecondaryStoryCardNewBase.defaultProps = {
|
|
160
153
|
cdn: '',
|
|
161
154
|
horizontalPadding: 12,
|
|
162
155
|
};
|
|
156
|
+
|
|
157
|
+
export const SecondaryStoryCard = memo(SecondaryStoryCardNewBase);
|
|
@@ -1,52 +1,33 @@
|
|
|
1
1
|
import { StyleSheet } from 'react-native';
|
|
2
2
|
|
|
3
|
-
export const
|
|
3
|
+
export const storyStyles = ({ COLORS, FONT_SIZE }) => StyleSheet.create({
|
|
4
4
|
container: {
|
|
5
5
|
flexDirection: 'row',
|
|
6
6
|
backgroundColor: COLORS.BRAND_WHITE,
|
|
7
|
-
|
|
7
|
+
padding: 8,
|
|
8
|
+
alignItems: 'center',
|
|
8
9
|
},
|
|
9
|
-
|
|
10
|
+
headlineAndTimestampBlockContainer: {
|
|
10
11
|
flexShrink: 1,
|
|
11
12
|
flex: 1,
|
|
12
13
|
justifyContent: 'space-between',
|
|
13
|
-
|
|
14
|
-
},
|
|
15
|
-
authorAndIconContainer: {
|
|
16
|
-
flexDirection: 'row',
|
|
17
|
-
justifyContent: 'space-between',
|
|
14
|
+
paddingLeft: 12,
|
|
18
15
|
},
|
|
19
|
-
|
|
16
|
+
timestamp: {
|
|
20
17
|
color: COLORS.BRAND_BLACK,
|
|
21
|
-
fontSize: FONT_SIZE.
|
|
22
|
-
lineHeight: FONT_SIZE.
|
|
23
|
-
opacity: 0.
|
|
24
|
-
|
|
25
|
-
paddingTop: 8,
|
|
18
|
+
fontSize: FONT_SIZE.h5,
|
|
19
|
+
lineHeight: FONT_SIZE.h5 * 1.5,
|
|
20
|
+
opacity: 0.6,
|
|
21
|
+
marginTop: 4,
|
|
26
22
|
},
|
|
27
23
|
headline: {
|
|
28
24
|
color: COLORS.BRAND_BLACK,
|
|
29
|
-
opacity: 0.9,
|
|
30
25
|
flexWrap: 'wrap',
|
|
31
26
|
fontSize: FONT_SIZE.h3,
|
|
32
|
-
lineHeight: FONT_SIZE.h3 * 1.
|
|
33
|
-
},
|
|
34
|
-
iconStyles: {
|
|
35
|
-
justifyContent: 'flex-end',
|
|
27
|
+
lineHeight: FONT_SIZE.h3 * 1.6,
|
|
36
28
|
},
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
bottom: 8,
|
|
40
|
-
right: 8,
|
|
41
|
-
},
|
|
42
|
-
xmin: {
|
|
43
|
-
backgroundColor: DARK_MODE ? COLORS.MONO6 : COLORS.BRAND_WHITE,
|
|
44
|
-
paddingLeft: 8,
|
|
45
|
-
paddingRight: 8,
|
|
46
|
-
},
|
|
47
|
-
xminText: {
|
|
48
|
-
color: COLORS.BRAND_BLACK,
|
|
49
|
-
fontSize: FONT_SIZE.h5,
|
|
29
|
+
icon: {
|
|
30
|
+
marginLeft: 8,
|
|
50
31
|
},
|
|
51
32
|
storyTypeContainer: {
|
|
52
33
|
position: 'absolute',
|
|
@@ -76,4 +57,8 @@ export const secStoryCardStyles = ({ COLORS, FONT_SIZE, DARK_MODE }) => StyleShe
|
|
|
76
57
|
borderRadius: 50,
|
|
77
58
|
backgroundColor: COLORS.BRAND_3,
|
|
78
59
|
},
|
|
60
|
+
premiumIcon: {
|
|
61
|
+
marginTop: FONT_SIZE.h3 * 0.45,
|
|
62
|
+
marginRight: 3,
|
|
63
|
+
},
|
|
79
64
|
});
|
|
@@ -6,7 +6,6 @@ import { Text } from '../index';
|
|
|
6
6
|
import { StoryHeader } from '../StoryHeader';
|
|
7
7
|
import { StoryContent } from '../StoryContent';
|
|
8
8
|
import { TagsRow } from '../TagsRow/TagsRow';
|
|
9
|
-
import { FBCommentsRow } from '../FBCommentsRow';
|
|
10
9
|
import { STORY_TYPES } from '../../utils/story-types';
|
|
11
10
|
import { getTimeInFormat, AppTheme } from '../../utils';
|
|
12
11
|
import { ShareIcon } from '../../Icons/ShareIcon';
|
|
@@ -134,13 +133,11 @@ export const Story = ({
|
|
|
134
133
|
onAuthorPress,
|
|
135
134
|
onTagsPress,
|
|
136
135
|
onSectionPress,
|
|
137
|
-
onFbCommentPress,
|
|
138
136
|
screenList,
|
|
139
137
|
navigation,
|
|
140
138
|
share,
|
|
141
139
|
accessComponent,
|
|
142
140
|
checkStoryAccess,
|
|
143
|
-
enableFbComments,
|
|
144
141
|
storyHasAccess = 'loading',
|
|
145
142
|
currentLayout,
|
|
146
143
|
getAd,
|
|
@@ -166,20 +163,6 @@ export const Story = ({
|
|
|
166
163
|
: 'hh:mm, d MMM yyyy';
|
|
167
164
|
const storyType = story['story-template'];
|
|
168
165
|
|
|
169
|
-
const shouldShowComments = () => {
|
|
170
|
-
if (!enableFbComments) return null;
|
|
171
|
-
if (
|
|
172
|
-
isStoryFree(story) === 0
|
|
173
|
-
|| (storyHasAccess !== 'loading' && storyHasAccess === 'granted')
|
|
174
|
-
) {
|
|
175
|
-
return (
|
|
176
|
-
<View>
|
|
177
|
-
<FBCommentsRow onPress={onFbCommentPress} />
|
|
178
|
-
</View>
|
|
179
|
-
);
|
|
180
|
-
}
|
|
181
|
-
return null;
|
|
182
|
-
};
|
|
183
166
|
|
|
184
167
|
useEffect(() => {
|
|
185
168
|
checkStoryAccess(story);
|
|
@@ -221,8 +204,6 @@ export const Story = ({
|
|
|
221
204
|
|
|
222
205
|
{accessComponent(story, storyHasAccess)}
|
|
223
206
|
|
|
224
|
-
{shouldShowComments()}
|
|
225
|
-
|
|
226
207
|
<View>
|
|
227
208
|
<TagsRow tags={story.tags} onPress={onTagsPress} />
|
|
228
209
|
</View>
|
|
@@ -245,7 +226,6 @@ Story.propTypes = {
|
|
|
245
226
|
onFbCommentPress: PropTypes.func,
|
|
246
227
|
screenList: PropTypes.any,
|
|
247
228
|
accessComponent: PropTypes.any,
|
|
248
|
-
enableFbComments: PropTypes.bool,
|
|
249
229
|
currentLayout: PropTypes.any,
|
|
250
230
|
navigation: PropTypes.any,
|
|
251
231
|
};
|
|
@@ -18,7 +18,6 @@ import { storyHeaderStyles } from './styles';
|
|
|
18
18
|
import { COMP_CONTENT_CONSTANTS } from '../../constants/component-constants/content-constants/constants';
|
|
19
19
|
|
|
20
20
|
import { DailyMotionPlayer } from '../DailyMotionPlayer';
|
|
21
|
-
import { RatingLayout } from '../Rating';
|
|
22
21
|
const getHeroImage = (cdn, story) => {
|
|
23
22
|
const imageSlug = story['hero-image-s3-key'];
|
|
24
23
|
if (!imageSlug) return null;
|
|
@@ -74,8 +73,7 @@ export const StoryHeader = (props) => {
|
|
|
74
73
|
const caption = story['hero-image-caption'];
|
|
75
74
|
const attribution = story['hero-image-attribution'];
|
|
76
75
|
const isPremiumStory = story['access'] === 'subscription';
|
|
77
|
-
|
|
78
|
-
const reviewData = story['metadata'] && story['metadata']['review-rating'];
|
|
76
|
+
|
|
79
77
|
|
|
80
78
|
const showAttribution = () => {
|
|
81
79
|
if (!caption && !attribution) {
|
|
@@ -130,7 +128,6 @@ export const StoryHeader = (props) => {
|
|
|
130
128
|
cdn={props.cdn}
|
|
131
129
|
readtime={story['read-time']}
|
|
132
130
|
/>
|
|
133
|
-
{reviewTitle && <RatingLayout reviewTitle={reviewTitle} ratingValue={reviewData?.value} ratingLabel={reviewData?.label}/>}
|
|
134
131
|
</View>
|
|
135
132
|
);
|
|
136
133
|
};
|
package/src/components/index.js
CHANGED
|
@@ -3,21 +3,16 @@ export { AuthorRow } from './AuthorRow';
|
|
|
3
3
|
export { BackNavigator } from './BackNavigator';
|
|
4
4
|
export { Button } from './Button';
|
|
5
5
|
export { CollectionCard } from './CollectionCard';
|
|
6
|
-
export { CollectionCardNew } from './CollectionCardNew';
|
|
7
6
|
export { CollectionTitle } from './CollectionTitle';
|
|
8
|
-
export { CollectionTitleNew } from './CollectionTitleNew';
|
|
9
7
|
export { CustomLoader } from './CustomLoader';
|
|
10
|
-
export { FBCommentsRow } from './FBCommentsRow';
|
|
11
8
|
export { Header } from './Header';
|
|
12
9
|
export { JSEmbedElement } from './JSEmbedElement';
|
|
13
10
|
export { PDFReader } from './PDFReader';
|
|
14
11
|
export { PrimaryStoryCard } from './PrimaryStoryCard';
|
|
15
|
-
export { PrimaryStoryCardNew } from './PrimaryStoryCardNew';
|
|
16
12
|
export { RadioButton } from './RadioButton';
|
|
17
13
|
export { ResponsiveImage } from './ResponsiveImage';
|
|
18
14
|
export { Search } from './Search';
|
|
19
15
|
export { SecondaryStoryCard } from './SecondaryStoryCard';
|
|
20
|
-
export { SecondaryStoryCardNew } from './SecondaryStoryCardNew';
|
|
21
16
|
export { ShareButton } from './ShareButton';
|
|
22
17
|
export { Story } from './Story';
|
|
23
18
|
export { StoryContent } from './StoryContent';
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import get from 'lodash/get';
|
|
2
|
-
import isEmpty from 'lodash/isEmpty';
|
|
3
|
-
import PropTypes from 'prop-types';
|
|
4
|
-
import React, { memo } from 'react';
|
|
5
|
-
import { getScreenPercentageWidth } from '../../utils/index';
|
|
6
|
-
import {
|
|
7
|
-
CollectionTitleNew,
|
|
8
|
-
PrimaryStoryCardNew,
|
|
9
|
-
SecondaryStoryCardNew,
|
|
10
|
-
ShareButton,
|
|
11
|
-
} from '../index';
|
|
12
|
-
|
|
13
|
-
const CollectionCardNewBase = ({
|
|
14
|
-
cdn,
|
|
15
|
-
collectionName,
|
|
16
|
-
stories,
|
|
17
|
-
onCollectionPress,
|
|
18
|
-
onStoryPress,
|
|
19
|
-
collectionTestID,
|
|
20
|
-
offset,
|
|
21
|
-
horizontalPadding,
|
|
22
|
-
initialOffset, /* Number of items to load on first load */
|
|
23
|
-
hideCollectionTitle,
|
|
24
|
-
}) => {
|
|
25
|
-
const sliceLimit = offset || initialOffset || 5;
|
|
26
|
-
const primaryStory = !isEmpty(stories) && get(stories, [0, 'story'], stories[0]);
|
|
27
|
-
|
|
28
|
-
return (
|
|
29
|
-
<>
|
|
30
|
-
{!hideCollectionTitle && (
|
|
31
|
-
<CollectionTitleNew
|
|
32
|
-
title={collectionName}
|
|
33
|
-
onPress={onCollectionPress}
|
|
34
|
-
horizontalPadding={horizontalPadding}
|
|
35
|
-
/>
|
|
36
|
-
)}
|
|
37
|
-
<PrimaryStoryCardNew
|
|
38
|
-
collectionTestID={collectionTestID}
|
|
39
|
-
onPress={() => {
|
|
40
|
-
!isEmpty(stories) && onStoryPress(primaryStory);
|
|
41
|
-
}}
|
|
42
|
-
cdn={cdn}
|
|
43
|
-
story={!isEmpty(stories) ? primaryStory : {}}
|
|
44
|
-
iconComponent={<ShareButton story={primaryStory} />}
|
|
45
|
-
imageWidth={getScreenPercentageWidth(100) - 2 * horizontalPadding}
|
|
46
|
-
horizontalPadding={horizontalPadding}
|
|
47
|
-
/>
|
|
48
|
-
{stories.slice(1, sliceLimit).map((currentStory) => {
|
|
49
|
-
const secondaryStory = get(currentStory, ['story'], currentStory);
|
|
50
|
-
return (
|
|
51
|
-
<SecondaryStoryCardNew
|
|
52
|
-
collectionTestID={collectionTestID}
|
|
53
|
-
onPress={() => onStoryPress(secondaryStory)}
|
|
54
|
-
key={secondaryStory?.id}
|
|
55
|
-
cdn={cdn}
|
|
56
|
-
story={secondaryStory}
|
|
57
|
-
iconComponent={<ShareButton story={secondaryStory} />}
|
|
58
|
-
imageWidth={getScreenPercentageWidth(25)}
|
|
59
|
-
horizontalPadding={horizontalPadding}
|
|
60
|
-
/>
|
|
61
|
-
);
|
|
62
|
-
})}
|
|
63
|
-
</>
|
|
64
|
-
);
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
CollectionCardNewBase.propTypes = {
|
|
68
|
-
offset: PropTypes.number,
|
|
69
|
-
initialOffset: PropTypes.number,
|
|
70
|
-
cdn: PropTypes.string.isRequired,
|
|
71
|
-
collectionName: PropTypes.string,
|
|
72
|
-
stories: PropTypes.array.isRequired,
|
|
73
|
-
onCollectionPress: PropTypes.func,
|
|
74
|
-
onStoryPress: PropTypes.func,
|
|
75
|
-
collectionTestID: PropTypes.string,
|
|
76
|
-
horizontalPadding: PropTypes.number,
|
|
77
|
-
hideCollectionTitle: PropTypes.bool,
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
CollectionCardNewBase.defaultProps = {
|
|
81
|
-
horizontalPadding: 12,
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
export const CollectionCardNew = memo(CollectionCardNewBase);
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import PropTypes from 'prop-types';
|
|
2
|
-
import React, { useContext, memo } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
TextStyle,
|
|
5
|
-
TouchableOpacity,
|
|
6
|
-
TouchableOpacityProps,
|
|
7
|
-
StyleSheet,
|
|
8
|
-
} from 'react-native';
|
|
9
|
-
import { Text } from '../index';
|
|
10
|
-
import { collectionTitleStyles } from './styles';
|
|
11
|
-
import { AppTheme } from '../../utils';
|
|
12
|
-
|
|
13
|
-
const CollectionTitleNewBase = (props) => {
|
|
14
|
-
const { theme } = useContext(AppTheme);
|
|
15
|
-
const styles = collectionTitleStyles(theme);
|
|
16
|
-
const containerStyle = StyleSheet.flatten([
|
|
17
|
-
styles.container,
|
|
18
|
-
{ paddingHorizontal: props.horizontalPadding },
|
|
19
|
-
]);
|
|
20
|
-
const titleStyle = StyleSheet.flatten([styles.title, props.titleStyle]);
|
|
21
|
-
|
|
22
|
-
if (!props.title) {
|
|
23
|
-
return null;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return (
|
|
27
|
-
<TouchableOpacity style={containerStyle} onPress={props.onPress}>
|
|
28
|
-
<Text style={titleStyle}>{props.title}</Text>
|
|
29
|
-
</TouchableOpacity>
|
|
30
|
-
);
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
CollectionTitleNewBase.propTypes = TouchableOpacityProps
|
|
34
|
-
&& {
|
|
35
|
-
title: PropTypes.string,
|
|
36
|
-
titleStyle: TextStyle,
|
|
37
|
-
horizontalPadding: PropTypes.number,
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
CollectionTitleNewBase.defaultProps = {
|
|
41
|
-
horizontalPadding: 12,
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
export const CollectionTitleNew = memo(CollectionTitleNewBase);
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { StyleSheet } from 'react-native';
|
|
2
|
-
|
|
3
|
-
export const collectionTitleStyles = (appThemeContext) => {
|
|
4
|
-
const { COLORS, FONT_SIZE } = appThemeContext;
|
|
5
|
-
|
|
6
|
-
return StyleSheet.create({
|
|
7
|
-
container: {
|
|
8
|
-
justifyContent: 'center',
|
|
9
|
-
backgroundColor: COLORS.BRAND_WHITE,
|
|
10
|
-
paddingHorizontal: 12,
|
|
11
|
-
paddingVertical: 8,
|
|
12
|
-
marginTop: 8,
|
|
13
|
-
},
|
|
14
|
-
title: {
|
|
15
|
-
fontSize: FONT_SIZE.h3,
|
|
16
|
-
color: COLORS.BRAND_5,
|
|
17
|
-
},
|
|
18
|
-
});
|
|
19
|
-
};
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
import { get, throttle } from 'lodash';
|
|
2
|
-
import PropTypes from 'prop-types';
|
|
3
|
-
import React, { useContext, memo } from 'react';
|
|
4
|
-
import { StyleSheet, TouchableOpacity, View } from 'react-native';
|
|
5
|
-
import Icon from 'react-native-vector-icons/FontAwesome';
|
|
6
|
-
import {
|
|
7
|
-
AppTheme,
|
|
8
|
-
getImageMetadata,
|
|
9
|
-
getImageSlug,
|
|
10
|
-
getTimeForStoryCards,
|
|
11
|
-
} from '../../utils';
|
|
12
|
-
import { getStoryHeadline } from '../../utils/story';
|
|
13
|
-
import { ResponsiveImage, Text } from '../index';
|
|
14
|
-
import { storyStyles } from './styles';
|
|
15
|
-
import {
|
|
16
|
-
COMP_GENERAL_CONSTANTS,
|
|
17
|
-
COMP_CONTENT_CONSTANTS,
|
|
18
|
-
} from '../../constants/component-constants';
|
|
19
|
-
import PremiumIcons from '../../Icons/PremiumIcons/index';
|
|
20
|
-
|
|
21
|
-
const PrimaryStoryCardNewBase = (props) => {
|
|
22
|
-
const { story = {} } = props;
|
|
23
|
-
const { theme } = useContext(AppTheme);
|
|
24
|
-
const {
|
|
25
|
-
COLORS,
|
|
26
|
-
FONT_SIZE,
|
|
27
|
-
locale,
|
|
28
|
-
DARK_MODE,
|
|
29
|
-
reverseTimeAdverbPosition,
|
|
30
|
-
enableReadTimeOnStoryCards,
|
|
31
|
-
DATE_TIME_FORMAT,
|
|
32
|
-
premiumIcon
|
|
33
|
-
} = theme || {};
|
|
34
|
-
|
|
35
|
-
const translate = get(theme, ['translate'], (word) => word);
|
|
36
|
-
|
|
37
|
-
const styles = storyStyles(COLORS, FONT_SIZE, DARK_MODE);
|
|
38
|
-
const containerStyle = StyleSheet.flatten([
|
|
39
|
-
styles.container,
|
|
40
|
-
{ paddingHorizontal: props.horizontalPadding },
|
|
41
|
-
]);
|
|
42
|
-
const headlineStyle = StyleSheet.flatten([
|
|
43
|
-
styles.headline,
|
|
44
|
-
props.headlineStyle,
|
|
45
|
-
]);
|
|
46
|
-
const timestampStyle = StyleSheet.flatten([
|
|
47
|
-
styles.timestamp,
|
|
48
|
-
props.timestampStyle,
|
|
49
|
-
]);
|
|
50
|
-
|
|
51
|
-
const DATE_FORMAT = DATE_TIME_FORMAT.dateFormat;
|
|
52
|
-
const readTime = enableReadTimeOnStoryCards && story['read-time']
|
|
53
|
-
? `${story['read-time']} ${translate('min read')} · `
|
|
54
|
-
: '';
|
|
55
|
-
const isPremiumStory = story['access'] === 'subscription';
|
|
56
|
-
|
|
57
|
-
const throttledOnpress = throttle(props.onPress, 1000);
|
|
58
|
-
|
|
59
|
-
const showIcon = (name) => (
|
|
60
|
-
<View style={styles.storyType}>
|
|
61
|
-
<Icon name={name} size={22} color={COLORS.MONO7} />
|
|
62
|
-
</View>
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
const showLiveBlogIcon = () => (
|
|
66
|
-
<View style={styles.storyType}>
|
|
67
|
-
<View style={styles.liveBlogIcon} />
|
|
68
|
-
<Text style={styles.liveBlogText}>LIVE</Text>
|
|
69
|
-
</View>
|
|
70
|
-
);
|
|
71
|
-
const showStoryType = () => {
|
|
72
|
-
switch (story['story-template']) {
|
|
73
|
-
case 'text':
|
|
74
|
-
return null;
|
|
75
|
-
case 'photo':
|
|
76
|
-
return showIcon('photo');
|
|
77
|
-
case 'video':
|
|
78
|
-
return showIcon('play');
|
|
79
|
-
case 'live-blog':
|
|
80
|
-
return showLiveBlogIcon();
|
|
81
|
-
default:
|
|
82
|
-
null;
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
return (
|
|
87
|
-
<TouchableOpacity
|
|
88
|
-
testID={COMP_GENERAL_CONSTANTS.primaryStoryCard}
|
|
89
|
-
onPress={throttledOnpress}
|
|
90
|
-
activeOpacity={0.8}
|
|
91
|
-
style={containerStyle}
|
|
92
|
-
>
|
|
93
|
-
<ResponsiveImage
|
|
94
|
-
metaData={getImageMetadata(story)}
|
|
95
|
-
slug={getImageSlug(story)}
|
|
96
|
-
cdn={props.cdn}
|
|
97
|
-
imageWidth={props.imageWidth}
|
|
98
|
-
>
|
|
99
|
-
<View style={styles.storyTypeContainer}>{showStoryType()}</View>
|
|
100
|
-
</ResponsiveImage>
|
|
101
|
-
<View style={styles.contentContainer}>
|
|
102
|
-
<View style={styles.headlineAndTimestampContainer}>
|
|
103
|
-
<View style={{display:'flex', flexDirection:'row'}}>
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
<Text
|
|
107
|
-
primary
|
|
108
|
-
numberOfLines={3}
|
|
109
|
-
ellipsizeMode="tail"
|
|
110
|
-
style={headlineStyle}
|
|
111
|
-
testID={COMP_GENERAL_CONSTANTS.primaryStoryHeadline}
|
|
112
|
-
>
|
|
113
|
-
{isPremiumStory && premiumIcon !=='none' && <PremiumIcons style={styles.premiumIcon} name={premiumIcon} color={COLORS.primary} size={FONT_SIZE.h2} /> }
|
|
114
|
-
{isPremiumStory && premiumIcon !=='none' && ' '}
|
|
115
|
-
{getStoryHeadline(story)}
|
|
116
|
-
</Text>
|
|
117
|
-
</View>
|
|
118
|
-
<Text
|
|
119
|
-
style={timestampStyle}
|
|
120
|
-
numberOfLines={2}
|
|
121
|
-
testID={COMP_CONTENT_CONSTANTS.publishedDate}
|
|
122
|
-
>
|
|
123
|
-
{readTime
|
|
124
|
-
+ getTimeForStoryCards(
|
|
125
|
-
story['published-at'],
|
|
126
|
-
DATE_FORMAT,
|
|
127
|
-
locale,
|
|
128
|
-
translate,
|
|
129
|
-
reverseTimeAdverbPosition,
|
|
130
|
-
)}
|
|
131
|
-
</Text>
|
|
132
|
-
</View>
|
|
133
|
-
<View style={styles.icon}>{props.iconComponent}</View>
|
|
134
|
-
</View>
|
|
135
|
-
</TouchableOpacity>
|
|
136
|
-
);
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
PrimaryStoryCardNewBase.propTypes = {
|
|
140
|
-
cdn: PropTypes.string,
|
|
141
|
-
imageWidth: PropTypes.number,
|
|
142
|
-
headlineStyle: PropTypes.func,
|
|
143
|
-
timestampStyle: PropTypes.func,
|
|
144
|
-
story: PropTypes.object.isRequired,
|
|
145
|
-
onPress: PropTypes.func,
|
|
146
|
-
horizontalPadding: PropTypes.number,
|
|
147
|
-
iconComponent: PropTypes.element,
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
PrimaryStoryCardNewBase.defaultProps = {
|
|
151
|
-
cdn: '',
|
|
152
|
-
horizontalPadding: 12,
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
export const PrimaryStoryCardNew = memo(PrimaryStoryCardNewBase);
|