Merge remote-tracking branch 'personal/album-subdirs-pagination' into develop

master
Andrew DeMaria 8 years ago
commit a7be3743b1
No known key found for this signature in database
GPG Key ID: 0A3F5E91F8364EDF
  1. 9
      libresonic-main/src/main/java/org/libresonic/player/command/PersonalSettingsCommand.java
  2. 38
      libresonic-main/src/main/java/org/libresonic/player/controller/MainController.java
  3. 2
      libresonic-main/src/main/java/org/libresonic/player/controller/PersonalSettingsController.java
  4. 8
      libresonic-main/src/main/java/org/libresonic/player/dao/UserDao.java
  5. 9
      libresonic-main/src/main/java/org/libresonic/player/domain/UserSettings.java
  6. 1
      libresonic-main/src/main/java/org/libresonic/player/service/SettingsService.java
  7. 17
      libresonic-main/src/main/resources/liquibase/6.2/add-user-pagination.xml
  8. 1
      libresonic-main/src/main/resources/liquibase/6.2/changelog.xml
  9. 1
      libresonic-main/src/main/resources/org/libresonic/player/i18n/ResourceBundle_en.properties
  10. 11
      libresonic-main/src/main/webapp/WEB-INF/jsp/albumMain.jsp
  11. 8
      libresonic-main/src/main/webapp/WEB-INF/jsp/artistMain.jsp
  12. 4
      libresonic-main/src/main/webapp/WEB-INF/jsp/personalSettings.jsp
  13. 7
      libresonic-main/src/main/webapp/WEB-INF/jsp/videoMain.jsp
  14. 10
      libresonic-main/src/main/webapp/script/util.js
  15. 3
      libresonic-main/src/test/java/org/libresonic/player/dao/UserDaoTestCase.java

