diff --git a/src/renderer/views/Playlist/Playlist.css b/src/renderer/views/Playlist/Playlist.css index c6f13f0a5c1e6..b8318e3828c16 100644 --- a/src/renderer/views/Playlist/Playlist.css +++ b/src/renderer/views/Playlist/Playlist.css @@ -34,6 +34,11 @@ color: var(--tertiary-text-color); } +.loadNextPageWrapper { + /* about the same height as the button */ + max-height: 7vh; +} + @media only screen and (max-width: 850px) { .routerView { flex-direction: column; diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js index cb9400a9e94df..ad2803bea116d 100644 --- a/src/renderer/views/Playlist/Playlist.js +++ b/src/renderer/views/Playlist/Playlist.js @@ -4,6 +4,8 @@ import FtLoader from '../../components/ft-loader/ft-loader.vue' import FtCard from '../../components/ft-card/ft-card.vue' import PlaylistInfo from '../../components/playlist-info/playlist-info.vue' import FtListVideo from '../../components/ft-list-video/ft-list-video.vue' +import FtFlexBox from '../../components/ft-flex-box/ft-flex-box.vue' +import FtButton from '../../components/ft-button/ft-button.vue' import i18n from '../../i18n/index' import { getLocalPlaylist } from '../../helpers/api/local' import { extractNumberFromString } from '../../helpers/utils' @@ -14,17 +16,18 @@ export default Vue.extend({ 'ft-loader': FtLoader, 'ft-card': FtCard, 'playlist-info': PlaylistInfo, - 'ft-list-video': FtListVideo + 'ft-list-video': FtListVideo, + 'ft-flex-box': FtFlexBox, + 'ft-button': FtButton }, data: function () { return { isLoading: false, playlistId: null, - nextPageRef: '', - lastSearchQuery: '', - playlistPage: 1, infoData: {}, - playlistItems: [] + playlistItems: [], + continuationData: null, + isLoadingMore: false } }, computed: { @@ -87,15 +90,11 @@ export default Vue.extend({ channelId: this.infoData.channelId }) - this.playlistItems = result.items.map((video) => { - return { - videoId: video.id, - title: video.title, - author: video.author.name, - authorId: video.author.id, - lengthSeconds: isNaN(video.duration.seconds) ? '' : video.duration.seconds - } - }) + this.playlistItems = result.items.map(this.parseVideoLocal) + + if (result.has_continuation) { + this.continuationData = result + } this.isLoading = false }).catch((err) => { @@ -109,6 +108,16 @@ export default Vue.extend({ }) }, + parseVideoLocal: function (video) { + return { + videoId: video.id, + title: video.title.text, + author: video.author.name, + authorId: video.author.id, + lengthSeconds: isNaN(video.duration.seconds) ? '' : video.duration.seconds + } + }, + getPlaylistInvidious: function () { this.isLoading = true @@ -155,22 +164,32 @@ export default Vue.extend({ }) }, - nextPage: function () { - const payload = { - query: this.query, - options: { - nextpageRef: this.nextPageRef - }, - nextPage: true + getNextPage: function () { + switch (this.infoData.infoSource) { + case 'local': + this.getNextPageLocal() + break + case 'invidious': + console.error('Playlist pagination is not currently supported when the Invidious backend is selected.') + break } - - this.performSearch(payload) }, - replaceShownResults: function (history) { - this.shownResults = history.data - this.nextPageRef = history.nextPageRef - this.isLoading = false + getNextPageLocal: function () { + this.isLoadingMore = true + + this.continuationData.getContinuation().then((result) => { + const parsedVideos = result.items.map(this.parseVideoLocal) + this.playlistItems = this.playlistItems.concat(parsedVideos) + + if (result.has_continuation) { + this.continuationData = result + } else { + this.continuationData = null + } + + this.isLoadingMore = false + }) }, ...mapActions([ diff --git a/src/renderer/views/Playlist/Playlist.vue b/src/renderer/views/Playlist/Playlist.vue index 7b65c9c002813..6cc23d7a77987 100644 --- a/src/renderer/views/Playlist/Playlist.vue +++ b/src/renderer/views/Playlist/Playlist.vue @@ -33,6 +33,22 @@ force-list-type="list" /> + + + +
+ +