@quintype/native-components 2.28.5 → 2.29.0-beta.1

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.
@@ -1,15 +1,15 @@
1
- # #!/bin/bash -e
1
+ #!/bin/bash -e
2
2
 
3
- # npm install
4
- # git diff --quiet
3
+ npm install
4
+ git diff --quiet
5
5
 
6
- # BRANCH=$(git symbolic-ref --short HEAD)
6
+ BRANCH=$(git symbolic-ref --short HEAD)
7
7
 
8
- # if [ "$BRANCH" == 'master' ]
9
- # then
10
- # npx standard-version
11
- # else
12
- # npx standard-version --prerelease "$(git symbolic-ref --short HEAD | sed s:/:-:g )" --skip.changelog=true
13
- # fi
8
+ if [ "$BRANCH" == 'master' ]
9
+ then
10
+ npx standard-version
11
+ else
12
+ npx standard-version --prerelease "$(git symbolic-ref --short HEAD | sed s:/:-:g )" --skip.changelog=true
13
+ fi
14
14
 
15
- # git push --follow-tags origin "$BRANCH"
15
+ git push --follow-tags origin "$BRANCH"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quintype/native-components",
3
- "version": "2.28.5",
3
+ "version": "2.29.0-beta.1",
4
4
  "description": "",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -9,6 +9,7 @@
9
9
  "lint:ci": "npx eslint $(git diff --pretty='' --diff-filter=d --name-only origin/master..HEAD -- '*.js' '*.jsx') ./start.js"
10
10
  },
11
11
  "dependencies": {
12
+ "@react-native-community/slider": "^4.5.3",
12
13
  "atob": "^2.1.2",
13
14
  "base-64": "^1.0.0",
14
15
  "date-fns": "^2.15.0",
@@ -16,24 +17,27 @@
16
17
  "prop-types": "15.7.2",
17
18
  "quintype-js": "1.2.1",
18
19
  "react-htmltext": "^0.40.2",
19
- "react-native-fast-image": "8.3.2",
20
+ "react-native-fast-image": ">=8.3.2",
20
21
  "react-native-image-pan-zoom": "^2.1.12",
21
22
  "react-native-lightbox": "0.8.1",
23
+ "react-native-modal": "^13.0.1",
22
24
  "react-native-render-html": "^4.2.3",
23
25
  "react-native-share": "^10.2.0",
24
- "react-native-star-rating-widget": "^1.7.3"
26
+ "react-native-star-rating-widget": "^1.7.3",
27
+ "react-native-track-player": "^4.1.1"
25
28
  },
26
29
  "peerDependencies": {
27
30
  "@react-navigation/native": ">=6.1.17",
28
31
  "lodash": ">=4.17.20",
29
32
  "react": ">=17.0.2",
30
33
  "react-native": ">=0.67.5",
34
+ "react-native-blob-util": ">=6.7.4",
31
35
  "react-native-fast-image": ">=8.3.2",
36
+ "react-native-linear-gradient": "^2.8.3",
32
37
  "react-native-pdf": ">=6.7.4",
33
- "react-native-blob-util": ">=6.7.4",
34
- "react-native-webview": ">=11.0.0",
35
38
  "react-native-vector-icons": "^10.0.0",
36
- "react-native-linear-gradient": "^2.8.3"
39
+ "react-native-device-info": "^11.1.0",
40
+ "react-native-webview": ">=11.0.0"
37
41
  },
