UNPKG

activator-oce-exporter

Version:

Extract Activator binder and convert it to valid OCE mono pacakge

600 lines (544 loc) 18.1 kB
import { html } from '@polymer/lit-element'; import { FusionBase } from '../../base'; import { FusionLogger } from '../../services/fusion-logger'; import { getValueObject, resetPlayer } from '../../utils'; import { applyMixins, ModeTrackable, SlideComponent } from '../../mixins'; const iconsConfig = { pause: 'M18 12L0 24V0', play: 'M0 0h6v24H0zM12 0h6v24h-6z', volumeLow: 'M14.667 0v2.747c3.853 1.146 6.666 4.72 6.666 8.946 0 4.227-2.813 7.787-6.666 8.934v2.76C20 22.173 24 17.4 24 11.693 24 5.987 20 1.213 14.667 0zM18 11.693c0-2.36-1.333-4.386-3.333-5.373v10.707c2-.947 3.333-2.987 3.333-5.334zm-18-4v8h5.333L12 22.36V1.027L5.333 7.693H0z', volumeAverage: 'M0 7.667v8h5.333L12 22.333V1L5.333 7.667M17.333 11.373C17.333 9.013 16 6.987 14 6v10.707c2-.947 3.333-2.987 3.333-5.334z', volumeHigh: 'M0 7.667v8h5.333L12 22.333V1L5.333 7.667', }; class FusionAudioPlayer extends applyMixins(FusionBase, [SlideComponent, ModeTrackable]) { constructor() { super(); this.sliderMinWidth = 65; } static get options() { return { componentName: 'fusion-audio-player', componentType: 'dynamic', componentUIName: 'Audio Player', componentScope: 'standard', componentCategory: 'media', componentDescription: 'Container for audio files handling playback and states', componentDomain: 'slide', isTextEdit: false, isRootNested: true, nestedTypes: [], nestedComponents: [], defaultTemplate: '', fileExtensions: ['mp3', 'wav'], resizable: 'all', draggable: 'xy', rotatable: true, sortable: false, }; } static get properties() { return { src: { type: String, fieldType: 'Modal', value: ' ', prop: true, assetType: 'Audio', }, ...super.properties, width: { type: String, fieldType: 'Number', value: '410px', }, 'background-color': { type: String, fieldType: 'ColorPicker', value: 'rgb(240, 240, 240)', }, 'main-color': { type: String, fieldType: 'ColorPicker', value: 'rgb(97, 114, 142)', }, 'additional-color': { type: String, fieldType: 'ColorPicker', value: 'rgb(68, 191, 163)', }, 'show-volume-handler': { type: Boolean, fieldType: 'Boolean', value: true, prop: true, }, 'show-progress-slider': { type: Boolean, fieldType: 'Boolean', value: true, prop: true, }, 'show-current-time': { type: Boolean, fieldType: 'Boolean', value: false, prop: true, }, 'show-total-time': { type: Boolean, fieldType: 'Boolean', value: true, prop: true, }, 'show-volume': { type: Boolean, fieldType: 'Boolean', value: true, prop: true, }, autoplay: { type: Boolean, fieldType: 'Boolean', value: true, prop: true, }, }; } getAudioPlayerPart() { return { 'show-progress-slider': this.progressControls, 'show-current-time': this.currentTime, 'show-total-time': this.totalTime, 'show-volume': this.volumeButton, }; } editorModeChanged(isEditMode) { if (isEditMode && this.audio) { resetPlayer(this.audio); } } updateAudioPlayerPartStyle() { const playerParts = this.getAudioPlayerPart(); Object.keys(playerParts).forEach((item) => { const toggleAudioPlayerPart = this.getAttribute(item) ? 'showAudioPlayerPart' : 'hideAudioPlayerPart'; return FusionAudioPlayer[toggleAudioPlayerPart](playerParts[item]); }); } updateWidthByPropChanges() { const sliderWidth = this.getCurrentSliderWidth(); const actualMinWidth = this.getActualInnerMinWidth(sliderWidth); const { num, unit } = getValueObject(this.width); if (num < actualMinWidth) { this.setElementProp('width', `${actualMinWidth}${unit}`); this.setAttribute('width', `${actualMinWidth}${unit}`); } } update(changedProps) { super.update(changedProps); if (this.isRendered) { this.updateAudioPlayerPartStyle(); this.updateWidthByPropChanges(); if (changedProps.has('src')) this.togglePlayButtonStyle(); if (FusionAudioPlayer.isVolumeControls(changedProps)) this.updateVolumeControls(changedProps); } } static isVolumeControls(changedProps) { return changedProps.has('show-volume-handler') || changedProps.has('show-volume'); } togglePlayButtonStyle() { const path = this.getAttribute('src'); const audioExtension = FusionAudioPlayer.options.fileExtensions; const isPathExists = audioExtension.includes(path.split('.').pop()); const method = isPathExists ? 'remove' : 'add'; this.playPauseButton.classList[method]('disabled'); } updateVolumeControls(changedProps) { const propertyNames = Array.from(changedProps.keys()); const methods = this.getControlsMethods(); const controlName = FusionAudioPlayer.getControlsName(propertyNames); return methods[controlName](); } static getControlsName(props) { return props.find(item => item === 'show-volume-handler' || item === 'show-volume'); } getControlsMethods() { return { 'show-volume-handler': () => this.updateVolumeHandler(), 'show-volume': () => this.updateVolumeControlClasses(), }; } updateVolumeHandler() { this['show-volume-handler'] ? this.volumeAdjust() : this.updateVolumeButtonIcon(); this.updateVolumeControlClasses(); } updateVolumeControlClasses() { this.volumeButton.classList.remove('open'); this.volumeControls.classList.add('hidden'); } setProp(num, unit) { const actualMinWidth = this.audioPlayer ? this.getActualInnerMinWidth(this.sliderMinWidth) : num; const width = Math.max(num, actualMinWidth); this.setElementProp('width', `${width}${unit}`); } getCurrentSliderWidth() { const padding = FusionAudioPlayer.getElementPadding(this.progressControls); return this.progressControls.offsetWidth - padding; } static getElementPadding(element) { const { paddingLeft, paddingRight } = window.getComputedStyle(element); return parseFloat(paddingLeft) + parseFloat(paddingRight); } getActualInnerMinWidth(value) { const padding = FusionAudioPlayer.getElementPadding(this.audioPlayer); const width = this.getInnerElementsWidth(value); return padding + width; } getInnerElementsWidth(value) { const initialWidth = 0; const sliderMinWidth = this.progressControls.classList.contains('hidden') ? initialWidth : value; const elements = [this.playPauseButton, this.currentTime, this.totalTime, this.volumeButton]; const innerElementsWidth = [sliderMinWidth, ...elements.map(item => item.offsetWidth)]; return innerElementsWidth.reduce((prev, next) => prev + next, 0); } static showAudioPlayerPart(part) { if (part) { part.classList.remove('hidden'); } } static hideAudioPlayerPart(part) { if (part) { part.classList.add('hidden'); } } showAudioPlayer() { this.audioPlayer.classList.remove('hide-player'); } hideAudioPlayer() { this.audioPlayer.classList.add('hide-player'); } play() { if (this.audio) { this.audio.play(); } } pause() { this.audio.pause(); } stop() { resetPlayer(this.audio); } parentStateChanged(parentState) { super.parentStateChanged(parentState); this.stop(); } triggerPlay(e) { FusionAudioPlayer.setButtonIcon(this.playPauseIcon, iconsConfig.play); this.emitCustomEvent(e.type); } triggerPause(e) { FusionAudioPlayer.setButtonIcon(this.playPauseIcon, iconsConfig.pause); this.emitCustomEvent(e.type); } togglePlay() { this.audio.paused ? this.play() : this.pause(); } static setButtonIcon(element, iconType) { if (element && iconType) { element.attributes.d.value = iconType; } } updateVolumeButtonIcon() { if (this.audio.volume >= 0.5) { FusionAudioPlayer.setButtonIcon(this.volumeIcon, iconsConfig.volumeLow); } else if (this.audio.volume < 0.5 && this.audio.volume > 0) { FusionAudioPlayer.setButtonIcon(this.volumeIcon, iconsConfig.volumeAverage); } else if (this.audio.volume <= 0) { FusionAudioPlayer.setButtonIcon(this.volumeIcon, iconsConfig.volumeHigh); } } showVolumeSlider() { this['show-volume-handler'] ? this.toggleVolumeControlsClasses() : this.toggleVolume(); } toggleVolumeControlsClasses() { this.volumeButton.classList.toggle('open'); this.volumeControls.classList.toggle('hidden'); } toggleVolume() { if (this.audio.volume) { this.audio.volume = 0; FusionAudioPlayer.setButtonIcon(this.volumeIcon, iconsConfig.volumeLow); } else { this.audio.volume = 1; FusionAudioPlayer.setButtonIcon(this.volumeIcon, iconsConfig.volumeHigh); } } updateProgress() { const current = this.audio.currentTime; if (this.audio.duration && !this.progressSlider.isHandlerSet) { this.progressSlider['start-value'] = current * FusionAudioPlayer.getCoefficient(this.audio.duration, this.progressSlider['max-value']); } this.currentTime.textContent = FusionAudioPlayer.formatTime(current); } static getCoefficient(mainScale, compareScale) { return compareScale / mainScale; } static formatTime(time) { const min = Math.floor(time / 60); const sec = Math.floor(time % 60); return `${min}:${sec < 10 ? `0${sec}` : sec}`; } setTotalTime() { this.totalTime.textContent = FusionAudioPlayer.formatTime(this.audio.duration); } volumeAdjust() { const compareScale = 1; if (this.audio.volume !== undefined) { this.audio.volume = this.volumeSlider.slider.value * FusionAudioPlayer.getCoefficient(this.volumeSlider['max-value'], compareScale); } } changeProgress() { if (this.audio && this.audio.duration) { const { num } = getValueObject(this.progressSlider.slider.value * FusionAudioPlayer.getCoefficient(this.progressSlider['max-value'], this.audio.duration)); this.audio.currentTime = num; } } setListenerType(eventType) { this.events.forEach((item) => { item.target[eventType](item.event, item.handler); }); } handleAudioEnd(e) { this.pause(); this.audio.currentTime = 0; this.progressSlider['start-value'] = 0; this.emitCustomEvent(e.type); } startAutoPlay() { const playPromise = this.audio.play(); if (playPromise !== undefined) { playPromise .then(() => {}) .catch(error => FusionLogger.error(`${error} ${FusionAudioPlayer.options.componentName}`, FusionAudioPlayer.options.componentUIName)); } } firstUpdated(changedProperties) { super.firstUpdated(changedProperties); this.audioPlayer = this.shadowRoot.querySelector('.custom-audio-player'); this.playPauseIcon = this.audioPlayer.querySelector('.play-pause-icon'); this.playPauseButton = this.audioPlayer.querySelector('.play-pause-button'); this.progressSlider = this.audioPlayer.querySelector('.progress-slider'); this.progressControls = this.audioPlayer.querySelector('.controls'); this.volumeSlider = this.audioPlayer.querySelector('.volume-slider'); this.volumeButton = this.audioPlayer.querySelector('.volume-button'); this.volumeControls = this.audioPlayer.querySelector('.volume-controls'); this.audio = this.audioPlayer.querySelector('audio'); this.currentTime = this.audioPlayer.querySelector('.current-time'); this.totalTime = this.audioPlayer.querySelector('.total-time'); this.volumeIcon = this.audioPlayer.querySelector('.volume-icon'); if (this.autoplay && this.src) this.startAutoPlay(); this.togglePlayButtonStyle(this.src); this.updateAudioPlayerPartStyle(); this.events = [ { target: this.playPauseButton, event: 'click', handler: this.togglePlay.bind(this), }, { target: this.audio, event: 'timeupdate', handler: this.updateProgress.bind(this), }, { target: this.audio, event: 'volumechange', handler: this.updateVolumeButtonIcon.bind(this), }, { target: this.audio, event: 'play', handler: this.triggerPlay.bind(this), }, { target: this.audio, event: 'pause', handler: this.triggerPause.bind(this), }, { target: this.audio, event: 'loadedmetadata', handler: this.setTotalTime.bind(this), }, { target: this.volumeButton, event: 'click', handler: this.showVolumeSlider.bind(this), }, { target: this.volumeSlider, event: 'change', handler: this.volumeAdjust.bind(this), }, { target: this.progressSlider, event: 'change', handler: this.changeProgress.bind(this), }, { target: this.audio, event: 'ended', handler: this.handleAudioEnd.bind(this), }, ]; if (this.audio) { this.setListenerType('addEventListener'); } } disconnectedCallback() { super.disconnectedCallback(); this.setListenerType('removeEventListener'); } connectedCallback() { super.connectedCallback(); } render() { super.render(); return html` <style> ${FusionAudioPlayer.getStyle()} :host { height: 50px; min-height: 35px; display: block; } :host .custom-audio-player { height: 100%; box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.15); display: flex; justify-content: space-between; align-items: center; padding: 0 15px; border-radius: 4px; user-select: none; background: var(--background-color); } :host .progress-slider { top: 50%; left: 0; } :host .slider { position: relative; } :host .time-output { padding: 0 7px; color: var(--main-color); } :host button { padding: 0 7px; border: none; background: no-repeat; outline: #cccccc; cursor: pointer; } :host button.disabled { pointer-events: none; opacity: 0.5; } :host .volume-inner { position: relative; width: 100%; height: 100%; } :host .volume-slider { top: 95%; left: 0; right: 0; transform: rotate(-90deg) translate(100%, 0%); } :host .controls { position: relative; display: flex; flex-grow: 1; justify-content: space-between; align-items: center; padding: 0 7px; font-size: 16px; line-height: 18px; color: #55606E; } :host .volume { position: relative; display: flex; align-items: center; } :host .volume-button { cursor: pointer; } :host .volume-button path { fill: var(--main-color); } :host .volume-button.open path { fill: var(--additional-color); } :host .play-pause-button path { fill: var(--main-color); } :host .hide-player { opacity: 0; } :host .volume-controls { position: absolute; left: 50%; bottom: 52px; display: flex; width: 30px; height: 135px; flex-direction: column; align-items: center; background-color: rgba(0, 0, 0, 0.62); border-radius: 7px; transform: translate(-50%); } :host .hidden { display: none; } :host .volume-controls .slider { width: 100%; margin: auto; border-radius: 3px; } :host svg { display: block; } :host(.${ModeTrackable.EditModeClassName}) .custom-audio-player { pointer-events: none; } </style> <div class='custom-audio-player'> <button class='play-pause-button'> <svg xmlns='http://www.w3.org/2000/svg' width='18' height='24' viewBox='0 0 18 24'> <path fill='#566574' fill-rule='evenodd' d='M18 12L0 24V0' class='play-pause-icon'/> </svg> </button> <output class='current-time time-output'>0:00</output> <div class='controls'> <fusion-slider class='progress-slider slider' height='6px' slider-height='6px' background='#aaa' width='100%' min-value='0' max-value='100' start-value='0' step='1' radius='18px'></fusion-slider> </div> <output class='total-time time-output' >0:00</output> <div class='volume'> <button class='volume-button'> <svg xmlns='' width='24' height='24' viewBox='0 0 24 24'> <path fill='#566574' fill-rule='evenodd' d='M14.667 0v2.747c3.853 1.146 6.666 4.72 6.666 8.946 0 4.227-2.813 7.787-6.666 8.934v2.76C20 22.173 24 17.4 24 11.693 24 5.987 20 1.213 14.667 0zM18 11.693c0-2.36-1.333-4.386-3.333-5.373v10.707c2-.947 3.333-2.987 3.333-5.334zm-18-4v8h5.333L12 22.36V1.027L5.333 7.693H0z' class='volume-icon'/> </svg> </button> <div class='volume-controls hidden'> <div class='volume-inner'> <fusion-slider class='slider volume-slider' height='6px' slider-height='6px' background='#aaa' width='115px' min-value='1' max-value='100' start-value='100' step='1' radius='18px'></fusion-slider> </div> </div> </div> <audio src=${this.src}></audio> </div> ${FusionAudioPlayer.getSystemSlotTemplate()} `; } } export { FusionAudioPlayer };