@ -54,6 +54,7 @@ public class PersonalSettingsCommand {
private boolean queueFollowingSongs;
private boolean lastFmEnabled;
private int listReloadDelay;
private int paginationSize;
private String lastFmUsername;
private String lastFmPassword;
@ -264,4 +265,12 @@ public class PersonalSettingsCommand {
public void setQueueFollowingSongs(boolean queueFollowingSongs) {
this.queueFollowingSongs = queueFollowingSongs;
}
public int getPaginationSize() {
return paginationSize;
}
public void setPaginationSize(int paginationSize) {
this.paginationSize = paginationSize;
}
}

@ -19,6 +19,7 @@
*/
package org.libresonic.player.controller;
import org.apache.commons.lang3.BooleanUtils;
import org.libresonic.player.domain.*;
import org.libresonic.player.service.*;
import org.springframework.beans.factory.annotation.Autowired;
@ -26,6 +27,7 @@ import org.springframework.stereotype.Controller;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;
@ -59,7 +61,9 @@ public class MainController {
private AdService adService;
@RequestMapping(method = RequestMethod.GET)
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
protected ModelAndView handleRequestInternal(@RequestParam(name = "showAll", required = false) Boolean showAll,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
Map<String, Object> map = new HashMap<>();
Player player = playerService.getPlayer(request, response);
@ -84,7 +88,12 @@ public class MainController {
return new ModelAndView(new RedirectView("accessDenied.view"));
}
List<MediaFile> children = mediaFiles.size() == 1 ? mediaFileService.getChildrenOf(dir, true, true, true) : getMultiFolderChildren(mediaFiles);
UserSettings userSettings = settingsService.getUserSettings(username);
List<MediaFile> children = mediaFiles.size() == 1 ? mediaFileService.getChildrenOf(dir,
true,
true,
true) : getMultiFolderChildren(mediaFiles);
List<MediaFile> files = new ArrayList<>();
List<MediaFile> subDirs = new ArrayList<>();
for (MediaFile child : children) {
@ -95,7 +104,14 @@ public class MainController {
}
}
UserSettings userSettings = settingsService.getUserSettings(username);
int userPaginationPreference = userSettings.getPaginationSize();
if(userPaginationPreference <= 0) {
showAll = true;
}
boolean thereIsMoreSubDirs = trimToSize(showAll, subDirs, userPaginationPreference);
boolean thereIsMoreSAlbums = false;
mediaFileService.populateStarredDate(dir, username);
mediaFileService.populateStarredDate(children, username);
@ -115,7 +131,9 @@ public class MainController {
map.put("brand", settingsService.getBrand());
map.put("viewAsList", isViewAsList(request, userSettings));
if (dir.isAlbum()) {
map.put("sieblingAlbums", getSieblingAlbums(dir));
List<MediaFile> sieblingAlbums = getSieblingAlbums(dir);
thereIsMoreSAlbums = trimToSize(showAll, sieblingAlbums, userPaginationPreference);
map.put("sieblingAlbums", sieblingAlbums);
map.put("artist", guessArtist(children));
map.put("album", guessAlbum(children));
}
@ -127,6 +145,7 @@ public class MainController {
} catch (SecurityException x) {
// Happens if Podcast directory is outside music folder.
}
map.put("thereIsMore", (thereIsMoreSubDirs || thereIsMoreSAlbums) && !BooleanUtils.isTrue(showAll));
Integer userRating = ratingService.getRatingForUser(username, dir);
Double averageRating = ratingService.getAverageRating(dir);
@ -155,6 +174,17 @@ public class MainController {
return new ModelAndView(view, "model", map);
}
private <T> boolean trimToSize(Boolean showAll, List<T> list, int userPaginationPreference) {
boolean trimmed = false;
if(!BooleanUtils.isTrue(showAll)) {
if(list.size() > userPaginationPreference) {
trimmed = true;
list.subList(userPaginationPreference, list.size()).clear();
}
}
return trimmed;
}
private boolean isViewAsList(HttpServletRequest request, UserSettings userSettings) {
boolean viewAsList = ServletRequestUtils.getBooleanParameter(request, "viewAsList", userSettings.isViewAsList());
if (viewAsList != userSettings.isViewAsList()) {

@ -82,6 +82,7 @@ public class PersonalSettingsController {
command.setLastFmEnabled(userSettings.isLastFmEnabled());
command.setLastFmUsername(userSettings.getLastFmUsername());
command.setLastFmPassword(userSettings.getLastFmPassword());
command.setPaginationSize(userSettings.getPaginationSize());
Locale currentLocale = userSettings.getLocale();
Locale[] locales = settingsService.getAvailableLocales();
@ -150,6 +151,7 @@ public class PersonalSettingsController {
settings.setLastFmUsername(command.getLastFmUsername());
settings.setSystemAvatarId(getSystemAvatarId(command));
settings.setAvatarScheme(getAvatarScheme(command));
settings.setPaginationSize(command.getPaginationSize());
if (StringUtils.isNotBlank(command.getLastFmPassword())) {
settings.setLastFmPassword(command.getLastFmPassword());

@ -46,7 +46,8 @@ public class UserDao extends AbstractDao {
"playlist_year, playlist_bit_rate, playlist_duration, playlist_format, playlist_file_size, " +
"last_fm_enabled, last_fm_username, last_fm_password, transcode_scheme, show_now_playing, selected_music_folder_id, " +
"party_mode_enabled, now_playing_allowed, avatar_scheme, system_avatar_id, changed, show_artist_info, auto_hide_play_queue, " +
"view_as_list, default_album_list, queue_following_songs, show_side_bar, list_reload_delay, keyboard_shortcuts_enabled";
"view_as_list, default_album_list, queue_following_songs, show_side_bar, list_reload_delay, " +
"keyboard_shortcuts_enabled, pagination_size";
private static final Integer ROLE_ID_ADMIN = 1;
private static final Integer ROLE_ID_DOWNLOAD = 2;
@ -214,7 +215,9 @@ public class UserDao extends AbstractDao {
settings.getAvatarScheme().name(), settings.getSystemAvatarId(), settings.getChanged(),
settings.isShowArtistInfoEnabled(), settings.isAutoHidePlayQueue(),
settings.isViewAsList(), settings.getDefaultAlbumList().getId(), settings.isQueueFollowingSongs(),
settings.isShowSideBar(), settings.getListReloadDelay(), settings.isKeyboardShortcutsEnabled()});
settings.isShowSideBar(), settings.getListReloadDelay(), settings.isKeyboardShortcutsEnabled(),
settings.getPaginationSize()
});
}
private static String encrypt(String s) {
@ -375,6 +378,7 @@ public class UserDao extends AbstractDao {
settings.setShowSideBar(rs.getBoolean(col++));
settings.setListReloadDelay((Integer) rs.getObject(col++));
settings.setKeyboardShortcutsEnabled(rs.getBoolean(col++));
settings.setPaginationSize(rs.getInt(col++));
return settings;
}

@ -56,6 +56,7 @@ public class UserSettings {
private AvatarScheme avatarScheme = AvatarScheme.NONE;
private Integer systemAvatarId;
private Date changed = new Date();
private int paginationSize;
public UserSettings(String username) {
this.username = username;
@ -287,6 +288,14 @@ public class UserSettings {
this.queueFollowingSongs = queueFollowingSongs;
}
public int getPaginationSize() {
return paginationSize;
}
public void setPaginationSize(int paginationSize) {
this.paginationSize = paginationSize;
}
/**
* Configuration of what information to display about a song.
*/

@ -1061,6 +1061,7 @@ public class SettingsService {
settings.setLastFmUsername(null);
settings.setLastFmPassword(null);
settings.setChanged(new Date());
settings.setPaginationSize(40);
UserSettings.Visibility playlist = settings.getPlaylistVisibility();
playlist.setArtistVisible(true);

@ -0,0 +1,17 @@
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet id="add-user-pagination_001" author="muff1nman">
<preConditions onFail="MARK_RAN">
<not>
<columnExists tableName="user_settings" columnName="pagination_size" />
</not>
</preConditions>
<addColumn tableName="user_settings">
<column name="pagination_size" type="int" defaultValueNumeric="40">
<constraints nullable="false" />
</column>
</addColumn>
</changeSet>
</databaseChangeLog>

@ -3,4 +3,5 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<include file="remove-show-chat.xml" relativeToChangelogFile="true"/>
<include file="add-user-pagination.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

@ -410,6 +410,7 @@ personalsettings.finalversionnotification = Notify me about new versions
personalsettings.betaversionnotification = Notify me about new beta versions
personalsettings.songnotification = Notify me when new songs are played (not supported by all browsers)
personalsettings.listreloaddelay = Album list reload delay (in seconds, 0 disables)
personalsettings.paginationsize = Number of initial related albums/directories to display (0 disables album pagination)
personalsettings.lastfmenabled = Register what I'm playing at <a href="http://last.fm/" target="_blank">Last.fm</a>
personalsettings.lastfmusername = Last.fm username
personalsettings.lastfmpassword = Last.fm password

@ -12,6 +12,7 @@
<script type="text/javascript" src="<c:url value="/dwr/interface/multiService.js"/>"></script>
<script type="text/javascript" src="<c:url value="/script/fancyzoom/FancyZoom.js"/>"></script>
<script type="text/javascript" src="<c:url value="/script/fancyzoom/FancyZoomHTML.js"/>"></script>
<script type="text/javascript" src="<c:url value="/script/util.js"/>"></script>
</head><body class="mainframe bgcolor1" onload="init();">
@ -156,8 +157,7 @@
});
}
function showAllAlbums() {
$("#showAllButton").hide();
$(".albumThumb").show();
window.location.href = updateQueryStringParameter(window.location.href, "showAll", "1");
}
</script>
@ -468,11 +468,14 @@
</tr>
</table>
<c:if test="${model.thereIsMore}">
<input id="showAllButton" class="albumOverflowButton" type="button" value="<fmt:message key="main.showall"/>" onclick="showAllAlbums()">
</c:if>
<c:if test="${not model.viewAsList}">
<div style="float: left">
<c:forEach items="${model.sieblingAlbums}" var="album" varStatus="loopStatus">
<div class="albumThumb" style="display:${loopStatus.count < 10 ? 'inline-block' : 'none'}">
<div class="albumThumb">
<c:import url="coverArt.jsp">
<c:param name="albumId" value="${album.id}"/>
<c:param name="caption1" value="${fn:escapeXml(album.name)}"/>
@ -485,7 +488,7 @@
</c:import>
</div>
</c:forEach>
<c:if test="${fn:length(model.sieblingAlbums) >= 10}">
<c:if test="${model.thereIsMore}">
<input id="showAllButton" class="albumOverflowButton" type="button" value="<fmt:message key="main.showall"/>" onclick="showAllAlbums()">
</c:if>
</div>

@ -31,6 +31,7 @@
<script type="text/javascript" src="<c:url value="/dwr/interface/multiService.js"/>"></script>
<script type="text/javascript" src="<c:url value="/script/fancyzoom/FancyZoom.js"/>"></script>
<script type="text/javascript" src="<c:url value="/script/fancyzoom/FancyZoomHTML.js"/>"></script>
<script type="text/javascript" src="<c:url value="/script/util.js"/>"></script>
</head><body class="mainframe bgcolor1" onload="init();">
@ -154,8 +155,7 @@
$().toastmessage('showSuccessToast', '<fmt:message key="main.addnext.toast"/>')
}
function showAllAlbums() {
$("#showAllButton").hide();
$(".albumThumb").show();
window.location.href = updateQueryStringParameter(window.location.href, "showAll", "1");
}
</script>
@ -265,7 +265,7 @@
<c:forEach items="${model.subDirs}" var="subDir" varStatus="loopStatus">
<c:if test="${subDir.album}">
<c:set var="albumCount" value="${albumCount + 1}"/>
<div class="albumThumb" style="display:${loopStatus.count < 40 ? 'inline-block' : 'none'}">
<div class="albumThumb">
<c:import url="coverArt.jsp">
<c:param name="albumId" value="${subDir.id}"/>
<c:param name="caption1" value="${fn:escapeXml(subDir.name)}"/>
@ -279,7 +279,7 @@
</div>
</c:if>
</c:forEach>
<c:if test="${albumCount >= 40}">
<c:if test="${model.thereIsMore}">
<input id="showAllButton" class="albumOverflowButton" type="button" value="<fmt:message key="main.showall"/>" onclick="showAllAlbums()">
</c:if>
</div>

@ -189,6 +189,10 @@
<td><fmt:message key="personalsettings.listreloaddelay"/></td>
<td><form:input path="listReloadDelay" size="24"/></td>
</tr>
<tr>
<td><fmt:message key="personalsettings.paginationsize"/></td>
<td><form:input path="paginationSize" size="24"/></td>
</tr>
</table>
<table id="lastFmTable" style="padding-left:2em">

@ -23,6 +23,7 @@
<html><head>
<%@ include file="head.jsp" %>
<%@ include file="jquery.jsp" %>
<script type="text/javascript" src="<c:url value="/script/util.js"/>"></script>
<script type="text/javascript">
var image;
@ -61,6 +62,9 @@
image.attr("src", "coverArt.view?id=" + id + "&size=" + size);
}
}
function showAllAlbums() {
window.location.href = updateQueryStringParameter(window.location.href, "showAll", "1");
}
</script>
<style type="text/css">
@ -121,6 +125,9 @@
</c:forEach>
</c:if>
</table>
<c:if test="${model.thereIsMore && fn:length(model.subDirs) gt 0}">
<input id="showAllButton" class="albumOverflowButton" type="button" value="<fmt:message key="main.showall"/>" onclick="showAllAlbums()">
</c:if>
<div style="clear:both;height:1.5em"></div>

@ -0,0 +1,10 @@
function updateQueryStringParameter(uri, key, value) {
var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");
var separator = uri.indexOf('?') !== -1 ? "&" : "?";
if (uri.match(re)) {
return uri.replace(re, '$1' + key + "=" + value + '$2');
}
else {
return uri + separator + key + "=" + value;
}
}

@ -196,6 +196,7 @@ public class UserDaoTestCase extends DaoTestCaseBean2 {
assertNull("Error in getUserSettings().", userSettings.getSystemAvatarId());
assertEquals("Error in getUserSettings().", 0, userSettings.getListReloadDelay());
assertFalse("Error in getUserSettings().", userSettings.isKeyboardShortcutsEnabled());
assertEquals("Error in getUserSettings().", 0, userSettings.getPaginationSize());
UserSettings settings = new UserSettings("sindre");
settings.setLocale(Locale.SIMPLIFIED_CHINESE);
@ -218,6 +219,7 @@ public class UserDaoTestCase extends DaoTestCaseBean2 {
settings.setChanged(new Date(9412L));
settings.setListReloadDelay(60);
settings.setKeyboardShortcutsEnabled(true);
settings.setPaginationSize(120);
userDao.updateUserSettings(settings);
userSettings = userDao.getUserSettings("sindre");
@ -243,6 +245,7 @@ public class UserDaoTestCase extends DaoTestCaseBean2 {
assertEquals("Error in getUserSettings().", new Date(9412L), userSettings.getChanged());
assertEquals("Error in getUserSettings().", 60, userSettings.getListReloadDelay());
assertTrue("Error in getUserSettings().", userSettings.isKeyboardShortcutsEnabled());
assertEquals("Error in getUserSettings().", 120, userSettings.getPaginationSize());
userDao.deleteUser("sindre");
assertNull("Error in cascading delete.", userDao.getUserSettings("sindre"));

Loading…
Cancel
Save