diff --git a/aircox/static/aircox/admin.css b/aircox/static/aircox/admin.css index 2a52547..4df472d 100644 --- a/aircox/static/aircox/admin.css +++ b/aircox/static/aircox/admin.css @@ -7410,6 +7410,7 @@ a.navbar-item.is-active { background: linear-gradient(transparent 1em, whitesmoke); } .player { + z-index: 10000; box-shadow: 0em 1.5em 2.5em rgba(0, 0, 0, 0.6); } .player .player-panels { height: 0%; diff --git a/aircox/static/aircox/admin.js b/aircox/static/aircox/admin.js index a5611e3..4c07b23 100644 --- a/aircox/static/aircox/admin.js +++ b/aircox/static/aircox/admin.js @@ -653,7 +653,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n//\n//\n//\n//\n//\n//\n\n/* /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"State\", function() { return State; });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.browser.js\");\n/* harmony import */ var _live__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./live */ \"./assets/public/live.js\");\n/* harmony import */ var _playlist__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./playlist */ \"./assets/public/playlist.vue\");\n/* harmony import */ var _progress__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./progress */ \"./assets/public/progress.vue\");\n/* harmony import */ var _sound__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./sound */ \"./assets/public/sound.js\");\n/* harmony import */ var _model__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./model */ \"./assets/public/model.js\");\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n\n\n\n\n\n\n\n\nconst State = {\n paused: 0,\n playing: 1,\n loading: 2,\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n data() {\n let audio = new Audio();\n audio.addEventListener('ended', e => this.onState(e));\n audio.addEventListener('pause', e => this.onState(e));\n audio.addEventListener('playing', e => this.onState(e));\n audio.addEventListener('timeupdate', e => {\n this.currentTime = this.audio.currentTime;\n });\n audio.addEventListener('durationchange', e => {\n this.duration = Number.isFinite(this.audio.duration) ? this.audio.duration : null;\n });\n\n return {\n audio, duration: 0, currentTime: 0, state: State.paused,\n\n /// Live instance\n live: this.liveArgs ? new _live__WEBPACK_IMPORTED_MODULE_1__[\"default\"](this.liveArgs) : null,\n /// Loaded item\n loaded: null,\n //! Active panel name\n panel: null,\n //! current playing playlist name\n playlistName: null,\n //! players' playlists' sets\n sets: {\n queue: _model__WEBPACK_IMPORTED_MODULE_5__[\"Set\"].storeLoad(_sound__WEBPACK_IMPORTED_MODULE_4__[\"default\"], \"playlist.queue\", { max: 30, unique: true }),\n pin: _model__WEBPACK_IMPORTED_MODULE_5__[\"Set\"].storeLoad(_sound__WEBPACK_IMPORTED_MODULE_4__[\"default\"], \"player.pin\", { max: 30, unique: true }),\n }\n }\n },\n\n props: {\n buttonTitle: String,\n liveArgs: Object,\n },\n\n computed: {\n self() { return this; },\n paused() { return this.state == State.paused; },\n playing() { return this.state == State.playing; },\n loading() { return this.state == State.loading; },\n\n playlist() {\n return this.playlistName ? this.$refs[this.playlistName] : null;\n },\n\n current() {\n return this.loaded || this.live && this.live.current;\n },\n\n buttonStyle() {\n if(!this.current)\n return;\n return { backgroundImage: `url(${this.current.cover})` }\n },\n },\n\n methods: {\n displayTime(seconds) {\n seconds = parseInt(seconds);\n let s = seconds % 60;\n seconds = (seconds - s) / 60;\n let m = seconds % 60;\n let h = (seconds - m) / 60;\n\n let [ss,mm,hh] = [s.toString().padStart(2, '0'),\n m.toString().padStart(2, '0'),\n h.toString().padStart(2, '0')];\n return h ? `${hh}:${mm}:${ss}` : `${mm}:${ss}`;\n },\n\n playlistButtonClass(name) {\n let set = this.sets[name];\n return (set ? (set.length ? \"\" : \"has-text-grey-light \")\n + (this.panel == name ? \"is-info \"\n : this.playlistName == name ? 'is-primary '\n : '') : '')\n + \"button has-text-weight-bold\";\n },\n\n /// Show/hide panel\n togglePanel(panel) { this.panel = this.panel == panel ? null : panel },\n /// Return True if item is loaded\n isLoaded(item) { return this.loaded && this.loaded.id == item.id },\n /// Return True if item is loaded\n isPlaying(item) { return this.isLoaded(item) && !this.paused },\n\n _setPlaylist(playlist) {\n this.playlistName = playlist;\n for(var p in this.sets)\n if(p != playlist)\n this.$refs[p].unselect();\n },\n\n /// Load a sound from playlist or live\n load(playlist=null, index=0) {\n let src = null;\n\n // from playlist\n if(playlist !== null) {\n let item = this.$refs[playlist].get(index);\n if(!item)\n throw `No sound at index ${index} for playlist ${playlist}`;\n this.loaded = item;\n src = item.src;\n }\n // from live\n else {\n this.loaded = null;\n src = this.live.src;\n }\n\n this._setPlaylist(playlist);\n\n // load sources\n const audio = this.audio;\n if(src instanceof Array) {\n audio.innerHTML = '';\n audio.removeAttribute('src');\n for(var s of src) {\n let source = document.createElement('source');\n source.setAttribute('src', s);\n console.log('src', source.getAttribute('src'));\n audio.appendChild(source)\n }\n }\n else {\n audio.src = src;\n }\n audio.load();\n console.log(audio);\n },\n\n play(playlist=null, index=0) {\n this.load(playlist, index);\n this.audio.play().catch(e => console.error(e))\n },\n\n /// Push items to playlist (by name)\n push(playlist, ...items) {\n return this.$refs[playlist].push(...items);\n },\n\n /// Push and play items\n playItems(playlist, ...items) {\n let index = this.push(playlist, ...items);\n this.$refs[playlist].selectedIndex = index;\n this.play(playlist, index);\n },\n\n /// Handle click event that plays multiple items (from `data-sounds` attribute)\n playButtonClick(event) {\n var items = JSON.parse(event.currentTarget.dataset.sounds);\n this.playItems('queue', ...items);\n },\n\n /// Pause\n pause() {\n this.audio.pause()\n },\n\n //! Play/pause\n togglePlay(playlist=null, index=0) {\n if(playlist !== null) {\n let item = this.sets[playlist].get(index);\n if(!this.playlist || this.playlistName !== playlist || this.loaded != item) {\n this.play(playlist, index);\n return;\n }\n }\n if(this.paused)\n this.audio.play().catch(e => console.error(e))\n else\n this.audio.pause();\n },\n\n //! Pin/Unpin an item\n togglePin(item) {\n let index = this.sets.pin.findIndex(item);\n if(index > -1)\n this.sets.pin.remove(index);\n else {\n this.sets.pin.push(item);\n this.$refs.pinPlaylistButton.focus();\n }\n },\n\n /// Audio player state change event\n onState(event) {\n const audio = this.audio;\n this.state = audio.paused ? State.paused : State.playing;\n\n if(event.type == 'ended' && (!this.playlist || this.playlist.selectNext() == -1))\n this.play();\n },\n },\n\n mounted() {\n this.load();\n },\n\n components: { Playlist: _playlist__WEBPACK_IMPORTED_MODULE_2__[\"default\"], Progress: _progress__WEBPACK_IMPORTED_MODULE_3__[\"default\"] },\n});\n\n\n//# sourceURL=webpack:///./assets/public/player.vue?./node_modules/vue-loader/lib??vue-loader-options"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"State\", function() { return State; });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.browser.js\");\n/* harmony import */ var _live__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./live */ \"./assets/public/live.js\");\n/* harmony import */ var _playlist__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./playlist */ \"./assets/public/playlist.vue\");\n/* harmony import */ var _progress__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./progress */ \"./assets/public/progress.vue\");\n/* harmony import */ var _sound__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./sound */ \"./assets/public/sound.js\");\n/* harmony import */ var _model__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./model */ \"./assets/public/model.js\");\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n\n\n\n\n\n\n\n\nconst State = {\n paused: 0,\n playing: 1,\n loading: 2,\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n data() {\n let audio = new Audio();\n audio.addEventListener('ended', e => this.onState(e));\n audio.addEventListener('pause', e => this.onState(e));\n audio.addEventListener('playing', e => this.onState(e));\n audio.addEventListener('timeupdate', e => {\n this.currentTime = this.audio.currentTime;\n });\n audio.addEventListener('durationchange', e => {\n this.duration = Number.isFinite(this.audio.duration) ? this.audio.duration : null;\n });\n\n return {\n audio, duration: 0, currentTime: 0, state: State.paused,\n\n /// Live instance\n live: this.liveArgs ? new _live__WEBPACK_IMPORTED_MODULE_1__[\"default\"](this.liveArgs) : null,\n /// Loaded item\n loaded: null,\n //! Active panel name\n panel: null,\n //! current playing playlist name\n playlistName: null,\n //! players' playlists' sets\n sets: {\n queue: _model__WEBPACK_IMPORTED_MODULE_5__[\"Set\"].storeLoad(_sound__WEBPACK_IMPORTED_MODULE_4__[\"default\"], \"playlist.queue\", { max: 30, unique: true }),\n pin: _model__WEBPACK_IMPORTED_MODULE_5__[\"Set\"].storeLoad(_sound__WEBPACK_IMPORTED_MODULE_4__[\"default\"], \"player.pin\", { max: 30, unique: true }),\n }\n }\n },\n\n props: {\n buttonTitle: String,\n liveArgs: Object,\n },\n\n computed: {\n self() { return this; },\n paused() { return this.state == State.paused; },\n playing() { return this.state == State.playing; },\n loading() { return this.state == State.loading; },\n\n playlist() {\n return this.playlistName ? this.$refs[this.playlistName] : null;\n },\n\n current() {\n return this.loaded || this.live && this.live.current;\n },\n },\n\n methods: {\n displayTime(seconds) {\n seconds = parseInt(seconds);\n let s = seconds % 60;\n seconds = (seconds - s) / 60;\n let m = seconds % 60;\n let h = (seconds - m) / 60;\n\n let [ss,mm,hh] = [s.toString().padStart(2, '0'),\n m.toString().padStart(2, '0'),\n h.toString().padStart(2, '0')];\n return h ? `${hh}:${mm}:${ss}` : `${mm}:${ss}`;\n },\n\n playlistButtonClass(name) {\n let set = this.sets[name];\n return (set ? (set.length ? \"\" : \"has-text-grey-light \")\n + (this.panel == name ? \"is-info \"\n : this.playlistName == name ? 'is-primary '\n : '') : '')\n + \"button has-text-weight-bold\";\n },\n\n /// Show/hide panel\n togglePanel(panel) { this.panel = this.panel == panel ? null : panel },\n /// Return True if item is loaded\n isLoaded(item) { return this.loaded && this.loaded.id == item.id },\n /// Return True if item is loaded\n isPlaying(item) { return this.isLoaded(item) && !this.paused },\n\n _setPlaylist(playlist) {\n this.playlistName = playlist;\n for(var p in this.sets)\n if(p != playlist)\n this.$refs[p].unselect();\n },\n\n /// Load a sound from playlist or live\n load(playlist=null, index=0) {\n let src = null;\n\n // from playlist\n if(playlist !== null) {\n let item = this.$refs[playlist].get(index);\n if(!item)\n throw `No sound at index ${index} for playlist ${playlist}`;\n this.loaded = item;\n src = item.src;\n }\n // from live\n else {\n this.loaded = null;\n src = this.live.src;\n }\n\n this._setPlaylist(playlist);\n\n // load sources\n const audio = this.audio;\n if(src instanceof Array) {\n audio.innerHTML = '';\n audio.removeAttribute('src');\n for(var s of src) {\n let source = document.createElement('source');\n source.setAttribute('src', s);\n console.log('src', source.getAttribute('src'));\n audio.appendChild(source)\n }\n }\n else {\n audio.src = src;\n }\n audio.load();\n console.log(audio);\n },\n\n play(playlist=null, index=0) {\n this.load(playlist, index);\n this.audio.play().catch(e => console.error(e))\n },\n\n /// Push items to playlist (by name)\n push(playlist, ...items) {\n return this.$refs[playlist].push(...items);\n },\n\n /// Push and play items\n playItems(playlist, ...items) {\n let index = this.push(playlist, ...items);\n this.$refs[playlist].selectedIndex = index;\n this.play(playlist, index);\n },\n\n /// Handle click event that plays multiple items (from `data-sounds` attribute)\n playButtonClick(event) {\n var items = JSON.parse(event.currentTarget.dataset.sounds);\n this.playItems('queue', ...items);\n },\n\n /// Pause\n pause() {\n this.audio.pause()\n },\n\n //! Play/pause\n togglePlay(playlist=null, index=0) {\n if(playlist !== null) {\n let item = this.sets[playlist].get(index);\n if(!this.playlist || this.playlistName !== playlist || this.loaded != item) {\n this.play(playlist, index);\n return;\n }\n }\n if(this.paused)\n this.audio.play().catch(e => console.error(e))\n else\n this.audio.pause();\n },\n\n //! Pin/Unpin an item\n togglePin(item) {\n let index = this.sets.pin.findIndex(item);\n if(index > -1)\n this.sets.pin.remove(index);\n else {\n this.sets.pin.push(item);\n this.$refs.pinPlaylistButton.focus();\n }\n },\n\n /// Audio player state change event\n onState(event) {\n const audio = this.audio;\n this.state = audio.paused ? State.paused : State.playing;\n\n if(event.type == 'ended' && (!this.playlist || this.playlist.selectNext() == -1))\n this.play();\n },\n },\n\n mounted() {\n this.load();\n },\n\n components: { Playlist: _playlist__WEBPACK_IMPORTED_MODULE_2__[\"default\"], Progress: _progress__WEBPACK_IMPORTED_MODULE_3__[\"default\"] },\n});\n\n\n//# sourceURL=webpack:///./assets/public/player.vue?./node_modules/vue-loader/lib??vue-loader-options"); /***/ }), @@ -761,7 +761,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) * /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return render; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return staticRenderFns; });\nvar render = function() {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\"div\", { staticClass: \"player\" }, [\n _c(\n \"div\",\n { class: [\"player-panels\", _vm.panel ? \"is-open\" : \"\"] },\n [\n _c(\"Playlist\", {\n directives: [\n {\n name: \"show\",\n rawName: \"v-show\",\n value: _vm.panel == \"pin\",\n expression: \"panel == 'pin'\"\n }\n ],\n ref: \"pin\",\n staticClass: \"player-panel menu\",\n attrs: {\n name: \"Pinned\",\n actions: [\"page\"],\n editable: true,\n player: _vm.self,\n set: _vm.sets.pin,\n listClass: \"menu-list\",\n itemClass: \"menu-item\"\n },\n on: {\n select: function($event) {\n return _vm.togglePlay(\"pin\", $event.index)\n }\n },\n scopedSlots: _vm._u([\n {\n key: \"header\",\n fn: function() {\n return [\n _c(\"p\", { staticClass: \"menu-label\" }, [\n _c(\"span\", { staticClass: \"icon\" }, [\n _c(\"span\", { staticClass: \"fa fa-thumbtack\" })\n ]),\n _vm._v(\"\\n Pinned\\n \")\n ])\n ]\n },\n proxy: true\n }\n ])\n }),\n _vm._v(\" \"),\n _c(\"Playlist\", {\n directives: [\n {\n name: \"show\",\n rawName: \"v-show\",\n value: _vm.panel == \"queue\",\n expression: \"panel == 'queue'\"\n }\n ],\n ref: \"queue\",\n staticClass: \"player-panel menu\",\n attrs: {\n actions: [\"page\"],\n editable: true,\n player: _vm.self,\n set: _vm.sets.queue,\n listClass: \"menu-list\",\n itemClass: \"menu-item\"\n },\n on: {\n select: function($event) {\n return _vm.togglePlay(\"queue\", $event.index)\n }\n },\n scopedSlots: _vm._u([\n {\n key: \"header\",\n fn: function() {\n return [\n _c(\"p\", { staticClass: \"menu-label\" }, [\n _c(\"span\", { staticClass: \"icon\" }, [\n _c(\"span\", { staticClass: \"fa fa-list\" })\n ]),\n _vm._v(\"\\n Playlist\\n \")\n ])\n ]\n },\n proxy: true\n }\n ])\n })\n ],\n 1\n ),\n _vm._v(\" \"),\n _c(\"div\", { staticClass: \"player-bar media\" }, [\n _c(\"div\", { staticClass: \"media-left\" }, [\n _c(\n \"button\",\n {\n staticClass: \"button\",\n attrs: { title: _vm.buttonTitle, \"aria-label\": _vm.buttonTitle },\n on: {\n click: function($event) {\n return _vm.togglePlay()\n }\n }\n },\n [\n _vm.playing\n ? _c(\"span\", { staticClass: \"fas fa-pause\" })\n : _c(\"span\", { staticClass: \"fas fa-play\" })\n ]\n )\n ]),\n _vm._v(\" \"),\n _vm.current && _vm.current.cover\n ? _c(\"div\", { staticClass: \"media-left media-cover\" }, [\n _c(\"img\", {\n staticClass: \"cover\",\n attrs: { src: _vm.current.cover }\n })\n ])\n : _vm._e(),\n _vm._v(\" \"),\n _c(\n \"div\",\n { staticClass: \"media-content\" },\n [\n _vm._t(\"content\", null, { current: _vm.current }),\n _vm._v(\" \"),\n _vm.loaded && _vm.duration\n ? _c(\"Progress\", {\n attrs: {\n value: _vm.currentTime,\n max: this.duration,\n format: _vm.displayTime\n },\n on: {\n select: function($event) {\n _vm.audio.currentTime = $event\n }\n }\n })\n : _vm._e()\n ],\n 2\n ),\n _vm._v(\" \"),\n _c(\"div\", { staticClass: \"media-right\" }, [\n _vm.loaded\n ? _c(\n \"button\",\n {\n staticClass: \"button has-text-weight-bold\",\n on: {\n click: function($event) {\n return _vm.play()\n }\n }\n },\n [_vm._m(0), _vm._v(\" \"), _c(\"span\", [_vm._v(\"Live\")])]\n )\n : _vm._e(),\n _vm._v(\" \"),\n _c(\n \"button\",\n {\n ref: \"pinPlaylistButton\",\n class: _vm.playlistButtonClass(\"pin\"),\n on: {\n click: function($event) {\n return _vm.togglePanel(\"pin\")\n }\n }\n },\n [\n _vm.sets.pin.length\n ? _c(\"span\", { staticClass: \"mr-2 is-size-6\" }, [\n _vm._v(\"\\n \" + _vm._s(_vm.sets.pin.length))\n ])\n : _vm._e(),\n _vm._v(\" \"),\n _vm._m(1)\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"button\",\n {\n class: _vm.playlistButtonClass(\"queue\"),\n on: {\n click: function($event) {\n return _vm.togglePanel(\"queue\")\n }\n }\n },\n [\n _vm.sets.queue.length\n ? _c(\"span\", { staticClass: \"mr-2 is-size-6\" }, [\n _vm._v(\n \"\\n \" + _vm._s(_vm.sets.queue.length)\n )\n ])\n : _vm._e(),\n _vm._v(\" \"),\n _vm._m(2)\n ]\n )\n ])\n ])\n ])\n}\nvar staticRenderFns = [\n function() {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\"span\", { staticClass: \"icon is-size-6 has-text-danger\" }, [\n _c(\"span\", { staticClass: \"fa fa-circle\" })\n ])\n },\n function() {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\"span\", { staticClass: \"icon\" }, [\n _c(\"span\", { staticClass: \"fa fa-thumbtack\" })\n ])\n },\n function() {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\"span\", { staticClass: \"icon\" }, [\n _c(\"span\", { staticClass: \"fa fa-list\" })\n ])\n }\n]\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./assets/public/player.vue?./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib??vue-loader-options"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return render; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return staticRenderFns; });\nvar render = function() {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\"div\", { staticClass: \"player\" }, [\n _c(\n \"div\",\n { class: [\"player-panels\", _vm.panel ? \"is-open\" : \"\"] },\n [\n _c(\"Playlist\", {\n directives: [\n {\n name: \"show\",\n rawName: \"v-show\",\n value: _vm.panel == \"pin\",\n expression: \"panel == 'pin'\"\n }\n ],\n ref: \"pin\",\n staticClass: \"player-panel menu\",\n attrs: {\n name: \"Pinned\",\n actions: [\"page\"],\n editable: true,\n player: _vm.self,\n set: _vm.sets.pin,\n listClass: \"menu-list\",\n itemClass: \"menu-item\"\n },\n on: {\n select: function($event) {\n return _vm.togglePlay(\"pin\", $event.index)\n }\n },\n scopedSlots: _vm._u([\n {\n key: \"header\",\n fn: function() {\n return [\n _c(\"p\", { staticClass: \"menu-label\" }, [\n _c(\"span\", { staticClass: \"icon\" }, [\n _c(\"span\", { staticClass: \"fa fa-thumbtack\" })\n ]),\n _vm._v(\"\\n Pinned\\n \")\n ])\n ]\n },\n proxy: true\n }\n ])\n }),\n _vm._v(\" \"),\n _c(\"Playlist\", {\n directives: [\n {\n name: \"show\",\n rawName: \"v-show\",\n value: _vm.panel == \"queue\",\n expression: \"panel == 'queue'\"\n }\n ],\n ref: \"queue\",\n staticClass: \"player-panel menu\",\n attrs: {\n actions: [\"page\"],\n editable: true,\n player: _vm.self,\n set: _vm.sets.queue,\n listClass: \"menu-list\",\n itemClass: \"menu-item\"\n },\n on: {\n select: function($event) {\n return _vm.togglePlay(\"queue\", $event.index)\n }\n },\n scopedSlots: _vm._u([\n {\n key: \"header\",\n fn: function() {\n return [\n _c(\"p\", { staticClass: \"menu-label\" }, [\n _c(\"span\", { staticClass: \"icon\" }, [\n _c(\"span\", { staticClass: \"fa fa-list\" })\n ]),\n _vm._v(\"\\n Playlist\\n \")\n ])\n ]\n },\n proxy: true\n }\n ])\n })\n ],\n 1\n ),\n _vm._v(\" \"),\n _c(\"div\", { staticClass: \"player-bar media\" }, [\n _c(\"div\", { staticClass: \"media-left\" }, [\n _c(\n \"button\",\n {\n staticClass: \"button\",\n attrs: { title: _vm.buttonTitle, \"aria-label\": _vm.buttonTitle },\n on: {\n click: function($event) {\n return _vm.togglePlay()\n }\n }\n },\n [\n _vm.playing\n ? _c(\"span\", { staticClass: \"fas fa-pause\" })\n : _c(\"span\", { staticClass: \"fas fa-play\" })\n ]\n )\n ]),\n _vm._v(\" \"),\n _vm.current && _vm.current.cover\n ? _c(\"div\", { staticClass: \"media-left media-cover\" }, [\n _c(\"img\", {\n staticClass: \"cover\",\n attrs: { src: _vm.current.cover }\n })\n ])\n : _vm._e(),\n _vm._v(\" \"),\n _c(\n \"div\",\n { staticClass: \"media-content\" },\n [\n _vm._t(\"content\", null, { loaded: _vm.loaded, live: _vm.live }),\n _vm._v(\" \"),\n _vm.loaded && _vm.duration\n ? _c(\"Progress\", {\n attrs: {\n value: _vm.currentTime,\n max: this.duration,\n format: _vm.displayTime\n },\n on: {\n select: function($event) {\n _vm.audio.currentTime = $event\n }\n }\n })\n : _vm._e()\n ],\n 2\n ),\n _vm._v(\" \"),\n _c(\"div\", { staticClass: \"media-right\" }, [\n _vm.loaded\n ? _c(\n \"button\",\n {\n staticClass: \"button has-text-weight-bold\",\n on: {\n click: function($event) {\n return _vm.play()\n }\n }\n },\n [_vm._m(0), _vm._v(\" \"), _c(\"span\", [_vm._v(\"Live\")])]\n )\n : _vm._e(),\n _vm._v(\" \"),\n _c(\n \"button\",\n {\n ref: \"pinPlaylistButton\",\n class: _vm.playlistButtonClass(\"pin\"),\n on: {\n click: function($event) {\n return _vm.togglePanel(\"pin\")\n }\n }\n },\n [\n _vm.sets.pin.length\n ? _c(\"span\", { staticClass: \"mr-2 is-size-6\" }, [\n _vm._v(\"\\n \" + _vm._s(_vm.sets.pin.length))\n ])\n : _vm._e(),\n _vm._v(\" \"),\n _vm._m(1)\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"button\",\n {\n class: _vm.playlistButtonClass(\"queue\"),\n on: {\n click: function($event) {\n return _vm.togglePanel(\"queue\")\n }\n }\n },\n [\n _vm.sets.queue.length\n ? _c(\"span\", { staticClass: \"mr-2 is-size-6\" }, [\n _vm._v(\n \"\\n \" + _vm._s(_vm.sets.queue.length)\n )\n ])\n : _vm._e(),\n _vm._v(\" \"),\n _vm._m(2)\n ]\n )\n ])\n ])\n ])\n}\nvar staticRenderFns = [\n function() {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\"span\", { staticClass: \"icon is-size-6 has-text-danger\" }, [\n _c(\"span\", { staticClass: \"fa fa-circle\" })\n ])\n },\n function() {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\"span\", { staticClass: \"icon\" }, [\n _c(\"span\", { staticClass: \"fa fa-thumbtack\" })\n ])\n },\n function() {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\"span\", { staticClass: \"icon\" }, [\n _c(\"span\", { staticClass: \"fa fa-list\" })\n ])\n }\n]\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./assets/public/player.vue?./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib??vue-loader-options"); /***/ }), diff --git a/aircox/static/aircox/main.css b/aircox/static/aircox/main.css index 1219a66..2ea2804 100644 --- a/aircox/static/aircox/main.css +++ b/aircox/static/aircox/main.css @@ -7389,6 +7389,7 @@ a.navbar-item.is-active { background: linear-gradient(transparent 1em, whitesmoke); } .player { + z-index: 10000; box-shadow: 0em 1.5em 2.5em rgba(0, 0, 0, 0.6); } .player .player-panels { height: 0%; diff --git a/aircox/static/aircox/main.js b/aircox/static/aircox/main.js index 63813b6..311e42b 100644 --- a/aircox/static/aircox/main.js +++ b/aircox/static/aircox/main.js @@ -582,7 +582,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n//\n//\n//\n//\n//\n//\n\n/* /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"State\", function() { return State; });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.browser.js\");\n/* harmony import */ var _live__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./live */ \"./assets/public/live.js\");\n/* harmony import */ var _playlist__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./playlist */ \"./assets/public/playlist.vue\");\n/* harmony import */ var _progress__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./progress */ \"./assets/public/progress.vue\");\n/* harmony import */ var _sound__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./sound */ \"./assets/public/sound.js\");\n/* harmony import */ var _model__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./model */ \"./assets/public/model.js\");\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n\n\n\n\n\n\n\n\nconst State = {\n paused: 0,\n playing: 1,\n loading: 2,\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n data() {\n let audio = new Audio();\n audio.addEventListener('ended', e => this.onState(e));\n audio.addEventListener('pause', e => this.onState(e));\n audio.addEventListener('playing', e => this.onState(e));\n audio.addEventListener('timeupdate', e => {\n this.currentTime = this.audio.currentTime;\n });\n audio.addEventListener('durationchange', e => {\n this.duration = Number.isFinite(this.audio.duration) ? this.audio.duration : null;\n });\n\n return {\n audio, duration: 0, currentTime: 0, state: State.paused,\n\n /// Live instance\n live: this.liveArgs ? new _live__WEBPACK_IMPORTED_MODULE_1__[\"default\"](this.liveArgs) : null,\n /// Loaded item\n loaded: null,\n //! Active panel name\n panel: null,\n //! current playing playlist name\n playlistName: null,\n //! players' playlists' sets\n sets: {\n queue: _model__WEBPACK_IMPORTED_MODULE_5__[\"Set\"].storeLoad(_sound__WEBPACK_IMPORTED_MODULE_4__[\"default\"], \"playlist.queue\", { max: 30, unique: true }),\n pin: _model__WEBPACK_IMPORTED_MODULE_5__[\"Set\"].storeLoad(_sound__WEBPACK_IMPORTED_MODULE_4__[\"default\"], \"player.pin\", { max: 30, unique: true }),\n }\n }\n },\n\n props: {\n buttonTitle: String,\n liveArgs: Object,\n },\n\n computed: {\n self() { return this; },\n paused() { return this.state == State.paused; },\n playing() { return this.state == State.playing; },\n loading() { return this.state == State.loading; },\n\n playlist() {\n return this.playlistName ? this.$refs[this.playlistName] : null;\n },\n\n current() {\n return this.loaded || this.live && this.live.current;\n },\n\n buttonStyle() {\n if(!this.current)\n return;\n return { backgroundImage: `url(${this.current.cover})` }\n },\n },\n\n methods: {\n displayTime(seconds) {\n seconds = parseInt(seconds);\n let s = seconds % 60;\n seconds = (seconds - s) / 60;\n let m = seconds % 60;\n let h = (seconds - m) / 60;\n\n let [ss,mm,hh] = [s.toString().padStart(2, '0'),\n m.toString().padStart(2, '0'),\n h.toString().padStart(2, '0')];\n return h ? `${hh}:${mm}:${ss}` : `${mm}:${ss}`;\n },\n\n playlistButtonClass(name) {\n let set = this.sets[name];\n return (set ? (set.length ? \"\" : \"has-text-grey-light \")\n + (this.panel == name ? \"is-info \"\n : this.playlistName == name ? 'is-primary '\n : '') : '')\n + \"button has-text-weight-bold\";\n },\n\n /// Show/hide panel\n togglePanel(panel) { this.panel = this.panel == panel ? null : panel },\n /// Return True if item is loaded\n isLoaded(item) { return this.loaded && this.loaded.id == item.id },\n /// Return True if item is loaded\n isPlaying(item) { return this.isLoaded(item) && !this.paused },\n\n _setPlaylist(playlist) {\n this.playlistName = playlist;\n for(var p in this.sets)\n if(p != playlist)\n this.$refs[p].unselect();\n },\n\n /// Load a sound from playlist or live\n load(playlist=null, index=0) {\n let src = null;\n\n // from playlist\n if(playlist !== null) {\n let item = this.$refs[playlist].get(index);\n if(!item)\n throw `No sound at index ${index} for playlist ${playlist}`;\n this.loaded = item;\n src = item.src;\n }\n // from live\n else {\n this.loaded = null;\n src = this.live.src;\n }\n\n this._setPlaylist(playlist);\n\n // load sources\n const audio = this.audio;\n if(src instanceof Array) {\n audio.innerHTML = '';\n audio.removeAttribute('src');\n for(var s of src) {\n let source = document.createElement('source');\n source.setAttribute('src', s);\n console.log('src', source.getAttribute('src'));\n audio.appendChild(source)\n }\n }\n else {\n audio.src = src;\n }\n audio.load();\n console.log(audio);\n },\n\n play(playlist=null, index=0) {\n this.load(playlist, index);\n this.audio.play().catch(e => console.error(e))\n },\n\n /// Push items to playlist (by name)\n push(playlist, ...items) {\n return this.$refs[playlist].push(...items);\n },\n\n /// Push and play items\n playItems(playlist, ...items) {\n let index = this.push(playlist, ...items);\n this.$refs[playlist].selectedIndex = index;\n this.play(playlist, index);\n },\n\n /// Handle click event that plays multiple items (from `data-sounds` attribute)\n playButtonClick(event) {\n var items = JSON.parse(event.currentTarget.dataset.sounds);\n this.playItems('queue', ...items);\n },\n\n /// Pause\n pause() {\n this.audio.pause()\n },\n\n //! Play/pause\n togglePlay(playlist=null, index=0) {\n if(playlist !== null) {\n let item = this.sets[playlist].get(index);\n if(!this.playlist || this.playlistName !== playlist || this.loaded != item) {\n this.play(playlist, index);\n return;\n }\n }\n if(this.paused)\n this.audio.play().catch(e => console.error(e))\n else\n this.audio.pause();\n },\n\n //! Pin/Unpin an item\n togglePin(item) {\n let index = this.sets.pin.findIndex(item);\n if(index > -1)\n this.sets.pin.remove(index);\n else {\n this.sets.pin.push(item);\n this.$refs.pinPlaylistButton.focus();\n }\n },\n\n /// Audio player state change event\n onState(event) {\n const audio = this.audio;\n this.state = audio.paused ? State.paused : State.playing;\n\n if(event.type == 'ended' && (!this.playlist || this.playlist.selectNext() == -1))\n this.play();\n },\n },\n\n mounted() {\n this.load();\n },\n\n components: { Playlist: _playlist__WEBPACK_IMPORTED_MODULE_2__[\"default\"], Progress: _progress__WEBPACK_IMPORTED_MODULE_3__[\"default\"] },\n});\n\n\n//# sourceURL=webpack:///./assets/public/player.vue?./node_modules/vue-loader/lib??vue-loader-options"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"State\", function() { return State; });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.browser.js\");\n/* harmony import */ var _live__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./live */ \"./assets/public/live.js\");\n/* harmony import */ var _playlist__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./playlist */ \"./assets/public/playlist.vue\");\n/* harmony import */ var _progress__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./progress */ \"./assets/public/progress.vue\");\n/* harmony import */ var _sound__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./sound */ \"./assets/public/sound.js\");\n/* harmony import */ var _model__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./model */ \"./assets/public/model.js\");\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n\n\n\n\n\n\n\n\nconst State = {\n paused: 0,\n playing: 1,\n loading: 2,\n}\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n data() {\n let audio = new Audio();\n audio.addEventListener('ended', e => this.onState(e));\n audio.addEventListener('pause', e => this.onState(e));\n audio.addEventListener('playing', e => this.onState(e));\n audio.addEventListener('timeupdate', e => {\n this.currentTime = this.audio.currentTime;\n });\n audio.addEventListener('durationchange', e => {\n this.duration = Number.isFinite(this.audio.duration) ? this.audio.duration : null;\n });\n\n return {\n audio, duration: 0, currentTime: 0, state: State.paused,\n\n /// Live instance\n live: this.liveArgs ? new _live__WEBPACK_IMPORTED_MODULE_1__[\"default\"](this.liveArgs) : null,\n /// Loaded item\n loaded: null,\n //! Active panel name\n panel: null,\n //! current playing playlist name\n playlistName: null,\n //! players' playlists' sets\n sets: {\n queue: _model__WEBPACK_IMPORTED_MODULE_5__[\"Set\"].storeLoad(_sound__WEBPACK_IMPORTED_MODULE_4__[\"default\"], \"playlist.queue\", { max: 30, unique: true }),\n pin: _model__WEBPACK_IMPORTED_MODULE_5__[\"Set\"].storeLoad(_sound__WEBPACK_IMPORTED_MODULE_4__[\"default\"], \"player.pin\", { max: 30, unique: true }),\n }\n }\n },\n\n props: {\n buttonTitle: String,\n liveArgs: Object,\n },\n\n computed: {\n self() { return this; },\n paused() { return this.state == State.paused; },\n playing() { return this.state == State.playing; },\n loading() { return this.state == State.loading; },\n\n playlist() {\n return this.playlistName ? this.$refs[this.playlistName] : null;\n },\n\n current() {\n return this.loaded || this.live && this.live.current;\n },\n },\n\n methods: {\n displayTime(seconds) {\n seconds = parseInt(seconds);\n let s = seconds % 60;\n seconds = (seconds - s) / 60;\n let m = seconds % 60;\n let h = (seconds - m) / 60;\n\n let [ss,mm,hh] = [s.toString().padStart(2, '0'),\n m.toString().padStart(2, '0'),\n h.toString().padStart(2, '0')];\n return h ? `${hh}:${mm}:${ss}` : `${mm}:${ss}`;\n },\n\n playlistButtonClass(name) {\n let set = this.sets[name];\n return (set ? (set.length ? \"\" : \"has-text-grey-light \")\n + (this.panel == name ? \"is-info \"\n : this.playlistName == name ? 'is-primary '\n : '') : '')\n + \"button has-text-weight-bold\";\n },\n\n /// Show/hide panel\n togglePanel(panel) { this.panel = this.panel == panel ? null : panel },\n /// Return True if item is loaded\n isLoaded(item) { return this.loaded && this.loaded.id == item.id },\n /// Return True if item is loaded\n isPlaying(item) { return this.isLoaded(item) && !this.paused },\n\n _setPlaylist(playlist) {\n this.playlistName = playlist;\n for(var p in this.sets)\n if(p != playlist)\n this.$refs[p].unselect();\n },\n\n /// Load a sound from playlist or live\n load(playlist=null, index=0) {\n let src = null;\n\n // from playlist\n if(playlist !== null) {\n let item = this.$refs[playlist].get(index);\n if(!item)\n throw `No sound at index ${index} for playlist ${playlist}`;\n this.loaded = item;\n src = item.src;\n }\n // from live\n else {\n this.loaded = null;\n src = this.live.src;\n }\n\n this._setPlaylist(playlist);\n\n // load sources\n const audio = this.audio;\n if(src instanceof Array) {\n audio.innerHTML = '';\n audio.removeAttribute('src');\n for(var s of src) {\n let source = document.createElement('source');\n source.setAttribute('src', s);\n console.log('src', source.getAttribute('src'));\n audio.appendChild(source)\n }\n }\n else {\n audio.src = src;\n }\n audio.load();\n console.log(audio);\n },\n\n play(playlist=null, index=0) {\n this.load(playlist, index);\n this.audio.play().catch(e => console.error(e))\n },\n\n /// Push items to playlist (by name)\n push(playlist, ...items) {\n return this.$refs[playlist].push(...items);\n },\n\n /// Push and play items\n playItems(playlist, ...items) {\n let index = this.push(playlist, ...items);\n this.$refs[playlist].selectedIndex = index;\n this.play(playlist, index);\n },\n\n /// Handle click event that plays multiple items (from `data-sounds` attribute)\n playButtonClick(event) {\n var items = JSON.parse(event.currentTarget.dataset.sounds);\n this.playItems('queue', ...items);\n },\n\n /// Pause\n pause() {\n this.audio.pause()\n },\n\n //! Play/pause\n togglePlay(playlist=null, index=0) {\n if(playlist !== null) {\n let item = this.sets[playlist].get(index);\n if(!this.playlist || this.playlistName !== playlist || this.loaded != item) {\n this.play(playlist, index);\n return;\n }\n }\n if(this.paused)\n this.audio.play().catch(e => console.error(e))\n else\n this.audio.pause();\n },\n\n //! Pin/Unpin an item\n togglePin(item) {\n let index = this.sets.pin.findIndex(item);\n if(index > -1)\n this.sets.pin.remove(index);\n else {\n this.sets.pin.push(item);\n this.$refs.pinPlaylistButton.focus();\n }\n },\n\n /// Audio player state change event\n onState(event) {\n const audio = this.audio;\n this.state = audio.paused ? State.paused : State.playing;\n\n if(event.type == 'ended' && (!this.playlist || this.playlist.selectNext() == -1))\n this.play();\n },\n },\n\n mounted() {\n this.load();\n },\n\n components: { Playlist: _playlist__WEBPACK_IMPORTED_MODULE_2__[\"default\"], Progress: _progress__WEBPACK_IMPORTED_MODULE_3__[\"default\"] },\n});\n\n\n//# sourceURL=webpack:///./assets/public/player.vue?./node_modules/vue-loader/lib??vue-loader-options"); /***/ }), @@ -678,7 +678,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) * /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return render; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return staticRenderFns; });\nvar render = function() {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\"div\", { staticClass: \"player\" }, [\n _c(\n \"div\",\n { class: [\"player-panels\", _vm.panel ? \"is-open\" : \"\"] },\n [\n _c(\"Playlist\", {\n directives: [\n {\n name: \"show\",\n rawName: \"v-show\",\n value: _vm.panel == \"pin\",\n expression: \"panel == 'pin'\"\n }\n ],\n ref: \"pin\",\n staticClass: \"player-panel menu\",\n attrs: {\n name: \"Pinned\",\n actions: [\"page\"],\n editable: true,\n player: _vm.self,\n set: _vm.sets.pin,\n listClass: \"menu-list\",\n itemClass: \"menu-item\"\n },\n on: {\n select: function($event) {\n return _vm.togglePlay(\"pin\", $event.index)\n }\n },\n scopedSlots: _vm._u([\n {\n key: \"header\",\n fn: function() {\n return [\n _c(\"p\", { staticClass: \"menu-label\" }, [\n _c(\"span\", { staticClass: \"icon\" }, [\n _c(\"span\", { staticClass: \"fa fa-thumbtack\" })\n ]),\n _vm._v(\"\\n Pinned\\n \")\n ])\n ]\n },\n proxy: true\n }\n ])\n }),\n _vm._v(\" \"),\n _c(\"Playlist\", {\n directives: [\n {\n name: \"show\",\n rawName: \"v-show\",\n value: _vm.panel == \"queue\",\n expression: \"panel == 'queue'\"\n }\n ],\n ref: \"queue\",\n staticClass: \"player-panel menu\",\n attrs: {\n actions: [\"page\"],\n editable: true,\n player: _vm.self,\n set: _vm.sets.queue,\n listClass: \"menu-list\",\n itemClass: \"menu-item\"\n },\n on: {\n select: function($event) {\n return _vm.togglePlay(\"queue\", $event.index)\n }\n },\n scopedSlots: _vm._u([\n {\n key: \"header\",\n fn: function() {\n return [\n _c(\"p\", { staticClass: \"menu-label\" }, [\n _c(\"span\", { staticClass: \"icon\" }, [\n _c(\"span\", { staticClass: \"fa fa-list\" })\n ]),\n _vm._v(\"\\n Playlist\\n \")\n ])\n ]\n },\n proxy: true\n }\n ])\n })\n ],\n 1\n ),\n _vm._v(\" \"),\n _c(\"div\", { staticClass: \"player-bar media\" }, [\n _c(\"div\", { staticClass: \"media-left\" }, [\n _c(\n \"button\",\n {\n staticClass: \"button\",\n attrs: { title: _vm.buttonTitle, \"aria-label\": _vm.buttonTitle },\n on: {\n click: function($event) {\n return _vm.togglePlay()\n }\n }\n },\n [\n _vm.playing\n ? _c(\"span\", { staticClass: \"fas fa-pause\" })\n : _c(\"span\", { staticClass: \"fas fa-play\" })\n ]\n )\n ]),\n _vm._v(\" \"),\n _vm.current && _vm.current.cover\n ? _c(\"div\", { staticClass: \"media-left media-cover\" }, [\n _c(\"img\", {\n staticClass: \"cover\",\n attrs: { src: _vm.current.cover }\n })\n ])\n : _vm._e(),\n _vm._v(\" \"),\n _c(\n \"div\",\n { staticClass: \"media-content\" },\n [\n _vm._t(\"content\", null, { current: _vm.current }),\n _vm._v(\" \"),\n _vm.loaded && _vm.duration\n ? _c(\"Progress\", {\n attrs: {\n value: _vm.currentTime,\n max: this.duration,\n format: _vm.displayTime\n },\n on: {\n select: function($event) {\n _vm.audio.currentTime = $event\n }\n }\n })\n : _vm._e()\n ],\n 2\n ),\n _vm._v(\" \"),\n _c(\"div\", { staticClass: \"media-right\" }, [\n _vm.loaded\n ? _c(\n \"button\",\n {\n staticClass: \"button has-text-weight-bold\",\n on: {\n click: function($event) {\n return _vm.play()\n }\n }\n },\n [_vm._m(0), _vm._v(\" \"), _c(\"span\", [_vm._v(\"Live\")])]\n )\n : _vm._e(),\n _vm._v(\" \"),\n _c(\n \"button\",\n {\n ref: \"pinPlaylistButton\",\n class: _vm.playlistButtonClass(\"pin\"),\n on: {\n click: function($event) {\n return _vm.togglePanel(\"pin\")\n }\n }\n },\n [\n _vm.sets.pin.length\n ? _c(\"span\", { staticClass: \"mr-2 is-size-6\" }, [\n _vm._v(\"\\n \" + _vm._s(_vm.sets.pin.length))\n ])\n : _vm._e(),\n _vm._v(\" \"),\n _vm._m(1)\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"button\",\n {\n class: _vm.playlistButtonClass(\"queue\"),\n on: {\n click: function($event) {\n return _vm.togglePanel(\"queue\")\n }\n }\n },\n [\n _vm.sets.queue.length\n ? _c(\"span\", { staticClass: \"mr-2 is-size-6\" }, [\n _vm._v(\n \"\\n \" + _vm._s(_vm.sets.queue.length)\n )\n ])\n : _vm._e(),\n _vm._v(\" \"),\n _vm._m(2)\n ]\n )\n ])\n ])\n ])\n}\nvar staticRenderFns = [\n function() {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\"span\", { staticClass: \"icon is-size-6 has-text-danger\" }, [\n _c(\"span\", { staticClass: \"fa fa-circle\" })\n ])\n },\n function() {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\"span\", { staticClass: \"icon\" }, [\n _c(\"span\", { staticClass: \"fa fa-thumbtack\" })\n ])\n },\n function() {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\"span\", { staticClass: \"icon\" }, [\n _c(\"span\", { staticClass: \"fa fa-list\" })\n ])\n }\n]\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./assets/public/player.vue?./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib??vue-loader-options"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return render; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return staticRenderFns; });\nvar render = function() {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\"div\", { staticClass: \"player\" }, [\n _c(\n \"div\",\n { class: [\"player-panels\", _vm.panel ? \"is-open\" : \"\"] },\n [\n _c(\"Playlist\", {\n directives: [\n {\n name: \"show\",\n rawName: \"v-show\",\n value: _vm.panel == \"pin\",\n expression: \"panel == 'pin'\"\n }\n ],\n ref: \"pin\",\n staticClass: \"player-panel menu\",\n attrs: {\n name: \"Pinned\",\n actions: [\"page\"],\n editable: true,\n player: _vm.self,\n set: _vm.sets.pin,\n listClass: \"menu-list\",\n itemClass: \"menu-item\"\n },\n on: {\n select: function($event) {\n return _vm.togglePlay(\"pin\", $event.index)\n }\n },\n scopedSlots: _vm._u([\n {\n key: \"header\",\n fn: function() {\n return [\n _c(\"p\", { staticClass: \"menu-label\" }, [\n _c(\"span\", { staticClass: \"icon\" }, [\n _c(\"span\", { staticClass: \"fa fa-thumbtack\" })\n ]),\n _vm._v(\"\\n Pinned\\n \")\n ])\n ]\n },\n proxy: true\n }\n ])\n }),\n _vm._v(\" \"),\n _c(\"Playlist\", {\n directives: [\n {\n name: \"show\",\n rawName: \"v-show\",\n value: _vm.panel == \"queue\",\n expression: \"panel == 'queue'\"\n }\n ],\n ref: \"queue\",\n staticClass: \"player-panel menu\",\n attrs: {\n actions: [\"page\"],\n editable: true,\n player: _vm.self,\n set: _vm.sets.queue,\n listClass: \"menu-list\",\n itemClass: \"menu-item\"\n },\n on: {\n select: function($event) {\n return _vm.togglePlay(\"queue\", $event.index)\n }\n },\n scopedSlots: _vm._u([\n {\n key: \"header\",\n fn: function() {\n return [\n _c(\"p\", { staticClass: \"menu-label\" }, [\n _c(\"span\", { staticClass: \"icon\" }, [\n _c(\"span\", { staticClass: \"fa fa-list\" })\n ]),\n _vm._v(\"\\n Playlist\\n \")\n ])\n ]\n },\n proxy: true\n }\n ])\n })\n ],\n 1\n ),\n _vm._v(\" \"),\n _c(\"div\", { staticClass: \"player-bar media\" }, [\n _c(\"div\", { staticClass: \"media-left\" }, [\n _c(\n \"button\",\n {\n staticClass: \"button\",\n attrs: { title: _vm.buttonTitle, \"aria-label\": _vm.buttonTitle },\n on: {\n click: function($event) {\n return _vm.togglePlay()\n }\n }\n },\n [\n _vm.playing\n ? _c(\"span\", { staticClass: \"fas fa-pause\" })\n : _c(\"span\", { staticClass: \"fas fa-play\" })\n ]\n )\n ]),\n _vm._v(\" \"),\n _vm.current && _vm.current.cover\n ? _c(\"div\", { staticClass: \"media-left media-cover\" }, [\n _c(\"img\", {\n staticClass: \"cover\",\n attrs: { src: _vm.current.cover }\n })\n ])\n : _vm._e(),\n _vm._v(\" \"),\n _c(\n \"div\",\n { staticClass: \"media-content\" },\n [\n _vm._t(\"content\", null, { loaded: _vm.loaded, live: _vm.live }),\n _vm._v(\" \"),\n _vm.loaded && _vm.duration\n ? _c(\"Progress\", {\n attrs: {\n value: _vm.currentTime,\n max: this.duration,\n format: _vm.displayTime\n },\n on: {\n select: function($event) {\n _vm.audio.currentTime = $event\n }\n }\n })\n : _vm._e()\n ],\n 2\n ),\n _vm._v(\" \"),\n _c(\"div\", { staticClass: \"media-right\" }, [\n _vm.loaded\n ? _c(\n \"button\",\n {\n staticClass: \"button has-text-weight-bold\",\n on: {\n click: function($event) {\n return _vm.play()\n }\n }\n },\n [_vm._m(0), _vm._v(\" \"), _c(\"span\", [_vm._v(\"Live\")])]\n )\n : _vm._e(),\n _vm._v(\" \"),\n _c(\n \"button\",\n {\n ref: \"pinPlaylistButton\",\n class: _vm.playlistButtonClass(\"pin\"),\n on: {\n click: function($event) {\n return _vm.togglePanel(\"pin\")\n }\n }\n },\n [\n _vm.sets.pin.length\n ? _c(\"span\", { staticClass: \"mr-2 is-size-6\" }, [\n _vm._v(\"\\n \" + _vm._s(_vm.sets.pin.length))\n ])\n : _vm._e(),\n _vm._v(\" \"),\n _vm._m(1)\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"button\",\n {\n class: _vm.playlistButtonClass(\"queue\"),\n on: {\n click: function($event) {\n return _vm.togglePanel(\"queue\")\n }\n }\n },\n [\n _vm.sets.queue.length\n ? _c(\"span\", { staticClass: \"mr-2 is-size-6\" }, [\n _vm._v(\n \"\\n \" + _vm._s(_vm.sets.queue.length)\n )\n ])\n : _vm._e(),\n _vm._v(\" \"),\n _vm._m(2)\n ]\n )\n ])\n ])\n ])\n}\nvar staticRenderFns = [\n function() {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\"span\", { staticClass: \"icon is-size-6 has-text-danger\" }, [\n _c(\"span\", { staticClass: \"fa fa-circle\" })\n ])\n },\n function() {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\"span\", { staticClass: \"icon\" }, [\n _c(\"span\", { staticClass: \"fa fa-thumbtack\" })\n ])\n },\n function() {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\"span\", { staticClass: \"icon\" }, [\n _c(\"span\", { staticClass: \"fa fa-list\" })\n ])\n }\n]\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./assets/public/player.vue?./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib??vue-loader-options"); /***/ }), diff --git a/aircox/templates/aircox/widgets/player.html b/aircox/templates/aircox/widgets/player.html index f09c976..a65e95e 100644 --- a/aircox/templates/aircox/widgets/player.html +++ b/aircox/templates/aircox/widgets/player.html @@ -20,8 +20,11 @@ The audio player -