diff --git a/demo/index.html b/demo/index.html index 6eb3084..ae359b1 100644 --- a/demo/index.html +++ b/demo/index.html @@ -35,7 +35,28 @@ plugins: { uiManagers: {}, download: {} - } + }, + ui: { + // translations - for local environment + translations: { + en: { + download: { + download: 'Download', + downloads: 'Downloads', + download_has_started: 'Download has started', + download_has_failed: 'Download has failed', + attachments: 'Attachments', + download_button_label: 'Click to download the video', + select_quality_label: 'Select quality', + hide_label: 'Hide', + source_label: 'Source', + more_captions_label: 'More captions', + less_captions_label: 'Less captions', + attachments_label: 'Attachments' + }, + } + } + }, }; const player = KalturaPlayer.setup(config); diff --git a/demo/style.css b/demo/style.css index a56016f..6a01235 100644 --- a/demo/style.css +++ b/demo/style.css @@ -4,6 +4,6 @@ body { #player-placeholder { margin: 100px auto; - max-width: 640px; + max-width: 840px; aspect-ratio: 10 / 5.62; } diff --git a/src/components/download-overlay/download-overlay.scss b/src/components/download-overlay/download-overlay.scss index 5323ca2..7798b2c 100644 --- a/src/components/download-overlay/download-overlay.scss +++ b/src/components/download-overlay/download-overlay.scss @@ -1,68 +1,67 @@ @import '~@playkit-js/playkit-js-ui'; @import '../../theme.scss'; -.download-overlay { - -webkit-backdrop-filter: blur(16px); - backdrop-filter: blur(16px); - background-color: rgba(0, 0, 0, .7); - color: $tone-1-color; - height: 100%; - position: absolute; - width: 100%; - z-index: 2; - display: flex; - flex-direction: column; - - .header { - font-size: 25px; - font-weight: 700; - margin-top: 48px; - text-align: center; - - &.small, - &.medium { - font-size: 18px; - } - } +.header { + font-size: 32px; + font-weight: 500; + margin-top: 30px; + width: 100%; + display: flex; + justify-content: center; +} - .file-info-list { - margin: auto; - margin-top: 25px; - overflow: auto; - height: 100%; - width: 100%; +:global(.playkit-size-sm), +:global(.playkit-size-md), { + .header { + font-size: 20px; + } +} - .sources-captions-container { - margin-bottom: 24px; - } - - @include download-scrollbar(); - &:hover::-webkit-scrollbar-track, - &:hover::-webkit-scrollbar-thumb, { - visibility: visible; - } +.download-overlay { + height: 100%; + position: absolute; + width: 100%; + padding: 0 calc(100% / 9); + overflow-y: auto; - &.large { - max-width: 600px; - } + @include download-scrollbar(); + &:hover::-webkit-scrollbar-track, + &:hover::-webkit-scrollbar-thumb { + visibility: visible; + } - &.medium { - max-width: calc(100% - 48px); - } + .file-info-list { + margin: auto; + margin-top: 25px; + height: 100%; + width: 100%; - &.small { - max-width: calc(100% - 16px); - } + .sources-captions-container { + margin-bottom: 24px; } + } +} - .close-button-container { - position: absolute; - top: 36px; - right: 36px; +:global(.playkit-player.playkit-size-lg), +:global(.playkit-player.playkit-size-md), +:global(.playkit-player.playkit-size-sm), +:global(.playkit-player.playkit-size-xs), +:global(.playkit-player.playkit-size-ty) { + :global(.playkit-overlay.playkit-download-overlay) { + :global(.playkit-close-overlay) { + top: 15px !important; + right: 15px !important; + } - &.small { - top: 10px; - right:10px; - } + :global(.playkit-overlay-contents) { + padding: 0; + background-color: rgba(0, 0, 0, 0.7); + color: $tone-1-color; + text-align: initial; + overflow-y: initial; + :global(.playkit-title) { + margin: 0; + } } -} \ No newline at end of file + } +} diff --git a/src/components/download-overlay/download-overlay.tsx b/src/components/download-overlay/download-overlay.tsx index 3564bc3..591a15c 100644 --- a/src/components/download-overlay/download-overlay.tsx +++ b/src/components/download-overlay/download-overlay.tsx @@ -1,16 +1,17 @@ -import {Button, ButtonType, ButtonSize, A11yWrapper, OnClickEvent} from '@playkit-js/common'; import {DownloadPluginManager} from '../../download-plugin-manager'; import {createRef} from 'preact'; import {useState, useEffect} from 'preact/hooks'; import {DownloadMetadata} from '../../types'; import {ui} from '@playkit-js/kaltura-player-js'; +import {OverlayPortal} from '@playkit-js/common/dist/hoc/overlay-portal'; +const {Overlay} = ui.Components; + const {bindActions} = ui.utils; const overlayActions = ui.reducers.overlay.actions; const {withEventManager} = KalturaPlayer.ui.Event; -const {PLAYER_SIZE} = KalturaPlayer.ui.components; const {connect} = KalturaPlayer.ui.redux; const {withText} = KalturaPlayer.ui.preacti18n; @@ -24,7 +25,6 @@ import {DownloadEvent} from '../../event'; interface DownloadOverlayProps { downloadPluginManager: DownloadPluginManager; eventManager: any; - sizeClass?: string; downloadsLabel?: string; closeLabel?: string; setFocus: () => void; @@ -32,135 +32,81 @@ interface DownloadOverlayProps { updateOverlay: (isOpen: boolean) => void; } -const mapStateToProps = (state: any) => { - const { - shell: {playerSize} - } = state; - let sizeClass = ''; - - switch (playerSize) { - case PLAYER_SIZE.EXTRA_LARGE: - case PLAYER_SIZE.LARGE: { - sizeClass = styles.large; - break; - } - case PLAYER_SIZE.MEDIUM: { - sizeClass = styles.medium; - break; - } - case PLAYER_SIZE.SMALL: - case PLAYER_SIZE.EXTRA_SMALL: { - sizeClass = styles.small; - break; - } - default: { - break; - } - } - - return { - sizeClass - }; -}; - const DownloadOverlay = withText({ downloadsLabel: 'download.downloads', closeLabel: 'overlay.close' })( connect( - mapStateToProps, + null, bindActions(overlayActions) )( - withEventManager( - ({ - downloadPluginManager, - eventManager, - sizeClass, - downloadsLabel, - closeLabel, - setFocus, - downloadMetadata, - updateOverlay - }: DownloadOverlayProps) => { - const [isVisible, setIsVisible] = useState(false); - const closeButtonRef = createRef(); - const downloadConfig = downloadPluginManager.downloadPlugin.config; - useEffect(() => { - eventManager?.listen(downloadPluginManager, DownloadEvent.SHOW_OVERLAY, () => { - setIsVisible(true); - }); - - eventManager?.listen(downloadPluginManager, DownloadEvent.HIDE_OVERLAY, () => { - setIsVisible(false); - }); - }, []); - - const renderSources = () => { - return ( - - ); - }; - - const renderCaptions = () => { - return ( - - ); - }; - - const renderAttachments = () => { - return ; - }; - - const shouldRenderSources = downloadConfig.displaySources && (downloadMetadata!.flavors.length || downloadMetadata!.imageDownloadUrl); - const shouldRenderCaptions = downloadConfig.displayCaptions && downloadMetadata!.captions.length; - const shouldRenderAttachments = downloadConfig.displayAttachments && downloadMetadata!.attachments.length; + withEventManager(({downloadPluginManager, eventManager, downloadsLabel, downloadMetadata, updateOverlay}: DownloadOverlayProps) => { + const [isVisible, setIsVisible] = useState(false); + const closeButtonRef = createRef(); + const downloadConfig = downloadPluginManager.downloadPlugin.config; + useEffect(() => { + eventManager?.listen(downloadPluginManager, DownloadEvent.SHOW_OVERLAY, () => { + setIsVisible(true); + }); + + eventManager?.listen(downloadPluginManager, DownloadEvent.HIDE_OVERLAY, () => { + setIsVisible(false); + }); + }, []); + + const renderSources = () => { + return ( + + ); + }; - return isVisible ? ( - - - { - updateOverlay(false); - downloadPluginManager.setShowOverlay(false); - if (byKeyboard) { - setFocus(); - } - }}> - { - closeButtonRef.current = ref; - }} - /> - - - {downloadsLabel} - - {shouldRenderSources || shouldRenderCaptions ? ( - - {shouldRenderSources && renderSources()} - {shouldRenderCaptions && renderCaptions()} - - ) : undefined} - {shouldRenderAttachments && renderAttachments()} - - - ) : ( - + const renderCaptions = () => { + return ( + ); - } - ) + }; + + const renderAttachments = () => { + return ; + }; + + const shouldRenderSources = downloadConfig.displaySources && (downloadMetadata!.flavors.length || downloadMetadata!.imageDownloadUrl); + const shouldRenderCaptions = downloadConfig.displayCaptions && downloadMetadata!.captions.length; + const shouldRenderAttachments = downloadConfig.displayAttachments && downloadMetadata!.attachments.length; + + return isVisible ? ( + + {/*@ts-ignore*/} + { + updateOverlay(false); + downloadPluginManager.setShowOverlay(false); + }} + type="playkit-download"> + + {downloadsLabel} + + {shouldRenderSources || shouldRenderCaptions ? ( + + {shouldRenderSources && renderSources()} + {shouldRenderCaptions && renderCaptions()} + + ) : undefined} + {shouldRenderAttachments && renderAttachments()} + + + + + ) : null; + }) ) ); diff --git a/src/components/sources-list/sources-list.tsx b/src/components/sources-list/sources-list.tsx index 9b9633e..b6598a4 100644 --- a/src/components/sources-list/sources-list.tsx +++ b/src/components/sources-list/sources-list.tsx @@ -69,6 +69,10 @@ export const SourcesList = withText({ _setDefaultFlavor(); const _buildSourceDescription = (flavor: KalturaFlavorAsset): string => { + // flavor.height - 0 = audio file + if (flavor.height === 0) { + return flavor.language !== 'Undefined' ? flavor.language : ''; + } let flavorDescription = `${flavor.height}p`; if (flavor.height >= HeightResolution.UHD_4K) { flavorDescription += ` ${RESOLUTION_4K}`; @@ -81,8 +85,8 @@ export const SourcesList = withText({ return flavorDescription; }; - const _getPlayIcon = (): ComponentChildren => { - return ; + const _getPlayIcon = (flavor: KalturaFlavorAsset): ComponentChildren => { + return 0 ? IconType.Play : IconType.Audio} viewBox={`0 0 32 32`} />; }; const _getImageIcon = (): ComponentChildren => { @@ -117,7 +121,7 @@ export const SourcesList = withText({ `${fileName}.${flavor.fileExt}`, _buildSourceDescription(flavor), flavor.downloadUrl, - _getPlayIcon(), + _getPlayIcon(flavor), isDefault ); }; diff --git a/src/download.tsx b/src/download.tsx index 4d77b1e..00222d1 100644 --- a/src/download.tsx +++ b/src/download.tsx @@ -16,6 +16,8 @@ const {Text} = ui.preacti18n; const PRESETS = [ReservedPresetNames.Playback, ReservedPresetNames.Img, ReservedPresetNames.MiniAudioUI]; class Download extends KalturaPlayer.core.BasePlugin { + public displayName = 'Download'; + public svgIcon = {path: DOWNLOAD, viewBox: '0 0 32 32'}; static defaultConfig: DownloadConfig = { flavorId: null, flavorParamId: '0', // source @@ -28,6 +30,7 @@ class Download extends KalturaPlayer.core.BasePlugin { }; private iconId = -1; + private audioPlayerIconId = -1; private defaultToastDuration = 5 * 1000; private componentDisposers: Array = []; @@ -66,7 +69,11 @@ class Download extends KalturaPlayer.core.BasePlugin { }); } - showOverlay(): void { + public open(): void { + this.showOverlay(); + } + + private showOverlay(): void { this.downloadPluginManager.setShowOverlay(true); } @@ -91,11 +98,9 @@ class Download extends KalturaPlayer.core.BasePlugin { } if (this.store.getState().shell['activePresetName'] !== ReservedPresetNames.MiniAudioUI) { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore this.iconId = this.upperBarManager.add({ // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore + //@ts-expect-error - TS2353: Object literal may only specify known properties, and ariaLabel does not exist in type IconDto ariaLabel: (Download) as never, displayName: 'Download', order: 40, @@ -107,9 +112,12 @@ class Download extends KalturaPlayer.core.BasePlugin { return ; }, // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore presets: PRESETS.filter(presetName => presetName !== ReservedPresetNames.MiniAudioUI) }) as number; + } else { + const {displayName, svgIcon} = this; + // @ts-expect-error - TS2339: Property add does not exist on type Object + this.audioPlayerIconId = this.player.getService('AudioPluginsManager').add({displayName, svgIcon, onClick: e => this.open(e)}); } this.componentDisposers.push( @@ -130,7 +138,7 @@ class Download extends KalturaPlayer.core.BasePlugin { ); } - private shouldInjectUI(downloadMetadata: DownloadMetadata): boolean { + public isEntrySupported(downloadMetadata: DownloadMetadata): boolean { if (!downloadMetadata) return false; const {flavors, captions, attachments, imageDownloadUrl} = downloadMetadata; const {displayCaptions, displayAttachments, displaySources} = this.downloadPluginManager.downloadPlugin.config; @@ -145,7 +153,7 @@ class Download extends KalturaPlayer.core.BasePlugin { this.downloadPluginManager.setShowOverlay(false, false); const downloadMetadata = await this.downloadPluginManager.getDownloadMetadata(true); - if (this.shouldInjectUI(downloadMetadata)) { + if (this.isEntrySupported(downloadMetadata)) { this.logger.debug('Download is supported for current entry'); this.injectOverlayComponents(downloadMetadata); } @@ -158,7 +166,10 @@ class Download extends KalturaPlayer.core.BasePlugin { reset() { this.upperBarManager?.remove(this.iconId); + // @ts-expect-error - TS2339: Property add does not exist on type Object + this.player.getService('AudioPluginsManager').remove(this.audioPlayerIconId); this.iconId = -1; + this.audioPlayerIconId = -1; this._pluginButtonRef = null; this.triggeredByKeyboard = false; diff --git a/src/providers/response-types/kaltura-flavor-asset-list-response.ts b/src/providers/response-types/kaltura-flavor-asset-list-response.ts index 336eeb6..05d43ad 100644 --- a/src/providers/response-types/kaltura-flavor-asset-list-response.ts +++ b/src/providers/response-types/kaltura-flavor-asset-list-response.ts @@ -18,19 +18,16 @@ export class KalturaFlavorAssetListResponse extends BaseServiceResult { private setDataWithoutDuplicates(flavors: Array): Array { const data = []; // sort flavors by height and filter out flavors with height 0 - const sortedFlavors = flavors - .sort((a: {height: number}, b: {height: number}) => { - return a.height < b.height ? 1 : -1; - }) - .filter(flavor => { - return flavor.height > 0; - }); + const sortedFlavors = flavors.sort((a: {height: number}, b: {height: number}) => { + return b.height - a.height; + }); data.push(new KalturaFlavorAsset(sortedFlavors[0])); let previousFlavor = data[0]; for (let i = 1; i < sortedFlavors.length; i++) { const currentFlavor = sortedFlavors[i]; - if (previousFlavor.height !== currentFlavor.height) { + // Excluding audio file from filter (it's always 0) + if (previousFlavor.height !== currentFlavor.height || currentFlavor.height === 0) { data.push(new KalturaFlavorAsset(currentFlavor)); } previousFlavor = currentFlavor; diff --git a/src/providers/response-types/kaltura-flavor-asset.ts b/src/providers/response-types/kaltura-flavor-asset.ts index 8f22b54..2aaa6f9 100644 --- a/src/providers/response-types/kaltura-flavor-asset.ts +++ b/src/providers/response-types/kaltura-flavor-asset.ts @@ -4,6 +4,7 @@ export interface KalturaFlavorAssetArgs { flavorParamsId: number; isOriginal: boolean; height: number; + language: string; } export class KalturaFlavorAsset { @@ -13,6 +14,7 @@ export class KalturaFlavorAsset { isOriginal: boolean; downloadUrl: string; height: number; + language: string; constructor(flavorAsset: KalturaFlavorAssetArgs) { this.id = flavorAsset.id; @@ -21,5 +23,6 @@ export class KalturaFlavorAsset { this.isOriginal = flavorAsset.isOriginal; this.downloadUrl = ''; this.height = flavorAsset.height; + this.language = flavorAsset.language; } } diff --git a/webpack.config.js b/webpack.config.js index f051a77..ad1aa37 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -34,7 +34,13 @@ module.exports = { { test: /\.scss$/, use: [ - 'style-loader', + { + loader: 'style-loader', + options: { + attributes: {id: `${packageData.name}`}, + injectType: "singletonStyleTag" + } + }, { loader: 'css-loader', options: {