@brightcove/components-embed-code-modal 0.8.1 → 0.8.3

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 (164) hide show
  1. package/.eslintignore +7 -0
  2. package/.eslintrc +23 -0
  3. package/.husky/pre-commit +4 -0
  4. package/.nvmrc +1 -0
  5. package/.prettierignore +7 -0
  6. package/.prettierrc +5 -0
  7. package/.release-it.json +40 -0
  8. package/.whitesource +3 -0
  9. package/CHANGELOG.md +342 -0
  10. package/CODEOWNERS +37 -0
  11. package/PULL_REQUEST_TEMPLATE.md +17 -0
  12. package/__tests__/EmbedCode.test.tsx +51 -0
  13. package/__tests__/InteractivityProject.test.tsx +50 -0
  14. package/__tests__/PlayerPreview.test.tsx +23 -0
  15. package/__tests__/TabsHeader.test.tsx +19 -0
  16. package/__tests__/TabsSection.test.tsx +46 -0
  17. package/__tests__/TitleWithTooltip.test.tsx +45 -0
  18. package/__tests__/VideoPlayer.test.tsx +38 -0
  19. package/__tests__/util.test.ts +89 -0
  20. package/babel.config.json +17 -0
  21. package/etc/wildcard.brightcove.com.key +27 -0
  22. package/etc/wildcard.brightcove.com.pem +96 -0
  23. package/jest/jest.setup.js +62 -0
  24. package/jest/jest.stub.js +4 -0
  25. package/jest.config.js +24 -0
  26. package/package.json +15 -5
  27. package/scripts/create-dist-pkg-prod.js +18 -0
  28. package/src/index.ts +16 -0
  29. package/src/js/EmbedCodeModal.tsx +88 -0
  30. package/src/js/components/CustomSettingsDropdown.tsx +184 -0
  31. package/src/js/components/EmbedCopySection.tsx +130 -0
  32. package/src/js/components/ModalContainer.tsx +274 -0
  33. package/src/js/components/NoPlayerModal.tsx +42 -0
  34. package/src/js/components/PlayerPreview.tsx +116 -0
  35. package/src/js/components/TabsHeader.tsx +31 -0
  36. package/src/js/components/TabsSection.tsx +74 -0
  37. package/src/js/components/TitleWithTooltip.tsx +39 -0
  38. package/src/js/components/VideoLinks.tsx +83 -0
  39. package/src/js/components/VideoPlayer.tsx +303 -0
  40. package/src/js/components/{index.d.ts → index.ts} +0 -1
  41. package/src/js/constants/baseUrls.ts +4 -0
  42. package/src/js/constants/embed.ts +12 -0
  43. package/src/js/constants/player.ts +32 -0
  44. package/src/js/constants/pluginsRegistry.ts +30 -0
  45. package/src/js/hooks/useGetPlayers.ts +12 -0
  46. package/src/js/i18n.ts +43 -0
  47. package/src/js/services/players-api.ts +26 -0
  48. package/src/js/services/url-shortener.ts +10 -0
  49. package/src/js/types/EmbedCodeModalProps.ts +72 -0
  50. package/src/js/types/EmbedCodeProps.ts +13 -0
  51. package/src/js/types/brightcoveEmbedCode.d.ts +18 -0
  52. package/src/js/types/players.ts +64 -0
  53. package/src/js/types/react-i18next.d.ts +8 -0
  54. package/src/js/types/studioModule.ts +7 -0
  55. package/src/js/utils/addPluginsDataToPlayers.ts +59 -0
  56. package/src/js/utils/call.ts +31 -0
  57. package/src/js/utils/dimensions.ts +53 -0
  58. package/src/js/utils/featureSwitches.ts +16 -0
  59. package/src/js/utils/util.ts +153 -0
  60. package/src/module.tsx +246 -0
  61. package/src/styles/CustomSettingsDropdown.sass +42 -0
  62. package/src/styles/EmbedCode.sass +30 -0
  63. package/src/styles/EmbedCodeModal.sass +76 -0
  64. package/src/styles/base.sass +1 -0
  65. package/src/styles/theme.sass +11 -0
  66. package/src/styles/typings.td.ts +9 -0
  67. package/src/translations/en.json +53 -0
  68. package/src/translations/es.json +53 -0
  69. package/src/translations/fr.json +53 -0
  70. package/src/translations/ja.json +53 -0
  71. package/src/translations/ko.json +53 -0
  72. package/src/translations/zh.json +53 -0
  73. package/src/types/studio.ts +197 -0
  74. package/tsconfig.json +34 -0
  75. package/webpack.config.js +97 -0
  76. package/__tests__/EmbedCode.test.d.ts +0 -2
  77. package/__tests__/EmbedCode.test.d.ts.map +0 -1
  78. package/__tests__/InteractivityProject.test.d.ts +0 -2
  79. package/__tests__/InteractivityProject.test.d.ts.map +0 -1
  80. package/__tests__/PlayerPreview.test.d.ts +0 -2
  81. package/__tests__/PlayerPreview.test.d.ts.map +0 -1
  82. package/__tests__/PlayersDropdown.test.d.ts +0 -2
  83. package/__tests__/PlayersDropdown.test.d.ts.map +0 -1
  84. package/__tests__/TabsHeader.test.d.ts +0 -2
  85. package/__tests__/TabsHeader.test.d.ts.map +0 -1
  86. package/__tests__/TabsSection.test.d.ts +0 -2
  87. package/__tests__/TabsSection.test.d.ts.map +0 -1
  88. package/__tests__/TitleWithTooltip.test.d.ts +0 -2
  89. package/__tests__/TitleWithTooltip.test.d.ts.map +0 -1
  90. package/__tests__/VideoPlayer.test.d.ts +0 -2
  91. package/__tests__/VideoPlayer.test.d.ts.map +0 -1
  92. package/__tests__/util.test.d.ts +0 -2
  93. package/__tests__/util.test.d.ts.map +0 -1
  94. package/index.js +0 -56
  95. package/index.js.map +0 -1
  96. package/src/index.d.ts +0 -5
  97. package/src/index.d.ts.map +0 -1
  98. package/src/js/EmbedCodeModal.d.ts +0 -17
  99. package/src/js/EmbedCodeModal.d.ts.map +0 -1
  100. package/src/js/components/ActivateInteractivityModal.d.ts +0 -3
  101. package/src/js/components/ActivateInteractivityModal.d.ts.map +0 -1
  102. package/src/js/components/CustomSettingsDropdown.d.ts +0 -11
  103. package/src/js/components/CustomSettingsDropdown.d.ts.map +0 -1
  104. package/src/js/components/EmbedCopySection.d.ts +0 -4
  105. package/src/js/components/EmbedCopySection.d.ts.map +0 -1
  106. package/src/js/components/ModalContainer.d.ts +0 -17
  107. package/src/js/components/ModalContainer.d.ts.map +0 -1
  108. package/src/js/components/NoPlayerModal.d.ts +0 -8
  109. package/src/js/components/NoPlayerModal.d.ts.map +0 -1
  110. package/src/js/components/PlayerPreview.d.ts +0 -4
  111. package/src/js/components/PlayerPreview.d.ts.map +0 -1
  112. package/src/js/components/PlayersDropdown.d.ts +0 -9
  113. package/src/js/components/PlayersDropdown.d.ts.map +0 -1
  114. package/src/js/components/TabsHeader.d.ts +0 -11
  115. package/src/js/components/TabsHeader.d.ts.map +0 -1
  116. package/src/js/components/TabsSection.d.ts +0 -15
  117. package/src/js/components/TabsSection.d.ts.map +0 -1
  118. package/src/js/components/TitleWithTooltip.d.ts +0 -8
  119. package/src/js/components/TitleWithTooltip.d.ts.map +0 -1
  120. package/src/js/components/VideoLinks.d.ts +0 -9
  121. package/src/js/components/VideoLinks.d.ts.map +0 -1
  122. package/src/js/components/VideoPlayer.d.ts +0 -17
  123. package/src/js/components/VideoPlayer.d.ts.map +0 -1
  124. package/src/js/components/index.d.ts.map +0 -1
  125. package/src/js/constants/baseUrls.d.ts +0 -5
  126. package/src/js/constants/baseUrls.d.ts.map +0 -1
  127. package/src/js/constants/embed.d.ts +0 -9
  128. package/src/js/constants/embed.d.ts.map +0 -1
  129. package/src/js/constants/player.d.ts +0 -27
  130. package/src/js/constants/player.d.ts.map +0 -1
  131. package/src/js/constants/pluginsRegistry.d.ts +0 -7
  132. package/src/js/constants/pluginsRegistry.d.ts.map +0 -1
  133. package/src/js/hooks/useGetPlayers.d.ts +0 -3
  134. package/src/js/hooks/useGetPlayers.d.ts.map +0 -1
  135. package/src/js/i18n.d.ts +0 -330
  136. package/src/js/i18n.d.ts.map +0 -1
  137. package/src/js/services/players-api.d.ts +0 -5
  138. package/src/js/services/players-api.d.ts.map +0 -1
  139. package/src/js/services/url-shortener.d.ts +0 -4
  140. package/src/js/services/url-shortener.d.ts.map +0 -1
  141. package/src/js/types/EmbedCodeModalProps.d.ts +0 -59
  142. package/src/js/types/EmbedCodeModalProps.d.ts.map +0 -1
  143. package/src/js/types/EmbedCodeProps.d.ts +0 -13
  144. package/src/js/types/EmbedCodeProps.d.ts.map +0 -1
  145. package/src/js/types/players.d.ts +0 -58
  146. package/src/js/types/players.d.ts.map +0 -1
  147. package/src/js/types/studioModule.d.ts +0 -8
  148. package/src/js/types/studioModule.d.ts.map +0 -1
  149. package/src/js/utils/addPluginsDataToPlayers.d.ts +0 -6
  150. package/src/js/utils/addPluginsDataToPlayers.d.ts.map +0 -1
  151. package/src/js/utils/call.d.ts +0 -14
  152. package/src/js/utils/call.d.ts.map +0 -1
  153. package/src/js/utils/dimensions.d.ts +0 -9
  154. package/src/js/utils/dimensions.d.ts.map +0 -1
  155. package/src/js/utils/featureSwitches.d.ts +0 -2
  156. package/src/js/utils/featureSwitches.d.ts.map +0 -1
  157. package/src/js/utils/util.d.ts +0 -67
  158. package/src/js/utils/util.d.ts.map +0 -1
  159. package/src/module.d.ts +0 -2
  160. package/src/module.d.ts.map +0 -1
  161. package/src/styles/typings.td.d.ts +0 -13
  162. package/src/styles/typings.td.d.ts.map +0 -1
  163. package/src/types/studio.d.ts +0 -202
  164. package/src/types/studio.d.ts.map +0 -1
