From 6d821350eaccad2780f7a3703a0550f6a695ee49 Mon Sep 17 00:00:00 2001 From: Jonas Heinrich <onny@project-insanity.org> Date: Thu, 18 Mar 2021 14:58:20 +0100 Subject: [PATCH] beginning to implement pagination for library and listening --- lib/Controller/EpisodeController.php | 31 +++++++++++++++--------- lib/Controller/ShowController.php | 12 +++++++++- lib/Service/FyydApiService.php | 2 ++ src/services/Player.js | 3 --- src/store/episode.js | 4 ++-- src/store/player.js | 12 ++++------ src/store/show.js | 2 +- src/views/Library.vue | 34 ++++++++++++++++++++++++++ src/views/Listening.vue | 36 ++++++++++++++++++++++++++++ 9 files changed, 110 insertions(+), 26 deletions(-) diff --git a/lib/Controller/EpisodeController.php b/lib/Controller/EpisodeController.php index e8f3818..db66b5b 100644 --- a/lib/Controller/EpisodeController.php +++ b/lib/Controller/EpisodeController.php @@ -66,7 +66,16 @@ class EpisodeController extends Controller { return new DataResponse($this->fyydapi->queryEpisodes($podcast_id, $count, $page)); } - return new DataResponse($this->service->findAll($this->userId)); + $data = $this->service->findAll($this->userId); + $data = array_slice($data, $page * $count, $count); + + $response = [ + "meta" => [ + "paging" => null + ], + "data" => $data, + ]; + return new DataResponse($response); } /** @@ -81,27 +90,27 @@ class EpisodeController extends Controller { /** * @NoAdminRequired */ - public function create(int $id, string $imgurl, string $title, + public function create(int $id, string $imgURL, string $title, string $pubdate, int $duration, int $playtime, int $lastplayed, - string $enclosure, string $description, int $podcastid + string $enclosure, string $description, int $podcast_id ): DataResponse { - return new DataResponse($this->service->create($id, $imgurl, $title, + return new DataResponse($this->service->create($id, $imgURL, $title, $pubdate, $duration, $playtime, $lastplayed, $enclosure, $description, - $podcastid, $this->userId)); + $podcast_id, $this->userId)); } /** * @NoAdminRequired */ - public function update(int $id, string $imgurl, string $title, + public function update(int $id, string $imgURL, string $title, string $pubdate, int $duration, int $playtime, int $lastplayed, - string $enclosure, string $description, int $podcastid + string $enclosure, string $description, int $podcast_id ): DataResponse { - return $this->handleNotFound(function () use ($id, $imgurl, $title, + return $this->handleNotFound(function () use ($id, $imgURL, $title, $pubdate, $duration, $playtime, $lastplayed, $enclosure, $description, - $podcastid) { - return $this->service->update($id, $imgurl, $title, $pubdate, $duration, - $playtime, $lastplayed, $enclosure, $description, $podcastid, + $podcast_id) { + return $this->service->update($id, $imgURL, $title, $pubdate, $duration, + $playtime, $lastplayed, $enclosure, $description, $podcast_id, $this->userId); }); } diff --git a/lib/Controller/ShowController.php b/lib/Controller/ShowController.php index e917b44..50d35a6 100644 --- a/lib/Controller/ShowController.php +++ b/lib/Controller/ShowController.php @@ -65,7 +65,17 @@ class ShowController extends Controller { return new DataResponse($this->fyydapi->queryPodcast($podcast_id)); } - return new DataResponse($this->service->findAll($this->userId)); + $data = $this->service->findAll($this->userId); + $data = array_slice($data, $page * $count, $count); + + $response = [ + "meta" => [ + "paging" => null, + ], + "data" => $data, + ]; + return new DataResponse($response); + } /** diff --git a/lib/Service/FyydApiService.php b/lib/Service/FyydApiService.php index f109e52..0d5cb09 100644 --- a/lib/Service/FyydApiService.php +++ b/lib/Service/FyydApiService.php @@ -64,8 +64,10 @@ class FyydApiService { throw $e; } $body = $response->getBody(); + $parsed = json_decode($body, true); + return $parsed; } diff --git a/src/services/Player.js b/src/services/Player.js index 07bb607..2695794 100644 --- a/src/services/Player.js +++ b/src/services/Player.js @@ -44,12 +44,9 @@ export class Player { store.dispatch('setBuffering', true) }, onplay() { - const duration = audioPlayer.duration() store.dispatch('setPlaying', true) store.dispatch('setBuffering', false) store.dispatch('setPausing', false) - store.dispatch('setDuration', duration) - }, onpause() { store.dispatch('setPlaying', false) diff --git a/src/store/episode.js b/src/store/episode.js index 5d82e97..d5af04d 100644 --- a/src/store/episode.js +++ b/src/store/episode.js @@ -63,9 +63,9 @@ export default { async loadEpisodes(context) { const episodes = await apiClient.loadEpisodes() if (episodes) { - context.dispatch('loadEpisode', episodes[0]) + context.dispatch('loadEpisode', episodes.data[0]) } - context.commit('setEpisodes', episodes) + context.commit('setEpisodes', episodes.data) }, addEpisode({ commit, getters }, episode) { if (getters.episodeExists(episode.id)) { diff --git a/src/store/player.js b/src/store/player.js index 1a35e99..6a9a6a4 100644 --- a/src/store/player.js +++ b/src/store/player.js @@ -65,7 +65,7 @@ export default { return state.isBuffering }, isPaused: state => (id) => { - return (state.episodeId === id && state.isPaused) + return (state.episode.id === id && state.isPaused) }, episodeLoaded: state => (id) => { return (state.episode.id === id) @@ -158,7 +158,7 @@ export default { player.load(episode.enclosure) }, playEpisode(context, episode) { - if (context.state.isPaused && episode.id === context.state.episodeId) { + if (context.state.isPaused && episode.id === context.state.episode.id) { player.play() } else { context.dispatch('loadEpisode', episode) @@ -175,7 +175,7 @@ export default { }, togglePlay(context) { - if (context.state.episodeId === null) { + if (context.state.episode.id === null) { return true } if (context.state.isPaused) { @@ -185,10 +185,6 @@ export default { } }, - setDuration(context, duration) { - context.commit('setDuration', duration) - }, - seekEpisode(context, startTime) { context.commit('seekEpisode', startTime) }, @@ -198,7 +194,7 @@ export default { }, storePlaybacktime(context, position) { - const episodeId = context.state.episodeId + const episodeId = context.state.episode.id const episode = context.getters.episodeById(episodeId) const episodeLastPlayed = episode.lastplayed const dateNow = Date.now() diff --git a/src/store/show.js b/src/store/show.js index 0ae2640..4953c75 100644 --- a/src/store/show.js +++ b/src/store/show.js @@ -59,7 +59,7 @@ export default { actions: { async loadShows({ commit }) { const shows = await apiClient.loadShows() - commit('setShows', shows) + commit('setShows', shows.data) }, addShow({ commit }, show) { apiClient.addShow(show) diff --git a/src/views/Library.vue b/src/views/Library.vue index 17d3f97..2ff4ed9 100644 --- a/src/views/Library.vue +++ b/src/views/Library.vue @@ -22,6 +22,7 @@ <template> <div class="mainContent"> <ItemGrid + v-resize:debounce="onResize" :title="t('podcast', 'Library')" :show-menu="true" :podcasts="podcasts" @@ -34,12 +35,19 @@ import ItemGrid from '../components/ItemGrid' import { mapGetters } from 'vuex' import { setBrowserTitle } from '../utils/misc.js' import { getRequestToken } from '@nextcloud/auth' +import resize from 'vue-resize-directive' export default { name: 'Library', components: { ItemGrid, }, + directives: { + resize, + }, + data: () => ({ + page: 0, + }), computed: { ...mapGetters([ 'subscribedShows', @@ -53,9 +61,35 @@ export default { }, mounted() { setBrowserTitle(t('podcast', 'Library')) + document.getElementById('app-content-vue').addEventListener('scroll', this.handleScroll) + }, + destroyed() { + document.getElementById('app-content-vue').removeEventListener('scroll', this.handleScroll) }, methods: { + preFill() { + const yFill = document.getElementsByClassName('tableLoading')[0].getBoundingClientRect().bottom + const playerPosY = document.getElementsByClassName('player')[0].getBoundingClientRect().top + if (yFill > 0 && yFill < playerPosY) { + this.queryPodcasts(this.page) + } + }, + + /** + * On scroll event, load more episodes if bottom reached + */ + handleScroll() { + const appContent = document.getElementById('app-content-vue') + if (appContent.scrollTop === (appContent.scrollHeight - appContent.clientHeight)) { + this.queryPodcasts(this.page) + } + }, + + onResize() { + this.preFill() + }, + doExport() { window.location = 'export?requesttoken=' diff --git a/src/views/Listening.vue b/src/views/Listening.vue index 1d639ad..f71ddf1 100644 --- a/src/views/Listening.vue +++ b/src/views/Listening.vue @@ -25,6 +25,7 @@ <h1>{{ t('podcast', 'Currently listening') }}</h1> </div> <Table + v-resize:debounce="onResize" :episodes="episodes" :extended="true" @doPlay="doPlay" /> @@ -35,12 +36,19 @@ import Table from '../components/Table' import { mapGetters, mapActions } from 'vuex' import { setBrowserTitle } from '../utils/misc.js' +import resize from 'vue-resize-directive' export default { name: 'Listening', components: { Table, }, + directives: { + resize, + }, + data: () => ({ + page: 0, + }), computed: { ...mapGetters([ 'getEpisodes', @@ -55,12 +63,39 @@ export default { }, mounted() { setBrowserTitle(t('podcast', 'Currently listening')) + document.getElementById('app-content-vue').addEventListener('scroll', this.handleScroll) + }, + destroyed() { + document.getElementById('app-content-vue').removeEventListener('scroll', this.handleScroll) }, methods: { ...mapActions([ 'pauseEpisode', 'playEpisode', ]), + + preFill() { + const yFill = document.getElementsByClassName('tableLoading')[0].getBoundingClientRect().bottom + const playerPosY = document.getElementsByClassName('player')[0].getBoundingClientRect().top + if (yFill > 0 && yFill < playerPosY) { + this.queryPodcasts(this.page) + } + }, + + /** + * On scroll event, load more episodes if bottom reached + */ + handleScroll() { + const appContent = document.getElementById('app-content-vue') + if (appContent.scrollTop === (appContent.scrollHeight - appContent.clientHeight)) { + this.queryPodcasts(this.page) + } + }, + + onResize() { + this.preFill() + }, + doPlay(episode) { if (this.episodePlaying(episode.id)) { this.pauseEpisode() @@ -68,6 +103,7 @@ export default { this.playEpisode(episode) } }, + }, } </script> -- GitLab