Merge pull request #1222 from kgarner7/paginate-songs-page

Paginate songs page
This commit is contained in:
vapormusic 2022-07-02 10:01:18 +07:00 committed by GitHub
commit 5bd5d92370
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 217 additions and 15 deletions

View file

@ -90,6 +90,9 @@
"term.size": "Size",
"term.size.normal": "Normal",
"term.size.compact": "Compact",
"term.scroll": "Scroll Mode",
"term.scroll.infinite": "Infinite",
"term.scroll.paged": "${songsPerPage} per page",
"term.enable": "Enable",
"term.disable": "Disable",
"term.enabled": "Enabled",

View file

@ -147,6 +147,7 @@ export class Store {
},
"libraryPrefs": {
"songs": {
"scroll": "infinite",
"sort": "name",
"sortOrder": "asc",
"size": "normal"

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="white" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.1.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M77.25 256l137.4-137.4c12.5-12.5 12.5-32.75 0-45.25s-32.75-12.5-45.25 0l-160 160c-12.5 12.5-12.5 32.75 0 45.25l160 160C175.6 444.9 183.8 448 192 448s16.38-3.125 22.62-9.375c12.5-12.5 12.5-32.75 0-45.25L77.25 256zM269.3 256l137.4-137.4c12.5-12.5 12.5-32.75 0-45.25s-32.75-12.5-45.25 0l-160 160c-12.5 12.5-12.5 32.75 0 45.25l160 160C367.6 444.9 375.8 448 384 448s16.38-3.125 22.62-9.375c12.5-12.5 12.5-32.75 0-45.25L269.3 256z"/></svg>

After

Width:  |  Height:  |  Size: 685 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="white" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.1.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M246.6 233.4l-160-160c-12.5-12.5-32.75-12.5-45.25 0s-12.5 32.75 0 45.25L178.8 256l-137.4 137.4c-12.5 12.5-12.5 32.75 0 45.25C47.63 444.9 55.81 448 64 448s16.38-3.125 22.62-9.375l160-160C259.1 266.1 259.1 245.9 246.6 233.4zM438.6 233.4l-160-160c-12.5-12.5-32.75-12.5-45.25 0s-12.5 32.75 0 45.25L370.8 256l-137.4 137.4c-12.5 12.5-12.5 32.75 0 45.25C239.6 444.9 247.8 448 256 448s16.38-3.125 22.62-9.375l160-160C451.1 266.1 451.1 245.9 438.6 233.4z"/></svg>

After

Width:  |  Height:  |  Size: 706 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="white" viewBox="0 0 320 512"><!--! Font Awesome Pro 6.1.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M96 480c-8.188 0-16.38-3.125-22.62-9.375c-12.5-12.5-12.5-32.75 0-45.25L242.8 256L73.38 86.63c-12.5-12.5-12.5-32.75 0-45.25s32.75-12.5 45.25 0l192 192c12.5 12.5 12.5 32.75 0 45.25l-192 192C112.4 476.9 104.2 480 96 480z"/></svg>

After

Width:  |  Height:  |  Size: 478 B

View file

@ -162,6 +162,32 @@
align-self: center;
}
.page-btn {
align-self: center;
height: 32px;
}
.page-btn img {
height: 100%;
align-self: center;
}
.md-ico-first {
content: url('./assets/angles-left.svg');
}
.md-ico-prev {
content: url('./assets/chevron-left.svg');
}
.md-ico-next {
content: url('./assets/chevron-right.svg');
}
.md-ico-last {
content: url('./assets/angles-right.svg');
}
.reload-btn {
background: rgb(86 86 86 / 52%);
border-radius: 100%;

View file

@ -10652,6 +10652,26 @@ fieldset:disabled .btn {
margin-bottom: -1.5px;
align-self: center;
}
.page-btn {
align-self: center;
height: 32px;
}
.page-btn img {
height: 100%;
align-self: center;
}
.md-ico-first {
content: url('./assets/angles-left.svg');
}
.md-ico-prev {
content: url('./assets/chevron-left.svg');
}
.md-ico-next {
content: url('./assets/chevron-right.svg');
}
.md-ico-last {
content: url('./assets/angles-right.svg');
}
.reload-btn {
background: rgba(86, 86, 86, 0.52);
border-radius: 100%;

View file

@ -1,5 +1,5 @@
<script type="text/x-template" id="mediaitem-list-item">
<div v-observe-visibility="{callback: visibilityChanged}"
<div v-observe-visibility="{callback: visibilityChanged, throttle: 100}"
@contextmenu="contextMenu"
@click="select"
:data-id="itemId"

View file

@ -1,5 +1,3 @@
<script type="text/x-template" id="cider-library-songs">
<div class="content-inner library-page">
<div class="library-header">
@ -48,6 +46,14 @@
</optgroup>
</select>
</div>
<div class="col">
<select class="md-select" v-model="prefs.scroll">
<optgroup :label="app.getLz('term.scroll')">
<option value="infinite">{{app.getLz('term.scroll.infinite')}}</option>
<option value="paged">{{app.getLz('term.scroll.paged').replace("${songsPerPage}", pageSize)}}</option>
</optgroup>
</select>
</div>
</div>
</div>
<div class="col-auto flex-center">
@ -58,14 +64,53 @@
</button>
</div>
</div>
<div class="row" style="margin-bottom: 16px" v-if="!isInfinite">
<button
class="col md-btn page-btn"
:disabled="currentPage === 1"
@click="goToPage(1)"
>
<img class="md-ico-first"/>
</button>
<button
class="col md-btn page-btn prev"
:disabled="currentPage === 1"
@click="goToPrevious()"
>
<img class="md-ico-prev"/>
</button>
<button
:class="`col md-btn page-btn${ isCurrentPage(page) ? ' md-btn-primary': ''}`"
@click="goToPage(page)"
v-for="page in pagesToShow"
>{{ page }}</button>
<button
class="col md-btn page-btn next"
:disabled="currentPage === numPages"
@click="goToNext()"
>
<img class="md-ico-next"/>
</button>
<button
class="col md-btn page-btn last"
:disabled="currentPage === numPages"
@click="goToEnd()"
>
<img class="md-ico-last"/>
</button>
<div class="col page-btn" style="min-width: 12em;">
<input type="number" min="1" :max="numPages" :value="currentPage" @change="changePage" />
<span>/ {{ numPages }}</span>
</div>
</div>
</div>
<div v-if="library.songs.downloadState == 3">Library contains no songs.</div>
<div class="well" :key="1" v-if="prefs.size == 'compact'">
<mediaitem-list-item class-list="compact" :item="item" :parent="'librarysongs'" :index="index" :show-meta-data="true" :show-library-status="false" v-for="(item, index) in library.songs.displayListing"></mediaitem-list-item>
<mediaitem-list-item class-list="compact" :item="item" :parent="'librarysongs'" :index="index" :show-meta-data="true" :show-library-status="false" v-for="(item, index) in currentSlice"></mediaitem-list-item>
</div>
<div class="well" :key="2" v-else>
<mediaitem-list-item :item="item" :parent="'librarysongs'" :index="index" :show-meta-data="true" :show-library-status="false" v-for="(item, index) in library.songs.displayListing"></mediaitem-list-item>
<mediaitem-list-item :item="item" :parent="'librarysongs'" :index="index" :show-meta-data="true" :show-library-status="false" v-for="(item, index) in currentSlice"></mediaitem-list-item>
</div>
</div>
</script>
@ -75,21 +120,125 @@
template: '#cider-library-songs',
data: function () {
return {
// currentPage is oneIndexed
currentPage: 1,
library: this.$root.library,
mediaItemSize: "compact",
pageSize: 250,
prefs: this.$root.cfg.libraryPrefs.songs,
app : this.$root
app: this.$root
}
},
mounted() {
document.querySelector("#app-content")
.addEventListener("scroll", this.handleScroll)
this.$root.getLibrarySongsFull()
},
methods: {
sayHello: function () {
alert('Hello world!');
destroyed() {
document.querySelector("#app-content")
.removeEventListener("scroll", this.handleScroll)
},
watch: {
'library.songs.displayListing.length': function () {
if (this.isInfinite) {
// If a search reduces the number of things to show, we want to limit
// the number of songs shown as well. This is to prevent you scrolling
// to load your entire library, searching for one song, and then having
// th re-render the entire library
if (this.currentPage > this.numPages) {
this.currentPage = this.numPages;
}
}
},
play: function () {
'prefs.scroll': function () {
// When changing modes, set the page to 1. This is primarily to
// prevent going to a high page (e.g., 50) and then switching to infinite
// and showing 12.5k songs
this.currentPage = 1;
}
},
computed: {
isInfinite: function () {
return this.prefs.scroll === "infinite"
},
currentSlice: function () {
if (this.isInfinite) {
return this.library.songs.displayListing.slice(
0, this.currentPage * this.pageSize
);
} else {
const startingPage = Math.min(this.numPages, this.currentPage);
return this.library.songs.displayListing.slice(
(startingPage - 1) * this.pageSize,
startingPage * this.pageSize
);
}
},
numPages: function () {
return Math.ceil(this.library.songs.displayListing.length / this.pageSize) || 1;
},
pagesToShow: function () {
let start = this.currentPage - 2;
let end = this.currentPage + 2;
if (start < 1) {
end += (1 - start);
start = 1;
}
const endDifference = end - this.numPages;
if (endDifference > 0) {
end = this.numPages;
start = Math.max(1, start - endDifference);
}
const array = [];
for (let idx = start; idx <= end; idx++) {
array.push(idx);
}
return array;
}
},
methods: {
// Infinite Scrolling
handleScroll: function (event) {
if (this.isInfinite &&
this.currentPage < this.numPages &&
event.target.scrollTop >= event.target.scrollHeight - event.target.clientHeight) {
this.currentPage += 1;
}
},
// Pagination
isCurrentPage: function (idx) {
return idx === this.currentPage ||
(idx === this.numPages && this.currentPage > this.numPages);
},
changePage: function (event) {
const value = event.target.valueAsNumber;
if (!isNaN(value) && value >= 1 && value <= this.numPages) {
this.currentPage = value;
}
},
goToPage: function (page) {
this.currentPage = page;
},
goToPrevious: function () {
if (this.currentPage > 1) {
this.currentPage -= 1;
}
},
goToNext: function () {
if (this.currentPage < this.numPages) {
this.currentPage += 1;
}
},
goToEnd: function () {
this.currentPage = this.numPages;
},
// Miscellaneous
play: function () {
function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
@ -101,11 +250,11 @@
let query = this.app.library.songs.displayListing.map(item => new MusicKit.MediaItem(item));
if (!app.mk.queue.isEmpty)
app.mk.queue.splice(0, app.mk.queue._itemIDs.length);
app.mk.queue.splice(0, app.mk.queue._itemIDs.length);
app.mk.stop().then(() => {
if (app.mk.shuffleMode == 1) {
shuffleArray(query)
}
if (app.mk.shuffleMode == 1) {
shuffleArray(query)
}
app.mk.queue.append(query)
app.mk.changeToMediaAtIndex(0)
});