diff --git a/CHANGELOG.md b/CHANGELOG.md index d8fe3b2a49f583e26746a2fddc25b7a83f956253..cce06a17d55dd7baa779ba64a24d0c223810a69c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,8 +11,12 @@ yet implemented. [#159](https://git.project-insanity.org/onny/nextcloud-app-podcast/-/issues/159) @onny ### Added +- Export podcast subscriptions as OPML + [#104](https://git.project-insanity.org/onny/nextcloud-app-podcast/-/issues/104) @onny - German translation [#183](https://git.project-insanity.org/onny/nextcloud-app-podcast/-/issues/183) @onny +- Make player metadata, title and show name as links + [#167](https://git.project-insanity.org/onny/nextcloud-app-podcast/-/issues/167) @onny ### Changed - Update npm modules diff --git a/lib/Db/Episode.php b/lib/Db/Episode.php index e912637fa39a5018e7779ab621ec90dda7fc4fb4..88812f09f25cafc10095f43f8381e9733c2c9bf0 100644 --- a/lib/Db/Episode.php +++ b/lib/Db/Episode.php @@ -42,7 +42,7 @@ class Episode extends Entity implements JsonSerializable { public function jsonSerialize(): array { return [ 'id' => $this->id, - 'imgurl' => $this->imgurl, + 'imgURL' => $this->imgurl, 'title' => $this->title, 'pubdate' => $this->pubdate, 'duration' => $this->duration, @@ -50,7 +50,7 @@ class Episode extends Entity implements JsonSerializable { 'lastplayed' => $this->lastplayed, 'enclosure' => $this->enclosure, 'description' => $this->description, - 'podcastid' => $this->podcastid, + 'podcast_id' => $this->podcastid, ]; } } diff --git a/lib/Migration/Version000100Date20210315125200.php b/lib/Migration/Version000100Date20210315125200.php new file mode 100644 index 0000000000000000000000000000000000000000..8a851b983827e731eafb53ab9b2bdc8a58aa554e --- /dev/null +++ b/lib/Migration/Version000100Date20210315125200.php @@ -0,0 +1,67 @@ +<?php + +/** + * Podcast App + * + * @author Jonas Heinrich + * @copyright 2021 Jonas Heinrich <onny@project-insanity.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library 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 library. If not, see <http://www.gnu.org/licenses/>. + * + */ + +declare(strict_types=1); + +namespace OCA\Podcast\Migration; + +use Closure; +use OCP\DB\ISchemaWrapper; +use OCP\Migration\SimpleMigrationStep; +use OCP\Migration\IOutput; +use Doctrine\DBAL\Types\Type; + +class Version000100Date20210315125200 extends SimpleMigrationStep { + + /** + * @param IOutput $output + * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + * @param array $options + * + * @return void + */ + public function preSchemaChange(IOutput $output, Closure $schemaClosure, array $options) { + } + + /** + * @param IOutput $output + * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + * @param array $options + * + * @return ISchemaWrapper + */ + public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) { + /** @var ISchemaWrapper $schema */ + $schema = $schemaClosure(); + + $table = $schema->getTable('shows'); + $table->addColumn('homepage', 'string', [ + 'notnull' => false, + ]); + $table->addColumn('feedurl', 'string', [ + 'notnull' => false, + ]); + + return $schema; + } +} diff --git a/src/components/Player.vue b/src/components/Player.vue index 6bcef1e27917d2a02650a3a3f56736499648159b..222c765b4a3f5726523cafb873f00e31f9dfb146 100644 --- a/src/components/Player.vue +++ b/src/components/Player.vue @@ -42,20 +42,25 @@ </div> <div class="metaControls"> <div - v-lazy:background-image="getImage" - class="playerThumb" /> + v-lazy:background-image="getEpisode.imgURL" + class="playerThumb" + @click="$router.push(`/browse/show/${getEpisode.podcast_id}/${getEpisode.id}`)" /> <div class="text"> - <span class="title">{{ getTitle }}</span> - <span>{{ getPodcastName }}</span> + <span class="title"> + <a :href="`#/browse/show/${getEpisode.podcast_id}/${getEpisode.id}`">{{ getEpisode.title }}</a> + </span> + <span> + <a :href="`#/browse/show/${getEpisode.podcast_id}`">{{ getPodcastName }}</a> + </span> </div> </div> <div class="playbackControls"> - <span>{{ secondsToHHMMSS(currentSeek) }} / {{ secondsToHHMMSS(getDuration) }}</span> + <span>{{ secondsToHHMMSS(currentSeek) }} / {{ secondsToHHMMSS( getEpisode.duration) }}</span> <input type="range" class="rangeStyle" min="0" - :max="getDuration" + :max="getEpisode.duration" step=".5" :value="currentSeek" :disabled="!getSeek" @@ -93,13 +98,11 @@ export default { ...mapGetters([ 'getVolume', 'getSeek', - 'getTitle', - 'getPodcastName', - 'getImage', - 'getDuration', 'isBuffering', 'isPlaying', 'isPaused', + 'getEpisode', + 'getPodcastName', ]), currentSeek() { if (this.seekLocked) { @@ -239,6 +242,7 @@ export default { background-size: cover; background-position: center; margin-right: 20px; + cursor: pointer; } .text { @@ -256,6 +260,14 @@ export default { font-weight: bold; margin-bottom: -5px; } + + a { + color: white; + + &:hover { + text-decoration: underline; + } + } } } diff --git a/src/services/EpisodeApi.js b/src/services/EpisodeApi.js index 9e03545638c7d7bd7d0cce2691315d7db9b37072..63338133fa953e9c20c2f5ea6b46fa71091b868a 100644 --- a/src/services/EpisodeApi.js +++ b/src/services/EpisodeApi.js @@ -34,7 +34,7 @@ export class EpisodeApi { addEpisode(episode) { episode = { id: episode.id, - imgurl: episode.imgURL, + imgURL: episode.imgURL, title: episode.title, pubdate: episode.pubdate, duration: episode.duration, @@ -42,7 +42,7 @@ export class EpisodeApi { lastplayed: Date.now(), enclosure: episode.enclosure, description: episode.description, - podcastid: episode.podcast_id, + podcast_id: episode.podcast_id, } axios.defaults.headers.requesttoken = getRequestToken() return axios.post(this.url('/episodes'), episode) @@ -94,7 +94,7 @@ export class EpisodeApi { updateEpisode({ episode, playtime } = {}) { episode = { id: episode.id, - imgurl: episode.imgURL || episode.imgurl, + imgURL: episode.imgURL, title: episode.title, pubdate: episode.pubdate, duration: episode.duration, @@ -102,7 +102,7 @@ export class EpisodeApi { lastplayed: Date.now(), enclosure: episode.enclosure, description: episode.description, - podcastid: episode.podcast_id || episode.podcastid, + podcast_id: episode.podcast_id, } axios.defaults.headers.requesttoken = getRequestToken() return axios.put(this.url(`/episodes/${episode.id}`), episode) diff --git a/src/store/player.js b/src/store/player.js index ea62d5f1af6e84bee9d34c5d6cc610cd8971fb02..509fdf3ccadec4be10115c0f8a4cefbe018b6692 100644 --- a/src/store/player.js +++ b/src/store/player.js @@ -34,24 +34,20 @@ export default { isPaused: false, volume: 0.5, oldVolume: null, - title: '', - image: '', - episodeId: null, - duration: null, seek: 0, lastplaytimeupdate: null, podcastName: '', + episode: { + id: null, + podcast_id: null, + title: null, + imgURL: null, + playtime: null, + duration: null, + enclosure: null, + }, }, getters: { - getTitle: state => { - return state.title - }, - getPodcastName: state => { - return state.podcastName - }, - getImage: state => { - return state.image - }, getSeek: state => { if (state.seek) { return state.seek @@ -59,9 +55,6 @@ export default { return 0 } }, - getDuration: state => { - return state.duration - }, getVolume: state => { return state.volume }, @@ -75,10 +68,16 @@ export default { return (state.episodeId === id && state.isPaused) }, episodeLoaded: state => (id) => { - return (state.episodeId === id) + return (state.episode.id === id) }, episodePlaying: state => (id) => { - return (state.episodeId === id && state.isPlaying) + return (state.episode.id === id && state.isPlaying) + }, + getEpisode: state => { + return state.episode + }, + getPodcastName: state => { + return state.podcastName }, }, mutations: { @@ -103,13 +102,6 @@ export default { localStorage.setItem('podcast.volume', state.volume) player.volume(state.volume) }, - setTitle(state, title) { - state.title = title - }, - setDuration(state, duration) { - duration = Math.round(duration) - state.duration = duration - }, setSeek(state, seek) { seek = Math.round(seek) if (seek) { @@ -130,15 +122,12 @@ export default { setBuffering(state, bufferingState) { state.isBuffering = bufferingState }, - setImage(state, image) { - state.image = image - }, - setEpisodeId(state, episodeId) { - state.episodeId = episodeId - }, setPodcastName(state, name) { state.podcastName = name }, + setEpisode(state, episode) { + state.episode = episode + }, }, actions: { setPlaying(context, playerState) { @@ -160,21 +149,9 @@ export default { context.commit('toggleMute') }, loadEpisode(context, episode) { - context.commit('setPodcastName', '') - context.commit('setTitle', episode.title) - if (episode.imgURL) { - context.commit('setImage', episode.imgURL) - } else { - context.commit('setImage', episode.imgurl) - } - context.commit('setEpisodeId', episode.id) + context.commit('setEpisode', episode) context.commit('setPausing', true) - if (episode.podcast_id) { - context.dispatch('setPodcastName', episode.podcast_id) - } else { - context.dispatch('setPodcastName', episode.podcastid) - } - context.commit('setDuration', episode.duration) + context.dispatch('setPodcastName', episode.podcast_id) if (episode.playtime) { context.commit('setSeek', episode.playtime) }