Add 'Refresh' button to update libraries (#222)
Add 'Refresh' button to update libraries. Tweak folder icons and context menus. Fixes #136.
This commit is contained in:
parent
8345fbb9c0
commit
9856685a00
@ -111,6 +111,7 @@ v2.4.0 (UNRELEASED)
|
||||
- Add 'Show Track Info' popup which can be activated from any context menu. The popup includes the URI of the track,
|
||||
which can be inserted into various lists elsewhere in the player.
|
||||
- Updated icon set for font-awesome 4.7.0.
|
||||
- Added 'Refresh' button for refreshing libraries. (Addresses: `#75 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/75>`_).
|
||||
|
||||
**Fixes**
|
||||
|
||||
@ -121,6 +122,7 @@ v2.4.0 (UNRELEASED)
|
||||
- Use correct icons for folders, audio, and other files when browsing local files.
|
||||
- Now initializes the GUI properly, even if the user is offline or the Mopidy server cannot be reached.
|
||||
- Fixed `Alarm Clock <https://pypi.python.org/pypi/Mopidy-AlarmClock/>`_ detection.
|
||||
- When browsing the library using the local 'File' extension, only playable audio files will have context menu icons.
|
||||
|
||||
v2.3.0 (2016-05-15)
|
||||
-------------------
|
||||
|
||||
@ -118,7 +118,6 @@
|
||||
/******************
|
||||
* Track Slider *
|
||||
******************/
|
||||
|
||||
#trackslider {
|
||||
display: inline;
|
||||
width: 100%;
|
||||
@ -366,6 +365,10 @@ span.hostInfo {
|
||||
background-color: #ccc !important;
|
||||
}
|
||||
|
||||
.refreshLibraryBtnDiv {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
* Now Playing area *
|
||||
|
||||
@ -404,7 +404,16 @@
|
||||
<!--/playlistspane-->
|
||||
|
||||
<div data-role="content" id="browsepane" class="pane">
|
||||
<h4>Browse</h4>
|
||||
<div class="ui-grid-a">
|
||||
<div class="ui-block-a">
|
||||
<h4>Browse</h4>
|
||||
</div>
|
||||
<div align="right" class="ui-block-b refreshLibraryBtnDiv" data-role="controlgroup" data-type="horizontal">
|
||||
<button id="refreshLibraryBtn" class="btn" type="button" title="Refresh library">
|
||||
<i class="fa fa-refresh"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui-grid">
|
||||
<ul id="browsetable" class="table"></ul>
|
||||
</div>
|
||||
|
||||
@ -416,6 +416,14 @@
|
||||
return false
|
||||
},
|
||||
|
||||
refreshLibrary: function () {
|
||||
var uri = $('#refreshLibraryBtn').data('url')
|
||||
mopidy.library.refresh({'uri': uri}).then(function () {
|
||||
library.getBrowseDir(uri)
|
||||
})
|
||||
return false
|
||||
},
|
||||
|
||||
/** ***********
|
||||
* Buttons *
|
||||
*************/
|
||||
|
||||
@ -75,8 +75,8 @@ var radioExtensionsList = ['somafm', 'tunein', 'dirble', 'audioaddict']
|
||||
var uriClassList = [
|
||||
['spotify', 'fa-spotify'],
|
||||
['spotifytunigo', 'fa-spotify'],
|
||||
['local', 'fa-file-sound-o'],
|
||||
['file', 'fa-file-o'],
|
||||
['local', 'fa-folder-o'],
|
||||
['file', 'fa-folder-o'],
|
||||
['m3u', 'fa-file-sound-o'],
|
||||
['podcast', 'fa-rss-square'],
|
||||
['podcast+file', 'fa-rss-square'],
|
||||
@ -240,13 +240,9 @@ function renderSongLi (previousTrack, track, nextTrack, uri, tlid, target, curre
|
||||
var onClick = ''
|
||||
var html = ''
|
||||
track.name = validateTrackName(track, currentIndex)
|
||||
// Leave out unplayable items
|
||||
if (track.name.substring(0, 12) === '[unplayable]') {
|
||||
return html
|
||||
}
|
||||
// Streams
|
||||
if (track.length === -1) {
|
||||
html += '<li class="albumli"><a href="#"><h1><i class="' + getMediaClass(track.uri) + '"></i> ' + track.name + ' [Stream]</h1></a></li>'
|
||||
html += '<li class="albumli"><a href="#"><h1><i class="' + getMediaClass(track) + '"></i> ' + track.name + ' [Stream]</h1></a></li>'
|
||||
return html
|
||||
}
|
||||
|
||||
@ -257,11 +253,13 @@ function renderSongLi (previousTrack, track, nextTrack, uri, tlid, target, curre
|
||||
onClick = 'return controls.playTracks(\'\', mopidy, \'' + track.uri + '\', \'' + uri + '\');'
|
||||
}
|
||||
|
||||
html +=
|
||||
'<li class="song albumli" id="' + getjQueryID(target, track.uri) + '" tlid="' + tlid + '">' +
|
||||
'<a href="#" class="moreBtn" onclick="return popupTracks(event, \'' + uri + '\',\'' + track.uri + tlidParameter + '\');">' +
|
||||
'<i class="fa fa-play-circle-o"></i></a>' +
|
||||
'<a href="#" onclick="' + onClick + '"><h1><i class="' + getMediaClass(track.uri) + '"></i> ' + track.name + '</h1>'
|
||||
html += '<li class="song albumli" id="' + getjQueryID(target, track.uri) + '" tlid="' + tlid + '">'
|
||||
if (isPlayable(track)) {
|
||||
// Show popup icon for audio files or 'tracks' of other scheme types
|
||||
html += '<a href="#" class="moreBtn" onclick="return popupTracks(event, \'' + uri + '\',\'' + track.uri + tlidParameter + '\');">' +
|
||||
'<i class="fa fa-play-circle-o"></i></a>'
|
||||
}
|
||||
html += '<a href="#" onclick="' + onClick + '"><h1><i class="' + getMediaClass(track) + '"></i> ' + track.name + '</h1>'
|
||||
|
||||
if (listLength === 1 || (!hasSameAlbum(previousTrack, track) && !hasSameAlbum(track, nextTrack))) {
|
||||
html += renderSongLiAlbumInfo(track)
|
||||
@ -309,7 +307,7 @@ function renderSongLiDivider (previousTrack, track, nextTrack, target) {
|
||||
html +=
|
||||
'<li class="albumdivider"><a href="#" onclick="return library.showAlbum(\'' + track.album.uri + '\');">' +
|
||||
'<img id="' + getjQueryID(target + '-cover', track.uri) + '" class="artistcover" width="30" height="30"/>' +
|
||||
'<h1><i class="' + getMediaClass(track.uri) + '"></i> ' + track.album.name + '</h1><p>' +
|
||||
'<h1>' + track.album.name + '</h1><p>' +
|
||||
renderSongLiTrackArtists(track) + '</p></a></li>'
|
||||
// Retrieve album covers
|
||||
images.setAlbumImage(track.uri, getjQueryID(target + '-cover', track.uri, true), mopidy, 'small')
|
||||
@ -317,7 +315,7 @@ function renderSongLiDivider (previousTrack, track, nextTrack, target) {
|
||||
// Small divider
|
||||
html += '<li class="smalldivider"> </li>'
|
||||
}
|
||||
if (typeof target !== 'undefined' && target.length > 0) {
|
||||
if (html.length > 0 && typeof target !== 'undefined' && target.length > 0) {
|
||||
target = getjQueryID(target, track.uri, true)
|
||||
$(target).before(html)
|
||||
}
|
||||
@ -494,26 +492,52 @@ function getScheme (uri) {
|
||||
return uri.split(':')[0].toLowerCase()
|
||||
}
|
||||
|
||||
function isAudioFile (uri) {
|
||||
var ext = uri.split('.').pop().toLowerCase()
|
||||
return $.inArray(ext, audioExt) !== -1
|
||||
function isPlayable (track) {
|
||||
if (typeof track.type === 'undefined' || track.type === 'track') {
|
||||
if (getScheme(track.uri) === 'file') {
|
||||
var ext = track.uri.split('.').pop().toLowerCase()
|
||||
if ($.inArray(ext, audioExt) === -1) {
|
||||
// Files must have the correct extension
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function isStreamUri (uri) {
|
||||
var a = validUri(uri)
|
||||
var b = radioExtensionsList.indexOf(getScheme(uri)) >= 0
|
||||
return a || b
|
||||
return validUri(uri) || radioExtensionsList.indexOf(getScheme(uri)) >= 0
|
||||
}
|
||||
|
||||
function getMediaClass (uri) {
|
||||
var scheme = getScheme(uri)
|
||||
if (scheme === 'file' && isAudioFile(uri)) {
|
||||
return 'fa fa-file-sound-o'
|
||||
}
|
||||
for (var i = 0; i < uriClassList.length; i++) {
|
||||
if (scheme === uriClassList[i][0]) {
|
||||
return 'fa ' + uriClassList[i][1]
|
||||
function getMediaClass (track) {
|
||||
var type = track.type
|
||||
if (typeof type === 'undefined' || type === 'track') {
|
||||
if (isPlayable(track)) {
|
||||
if (isStreamUri(track.uri)) {
|
||||
return 'fa fa-rss' // Stream
|
||||
} else {
|
||||
return 'fa fa-file-sound-o' // Sound file (default)
|
||||
}
|
||||
} else {
|
||||
return 'fa fa-file-o' // Unplayable file
|
||||
}
|
||||
} else if (type === 'directory') {
|
||||
for (var i = 0; i < uriClassList.length; i++) {
|
||||
if (getScheme(track.uri) === uriClassList[i][0]) {
|
||||
return 'fa ' + uriClassList[i][1] // Mapped service directory
|
||||
}
|
||||
}
|
||||
return 'fa fa-folder-o' // Unmapped directory
|
||||
} else if (type === 'album') {
|
||||
// return 'fa fa-bullseye' // Album
|
||||
return 'fa fa-folder-o'
|
||||
} else if (type === 'artist') {
|
||||
// return 'fa fa-user-circle-o' // Artist
|
||||
return 'fa fa-folder-o'
|
||||
} else if (type === 'playlist') {
|
||||
// return 'fa fa-star' // Playlist
|
||||
return ''
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
@ -145,7 +145,7 @@
|
||||
tokens = {
|
||||
'id': results.artists[i].uri,
|
||||
'name': results.artists[i].name,
|
||||
'class': getMediaClass(results.artists[i].uri)
|
||||
'class': getMediaClass(results.artists[i])
|
||||
}
|
||||
|
||||
// Add 'Show all' item after a certain number of hits.
|
||||
@ -173,7 +173,7 @@
|
||||
'albumName': results.albums[i].name,
|
||||
'artistName': '',
|
||||
'albumYear': results.albums[i].date,
|
||||
'class': getMediaClass(results.albums[i].uri)
|
||||
'class': getMediaClass(results.albums[i])
|
||||
}
|
||||
if (results.albums[i].artists) {
|
||||
for (j = 0; j < results.albums[i].artists.length; j++) {
|
||||
@ -215,14 +215,23 @@
|
||||
showLoading(true)
|
||||
if (!rootdir) {
|
||||
browseStack.pop()
|
||||
rootdir = browseStack[browseStack.length - 1]
|
||||
rootdir = browseStack[browseStack.length - 1] || null
|
||||
} else {
|
||||
browseStack.push(rootdir)
|
||||
if (rootdir !== browseStack[browseStack.length - 1]) {
|
||||
browseStack.push(rootdir)
|
||||
}
|
||||
}
|
||||
if (!rootdir) {
|
||||
rootdir = null
|
||||
}
|
||||
mopidy.library.browse({'uri': rootdir}).then(processBrowseDir, console.error)
|
||||
mopidy.library.browse({'uri': rootdir}).then(function (resultArr) {
|
||||
processBrowseDir(resultArr)
|
||||
if (rootdir === null) {
|
||||
$('.refreshLibraryBtnDiv').hide()
|
||||
} else {
|
||||
$('.refreshLibraryBtnDiv').show()
|
||||
$('#refreshLibraryBtn').data('url', rootdir)
|
||||
$('#refreshLibraryBtn').off('click')
|
||||
$('#refreshLibraryBtn').one('click', controls.refreshLibrary)
|
||||
}
|
||||
}, console.error)
|
||||
},
|
||||
|
||||
getCurrentPlaylist: function () {
|
||||
|
||||
@ -90,8 +90,9 @@ function processBrowseDir (resultArr) {
|
||||
var length = 0 || resultArr.length
|
||||
customTracklists[BROWSE_TABLE] = []
|
||||
var html = ''
|
||||
var i
|
||||
|
||||
for (var i = 0, index = 0; i < resultArr.length; i++) {
|
||||
for (i = 0, index = 0; i < resultArr.length; i++) {
|
||||
if (resultArr[i].type === 'track') {
|
||||
previousRef = ref || undefined
|
||||
nextRef = i < resultArr.length - 1 ? resultArr[i + 1] : undefined
|
||||
@ -105,14 +106,8 @@ function processBrowseDir (resultArr) {
|
||||
|
||||
index++
|
||||
} else {
|
||||
var iconClass = ''
|
||||
if (browseStack.length > 0 && resultArr[i].type === 'directory') {
|
||||
iconClass = 'fa fa-folder-o'
|
||||
} else {
|
||||
iconClass = getMediaClass(resultArr[i].uri)
|
||||
}
|
||||
html += '<li><a href="#" onclick="return library.getBrowseDir(this.id);" id="' + resultArr[i].uri + '">' +
|
||||
'<h1><i class="' + iconClass + '"></i> ' + resultArr[i].name + '</h1></a></li>'
|
||||
'<h1><i class="' + getMediaClass(resultArr[i]) + '"></i> ' + resultArr[i].name + '</h1></a></li>'
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,22 +119,22 @@ function processBrowseDir (resultArr) {
|
||||
mopidy.library.lookup({'uris': uris}).then(function (resultDict) {
|
||||
// Break into albums and put in tables
|
||||
var track, previousTrack, nextTrack, uri
|
||||
$.each(resultArr, function (i, ref) {
|
||||
if (ref.type === 'track') {
|
||||
for (i = 0, index = 0; i < resultArr.length; i++) {
|
||||
if (resultArr[i].type === 'track') {
|
||||
previousTrack = track || undefined
|
||||
if (i < resultArr.length - 1 && resultDict[resultArr[i + 1].uri]) {
|
||||
nextTrack = resultDict[resultArr[i + 1].uri][0]
|
||||
} else {
|
||||
nextTrack = undefined
|
||||
}
|
||||
track = resultDict[ref.uri][0]
|
||||
track = resultDict[resultArr[i].uri][0]
|
||||
popupData[track.uri] = track // Need full track info in popups in order to display albums and artists.
|
||||
if (uris.length === 1 || (previousTrack && !hasSameAlbum(previousTrack, track) && !hasSameAlbum(track, nextTrack))) {
|
||||
renderSongLiAlbumInfo(track, BROWSE_TABLE)
|
||||
}
|
||||
renderSongLiDivider(previousTrack, track, nextTrack, BROWSE_TABLE)
|
||||
}
|
||||
})
|
||||
}
|
||||
showLoading(false)
|
||||
}, console.error)
|
||||
} else {
|
||||
@ -166,7 +161,7 @@ function processGetPlaylists (resultArr) {
|
||||
} else if (isFavouritesPlaylist(resultArr[i])) {
|
||||
favourites = li_html + '♥ Musicbox Favourites</a></li>'
|
||||
} else {
|
||||
tmp = tmp + li_html + '<i class="' + getMediaClass(resultArr[i].uri) + '"></i> ' + resultArr[i].name + '</a></li>'
|
||||
tmp = tmp + li_html + '<i class="' + getMediaClass(resultArr[i]) + '"></i> ' + resultArr[i].name + '</a></li>'
|
||||
}
|
||||
}
|
||||
// Prepend the user's Spotify "Starred" playlist and favourites to the results. (like Spotify official client).
|
||||
|
||||
Loading…
Reference in New Issue
Block a user