diff --git a/htdocs/Makefile.am b/htdocs/Makefile.am index 3a2ac9ea..4651d040 100644 --- a/htdocs/Makefile.am +++ b/htdocs/Makefile.am @@ -100,7 +100,11 @@ dist_htdocsplayerjs_DATA = \ player/js/app.js \ player/js/app.js.map \ player/js/chunk-vendors.js \ - player/js/chunk-vendors.js.map + player/js/chunk-vendors.js.map \ + player/js/app-legacy.js \ + player/js/app-legacy.js.map \ + player/js/chunk-vendors-legacy.js \ + player/js/chunk-vendors-legacy.js.map htdocsplayerimgdir = $(datadir)/forked-daapd/htdocs/player/img diff --git a/htdocs/index.html b/htdocs/index.html index 142ef05d..bd88fc1d 100644 --- a/htdocs/index.html +++ b/htdocs/index.html @@ -1 +1 @@ -
{{ queue.count }} tracks
\nQueue
\n \n \n \n \n \n\n
\n {{ item_progress_ms | duration }} / {{ now_playing.length_ms | duration }}\n
\nRecently added
\nalbums
\n \n \nRecently played
\ntracks
\n \n \nRecently added
\nalbums
\n \n \nRecently played
\ntracks
\n \n \nArtists
\n{{ artists.total }} artists
\n \n \n \n \n \n \n Hide singles\n \n \n \n{{ artist.name }}
\n \n \n \n \n \n{{ artist.album_count }} albums | {{ artist.track_count }} tracks
\nAlbums
\n{{ albums.total }} albums
\n \n \n \n \n \n \n Hide singles\n \n \n \n{{ album.track_count }} tracks
\nGenres
\n{{ genres.total }} genres
\n \n \n{{ name }}
\n \n \n \n \n \n{{ genre_albums.total }} albums | tracks
\n{{ genre }}
\n \n \n \n \n \nalbums | {{ tracks.total }} tracks
\n{{ artist.name }}
\n \n \n \n \n \n{{ artist.album_count }} albums | {{ artist.track_count }} tracks
\nNew episodes
\n \n \n \n \n \nPodcasts
\n{{ albums.total }} podcasts
\n \n \n \n \n \nPermanently remove this podcast from your library?
\n(This will also remove the RSS playlist {{ rss_playlist_to_remove.name }}.)
\n \n{{ album.track_count }} tracks
\nPermanently remove this podcast from your library?
\n(This will also remove the RSS playlist {{ rss_playlist_to_remove.name }}.)
\n \nAudiobooks
\n{{ albums.total }} audiobooks
\n \n \n{{ album.track_count }} tracks
\n{{ playlist.name }}
\n{{ playlists.total }} playlists
\n \n \n{{ tracks.length }} tracks
\nFiles
\n{{ current_directory }}
\n \n \n \n \n \nTracks
\n \n \nNo results
\n \nArtists
\n \n \nNo results
\n \nAlbums
\n \n \nNo results
\n \nPlaylists
\n \n \nNo results
\n \nforked-daapd - version {{ config.version }}
\nArtists | \n{{ library.artists | number }} | \n
---|---|
Albums | \n{{ library.albums | number }} | \n
Tracks | \n{{ library.songs | number }} | \n
Total playtime | \n{{ library.db_playtime * 1000 | duration('y [years], d [days], h [hours], m [minutes]') }} | \n
Library updated | \n{{ library.updated_at | timeFromNow }} ({{ library.updated_at | time('MMM Do, h:mm') }}) | \n
Uptime | \n{{ library.started_at | timeFromNow(true) }} ({{ library.started_at | time('MMM Do, h:mm') }}) | \n
Compiled with support for {{ config.buildoptions | join }}.
\nWeb interface built with Bulma, Material Design Icons, Vue.js, axios and more.
\nNew Releases
\n \n \nFeatured Playlists
\n \n \nNew Releases
\n \n \nFeatured Playlists
\n \n \n{{ artist.name }}
\n \n \n \n \n \n{{ total }} albums
\n{{ album.tracks.total }} tracks
\n{{ playlist.tracks.total }} tracks
\nTracks
\n \n \nNo results
\n \nArtists
\n \n \nNo results
\n \nAlbums
\n \n \nNo results
\n \nPlaylists
\n \n \nNo results
\n \n\n
\n Comma separated list of genres the composer should be displayed on the "now playing page".\n
\n\n Leave empty to always show the composer.\n
\n\n The genre tag of the current track is matched by checking, if one of the defined genres are included.\n For example setting to classical, soundtrack
will show the composer for tracks with\n a genre tag of "Contemporary Classical".
\n
\n forked-daapd supports PNG and JPEG artwork which is either placed as separate image files in the library,\n embedded in the media files or made available online by radio stations.\n
\nIn addition to that, you can enable fetching artwork from the following artwork providers:
\nforked-daapd was either built without support for Spotify or libspotify is not installed.
\n\n libspotify - Login with your Spotify username and password\n
\n\n Logged in as {{ spotify.libspotify_user }}
\n
{{ libspotify.errors.error }}
\n\n libspotify enables forked-daapd to play Spotify tracks.\n
\n\n forked-daapd will not store your password, but will still be able to log you in automatically afterwards, because libspotify saves a login token.\n
\n\n Spotify Web API - Grant access to the Spotify Web API\n
\n\n Access granted for {{ spotify.webapi_user }}
\n
0\">\n Please reauthorize Web API access to grant forked-daapd the following additional access rights:\n {{ spotify_missing_scope | join }}
\n
\n Access to the Spotify Web API enables scanning of your Spotify library. Required scopes are\n {{ spotify_required_scope | join }}
.\n
forked-daapd was built without support for Last.fm.
\n\n Last.fm - Login with your Last.fm username and password to enable scrobbling\n
\nNo active pairing request.
\n\n If your Apple TV requires device verification then activate the device below and enter the PIN that the Apple TV displays.\n
\n\n{{ queue.count }} tracks
\nQueue
\n \n \n \n \n \n\n
\n {{ item_progress_ms | duration }} / {{ now_playing.length_ms | duration }}\n
\n \nRecently added
\nalbums
\n \n \nRecently played
\ntracks
\n \n \nRecently added
\nalbums
\n \n \nRecently played
\ntracks
\n \n \nArtists
\n{{ artists.total }} artists
\n \n \n \n \n \n \n Hide singles\n \n \n \n{{ artist.name }}
\n \n \n \n \n \n{{ artist.album_count }} albums | {{ artist.track_count }} tracks
\nAlbums
\n{{ albums.total }} albums
\n \n \n \n \n \n \n Hide singles\n \n \n \n{{ album.track_count }} tracks
\nGenres
\n{{ genres.total }} genres
\n \n \n{{ name }}
\n \n \n \n \n \n{{ genre_albums.total }} albums | tracks
\n{{ genre }}
\n \n \n \n \n \nalbums | {{ tracks.total }} tracks
\n{{ artist.name }}
\n \n \n \n \n \n{{ artist.album_count }} albums | {{ artist.track_count }} tracks
\nNew episodes
\n \n \nPodcasts
\n{{ albums.total }} podcasts
\n \n \n{{ album.track_count }} tracks
\nAudiobooks
\n{{ albums.total }} audiobooks
\n \n \n{{ album.track_count }} tracks
\n{{ playlist.name }}
\n{{ playlists.total }} playlists
\n \n \n{{ tracks.length }} tracks
\nFiles
\n{{ current_directory }}
\n \n \n \n \n \nTracks
\n \n \nNo results
\n \nArtists
\n \n \nNo results
\n \nAlbums
\n \n \nNo results
\n \nPlaylists
\n \n \nNo results
\n \nforked-daapd - version {{ config.version }}
\nArtists | \n{{ library.artists | number }} | \n
---|---|
Albums | \n{{ library.albums | number }} | \n
Tracks | \n{{ library.songs | number }} | \n
Total playtime | \n{{ library.db_playtime * 1000 | duration('y [years], d [days], h [hours], m [minutes]') }} | \n
Library updated | \n{{ library.updated_at | timeFromNow }} ({{ library.updated_at | time('MMM Do, h:mm') }}) | \n
Uptime | \n{{ library.started_at | timeFromNow(true) }} ({{ library.started_at | time('MMM Do, h:mm') }}) | \n
Compiled with support for {{ config.buildoptions | join }}.
\nWeb interface built with Bulma, Material Design Icons, Vue.js, axios and more.
\nNew Releases
\n \n \nFeatured Playlists
\n \n \nNew Releases
\n \n \nFeatured Playlists
\n \n \n{{ artist.name }}
\n \n \n \n \n \n{{ total }} albums
\n{{ album.tracks.total }} tracks
\n{{ playlist.tracks.total }} tracks
\nTracks
\n \n \nNo results
\n \nArtists
\n \n \nNo results
\n \nAlbums
\n \n \nNo results
\n \nPlaylists
\n \n \nNo results
\n \n\n If enabled the composer of the current playing track is shown on the "now playing page"\n
\nforked-daapd was either built without support for Spotify or libspotify is not installed.
\n\n libspotify - Login with your Spotify username and password\n
\n\n Logged in as {{ spotify.libspotify_user }}
\n
{{ libspotify.errors.error }}
\n\n libspotify enables forked-daapd to play Spotify tracks.\n
\n\n forked-daapd will not store your password, but will still be able to log you in automatically afterwards, because libspotify saves a login token.\n
\n\n Spotify Web API - Grant access to the Spotify Web API\n
\n\n Access granted for {{ spotify.webapi_user }}
\n
0\">\n Please reauthorize Web API access to grant forked-daapd the following additional access rights:\n {{ spotify_missing_scope | join }}
\n
\n Access to the Spotify Web API enables scanning of your Spotify library. Required scopes are\n {{ spotify_required_scope | join }}
.\n
forked-daapd was built without support for Last.fm.
\n\n Last.fm - Login with your Last.fm username and password to enable scrobbling\n
\nNo active pairing request.
\n\n If your Apple TV requires device verification then activate the device below and enter the PIN that the Apple TV displays.\n
\n\n{{ queue.count }} tracks
\nQueue
\n \n \n \n \n \n\n
\n {{ item_progress_ms | duration }} / {{ now_playing.length_ms | duration }}\n
\nRecently added
\nalbums
\n \n \nRecently played
\ntracks
\n \n \nRecently added
\nalbums
\n \n \nRecently played
\ntracks
\n \n \nArtists
\n{{ artists.total }} artists
\n \n \n \n \n \n \n Hide singles\n \n \n \n{{ artist.name }}
\n \n \n \n \n \n{{ artist.album_count }} albums | {{ artist.track_count }} tracks
\nAlbums
\n{{ albums.total }} albums
\n \n \n \n \n \n \n Hide singles\n \n \n \n{{ album.track_count }} tracks
\nGenres
\n{{ genres.total }} genres
\n \n \n{{ name }}
\n \n \n \n \n \n{{ genre_albums.total }} albums | tracks
\n{{ genre }}
\n \n \n \n \n \nalbums | {{ tracks.total }} tracks
\n{{ artist.name }}
\n \n \n \n \n \n{{ artist.album_count }} albums | {{ artist.track_count }} tracks
\nNew episodes
\n \n \n \n \n \nPodcasts
\n{{ albums.total }} podcasts
\n \n \n \n \n \nPermanently remove this podcast from your library?
\n(This will also remove the RSS playlist {{ rss_playlist_to_remove.name }}.)
\n \n{{ album.track_count }} tracks
\nPermanently remove this podcast from your library?
\n(This will also remove the RSS playlist {{ rss_playlist_to_remove.name }}.)
\n \nAudiobooks
\n{{ albums.total }} audiobooks
\n \n \n{{ album.track_count }} tracks
\n{{ playlist.name }}
\n{{ playlists.total }} playlists
\n \n \n{{ tracks.length }} tracks
\nFiles
\n{{ current_directory }}
\n \n \n \n \n \nTracks
\n \n \nNo results
\n \nArtists
\n \n \nNo results
\n \nAlbums
\n \n \nNo results
\n \nPlaylists
\n \n \nNo results
\n \nforked-daapd - version {{ config.version }}
\nArtists | \n{{ library.artists | number }} | \n
---|---|
Albums | \n{{ library.albums | number }} | \n
Tracks | \n{{ library.songs | number }} | \n
Total playtime | \n{{ library.db_playtime * 1000 | duration('y [years], d [days], h [hours], m [minutes]') }} | \n
Library updated | \n{{ library.updated_at | timeFromNow }} ({{ library.updated_at | time('MMM Do, h:mm') }}) | \n
Uptime | \n{{ library.started_at | timeFromNow(true) }} ({{ library.started_at | time('MMM Do, h:mm') }}) | \n
Compiled with support for {{ config.buildoptions | join }}.
\nWeb interface built with Bulma, Material Design Icons, Vue.js, axios and more.
\nNew Releases
\n \n \nFeatured Playlists
\n \n \nNew Releases
\n \n \nFeatured Playlists
\n \n \n{{ artist.name }}
\n \n \n \n \n \n{{ total }} albums
\n{{ album.tracks.total }} tracks
\n{{ playlist.tracks.total }} tracks
\nTracks
\n \n \nNo results
\n \nArtists
\n \n \nNo results
\n \nAlbums
\n \n \nNo results
\n \nPlaylists
\n \n \nNo results
\n \n\n
\n Comma separated list of genres the composer should be displayed on the "now playing page".\n
\n\n Leave empty to always show the composer.\n
\n\n The genre tag of the current track is matched by checking, if one of the defined genres are included.\n For example setting to classical, soundtrack
will show the composer for tracks with\n a genre tag of "Contemporary Classical".
\n
\n forked-daapd supports PNG and JPEG artwork which is either placed as separate image files in the library,\n embedded in the media files or made available online by radio stations.\n
\nIn addition to that, you can enable fetching artwork from the following artwork providers:
\nforked-daapd was either built without support for Spotify or libspotify is not installed.
\n\n libspotify - Login with your Spotify username and password\n
\n\n Logged in as {{ spotify.libspotify_user }}
\n
{{ libspotify.errors.error }}
\n\n libspotify enables forked-daapd to play Spotify tracks.\n
\n\n forked-daapd will not store your password, but will still be able to log you in automatically afterwards, because libspotify saves a login token.\n
\n\n Spotify Web API - Grant access to the Spotify Web API\n
\n\n Access granted for {{ spotify.webapi_user }}
\n
0\">\n Please reauthorize Web API access to grant forked-daapd the following additional access rights:\n {{ spotify_missing_scope | join }}
\n
\n Access to the Spotify Web API enables scanning of your Spotify library. Required scopes are\n {{ spotify_required_scope | join }}
.\n
forked-daapd was built without support for Last.fm.
\n\n Last.fm - Login with your Last.fm username and password to enable scrobbling\n
\nNo active pairing request.
\n\n If your Apple TV requires device verification then activate the device below and enter the PIN that the Apple TV displays.\n
\n\n, or missing
. Bailing hydration and performing ' +\n 'full client-side render.'\n );\n }\n }\n // either not server-rendered, or hydration failed.\n // create an empty node and replace it\n oldVnode = emptyNodeAt(oldVnode);\n }\n\n // replacing existing element\n var oldElm = oldVnode.elm;\n var parentElm = nodeOps.parentNode(oldElm);\n\n // create new node\n createElm(\n vnode,\n insertedVnodeQueue,\n // extremely rare edge case: do not insert if old element is in a\n // leaving transition. Only happens when combining transition +\n // keep-alive + HOCs. (#4590)\n oldElm._leaveCb ? null : parentElm,\n nodeOps.nextSibling(oldElm)\n );\n\n // update parent placeholder node element, recursively\n if (isDef(vnode.parent)) {\n var ancestor = vnode.parent;\n var patchable = isPatchable(vnode);\n while (ancestor) {\n for (var i = 0; i < cbs.destroy.length; ++i) {\n cbs.destroy[i](ancestor);\n }\n ancestor.elm = vnode.elm;\n if (patchable) {\n for (var i$1 = 0; i$1 < cbs.create.length; ++i$1) {\n cbs.create[i$1](emptyNode, ancestor);\n }\n // #6513\n // invoke insert hooks that may have been merged by create hooks.\n // e.g. for directives that uses the \"inserted\" hook.\n var insert = ancestor.data.hook.insert;\n if (insert.merged) {\n // start at index 1 to avoid re-invoking component mounted hook\n for (var i$2 = 1; i$2 < insert.fns.length; i$2++) {\n insert.fns[i$2]();\n }\n }\n } else {\n registerRef(ancestor);\n }\n ancestor = ancestor.parent;\n }\n }\n\n // destroy old node\n if (isDef(parentElm)) {\n removeVnodes([oldVnode], 0, 0);\n } else if (isDef(oldVnode.tag)) {\n invokeDestroyHook(oldVnode);\n }\n }\n }\n\n invokeInsertHook(vnode, insertedVnodeQueue, isInitialPatch);\n return vnode.elm\n }\n}\n\n/* */\n\nvar directives = {\n create: updateDirectives,\n update: updateDirectives,\n destroy: function unbindDirectives (vnode) {\n updateDirectives(vnode, emptyNode);\n }\n};\n\nfunction updateDirectives (oldVnode, vnode) {\n if (oldVnode.data.directives || vnode.data.directives) {\n _update(oldVnode, vnode);\n }\n}\n\nfunction _update (oldVnode, vnode) {\n var isCreate = oldVnode === emptyNode;\n var isDestroy = vnode === emptyNode;\n var oldDirs = normalizeDirectives$1(oldVnode.data.directives, oldVnode.context);\n var newDirs = normalizeDirectives$1(vnode.data.directives, vnode.context);\n\n var dirsWithInsert = [];\n var dirsWithPostpatch = [];\n\n var key, oldDir, dir;\n for (key in newDirs) {\n oldDir = oldDirs[key];\n dir = newDirs[key];\n if (!oldDir) {\n // new directive, bind\n callHook$1(dir, 'bind', vnode, oldVnode);\n if (dir.def && dir.def.inserted) {\n dirsWithInsert.push(dir);\n }\n } else {\n // existing directive, update\n dir.oldValue = oldDir.value;\n dir.oldArg = oldDir.arg;\n callHook$1(dir, 'update', vnode, oldVnode);\n if (dir.def && dir.def.componentUpdated) {\n dirsWithPostpatch.push(dir);\n }\n }\n }\n\n if (dirsWithInsert.length) {\n var callInsert = function () {\n for (var i = 0; i < dirsWithInsert.length; i++) {\n callHook$1(dirsWithInsert[i], 'inserted', vnode, oldVnode);\n }\n };\n if (isCreate) {\n mergeVNodeHook(vnode, 'insert', callInsert);\n } else {\n callInsert();\n }\n }\n\n if (dirsWithPostpatch.length) {\n mergeVNodeHook(vnode, 'postpatch', function () {\n for (var i = 0; i < dirsWithPostpatch.length; i++) {\n callHook$1(dirsWithPostpatch[i], 'componentUpdated', vnode, oldVnode);\n }\n });\n }\n\n if (!isCreate) {\n for (key in oldDirs) {\n if (!newDirs[key]) {\n // no longer present, unbind\n callHook$1(oldDirs[key], 'unbind', oldVnode, oldVnode, isDestroy);\n }\n }\n }\n}\n\nvar emptyModifiers = Object.create(null);\n\nfunction normalizeDirectives$1 (\n dirs,\n vm\n) {\n var res = Object.create(null);\n if (!dirs) {\n // $flow-disable-line\n return res\n }\n var i, dir;\n for (i = 0; i < dirs.length; i++) {\n dir = dirs[i];\n if (!dir.modifiers) {\n // $flow-disable-line\n dir.modifiers = emptyModifiers;\n }\n res[getRawDirName(dir)] = dir;\n dir.def = resolveAsset(vm.$options, 'directives', dir.name, true);\n }\n // $flow-disable-line\n return res\n}\n\nfunction getRawDirName (dir) {\n return dir.rawName || ((dir.name) + \".\" + (Object.keys(dir.modifiers || {}).join('.')))\n}\n\nfunction callHook$1 (dir, hook, vnode, oldVnode, isDestroy) {\n var fn = dir.def && dir.def[hook];\n if (fn) {\n try {\n fn(vnode.elm, dir, vnode, oldVnode, isDestroy);\n } catch (e) {\n handleError(e, vnode.context, (\"directive \" + (dir.name) + \" \" + hook + \" hook\"));\n }\n }\n}\n\nvar baseModules = [\n ref,\n directives\n];\n\n/* */\n\nfunction updateAttrs (oldVnode, vnode) {\n var opts = vnode.componentOptions;\n if (isDef(opts) && opts.Ctor.options.inheritAttrs === false) {\n return\n }\n if (isUndef(oldVnode.data.attrs) && isUndef(vnode.data.attrs)) {\n return\n }\n var key, cur, old;\n var elm = vnode.elm;\n var oldAttrs = oldVnode.data.attrs || {};\n var attrs = vnode.data.attrs || {};\n // clone observed objects, as the user probably wants to mutate it\n if (isDef(attrs.__ob__)) {\n attrs = vnode.data.attrs = extend({}, attrs);\n }\n\n for (key in attrs) {\n cur = attrs[key];\n old = oldAttrs[key];\n if (old !== cur) {\n setAttr(elm, key, cur);\n }\n }\n // #4391: in IE9, setting type can reset value for input[type=radio]\n // #6666: IE/Edge forces progress value down to 1 before setting a max\n /* istanbul ignore if */\n if ((isIE || isEdge) && attrs.value !== oldAttrs.value) {\n setAttr(elm, 'value', attrs.value);\n }\n for (key in oldAttrs) {\n if (isUndef(attrs[key])) {\n if (isXlink(key)) {\n elm.removeAttributeNS(xlinkNS, getXlinkProp(key));\n } else if (!isEnumeratedAttr(key)) {\n elm.removeAttribute(key);\n }\n }\n }\n}\n\nfunction setAttr (el, key, value) {\n if (el.tagName.indexOf('-') > -1) {\n baseSetAttr(el, key, value);\n } else if (isBooleanAttr(key)) {\n // set attribute for blank value\n // e.g. \n if (isFalsyAttrValue(value)) {\n el.removeAttribute(key);\n } else {\n // technically allowfullscreen is a boolean attribute for