From 063d1f194e316f6b0342bdda9063b043797959bf Mon Sep 17 00:00:00 2001 From: bkfox Date: Tue, 27 Oct 2020 20:52:46 +0100 Subject: [PATCH] work on player --- aircox/static/aircox/admin.js | 86 ++++++-- aircox/static/aircox/main.js | 86 ++++++-- aircox/static/aircox/streamer.js | 6 +- aircox/templates/aircox/episode_detail.html | 23 +- aircox/templates/aircox/program_sidebar.html | 8 + .../aircox/widgets/podcast_item.html | 2 +- aircox/templatetags/aircox.py | 1 + assets/public/app.js | 14 +- assets/public/index.js | 11 +- assets/public/list.vue | 44 ++-- assets/public/model.js | 64 ++++-- assets/public/player.vue | 200 +++++++++++------- assets/public/playlist.vue | 58 +++++ assets/public/soundItem.vue | 74 +++---- 14 files changed, 477 insertions(+), 200 deletions(-) create mode 100644 aircox/templates/aircox/program_sidebar.html create mode 100644 assets/public/playlist.vue diff --git a/aircox/static/aircox/admin.js b/aircox/static/aircox/admin.js index 0da11c3..f7614f7 100644 --- a/aircox/static/aircox/admin.js +++ b/aircox/static/aircox/admin.js @@ -218,11 +218,11 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _nod /*!******************************!*\ !*** ./assets/public/app.js ***! \******************************/ -/*! exports provided: defaultConfig, App, AppConfig */ +/*! exports provided: defaultConfig, default, AppConfig */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"defaultConfig\", function() { return defaultConfig; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"App\", function() { return App; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AppConfig\", function() { return AppConfig; });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.browser.js\");\n\n\n\nconst defaultConfig = {\n el: '#app',\n delimiters: ['[[', ']]'],\n\n computed: {\n player() {\n return window.aircox.player;\n }\n }\n}\n\nfunction App(config) {\n return (new AppConfig(config)).load()\n}\n\n/**\n * Application config for an application instance\n */\nclass AppConfig {\n constructor(config) {\n this._config = config;\n }\n\n get config() {\n let config = this._config instanceof Function ? this._config() : this._config;\n return {...defaultConfig, ...config};\n }\n\n set config(value) {\n this._config = value;\n }\n\n load() {\n var self = this;\n return new Promise(function(resolve, reject) {\n window.addEventListener('load', () => {\n try {\n let config = self.config;\n const el = document.querySelector(config.el)\n if(!el) {\n reject(`Error: missing element ${config.el}`);\n return;\n }\n resolve(new vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"](config))\n }\n catch(error) { reject(error) }\n })\n });\n }\n}\n\n\n\n\n//# sourceURL=webpack:///./assets/public/app.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"defaultConfig\", function() { return defaultConfig; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return App; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AppConfig\", function() { return AppConfig; });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.browser.js\");\n\n\n\nconst defaultConfig = {\n el: '#app',\n delimiters: ['[[', ']]'],\n\n data() {\n return {\n page: null,\n }\n },\n\n computed: {\n player() { return window.aircox.player; }\n },\n}\n\nfunction App(config) {\n return (new AppConfig(config)).load()\n}\n\n/**\n * Application config for an application instance\n */\nclass AppConfig {\n constructor(config) {\n this._config = config;\n }\n\n get config() {\n let config = this._config instanceof Function ? this._config() : this._config;\n return {...defaultConfig, ...config};\n }\n\n set config(value) {\n this._config = value;\n }\n\n load() {\n var self = this;\n return new Promise(function(resolve, reject) {\n window.addEventListener('load', () => {\n try {\n let config = self.config;\n const el = document.querySelector(config.el)\n if(!el) {\n reject(`Error: missing element ${config.el}`);\n return;\n }\n resolve(new vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"](config))\n }\n catch(error) { reject(error) }\n })\n });\n }\n}\n\n\n\n\n//# sourceURL=webpack:///./assets/public/app.js?"); /***/ }), @@ -270,7 +270,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _nod /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.browser.js\");\n/* harmony import */ var _fortawesome_fontawesome_free_css_all_min_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @fortawesome/fontawesome-free/css/all.min.css */ \"./node_modules/@fortawesome/fontawesome-free/css/all.min.css\");\n/* harmony import */ var _fortawesome_fontawesome_free_css_all_min_css__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_fortawesome_fontawesome_free_css_all_min_css__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _fortawesome_fontawesome_free_css_fontawesome_min_css__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @fortawesome/fontawesome-free/css/fontawesome.min.css */ \"./node_modules/@fortawesome/fontawesome-free/css/fontawesome.min.css\");\n/* harmony import */ var _fortawesome_fontawesome_free_css_fontawesome_min_css__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_fortawesome_fontawesome_free_css_fontawesome_min_css__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _app__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./app */ \"./assets/public/app.js\");\n/* harmony import */ var _styles_scss__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./styles.scss */ \"./assets/public/styles.scss\");\n/* harmony import */ var _styles_scss__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_styles_scss__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var _autocomplete_vue__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./autocomplete.vue */ \"./assets/public/autocomplete.vue\");\n/* harmony import */ var _player_vue__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./player.vue */ \"./assets/public/player.vue\");\n/* harmony import */ var _soundItem__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./soundItem */ \"./assets/public/soundItem.vue\");\n/**\n * This module includes code available for both the public website and\n * administration interface)\n */\n//-- vendor\n\n\n\n\n\n\n//-- aircox\n\n\n\n\n\n\n\n\nvue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].component('a-autocomplete', _autocomplete_vue__WEBPACK_IMPORTED_MODULE_5__[\"default\"])\nvue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].component('a-player', _player_vue__WEBPACK_IMPORTED_MODULE_6__[\"default\"])\nvue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].component('a-sound-item', _soundItem__WEBPACK_IMPORTED_MODULE_7__[\"default\"])\n\n\nwindow.aircox = {\n // main application\n app: null,\n\n // main application config\n appConfig: {},\n\n // player application\n playerApp: null,\n\n // player component\n get player() {\n return this.playerApp && this.playerApp.$refs.player\n }\n};\n\n\nObject(_app__WEBPACK_IMPORTED_MODULE_3__[\"App\"])({el: '#player'}).then(app => window.aircox.playerApp = app,\n () => undefined);\nObject(_app__WEBPACK_IMPORTED_MODULE_3__[\"App\"])(() => window.aircox.appConfig).then(app => { window.aircox.app = app },\n () => undefined)\n\n\n\n\n//# sourceURL=webpack:///./assets/public/index.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.browser.js\");\n/* harmony import */ var _fortawesome_fontawesome_free_css_all_min_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @fortawesome/fontawesome-free/css/all.min.css */ \"./node_modules/@fortawesome/fontawesome-free/css/all.min.css\");\n/* harmony import */ var _fortawesome_fontawesome_free_css_all_min_css__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_fortawesome_fontawesome_free_css_all_min_css__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _fortawesome_fontawesome_free_css_fontawesome_min_css__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @fortawesome/fontawesome-free/css/fontawesome.min.css */ \"./node_modules/@fortawesome/fontawesome-free/css/fontawesome.min.css\");\n/* harmony import */ var _fortawesome_fontawesome_free_css_fontawesome_min_css__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_fortawesome_fontawesome_free_css_fontawesome_min_css__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _app__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./app */ \"./assets/public/app.js\");\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/* harmony import */ var _styles_scss__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./styles.scss */ \"./assets/public/styles.scss\");\n/* harmony import */ var _styles_scss__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(_styles_scss__WEBPACK_IMPORTED_MODULE_6__);\n/* harmony import */ var _autocomplete_vue__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./autocomplete.vue */ \"./assets/public/autocomplete.vue\");\n/* harmony import */ var _player_vue__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./player.vue */ \"./assets/public/player.vue\");\n/* harmony import */ var _playlist_vue__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./playlist.vue */ \"./assets/public/playlist.vue\");\n/* harmony import */ var _soundItem__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./soundItem */ \"./assets/public/soundItem.vue\");\n/**\n * This module includes code available for both the public website and\n * administration interface)\n */\n//-- vendor\n\n\n\n\n\n\n//-- aircox\n\n\n\n\n\n\n\n\n\n\n\nvue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].component('a-autocomplete', _autocomplete_vue__WEBPACK_IMPORTED_MODULE_7__[\"default\"])\nvue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].component('a-player', _player_vue__WEBPACK_IMPORTED_MODULE_8__[\"default\"])\nvue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].component('a-playlist', _playlist_vue__WEBPACK_IMPORTED_MODULE_9__[\"default\"])\nvue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].component('a-sound-item', _soundItem__WEBPACK_IMPORTED_MODULE_10__[\"default\"])\n\n\nwindow.aircox = {\n // main application\n app: null,\n\n // main application config\n appConfig: {},\n\n // player application\n playerApp: null,\n\n // player component\n get player() {\n return this.playerApp && this.playerApp.$refs.player\n },\n\n Set: _model__WEBPACK_IMPORTED_MODULE_5__[\"Set\"], Sound: _sound__WEBPACK_IMPORTED_MODULE_4__[\"default\"],\n};\nwindow.Vue = vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"];\n\n\nObject(_app__WEBPACK_IMPORTED_MODULE_3__[\"default\"])({el: '#player'}).then(app => window.aircox.playerApp = app,\n () => undefined);\nObject(_app__WEBPACK_IMPORTED_MODULE_3__[\"default\"])(() => window.aircox.appConfig).then(app => { window.aircox.app = app },\n () => undefined)\n\n\n\n\n//# sourceURL=webpack:///./assets/public/index.js?"); /***/ }), @@ -330,7 +330,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__, \"getCsrf\", function() { return getCsrf; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return Model; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Set\", function() { return Set; });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.browser.js\");\n\n\nfunction getCookie(name) {\n if(document.cookie && document.cookie !== '') {\n const cookie = document.cookie.split(';')\n .find(c => c.trim().startsWith(name + '='))\n return cookie ? decodeURIComponent(cookie.split('=')[1]) : null;\n }\n return null;\n}\n\nvar csrfToken = null;\n\nfunction getCsrf() {\n if(csrfToken === null)\n csrfToken = getCookie('csrftoken')\n return csrfToken;\n}\n\n\n// TODO: prevent duplicate simple fetch\nclass Model {\n constructor(data, {url=null}={}) {\n this.url = url;\n this.commit(data);\n }\n\n /**\n * Get instance id from its data\n */\n static getId(data) {\n return data.id;\n }\n\n /**\n * Return fetch options\n */\n static getOptions(options) {\n return {\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n 'X-CSRFToken': getCsrf(),\n },\n ...options,\n }\n }\n\n /**\n * Fetch item from server\n */\n static fetch(url, options=null, args=null) {\n options = this.getOptions(options)\n return fetch(url, options)\n .then(response => response.json())\n .then(data => new this(data, {url: url, ...args}));\n }\n\n /**\n * Fetch data from server.\n */\n fetch(options) {\n options = this.constructor.getOptions(options)\n return fetch(this.url, options)\n .then(response => response.json())\n .then(data => this.commit(data));\n }\n\n /**\n * Call API action on object.\n */\n action(path, options, commit=false) {\n options = this.constructor.getOptions(options)\n const promise = fetch(this.url + path, options);\n return commit ? promise.then(data => data.json())\n .then(data => { this.commit(data); this.data })\n : promise;\n }\n\n /**\n * Update instance's data with provided data. Return None\n */\n commit(data) {\n this.id = this.constructor.getId(data);\n vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].set(this, 'data', data);\n }\n\n /**\n * Save instance into localStorage.\n */\n store(key) {\n window.localStorage.setItem(key, JSON.stringify(this.data));\n }\n\n /**\n * Load model instance from localStorage.\n */\n static storeLoad(key) {\n let item = window.localStorage.getItem(key);\n return item === null ? item : new this(JSON.parse(item));\n }\n}\n\n\n/**\n * List of models\n */\nclass Set {\n constructor(model, {items=[],url=null,args={},unique=null,max=null,storeKey=null}={}) {\n this.items = items.map(x => x instanceof model ? x : new model(x, args));\n this.model = model;\n this.url = url;\n this.unique = unique;\n this.max = max;\n this.storeKey = storeKey;\n }\n\n get length() { return this.items.length }\n indexOf(...args) { return this.items.indexOf(...args); }\n\n /**\n * Fetch multiple items from server\n */\n static fetch(url, options=null, args=null) {\n options = this.getOptions(options)\n return fetch(url, options)\n .then(response => response.json())\n .then(data => (data instanceof Array ? data : data.results)\n .map(d => new this.model(d, {url: url, ...args})))\n }\n\n /**\n * Load list from localStorage\n */\n static storeLoad(model, key, args={}) {\n let items = window.localStorage.getItem(key);\n return new this(model, {...args, storeKey: key, items: items ? JSON.parse(items) : []});\n }\n\n /**\n * Store list into localStorage\n */\n store() {\n if(this.storeKey)\n window.localStorage.setItem(this.storeKey, JSON.stringify(\n this.items.map(i => i.data)));\n }\n\n push(item, {args={}}={}) {\n item = item instanceof this.model ? item : new this.model(item, args);\n if(this.unique && this.items.find(x => x.id == item.id))\n return;\n if(this.max && this.items.length >= this.max)\n this.items.splice(0,this.items.length-this.max)\n\n this.items.push(item);\n this._updated()\n }\n\n remove(item, {args={}}={}) {\n item = item instanceof this.model ? item : new this.model(item, args);\n let index = this.items.findIndex(x => x.id == item.id);\n if(index == -1)\n return;\n\n this.items.splice(index,1);\n this._updated()\n }\n\n _updated() {\n vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].set(this, 'items', this.items);\n this.store();\n }\n}\n\nSet[Symbol.iterator] = function () {\n return this.items[Symbol.iterator]();\n}\n\n\n\n//# sourceURL=webpack:///./assets/public/model.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"getCsrf\", function() { return getCsrf; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return Model; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Set\", function() { return Set; });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.browser.js\");\n\n\nfunction getCookie(name) {\n if(document.cookie && document.cookie !== '') {\n const cookie = document.cookie.split(';')\n .find(c => c.trim().startsWith(name + '='))\n return cookie ? decodeURIComponent(cookie.split('=')[1]) : null;\n }\n return null;\n}\n\nvar csrfToken = null;\n\nfunction getCsrf() {\n if(csrfToken === null)\n csrfToken = getCookie('csrftoken')\n return csrfToken;\n}\n\n\n// TODO: prevent duplicate simple fetch\nclass Model {\n constructor(data, {url=null}={}) {\n this.url = url;\n this.commit(data);\n }\n\n /**\n * Get instance id from its data\n */\n static getId(data) {\n return data.id;\n }\n\n /**\n * Return fetch options\n */\n static getOptions(options) {\n return {\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n 'X-CSRFToken': getCsrf(),\n },\n ...options,\n }\n }\n\n /**\n * Fetch item from server\n */\n static fetch(url, options=null, args=null) {\n options = this.getOptions(options)\n return fetch(url, options)\n .then(response => response.json())\n .then(data => new this(data, {url: url, ...args}));\n }\n\n /**\n * Fetch data from server.\n */\n fetch(options) {\n options = this.constructor.getOptions(options)\n return fetch(this.url, options)\n .then(response => response.json())\n .then(data => this.commit(data));\n }\n\n /**\n * Call API action on object.\n */\n action(path, options, commit=false) {\n options = this.constructor.getOptions(options)\n const promise = fetch(this.url + path, options);\n return commit ? promise.then(data => data.json())\n .then(data => { this.commit(data); this.data })\n : promise;\n }\n\n /**\n * Update instance's data with provided data. Return None\n */\n commit(data) {\n this.id = this.constructor.getId(data);\n vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].set(this, 'data', data);\n }\n\n /**\n * Save instance into localStorage.\n */\n store(key) {\n window.localStorage.setItem(key, JSON.stringify(this.data));\n }\n\n /**\n * Load model instance from localStorage.\n */\n static storeLoad(key) {\n let item = window.localStorage.getItem(key);\n return item === null ? item : new this(JSON.parse(item));\n }\n}\n\n\n/**\n * List of models\n */\nclass Set {\n constructor(model, {items=[],url=null,args={},unique=null,max=null,storeKey=null}={}) {\n this.items = [];\n this.model = model;\n this.url = url;\n this.unique = unique;\n this.max = max;\n this.storeKey = storeKey;\n\n for(var item of items)\n this.push(item, {args: args, save: false});\n }\n\n get length() { return this.items.length }\n get(index) { return this.items[index] }\n\n /**\n * Fetch multiple items from server\n */\n static fetch(url, options=null, args=null) {\n options = this.getOptions(options)\n return fetch(url, options)\n .then(response => response.json())\n .then(data => (data instanceof Array ? data : data.results)\n .map(d => new this.model(d, {url: url, ...args})))\n }\n\n /**\n * Load list from localStorage\n */\n static storeLoad(model, key, args={}) {\n let items = window.localStorage.getItem(key);\n return new this(model, {...args, storeKey: key, items: items ? JSON.parse(items) : []});\n }\n\n /**\n * Store list into localStorage\n */\n store() {\n this.storeKey && window.localStorage.setItem(this.storeKey, JSON.stringify(\n this.items.map(i => i.data)));\n }\n\n /**\n * Save item\n */\n save() {\n this.storeKey && this.store();\n }\n\n /**\n * Find item by id\n */\n find(item) {\n return this.items.find(x => x.id == item.id);\n }\n\n /**\n * Find item index by id\n */\n findIndex(item) {\n return this.items.findIndex(x => x.id == item.id);\n }\n\n /**\n * Add item to set\n */\n push(item, {args={},save=true}={}) {\n item = item instanceof this.model ? item : new this.model(item, args);\n if(this.unique) {\n let index = this.findIndex(item);\n if(index > -1)\n this.items.splice(index,1);\n }\n if(this.max && this.items.length >= this.max)\n this.items.splice(0,this.items.length-this.max)\n\n this.items.push(item);\n save && this.save();\n }\n\n /**\n * Remove item from set by index\n */\n remove(index, {save=true}={}) {\n this.items.splice(index,1);\n save && this.save();\n }\n}\n\nSet[Symbol.iterator] = function () {\n return this.items[Symbol.iterator]();\n}\n\n\n\n//# sourceURL=webpack:///./assets/public/model.js?"); /***/ }), @@ -338,11 +338,11 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) * /*!**********************************!*\ !*** ./assets/public/player.vue ***! \**********************************/ -/*! exports provided: State, default */ +/*! no static exports found */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _player_vue_vue_type_template_id_42a56ec9___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./player.vue?vue&type=template&id=42a56ec9& */ \"./assets/public/player.vue?vue&type=template&id=42a56ec9&\");\n/* harmony import */ var _player_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./player.vue?vue&type=script&lang=js& */ \"./assets/public/player.vue?vue&type=script&lang=js&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"State\", function() { return _player_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"State\"]; });\n\n/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ \"./node_modules/vue-loader/lib/runtime/componentNormalizer.js\");\n\n\n\n\n\n/* normalize component */\n\nvar component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(\n _player_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n _player_vue_vue_type_template_id_42a56ec9___WEBPACK_IMPORTED_MODULE_0__[\"render\"],\n _player_vue_vue_type_template_id_42a56ec9___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"],\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"assets/public/player.vue\"\n/* harmony default export */ __webpack_exports__[\"default\"] = (component.exports);\n\n//# sourceURL=webpack:///./assets/public/player.vue?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _player_vue_vue_type_template_id_42a56ec9___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./player.vue?vue&type=template&id=42a56ec9& */ \"./assets/public/player.vue?vue&type=template&id=42a56ec9&\");\n/* harmony import */ var _player_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./player.vue?vue&type=script&lang=js& */ \"./assets/public/player.vue?vue&type=script&lang=js&\");\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _player_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _player_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ \"./node_modules/vue-loader/lib/runtime/componentNormalizer.js\");\n\n\n\n\n\n/* normalize component */\n\nvar component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(\n _player_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n _player_vue_vue_type_template_id_42a56ec9___WEBPACK_IMPORTED_MODULE_0__[\"render\"],\n _player_vue_vue_type_template_id_42a56ec9___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"],\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"assets/public/player.vue\"\n/* harmony default export */ __webpack_exports__[\"default\"] = (component.exports);\n\n//# sourceURL=webpack:///./assets/public/player.vue?"); /***/ }), @@ -350,7 +350,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _pla /*!***********************************************************!*\ !*** ./assets/public/player.vue?vue&type=script&lang=js& ***! \***********************************************************/ -/*! exports provided: default, State */ +/*! no static exports found */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -370,6 +370,42 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _nod /***/ }), +/***/ "./assets/public/playlist.vue": +/*!************************************!*\ + !*** ./assets/public/playlist.vue ***! + \************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _playlist_vue_vue_type_template_id_c0d17d8c___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./playlist.vue?vue&type=template&id=c0d17d8c& */ \"./assets/public/playlist.vue?vue&type=template&id=c0d17d8c&\");\n/* harmony import */ var _playlist_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./playlist.vue?vue&type=script&lang=js& */ \"./assets/public/playlist.vue?vue&type=script&lang=js&\");\n/* empty/unused harmony star reexport *//* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ \"./node_modules/vue-loader/lib/runtime/componentNormalizer.js\");\n\n\n\n\n\n/* normalize component */\n\nvar component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(\n _playlist_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n _playlist_vue_vue_type_template_id_c0d17d8c___WEBPACK_IMPORTED_MODULE_0__[\"render\"],\n _playlist_vue_vue_type_template_id_c0d17d8c___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"],\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"assets/public/playlist.vue\"\n/* harmony default export */ __webpack_exports__[\"default\"] = (component.exports);\n\n//# sourceURL=webpack:///./assets/public/playlist.vue?"); + +/***/ }), + +/***/ "./assets/public/playlist.vue?vue&type=script&lang=js&": +/*!*************************************************************!*\ + !*** ./assets/public/playlist.vue?vue&type=script&lang=js& ***! + \*************************************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_vue_loader_lib_index_js_vue_loader_options_playlist_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../node_modules/vue-loader/lib??vue-loader-options!./playlist.vue?vue&type=script&lang=js& */ \"./node_modules/vue-loader/lib/index.js?!./assets/public/playlist.vue?vue&type=script&lang=js&\");\n/* empty/unused harmony star reexport */ /* harmony default export */ __webpack_exports__[\"default\"] = (_node_modules_vue_loader_lib_index_js_vue_loader_options_playlist_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[\"default\"]); \n\n//# sourceURL=webpack:///./assets/public/playlist.vue?"); + +/***/ }), + +/***/ "./assets/public/playlist.vue?vue&type=template&id=c0d17d8c&": +/*!*******************************************************************!*\ + !*** ./assets/public/playlist.vue?vue&type=template&id=c0d17d8c& ***! + \*******************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_playlist_vue_vue_type_template_id_c0d17d8c___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!../../node_modules/vue-loader/lib??vue-loader-options!./playlist.vue?vue&type=template&id=c0d17d8c& */ \"./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/vue-loader/lib/index.js?!./assets/public/playlist.vue?vue&type=template&id=c0d17d8c&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_playlist_vue_vue_type_template_id_c0d17d8c___WEBPACK_IMPORTED_MODULE_0__[\"render\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_playlist_vue_vue_type_template_id_c0d17d8c___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"]; });\n\n\n\n//# sourceURL=webpack:///./assets/public/playlist.vue?"); + +/***/ }), + /***/ "./assets/public/sound.js": /*!********************************!*\ !*** ./assets/public/sound.js ***! @@ -473,7 +509,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var loda /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n data() {\n return {\n selectedIndex: this.default,\n }\n },\n\n props: {\n listClass: String,\n itemClass: String,\n default: { type: Number, default: -1},\n set: Object,\n },\n\n computed: {\n model() { return this.set.model },\n items() { return this.set.items },\n length() { return this.set.length },\n\n selected() {\n return this.items && this.items.length > this.selectedIndex > -1\n ? this.items[this.selectedIndex] : null;\n },\n },\n\n methods: {\n select(index=null) {\n if(index === null)\n index = this.selectedIndex;\n else if(this.selectedIndex == index)\n return;\n\n this.selectedIndex = Math.min(index, this.items.length-1);\n this.$emit('select', { item: this.selected, index: this.selectedIndex });\n return this.selectedIndex;\n },\n\n selectNext() {\n let index = this.selectedIndex + 1;\n return this.select(index >= this.items.length ? -1 : index);\n },\n\n // add()\n // insert() + drag & drop\n // remove()\n },\n});\n\n\n//# sourceURL=webpack:///./assets/public/list.vue?./node_modules/vue-loader/lib??vue-loader-options"); +eval("__webpack_require__.r(__webpack_exports__);\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n data() {\n return {\n selectedIndex: this.defaultIndex,\n }\n },\n\n props: {\n listClass: String,\n itemClass: String,\n defaultIndex: { type: Number, default: -1},\n set: Object,\n },\n\n computed: {\n model() { return this.set.model },\n items() { return this.set.items },\n length() { return this.set.length },\n\n selected() {\n return this.selectedIndex > -1 && this.items.length > this.selectedIndex > -1\n ? this.items[this.selectedIndex] : null;\n },\n },\n\n methods: {\n get(index) { return this.set.get(index) },\n find(item) { return this.set.find(item) },\n findIndex(item) { return this.set.findIndex(item) },\n\n push(...items) {\n let index = this.set.length;\n for(var item of items)\n this.set.push(item);\n },\n\n remove(index, select=False) {\n this.set.remove(index);\n if(index < this.selectedIndex)\n this.selectedIndex--;\n if(select && this.selectedIndex == index)\n this.select(index)\n },\n\n select(index) {\n this.selectedIndex = index > -1 && this.items.length ? index % this.items.length : -1;\n this.$emit('select', { target: this, item: this.selected, index: this.selectedIndex });\n return this.selectedIndex;\n },\n\n\n },\n});\n\n\n//# sourceURL=webpack:///./assets/public/list.vue?./node_modules/vue-loader/lib??vue-loader-options"); /***/ }), @@ -485,7 +521,19 @@ 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 _list__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./list */ \"./assets/public/list.vue\");\n/* harmony import */ var _soundItem__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./soundItem */ \"./assets/public/soundItem.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//\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 return {\n state: State.paused,\n active: null,\n live: this.liveArgs ? new _live__WEBPACK_IMPORTED_MODULE_1__[\"default\"](this.liveArgs) : null,\n panel: null,\n queue: _model__WEBPACK_IMPORTED_MODULE_5__[\"Set\"].storeLoad(_sound__WEBPACK_IMPORTED_MODULE_4__[\"default\"], \"player.queue\", { max: 30, unique: true }),\n history: _model__WEBPACK_IMPORTED_MODULE_5__[\"Set\"].storeLoad(_sound__WEBPACK_IMPORTED_MODULE_4__[\"default\"], \"player.history\", { max: 30, unique: true }),\n }\n },\n\n props: {\n buttonTitle: String,\n liveArgs: Object,\n },\n\n computed: {\n paused() { return this.state == State.paused; },\n playing() { return this.state == State.playing; },\n loading() { return this.state == State.loading; },\n self() { return this; },\n\n current() {\n return this.active || this.live && this.live.current;\n },\n\n progress() {\n let audio = this.$refs.audio;\n return audio && Number.isFinite(audio.duration) && audio.duration ?\n audio.pos / audio.duration * 100 : null;\n },\n\n buttonStyle() {\n if(!this.current)\n return;\n return { backgroundImage: `url(${this.current.cover})` }\n },\n },\n\n methods: {\n togglePanel(panel) {\n this.panel = this.panel == panel ? null : panel;\n },\n\n isActive(item) {\n return item && this.active && this.active.src == item.src;\n },\n\n _load(src) {\n const audio = this.$refs.audio;\n if(src instanceof Array) {\n audio.innerHTML = '';\n for(var s of src) {\n let source = document.createElement(source);\n source.setAttribute('src', s);\n audio.appendChild(source)\n }\n }\n else {\n audio.src = src;\n }\n audio.load();\n },\n\n load(item) {\n if(item) {\n this._load(item.src)\n this.history.push(item);\n }\n else\n this._load(this.live.src);\n this.$set(this, 'active', item);\n },\n\n play(item) {\n if(item)\n this.load(item);\n this.$refs.audio.play().catch(e => console.error(e))\n },\n\n pause() {\n this.$refs.audio.pause()\n },\n\n //! Play/pause\n togglePlay() {\n if(this.paused)\n this.play()\n else\n this.pause()\n },\n\n //! Push item to queue\n push(item) {\n this.queue.push(item);\n this.panel = 'queue';\n },\n\n onState(event) {\n const audio = this.$refs.audio;\n this.state = audio.paused ? State.paused : State.playing;\n\n if(event.type == 'ended' && this.active) {\n this.queue.remove(this.active);\n if(this.queue.length)\n this.$refs.queue.select(0);\n else\n this.load();\n }\n },\n\n onSelect({item,index}) {\n if(!this.isActive(item))\n this.play(item);\n },\n },\n\n mounted() {\n this.sources = this.$slots.sources;\n },\n\n components: {\n List: _list__WEBPACK_IMPORTED_MODULE_2__[\"default\"], SoundItem: _soundItem__WEBPACK_IMPORTED_MODULE_3__[\"default\"],\n },\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 _sound__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./sound */ \"./assets/public/sound.js\");\n/* harmony import */ var _model__WEBPACK_IMPORTED_MODULE_4__ = __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//\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 return {\n state: State.paused,\n /// Loaded item\n loaded: null,\n /// Live instance\n live: this.liveArgs ? new _live__WEBPACK_IMPORTED_MODULE_1__[\"default\"](this.liveArgs) : null,\n //! Active panel name\n panel: null,\n //! current playing playlist component\n playlist: null,\n //! players' playlists' sets\n sets: {\n queue: _model__WEBPACK_IMPORTED_MODULE_4__[\"Set\"].storeLoad(_sound__WEBPACK_IMPORTED_MODULE_3__[\"default\"], \"playlist.queue\", { max: 30, unique: true }),\n pin: _model__WEBPACK_IMPORTED_MODULE_4__[\"Set\"].storeLoad(_sound__WEBPACK_IMPORTED_MODULE_3__[\"default\"], \"player.pin\", { max: 30, unique: true }),\n history: _model__WEBPACK_IMPORTED_MODULE_4__[\"Set\"].storeLoad(_sound__WEBPACK_IMPORTED_MODULE_3__[\"default\"], \"player.history\", { max: 30, unique: true }),\n }\n }\n },\n\n props: {\n buttonTitle: String,\n liveArgs: Object,\n },\n\n computed: {\n paused() { return this.state == State.paused; },\n playing() { return this.state == State.playing; },\n loading() { return this.state == State.loading; },\n self() { return this; },\n\n current() {\n return this.loaded || this.live && this.live.current;\n },\n\n progress() {\n let audio = this.$refs.audio;\n return audio && Number.isFinite(audio.duration) && audio.duration ?\n audio.pos / audio.duration * 100 : null;\n },\n\n buttonStyle() {\n if(!this.current)\n return;\n return { backgroundImage: `url(${this.current.cover})` }\n },\n },\n\n methods: {\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.playlist && this.playlist == this.$refs[name] ? 'is-primary '\n : '') : '')\n + \"button has-text-weight-bold\";\n },\n\n /// Show/hide panel\n togglePanel(panel) {\n this.panel = this.panel == panel ? null : panel;\n },\n\n /// Return True if item is loaded\n isLoaded(item) {\n return this.loaded && this.loaded.src == item.src;\n },\n\n /// Return True if item is loaded\n isPlaying(item) {\n return this.isLoaded(item) && !this.player.paused;\n },\n\n load(playlist, {src=null, item=null}={}) {\n src = src || item.src;\n this.loaded = item;\n this.playlist = playlist ? this.$refs[playlist] : null;\n\n const audio = this.$refs.audio;\n if(src instanceof Array) {\n audio.innerHTML = '';\n for(var s of src) {\n let source = document.createElement(source);\n source.setAttribute('src', s);\n audio.appendChild(source)\n }\n }\n else {\n audio.src = src;\n }\n audio.load();\n },\n\n /// Play a playlist's sound (by playlist name, and sound index)\n play(playlist=null, index=0) {\n if(!playlist)\n playlist = 'queue';\n\n let item = this.$refs[playlist].get(index);\n if(item) {\n this.load(playlist, {item: item});\n this.sets.history.push(item);\n this.$refs.audio.play().catch(e => console.error(e))\n }\n else\n throw `No sound at index ${index} for playlist ${playlist}`;\n },\n\n /// Push items to playlist (by name)\n push(playlist, ...items) {\n this.$refs[playlist].push(...items);\n },\n\n /// Push and play items\n playItems(playlist, ...items) {\n this.push(playlist, ...items);\n\n let index = this.$refs[playlist].findIndex(items[0]);\n this.$refs[playlist].selectedIndex = index;\n this.play(playlist, index);\n },\n\n /// Play live stream\n playLive() {\n this.load(null, {src: this.live.src});\n this.$refs.audio.play().catch(e => console.error(e))\n this.panel = '';\n },\n\n /// Pause\n pause() {\n this.$refs.audio.pause()\n },\n\n //! Play/pause\n togglePlay() {\n if(this.paused)\n this.$refs.audio.play().catch(e => console.error(e))\n else\n this.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 if(!this.panel)\n this.panel = 'pin';\n }\n },\n\n /// Audio player state change event\n onState(event) {\n const audio = this.$refs.audio;\n this.state = audio.paused ? State.paused : State.playing;\n\n if(event.type == 'ended' && (!this.playlist || this.playlist.selectNext() == -1))\n this.playLive();\n },\n },\n\n mounted() {\n this.sources = this.$slots.sources;\n },\n\n components: { Playlist: _playlist__WEBPACK_IMPORTED_MODULE_2__[\"default\"] },\n});\n\n\n//# sourceURL=webpack:///./assets/public/player.vue?./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/vue-loader/lib/index.js?!./assets/public/playlist.vue?vue&type=script&lang=js&": +/*!***************************************************************************************************************!*\ + !*** ./node_modules/vue-loader/lib??vue-loader-options!./assets/public/playlist.vue?vue&type=script&lang=js& ***! + \***************************************************************************************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _list__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./list */ \"./assets/public/list.vue\");\n/* harmony import */ var _soundItem__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./soundItem */ \"./assets/public/soundItem.vue\");\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/* harmony default export */ __webpack_exports__[\"default\"] = ({\n extends: _list__WEBPACK_IMPORTED_MODULE_0__[\"default\"],\n\n props: {\n actions: Array,\n name: String,\n player: Object,\n editable: Boolean,\n },\n\n computed: {\n self() { return this; }\n },\n\n methods: {\n hasAction(action) { return this.actions && this.actions.indexOf(action) != -1; },\n\n selectNext() {\n let index = this.selectedIndex + 1;\n return this.select(index >= this.items.length ? -1 : index);\n },\n\n togglePlay(index) {\n if(this.player.isPlaying(this.set.get(index)))\n this.player.pause();\n else\n this.select(index)\n },\n },\n components: { List: _list__WEBPACK_IMPORTED_MODULE_0__[\"default\"], SoundItem: _soundItem__WEBPACK_IMPORTED_MODULE_1__[\"default\"] },\n});\n\n\n//# sourceURL=webpack:///./assets/public/playlist.vue?./node_modules/vue-loader/lib??vue-loader-options"); /***/ }), @@ -497,7 +545,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 import */ var _model__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./model */ \"./assets/public/model.js\");\n/* harmony import */ var _sound__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./sound */ \"./assets/public/sound.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/* harmony default export */ __webpack_exports__[\"default\"] = ({\n props: {\n data: {type: Object, default: x => {}},\n name: String,\n cover: String,\n set: Object,\n player: Object,\n page_url: String,\n activeClass: String,\n actions: {type:Array, default: x => []},\n },\n\n computed: {\n item() { return this.data instanceof _model__WEBPACK_IMPORTED_MODULE_0__[\"default\"] ? this.data : new _sound__WEBPACK_IMPORTED_MODULE_1__[\"default\"](this.data || {}); },\n active() { return this.player && this.player.isActive(this.item) },\n playing() { return this.player && this.player.playing && this.active },\n paused() { return this.player && this.player.paused && this.active },\n loading() { return this.player && this.player.loading && this.active },\n },\n\n methods: {\n hasAction(action) {\n return this.actions && this.actions.indexOf(action) != -1;\n },\n\n play() {\n if(this.player && this.active)\n this.player.togglePlay()\n else\n this.player.play(this.item);\n },\n\n push_to(playlist) {\n this.player.playlists[playlist].push(this.item, {unique_key:'id'});\n },\n }\n});\n\n\n//# sourceURL=webpack:///./assets/public/soundItem.vue?./node_modules/vue-loader/lib??vue-loader-options"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _model__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./model */ \"./assets/public/model.js\");\n/* harmony import */ var _sound__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./sound */ \"./assets/public/sound.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/* harmony default export */ __webpack_exports__[\"default\"] = ({\n props: {\n data: {type: Object, default: x => {}},\n name: String,\n cover: String,\n player: Object,\n page_url: String,\n actions: {type:Array, default: x => []},\n index: {type:Number, default: null},\n },\n\n computed: {\n item() { return this.data instanceof _model__WEBPACK_IMPORTED_MODULE_0__[\"default\"] ? this.data : new _sound__WEBPACK_IMPORTED_MODULE_1__[\"default\"](this.data || {}); },\n loaded() { return this.player && this.player.isLoaded(this.item) },\n playing() { return this.player && this.player.playing && this.loaded },\n paused() { return this.player && this.player.paused && this.loaded },\n loading() { return this.player && this.player.loading && this.loaded },\n pinned() { return this.player && this.player.sets.pin.find(this.item) },\n },\n\n methods: {\n hasAction(action) {\n return this.actions && this.actions.indexOf(action) != -1;\n },\n }\n});\n\n\n//# sourceURL=webpack:///./assets/public/soundItem.vue?./node_modules/vue-loader/lib??vue-loader-options"); /***/ }), @@ -533,7 +581,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(\n \"div\",\n [\n _vm._t(\"header\"),\n _vm._v(\" \"),\n _c(\n \"ul\",\n { class: _vm.listClass },\n [\n _vm._t(\"start\"),\n _vm._v(\" \"),\n _vm._l(_vm.items, function(item, index) {\n return [\n _c(\n \"li\",\n {\n class: _vm.itemClass,\n on: {\n click: function($event) {\n return _vm.select(index)\n }\n }\n },\n [\n _vm._t(\"item\", null, {\n set: _vm.set,\n index: index,\n item: item\n })\n ],\n 2\n )\n ]\n }),\n _vm._v(\" \"),\n _vm._t(\"end\")\n ],\n 2\n ),\n _vm._v(\" \"),\n _vm._t(\"footer\")\n ],\n 2\n )\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./assets/public/list.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(\n \"div\",\n [\n _vm._t(\"header\"),\n _vm._v(\" \"),\n _c(\n \"ul\",\n { class: _vm.listClass },\n [\n _vm._l(_vm.items, function(item, index) {\n return [\n _c(\n \"li\",\n {\n class: _vm.itemClass,\n on: {\n click: function($event) {\n return _vm.select(index)\n }\n }\n },\n [\n _vm._t(\"item\", null, {\n selected: index == _vm.selectedIndex,\n set: _vm.set,\n index: index,\n item: item\n })\n ],\n 2\n )\n ]\n })\n ],\n 2\n ),\n _vm._v(\" \"),\n _vm._t(\"footer\")\n ],\n 2\n )\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./assets/public/list.vue?./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib??vue-loader-options"); /***/ }), @@ -545,7 +593,19 @@ 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(\n \"div\",\n { staticClass: \"player\" },\n [\n _c(\"List\", {\n directives: [\n {\n name: \"show\",\n rawName: \"v-show\",\n value: _vm.panel == \"queue\" && _vm.queue.length,\n expression: \"panel == 'queue' && queue.length\"\n }\n ],\n ref: \"queue\",\n staticClass: \"player-panel menu\",\n attrs: {\n set: _vm.queue,\n listClass: \"menu-list\",\n itemClass: \"menu-item\"\n },\n on: { select: _vm.onSelect },\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 key: \"item\",\n fn: function(ref) {\n var item = ref.item\n var index = ref.index\n var set = ref.set\n return [\n _c(\"SoundItem\", {\n attrs: {\n activeClass: \"is-active\",\n data: item,\n player: _vm.self,\n set: set,\n actions: [\"remove\"]\n },\n scopedSlots: _vm._u(\n [\n {\n key: \"actions\",\n fn: function(ref) {\n var active = ref.active\n var set = ref.set\n return undefined\n }\n }\n ],\n null,\n true\n )\n })\n ]\n }\n }\n ])\n }),\n _vm._v(\" \"),\n _c(\"List\", {\n directives: [\n {\n name: \"show\",\n rawName: \"v-show\",\n value: _vm.panel == \"history\" && _vm.history.length,\n expression: \"panel == 'history' && history.length\"\n }\n ],\n ref: \"history\",\n staticClass: \"player-panel menu\",\n attrs: {\n set: _vm.history,\n listClass: \"menu-list\",\n itemClass: \"menu-item\"\n },\n on: { select: _vm.onSelect },\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-clock\" })\n ]),\n _vm._v(\"\\n History\\n \")\n ])\n ]\n },\n proxy: true\n },\n {\n key: \"item\",\n fn: function(ref) {\n var item = ref.item\n var index = ref.index\n var set = ref.set\n return [\n _c(\"SoundItem\", {\n attrs: {\n activeClass: \"is-active\",\n data: item,\n player: _vm.self,\n set: set,\n actions: [\"queue\", \"remove\"]\n }\n })\n ]\n }\n }\n ])\n }),\n _vm._v(\" \"),\n _c(\"div\", { staticClass: \"player-bar media\" }, [\n _c(\n \"div\",\n { staticClass: \"media-left\" },\n [\n _c(\n \"div\",\n {\n staticClass: \"button\",\n attrs: {\n title: _vm.buttonTitle,\n \"aria-label\": _vm.buttonTitle\n },\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 _vm._v(\" \"),\n _c(\"audio\", {\n ref: \"audio\",\n attrs: { preload: \"metadata\" },\n on: {\n playing: _vm.onState,\n ended: _vm.onState,\n pause: _vm.onState\n }\n }),\n _vm._v(\" \"),\n _vm._t(\"sources\")\n ],\n 2\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 [_vm._t(\"content\", null, { current: _vm.current })],\n 2\n ),\n _vm._v(\" \"),\n _c(\"div\", { staticClass: \"media-right\" }, [\n _vm.active\n ? _c(\n \"button\",\n {\n staticClass: \"button\",\n on: {\n click: function($event) {\n _vm.load() && _vm.play()\n }\n }\n },\n [_vm._m(0), _vm._v(\" \"), _c(\"span\", [_vm._v(\"Live\")])]\n )\n : _vm._e(),\n _vm._v(\" \"),\n _vm.history.length\n ? _c(\n \"button\",\n {\n staticClass: \"button\",\n class: [_vm.panel == \"history\" ? \"is-info\" : \"\"],\n on: {\n click: function($event) {\n return _vm.togglePanel(\"history\")\n }\n }\n },\n [_vm._m(1)]\n )\n : _vm._e(),\n _vm._v(\" \"),\n _vm.queue.length\n ? _c(\n \"button\",\n {\n staticClass: \"button\",\n class: [_vm.panel == \"queue\" ? \"is-info\" : \"\"],\n on: {\n click: function($event) {\n return _vm.togglePanel(\"queue\")\n }\n }\n },\n [\n _c(\"span\", { staticClass: \"mr-2 is-size-6\" }, [\n _vm._v(_vm._s(_vm.queue.length))\n ]),\n _vm._v(\" \"),\n _vm._m(2)\n ]\n )\n : _vm._e()\n ])\n ]),\n _vm._v(\" \"),\n _vm.progress\n ? _c(\"div\", [_c(\"span\", { style: { width: _vm.progress } })])\n : _vm._e()\n ],\n 1\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 has-text-danger\" }, [\n _c(\"span\", { staticClass: \"fa fa-broadcast-tower\" })\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-clock\" })\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(\n \"div\",\n { staticClass: \"player\" },\n [\n _c(\"Playlist\", {\n directives: [\n {\n name: \"show\",\n rawName: \"v-show\",\n value: _vm.panel == \"history\",\n expression: \"panel == 'history'\"\n }\n ],\n ref: \"history\",\n staticClass: \"panel-menu menu\",\n attrs: {\n name: \"History\",\n editable: true,\n player: _vm.self,\n set: _vm.sets.history,\n listClass: \"menu-list\",\n itemClass: \"menu-item\"\n },\n on: {\n select: function($event) {\n return _vm.play(\"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-clock\" })\n ]),\n _vm._v(\"\\n History\\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 == \"pin\",\n expression: \"panel == 'pin'\"\n }\n ],\n ref: \"pin\",\n staticClass: \"player-panel menu\",\n attrs: {\n name: \"Pinned\",\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.play(\"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 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.play(\"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 _vm._v(\" \"),\n _c(\"div\", { staticClass: \"player-bar media\" }, [\n _c(\n \"div\",\n { staticClass: \"media-left\" },\n [\n _c(\n \"div\",\n {\n staticClass: \"button\",\n attrs: {\n title: _vm.buttonTitle,\n \"aria-label\": _vm.buttonTitle\n },\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 _vm._v(\" \"),\n _c(\"audio\", {\n ref: \"audio\",\n attrs: { preload: \"metadata\" },\n on: {\n playing: _vm.onState,\n ended: _vm.onState,\n pause: _vm.onState\n }\n }),\n _vm._v(\" \"),\n _vm._t(\"sources\")\n ],\n 2\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 [_vm._t(\"content\", null, { current: _vm.current })],\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.playLive()\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 class: _vm.playlistButtonClass(\"history\"),\n on: {\n click: function($event) {\n return _vm.togglePanel(\"history\")\n }\n }\n },\n [\n _vm.sets.history.length\n ? _c(\"span\", { staticClass: \"mr-2 is-size-6\" }, [\n _vm._v(\n \"\\n \" + _vm._s(_vm.sets.history.length)\n )\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(\"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 \"\\n \" + _vm._s(_vm.sets.pin.length)\n )\n ])\n : _vm._e(),\n _vm._v(\" \"),\n _vm._m(2)\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(3)\n ]\n )\n ])\n ]),\n _vm._v(\" \"),\n _vm.progress\n ? _c(\"div\", [_c(\"span\", { style: { width: _vm.progress } })])\n : _vm._e()\n ],\n 1\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 has-text-danger\" }, [\n _c(\"span\", { staticClass: \"fa fa-broadcast-tower\" })\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-clock\" })\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"); + +/***/ }), + +/***/ "./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/vue-loader/lib/index.js?!./assets/public/playlist.vue?vue&type=template&id=c0d17d8c&": +/*!*************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib??vue-loader-options!./assets/public/playlist.vue?vue&type=template&id=c0d17d8c& ***! + \*************************************************************************************************************************************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (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(\n \"div\",\n [\n _vm._t(\"header\"),\n _vm._v(\" \"),\n _c(\n \"ul\",\n { class: _vm.listClass },\n _vm._l(_vm.items, function(item, index) {\n return _c(\n \"li\",\n {\n class: _vm.itemClass,\n on: {\n click: function($event) {\n !_vm.hasAction(\"play\") && _vm.select(index)\n }\n }\n },\n [\n _c(\n \"a\",\n { class: index == _vm.selectedIndex ? \"is-active\" : \"\" },\n [\n _c(\"SoundItem\", {\n attrs: {\n data: item,\n index: index,\n player: _vm.player,\n set: _vm.set,\n actions: _vm.actions\n },\n on: {\n togglePlay: function($event) {\n return _vm.togglePlay(index)\n }\n },\n scopedSlots: _vm._u(\n [\n {\n key: \"actions\",\n fn: function(ref) {\n var loaded = ref.loaded\n var set = ref.set\n return [\n _vm.editable\n ? _c(\n \"button\",\n {\n staticClass: \"button\",\n on: {\n click: function($event) {\n $event.stopPropagation()\n return _vm.remove(index, true)\n }\n }\n },\n [\n _c(\n \"span\",\n { staticClass: \"icon is-small\" },\n [\n _c(\"span\", {\n staticClass: \"fa fa-minus\"\n })\n ]\n )\n ]\n )\n : _vm._e()\n ]\n }\n }\n ],\n null,\n true\n )\n })\n ],\n 1\n )\n ]\n )\n }),\n 0\n ),\n _vm._v(\" \"),\n _vm._t(\"footer\")\n ],\n 2\n )\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./assets/public/playlist.vue?./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib??vue-loader-options"); /***/ }), @@ -557,7 +617,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(\n \"a\",\n {\n class: [_vm.active ? _vm.activeClass : \"\"],\n on: {\n click: function($event) {\n _vm.actions.indexOf(\"play\") == -1 && _vm.play()\n }\n }\n },\n [\n _c(\"div\", { staticClass: \"media\" }, [\n _vm.hasAction(\"play\")\n ? _c(\"div\", { staticClass: \"media-left\" }, [\n _c(\n \"button\",\n {\n staticClass: \"button\",\n on: {\n click: function($event) {\n return _vm.play()\n }\n }\n },\n [\n _c(\"div\", { staticClass: \"icon\" }, [\n _vm.playing || _vm.loading\n ? _c(\"span\", { staticClass: \"fa fa-pause\" })\n : _c(\"span\", { staticClass: \"fa fa-play\" })\n ])\n ]\n )\n ])\n : _vm._e(),\n _vm._v(\" \"),\n _c(\n \"div\",\n { staticClass: \"media-content\" },\n [\n _vm._t(\n \"content\",\n [\n _c(\"h4\", { staticClass: \"title is-4 is-inline-block\" }, [\n _vm._v(\n \"\\n \" +\n _vm._s(_vm.name || _vm.item.name) +\n \"\\n \"\n )\n ])\n ],\n { player: _vm.player, item: _vm.item, active: _vm.active }\n )\n ],\n 2\n ),\n _vm._v(\" \"),\n _c(\n \"div\",\n { staticClass: \"media-right\" },\n [\n _vm.hasAction(\"queue\")\n ? _c(\n \"button\",\n {\n staticClass: \"button\",\n on: {\n click: function($event) {\n $event.stopPropagation()\n return _vm.player.push(_vm.item)\n }\n }\n },\n [_vm._m(0)]\n )\n : _vm._e(),\n _vm._v(\" \"),\n _vm.hasAction(\"remove\")\n ? _c(\n \"button\",\n {\n staticClass: \"button\",\n on: {\n click: function($event) {\n $event.stopPropagation()\n return _vm.set.remove(_vm.item)\n }\n }\n },\n [_vm._m(1)]\n )\n : _vm._e(),\n _vm._v(\" \"),\n _vm._t(\"actions\", null, {\n player: _vm.player,\n item: _vm.item,\n active: _vm.active\n })\n ],\n 2\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-small\" }, [\n _c(\"span\", { staticClass: \"fa fa-list\" })\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 is-small\" }, [\n _c(\"span\", { staticClass: \"fa fa-minus\" })\n ])\n }\n]\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./assets/public/soundItem.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: \"media\" }, [\n _vm.hasAction(\"play\")\n ? _c(\"div\", { staticClass: \"media-left\" }, [\n _c(\n \"button\",\n {\n staticClass: \"button\",\n on: {\n click: function($event) {\n return _vm.$emit(\"togglePlay\")\n }\n }\n },\n [\n _c(\"div\", { staticClass: \"icon\" }, [\n _vm.playing || _vm.loading\n ? _c(\"span\", { staticClass: \"fa fa-pause\" })\n : _c(\"span\", { staticClass: \"fa fa-play\" })\n ])\n ]\n )\n ])\n : _vm._e(),\n _vm._v(\" \"),\n _c(\n \"div\",\n { staticClass: \"media-content\" },\n [\n _vm._t(\n \"content\",\n [\n _c(\"h4\", { staticClass: \"title is-4 is-inline-block\" }, [\n _vm._v(\n \"\\n \" +\n _vm._s(_vm.name || _vm.item.name) +\n \"\\n \"\n )\n ])\n ],\n { player: _vm.player, item: _vm.item, loaded: _vm.loaded }\n )\n ],\n 2\n ),\n _vm._v(\" \"),\n _c(\n \"div\",\n { staticClass: \"media-right\" },\n [\n _vm.player.$refs.pin != _vm.$parent\n ? _c(\n \"button\",\n {\n staticClass: \"button\",\n on: {\n click: function($event) {\n $event.stopPropagation()\n return _vm.player.togglePin(_vm.item)\n }\n }\n },\n [\n _c(\"span\", { staticClass: \"icon is-small\" }, [\n _c(\"span\", {\n class:\n (_vm.pinned ? \"\" : \"has-text-grey-light \") +\n \"fa fa-thumbtack\"\n })\n ])\n ]\n )\n : _vm._e(),\n _vm._v(\" \"),\n _vm._t(\"actions\", null, {\n player: _vm.player,\n item: _vm.item,\n loaded: _vm.loaded\n })\n ],\n 2\n )\n ])\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./assets/public/soundItem.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.js b/aircox/static/aircox/main.js index 76830b0..b963a20 100644 --- a/aircox/static/aircox/main.js +++ b/aircox/static/aircox/main.js @@ -159,11 +159,11 @@ /*!******************************!*\ !*** ./assets/public/app.js ***! \******************************/ -/*! exports provided: defaultConfig, App, AppConfig */ +/*! exports provided: defaultConfig, default, AppConfig */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"defaultConfig\", function() { return defaultConfig; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"App\", function() { return App; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AppConfig\", function() { return AppConfig; });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.browser.js\");\n\n\n\nconst defaultConfig = {\n el: '#app',\n delimiters: ['[[', ']]'],\n\n computed: {\n player() {\n return window.aircox.player;\n }\n }\n}\n\nfunction App(config) {\n return (new AppConfig(config)).load()\n}\n\n/**\n * Application config for an application instance\n */\nclass AppConfig {\n constructor(config) {\n this._config = config;\n }\n\n get config() {\n let config = this._config instanceof Function ? this._config() : this._config;\n return {...defaultConfig, ...config};\n }\n\n set config(value) {\n this._config = value;\n }\n\n load() {\n var self = this;\n return new Promise(function(resolve, reject) {\n window.addEventListener('load', () => {\n try {\n let config = self.config;\n const el = document.querySelector(config.el)\n if(!el) {\n reject(`Error: missing element ${config.el}`);\n return;\n }\n resolve(new vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"](config))\n }\n catch(error) { reject(error) }\n })\n });\n }\n}\n\n\n\n\n//# sourceURL=webpack:///./assets/public/app.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"defaultConfig\", function() { return defaultConfig; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return App; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AppConfig\", function() { return AppConfig; });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.browser.js\");\n\n\n\nconst defaultConfig = {\n el: '#app',\n delimiters: ['[[', ']]'],\n\n data() {\n return {\n page: null,\n }\n },\n\n computed: {\n player() { return window.aircox.player; }\n },\n}\n\nfunction App(config) {\n return (new AppConfig(config)).load()\n}\n\n/**\n * Application config for an application instance\n */\nclass AppConfig {\n constructor(config) {\n this._config = config;\n }\n\n get config() {\n let config = this._config instanceof Function ? this._config() : this._config;\n return {...defaultConfig, ...config};\n }\n\n set config(value) {\n this._config = value;\n }\n\n load() {\n var self = this;\n return new Promise(function(resolve, reject) {\n window.addEventListener('load', () => {\n try {\n let config = self.config;\n const el = document.querySelector(config.el)\n if(!el) {\n reject(`Error: missing element ${config.el}`);\n return;\n }\n resolve(new vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"](config))\n }\n catch(error) { reject(error) }\n })\n });\n }\n}\n\n\n\n\n//# sourceURL=webpack:///./assets/public/app.js?"); /***/ }), @@ -211,7 +211,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _nod /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.browser.js\");\n/* harmony import */ var _fortawesome_fontawesome_free_css_all_min_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @fortawesome/fontawesome-free/css/all.min.css */ \"./node_modules/@fortawesome/fontawesome-free/css/all.min.css\");\n/* harmony import */ var _fortawesome_fontawesome_free_css_all_min_css__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_fortawesome_fontawesome_free_css_all_min_css__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _fortawesome_fontawesome_free_css_fontawesome_min_css__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @fortawesome/fontawesome-free/css/fontawesome.min.css */ \"./node_modules/@fortawesome/fontawesome-free/css/fontawesome.min.css\");\n/* harmony import */ var _fortawesome_fontawesome_free_css_fontawesome_min_css__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_fortawesome_fontawesome_free_css_fontawesome_min_css__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _app__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./app */ \"./assets/public/app.js\");\n/* harmony import */ var _styles_scss__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./styles.scss */ \"./assets/public/styles.scss\");\n/* harmony import */ var _styles_scss__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_styles_scss__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var _autocomplete_vue__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./autocomplete.vue */ \"./assets/public/autocomplete.vue\");\n/* harmony import */ var _player_vue__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./player.vue */ \"./assets/public/player.vue\");\n/* harmony import */ var _soundItem__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./soundItem */ \"./assets/public/soundItem.vue\");\n/**\n * This module includes code available for both the public website and\n * administration interface)\n */\n//-- vendor\n\n\n\n\n\n\n//-- aircox\n\n\n\n\n\n\n\n\nvue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].component('a-autocomplete', _autocomplete_vue__WEBPACK_IMPORTED_MODULE_5__[\"default\"])\nvue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].component('a-player', _player_vue__WEBPACK_IMPORTED_MODULE_6__[\"default\"])\nvue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].component('a-sound-item', _soundItem__WEBPACK_IMPORTED_MODULE_7__[\"default\"])\n\n\nwindow.aircox = {\n // main application\n app: null,\n\n // main application config\n appConfig: {},\n\n // player application\n playerApp: null,\n\n // player component\n get player() {\n return this.playerApp && this.playerApp.$refs.player\n }\n};\n\n\nObject(_app__WEBPACK_IMPORTED_MODULE_3__[\"App\"])({el: '#player'}).then(app => window.aircox.playerApp = app,\n () => undefined);\nObject(_app__WEBPACK_IMPORTED_MODULE_3__[\"App\"])(() => window.aircox.appConfig).then(app => { window.aircox.app = app },\n () => undefined)\n\n\n\n\n//# sourceURL=webpack:///./assets/public/index.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.browser.js\");\n/* harmony import */ var _fortawesome_fontawesome_free_css_all_min_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @fortawesome/fontawesome-free/css/all.min.css */ \"./node_modules/@fortawesome/fontawesome-free/css/all.min.css\");\n/* harmony import */ var _fortawesome_fontawesome_free_css_all_min_css__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_fortawesome_fontawesome_free_css_all_min_css__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _fortawesome_fontawesome_free_css_fontawesome_min_css__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @fortawesome/fontawesome-free/css/fontawesome.min.css */ \"./node_modules/@fortawesome/fontawesome-free/css/fontawesome.min.css\");\n/* harmony import */ var _fortawesome_fontawesome_free_css_fontawesome_min_css__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_fortawesome_fontawesome_free_css_fontawesome_min_css__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _app__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./app */ \"./assets/public/app.js\");\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/* harmony import */ var _styles_scss__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./styles.scss */ \"./assets/public/styles.scss\");\n/* harmony import */ var _styles_scss__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(_styles_scss__WEBPACK_IMPORTED_MODULE_6__);\n/* harmony import */ var _autocomplete_vue__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./autocomplete.vue */ \"./assets/public/autocomplete.vue\");\n/* harmony import */ var _player_vue__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./player.vue */ \"./assets/public/player.vue\");\n/* harmony import */ var _playlist_vue__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./playlist.vue */ \"./assets/public/playlist.vue\");\n/* harmony import */ var _soundItem__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./soundItem */ \"./assets/public/soundItem.vue\");\n/**\n * This module includes code available for both the public website and\n * administration interface)\n */\n//-- vendor\n\n\n\n\n\n\n//-- aircox\n\n\n\n\n\n\n\n\n\n\n\nvue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].component('a-autocomplete', _autocomplete_vue__WEBPACK_IMPORTED_MODULE_7__[\"default\"])\nvue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].component('a-player', _player_vue__WEBPACK_IMPORTED_MODULE_8__[\"default\"])\nvue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].component('a-playlist', _playlist_vue__WEBPACK_IMPORTED_MODULE_9__[\"default\"])\nvue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].component('a-sound-item', _soundItem__WEBPACK_IMPORTED_MODULE_10__[\"default\"])\n\n\nwindow.aircox = {\n // main application\n app: null,\n\n // main application config\n appConfig: {},\n\n // player application\n playerApp: null,\n\n // player component\n get player() {\n return this.playerApp && this.playerApp.$refs.player\n },\n\n Set: _model__WEBPACK_IMPORTED_MODULE_5__[\"Set\"], Sound: _sound__WEBPACK_IMPORTED_MODULE_4__[\"default\"],\n};\nwindow.Vue = vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"];\n\n\nObject(_app__WEBPACK_IMPORTED_MODULE_3__[\"default\"])({el: '#player'}).then(app => window.aircox.playerApp = app,\n () => undefined);\nObject(_app__WEBPACK_IMPORTED_MODULE_3__[\"default\"])(() => window.aircox.appConfig).then(app => { window.aircox.app = app },\n () => undefined)\n\n\n\n\n//# sourceURL=webpack:///./assets/public/index.js?"); /***/ }), @@ -271,7 +271,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__, \"getCsrf\", function() { return getCsrf; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return Model; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Set\", function() { return Set; });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.browser.js\");\n\n\nfunction getCookie(name) {\n if(document.cookie && document.cookie !== '') {\n const cookie = document.cookie.split(';')\n .find(c => c.trim().startsWith(name + '='))\n return cookie ? decodeURIComponent(cookie.split('=')[1]) : null;\n }\n return null;\n}\n\nvar csrfToken = null;\n\nfunction getCsrf() {\n if(csrfToken === null)\n csrfToken = getCookie('csrftoken')\n return csrfToken;\n}\n\n\n// TODO: prevent duplicate simple fetch\nclass Model {\n constructor(data, {url=null}={}) {\n this.url = url;\n this.commit(data);\n }\n\n /**\n * Get instance id from its data\n */\n static getId(data) {\n return data.id;\n }\n\n /**\n * Return fetch options\n */\n static getOptions(options) {\n return {\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n 'X-CSRFToken': getCsrf(),\n },\n ...options,\n }\n }\n\n /**\n * Fetch item from server\n */\n static fetch(url, options=null, args=null) {\n options = this.getOptions(options)\n return fetch(url, options)\n .then(response => response.json())\n .then(data => new this(data, {url: url, ...args}));\n }\n\n /**\n * Fetch data from server.\n */\n fetch(options) {\n options = this.constructor.getOptions(options)\n return fetch(this.url, options)\n .then(response => response.json())\n .then(data => this.commit(data));\n }\n\n /**\n * Call API action on object.\n */\n action(path, options, commit=false) {\n options = this.constructor.getOptions(options)\n const promise = fetch(this.url + path, options);\n return commit ? promise.then(data => data.json())\n .then(data => { this.commit(data); this.data })\n : promise;\n }\n\n /**\n * Update instance's data with provided data. Return None\n */\n commit(data) {\n this.id = this.constructor.getId(data);\n vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].set(this, 'data', data);\n }\n\n /**\n * Save instance into localStorage.\n */\n store(key) {\n window.localStorage.setItem(key, JSON.stringify(this.data));\n }\n\n /**\n * Load model instance from localStorage.\n */\n static storeLoad(key) {\n let item = window.localStorage.getItem(key);\n return item === null ? item : new this(JSON.parse(item));\n }\n}\n\n\n/**\n * List of models\n */\nclass Set {\n constructor(model, {items=[],url=null,args={},unique=null,max=null,storeKey=null}={}) {\n this.items = items.map(x => x instanceof model ? x : new model(x, args));\n this.model = model;\n this.url = url;\n this.unique = unique;\n this.max = max;\n this.storeKey = storeKey;\n }\n\n get length() { return this.items.length }\n indexOf(...args) { return this.items.indexOf(...args); }\n\n /**\n * Fetch multiple items from server\n */\n static fetch(url, options=null, args=null) {\n options = this.getOptions(options)\n return fetch(url, options)\n .then(response => response.json())\n .then(data => (data instanceof Array ? data : data.results)\n .map(d => new this.model(d, {url: url, ...args})))\n }\n\n /**\n * Load list from localStorage\n */\n static storeLoad(model, key, args={}) {\n let items = window.localStorage.getItem(key);\n return new this(model, {...args, storeKey: key, items: items ? JSON.parse(items) : []});\n }\n\n /**\n * Store list into localStorage\n */\n store() {\n if(this.storeKey)\n window.localStorage.setItem(this.storeKey, JSON.stringify(\n this.items.map(i => i.data)));\n }\n\n push(item, {args={}}={}) {\n item = item instanceof this.model ? item : new this.model(item, args);\n if(this.unique && this.items.find(x => x.id == item.id))\n return;\n if(this.max && this.items.length >= this.max)\n this.items.splice(0,this.items.length-this.max)\n\n this.items.push(item);\n this._updated()\n }\n\n remove(item, {args={}}={}) {\n item = item instanceof this.model ? item : new this.model(item, args);\n let index = this.items.findIndex(x => x.id == item.id);\n if(index == -1)\n return;\n\n this.items.splice(index,1);\n this._updated()\n }\n\n _updated() {\n vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].set(this, 'items', this.items);\n this.store();\n }\n}\n\nSet[Symbol.iterator] = function () {\n return this.items[Symbol.iterator]();\n}\n\n\n\n//# sourceURL=webpack:///./assets/public/model.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"getCsrf\", function() { return getCsrf; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return Model; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Set\", function() { return Set; });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.browser.js\");\n\n\nfunction getCookie(name) {\n if(document.cookie && document.cookie !== '') {\n const cookie = document.cookie.split(';')\n .find(c => c.trim().startsWith(name + '='))\n return cookie ? decodeURIComponent(cookie.split('=')[1]) : null;\n }\n return null;\n}\n\nvar csrfToken = null;\n\nfunction getCsrf() {\n if(csrfToken === null)\n csrfToken = getCookie('csrftoken')\n return csrfToken;\n}\n\n\n// TODO: prevent duplicate simple fetch\nclass Model {\n constructor(data, {url=null}={}) {\n this.url = url;\n this.commit(data);\n }\n\n /**\n * Get instance id from its data\n */\n static getId(data) {\n return data.id;\n }\n\n /**\n * Return fetch options\n */\n static getOptions(options) {\n return {\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n 'X-CSRFToken': getCsrf(),\n },\n ...options,\n }\n }\n\n /**\n * Fetch item from server\n */\n static fetch(url, options=null, args=null) {\n options = this.getOptions(options)\n return fetch(url, options)\n .then(response => response.json())\n .then(data => new this(data, {url: url, ...args}));\n }\n\n /**\n * Fetch data from server.\n */\n fetch(options) {\n options = this.constructor.getOptions(options)\n return fetch(this.url, options)\n .then(response => response.json())\n .then(data => this.commit(data));\n }\n\n /**\n * Call API action on object.\n */\n action(path, options, commit=false) {\n options = this.constructor.getOptions(options)\n const promise = fetch(this.url + path, options);\n return commit ? promise.then(data => data.json())\n .then(data => { this.commit(data); this.data })\n : promise;\n }\n\n /**\n * Update instance's data with provided data. Return None\n */\n commit(data) {\n this.id = this.constructor.getId(data);\n vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].set(this, 'data', data);\n }\n\n /**\n * Save instance into localStorage.\n */\n store(key) {\n window.localStorage.setItem(key, JSON.stringify(this.data));\n }\n\n /**\n * Load model instance from localStorage.\n */\n static storeLoad(key) {\n let item = window.localStorage.getItem(key);\n return item === null ? item : new this(JSON.parse(item));\n }\n}\n\n\n/**\n * List of models\n */\nclass Set {\n constructor(model, {items=[],url=null,args={},unique=null,max=null,storeKey=null}={}) {\n this.items = [];\n this.model = model;\n this.url = url;\n this.unique = unique;\n this.max = max;\n this.storeKey = storeKey;\n\n for(var item of items)\n this.push(item, {args: args, save: false});\n }\n\n get length() { return this.items.length }\n get(index) { return this.items[index] }\n\n /**\n * Fetch multiple items from server\n */\n static fetch(url, options=null, args=null) {\n options = this.getOptions(options)\n return fetch(url, options)\n .then(response => response.json())\n .then(data => (data instanceof Array ? data : data.results)\n .map(d => new this.model(d, {url: url, ...args})))\n }\n\n /**\n * Load list from localStorage\n */\n static storeLoad(model, key, args={}) {\n let items = window.localStorage.getItem(key);\n return new this(model, {...args, storeKey: key, items: items ? JSON.parse(items) : []});\n }\n\n /**\n * Store list into localStorage\n */\n store() {\n this.storeKey && window.localStorage.setItem(this.storeKey, JSON.stringify(\n this.items.map(i => i.data)));\n }\n\n /**\n * Save item\n */\n save() {\n this.storeKey && this.store();\n }\n\n /**\n * Find item by id\n */\n find(item) {\n return this.items.find(x => x.id == item.id);\n }\n\n /**\n * Find item index by id\n */\n findIndex(item) {\n return this.items.findIndex(x => x.id == item.id);\n }\n\n /**\n * Add item to set\n */\n push(item, {args={},save=true}={}) {\n item = item instanceof this.model ? item : new this.model(item, args);\n if(this.unique) {\n let index = this.findIndex(item);\n if(index > -1)\n this.items.splice(index,1);\n }\n if(this.max && this.items.length >= this.max)\n this.items.splice(0,this.items.length-this.max)\n\n this.items.push(item);\n save && this.save();\n }\n\n /**\n * Remove item from set by index\n */\n remove(index, {save=true}={}) {\n this.items.splice(index,1);\n save && this.save();\n }\n}\n\nSet[Symbol.iterator] = function () {\n return this.items[Symbol.iterator]();\n}\n\n\n\n//# sourceURL=webpack:///./assets/public/model.js?"); /***/ }), @@ -279,11 +279,11 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) * /*!**********************************!*\ !*** ./assets/public/player.vue ***! \**********************************/ -/*! exports provided: State, default */ +/*! no static exports found */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _player_vue_vue_type_template_id_42a56ec9___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./player.vue?vue&type=template&id=42a56ec9& */ \"./assets/public/player.vue?vue&type=template&id=42a56ec9&\");\n/* harmony import */ var _player_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./player.vue?vue&type=script&lang=js& */ \"./assets/public/player.vue?vue&type=script&lang=js&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"State\", function() { return _player_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"State\"]; });\n\n/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ \"./node_modules/vue-loader/lib/runtime/componentNormalizer.js\");\n\n\n\n\n\n/* normalize component */\n\nvar component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(\n _player_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n _player_vue_vue_type_template_id_42a56ec9___WEBPACK_IMPORTED_MODULE_0__[\"render\"],\n _player_vue_vue_type_template_id_42a56ec9___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"],\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"assets/public/player.vue\"\n/* harmony default export */ __webpack_exports__[\"default\"] = (component.exports);\n\n//# sourceURL=webpack:///./assets/public/player.vue?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _player_vue_vue_type_template_id_42a56ec9___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./player.vue?vue&type=template&id=42a56ec9& */ \"./assets/public/player.vue?vue&type=template&id=42a56ec9&\");\n/* harmony import */ var _player_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./player.vue?vue&type=script&lang=js& */ \"./assets/public/player.vue?vue&type=script&lang=js&\");\n/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _player_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__) if([\"default\"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _player_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[key]; }) }(__WEBPACK_IMPORT_KEY__));\n/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ \"./node_modules/vue-loader/lib/runtime/componentNormalizer.js\");\n\n\n\n\n\n/* normalize component */\n\nvar component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(\n _player_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n _player_vue_vue_type_template_id_42a56ec9___WEBPACK_IMPORTED_MODULE_0__[\"render\"],\n _player_vue_vue_type_template_id_42a56ec9___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"],\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"assets/public/player.vue\"\n/* harmony default export */ __webpack_exports__[\"default\"] = (component.exports);\n\n//# sourceURL=webpack:///./assets/public/player.vue?"); /***/ }), @@ -291,7 +291,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _pla /*!***********************************************************!*\ !*** ./assets/public/player.vue?vue&type=script&lang=js& ***! \***********************************************************/ -/*! exports provided: default, State */ +/*! no static exports found */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -311,6 +311,42 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _nod /***/ }), +/***/ "./assets/public/playlist.vue": +/*!************************************!*\ + !*** ./assets/public/playlist.vue ***! + \************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _playlist_vue_vue_type_template_id_c0d17d8c___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./playlist.vue?vue&type=template&id=c0d17d8c& */ \"./assets/public/playlist.vue?vue&type=template&id=c0d17d8c&\");\n/* harmony import */ var _playlist_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./playlist.vue?vue&type=script&lang=js& */ \"./assets/public/playlist.vue?vue&type=script&lang=js&\");\n/* empty/unused harmony star reexport *//* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ \"./node_modules/vue-loader/lib/runtime/componentNormalizer.js\");\n\n\n\n\n\n/* normalize component */\n\nvar component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(\n _playlist_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n _playlist_vue_vue_type_template_id_c0d17d8c___WEBPACK_IMPORTED_MODULE_0__[\"render\"],\n _playlist_vue_vue_type_template_id_c0d17d8c___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"],\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = \"assets/public/playlist.vue\"\n/* harmony default export */ __webpack_exports__[\"default\"] = (component.exports);\n\n//# sourceURL=webpack:///./assets/public/playlist.vue?"); + +/***/ }), + +/***/ "./assets/public/playlist.vue?vue&type=script&lang=js&": +/*!*************************************************************!*\ + !*** ./assets/public/playlist.vue?vue&type=script&lang=js& ***! + \*************************************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_vue_loader_lib_index_js_vue_loader_options_playlist_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../node_modules/vue-loader/lib??vue-loader-options!./playlist.vue?vue&type=script&lang=js& */ \"./node_modules/vue-loader/lib/index.js?!./assets/public/playlist.vue?vue&type=script&lang=js&\");\n/* empty/unused harmony star reexport */ /* harmony default export */ __webpack_exports__[\"default\"] = (_node_modules_vue_loader_lib_index_js_vue_loader_options_playlist_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__[\"default\"]); \n\n//# sourceURL=webpack:///./assets/public/playlist.vue?"); + +/***/ }), + +/***/ "./assets/public/playlist.vue?vue&type=template&id=c0d17d8c&": +/*!*******************************************************************!*\ + !*** ./assets/public/playlist.vue?vue&type=template&id=c0d17d8c& ***! + \*******************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_playlist_vue_vue_type_template_id_c0d17d8c___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!../../node_modules/vue-loader/lib??vue-loader-options!./playlist.vue?vue&type=template&id=c0d17d8c& */ \"./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/vue-loader/lib/index.js?!./assets/public/playlist.vue?vue&type=template&id=c0d17d8c&\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"render\", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_playlist_vue_vue_type_template_id_c0d17d8c___WEBPACK_IMPORTED_MODULE_0__[\"render\"]; });\n\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"staticRenderFns\", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_playlist_vue_vue_type_template_id_c0d17d8c___WEBPACK_IMPORTED_MODULE_0__[\"staticRenderFns\"]; });\n\n\n\n//# sourceURL=webpack:///./assets/public/playlist.vue?"); + +/***/ }), + /***/ "./assets/public/sound.js": /*!********************************!*\ !*** ./assets/public/sound.js ***! @@ -402,7 +438,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var loda /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n data() {\n return {\n selectedIndex: this.default,\n }\n },\n\n props: {\n listClass: String,\n itemClass: String,\n default: { type: Number, default: -1},\n set: Object,\n },\n\n computed: {\n model() { return this.set.model },\n items() { return this.set.items },\n length() { return this.set.length },\n\n selected() {\n return this.items && this.items.length > this.selectedIndex > -1\n ? this.items[this.selectedIndex] : null;\n },\n },\n\n methods: {\n select(index=null) {\n if(index === null)\n index = this.selectedIndex;\n else if(this.selectedIndex == index)\n return;\n\n this.selectedIndex = Math.min(index, this.items.length-1);\n this.$emit('select', { item: this.selected, index: this.selectedIndex });\n return this.selectedIndex;\n },\n\n selectNext() {\n let index = this.selectedIndex + 1;\n return this.select(index >= this.items.length ? -1 : index);\n },\n\n // add()\n // insert() + drag & drop\n // remove()\n },\n});\n\n\n//# sourceURL=webpack:///./assets/public/list.vue?./node_modules/vue-loader/lib??vue-loader-options"); +eval("__webpack_require__.r(__webpack_exports__);\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n data() {\n return {\n selectedIndex: this.defaultIndex,\n }\n },\n\n props: {\n listClass: String,\n itemClass: String,\n defaultIndex: { type: Number, default: -1},\n set: Object,\n },\n\n computed: {\n model() { return this.set.model },\n items() { return this.set.items },\n length() { return this.set.length },\n\n selected() {\n return this.selectedIndex > -1 && this.items.length > this.selectedIndex > -1\n ? this.items[this.selectedIndex] : null;\n },\n },\n\n methods: {\n get(index) { return this.set.get(index) },\n find(item) { return this.set.find(item) },\n findIndex(item) { return this.set.findIndex(item) },\n\n push(...items) {\n let index = this.set.length;\n for(var item of items)\n this.set.push(item);\n },\n\n remove(index, select=False) {\n this.set.remove(index);\n if(index < this.selectedIndex)\n this.selectedIndex--;\n if(select && this.selectedIndex == index)\n this.select(index)\n },\n\n select(index) {\n this.selectedIndex = index > -1 && this.items.length ? index % this.items.length : -1;\n this.$emit('select', { target: this, item: this.selected, index: this.selectedIndex });\n return this.selectedIndex;\n },\n\n\n },\n});\n\n\n//# sourceURL=webpack:///./assets/public/list.vue?./node_modules/vue-loader/lib??vue-loader-options"); /***/ }), @@ -414,7 +450,19 @@ 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 _list__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./list */ \"./assets/public/list.vue\");\n/* harmony import */ var _soundItem__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./soundItem */ \"./assets/public/soundItem.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//\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 return {\n state: State.paused,\n active: null,\n live: this.liveArgs ? new _live__WEBPACK_IMPORTED_MODULE_1__[\"default\"](this.liveArgs) : null,\n panel: null,\n queue: _model__WEBPACK_IMPORTED_MODULE_5__[\"Set\"].storeLoad(_sound__WEBPACK_IMPORTED_MODULE_4__[\"default\"], \"player.queue\", { max: 30, unique: true }),\n history: _model__WEBPACK_IMPORTED_MODULE_5__[\"Set\"].storeLoad(_sound__WEBPACK_IMPORTED_MODULE_4__[\"default\"], \"player.history\", { max: 30, unique: true }),\n }\n },\n\n props: {\n buttonTitle: String,\n liveArgs: Object,\n },\n\n computed: {\n paused() { return this.state == State.paused; },\n playing() { return this.state == State.playing; },\n loading() { return this.state == State.loading; },\n self() { return this; },\n\n current() {\n return this.active || this.live && this.live.current;\n },\n\n progress() {\n let audio = this.$refs.audio;\n return audio && Number.isFinite(audio.duration) && audio.duration ?\n audio.pos / audio.duration * 100 : null;\n },\n\n buttonStyle() {\n if(!this.current)\n return;\n return { backgroundImage: `url(${this.current.cover})` }\n },\n },\n\n methods: {\n togglePanel(panel) {\n this.panel = this.panel == panel ? null : panel;\n },\n\n isActive(item) {\n return item && this.active && this.active.src == item.src;\n },\n\n _load(src) {\n const audio = this.$refs.audio;\n if(src instanceof Array) {\n audio.innerHTML = '';\n for(var s of src) {\n let source = document.createElement(source);\n source.setAttribute('src', s);\n audio.appendChild(source)\n }\n }\n else {\n audio.src = src;\n }\n audio.load();\n },\n\n load(item) {\n if(item) {\n this._load(item.src)\n this.history.push(item);\n }\n else\n this._load(this.live.src);\n this.$set(this, 'active', item);\n },\n\n play(item) {\n if(item)\n this.load(item);\n this.$refs.audio.play().catch(e => console.error(e))\n },\n\n pause() {\n this.$refs.audio.pause()\n },\n\n //! Play/pause\n togglePlay() {\n if(this.paused)\n this.play()\n else\n this.pause()\n },\n\n //! Push item to queue\n push(item) {\n this.queue.push(item);\n this.panel = 'queue';\n },\n\n onState(event) {\n const audio = this.$refs.audio;\n this.state = audio.paused ? State.paused : State.playing;\n\n if(event.type == 'ended' && this.active) {\n this.queue.remove(this.active);\n if(this.queue.length)\n this.$refs.queue.select(0);\n else\n this.load();\n }\n },\n\n onSelect({item,index}) {\n if(!this.isActive(item))\n this.play(item);\n },\n },\n\n mounted() {\n this.sources = this.$slots.sources;\n },\n\n components: {\n List: _list__WEBPACK_IMPORTED_MODULE_2__[\"default\"], SoundItem: _soundItem__WEBPACK_IMPORTED_MODULE_3__[\"default\"],\n },\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 _sound__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./sound */ \"./assets/public/sound.js\");\n/* harmony import */ var _model__WEBPACK_IMPORTED_MODULE_4__ = __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//\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 return {\n state: State.paused,\n /// Loaded item\n loaded: null,\n /// Live instance\n live: this.liveArgs ? new _live__WEBPACK_IMPORTED_MODULE_1__[\"default\"](this.liveArgs) : null,\n //! Active panel name\n panel: null,\n //! current playing playlist component\n playlist: null,\n //! players' playlists' sets\n sets: {\n queue: _model__WEBPACK_IMPORTED_MODULE_4__[\"Set\"].storeLoad(_sound__WEBPACK_IMPORTED_MODULE_3__[\"default\"], \"playlist.queue\", { max: 30, unique: true }),\n pin: _model__WEBPACK_IMPORTED_MODULE_4__[\"Set\"].storeLoad(_sound__WEBPACK_IMPORTED_MODULE_3__[\"default\"], \"player.pin\", { max: 30, unique: true }),\n history: _model__WEBPACK_IMPORTED_MODULE_4__[\"Set\"].storeLoad(_sound__WEBPACK_IMPORTED_MODULE_3__[\"default\"], \"player.history\", { max: 30, unique: true }),\n }\n }\n },\n\n props: {\n buttonTitle: String,\n liveArgs: Object,\n },\n\n computed: {\n paused() { return this.state == State.paused; },\n playing() { return this.state == State.playing; },\n loading() { return this.state == State.loading; },\n self() { return this; },\n\n current() {\n return this.loaded || this.live && this.live.current;\n },\n\n progress() {\n let audio = this.$refs.audio;\n return audio && Number.isFinite(audio.duration) && audio.duration ?\n audio.pos / audio.duration * 100 : null;\n },\n\n buttonStyle() {\n if(!this.current)\n return;\n return { backgroundImage: `url(${this.current.cover})` }\n },\n },\n\n methods: {\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.playlist && this.playlist == this.$refs[name] ? 'is-primary '\n : '') : '')\n + \"button has-text-weight-bold\";\n },\n\n /// Show/hide panel\n togglePanel(panel) {\n this.panel = this.panel == panel ? null : panel;\n },\n\n /// Return True if item is loaded\n isLoaded(item) {\n return this.loaded && this.loaded.src == item.src;\n },\n\n /// Return True if item is loaded\n isPlaying(item) {\n return this.isLoaded(item) && !this.player.paused;\n },\n\n load(playlist, {src=null, item=null}={}) {\n src = src || item.src;\n this.loaded = item;\n this.playlist = playlist ? this.$refs[playlist] : null;\n\n const audio = this.$refs.audio;\n if(src instanceof Array) {\n audio.innerHTML = '';\n for(var s of src) {\n let source = document.createElement(source);\n source.setAttribute('src', s);\n audio.appendChild(source)\n }\n }\n else {\n audio.src = src;\n }\n audio.load();\n },\n\n /// Play a playlist's sound (by playlist name, and sound index)\n play(playlist=null, index=0) {\n if(!playlist)\n playlist = 'queue';\n\n let item = this.$refs[playlist].get(index);\n if(item) {\n this.load(playlist, {item: item});\n this.sets.history.push(item);\n this.$refs.audio.play().catch(e => console.error(e))\n }\n else\n throw `No sound at index ${index} for playlist ${playlist}`;\n },\n\n /// Push items to playlist (by name)\n push(playlist, ...items) {\n this.$refs[playlist].push(...items);\n },\n\n /// Push and play items\n playItems(playlist, ...items) {\n this.push(playlist, ...items);\n\n let index = this.$refs[playlist].findIndex(items[0]);\n this.$refs[playlist].selectedIndex = index;\n this.play(playlist, index);\n },\n\n /// Play live stream\n playLive() {\n this.load(null, {src: this.live.src});\n this.$refs.audio.play().catch(e => console.error(e))\n this.panel = '';\n },\n\n /// Pause\n pause() {\n this.$refs.audio.pause()\n },\n\n //! Play/pause\n togglePlay() {\n if(this.paused)\n this.$refs.audio.play().catch(e => console.error(e))\n else\n this.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 if(!this.panel)\n this.panel = 'pin';\n }\n },\n\n /// Audio player state change event\n onState(event) {\n const audio = this.$refs.audio;\n this.state = audio.paused ? State.paused : State.playing;\n\n if(event.type == 'ended' && (!this.playlist || this.playlist.selectNext() == -1))\n this.playLive();\n },\n },\n\n mounted() {\n this.sources = this.$slots.sources;\n },\n\n components: { Playlist: _playlist__WEBPACK_IMPORTED_MODULE_2__[\"default\"] },\n});\n\n\n//# sourceURL=webpack:///./assets/public/player.vue?./node_modules/vue-loader/lib??vue-loader-options"); + +/***/ }), + +/***/ "./node_modules/vue-loader/lib/index.js?!./assets/public/playlist.vue?vue&type=script&lang=js&": +/*!***************************************************************************************************************!*\ + !*** ./node_modules/vue-loader/lib??vue-loader-options!./assets/public/playlist.vue?vue&type=script&lang=js& ***! + \***************************************************************************************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _list__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./list */ \"./assets/public/list.vue\");\n/* harmony import */ var _soundItem__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./soundItem */ \"./assets/public/soundItem.vue\");\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/* harmony default export */ __webpack_exports__[\"default\"] = ({\n extends: _list__WEBPACK_IMPORTED_MODULE_0__[\"default\"],\n\n props: {\n actions: Array,\n name: String,\n player: Object,\n editable: Boolean,\n },\n\n computed: {\n self() { return this; }\n },\n\n methods: {\n hasAction(action) { return this.actions && this.actions.indexOf(action) != -1; },\n\n selectNext() {\n let index = this.selectedIndex + 1;\n return this.select(index >= this.items.length ? -1 : index);\n },\n\n togglePlay(index) {\n if(this.player.isPlaying(this.set.get(index)))\n this.player.pause();\n else\n this.select(index)\n },\n },\n components: { List: _list__WEBPACK_IMPORTED_MODULE_0__[\"default\"], SoundItem: _soundItem__WEBPACK_IMPORTED_MODULE_1__[\"default\"] },\n});\n\n\n//# sourceURL=webpack:///./assets/public/playlist.vue?./node_modules/vue-loader/lib??vue-loader-options"); /***/ }), @@ -426,7 +474,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 import */ var _model__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./model */ \"./assets/public/model.js\");\n/* harmony import */ var _sound__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./sound */ \"./assets/public/sound.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/* harmony default export */ __webpack_exports__[\"default\"] = ({\n props: {\n data: {type: Object, default: x => {}},\n name: String,\n cover: String,\n set: Object,\n player: Object,\n page_url: String,\n activeClass: String,\n actions: {type:Array, default: x => []},\n },\n\n computed: {\n item() { return this.data instanceof _model__WEBPACK_IMPORTED_MODULE_0__[\"default\"] ? this.data : new _sound__WEBPACK_IMPORTED_MODULE_1__[\"default\"](this.data || {}); },\n active() { return this.player && this.player.isActive(this.item) },\n playing() { return this.player && this.player.playing && this.active },\n paused() { return this.player && this.player.paused && this.active },\n loading() { return this.player && this.player.loading && this.active },\n },\n\n methods: {\n hasAction(action) {\n return this.actions && this.actions.indexOf(action) != -1;\n },\n\n play() {\n if(this.player && this.active)\n this.player.togglePlay()\n else\n this.player.play(this.item);\n },\n\n push_to(playlist) {\n this.player.playlists[playlist].push(this.item, {unique_key:'id'});\n },\n }\n});\n\n\n//# sourceURL=webpack:///./assets/public/soundItem.vue?./node_modules/vue-loader/lib??vue-loader-options"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _model__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./model */ \"./assets/public/model.js\");\n/* harmony import */ var _sound__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./sound */ \"./assets/public/sound.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/* harmony default export */ __webpack_exports__[\"default\"] = ({\n props: {\n data: {type: Object, default: x => {}},\n name: String,\n cover: String,\n player: Object,\n page_url: String,\n actions: {type:Array, default: x => []},\n index: {type:Number, default: null},\n },\n\n computed: {\n item() { return this.data instanceof _model__WEBPACK_IMPORTED_MODULE_0__[\"default\"] ? this.data : new _sound__WEBPACK_IMPORTED_MODULE_1__[\"default\"](this.data || {}); },\n loaded() { return this.player && this.player.isLoaded(this.item) },\n playing() { return this.player && this.player.playing && this.loaded },\n paused() { return this.player && this.player.paused && this.loaded },\n loading() { return this.player && this.player.loading && this.loaded },\n pinned() { return this.player && this.player.sets.pin.find(this.item) },\n },\n\n methods: {\n hasAction(action) {\n return this.actions && this.actions.indexOf(action) != -1;\n },\n }\n});\n\n\n//# sourceURL=webpack:///./assets/public/soundItem.vue?./node_modules/vue-loader/lib??vue-loader-options"); /***/ }), @@ -450,7 +498,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(\n \"div\",\n [\n _vm._t(\"header\"),\n _vm._v(\" \"),\n _c(\n \"ul\",\n { class: _vm.listClass },\n [\n _vm._t(\"start\"),\n _vm._v(\" \"),\n _vm._l(_vm.items, function(item, index) {\n return [\n _c(\n \"li\",\n {\n class: _vm.itemClass,\n on: {\n click: function($event) {\n return _vm.select(index)\n }\n }\n },\n [\n _vm._t(\"item\", null, {\n set: _vm.set,\n index: index,\n item: item\n })\n ],\n 2\n )\n ]\n }),\n _vm._v(\" \"),\n _vm._t(\"end\")\n ],\n 2\n ),\n _vm._v(\" \"),\n _vm._t(\"footer\")\n ],\n 2\n )\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./assets/public/list.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(\n \"div\",\n [\n _vm._t(\"header\"),\n _vm._v(\" \"),\n _c(\n \"ul\",\n { class: _vm.listClass },\n [\n _vm._l(_vm.items, function(item, index) {\n return [\n _c(\n \"li\",\n {\n class: _vm.itemClass,\n on: {\n click: function($event) {\n return _vm.select(index)\n }\n }\n },\n [\n _vm._t(\"item\", null, {\n selected: index == _vm.selectedIndex,\n set: _vm.set,\n index: index,\n item: item\n })\n ],\n 2\n )\n ]\n })\n ],\n 2\n ),\n _vm._v(\" \"),\n _vm._t(\"footer\")\n ],\n 2\n )\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./assets/public/list.vue?./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib??vue-loader-options"); /***/ }), @@ -462,7 +510,19 @@ 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(\n \"div\",\n { staticClass: \"player\" },\n [\n _c(\"List\", {\n directives: [\n {\n name: \"show\",\n rawName: \"v-show\",\n value: _vm.panel == \"queue\" && _vm.queue.length,\n expression: \"panel == 'queue' && queue.length\"\n }\n ],\n ref: \"queue\",\n staticClass: \"player-panel menu\",\n attrs: {\n set: _vm.queue,\n listClass: \"menu-list\",\n itemClass: \"menu-item\"\n },\n on: { select: _vm.onSelect },\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 key: \"item\",\n fn: function(ref) {\n var item = ref.item\n var index = ref.index\n var set = ref.set\n return [\n _c(\"SoundItem\", {\n attrs: {\n activeClass: \"is-active\",\n data: item,\n player: _vm.self,\n set: set,\n actions: [\"remove\"]\n },\n scopedSlots: _vm._u(\n [\n {\n key: \"actions\",\n fn: function(ref) {\n var active = ref.active\n var set = ref.set\n return undefined\n }\n }\n ],\n null,\n true\n )\n })\n ]\n }\n }\n ])\n }),\n _vm._v(\" \"),\n _c(\"List\", {\n directives: [\n {\n name: \"show\",\n rawName: \"v-show\",\n value: _vm.panel == \"history\" && _vm.history.length,\n expression: \"panel == 'history' && history.length\"\n }\n ],\n ref: \"history\",\n staticClass: \"player-panel menu\",\n attrs: {\n set: _vm.history,\n listClass: \"menu-list\",\n itemClass: \"menu-item\"\n },\n on: { select: _vm.onSelect },\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-clock\" })\n ]),\n _vm._v(\"\\n History\\n \")\n ])\n ]\n },\n proxy: true\n },\n {\n key: \"item\",\n fn: function(ref) {\n var item = ref.item\n var index = ref.index\n var set = ref.set\n return [\n _c(\"SoundItem\", {\n attrs: {\n activeClass: \"is-active\",\n data: item,\n player: _vm.self,\n set: set,\n actions: [\"queue\", \"remove\"]\n }\n })\n ]\n }\n }\n ])\n }),\n _vm._v(\" \"),\n _c(\"div\", { staticClass: \"player-bar media\" }, [\n _c(\n \"div\",\n { staticClass: \"media-left\" },\n [\n _c(\n \"div\",\n {\n staticClass: \"button\",\n attrs: {\n title: _vm.buttonTitle,\n \"aria-label\": _vm.buttonTitle\n },\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 _vm._v(\" \"),\n _c(\"audio\", {\n ref: \"audio\",\n attrs: { preload: \"metadata\" },\n on: {\n playing: _vm.onState,\n ended: _vm.onState,\n pause: _vm.onState\n }\n }),\n _vm._v(\" \"),\n _vm._t(\"sources\")\n ],\n 2\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 [_vm._t(\"content\", null, { current: _vm.current })],\n 2\n ),\n _vm._v(\" \"),\n _c(\"div\", { staticClass: \"media-right\" }, [\n _vm.active\n ? _c(\n \"button\",\n {\n staticClass: \"button\",\n on: {\n click: function($event) {\n _vm.load() && _vm.play()\n }\n }\n },\n [_vm._m(0), _vm._v(\" \"), _c(\"span\", [_vm._v(\"Live\")])]\n )\n : _vm._e(),\n _vm._v(\" \"),\n _vm.history.length\n ? _c(\n \"button\",\n {\n staticClass: \"button\",\n class: [_vm.panel == \"history\" ? \"is-info\" : \"\"],\n on: {\n click: function($event) {\n return _vm.togglePanel(\"history\")\n }\n }\n },\n [_vm._m(1)]\n )\n : _vm._e(),\n _vm._v(\" \"),\n _vm.queue.length\n ? _c(\n \"button\",\n {\n staticClass: \"button\",\n class: [_vm.panel == \"queue\" ? \"is-info\" : \"\"],\n on: {\n click: function($event) {\n return _vm.togglePanel(\"queue\")\n }\n }\n },\n [\n _c(\"span\", { staticClass: \"mr-2 is-size-6\" }, [\n _vm._v(_vm._s(_vm.queue.length))\n ]),\n _vm._v(\" \"),\n _vm._m(2)\n ]\n )\n : _vm._e()\n ])\n ]),\n _vm._v(\" \"),\n _vm.progress\n ? _c(\"div\", [_c(\"span\", { style: { width: _vm.progress } })])\n : _vm._e()\n ],\n 1\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 has-text-danger\" }, [\n _c(\"span\", { staticClass: \"fa fa-broadcast-tower\" })\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-clock\" })\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(\n \"div\",\n { staticClass: \"player\" },\n [\n _c(\"Playlist\", {\n directives: [\n {\n name: \"show\",\n rawName: \"v-show\",\n value: _vm.panel == \"history\",\n expression: \"panel == 'history'\"\n }\n ],\n ref: \"history\",\n staticClass: \"panel-menu menu\",\n attrs: {\n name: \"History\",\n editable: true,\n player: _vm.self,\n set: _vm.sets.history,\n listClass: \"menu-list\",\n itemClass: \"menu-item\"\n },\n on: {\n select: function($event) {\n return _vm.play(\"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-clock\" })\n ]),\n _vm._v(\"\\n History\\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 == \"pin\",\n expression: \"panel == 'pin'\"\n }\n ],\n ref: \"pin\",\n staticClass: \"player-panel menu\",\n attrs: {\n name: \"Pinned\",\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.play(\"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 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.play(\"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 _vm._v(\" \"),\n _c(\"div\", { staticClass: \"player-bar media\" }, [\n _c(\n \"div\",\n { staticClass: \"media-left\" },\n [\n _c(\n \"div\",\n {\n staticClass: \"button\",\n attrs: {\n title: _vm.buttonTitle,\n \"aria-label\": _vm.buttonTitle\n },\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 _vm._v(\" \"),\n _c(\"audio\", {\n ref: \"audio\",\n attrs: { preload: \"metadata\" },\n on: {\n playing: _vm.onState,\n ended: _vm.onState,\n pause: _vm.onState\n }\n }),\n _vm._v(\" \"),\n _vm._t(\"sources\")\n ],\n 2\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 [_vm._t(\"content\", null, { current: _vm.current })],\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.playLive()\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 class: _vm.playlistButtonClass(\"history\"),\n on: {\n click: function($event) {\n return _vm.togglePanel(\"history\")\n }\n }\n },\n [\n _vm.sets.history.length\n ? _c(\"span\", { staticClass: \"mr-2 is-size-6\" }, [\n _vm._v(\n \"\\n \" + _vm._s(_vm.sets.history.length)\n )\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(\"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 \"\\n \" + _vm._s(_vm.sets.pin.length)\n )\n ])\n : _vm._e(),\n _vm._v(\" \"),\n _vm._m(2)\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(3)\n ]\n )\n ])\n ]),\n _vm._v(\" \"),\n _vm.progress\n ? _c(\"div\", [_c(\"span\", { style: { width: _vm.progress } })])\n : _vm._e()\n ],\n 1\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 has-text-danger\" }, [\n _c(\"span\", { staticClass: \"fa fa-broadcast-tower\" })\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-clock\" })\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"); + +/***/ }), + +/***/ "./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/vue-loader/lib/index.js?!./assets/public/playlist.vue?vue&type=template&id=c0d17d8c&": +/*!*************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib??vue-loader-options!./assets/public/playlist.vue?vue&type=template&id=c0d17d8c& ***! + \*************************************************************************************************************************************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (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(\n \"div\",\n [\n _vm._t(\"header\"),\n _vm._v(\" \"),\n _c(\n \"ul\",\n { class: _vm.listClass },\n _vm._l(_vm.items, function(item, index) {\n return _c(\n \"li\",\n {\n class: _vm.itemClass,\n on: {\n click: function($event) {\n !_vm.hasAction(\"play\") && _vm.select(index)\n }\n }\n },\n [\n _c(\n \"a\",\n { class: index == _vm.selectedIndex ? \"is-active\" : \"\" },\n [\n _c(\"SoundItem\", {\n attrs: {\n data: item,\n index: index,\n player: _vm.player,\n set: _vm.set,\n actions: _vm.actions\n },\n on: {\n togglePlay: function($event) {\n return _vm.togglePlay(index)\n }\n },\n scopedSlots: _vm._u(\n [\n {\n key: \"actions\",\n fn: function(ref) {\n var loaded = ref.loaded\n var set = ref.set\n return [\n _vm.editable\n ? _c(\n \"button\",\n {\n staticClass: \"button\",\n on: {\n click: function($event) {\n $event.stopPropagation()\n return _vm.remove(index, true)\n }\n }\n },\n [\n _c(\n \"span\",\n { staticClass: \"icon is-small\" },\n [\n _c(\"span\", {\n staticClass: \"fa fa-minus\"\n })\n ]\n )\n ]\n )\n : _vm._e()\n ]\n }\n }\n ],\n null,\n true\n )\n })\n ],\n 1\n )\n ]\n )\n }),\n 0\n ),\n _vm._v(\" \"),\n _vm._t(\"footer\")\n ],\n 2\n )\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./assets/public/playlist.vue?./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib??vue-loader-options"); /***/ }), @@ -474,7 +534,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(\n \"a\",\n {\n class: [_vm.active ? _vm.activeClass : \"\"],\n on: {\n click: function($event) {\n _vm.actions.indexOf(\"play\") == -1 && _vm.play()\n }\n }\n },\n [\n _c(\"div\", { staticClass: \"media\" }, [\n _vm.hasAction(\"play\")\n ? _c(\"div\", { staticClass: \"media-left\" }, [\n _c(\n \"button\",\n {\n staticClass: \"button\",\n on: {\n click: function($event) {\n return _vm.play()\n }\n }\n },\n [\n _c(\"div\", { staticClass: \"icon\" }, [\n _vm.playing || _vm.loading\n ? _c(\"span\", { staticClass: \"fa fa-pause\" })\n : _c(\"span\", { staticClass: \"fa fa-play\" })\n ])\n ]\n )\n ])\n : _vm._e(),\n _vm._v(\" \"),\n _c(\n \"div\",\n { staticClass: \"media-content\" },\n [\n _vm._t(\n \"content\",\n [\n _c(\"h4\", { staticClass: \"title is-4 is-inline-block\" }, [\n _vm._v(\n \"\\n \" +\n _vm._s(_vm.name || _vm.item.name) +\n \"\\n \"\n )\n ])\n ],\n { player: _vm.player, item: _vm.item, active: _vm.active }\n )\n ],\n 2\n ),\n _vm._v(\" \"),\n _c(\n \"div\",\n { staticClass: \"media-right\" },\n [\n _vm.hasAction(\"queue\")\n ? _c(\n \"button\",\n {\n staticClass: \"button\",\n on: {\n click: function($event) {\n $event.stopPropagation()\n return _vm.player.push(_vm.item)\n }\n }\n },\n [_vm._m(0)]\n )\n : _vm._e(),\n _vm._v(\" \"),\n _vm.hasAction(\"remove\")\n ? _c(\n \"button\",\n {\n staticClass: \"button\",\n on: {\n click: function($event) {\n $event.stopPropagation()\n return _vm.set.remove(_vm.item)\n }\n }\n },\n [_vm._m(1)]\n )\n : _vm._e(),\n _vm._v(\" \"),\n _vm._t(\"actions\", null, {\n player: _vm.player,\n item: _vm.item,\n active: _vm.active\n })\n ],\n 2\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-small\" }, [\n _c(\"span\", { staticClass: \"fa fa-list\" })\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 is-small\" }, [\n _c(\"span\", { staticClass: \"fa fa-minus\" })\n ])\n }\n]\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./assets/public/soundItem.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: \"media\" }, [\n _vm.hasAction(\"play\")\n ? _c(\"div\", { staticClass: \"media-left\" }, [\n _c(\n \"button\",\n {\n staticClass: \"button\",\n on: {\n click: function($event) {\n return _vm.$emit(\"togglePlay\")\n }\n }\n },\n [\n _c(\"div\", { staticClass: \"icon\" }, [\n _vm.playing || _vm.loading\n ? _c(\"span\", { staticClass: \"fa fa-pause\" })\n : _c(\"span\", { staticClass: \"fa fa-play\" })\n ])\n ]\n )\n ])\n : _vm._e(),\n _vm._v(\" \"),\n _c(\n \"div\",\n { staticClass: \"media-content\" },\n [\n _vm._t(\n \"content\",\n [\n _c(\"h4\", { staticClass: \"title is-4 is-inline-block\" }, [\n _vm._v(\n \"\\n \" +\n _vm._s(_vm.name || _vm.item.name) +\n \"\\n \"\n )\n ])\n ],\n { player: _vm.player, item: _vm.item, loaded: _vm.loaded }\n )\n ],\n 2\n ),\n _vm._v(\" \"),\n _c(\n \"div\",\n { staticClass: \"media-right\" },\n [\n _vm.player.$refs.pin != _vm.$parent\n ? _c(\n \"button\",\n {\n staticClass: \"button\",\n on: {\n click: function($event) {\n $event.stopPropagation()\n return _vm.player.togglePin(_vm.item)\n }\n }\n },\n [\n _c(\"span\", { staticClass: \"icon is-small\" }, [\n _c(\"span\", {\n class:\n (_vm.pinned ? \"\" : \"has-text-grey-light \") +\n \"fa fa-thumbtack\"\n })\n ])\n ]\n )\n : _vm._e(),\n _vm._v(\" \"),\n _vm._t(\"actions\", null, {\n player: _vm.player,\n item: _vm.item,\n loaded: _vm.loaded\n })\n ],\n 2\n )\n ])\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n\n//# sourceURL=webpack:///./assets/public/soundItem.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/streamer.js b/aircox/static/aircox/streamer.js index 956ff99..877bd36 100644 --- a/aircox/static/aircox/streamer.js +++ b/aircox/static/aircox/streamer.js @@ -159,11 +159,11 @@ /*!******************************!*\ !*** ./assets/public/app.js ***! \******************************/ -/*! exports provided: defaultConfig, App, AppConfig */ +/*! exports provided: defaultConfig, default, AppConfig */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"defaultConfig\", function() { return defaultConfig; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"App\", function() { return App; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AppConfig\", function() { return AppConfig; });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.browser.js\");\n\n\n\nconst defaultConfig = {\n el: '#app',\n delimiters: ['[[', ']]'],\n\n computed: {\n player() {\n return window.aircox.player;\n }\n }\n}\n\nfunction App(config) {\n return (new AppConfig(config)).load()\n}\n\n/**\n * Application config for an application instance\n */\nclass AppConfig {\n constructor(config) {\n this._config = config;\n }\n\n get config() {\n let config = this._config instanceof Function ? this._config() : this._config;\n return {...defaultConfig, ...config};\n }\n\n set config(value) {\n this._config = value;\n }\n\n load() {\n var self = this;\n return new Promise(function(resolve, reject) {\n window.addEventListener('load', () => {\n try {\n let config = self.config;\n const el = document.querySelector(config.el)\n if(!el) {\n reject(`Error: missing element ${config.el}`);\n return;\n }\n resolve(new vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"](config))\n }\n catch(error) { reject(error) }\n })\n });\n }\n}\n\n\n\n\n//# sourceURL=webpack:///./assets/public/app.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"defaultConfig\", function() { return defaultConfig; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return App; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"AppConfig\", function() { return AppConfig; });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.browser.js\");\n\n\n\nconst defaultConfig = {\n el: '#app',\n delimiters: ['[[', ']]'],\n\n data() {\n return {\n page: null,\n }\n },\n\n computed: {\n player() { return window.aircox.player; }\n },\n}\n\nfunction App(config) {\n return (new AppConfig(config)).load()\n}\n\n/**\n * Application config for an application instance\n */\nclass AppConfig {\n constructor(config) {\n this._config = config;\n }\n\n get config() {\n let config = this._config instanceof Function ? this._config() : this._config;\n return {...defaultConfig, ...config};\n }\n\n set config(value) {\n this._config = value;\n }\n\n load() {\n var self = this;\n return new Promise(function(resolve, reject) {\n window.addEventListener('load', () => {\n try {\n let config = self.config;\n const el = document.querySelector(config.el)\n if(!el) {\n reject(`Error: missing element ${config.el}`);\n return;\n }\n resolve(new vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"](config))\n }\n catch(error) { reject(error) }\n })\n });\n }\n}\n\n\n\n\n//# sourceURL=webpack:///./assets/public/app.js?"); /***/ }), @@ -175,7 +175,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__, \"getCsrf\", function() { return getCsrf; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return Model; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Set\", function() { return Set; });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.browser.js\");\n\n\nfunction getCookie(name) {\n if(document.cookie && document.cookie !== '') {\n const cookie = document.cookie.split(';')\n .find(c => c.trim().startsWith(name + '='))\n return cookie ? decodeURIComponent(cookie.split('=')[1]) : null;\n }\n return null;\n}\n\nvar csrfToken = null;\n\nfunction getCsrf() {\n if(csrfToken === null)\n csrfToken = getCookie('csrftoken')\n return csrfToken;\n}\n\n\n// TODO: prevent duplicate simple fetch\nclass Model {\n constructor(data, {url=null}={}) {\n this.url = url;\n this.commit(data);\n }\n\n /**\n * Get instance id from its data\n */\n static getId(data) {\n return data.id;\n }\n\n /**\n * Return fetch options\n */\n static getOptions(options) {\n return {\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n 'X-CSRFToken': getCsrf(),\n },\n ...options,\n }\n }\n\n /**\n * Fetch item from server\n */\n static fetch(url, options=null, args=null) {\n options = this.getOptions(options)\n return fetch(url, options)\n .then(response => response.json())\n .then(data => new this(data, {url: url, ...args}));\n }\n\n /**\n * Fetch data from server.\n */\n fetch(options) {\n options = this.constructor.getOptions(options)\n return fetch(this.url, options)\n .then(response => response.json())\n .then(data => this.commit(data));\n }\n\n /**\n * Call API action on object.\n */\n action(path, options, commit=false) {\n options = this.constructor.getOptions(options)\n const promise = fetch(this.url + path, options);\n return commit ? promise.then(data => data.json())\n .then(data => { this.commit(data); this.data })\n : promise;\n }\n\n /**\n * Update instance's data with provided data. Return None\n */\n commit(data) {\n this.id = this.constructor.getId(data);\n vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].set(this, 'data', data);\n }\n\n /**\n * Save instance into localStorage.\n */\n store(key) {\n window.localStorage.setItem(key, JSON.stringify(this.data));\n }\n\n /**\n * Load model instance from localStorage.\n */\n static storeLoad(key) {\n let item = window.localStorage.getItem(key);\n return item === null ? item : new this(JSON.parse(item));\n }\n}\n\n\n/**\n * List of models\n */\nclass Set {\n constructor(model, {items=[],url=null,args={},unique=null,max=null,storeKey=null}={}) {\n this.items = items.map(x => x instanceof model ? x : new model(x, args));\n this.model = model;\n this.url = url;\n this.unique = unique;\n this.max = max;\n this.storeKey = storeKey;\n }\n\n get length() { return this.items.length }\n indexOf(...args) { return this.items.indexOf(...args); }\n\n /**\n * Fetch multiple items from server\n */\n static fetch(url, options=null, args=null) {\n options = this.getOptions(options)\n return fetch(url, options)\n .then(response => response.json())\n .then(data => (data instanceof Array ? data : data.results)\n .map(d => new this.model(d, {url: url, ...args})))\n }\n\n /**\n * Load list from localStorage\n */\n static storeLoad(model, key, args={}) {\n let items = window.localStorage.getItem(key);\n return new this(model, {...args, storeKey: key, items: items ? JSON.parse(items) : []});\n }\n\n /**\n * Store list into localStorage\n */\n store() {\n if(this.storeKey)\n window.localStorage.setItem(this.storeKey, JSON.stringify(\n this.items.map(i => i.data)));\n }\n\n push(item, {args={}}={}) {\n item = item instanceof this.model ? item : new this.model(item, args);\n if(this.unique && this.items.find(x => x.id == item.id))\n return;\n if(this.max && this.items.length >= this.max)\n this.items.splice(0,this.items.length-this.max)\n\n this.items.push(item);\n this._updated()\n }\n\n remove(item, {args={}}={}) {\n item = item instanceof this.model ? item : new this.model(item, args);\n let index = this.items.findIndex(x => x.id == item.id);\n if(index == -1)\n return;\n\n this.items.splice(index,1);\n this._updated()\n }\n\n _updated() {\n vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].set(this, 'items', this.items);\n this.store();\n }\n}\n\nSet[Symbol.iterator] = function () {\n return this.items[Symbol.iterator]();\n}\n\n\n\n//# sourceURL=webpack:///./assets/public/model.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"getCsrf\", function() { return getCsrf; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return Model; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Set\", function() { return Set; });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.esm.browser.js\");\n\n\nfunction getCookie(name) {\n if(document.cookie && document.cookie !== '') {\n const cookie = document.cookie.split(';')\n .find(c => c.trim().startsWith(name + '='))\n return cookie ? decodeURIComponent(cookie.split('=')[1]) : null;\n }\n return null;\n}\n\nvar csrfToken = null;\n\nfunction getCsrf() {\n if(csrfToken === null)\n csrfToken = getCookie('csrftoken')\n return csrfToken;\n}\n\n\n// TODO: prevent duplicate simple fetch\nclass Model {\n constructor(data, {url=null}={}) {\n this.url = url;\n this.commit(data);\n }\n\n /**\n * Get instance id from its data\n */\n static getId(data) {\n return data.id;\n }\n\n /**\n * Return fetch options\n */\n static getOptions(options) {\n return {\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n 'X-CSRFToken': getCsrf(),\n },\n ...options,\n }\n }\n\n /**\n * Fetch item from server\n */\n static fetch(url, options=null, args=null) {\n options = this.getOptions(options)\n return fetch(url, options)\n .then(response => response.json())\n .then(data => new this(data, {url: url, ...args}));\n }\n\n /**\n * Fetch data from server.\n */\n fetch(options) {\n options = this.constructor.getOptions(options)\n return fetch(this.url, options)\n .then(response => response.json())\n .then(data => this.commit(data));\n }\n\n /**\n * Call API action on object.\n */\n action(path, options, commit=false) {\n options = this.constructor.getOptions(options)\n const promise = fetch(this.url + path, options);\n return commit ? promise.then(data => data.json())\n .then(data => { this.commit(data); this.data })\n : promise;\n }\n\n /**\n * Update instance's data with provided data. Return None\n */\n commit(data) {\n this.id = this.constructor.getId(data);\n vue__WEBPACK_IMPORTED_MODULE_0__[\"default\"].set(this, 'data', data);\n }\n\n /**\n * Save instance into localStorage.\n */\n store(key) {\n window.localStorage.setItem(key, JSON.stringify(this.data));\n }\n\n /**\n * Load model instance from localStorage.\n */\n static storeLoad(key) {\n let item = window.localStorage.getItem(key);\n return item === null ? item : new this(JSON.parse(item));\n }\n}\n\n\n/**\n * List of models\n */\nclass Set {\n constructor(model, {items=[],url=null,args={},unique=null,max=null,storeKey=null}={}) {\n this.items = [];\n this.model = model;\n this.url = url;\n this.unique = unique;\n this.max = max;\n this.storeKey = storeKey;\n\n for(var item of items)\n this.push(item, {args: args, save: false});\n }\n\n get length() { return this.items.length }\n get(index) { return this.items[index] }\n\n /**\n * Fetch multiple items from server\n */\n static fetch(url, options=null, args=null) {\n options = this.getOptions(options)\n return fetch(url, options)\n .then(response => response.json())\n .then(data => (data instanceof Array ? data : data.results)\n .map(d => new this.model(d, {url: url, ...args})))\n }\n\n /**\n * Load list from localStorage\n */\n static storeLoad(model, key, args={}) {\n let items = window.localStorage.getItem(key);\n return new this(model, {...args, storeKey: key, items: items ? JSON.parse(items) : []});\n }\n\n /**\n * Store list into localStorage\n */\n store() {\n this.storeKey && window.localStorage.setItem(this.storeKey, JSON.stringify(\n this.items.map(i => i.data)));\n }\n\n /**\n * Save item\n */\n save() {\n this.storeKey && this.store();\n }\n\n /**\n * Find item by id\n */\n find(item) {\n return this.items.find(x => x.id == item.id);\n }\n\n /**\n * Find item index by id\n */\n findIndex(item) {\n return this.items.findIndex(x => x.id == item.id);\n }\n\n /**\n * Add item to set\n */\n push(item, {args={},save=true}={}) {\n item = item instanceof this.model ? item : new this.model(item, args);\n if(this.unique) {\n let index = this.findIndex(item);\n if(index > -1)\n this.items.splice(index,1);\n }\n if(this.max && this.items.length >= this.max)\n this.items.splice(0,this.items.length-this.max)\n\n this.items.push(item);\n save && this.save();\n }\n\n /**\n * Remove item from set by index\n */\n remove(index, {save=true}={}) {\n this.items.splice(index,1);\n save && this.save();\n }\n}\n\nSet[Symbol.iterator] = function () {\n return this.items[Symbol.iterator]();\n}\n\n\n\n//# sourceURL=webpack:///./assets/public/model.js?"); /***/ }), diff --git a/aircox/templates/aircox/episode_detail.html b/aircox/templates/aircox/episode_detail.html index 8b78f1b..b7f00bf 100644 --- a/aircox/templates/aircox/episode_detail.html +++ b/aircox/templates/aircox/episode_detail.html @@ -1,6 +1,16 @@ {% extends "aircox/page_detail.html" %} {% comment %}List of a show's episodes for a specific{% endcomment %} -{% load i18n %} +{% load i18n aircox %} + +{% block head_extra %} + +{% endblock head_extra %} {% include "aircox/program_sidebar.html" %} @@ -38,10 +48,19 @@ {% if podcasts %}
-
{% trans "Podcasts" %}
+ + + + {% comment %} {% for object in podcasts %} {% include "aircox/widgets/podcast_item.html" %} {% endfor %} + {% endcomment %}
{% endif %} diff --git a/aircox/templates/aircox/program_sidebar.html b/aircox/templates/aircox/program_sidebar.html new file mode 100644 index 0000000..0b5a0f2 --- /dev/null +++ b/aircox/templates/aircox/program_sidebar.html @@ -0,0 +1,8 @@ + +{% block sidebar_title %} +{% with program.title as program %} +{% blocktrans %}Recently on {{ program }}{% endblocktrans %} +{% endwith %} +{% endblock %} + + diff --git a/aircox/templates/aircox/widgets/podcast_item.html b/aircox/templates/aircox/widgets/podcast_item.html index 8687d94..5d74019 100644 --- a/aircox/templates/aircox/widgets/podcast_item.html +++ b/aircox/templates/aircox/widgets/podcast_item.html @@ -12,7 +12,7 @@ List item for a podcast. {% endif %} {% endcomment %} + :actions="['play']" @click="player.play(item)"> diff --git a/aircox/templatetags/aircox.py b/aircox/templatetags/aircox.py index f9d979e..668c807 100644 --- a/aircox/templatetags/aircox.py +++ b/aircox/templatetags/aircox.py @@ -2,6 +2,7 @@ import random import json from django import template +from django.utils.safestring import mark_safe from aircox.models import Page, Diffusion, Log diff --git a/assets/public/app.js b/assets/public/app.js index 3e1cb23..08b6e9f 100644 --- a/assets/public/app.js +++ b/assets/public/app.js @@ -5,14 +5,18 @@ export const defaultConfig = { el: '#app', delimiters: ['[[', ']]'], - computed: { - player() { - return window.aircox.player; + data() { + return { + page: null, } - } + }, + + computed: { + player() { return window.aircox.player; } + }, } -export function App(config) { +export default function App(config) { return (new AppConfig(config)).load() } diff --git a/assets/public/index.js b/assets/public/index.js index 85150b7..f001bf2 100644 --- a/assets/public/index.js +++ b/assets/public/index.js @@ -10,16 +10,20 @@ import '@fortawesome/fontawesome-free/css/fontawesome.min.css'; //-- aircox -import {App} from './app'; +import App from './app'; +import Sound from './sound'; +import {Set} from './model'; import './styles.scss'; import Autocomplete from './autocomplete.vue'; import Player from './player.vue'; +import Playlist from './playlist.vue'; import SoundItem from './soundItem'; Vue.component('a-autocomplete', Autocomplete) Vue.component('a-player', Player) +Vue.component('a-playlist', Playlist) Vue.component('a-sound-item', SoundItem) @@ -36,8 +40,11 @@ window.aircox = { // player component get player() { return this.playerApp && this.playerApp.$refs.player - } + }, + + Set: Set, Sound: Sound, }; +window.Vue = Vue; App({el: '#player'}).then(app => window.aircox.playerApp = app, diff --git a/assets/public/list.vue b/assets/public/list.vue index c859107..9a446fe 100644 --- a/assets/public/list.vue +++ b/assets/public/list.vue @@ -2,13 +2,11 @@
@@ -17,14 +15,14 @@ export default { data() { return { - selectedIndex: this.default, + selectedIndex: this.defaultIndex, } }, props: { listClass: String, itemClass: String, - default: { type: Number, default: -1}, + defaultIndex: { type: Number, default: -1}, set: Object, }, @@ -34,31 +32,37 @@ export default { length() { return this.set.length }, selected() { - return this.items && this.items.length > this.selectedIndex > -1 + return this.selectedIndex > -1 && this.items.length > this.selectedIndex > -1 ? this.items[this.selectedIndex] : null; }, }, methods: { - select(index=null) { - if(index === null) - index = this.selectedIndex; - else if(this.selectedIndex == index) - return; + get(index) { return this.set.get(index) }, + find(item) { return this.set.find(item) }, + findIndex(item) { return this.set.findIndex(item) }, - this.selectedIndex = Math.min(index, this.items.length-1); - this.$emit('select', { item: this.selected, index: this.selectedIndex }); + push(...items) { + let index = this.set.length; + for(var item of items) + this.set.push(item); + }, + + remove(index, select=False) { + this.set.remove(index); + if(index < this.selectedIndex) + this.selectedIndex--; + if(select && this.selectedIndex == index) + this.select(index) + }, + + select(index) { + this.selectedIndex = index > -1 && this.items.length ? index % this.items.length : -1; + this.$emit('select', { target: this, item: this.selected, index: this.selectedIndex }); return this.selectedIndex; }, - selectNext() { - let index = this.selectedIndex + 1; - return this.select(index >= this.items.length ? -1 : index); - }, - // add() - // insert() + drag & drop - // remove() }, } diff --git a/assets/public/model.js b/assets/public/model.js index f9aa280..2a6e0b3 100644 --- a/assets/public/model.js +++ b/assets/public/model.js @@ -107,16 +107,19 @@ export default class Model { */ export class Set { constructor(model, {items=[],url=null,args={},unique=null,max=null,storeKey=null}={}) { - this.items = items.map(x => x instanceof model ? x : new model(x, args)); + this.items = []; this.model = model; this.url = url; this.unique = unique; this.max = max; this.storeKey = storeKey; + + for(var item of items) + this.push(item, {args: args, save: false}); } get length() { return this.items.length } - indexOf(...args) { return this.items.indexOf(...args); } + get(index) { return this.items[index] } /** * Fetch multiple items from server @@ -141,35 +144,54 @@ export class Set { * Store list into localStorage */ store() { - if(this.storeKey) - window.localStorage.setItem(this.storeKey, JSON.stringify( - this.items.map(i => i.data))); + this.storeKey && window.localStorage.setItem(this.storeKey, JSON.stringify( + this.items.map(i => i.data))); } - push(item, {args={}}={}) { + /** + * Save item + */ + save() { + this.storeKey && this.store(); + } + + /** + * Find item by id + */ + find(item) { + return this.items.find(x => x.id == item.id); + } + + /** + * Find item index by id + */ + findIndex(item) { + return this.items.findIndex(x => x.id == item.id); + } + + /** + * Add item to set + */ + push(item, {args={},save=true}={}) { item = item instanceof this.model ? item : new this.model(item, args); - if(this.unique && this.items.find(x => x.id == item.id)) - return; + if(this.unique) { + let index = this.findIndex(item); + if(index > -1) + this.items.splice(index,1); + } if(this.max && this.items.length >= this.max) this.items.splice(0,this.items.length-this.max) this.items.push(item); - this._updated() + save && this.save(); } - remove(item, {args={}}={}) { - item = item instanceof this.model ? item : new this.model(item, args); - let index = this.items.findIndex(x => x.id == item.id); - if(index == -1) - return; - + /** + * Remove item from set by index + */ + remove(index, {save=true}={}) { this.items.splice(index,1); - this._updated() - } - - _updated() { - Vue.set(this, 'items', this.items); - this.store(); + save && this.save(); } } diff --git a/assets/public/player.vue b/assets/public/player.vue index 989f2ae..8eeb916 100644 --- a/assets/public/player.vue +++ b/assets/public/player.vue @@ -1,39 +1,38 @@