Save scrolling position when switching pages or browsing the library.

Fixes #73. Fixes #93.
This commit is contained in:
jcass 2017-01-22 09:02:23 +02:00
parent 9856685a00
commit 466b805062
7 changed files with 56 additions and 82 deletions

View File

@ -123,6 +123,8 @@ v2.4.0 (UNRELEASED)
- Now initializes the GUI properly, even if the user is offline or the Mopidy server cannot be reached. - 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. - 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. - When browsing the library using the local 'File' extension, only playable audio files will have context menu icons.
- The last scroll position is now always saved when navigating between pages or browsing the library.
(Fixes: `#73 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/73>`_, `#93 <https://github.com/pimusicbox/mopidy-musicbox-webclient/issues/93>`_).
v2.3.0 (2016-05-15) v2.3.0 (2016-05-15)
------------------- -------------------

View File

@ -20,6 +20,17 @@
$(document).bind('mobileinit', configureJQueryMobile) $(document).bind('mobileinit', configureJQueryMobile)
// Extension: timeout to detect end of scrolling action.
$.fn.scrollEnd = function (callback, timeout) {
$(this).scroll(function () {
var $this = $(this)
if ($this.data('scrollTimeout')) {
clearTimeout($this.data('scrollTimeout'))
}
$this.data('scrollTimeout', setTimeout(callback, timeout))
})
}
return configureJQueryMobile return configureJQueryMobile
})) }))

View File

@ -28,8 +28,7 @@ var artiststext = ''
var songname = '' var songname = ''
var songdata = {'track': {}, 'tlid': -1} var songdata = {'track': {}, 'tlid': -1}
var playlisttracksScroll var pageScrollPos = {}
var playlistslistScroll
var STREAMS_PLAYLIST_NAME = '[Radio Streams]' var STREAMS_PLAYLIST_NAME = '[Radio Streams]'
var STREAMS_PLAYLIST_SCHEME = 'm3u' var STREAMS_PLAYLIST_SCHEME = 'm3u'
@ -159,9 +158,8 @@ var audioExt = [
] ]
function scrollToTop () { function scrollToTop () {
var divtop = 0
$('body,html').animate({ $('body,html').animate({
scrollTop: divtop scrollTop: 0
}, 250) }, 250)
} }

View File