@@ -0,0 +1,116 @@
1
+ import React, { useMemo } from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import cx from 'classnames';
4
+ import { Hideable } from '@brightcove/studio-components';
5
+ import ReactPlayerLoader from '@brightcove/react-player-loader';
6
+
7
+ import {
8
+ getPreviewPlayerUrl,
9
+ getUrlBase,
10
+ getVideoPreviewLink,
11
+ } from 'js/utils/util';
12
+ import {
13
+ bcHostedPlugins,
14
+ CAMPAIGN_PLUGIN_NAME,
15
+ VIEWER_ID_KEY_NAME,
16
+ BC_MAP_TRACKING_NAME,
17
+ } from 'js/constants/pluginsRegistry';
18
+ import { PlayerPayload } from '../types/EmbedCodeModalProps';
19
+
20
+ import { TabsSection, VideoLinks } from 'js/components';
21
+
22
+ import css from 'styles/EmbedCodeModal.sass';
23
+
24
+ interface Plugin {
25
+ name: string;
26
+ options?: Record<string, unknown>;
27
+ }
28
+
29
+ export const PlayerPreview = ({
30
+ id,
31
+ configuration,
32
+ accountId = '',
33
+ embedCodeProperties,
34
+ isOutstreamPlayer,
35
+ }: PlayerPayload) => {
36
+ const { t } = useTranslation();
37
+ const previewPlayerUrl = getPreviewPlayerUrl(accountId, id);
38
+ const playerUrl = getVideoPreviewLink({ accountId, playerId: id });
39
+
40
+ const {
41
+ hasCustomPlugins,
42
+ isCampaignPlayer,
43
+ isViewerIdSource,
44
+ isBcMapTracking,
45
+ } = useMemo((): {
46
+ isCampaignPlayer: boolean;
47
+ hasCustomPlugins: boolean;
48
+ isViewerIdSource: boolean;
49
+ isBcMapTracking: boolean;
50
+ } => {
51
+ let hasBCHostedPlugin = false;
52
+ let isCampaignPlayer = false;
53
+ let isViewerIdSource = false;
54
+ let isBcMapTracking = false;
55
+ let plugins: Plugin[] = [];
56
+
57
+ // TODO: refactor with addPluginsDataToPlayers function to reuse code
58
+ if (configuration) {
59
+ plugins = (configuration.plugins as Plugin[]) ?? plugins;
60
+ for (const plugin of plugins) {
61
+ const { name } = plugin;
62
+ hasBCHostedPlugin = bcHostedPlugins.includes(name);
63
+ isCampaignPlayer =
64
+ isCampaignPlayer || plugin.name === CAMPAIGN_PLUGIN_NAME;
65
+ isBcMapTracking =
66
+ isBcMapTracking || plugin.name === BC_MAP_TRACKING_NAME;
67
+ }
68
+ isViewerIdSource =
69
+ (configuration[VIEWER_ID_KEY_NAME] as boolean) || false;
70
+ }
71
+
72
+ return {
73
+ hasCustomPlugins: !hasBCHostedPlugin && plugins.length > 0,
74
+ isCampaignPlayer,
75
+ isViewerIdSource,
76
+ isBcMapTracking,
77
+ };
78
+ }, [configuration]);
79
+
80
+ return (
81
+ <>
82
+ <div className={css.leftContent}>
83
+ <ReactPlayerLoader
84
+ accountId={accountId}
85
+ baseUrl={getUrlBase()}
86
+ attrs={{ className: css.playerLoader }}
87
+ embedType='iframe'
88
+ refNode='player-container'
89
+ playerUrl={previewPlayerUrl}
90
+ />
91
+ <Hideable show={hasCustomPlugins}>
92
+ <span className={css.customPluginNotice}>
93
+ {t('customPluginNotice')}
94
+ </span>
95
+ </Hideable>
96
+ {isOutstreamPlayer ? null : (
97
+ <VideoLinks previewUrl={previewPlayerUrl} playerUrl={playerUrl} />
98
+ )}
99
+ </div>
100
+ <div
101
+ className={cx(css.rightContent, {
102
+ [css.rightContentFullWidth]: !!isOutstreamPlayer,
103
+ })}
104
+ >
105
+ <TabsSection
106
+ isCampaign={isCampaignPlayer}
107
+ isViewerIdSource={isViewerIdSource}
108
+ isBcMapTracking={isBcMapTracking}
109
+ playerId={id}
110
+ accountId={accountId}
111
+ embedCodeProperties={embedCodeProperties}
112
+ />
113
+ </div>
114
+ </>
115
+ );
116
+ };
@@ -0,0 +1,31 @@
1
+ import React from 'react';
2
+ import { Flex, Tabs, TabList, Tab } from '@brightcove/studio-components';
3
+ import { TabsSelectedId } from 'js/types/players';
4
+
5
+ interface TabsHeaderProps {
6
+ currentTab: TabsSelectedId;
7
+ handleTabChange: () => void;
8
+ iframeLabel: string;
9
+ jsLabel: string;
10
+ }
11
+ export const TabsHeader = ({
12
+ currentTab,
13
+ handleTabChange,
14
+ iframeLabel,
15
+ jsLabel,
16
+ }: TabsHeaderProps) => {
17
+ return (
18
+ <Flex justifyContent='space-between' alignItems='baseline'>
19
+ <Tabs selectedId={currentTab} onSelect={handleTabChange}>
20
+ <TabList>
21
+ <Tab tabId='iframe' testName={'iframe-tab'}>
22
+ {iframeLabel}
23
+ </Tab>
24
+ <Tab tabId='javascript' testName={'js-tab'}>
25
+ {jsLabel}
26
+ </Tab>
27
+ </TabList>
28
+ </Tabs>
29
+ </Flex>
30
+ );
31
+ };
@@ -0,0 +1,74 @@
1
+ import React, { useState } from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { TabPanel } from '@brightcove/studio-components';
4
+ import { TabsSelectedId } from 'js/types/players';
5
+ import css from 'styles/EmbedCodeModal.sass';
6
+ import { TabsHeader, EmbedCode } from 'js/components';
7
+ import { EmbedCodeProperties } from 'js/types/EmbedCodeModalProps';
8
+
9
+ export const TabsSection = ({
10
+ isCampaign,
11
+ isViewerIdSource,
12
+ isBcMapTracking,
13
+ ...rest
14
+ }: {
15
+ playerId: string;
16
+ isCampaign: boolean;
17
+ isViewerIdSource: boolean;
18
+ isBcMapTracking: boolean;
19
+ videoId?: string;
20
+ accountId: string;
21
+ interactivityProjectId?: string;
22
+ livePlaybackToken?: string;
23
+ adConfigId?: string;
24
+ embedCodeProperties?: EmbedCodeProperties;
25
+ }) => {
26
+ const { t } = useTranslation();
27
+ const [currentTab, setCurrentTab] = useState<TabsSelectedId>('iframe');
28
+
29
+ const isIframe = currentTab === 'iframe';
30
+
31
+ const handleTabChange = (id?: string | number) => setCurrentTab(id);
32
+
33
+ return (
34
+ <>
35
+ <TabsHeader
36
+ currentTab={currentTab}
37
+ handleTabChange={handleTabChange}
38
+ jsLabel={t('tabs.labels.javascript')}
39
+ iframeLabel={t('tabs.labels.iframe')}
40
+ />
41
+ <TabPanel
42
+ testName='embed-tab-content'
43
+ className={css.tabPanelContent}
44
+ render={() => {
45
+ if (isIframe) {
46
+ if (isCampaign) {
47
+ return (
48
+ <span className={css.redHelperText}>
49
+ {t('tabs.helperTextWarning')}
50
+ </span>
51
+ );
52
+ } else if (isViewerIdSource) {
53
+ return (
54
+ <span className={css.redHelperText}>
55
+ {t('tabs.viewerIdTextWarning')}
56
+ </span>
57
+ );
58
+ } else if (isBcMapTracking) {
59
+ return (
60
+ <span className={css.redHelperText}>
61
+ {t('tabs.bcMapTrackingTextWarning')}
62
+ </span>
63
+ );
64
+ } else {
65
+ return <EmbedCode iframe={isIframe} {...rest} />;
66
+ }
67
+ } else {
68
+ return <EmbedCode iframe={isIframe} {...rest} />;
69
+ }
70
+ }}
71
+ />
72
+ </>
73
+ );
74
+ };
@@ -0,0 +1,39 @@
1
+ import React, { useEffect, useMemo, useState } from 'react';
2
+ import { Flex, ToolTip } from '@brightcove/studio-components';
3
+ import css from 'styles/EmbedCodeModal.sass';
4
+ import { truncateVideoTitle } from '../utils/util';
5
+
6
+ interface TitleWithTooltipProps {
7
+ name: string;
8
+ id: string;
9
+ }
10
+ export const TitleWithTooltip = ({ name, id }: TitleWithTooltipProps) => {
11
+ const [isOverflowing, setIsOverflowing] = useState(false);
12
+
13
+ const titleMemo = useMemo(
14
+ () => (name ? truncateVideoTitle(name) : ''),
15
+ [name],
16
+ );
17
+
18
+ useEffect(() => {
19
+ if (name) {
20
+ setIsOverflowing(titleMemo !== name);
21
+ }
22
+ }, [titleMemo, name]);
23
+
24
+ return (
25
+ <Flex flexDirection='column' className={css.mediaData}>
26
+ <ToolTip
27
+ placement='top'
28
+ portal
29
+ block
30
+ content={name}
31
+ active={isOverflowing}
32
+ testName='embed-video-tooltip'
33
+ >
34
+ <div className={css.mediaTitle}>{titleMemo}</div>
35
+ </ToolTip>
36
+ <div className={css.mediaId}>{id}</div>
37
+ </Flex>
38
+ );
39
+ };
@@ -0,0 +1,83 @@
1
+ import React, { useCallback, useState } from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { Button, Loader } from '@brightcove/studio-components';
4
+ import css from 'styles/EmbedCodeModal.sass';
5
+ import { shortenUrl } from '../services/url-shortener';
6
+ import { getBrightcove } from 'js/utils/util';
7
+
8
+ interface VideoLinksProps {
9
+ previewUrl: string;
10
+ playerUrl: string;
11
+ }
12
+
13
+ export const VideoLinks = ({ previewUrl, playerUrl }: VideoLinksProps) => {
14
+ const { t } = useTranslation();
15
+ const [isGetUrlLoading, setIsGetUrlLoading] = useState<boolean>(false);
16
+
17
+ const copyPreviewURL = useCallback(
18
+ async (link: string) => {
19
+ setIsGetUrlLoading(true);
20
+ getUrlAndAddItToClipboard(link)
21
+ .then(() => {
22
+ getBrightcove().Toaster.success({
23
+ title: t('toasterTitle'),
24
+ message: t('toasterGetURLSuccess'),
25
+ });
26
+ })
27
+ .catch(() => {
28
+ getBrightcove().Toaster.error({
29
+ message: t('toasterGetURLError'),
30
+ });
31
+ })
32
+ .finally(() => setIsGetUrlLoading(false));
33
+ },
34
+ [t],
35
+ );
36
+ return (
37
+ <div>
38
+ <div className={css.getURLBtnContainer}>
39
+ <Button
40
+ look='tertiary'
41
+ text={t('getURL')}
42
+ testName='get-url-btn'
43
+ icon={isGetUrlLoading ? '' : 'link'}
44
+ iconRight
45
+ onClick={() => copyPreviewURL(playerUrl)}
46
+ />
47
+ {isGetUrlLoading && (
48
+ <Loader className={css.getURLBtnSpinner} size='inline' color='navy' />
49
+ )}
50
+ </div>
51
+ <Button
52
+ look='tertiary'
53
+ text={t('previewButton')}
54
+ testName='preview-player-btn'
55
+ icon='external_link'
56
+ iconRight
57
+ onClick={() => {
58
+ window.open(previewUrl, '_blank');
59
+ }}
60
+ />
61
+ </div>
62
+ );
63
+ };
64
+
65
+ export const getUrlAndAddItToClipboard = async (url: string) => {
66
+ const escapedLongUrl = encodeURI(url);
67
+ // safari
68
+ try {
69
+ return navigator.clipboard.write([
70
+ new ClipboardItem({
71
+ // eslint-disable-next-line no-async-promise-executor
72
+ 'text/plain': new Promise(async (resolve) => {
73
+ const shortUrl = await shortenUrl({ longUrl: escapedLongUrl });
74
+ resolve(new Blob([shortUrl], { type: 'text/plain' }));
75
+ }),
76
+ }),
77
+ ]);
78
+ } catch {
79
+ // chrome and firefox
80
+ const shortUrl = await shortenUrl({ longUrl: escapedLongUrl });
81
+ return navigator.clipboard.writeText(shortUrl);
82
+ }
83
+ };
@@ -0,0 +1,303 @@
1
+ import React, { useEffect, useState, useMemo, useCallback } from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import ReactPlayerLoader from '@brightcove/react-player-loader';
4
+ import {
5
+ Checkbox,
6
+ Hideable,
7
+ Input,
8
+ PlayerSelect,
9
+ } from '@brightcove/studio-components';
10
+ import {
11
+ VideoPayload,
12
+ ProjectPayload,
13
+ EmbedCodeModalTypes,
14
+ EmbedCodeProperties,
15
+ LivePayload,
16
+ } from 'js/types/EmbedCodeModalProps';
17
+ import {
18
+ PlayerSelectItem,
19
+ PlayersObject,
20
+ PlayersObjectItem,
21
+ } from 'js/types/players';
22
+ import css from 'styles/EmbedCodeModal.sass';
23
+ import {
24
+ getUrlBase,
25
+ getVideoPreviewLink,
26
+ PREVIEW_URL_BASE,
27
+ VideoPreviewLinkOptions,
28
+ } from 'js/utils/util';
29
+ import {
30
+ VideoLinks,
31
+ TitleWithTooltip,
32
+ TabsSection,
33
+ CustomSettingsDropdown,
34
+ } from 'js/components';
35
+ import { DEFAULT_PLAYER_ID } from 'js/constants/player';
36
+ import { EMBED_DEFAULT } from 'js/constants/embed';
37
+ import { getFavoritePlayer } from 'js/utils/featureSwitches';
38
+ import cx from 'classnames';
39
+
40
+ export const VideoPlayer = ({
41
+ video,
42
+ embedCodeModalType,
43
+ playerListForSelection,
44
+ players,
45
+ hasCreatedPlayer,
46
+ embedCodeProperties,
47
+ showDVR,
48
+ onDVRClick,
49
+ dvrTime,
50
+ showLowLatency,
51
+ onLowLatencyClick,
52
+ }: {
53
+ video: VideoPayload | ProjectPayload | LivePayload;
54
+ embedCodeModalType: EmbedCodeModalTypes;
55
+ playerListForSelection: PlayerSelectItem[];
56
+ players: PlayersObject;
57
+ hasCreatedPlayer?: boolean;
58
+ embedCodeProperties?: EmbedCodeProperties;
59
+ showDVR?: boolean;
60
+ onDVRClick?: (newValue: boolean) => void;
61
+ dvrTime?: number;
62
+ showLowLatency?: boolean;
63
+ onLowLatencyClick?: (newValue: boolean) => void;
64
+ }) => {
65
+ const { t } = useTranslation();
66
+ const [player, setPlayer] = useState<PlayersObjectItem>();
67
+ const [previewUrl, setPreviewUrl] = useState<string>('');
68
+ const [embedProperties, setEmbedProperties] = useState<EmbedCodeProperties>(
69
+ embedCodeProperties ? embedCodeProperties : EMBED_DEFAULT,
70
+ );
71
+ const [allowLowLatency, setAllowLowLatency] = useState(true);
72
+ const [allowDVR, setAllowDVR] = useState(!showLowLatency);
73
+ const [time, setTime] = useState<number>(dvrTime || 0);
74
+
75
+ useEffect(() => {
76
+ setTime(dvrTime || 0);
77
+ }, [dvrTime]);
78
+
79
+ useEffect(() => {
80
+ if (playerListForSelection.length === 0) return;
81
+ const favoritePlayer = getFavoritePlayer();
82
+ const player = players[favoritePlayer];
83
+
84
+ if (
85
+ playerListForSelection.find((selection) => selection.value === player?.id)
86
+ ) {
87
+ setPlayer(player);
88
+ } else {
89
+ setPlayer(players[playerListForSelection[0].value]);
90
+ }
91
+ // eslint-disable-next-line react-hooks/exhaustive-deps
92
+ }, [playerListForSelection]);
93
+
94
+ const onPlayerSelectChange = (id: string) => {
95
+ const player = players[id];
96
+ setPlayer(player);
97
+ };
98
+
99
+ const interactivityProjectId = useMemo(() => {
100
+ return embedCodeModalType === EmbedCodeModalTypes.PROJECT
101
+ ? (video as ProjectPayload).interactivityProjectId
102
+ : null;
103
+ }, [video, embedCodeModalType]);
104
+
105
+ const onEmbedCreated = useCallback(
106
+ (el: HTMLElement) => {
107
+ if (interactivityProjectId) {
108
+ el.setAttribute(
109
+ 'data-interactivity-project-id',
110
+ interactivityProjectId,
111
+ );
112
+ }
113
+ },
114
+ [interactivityProjectId],
115
+ );
116
+
117
+ const sharedProps: {
118
+ accountId: string;
119
+ playerId: string;
120
+ isCampaign: boolean;
121
+ isViewerIdSource: boolean;
122
+ isBcMapTracking: boolean;
123
+ videoId?: string;
124
+ interactivityProjectId?: string;
125
+ livePlaybackToken?: string;
126
+ adConfigId?: string;
127
+ } = {
128
+ accountId: video.accountId,
129
+ playerId:
130
+ player?.id ||
131
+ (playerListForSelection.length > 0
132
+ ? playerListForSelection[0].value
133
+ : DEFAULT_PLAYER_ID),
134
+ isCampaign: player?.hasCampaignPlugin || false,
135
+ isViewerIdSource: player?.hasViewerIDSource || false,
136
+ isBcMapTracking: player?.hasBcMapTracking || false,
137
+ videoId: video.videoId,
138
+ };
139
+
140
+ const name = interactivityProjectId
141
+ ? (video as ProjectPayload).interactivityProjectName
142
+ : (video as VideoPayload).videoName;
143
+ const id = interactivityProjectId || video.videoId;
144
+
145
+ if (interactivityProjectId) {
146
+ sharedProps.interactivityProjectId = interactivityProjectId;
147
+ }
148
+
149
+ const { livePlaybackToken, adConfigId } = video as LivePayload;
150
+
151
+ if (livePlaybackToken) {
152
+ sharedProps.livePlaybackToken = livePlaybackToken;
153
+ }
154
+
155
+ if (adConfigId) {
156
+ sharedProps.adConfigId = adConfigId;
157
+ }
158
+
159
+ const {
160
+ adConfigId: sharedAdConfigId,
161
+ livePlaybackToken: sharedLivePlaybackToken,
162
+ ...restSharedProps
163
+ } = sharedProps;
164
+
165
+ const playerProps = {
166
+ ...restSharedProps,
167
+ ...(sharedAdConfigId ? {} : { adConfigId: sharedAdConfigId }),
168
+ ...(sharedLivePlaybackToken
169
+ ? {}
170
+ : { livePlaybackToken: sharedLivePlaybackToken }),
171
+ };
172
+
173
+ useEffect(() => {
174
+ if (player?.id) {
175
+ const options: VideoPreviewLinkOptions = {
176
+ accountId: video.accountId,
177
+ playerId: player.id,
178
+ videoId: video.videoId,
179
+ };
180
+ if (interactivityProjectId) {
181
+ options.interactivityProjectId = interactivityProjectId;
182
+ }
183
+
184
+ if (adConfigId) {
185
+ options.adConfigId = adConfigId;
186
+ }
187
+
188
+ if (livePlaybackToken) {
189
+ options.livePlaybackToken = livePlaybackToken;
190
+ }
191
+
192
+ setPreviewUrl(getVideoPreviewLink(options));
193
+ }
194
+ }, [player, video, interactivityProjectId, adConfigId, livePlaybackToken]);
195
+
196
+ return (
197
+ <>
198
+ <div className={css.leftContent}>
199
+ <PlayerSelect
200
+ label={t('player')}
201
+ tooltip={
202
+ <>
203
+ <div>{t('tooltipTextNew')}</div>
204
+ <a href={t('learnmore')} target='_blank' rel='noreferrer'>
205
+ {t('tooltipLink')}
206
+ </a>
207
+ </>
208
+ }
209
+ selectedPlayer={player?.id || DEFAULT_PLAYER_ID}
210
+ players={playerListForSelection}
211
+ onChange={onPlayerSelectChange}
212
+ inputClassName={css.playerSelect}
213
+ testName='embed-player-select'
214
+ />
215
+ {hasCreatedPlayer ? (
216
+ <iframe
217
+ src={`${PREVIEW_URL_BASE()}/${sharedProps.accountId}/players/${
218
+ sharedProps.playerId
219
+ }/preview/embeds/default/master/index.html?interactivityProjectId=${
220
+ sharedProps.interactivityProjectId
221
+ }&videoId=${sharedProps.videoId}`}
222
+ allowFullScreen
223
+ allow='autoplay;encrypted-media;fullscreen'
224
+ width='539'
225
+ height='303.2'
226
+ data-interactivity-project-id={interactivityProjectId}
227
+ ></iframe>
228
+ ) : (
229
+ <ReactPlayerLoader
230
+ {...playerProps}
231
+ baseUrl={getUrlBase()}
232
+ attrs={{ className: css.playerLoader }}
233
+ embedType='iframe'
234
+ refNode='player-container'
235
+ onEmbedCreated={onEmbedCreated}
236
+ />
237
+ )}
238
+ <Hideable show={player?.hasCustomPlugins}>
239
+ <span className={css.customPluginNotice}>
240
+ {t('customPluginNotice')}
241
+ </span>
242
+ </Hideable>
243
+ <VideoLinks previewUrl={previewUrl} playerUrl={previewUrl} />
244
+ </div>
245
+ <div
246
+ className={cx(css.rightContent, {
247
+ [css.expandRightContent]: showDVR,
248
+ })}
249
+ >
250
+ <TitleWithTooltip name={name} id={id} />
251
+ {(embedCodeModalType === EmbedCodeModalTypes.VIDEO ||
252
+ embedCodeModalType === EmbedCodeModalTypes.PROJECT ||
253
+ embedCodeModalType === EmbedCodeModalTypes.LIVE) && (
254
+ <CustomSettingsDropdown
255
+ setEmbedProperties={setEmbedProperties}
256
+ embedProperties={embedProperties}
257
+ />
258
+ )}
259
+ <TabsSection {...sharedProps} embedCodeProperties={embedProperties} />
260
+ {showLowLatency ? (
261
+ <Checkbox
262
+ disabled={showDVR && allowDVR}
263
+ checked={allowLowLatency}
264
+ onChange={() => {
265
+ onLowLatencyClick?.(!allowLowLatency);
266
+ setAllowLowLatency(!allowLowLatency);
267
+ }}
268
+ className={css.dvrCheckbox}
269
+ testName='low-latency-checkbox'
270
+ >
271
+ {t('lowLatency')}
272
+ </Checkbox>
273
+ ) : null}
274
+ {showDVR && (
275
+ <div>
276
+ <Checkbox
277
+ disabled={showLowLatency && allowLowLatency}
278
+ checked={allowDVR}
279
+ onChange={() => {
280
+ onDVRClick?.(!allowDVR);
281
+ setAllowDVR(!allowDVR);
282
+ }}
283
+ className={css.dvrCheckbox}
284
+ testName='dvr-checkbox'
285
+ >
286
+ {t('dvr.allowDVR')}
287
+ </Checkbox>
288
+ {allowDVR && (
289
+ <Input
290
+ className={css.timeInput}
291
+ label={t('dvr.inputLabel')}
292
+ value={time}
293
+ description={t('dvr.inputDescription')}
294
+ disabled
295
+ testName='dvr-time-input'
296
+ />
297
+ )}
298
+ </div>
299
+ )}
300
+ </div>
301
+ </>
302
+ );
303
+ };
@@ -7,4 +7,3 @@ export * from './VideoLinks';
7
7
  export * from './VideoPlayer';
