diff --git a/src/services/FyydApi.js b/src/services/FyydApi.js new file mode 100644 index 0000000000000000000000000000000000000000..7db2eb441e860e1f1dc52e1b09c61ac48c1a9f2c --- /dev/null +++ b/src/services/FyydApi.js @@ -0,0 +1,100 @@ +/* + * @copyright Copyright (c) 2020 Jonas Heinrich <onny@project-insanity.org> + * + * @author Jonas Heinrich <onny@project-insanity.org> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +import axios from '@nextcloud/axios' + +export class FyydApi { + + url() { + const url = 'https://api.fyyd.de/0.2' + return url + } + + queryPodcast(podcastId) { + + delete axios.defaults.headers.requesttoken + return axios.get(this.url() + '/podcast', { + params: { + podcast_id: podcastId, + }, + }) + .then( + (response) => { + return Promise.resolve(response.data) + }, + (err) => { + return Promise.reject(err) + } + ) + .catch((err) => { + return Promise.reject(err) + }) + + } + + queryEpisodes(podcastId, page) { + + delete axios.defaults.headers.requesttoken + return axios.get(this.url() + '/podcast/episodes', { + params: { + podcast_id: podcastId, + count: 20, + page, + }, + }) + .then( + (response) => { + return Promise.resolve(response.data) + }, + (err) => { + return Promise.reject(err) + } + ) + .catch((err) => { + return Promise.reject(err) + }) + + } + + queryEpisode(episodeId) { + + delete axios.defaults.headers.requesttoken + return axios.get(this.url() + '/episode', { + params: { + episode_id: episodeId, + }, + }) + .then( + (response) => { + return Promise.resolve(response.data) + }, + (err) => { + return Promise.reject(err) + } + ) + .catch((err) => { + return Promise.reject(err) + }) + + } + +} diff --git a/src/services/ShowApi.js b/src/services/ShowApi.js new file mode 100644 index 0000000000000000000000000000000000000000..65d5f1b0d609acf38ab4a2729055df761d5c6513 --- /dev/null +++ b/src/services/ShowApi.js @@ -0,0 +1,57 @@ +/* + * @copyright Copyright (c) 2020 Jonas Heinrich <onny@project-insanity.org> + * + * @author Jonas Heinrich <onny@project-insanity.org> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +import axios from '@nextcloud/axios' +import { generateUrl } from '@nextcloud/router' + +const requesttoken = axios.defaults.headers.requesttoken + +export class ShowApi { + + url(url) { + url = `/apps/podcast/api${url}` + return generateUrl(url) + } + + addShow(show) { + show = { + id: show.id, + imgurl: show.smallImageURL, + title: show.title, + author: show.author, + } + axios.defaults.headers.requesttoken = requesttoken + return axios.post(this.url('/shows'), show) + .then( + (response) => { + return Promise.resolve(response.data) + }, + (err) => { + return Promise.reject(err) + } + ) + .catch((err) => { + return Promise.reject(err) + }) + } + +} diff --git a/src/services/player.js b/src/services/player.js index 2e405dbe6f534b942e396da6d6d83b0c18c33309..1cb127d4b1ddc308204029c0988784a6972e51ae 100644 --- a/src/services/player.js +++ b/src/services/player.js @@ -1,3 +1,25 @@ +/* + * @copyright Copyright (c) 2020 Jonas Heinrich <onny@project-insanity.org> + * + * @author Jonas Heinrich <onny@project-insanity.org> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + import { Howl, Howler } from 'howler' import { showError } from '@nextcloud/dialogs' diff --git a/src/services/podcastApi.js b/src/services/podcastApi.js index ac0a5c6f45d95359a4e04fd67babe3e4f23d9695..0ad52ba81557b6f06c0b249e631b8d3c54c12da2 100644 --- a/src/services/podcastApi.js +++ b/src/services/podcastApi.js @@ -1,3 +1,25 @@ +/* + * @copyright Copyright (c) 2020 Jonas Heinrich <onny@project-insanity.org> + * + * @author Jonas Heinrich <onny@project-insanity.org> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + const categories = require('../assets/categories.json') export function getCategoryName(categoryid) { diff --git a/src/views/Episode.vue b/src/views/Episode.vue index 2ddec6ac24122b68bfdb477368225fd252d31d6f..925b5fd0c8c74869775fcd53d3b451b297d2d561 100644 --- a/src/views/Episode.vue +++ b/src/views/Episode.vue @@ -77,14 +77,15 @@ <script> -import { showError } from '@nextcloud/dialogs' -import axios from '@nextcloud/axios' import EpisodeEmpty from './placeholder/Episode' import ContentCollapsable from '../components/ContentCollapsable' import MediaHeader from '../components/MediaHeader' import TimeAgo from 'javascript-time-ago' +import { FyydApi } from './../services/FyydApi' +const fyydClient = new FyydApi() + const timeAgo = new TimeAgo('en-US') export default { @@ -133,14 +134,14 @@ export default { }, }) .then(function(response) { - vm.processPodcast(response.data) + vm.processEpisode(response.data) }) } catch (error) { showError(t('podcast', 'Could not fetch episode from remote API')) } }, - processPodcast(episode) { + processEpisode(episode) { this.episode = episode.data document.title = episode.data.title + ' - Podcast - Nextcloud' this.loading = false diff --git a/src/views/Show.vue b/src/views/Show.vue index 629ad33d2046681bc5beab5c4ccf7c8bff953cc6..858bdb990f7debcacfd5e26748fbd2e288744311 100644 --- a/src/views/Show.vue +++ b/src/views/Show.vue @@ -37,10 +37,10 @@ @doSubscribe="doSubscribe" /> <Table v-resize="onResize" - :episodes="podcast.episodes" + :episodes="episodes" @doPlay="doPlay" /> <EmptyContent - v-show="nextPage" + v-show="page" icon="icon-loading" class="tableLoading" /> </div> @@ -52,17 +52,16 @@ import Table from '../components/Table' import MediaHeader from '../components/MediaHeader' -import { showError } from '@nextcloud/dialogs' import EmptyContent from '@nextcloud/vue/dist/Components/EmptyContent' -import axios from '@nextcloud/axios' -import { generateUrl } from '@nextcloud/router' - import { audioPlayer, doPlay } from '../services/player' import ShowEmpty from './placeholder/Show' -const requesttoken = axios.defaults.headers.requesttoken +import { ShowApi } from './../services/ShowApi' +import { FyydApi } from './../services/FyydApi' +const fyydClient = new FyydApi() +const apiClient = new ShowApi() export default { name: 'Show', @@ -73,25 +72,24 @@ export default { ShowEmpty, }, data: () => ({ - podcast: { - episodes: [], - }, - loading: true, - nextPage: null, + podcast: {}, + episodes: [], + page: 0, podcastId: null, issubscribed: false, }), computed: { + loading() { + return this.episodes.length === 0 + }, player() { return this.$store.state.player }, }, watch: { '$route'(to, from) { - this.loading = true - this.nextPage = null this.podcastId = to.params.id - this.queryPodcast(this.podcastId) + this.init() }, 'player.volume'(newVolume, oldVolume) { if (audioPlayer !== null) { @@ -107,17 +105,23 @@ export default { }, }, mounted() { - this.podcastId = this.$route.params.id - this.queryPodcast(this.podcastId) - }, - created() { - window.addEventListener('scroll', this.handleScroll) + this.init() }, destroyed() { window.removeEventListener('scroll', this.handleScroll) }, methods: { + init() { + this.podcast = {} + this.episodes = [] + this.page = 0 + this.podcastId = this.$route.params.id + window.addEventListener('scroll', this.handleScroll) + this.queryPodcast(this.podcastId) + this.queryEpisodes(this.podcastId, this.page) + }, + onResize({ width, height }) { const rect = document.getElementsByClassName('episodeTable')[0].getBoundingClientRect() @@ -136,23 +140,8 @@ export default { }, async doSubscribe() { - const podcastShow = { - id: this.podcast.id, - imgurl: this.podcast.smallImageURL, - title: this.podcast.title, - author: this.podcast.author, - } - try { - axios.defaults.headers.requesttoken = requesttoken - await axios - .post(generateUrl('/apps/podcast/api/shows'), podcastShow) - .then(response => { - this.issubscribed = true - }) - } catch (error) { - showError(t('podcast', 'Could not subscribe to podcast')) - } - + await apiClient.addShow(this.podcast) + this.issubscribed = true }, preFill() { @@ -161,42 +150,24 @@ export default { }, async queryPodcast(podcastId) { - - const vm = this - - const queryURI = this.$apiUrl + '/podcast/episodes' - try { - delete axios.defaults.headers.requesttoken - await axios.get(queryURI, { - params: { - podcast_id: podcastId, - count: 20, - page: vm.nextPage, - }, - }) - .then(function(response) { - vm.nextPage = response.data.meta.paging.next_page - vm.processPodcast(response.data) - }) - } catch (error) { - showError(t('podcast', 'Could not fetch stations from remote API')) - } + const podcast = await fyydClient.queryPodcast(podcastId) + this.processPodcast(podcast.data) }, - processPodcast(podcast) { - if (podcast.meta.paging.page === podcast.meta.paging.last_page) { - this.nextPage = false + async queryEpisodes(podcastId, page) { + const episodes = await fyydClient.queryEpisodes(podcastId, page) + this.episodes = this.episodes.concat(episodes.data.episodes) + if (episodes.meta.paging.next_page === null) { + this.page = null window.removeEventListener('scroll', this.handleScroll) } else { - this.nextPage = podcast.meta.paging.next_page + this.page += 1 } - if (podcast.meta.paging.page === 0) { - this.podcast = podcast.data - } else { - this.podcast.episodes = this.podcast.episodes.concat(podcast.data.episodes) - } - document.title = podcast.data.title + ' - Podcast - Nextcloud' - this.loading = false + }, + + processPodcast(podcast) { + this.podcast = podcast + document.title = podcast.title + ' - Podcast - Nextcloud' }, /** @@ -205,7 +176,7 @@ export default { handleScroll() { if ((window.innerHeight + window.scrollY) >= document.body.scrollHeight) { if (!this.episodesLoaded) { - this.queryPodcast(this.podcastId) + this.queryEpisodes(this.podcastId, this.page) } } },