38
42
  "devDependencies": {
39
43
  "@babel/core": "^7.11.1",
@@ -53,7 +57,6 @@
53
57
  "metro-react-native-babel-preset": "^0.62.0",
54
58
  "react": "18.2.0",
55
59
  "react-native": "0.71.17",
56
- "react-native-device-info": "^5.6.5",
57
60
  "react-native-svg": "^12.3.0",
58
61
  "react-navigation-hooks": "^1.1.0",
59
62
  "react-test-renderer": "16.13.1"
@@ -0,0 +1,143 @@
1
+ import React, { memo } from "react";
2
+ import PropTypes from "prop-types";
3
+ import { useProgress, usePlaybackState, State } from "react-native-track-player";
4
+ import { TouchableOpacity, ActivityIndicator, View, ViewPropTypes, useWindowDimensions } from "react-native";
5
+ import Icon from "react-native-vector-icons/AntDesign";
6
+ import MaterialCommunityIcons from "react-native-vector-icons/MaterialCommunityIcons";
7
+ import { playerStyles } from "./styles";
8
+ import Slider from "@react-native-community/slider";
9
+ import { AppTheme } from "../../utils";
10
+ import { useContext } from "react";
11
+ import { Text } from '../index';
12
+
13
+ const ProgressBar = (props) => {
14
+ const screenDimensions = useWindowDimensions();
15
+ const progress = useProgress();
16
+ const { theme } = useContext(AppTheme);
17
+ const { COLORS} = theme;
18
+ const {progressCompleted, progressBar } = playerStyles(screenDimensions);
19
+ const stylesWithFlexValue = (flex, styles) => ({ flex: flex, ...styles });
20
+
21
+ return (
22
+ <View style={progressBar}>
23
+ <Slider
24
+ style={stylesWithFlexValue(progress.position, progressCompleted)}
25
+ minimumValue={0}
26
+ maximumValue={progress.duration}
27
+ minimumTrackTintColor={COLORS.BRAND_BLACK}
28
+ maximumTrackTintColor={COLORS.MONO_6}
29
+ value={progress.position}
30
+ onValueChange={(val) => props.seekTo(val)}
31
+ thumbTintColor={COLORS.BRAND_BLACK}
32
+ thumbStyle={{size:50}}
33
+ />
34
+ </View>
35
+ );
36
+ };
37
+
38
+ export const ControlButton = ({ iconName, onPress, FONT_SIZE }) => {
39
+ const screenDimensions = useWindowDimensions();
40
+ const { controlButtonContainer, controlButton } = playerStyles(screenDimensions);
41
+
42
+ return (
43
+ <TouchableOpacity style={controlButtonContainer} onPress={onPress} >
44
+ <Icon name={iconName} size={FONT_SIZE.title} style={controlButton} />
45
+ </TouchableOpacity>
46
+ );
47
+ };
48
+
49
+ const PlayerBase = (props) => {
50
+ const screenDimensions = useWindowDimensions();
51
+ const { theme } = useContext(AppTheme);
52
+ const { COLORS,translate, FONT_SIZE, DARK_MODE } = theme;
53
+ const { card, container, subContainer, playerControlStyle, playbackSpeedText, playerContainer } = playerStyles(screenDimensions);
54
+ const { style, onTogglePlayback, testID, seekTo, rewindOrForward, isFinishedPlaying, restart, closeButtonHandler } = props;
55
+
56
+ const playbackState = usePlaybackState();
57
+
58
+ const getControlButton = (state) => {
59
+ switch (state?.state) {
60
+ case State.Buffering:
61
+ return <ActivityIndicator size="large" />;
62
+ case State.Playing:
63
+ return (
64
+ <ControlButton
65
+ iconName={"pausecircleo"}
66
+ onPress={() => {
67
+ onTogglePlayback();
68
+ }}
69
+ FONT_SIZE={FONT_SIZE}
70
+ />
71
+ );
72
+ default:
73
+ return <ControlButton iconName={"playcircleo"} onPress={onTogglePlayback} FONT_SIZE={FONT_SIZE}/>;
74
+ }
75
+ };
76
+
77
+ function formatNumber(num) {
78
+ return num % 1 === 0 ? num.toFixed(1) : num.toString();
79
+ }
80
+
81
+ return (
82
+ <View testID={testID}>
83
+ <View
84
+ style={container}
85
+ >
86
+ <Text
87
+ style={subContainer}
88
+ >
89
+ {translate("Listen to this article")}
90
+ </Text>
91
+ <View style={playerControlStyle}>
92
+ <TouchableOpacity style={{ marginHorizontal: 10 }} onPress={() => rewindOrForward("rewind")}>
93
+ <MaterialCommunityIcons color={COLORS.BRAND_BLACK} name={"rewind-10"} size={FONT_SIZE.title} />
94
+ </TouchableOpacity>
95
+ <TouchableOpacity style={{ marginHorizontal: 10 }} onPress={() => rewindOrForward("forward")}>
96
+ <MaterialCommunityIcons color={COLORS.BRAND_BLACK} name={"fast-forward-10"} size={FONT_SIZE.title} />
97
+ </TouchableOpacity>
98
+ <TouchableOpacity
99
+ style={playbackSpeedText}
100
+ onPress={() => props.setShowModal(true)}
101
+ >
102
+ <Text style={{ fontSize: FONT_SIZE.h3, color: DARK_MODE ? COLORS.BRAND_WHITE : COLORS.BRAND_BLACK}}>{`${formatNumber(props.audioRate)}x`}</Text>
103
+ </TouchableOpacity>
104
+ </View>
105
+ </View>
106
+
107
+ <View
108
+ style={[card,style]}
109
+ >
110
+ <View style={playerContainer}>
111
+ { isFinishedPlaying ?
112
+ <ControlButton iconName={"reload1"} onPress={() => restart()} FONT_SIZE={FONT_SIZE} /> :
113
+ getControlButton(playbackState)}
114
+ </View>
115
+ <ProgressBar seekTo={seekTo} />
116
+ <MaterialCommunityIcons
117
+ color={COLORS.BRAND_BLACK}
118
+ onPress={()=>closeButtonHandler()}
119
+ size={FONT_SIZE.title}
120
+ name="close"
121
+ />
122
+ </View>
123
+ </View>
124
+ );
125
+ };
126
+
127
+ ControlButton.propTypes = {
128
+ iconName: PropTypes.string.isRequired,
129
+ onPress: PropTypes.func.isRequired,
130
+ testID: PropTypes.string,
131
+ };
132
+
133
+ PlayerBase.propTypes = {
134
+ style: ViewPropTypes.style,
135
+ onTogglePlayback: PropTypes.func.isRequired,
136
+ testID: PropTypes.string,
137
+ };
138
+
139
+ PlayerBase.defaultProps = {
140
+ style: {},
141
+ };
142
+
143
+ export const Player = memo(PlayerBase);
@@ -0,0 +1,79 @@
1
+ import { StyleSheet } from "react-native";
2
+ import { AppTheme } from "../../utils";
3
+ import { useContext } from "react";
4
+
5
+ export const playerStyles = (screenDimensions) => {
6
+ const { theme } = useContext(AppTheme);
7
+ const { COLORS, DARK_MODE, FONT_SIZE } = theme;
8
+
9
+ return StyleSheet.create({
10
+ container: {
11
+ display: "flex",
12
+ flexDirection: "row",
13
+ justifyContent: "space-between",
14
+ marginHorizontal: 10,
15
+ alignItems: "flex-start",
16
+ marginTop: 15,
17
+ marginBottom: 16,
18
+ },
19
+ subContainer: {
20
+ fontSize: FONT_SIZE.h2,
21
+ color: COLORS.BRAND_BLACK,
22
+ },
23
+ playerControlStyle: { display: "flex", flexDirection: "row", alignItems: "center" },
24
+ playbackSpeedText: {
25
+ backgroundColor: COLORS.MONO5,
26
+ minWidth: screenDimensions.width * .013,
27
+ height: screenDimensions.height * .003,
28
+ borderRadius: 5,
29
+ alignItems: "center",
30
+ justifyContent: "center",
31
+ marginHorizontal: 10,
32
+ },
33
+ card: {
34
+ backgroundColor: DARK_MODE ? COLORS.MONO6 : COLORS.BRAND_WHITE,
35
+ elevation: 10,
36
+ shadowColor: COLORS.BRAND_BLACK,
37
+ shadowOffset: { width: 0, height: -1 },
38
+ shadowOpacity: 0.1,
39
+ shadowRadius: 1,
40
+ width: "95%",
41
+ minHeight: 70,
42
+ borderBottomWidth: 2,
43
+ borderColor: COLORS.MONO6,
44
+ marginBottom: 7,
45
+ display: "flex",
46
+ flexDirection: "row",
47
+ alignItems: "center",
48
+ marginHorizontal: screenDimensions.width * .0025,
49
+ borderRadius: 5,
50
+ },
51
+ playerContainer: {
52
+ width: screenDimensions.width * .012,
53
+ display: 'flex',
54
+ flexDirection: 'row',
55
+ alignItems: 'center',
56
+ justifyContent: 'center',
57
+ },
58
+ controlButton: {
59
+ alignItems: "center",
60
+ color: COLORS.BRAND_BLACK,
61
+ },
62
+ controlButtonContainer: {
63
+ alignItems: "center",
64
+ flex: 1,
65
+ },
66
+ controls: {},
67
+ progressBar: {
68
+ width: screenDimensions.width * .070,
69
+ marginHorizontal: screenDimensions.width * .001,
70
+ },
71
+ progressCompleted: {
72
+ backgroundColor: DARK_MODE ? COLORS.MONO6 : COLORS.BRAND_WHITE,
73
+ },
74
+ progressRemaining: {
75
+ backgroundColor: COLORS.BRAND_BLACK,
76
+ opacity: 0.1,
77
+ },
78
+ });
79
+ };
@@ -2,7 +2,6 @@ import get from 'lodash/get';
2
2
  import isEmpty from 'lodash/isEmpty';
3
3
  import PropTypes from 'prop-types';
4
4
  import React, { memo } from 'react';
5
- import { getScreenPercentageWidth } from '../../utils/index';
6
5
  import {
7
6
  CollectionTitle,
8
7
  PrimaryStoryCard,
@@ -42,7 +41,6 @@ const CollectionCardBase = ({
42
41
  cdn={cdn}
43
42
  story={!isEmpty(stories) ? primaryStory : {}}
44
43
  iconComponent={<ShareButton story={primaryStory} inListingStoryCard />}
45
- imageWidth={getScreenPercentageWidth(100) - 2 * horizontalPadding}
46
44
  horizontalPadding={horizontalPadding}
47
45
  />
48
46
  {stories.slice(1, sliceLimit).map((currentStory) => {
@@ -55,7 +53,6 @@ const CollectionCardBase = ({
55
53
  cdn={cdn}
56
54
  story={secondaryStory}
57
55
  iconComponent={<ShareButton story={secondaryStory} inListingStoryCard />}
58
- imageWidth={getScreenPercentageWidth(28)}
59
56
  horizontalPadding={horizontalPadding}
60
57
  />
61
58
  );
@@ -2,7 +2,7 @@ import { decode as atob } from 'base-64';
2
2
  import get from 'lodash/get';
3
3
  import PropTypes from 'prop-types';
4
4
  import React, { useEffect, useRef, useState } from 'react';
5
- import { Dimensions, View } from 'react-native';
5
+ import { useWindowDimensions, View } from 'react-native';
6
6
  import { WebView } from 'react-native-webview';
7
7
  import { STORY_ELEMENT_SUBTYPES } from '../../constants/cardConstants';
8
8
 
@@ -37,7 +37,7 @@ const removeWidthnHeight = (htmlContent) => {
37
37
  };
38
38
 
39
39
  const getHTMLContent = (embedJs) => {
40
- const { width } = Dimensions.get('window');
40
+ const width = useWindowDimensions().width;
41
41
  const decodedContent = getDecodedContent(embedJs);
42
42
  let htmlContent = replaceDefaultProtocol(decodedContent);
43
43
  htmlContent = removeWidthnHeight(htmlContent);
@@ -77,10 +77,11 @@ const getHTMLContent = (embedJs) => {
77
77
  export const JSEmbedElement = (props) => {
78
78
  const [height, setHeight] = useState(-1);
79
79
  const webViewRef = useRef(null);
80
+ const screenWidth = useWindowDimensions().width;
80
81
  const width = get(
81
82
  props,
82
83
  ['currentLayout', 'width'],
83
- Dimensions.get('window').width,
84
+ screenWidth,
84
85
  );
85
86
 
86
87
  useEffect(() => {
@@ -1,7 +1,7 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import React, { useContext } from 'react';
3
3
  import {
4
- Dimensions, Image, Modal, SafeAreaView, TouchableOpacity, View,
4
+ useWindowDimensions, Image, Modal, SafeAreaView, TouchableOpacity, View,
5
5
  } from 'react-native';
6
6
  import ImageZoom from 'react-native-image-pan-zoom';
7
7
  import Icon from 'react-native-vector-icons/FontAwesome';
@@ -13,7 +13,7 @@ export const LightBox = ({ visible, imageUri, closeModal }) => {
13
13
  const { COLORS, DARK_MODE } = theme;
14
14
  const styles = lightBoxStyles();
15
15
 
16
- const { width: screenWidth, height: screenHeight } = Dimensions.get('window');
16
+ const { width: screenWidth, height: screenHeight } = useWindowDimensions();
17
17
  const imageZoomHeight = screenHeight - 80;
18
18
 
19
19
  return (
@@ -1,6 +1,6 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import React, { useState } from 'react';
3
- import { TouchableOpacity } from 'react-native';
3
+ import { TouchableOpacity, useWindowDimensions } from 'react-native';
4
4
  import { getImageHeight } from '../../utils';
5
5
  import { LightBox } from '../LightBox';
6
6
  import { ResponsiveImage } from '../ResponsiveImage';
@@ -11,8 +11,9 @@ export const LightBoxImage = ({
11
11
  const {
12
12
  cdn, slug, metaData, imageWidth: previewWidth,
13
13
  } = data;
14
+ const screenWidth = useWindowDimensions().width;
14
15
  const { width, height } = metaData || {};
15
- const imageHeight = getImageHeight(width, height);
16
+ const imageHeight = getImageHeight(width, height, screenWidth);
16
17
  const imageUri = `${data?.cdn}/${data?.slug}`;
17
18
  const [showModal, setShowModal] = useState(false);
18
19
 
@@ -1,7 +1,7 @@
1
1
  import { get, throttle } from 'lodash';
2
2
  import PropTypes from 'prop-types';
3
3
  import React, { memo, useContext } from 'react';
4
- import { StyleSheet, TouchableOpacity, View } from 'react-native';
4
+ import { StyleSheet, TouchableOpacity, View, useWindowDimensions } from 'react-native';
5
5
  import PremiumIcons from '../../Icons/PremiumIcons/index';
6
6
  import {
7
7
  COMP_GENERAL_CONSTANTS,
@@ -36,8 +36,9 @@ const PrimaryStoryCardBase = (props) => {
36
36
  ]);
37
37
 
38
38
  const isPremiumStory = story['access'] === 'subscription';
39
-
40
39
  const throttledOnpress = throttle(props.onPress, 1000);
40
+ const screenWidth = useWindowDimensions().width;
41
+ const imageWidth = screenWidth - 2 * props.horizontalPadding;
41
42
 
42
43
  return (
43
44
  <>
@@ -51,7 +52,7 @@ const PrimaryStoryCardBase = (props) => {
51
52
  metaData={getImageMetadata(story)}
52
53
  slug={getImageSlug(story)}
53
54
  cdn={props.cdn}
54
- imageWidth={props.imageWidth}
55
+ imageWidth={imageWidth}
55
56
  >
56
57
  <View style={styles.storyTypeContainer}>
57
58
  <StoryTemplateIcon storyTemplate={story['story-template']} cardType="primary" theme={theme} />
@@ -89,7 +90,6 @@ const PrimaryStoryCardBase = (props) => {
89
90
 
90
91
  PrimaryStoryCardBase.propTypes = {
91
92
  cdn: PropTypes.string,
92
- imageWidth: PropTypes.number,
93
93
  headlineStyle: PropTypes.func,
94
94
  story: PropTypes.object.isRequired,
95
95
  onPress: PropTypes.func,
@@ -2,7 +2,7 @@ import get from 'lodash/get';
2
2
  import PropTypes from 'prop-types';
3
3
  import React, { useContext } from 'react';
4
4
  import { Text, View ,I18nManager} from 'react-native';
5
- import { getScreenPercentageWidth, AppTheme } from '../../utils/index';
5
+ import { AppTheme } from '../../utils/index';
6
6
  import { SecondaryStoryCard, ShareButton } from '../index';
7
7
 
8
8
  import { relatedStoriesStyles } from './styles';
@@ -42,7 +42,6 @@ export const RelatedStoriesCard = ({
42
42
  return <SecondaryStoryCard
43
43
  {...storyCardProps}
44
44
  iconComponent={<ShareButton story={secondaryStory} inListingStoryCard />}
45
- imageWidth={getScreenPercentageWidth(28)}
46
45
  horizontalPadding={4}
47
46
  />
48
47
  })}
@@ -2,17 +2,17 @@ import PropTypes from 'prop-types';
2
2
  import React, {
3
3
  memo, useCallback, useContext, useState,
4
4
  } from 'react';
5
- import { StyleSheet, View, ImageBackground } from 'react-native';
5
+ import { StyleSheet, View, ImageBackground, useWindowDimensions } from 'react-native';
6
6
  import FastImage from 'react-native-fast-image';
7
7
  import Icon from 'react-native-vector-icons/FontAwesome';
8
8
  import { FallbackIcon } from '../../Icons/FallBackIcon';
9
9
  import { AppTheme } from '../../utils';
10
10
  import {
11
11
  getImageURL,
12
- getCustomResolutionImageURL,
13
12
  } from '../../utils/imageUtils';
14
13
 
15
14
  const ResponsiveImageBase = (props) => {
15
+ const screenWidth = useWindowDimensions().width;
16
16
  const [placeholder, setPlaceholder] = useState(true);
17
17
  const { theme } = useContext(AppTheme);
18
18
  const {
@@ -61,7 +61,7 @@ const ResponsiveImageBase = (props) => {
61
61
  );
62
62
 
63
63
 
64
- let imageUrl = getImageURL(props)
64
+ let imageUrl = getImageURL(props, screenWidth);
65
65
 
66
66
  const userFallback = () => <Icon name="user" size={20} />;
67
67
 
@@ -78,7 +78,7 @@ const ResponsiveImageBase = (props) => {
78
78
  const onLoadHandler = useCallback(handleImageLoad, []);
79
79
 
80
80
  const lowestQualitySourceURI = {
81
- uri: decodeURIComponent(getImageURL(props,2)),
81
+ uri: decodeURIComponent(imageUrl),
82
82
  priority: FastImage.priority.high,
83
83
  }
84
84
 
@@ -7,6 +7,7 @@ import {
7
7
  View,
8
8
  TextStyle,
9
9
  TouchableOpacityProps,
10
+ useWindowDimensions,
10
11
  } from 'react-native';
11
12
  import {
12
13
  AppTheme,
@@ -43,8 +44,9 @@ const SecondaryStoryCardBase = (props) => {
43
44
  ]);
44
45
 
45
46
  const isPremiumStory = story['access'] === 'subscription';
46
-
47
47
  const throttledOnpress = throttle(props.onPress, 1000);
48
+ const screenWidth = useWindowDimensions().width;
49
+ const imageWidth = screenWidth * .28;
48
50
 
49
51
  return (
50
52
  <>
@@ -60,7 +62,7 @@ const SecondaryStoryCardBase = (props) => {
60
62
  metaData={getImageMetadata(story)}
61
63
  slug={getImageSlug(story) || ''}
62
64
  cdn={props.cdn || ''}
63
- imageWidth={props.imageWidth}
65
+ imageWidth={imageWidth}
64
66
  >
65
67
  <View style={styles.storyTypeContainer}>
66
68
  <StoryTemplateIcon storyTemplate={story['story-template']} theme={theme} />
@@ -98,7 +100,6 @@ const SecondaryStoryCardBase = (props) => {
98
100
 
99
101
  SecondaryStoryCardBase.propTypes = TouchableOpacityProps && {
100
102
  cdn: PropTypes.string.isRequired,
101
- imageWidth: PropTypes.number,
102
103
  headlineStyle: TextStyle,
103
104
  story: PropTypes.any.isRequired,
104
105
  iconComponent: PropTypes.element,
@@ -1,9 +1,8 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import React, { useContext } from 'react';
3
- import { View } from 'react-native';
3
+ import { View, useWindowDimensions } from 'react-native';
4
4
  import {
5
5
  AppTheme,
6
- getScreenPercentageWidth,
7
6
  stripHTML,
8
7
  } from '../../utils/index';
9
8
  import { Text } from '../index';
@@ -14,11 +13,12 @@ export const SlideshowStoryCard = ({ card, cdn }) => {
14
13
  const attribution = card['image-attribution'];
15
14
  const { title } = card;
16
15
  const { theme } = useContext(AppTheme);
17
- const styles = slideshowStoryCardStyles(theme);
16
+ const screenWidth = useWindowDimensions().width;
17
+ const styles = slideshowStoryCardStyles(theme, screenWidth);
18
18
  const imgData = {
19
19
  cdn,
20
20
  slug: card['image-s3-key'],
21
- imageWidth: getScreenPercentageWidth(100),
21
+ imageWidth: screenWidth,
22
22
  metaData: card['image-metadata'],
23
23
  };
24
24
 
@@ -1,8 +1,6 @@
1
- import { StyleSheet, Dimensions } from 'react-native';
1
+ import { StyleSheet } from 'react-native';
2
2
 
3
- const { width } = Dimensions.get('window');
4
-
5
- export const slideshowStoryCardStyles = ({ COLORS, FONT_FAMILY }) => StyleSheet.create({
3
+ export const slideshowStoryCardStyles = ({ COLORS, FONT_FAMILY }, screenWidth) => StyleSheet.create({
6
4
  textContainer: {
7
5
  paddingHorizontal: 10,
8
6
  flexDirection: 'column',
@@ -16,7 +14,7 @@ export const slideshowStoryCardStyles = ({ COLORS, FONT_FAMILY }) => StyleSheet.
16
14
  },
17
15
  container: {
18
16
  flexDirection: 'column',
19
- width,
17
+ width: screenWidth,
20
18
  },
21
19
  attributionText: {
22
20
  color: COLORS.BRAND_BLACK,
@@ -1,19 +1,27 @@
1
1
  import { hexToRgb } from '@quintype/native-components/src/utils/colorUtils';
2
2
  import PropTypes from 'prop-types';
3
- import React, { useContext, useEffect } from 'react';
4
- import { I18nManager, View } from 'react-native';
3
+ import React, { useContext, useEffect, useState, useFocusEffect } from 'react';
4
+ import { I18nManager, TouchableOpacity, View, StyleSheet, AppState } from 'react-native';
5
5
  import LinearGradient from "react-native-linear-gradient";
6
6
  import { ClockIcon } from '../../Icons/ClockIcon';
7
7
  import { AppTheme, getTimeInFormat } from '../../utils';
8
8
  import { isMiddleIndexOfArray } from '../../utils/arrayUtils';
9
- import { getFirstVideoElement, isStoryFree } from '../../utils/story';
9
+ import { getFirstVideoElement, isStoryFree, getStoryHeadline } from '../../utils/story';
10
+ import { getImageSlug } from '../../utils';
10
11
  import { STORY_TYPES } from '../../utils/story-types';
11
12
  import { FBCommentsRow } from '../FBCommentsRow';
12
13
  import { StoryContent } from '../StoryContent';
13
14
  import { StoryHeader } from '../StoryHeader';
14
15
  import { TagsRow } from '../TagsRow/TagsRow';
15
16
  import { ShareButton, Text } from '../index';
16
- import { storyStyles } from './styles';
17
+ import { storyStyles, modalStyles } from './styles';
18
+ import { Player } from '../AudioPlayer';
19
+ import Icon from 'react-native-vector-icons/AntDesign';
20
+ import TrackPlayer, { usePlaybackState, Capability, State, AppKilledPlaybackBehavior, useProgress } from "react-native-track-player";
21
+ import MaterialIcon from "react-native-vector-icons/MaterialCommunityIcons";
22
+ import FontAwesomeIcon from "react-native-vector-icons/FontAwesome";
23
+
24
+ import Modal from 'react-native-modal';
17
25
 
18
26
  const getLiveBlogTimeStamp = (card, DATE_FORMAT, story, styles, locale) => {
19
27
  const slug = `?cardId=${card.id}`;
@@ -140,12 +148,151 @@ export const Story = ({
140
148
  linkedStories,
141
149
  showWall,
142
150
  userObjectLength,
143
- numberOfVisibleStoryCard
151
+ numberOfVisibleStoryCard,
152
+ audioS3Key,
153
+ ttsButtonState,
154
+ setShowTTSPlayer,
155
+ gaTrigerredTTS
144
156
  }) => {
145
157
  const { theme } = useContext(AppTheme);
146
- const { COLORS, FONT_SIZE, locale, DARK_MODE } = theme;
147
- const styles = storyStyles(COLORS, FONT_SIZE);
158
+ const { COLORS, FONT_SIZE, locale, DARK_MODE,translate } = theme;
159
+ const styles = storyStyles(COLORS, FONT_SIZE, DARK_MODE);
160
+ const Modalstyles = modalStyles(COLORS, FONT_SIZE, DARK_MODE);
148
161
  const cards = story?.cards ?? [];
162
+ const [showModal, setShowModal] = useState(false);
163
+ const [audioRate, setAudioRate] = useState(1);
164
+ const playbackState = usePlaybackState();
165
+ const progress = useProgress();
166
+ const [isFinishedPlaying, setFinishedPlaying] = useState(false);
167
+
168
+
169
+ const setup = async () => {
170
+ //If TrackPlayer is not initialized, initialize it
171
+ try{
172
+ let activeTrack = await TrackPlayer.getActiveTrack();
173
+ } catch(err){
174
+ await TrackPlayer.setupPlayer({});
175
+ }
176
+
177
+ await TrackPlayer.updateOptions({
178
+ capabilities: [Capability.Play, Capability.Pause, Capability.Stop],
179
+ compactCapabilities: [Capability.Play, Capability.Pause],
180
+ notificationCapabilities: [Capability.Play, Capability.Pause, Capability.Stop],
181
+ });
182
+ };
183
+
184
+ const addTrack = async () => {
185
+ setFinishedPlaying(false)
186
+ let activeTrack = await TrackPlayer.getActiveTrack();
187
+ const storyAudioURL = `${cdn}/${audioS3Key}`;
188
+
189
+ if (!activeTrack || activeTrack?.id !== audioS3Key) {
190
+ await TrackPlayer.reset();
191
+ const headline = getStoryHeadline(story);
192
+
193
+ await TrackPlayer.add({
194
+ id: audioS3Key,
195
+ url: storyAudioURL,
196
+ title: headline,
197
+ album: cdn + "/" + getImageSlug(story),
198
+ artwork: cdn + "/" + getImageSlug(story),
199
+ });
200
+ }
201
+ };
202
+
203
+ const initialSetup = async () => {
204
+ await setup();
205
+ await addTrack();
206
+ };
207
+
208
+ React.useEffect(() => {
209
+ const unsubscribe = navigation.addListener('blur', async() => {
210
+ await TrackPlayer.pause();
211
+ });
212
+
213
+ const unsubscribe2 = navigation.addListener('focus', async() => {
214
+ addTrack();
215
+ })
216
+
217
+ const appStateListener = AppState.addEventListener('change', async (nextAppState) => {
218
+ if (nextAppState !== 'active') {
219
+ await TrackPlayer.pause();
220
+ }
221
+
222
+ });
223
+
224
+ return () => {
225
+ unsubscribe();
226
+ unsubscribe2();
227
+ };
228
+ }, [navigation]);
229
+
230
+
231
+
232
+ const resetPlayer = async () => {
233
+ setAudioRate(1);
234
+ setShowTTSPlayer(false);
235
+
236
+ await TrackPlayer.stop();
237
+ await TrackPlayer.setRate(1);
238
+ };
239
+
240
+ useEffect(() => {
241
+ return async() => await TrackPlayer.pause();
242
+ }, []);
243
+
244
+ useEffect(()=>{
245
+ if(progress?.duration < progress.position + 1 && progress.position !== 0){
246
+ setFinishedPlaying(true);
247
+ }
248
+ },[progress])
249
+
250
+
251
+
252
+ useEffect(() => {
253
+ if (audioS3Key) {
254
+ initialSetup();
255
+ }
256
+ }, [audioS3Key]);
257
+
258
+
259
+ const restartPlayer = async () => {
260
+ setFinishedPlaying(false);
261
+ await TrackPlayer.seekTo(0);
262
+ await TrackPlayer.play();
263
+ }
264
+
265
+ const togglePlayback = async () => {
266
+ console.log('risi - tts toggle playback', playbackState.state, TrackPlayer)
267
+ if (playbackState?.state === State.Playing) {
268
+ await TrackPlayer.pause();
269
+ } else {
270
+ await TrackPlayer.play();
271
+ }
272
+ };
273
+ const rewindOrForward = async (type) => {
274
+ const duration = await TrackPlayer.getProgress();
275
+
276
+ if (type === "rewind") {
277
+ await TrackPlayer.seekTo(duration.position - 10);
278
+ } else {
279
+ await TrackPlayer.seekTo(duration.position + 10);
280
+ }
281
+ };
282
+
283
+ const updateSpeedRate = async (rate) => {
284
+ await TrackPlayer.setRate(rate);
285
+ setAudioRate(rate);
286
+ setShowModal(false);
287
+ };
288
+
289
+ useEffect(()=>{
290
+ if(ttsButtonState && storyHasAccess === 'granted' && !showPlayer){
291
+ setShowPlayer(true)
292
+ togglePlayback()
293
+
294
+ }
295
+ },[ttsButtonState])
149
296
 
150
297
 
151
298
  const firstVideoElement = story['story-template'] === STORY_TYPES.VIDEO_STORY
@@ -198,6 +345,28 @@ export const Story = ({
198
345
  );
199
346
  };
200
347
 
348
+ const [showPlayer, setShowPlayer] = useState(false);
349
+ const closeButtonHandler = async() =>{
350
+ setFinishedPlaying(false);
351
+ setShowTTSPlayer(false);
352
+ setShowPlayer(false);
353
+ try{
354
+ await TrackPlayer.seekTo(0);
355
+ await resetPlayer();
356
+ }catch(err) {
357
+ console.log(err)
358
+ }
359
+ }
360
+
361
+ const ModalContent = ({rate, updateSpeedRate}) => {
362
+ return <Text
363
+ onPress={() => updateSpeedRate(rate)}
364
+ style={styles.textStyle}
365
+ >
366
+ {rate}
367
+ </Text>
368
+ }
369
+
201
370
  return (
202
371
  <>
203
372
  <View>
@@ -209,7 +378,33 @@ export const Story = ({
209
378
  onAuthorPress={onAuthorPress}
210
379
  onSectionPress={onSectionPress}
211
380
  />
212
-
381
+ { storyHasAccess === 'granted' && audioS3Key && (!showPlayer ?
382
+ (<TouchableOpacity onPress={async()=>{
383
+ gaTrigerredTTS({ slug: story.slug });
384
+ setShowPlayer(true)
385
+ await togglePlayback()
386
+ }}
387
+ style={styles.ttsStoryButtonStyle}
388
+ >
389
+ <MaterialIcon name='account-voice' size={FONT_SIZE.h2} color={COLORS.BRAND_BLACK}/>
390
+ <Text style={styles.ttsTextStyle}>{translate('Listen to this article')}</Text>
391
+ </TouchableOpacity>) :
392
+ (<View
393
+ style={styles.ttsPlayerContainer}
394
+ >
395
+ <Player
396
+ onTogglePlayback={togglePlayback}
397
+ seekTo={TrackPlayer.seekTo}
398
+ rewindOrForward={rewindOrForward}
399
+ setShowTTSPlayer={setShowPlayer}
400
+ setShowModal={setShowModal}
401
+ audioRate={audioRate}
402
+ resetPlayer={resetPlayer}
403
+ isFinishedPlaying={isFinishedPlaying}
404
+ closeButtonHandler={closeButtonHandler}
405
+ restart={restartPlayer}
406
+ />
407
+ </View>))}
213
408
 
214
409
 
215
410
  {getAd()}
@@ -247,10 +442,39 @@ export const Story = ({
247
442
  <View>
248
443
  <TagsRow tags={story.tags} onPress={onTagsPress} />
249
444
  </View>
445
+ <Modal
446
+ isVisible={showModal}
447
+ transparent={true}
448
+ onBackdropPress={() => setShowModal(false)}
449
+ style={Modalstyles.modalContainer}
450
+ swipeDirection="down"
451
+ onSwipeComplete={() => setShowModal(false)}
452
+ >
453
+ <View style={[Modalstyles.modalContent, styles.modalBackgound]}>
454
+ <View style={Modalstyles.header}>
455
+ <Text style={[Modalstyles.title, styles.textStyle]}>{translate("Playback Speed")}</Text>
456
+ <TouchableOpacity onPress={() => setShowModal(false)}>
457
+ <MaterialIcon name="close" size={25} color={styles?.textStyle?.color} />
458
+ </TouchableOpacity>
459
+ </View>
460
+ <View style={Modalstyles.modalBody}>
461
+ <ModalContent rate={0.25} updateSpeedRate={updateSpeedRate}/>
462
+ <ModalContent rate={0.5} updateSpeedRate={updateSpeedRate}/>
463
+ <ModalContent rate={0.75} updateSpeedRate={updateSpeedRate}/>
464
+ <ModalContent rate={1} updateSpeedRate={updateSpeedRate}/>
465
+ <ModalContent rate={1.25} updateSpeedRate={updateSpeedRate}/>
466
+ <ModalContent rate={1.55} updateSpeedRate={updateSpeedRate}/>
467
+ <ModalContent rate={1.75} updateSpeedRate={updateSpeedRate}/>
468
+ <ModalContent rate={2} updateSpeedRate={updateSpeedRate}/>
469
+ </View>
470
+ </View>
471
+ </Modal>
250
472
  </>
251
473
  );
252
474
  };
253
475
 
476
+
477
+
254
478
  Story.propTypes = {
255
479
  story: PropTypes.any.isRequired,
256
480
  cdn: PropTypes.string.isRequired,
@@ -1,6 +1,6 @@
1
1
  import { StyleSheet } from 'react-native';
2
2
 
3
- export const storyStyles = (COLORS, FONT_SIZE) => StyleSheet.create({
3
+ export const storyStyles = (COLORS, FONT_SIZE, DARK_MODE) => StyleSheet.create({
4
4
  container: {
5
5
  padding: 10,
6
6
  flexDirection: 'row',
@@ -39,5 +39,81 @@ export const storyStyles = (COLORS, FONT_SIZE) => StyleSheet.create({
39
39
  },
40
40
  overlay:{
41
41
  marginTop:-220
42
- }
42
+ },
43
+ modalBackgound: {
44
+ backgroundColor: COLORS.BRAND_WHITE,
45
+ position:'absolute',
46
+ bottom:0,
47
+ width:'100%',
48
+
49
+ },
50
+ textStyle: {
51
+ color: COLORS.BRAND_BLACK,
52
+ marginVertical: 10,
53
+ fontSize: FONT_SIZE.h3
54
+ },
55
+ ttsStoryButtonStyle:{
56
+ flexDirection:'row',
57
+ marginLeft:10,
58
+ alignItems:'center',
59
+ padding:10,
60
+ borderRadius:35,
61
+ paddingLeft:15,
62
+ alignSelf:'flex-start',
63
+ backgroundColor:COLORS.MONO6,
64
+ backgroundColor: DARK_MODE ? COLORS.MONO6 : COLORS.BRAND_WHITE,
65
+ elevation: 5,
66
+ shadowColor: COLORS.BRAND_BLACK,
67
+ shadowOffset: { width: 0, height: -1 },
68
+ shadowOpacity: 0.1,
69
+ shadowRadius: 1,
70
+ borderWidth:1,
71
+ borderColor: COLORS.MONO6,
72
+ marginBottom: 7},
73
+ ttsTextStyle:{marginLeft:10, fontSize:FONT_SIZE.h3, color:COLORS.BRAND_BLACK},
74
+ ttsPlayerContainer:{
75
+ width: "100%",
76
+ alignSelf: "center",
77
+ zIndex: 1,
78
+ marginBottom: 5,
79
+ marginVertical:10,
80
+
81
+ }
43
82
  });
83
+
84
+ export const modalStyles = (COLORS, FONT_SIZE, DARK_MODE) => StyleSheet.create({
85
+ container: {
86
+ flex: 1,
87
+ justifyContent: "center",
88
+ alignItems: "center",
89
+ backgroundColor:'green'
90
+ },
91
+ modalContainer: {
92
+ justifyContent: "flex-end",
93
+ margin: 0,
94
+ position:'absolute',
95
+ bottom:0,
96
+ width:'100%',
97
+ },
98
+ modalContent: {
99
+ borderTopLeftRadius: 15,
100
+ borderTopRightRadius: 15,
101
+ padding: 32,
102
+ },
103
+ header: {
104
+ flexDirection: "row",
105
+ justifyContent: "space-between",
106
+ alignItems: "center",
107
+ borderBottomWidth: 1,
108
+ borderBottomColor: COLORS.MONO5,
109
+ paddingBottom: 10,
110
+ },
111
+ title: {
112
+ fontSize: 18,
113
+ fontWeight: "bold",
114
+ },
115
+ modalBody: {
116
+ marginTop: 15,
117
+ fontSize: 16,
118
+ },
119
+ })
@@ -7,6 +7,7 @@ import {
7
7
  FlatList,
8
8
  TouchableOpacity,
9
9
  ScrollView,
10
+ useWindowDimensions,
10
11
  } from 'react-native';
11
12
  import Icon from 'react-native-vector-icons/FontAwesome';
12
13
  import FastImage from 'react-native-fast-image';
@@ -18,7 +19,8 @@ import { LightBoxImage } from '../LightBoxImage';
18
19
  export const StoryGallery = ({ cdn, card }) => {
19
20
  const { theme } = useContext(AppTheme);
20
21
  const { COLORS, DARK_MODE } = theme;
21
- const galleryStyles = styles(theme);
22
+ const screenDimensions = useWindowDimensions();
23
+ const galleryStyles = styles(theme, screenDimensions);
22
24
  const storyElements = card['story-elements'];
23
25
  const [showModal, setShowModal] = useState(false);
24
26
 
@@ -1,9 +1,9 @@
1
- import { StyleSheet, Dimensions } from 'react-native';
1
+ import { StyleSheet } from 'react-native';
2
2
  import { useContext } from 'react';
3
3
  import { AppTheme } from '../../utils';
4
4
 
5
- export const styles = ({ FONT_SIZE }) => {
6
- const { width: deviceWidth, height: deviceHeight } = Dimensions.get('window');
5
+ export const styles = ({ FONT_SIZE }, screenDimensions) => {
6
+ const { width: deviceWidth, height: deviceHeight } = screenDimensions;
7
7
  const { theme } = useContext(AppTheme);
8
8
  const { COLORS, DARK_MODE, FONT_FAMILY } = theme;
9
9
 
@@ -1,12 +1,11 @@
1
1
  import get from 'lodash/get';
2
2
  import PropTypes from 'prop-types';
3
3
  import React, { useContext } from 'react';
4
- import { TouchableOpacity, View } from 'react-native';
4
+ import { TouchableOpacity, useWindowDimensions, View } from 'react-native';
5
5
  import { COMP_CONTENT_CONSTANTS } from '../../constants/component-constants/content-constants/constants';
6
6
  import {
7
7
  AppTheme,
8
8
  getImageMetadata,
9
- getScreenPercentageWidth,
10
9
  getTimeInFormat
11
10
  } from '../../utils';
12
11
  import { STORY_TYPES } from '../../utils/story-types';
@@ -25,12 +24,14 @@ const getHeroImage = (cdn, story) => {
25
24
  const imageSlug = story['hero-image-s3-key'];
26
25
  if (!imageSlug) return null;
27
26
 
27
+ const screenWidth = useWindowDimensions().width;
28
+
28
29
  return (
29
30
  <ResponsiveImage
30
31
  cdn={cdn}
31
32
  metaData={getImageMetadata(story)}
32
33
  slug={imageSlug}
33
- imageWidth={getScreenPercentageWidth(100)}
34
+ imageWidth={screenWidth}
34
35
  />
35
36
  );
36
37
  };
@@ -1,8 +1,8 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import React, { useContext } from 'react';
3
- import { View } from 'react-native';
3
+ import { View, useWindowDimensions } from 'react-native';
4
4
  import { ShareButton } from '../index';
5
- import { AppTheme, getScreenPercentageWidth, stripHTML } from '../../utils';
5
+ import { AppTheme, stripHTML } from '../../utils';
6
6
  import { Text } from '../index';
7
7
  import { LightBoxImage } from '../LightBoxImage';
8
8
  import { storyImageStyles } from './styles';
@@ -13,15 +13,16 @@ export const StoryImage = ({
13
13
  const slug = `?cardId=${card.id}`;
14
14
  const sharePhotoCard = storyType === 'photo';
15
15
  const { theme } = useContext(AppTheme);
16
+ const screenWidth = useWindowDimensions().width;
16
17
 
17
18
  const imageData = {
18
19
  cdn,
19
20
  slug: card['image-s3-key'],
20
21
  metaData: card['image-metadata'],
21
- imageWidth: getScreenPercentageWidth(100),
22
+ imageWidth: screenWidth,
22
23
  };
23
24
 
24
- const styles = storyImageStyles(theme, imageData.metaData);
25
+ const styles = storyImageStyles(theme, imageData.metaData, screenWidth);
25
26
 
26
27
  return (
27
28
  <>
@@ -1,9 +1,9 @@
1
1
  import { StyleSheet } from 'react-native';
2
2
  import { getImageHeight } from '../../utils';
3
3
 
4
- export const storyImageStyles = ({ COLORS, FONT_SIZE, lineHeightMultiplier }, metadata = {}) => {
4
+ export const storyImageStyles = ({ COLORS, FONT_SIZE, lineHeightMultiplier }, metadata = {}, screenWidth) => {
5
5
  const { width, height } = metadata || {};
6
- const imageHeight = getImageHeight(width, height);
6
+ const imageHeight = getImageHeight(width, height, screenWidth);
7
7
 
8
8
  return StyleSheet.create({
9
9
  image: {
@@ -1,6 +1,6 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import React, { useContext, useRef, useState } from 'react';
3
- import { TouchableOpacity, View, FlatList } from 'react-native';
3
+ import { TouchableOpacity, View, FlatList, useWindowDimensions } from 'react-native';
4
4
  import Icon from 'react-native-vector-icons/AntDesign';
5
5
  import { AppTheme } from '../../utils';
6
6
  import { SlideshowStoryCard } from '../SlideshowStoryCard';
@@ -9,7 +9,8 @@ import { storySlideshowStyles } from './styles';
9
9
  export const StorySlideshow = ({ card, cdn }) => {
10
10
  const { theme } = useContext(AppTheme);
11
11
  const { COLORS } = theme;
12
- const styles = storySlideshowStyles(theme);
12
+ const screenWidth = useWindowDimensions().width;
13
+ const styles = storySlideshowStyles(theme, screenWidth);
13
14
  const [currentIndex, setCurrentTabIndex] = useState(0);
14
15
 
15
16
  const flatlistRef = useRef();
@@ -1,8 +1,6 @@
1
- import { StyleSheet, Dimensions } from 'react-native';
1
+ import { StyleSheet } from 'react-native';
2
2
 
3
- const { width } = Dimensions.get('window');
4
-
5
- export const storySlideshowStyles = ({ COLORS }) => StyleSheet.create({
3
+ export const storySlideshowStyles = ({ COLORS }, screenWidth) => StyleSheet.create({
6
4
  cardsContainer: {
7
5
  marginTop: 10,
8
6
  position: 'relative',
@@ -10,7 +8,7 @@ export const storySlideshowStyles = ({ COLORS }) => StyleSheet.create({
10
8
  leftArrow: {
11
9
  position: 'absolute',
12
10
  marginTop: -20,
13
- top: width * 0.28125, // width * 9/16 / 2
11
+ top: screenWidth * 0.28125, // screenWidth * 9/16 / 2
14
12
  left: 0,
15
13
  zIndex: 999,
16
14
  width: 40,
@@ -23,7 +21,7 @@ export const storySlideshowStyles = ({ COLORS }) => StyleSheet.create({
23
21
  rightArrow: {
24
22
  position: 'absolute',
25
23
  marginTop: -20,
26
- top: width * 0.28125, // width * 9/16 / 2
24
+ top: screenWidth * 0.28125, // screenWidth * 9/16 / 2
27
25
  right: 0,
28
26
  zIndex: 999,
29
27
  width: 40,
@@ -1,13 +1,13 @@
1
1
  import PropTypes from "prop-types";
2
2
  import React from "react";
3
- import { View, Dimensions } from "react-native";
3
+ import { View, useWindowDimensions } from "react-native";
4
4
  import { WebView } from "react-native-webview";
5
5
 
6
6
  export const YouTubePlayer = ({ card = {} }) => {
7
7
  const ytEmbedURL = card['embed-url'];
8
8
  if (!ytEmbedURL) return null;
9
9
 
10
- const windowWidth = Dimensions.get("window").width;
10
+ const windowWidth = useWindowDimensions().width;
11
11
  const styles = webviewStyles(windowWidth);
12
12
 
13
13
  const getYoutubeIframe = (ytEmbedURL) => {
@@ -40,7 +40,7 @@ export { IconText } from './IconText';
40
40
  export { CustomSwitch } from './CustomSwitch';
41
41
  export { RelatedStoriesCard } from './RelatedStoriesCard';
42
42
  export { References } from './References';
43
- export { StoryTemplateIcon } from './StoryTemplateIcon'
43
+ export { StoryTemplateIcon } from './StoryTemplateIcon';
44
44
  export { StoryCardDetailsRow } from './StoryCardDetailsRow';
45
- export { TextA } from './TextA'
46
- export { TextQ } from './TextQ'
45
+ export { TextA } from './TextA';
46
+ export { TextQ } from './TextQ';
@@ -1,11 +1,9 @@
1
1
  import { useContext } from 'react';
2
- import { PixelRatio, Dimensions } from 'react-native';
2
+ import { PixelRatio } from 'react-native';
3
3
  import { FocusedImage } from 'quintype-js';
4
4
  import get from 'lodash/get';
5
5
  import { AppTheme } from '.';
6
6
 
7
- const { width: deviceWidth } = Dimensions.get('window');
8
-
9
7
  /**
10
8
   |--------------------------------------------------
11
9
   | Gets a higher resolution image if you are on a high pixel density device.
@@ -40,28 +38,18 @@ export function getImageQuality() {
40
38
  return 30;
41
39
  }
42
40
 
43
- /**
44
-  |--------------------------------------------------
45
-  | Gets the percentage width based on device width
46
-  |--------------------------------------------------
47
-  */
48
-
49
- export function getScreenPercentageWidth(percentage) {
50
- return Math.round(0.01 * percentage * deviceWidth);
51
- }
52
-
53
41
  /**
54
42
   |--------------------------------------------------
55
43
   | Gets image height based on device width
56
44
   |--------------------------------------------------
57
45
   */
58
46
 
59
- export function getImageHeight(imageWidth, imageHeight) {
47
+ export function getImageHeight(imageWidth, imageHeight, screenWidth) {
60
48
  /* Return back a default size if either of the params are falsy */
61
49
  if (!imageHeight || !imageWidth) {
62
50
  return 250;
63
51
  }
64
- const ratio = deviceWidth / imageWidth;
52
+ const ratio = screenWidth / imageWidth;
65
53
  return imageHeight * ratio;
66
54
  }
67
55
 
@@ -105,7 +93,7 @@ export function getImageMetadata(story = {}) {
105
93
  /**
106
94
  * Returns an ImageURL
107
95
  */
108
- export const getImageURL = (props) => {
96
+ export const getImageURL = (props, screenWidth) => {
109
97
  const { theme } = useContext(AppTheme);
110
98
  const { IMAGE_QUALITY } = theme;
111
99
 
@@ -113,26 +101,9 @@ export const getImageURL = (props) => {
113
101
  aspectRatio, metaData, slug, imageWidth, cdn,
114
102
  } = props;
115
103
  const image = new FocusedImage(slug, metaData);
116
-
117
104
  const imageCdn = cdn || 'https://www.quintype.com';
118
105
  return `${imageCdn}/${image.path(aspectRatio || [16, 9], {
119
- w: getPixelRatioForDevice(imageWidth) || Math.round(deviceWidth),
120
- q: IMAGE_QUALITY,
121
- })}`;
122
- };
123
-
124
- export const getCustomResolutionImageURL = (props, customAspectRatio) => {
125
- const { theme } = useContext(AppTheme);
126
- const { IMAGE_QUALITY } = theme;
127
-
128
- const {
129
- metaData, slug, imageWidth, cdn,
130
- } = props;
131
- const image = new FocusedImage(slug, metaData);
132
-
133
- const imageCdn = cdn || 'https://www.quintype.com';
134
- return `${imageCdn}/${image.path(customAspectRatio, {
135
- w: getPixelRatioForDevice(imageWidth) || Math.round(deviceWidth),
106
+ w: getPixelRatioForDevice(imageWidth) || Math.round(screenWidth),
136
107
  q: IMAGE_QUALITY,
137
108
  })}`;
138
109
  };
@@ -0,0 +1,13 @@
1
+ import get from "lodash/get";
2
+ import { useNavigationState } from "@react-navigation/native";
3
+
4
+ export const getScreenCount = (screenName) => {
5
+ /* Note: To figure out if there are screen instances in the stack */
6
+ const navigationState = useNavigationState((state) => state) || {};
7
+ return get(navigationState, ["routes"], []).reduce((acc, route) => {
8
+ if (route.name === screenName) {
9
+ acc = acc + 1;
10
+ }
11
+ return acc;
12
+ }, 0);
13
+ };