8
8
  export * from './PlayerPreview';
9
9
  export * from './CustomSettingsDropdown';
10
- //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,4 @@
1
+ export const QA_URL = 'https://players.qa.brightcove.net/';
2
+ export const PROD_URL = 'https://players.brightcove.net/';
3
+ export const QA_PREVIEW_URL = 'https://preview-players.qa.brightcove.net';
4
+ export const PROD_PREVIEW_URL = 'https://preview-players.brightcove.net';
@@ -0,0 +1,12 @@
1
+ import {
2
+ EmbedCodeAspectRatio,
3
+ EmbedCodeUnits,
4
+ } from 'js/types/EmbedCodeModalProps';
5
+
6
+ export const EMBED_DEFAULT = {
7
+ responsive: false,
8
+ width: 960,
9
+ height: 540,
10
+ units: EmbedCodeUnits.PX,
11
+ aspectRatio: EmbedCodeAspectRatio.CUSTOM,
12
+ };
@@ -0,0 +1,32 @@
1
+ export const DEFAULT_PLAYER_ID = 'default';
2
+ export const DEFAULT_PLAYER_NAME = 'Brightcove Default Player';
3
+
4
+ export const PLAYER_LIST_FOR_SELECTION = [
5
+ {
6
+ label: DEFAULT_PLAYER_NAME,
7
+ value: DEFAULT_PLAYER_ID,
8
+ },
9
+ ];
10
+
11
+ export const FAVORITE_PLAYER_SETTING = 'favorite_player_id';
12
+
13
+ export const PLAYERS = {
14
+ default: {
15
+ hasCustomPlugins: false,
16
+ id: DEFAULT_PLAYER_ID,
17
+ hasCampaignPlugin: false,
18
+ label: DEFAULT_PLAYER_NAME,
19
+ hasInteractivityPlugin: false,
20
+ hasViewerIDSource: false,
21
+ hasBcMapTracking: false,
22
+ },
23
+ };
24
+
25
+ export const DEFAULT_INTERACTIVITY_PLAYER = {
26
+ name: 'Interactivity Player',
27
+ registry_id: '@brightcove/videojs-interactivity-viewer',
28
+ version: '2.x',
29
+ options: {
30
+ mobilefullscreen: true,
31
+ },
32
+ };