@ -23,48 +23,10 @@ function resizeMb () {
$('#infoname').html(songdata.track.name) $('#infoname').html(songdata.track.name)
$('#infoartist').html(artiststext) $('#infoartist').html(artiststext)
if ($(window).width() <= 960) { if ($(window).width() > 960) {
// $('#playlisttracksdiv').hide();
// $('#playlistslistdiv').show();
} else {
$('#playlisttracksdiv').show() $('#playlisttracksdiv').show()
$('#playlistslistdiv').show() $('#playlistslistdiv').show()
} }
// //set height of playlist scrollers
/* if ($(window).width() > 960) {
$('#playlisttracksdiv').show();
$('#playlistslistdiv').show();
$('.scroll').removeClass('height').removeClass('width');
$('#playlistspane').removeClass('height').removeClass('width');
} else {
if ( $('#playlisttracksdiv').is(':visible') == $('#playlistslistdiv').is(':visible')) {
$('#playlisttracksdiv').hide();
$('#playlistslistdiv').show();
$('.scroll').addClass('height', '99%').addClass('width', '99%');
$('#playlistspane').addClass('height', '99%').addClass('width', '99%');
}
}
if ($('#playlisttracksdiv').is(':visible') && !$('#playlisttracksback').is(':visible') ) {
$('.scroll').height($(window).height() - 96);
//jqm added something which it shouldnt (at least in this case) I guess
// $('#playlistspane').removeClass('height').height($(window).height() - 110);
$('.scroll').removeClass('height').removeClass('width');
$('#playlistspane').removeClass('height').removeClass('width');
$('#playlisttracksdiv').show();
$('#playlistslistdiv').show();
} else {
$('.scroll').addClass('height', '99%').addClass('width', '99%');
$('#playlistspane').addClass('height', '99%').addClass('width', '99%');
$('#playlisttracksdiv').show();
$('#playlistslistdiv').show();
}
if (isMobileWebkit && ($(window).width() > 480)) {
playlistslistScroll.refresh();
playlisttracksScroll.refresh();
}
*/
} }
function setSongTitle (title, refresh_ui) { function setSongTitle (title, refresh_ui) {
@ -400,42 +362,34 @@ function locationHashChanged () {
var hash = document.location.hash.split('?') var hash = document.location.hash.split('?')
// remove # // remove #
var divid = hash[0].substr(1) var divid = hash[0].substr(1)
var uri = hash[1]
setHeadline(divid) setHeadline(divid)
var uri = hash[1]
$('.mainNav a').removeClass('ui-state-active ui-state-persist ui-btn-active')
// i don't know why some li elements have those classes, but they do, so we need to remove them
$('.mainNav li').removeClass('ui-state-active ui-state-persist ui-btn-active')
if ($(window).width() < 560) { if ($(window).width() < 560) {
$('#panel').panel('close') $('#panel').panel('close')
} }
$('.pane').hide()
$('#' + divid + 'pane').show() $('.mainNav a').removeClass($.mobile.activeBtnClass)
// i don't know why some li elements have those classes, but they do, so we need to remove them
$('.mainNav li').removeClass($.mobile.activeBtnClass)
$('#nav' + divid + ' a').addClass($.mobile.activeBtnClass) // Update navigation pane
$('.pane').hide() // Hide all pages
$('#' + divid + 'pane').show() // Switch to active pane
if (typeof pageScrollPos[divid] !== 'undefined') { // Set scroll position
window.scrollTo(0, pageScrollPos[divid])
}
switch (divid) { switch (divid) {
case 'home': case 'nowPlaying': // Show 'now playing' footer
$('#navhome a').addClass('ui-state-active ui-state-persist ui-btn-active') $('#normalFooter').hide()
break $('#nowPlayingFooter').show()
case 'nowPlaying':
$('#navnowPlaying a').addClass('ui-state-active ui-state-persist ui-btn-active')
break
case 'current':
$('#navcurrent a').addClass('ui-state-active ui-state-persist ui-btn-active')
break
case 'playlists':
$('#navplaylists a').addClass('ui-state-active ui-state-persist ui-btn-active')
break
case 'browse':
$('#navbrowse a').addClass('ui-state-active ui-state-persist ui-btn-active')
break break
case 'search': case 'search':
$('#navsearch a').addClass($.mobile.activeBtnClass)
$('#searchinput').focus() $('#searchinput').focus()
break break
case 'stream':
$('#navstream a').addClass('ui-state-active ui-state-persist ui-btn-active')
break
case 'artists': case 'artists':
if (uri !== '') { if (uri !== '') {
library.showArtist(uri) library.showArtist(uri)
@ -446,15 +400,7 @@ function locationHashChanged () {
library.showAlbum(uri) library.showAlbum(uri)
} }
break break
} default: // Default footer
// switch the footer
switch (divid) {
case 'nowPlaying':
$('#normalFooter').hide()
$('#nowPlayingFooter').show()
break
default:
$('#normalFooter').show() $('#normalFooter').show()
$('#nowPlayingFooter').hide() $('#nowPlayingFooter').hide()
} }
@ -483,6 +429,16 @@ $(document).ready(function (event) {
} }
$(window).hashchange() $(window).hashchange()
// Remember scroll position for each page and browsed folder
$(window).scrollEnd(function () {
var divid = document.location.hash.split('?')[0].substr(1)
if (divid === 'browse' && browseStack.length > 0) {
browseStack[browseStack.length - 1].scrollPos = window.pageYOffset
} else {
pageScrollPos[divid] = window.pageYOffset
}
}, 250)
initgui = false initgui = false
// only show backbutton if in UIWebview // only show backbutton if in UIWebview

View File

@ -215,16 +215,18 @@
showLoading(true) showLoading(true)
if (!rootdir) { if (!rootdir) {
browseStack.pop() browseStack.pop()
rootdir = browseStack[browseStack.length - 1] || null if (browseStack.length > 0) {
} else { rootdir = browseStack[browseStack.length - 1].uri // Navigated one level up
if (rootdir !== browseStack[browseStack.length - 1]) { } else {
browseStack.push(rootdir) rootdir = null // Navigated to top of library
} }
} else if (browseStack.length === 0 || rootdir !== browseStack[browseStack.length - 1].uri) {
browseStack.push({'uri': rootdir, 'scrollPos': 0}) // Navigated one level down
} }
mopidy.library.browse({'uri': rootdir}).then(function (resultArr) { mopidy.library.browse({'uri': rootdir}).then(function (resultArr) {
processBrowseDir(resultArr) processBrowseDir(resultArr)
if (rootdir === null) { if (rootdir === null) {
$('.refreshLibraryBtnDiv').hide() $('.refreshLibraryBtnDiv').hide() // Mopidy does not support refreshing list of backends.
} else { } else {
$('.refreshLibraryBtnDiv').show() $('.refreshLibraryBtnDiv').show()
$('#refreshLibraryBtn').data('url', rootdir) $('#refreshLibraryBtn').data('url', rootdir)

View File

@ -92,6 +92,7 @@ function processBrowseDir (resultArr) {
var html = '' var html = ''
var i var i
// Render list of tracks
for (i = 0, index = 0; i < resultArr.length; i++) { for (i = 0, index = 0; i < resultArr.length; i++) {
if (resultArr[i].type === 'track') { if (resultArr[i].type === 'track') {
previousRef = ref || undefined previousRef = ref || undefined
@ -112,9 +113,13 @@ function processBrowseDir (resultArr) {
} }
$(BROWSE_TABLE).append(html) $(BROWSE_TABLE).append(html)
if (browseStack.length > 0) {
window.scrollTo(0, browseStack[browseStack.length - 1].scrollPos || 0) // Restore scroll position
}
updatePlayIcons(songdata.track.uri, songdata.tlid, controls.getIconForAction()) updatePlayIcons(songdata.track.uri, songdata.tlid, controls.getIconForAction())
// Look up track details and add album headers
if (uris.length > 0) { if (uris.length > 0) {
mopidy.library.lookup({'uris': uris}).then(function (resultDict) { mopidy.library.lookup({'uris': uris}).then(function (resultDict) {
// Break into albums and put in tables // Break into albums and put in tables

View File

@ -1,6 +1,6 @@
CACHE MANIFEST CACHE MANIFEST
# 2017-01-18:v2 # 2017-01-22:v1
NETWORK: NETWORK:
* *