@quintype/native-components 2.30.2 → 2.30.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quintype/native-components",
3
- "version": "2.30.2",
3
+ "version": "2.30.4",
4
4
  "description": "",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -23,7 +23,7 @@ const removeWidthnHeight = (htmlContent) => {
23
23
  if (temp[0] === '<iframe') {
24
24
  for (let i = 0; i < temp.length; i++) {
25
25
  if (
26
- (temp[i].includes('width') || temp[i].includes('height'))
26
+ (temp[i].includes('width=') || temp[i].includes('height='))
27
27
  && !temp[i].includes('/')
28
28
  ) {
29
29
  continue;
@@ -40,6 +40,7 @@ const getHTMLContent = (embedJs) => {
40
40
  const width = useWindowDimensions().width;
41
41
  const decodedContent = getDecodedContent(embedJs);
42
42
  let htmlContent = replaceDefaultProtocol(decodedContent);
43
+ htmlContent = removeWidthnHeight(htmlContent);
43
44
 
44
45
  const webViewScript = `
45
46
  <script type="application/javascript">
@@ -62,8 +63,22 @@ const getHTMLContent = (embedJs) => {
62
63
  <head>
63
64
  <meta name="viewport" content="width=device-width, initial-scale=1">
64
65
  <style>
65
- iframe{
66
- width:${width - 20}px;
66
+ * {
67
+ margin: 0;
68
+ padding: 0;
69
+ box-sizing: border-box;
70
+ }
71
+ body {
72
+ width: 100%;
73
+ overflow-x: hidden;
74
+ }
75
+ iframe {
76
+ width: 100% !important;
77
+ max-width: ${width - 20}px;
78
+ height: ${Math.round((width - 20) * 9 / 16)}px;
79
+ min-height: 200px;
80
+ display: block;
81
+ margin: 0 auto;
67
82
  }
68
83
  </style>
69
84
  </head>
@@ -93,44 +108,23 @@ export const JSEmbedElement = (props) => {
93
108
  setHeight(parseInt(event.nativeEvent.data));
94
109
  };
95
110
 
96
- // Function to manually extract the base URL from an iframe src
97
- const extractBaseUrlFromIframe = (iframeHtml) => {
98
- const regex = /src="([^"]+)"/; // Regex to extract src URL from iframe
99
- const match = iframeHtml.match(regex);
100
-
101
- if (match && match[1]) {
102
- const srcUrl = match[1]; // The full src URL from iframe
103
-
104
- // Manually extract the base URL (protocol + host + pathname)
105
- const urlPattern = /^(https?:\/\/[^/]+(?:\/[^?]*)?)/;
106
- const baseUrlMatch = srcUrl.match(urlPattern);
107
-
108
- if (baseUrlMatch) {
109
- return baseUrlMatch[1]; // Return the base URL
110
- } else {
111
- console.error('Invalid URL format.');
112
- return null;
113
- }
114
- } else {
115
- console.error('Iframe src not found.');
116
- return null;
117
- }
118
- };
119
-
120
111
  const constructSource = () => {
112
+ const html = getHTMLContent(props.element['embed-js']);
113
+
121
114
  return {
122
- html: getHTMLContent(props.element['embed-js']),
123
- baseUrl: extractBaseUrlFromIframe(getDecodedContent(props.element['embed-js'])),
115
+ html,
116
+ baseUrl: props.appReferer,
124
117
  };
125
118
  };
126
119
 
127
120
  if (height > 0) {
121
+ const calculatedHeight = Math.max(Number(height), Math.round((width - 20) * 9 / 16) + 20);
128
122
  return <View testID="embed-js">
129
123
  <WebView
130
124
  ref={webViewRef}
131
125
  style={{
132
126
  width,
133
- height: Math.min(Number(height), screenHeight-250),
127
+ height: Math.min(calculatedHeight, screenHeight - 100),
134
128
  flex: 0,
135
129
  opacity: 0.99,
136
130
  }}
@@ -160,7 +154,7 @@ const extractBaseUrlFromIframe = (iframeHtml) => {
160
154
  ref={webViewRef}
161
155
  style={{
162
156
  width,
163
- height: Number(height),
157
+ height: Math.max(Number(height), Math.round((width - 20) * 9 / 16) + 20),
164
158
  flex: 0,
165
159
  opacity: 0.99,
166
160
  }}
@@ -204,4 +198,5 @@ JSEmbedElement.propTypes = {
204
198
  height: PropTypes.number,
205
199
  orientation: PropTypes.string,
206
200
  }),
207
- };
201
+ appReferer: PropTypes.string,
202
+ };
@@ -79,6 +79,7 @@ const getStoryCards = (
79
79
  currentLayout,
80
80
  getAd,
81
81
  locale,
82
+ appReferer,
82
83
  ) => cards.map((card, index, source) => (
83
84
  <View key={card?.id}>
84
85
  {isLiveBlog
@@ -121,6 +122,7 @@ const getStoryCards = (
121
122
  story={story}
122
123
  storyType={storyType}
123
124
  currentLayout={currentLayout}
125
+ appReferer={appReferer}
124
126
  />
125
127
  </>
126
128
  );
@@ -152,7 +154,8 @@ export const Story = ({
152
154
  gaTrigerredTTS,
153
155
  commentData,
154
156
  commentLoader,
155
- storyLayout
157
+ storyLayout,
158
+ appReferer,
156
159
  }) => {
157
160
  const { theme } = useContext(AppTheme);
158
161
  const { COLORS, FONT_SIZE, locale, DARK_MODE,translate, enableComments } = theme;
@@ -376,6 +379,7 @@ export const Story = ({
376
379
  onAuthorPress={onAuthorPress}
377
380
  onSectionPress={onSectionPress}
378
381
  storyLayout={storyLayout}
382
+ appReferer={appReferer}
379
383
  />
380
384
  { storyHasAccess === 'granted' && audioS3Key && (!showPlayer ?
381
385
  (<TouchableOpacity onPress={async()=>{
@@ -427,6 +431,7 @@ export const Story = ({
427
431
  currentLayout,
428
432
  getAd,
429
433
  locale,
434
+ appReferer,
430
435
  )}
431
436
 
432
437
  {(!(isStoryFree(story) === 0 || storyHasAccess === "granted") && showWall) && <View style={styles.overlay} >
@@ -492,4 +497,5 @@ Story.propTypes = {
492
497
  enableFbComments: PropTypes.bool,
493
498
  currentLayout: PropTypes.any,
494
499
  navigation: PropTypes.any,
500
+ appReferer: PropTypes.string,
495
501
  };
@@ -18,6 +18,7 @@ export const StoryContent = ({
18
18
  story,
19
19
  storyType,
20
20
  currentLayout,
21
+ appReferer,
21
22
  }) => {
22
23
  const textProps = {
23
24
  text: storyElement.text,
@@ -78,7 +79,7 @@ export const StoryContent = ({
78
79
  />
79
80
  );
80
81
  case STORY_ELEMENT_TYPES.YOUTUBE_VIDEO:
81
- return <AllComponents.YouTubePlayer card={storyElement} />;
82
+ return <AllComponents.YouTubePlayer card={storyElement} appReferer={appReferer} />;
82
83
  case STORY_ELEMENT_TYPES.FILE:
83
84
  return <AllComponents.PDFReader card={storyElement} story={story} />;
84
85
  case STORY_ELEMENT_TYPES.DATA:
@@ -109,7 +110,7 @@ export const StoryContent = ({
109
110
  // }
110
111
  // default: break;
111
112
  // }
112
- return <AllComponents.JSEmbedElement element={storyElement} currentLayout={currentLayout} />;
113
+ return <AllComponents.JSEmbedElement element={storyElement} currentLayout={currentLayout} appReferer={appReferer} />;
113
114
  }
114
115
  default:
115
116
  return null;
@@ -125,4 +126,5 @@ StoryContent.propTypes = {
125
126
  screenList: PropTypes.object,
126
127
  navigation: PropTypes.shape({ }),
127
128
  currentLayout: PropTypes.any,
129
+ appReferer: PropTypes.string,
128
130
  };
@@ -37,7 +37,7 @@ const getHeroImage = (cdn, story) => {
37
37
  };
38
38
 
39
39
  const getHeroComponent = (props) => {
40
- const { story = {},firstVideoElement, cdn } = props;
40
+ const { story = {},firstVideoElement, cdn, appReferer } = props;
41
41
 
42
42
  switch (story['story-template']) {
43
43
  case STORY_TYPES.VIDEO_STORY: {
@@ -51,6 +51,7 @@ const getHeroComponent = (props) => {
51
51
  <YouTubePlayer
52
52
  styles={{ container: { padding: 0 } }}
53
53
  card={firstVideoElement}
54
+ appReferer={appReferer}
54
55
  />
55
56
  );
56
57
  }
@@ -182,4 +183,5 @@ StoryHeader.propTypes = {
182
183
  id: PropTypes.string,
183
184
  'embed-url': PropTypes.string,
184
185
  }),
186
+ appReferer: PropTypes.string,
185
187
  };
@@ -13,7 +13,7 @@ import { AppTheme } from '../../utils/context';
13
13
  import { storyTextStyles } from './styles';
14
14
 
15
15
  export const StoryText = (props) => {
16
- const {navigation} = props;
16
+ const { navigation } = props;
17
17
  const { theme, useDeeplinkHandler } = useContext(AppTheme);
18
18
  const {
19
19
  COLORS,
@@ -46,14 +46,13 @@ export const StoryText = (props) => {
46
46
  useDeeplinkHandler(href, navigation)
47
47
  }}
48
48
  listsPrefixesRenderers={{
49
- ul: () => <View style={customTagsStyles.ul} />,
49
+ ul: () => <View style={customTagsStyles['ul-bullet']} />,
50
50
  ol: (htmlAttribs, children, convertedCSSStyles, passProps) => {
51
51
  const { index } = passProps;
52
- const bulletNumber = htmlAttribs.start ? htmlAttribs.start : index + 1;
52
+ const bulletNumber = htmlAttribs.start ? parseInt(htmlAttribs.start) + index : index + 1;
53
53
  return (
54
- <Text style={customTagsStyles.ol}>
55
- {bulletNumber}
56
- )
54
+ <Text style={customTagsStyles['ol-number']}>
55
+ {bulletNumber})
57
56
  </Text>
58
57
  );
59
58
  },
@@ -63,6 +62,8 @@ export const StoryText = (props) => {
63
62
  ins: customTagsStyles.ins,
64
63
  p: customTagsStyles.p,
65
64
  li: customTagsStyles.li,
65
+ ul: customTagsStyles.ul,
66
+ ol: customTagsStyles.ol,
66
67
  a: customTagsStyles.a,
67
68
  h2: customTagsStyles.h,
68
69
  h3: customTagsStyles.h,
@@ -36,10 +36,31 @@ export const TextSummary = (props) => {
36
36
  onLinkPress={(evt, href) => {
37
37
  useDeeplinkHandler(href);
38
38
  }}
39
+ listsPrefixesRenderers={{
40
+ ul: () => <View style={customTagsStyles['ul-bullet']} />,
41
+ ol: (htmlAttribs, children, convertedCSSStyles, passProps) => {
42
+ const { index } = passProps;
43
+ const bulletNumber = htmlAttribs.start ? parseInt(htmlAttribs.start) + index : index + 1;
44
+ return (
45
+ <Text style={customTagsStyles['ol-number']}>
46
+ {bulletNumber})
47
+ </Text>
48
+ );
49
+ },
50
+ }}
39
51
  tagsStyles={{
40
52
  del: customTagsStyles.del,
41
53
  ins: customTagsStyles.ins,
42
54
  p: customTagsStyles.p,
55
+ li: customTagsStyles.li,
56
+ ul: customTagsStyles.ul,
57
+ ol: customTagsStyles.ol,
58
+ a: customTagsStyles.a,
59
+ h2: customTagsStyles.h,
60
+ h3: customTagsStyles.h,
61
+ h4: customTagsStyles.h,
62
+ h5: customTagsStyles.h,
63
+ h6: customTagsStyles.h,
43
64
  }}
44
65
  />
45
66
 
@@ -1,7 +1,7 @@
1
1
  import { StyleSheet } from 'react-native';
2
2
 
3
3
  export const titleElementStyles = (appThemeContext) => {
4
- const { COLORS } = appThemeContext;
4
+ const { COLORS, FONT_FAMILY } = appThemeContext;
5
5
  return StyleSheet.create({
6
6
  titleText: {
7
7
  fontSize: 20,
@@ -10,6 +10,7 @@ export const titleElementStyles = (appThemeContext) => {
10
10
  paddingRight: 10,
11
11
  paddingTop: 8,
12
12
  color: COLORS.BRAND_BLACK,
13
+ fontFamily: FONT_FAMILY.primaryBold,
13
14
  },
14
15
  });
15
16
  };
@@ -3,7 +3,7 @@ import React from "react";
3
3
  import { View, useWindowDimensions } from "react-native";
4
4
  import { WebView } from "react-native-webview";
5
5
 
6
- export const YouTubePlayer = ({ card = {} }) => {
6
+ export const YouTubePlayer = ({ card = {}, appReferer }) => {
7
7
  const ytEmbedURL = card['embed-url'];
8
8
  if (!ytEmbedURL) return null;
9
9
 
@@ -53,7 +53,10 @@ export const YouTubePlayer = ({ card = {} }) => {
53
53
  <WebView
54
54
  mediaPlaybackRequiresUserAction
55
55
  style={styles.webViewContainer}
56
- source={{ html: getYoutubeIframe(ytEmbedURL), baseUrl:'https://www.youtube.com'}}
56
+ source={{
57
+ html: getYoutubeIframe(ytEmbedURL),
58
+ baseUrl: appReferer,
59
+ }}
57
60
  javaScriptEnabled
58
61
  domStorageEnabled
59
62
  startInLoadingState
@@ -78,4 +81,5 @@ const webviewStyles = (windowWidth) => {
78
81
 
79
82
  YouTubePlayer.propTypes = {
80
83
  card: PropTypes.any.isRequired,
84
+ appReferer: PropTypes.string,
81
85
  };
@@ -26,25 +26,40 @@ export const customHTMLStyles = () => {
26
26
  opacity: 0.85,
27
27
  },
28
28
  li: {
29
- fontSize: FONT_SIZE.h3,
30
- lineHeight: FONT_SIZE.h3 * 1.5,
31
- marginTop: 8,
29
+ fontSize: FONT_SIZE.p1,
30
+ lineHeight: FONT_SIZE.p1 * 1.7,
31
+ marginBottom: -10,
32
32
  color: COLORS.BRAND_BLACK,
33
- opacity: 0.85,
33
+ opacity: 0.95,
34
34
  },
35
35
  ul: {
36
- height: 3,
37
- borderRadius: 20,
38
- marginTop: 24,
39
- marginRight: 8,
40
- padding: 3,
36
+ marginTop: 2,
37
+ marginBottom: 2,
38
+ marginLeft: 10
39
+ },
40
+ 'ul-bullet': {
41
+ width: 8,
42
+ height: 8,
43
+ borderRadius: 4,
41
44
  backgroundColor: COLORS.BRAND_BLACK,
45
+ marginTop: 20,
46
+ marginRight: 8,
47
+ alignSelf: 'flex-start',
42
48
  },
43
49
  ol: {
44
- marginTop: 16,
45
- marginRight: 4,
50
+ marginTop: 7,
51
+ marginBottom: 7,
52
+ marginLeft: 10
53
+ },
54
+ 'ol-number': {
55
+ fontSize: FONT_SIZE.p1,
56
+ lineHeight: FONT_SIZE.p1 * 1.7,
46
57
  color: COLORS.BRAND_BLACK,
47
58
  opacity: 0.85,
59
+ marginTop: 7,
60
+ marginRight: 8,
61
+ alignSelf: 'flex-start',
62
+ fontWeight: 'bold',
48
63
  },
49
64
  a: {
50
65
  marginTop: 7,
@@ -7,3 +7,4 @@ export * from './context';
7
7
  export * from './textUtils';
8
8
  export * from './testUtils';
9
9
  export * from './rtlUtil';
10
+ export * from './refererUtils';
@@ -0,0 +1,14 @@
1
+ import { Platform } from 'react-native';
2
+
3
+ /**
4
+ * Generates the app referer URL based on platform and bundle IDs
5
+ * @param {string} androidBundleId - Android package name (e.g., 'com.example.app')
6
+ * @param {string} iosBundleId - iOS bundle identifier (e.g., 'com.example.app.ios')
7
+ * @returns {string} The referer URL for the current platform
8
+ */
9
+ export const getAppReferer = (androidBundleId, iosBundleId) => {
10
+ return Platform.select({
11
+ ios: `https://${iosBundleId}`,
12
+ android: `https://${androidBundleId}`,
13
+ });
14
+ };