Skip to content
Snippets Groups Projects
Episode.vue 6.6 KiB
Newer Older
<!--
  - @copyright Copyright (c) 2020 Jonas Heinrich
  -
  - @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/>.
  -
  -->
<template>
	<div>
		<ShowEmpty v-show="pageLoading" />
		<transition name="fade">
			<div v-show="!pageLoading">
					class="podcastHeaderBg"
					:style="{ backgroundImage: `url(${episode.imgURL})` }">
					<div class="podcastHeader">
						<div
							class="podcastImage"
							:style="{ backgroundImage: `url(${episode.imgURL})` }" />
						<div class="podcastDescription">
							<h1>{{ episode.title }}</h1>
							<div class="podcastAuthor">
								{{ t('podcast', 'by') }} <a :href="episode.htmlURL" target="_blank">{{ episode.author }}</a>
							</div>
							<button class="icon-play-white podcastButton button primary new-button">
								{{ t('podcast', 'Play episode') }}
							</button>
							<br><br>
							<span>
								<b>Duration:</b>
								{{ episode.duration_string }}
							</span>
							<br>
							<span>
								<b>Publication date:</b>
								{{ readableDate(episode.pubdate) }}
							</span>
						</div>
					</div>
				</div>
				<div class="episodeContent">
					<h2>{{ t('podcast', 'Episode notes') }}</h2>
					<div
						v-show="showNotes"
						class="menuToggle"
						@click="showNotes = !showNotes">
						{{ t('podcast', 'Hide notes') }}
					</div>
					<div
						v-show="!showNotes"
						class="menuToggle"
						@click="showNotes = !showNotes">
						{{ t('podcast', 'Show notes') }}
					<!-- eslint-disable -->
					<p
						v-show="showNotes"
						v-html="episode.description" />
					<!-- eslint-enable -->
				</div>
				<div v-show="episode.chapters" class="episodeContent">
					<h2>{{ t('podcast', 'Episode chapters') }}</h2>
					<table class="chapterTable">
						<tbody>
							<tr
								v-for="(chapter, idx) in episode.chapters"
								:key="idx">
								<td class="timeColumn">
									{{ chapter.start }}
								</td>
								<td>{{ chapter.title }}</td>
							</tr>
						</tbody>
					</table>
import { showError } from '@nextcloud/dialogs'
import axios from '@nextcloud/axios'
import ShowEmpty from './ShowEmpty'

import TimeAgo from 'javascript-time-ago'
const timeAgo = new TimeAgo('en-US')

export default {
	name: 'Episode',
	components: {
		pageLoading: false,
		this.pageLoading = true
		const episodeId = this.$route.params.episodeId
		this.queryEpisode(episodeId)
		readableDate(datetime) {
			return timeAgo.format(Date.parse(datetime), 'twitter-minute-now')
		async queryEpisode(episodeId) {
			const queryURI = 'https://api.fyyd.de/0.2/episode'
			try {
				delete axios.defaults.headers.requesttoken
				await axios.get(queryURI, {
					params: {
						episode_id: episodeId,
					},
				})
					.then(function(response) {
						vm.processPodcast(response.data)
					})
			} catch (error) {
				showError(t('podcast', 'Could not fetch episode from remote API'))
		processPodcast(episode) {
			this.episode = episode.data
			this.pageLoading = false
		},
.podcastHeaderBg {
	background-size: cover;
	background-position: center center;
	background-attachment: fixed;
}
.podcastHeader {
	width: 100%;
	min-height: 300px;
	display: flex;
	color: white;
	justify-content: center;
	padding: 40px 20px;
	/* gap: 30px; */
	background-color: rgba(0, 0, 0, .7);
	backdrop-filter: blur(8px);
	text-shadow: 1px 1px 2px rgba(0,0,0,.5);
	.podcastImage {
		width: 200px;
		height: 200px;
onny's avatar
onny committed
		flex-shrink: 0;
		background-size: cover;
		background-position: center;
		box-shadow: 0 4px 60px rgba(0,0,0,.5);
		margin-right: 25px;
		border-radius: 5px;
	}
	.podcastDescription {
		max-width: 500px;
onny's avatar
onny committed
		width: 100%;
		h1 {
			font-size: 30px;
			font-weight: bold;
			line-height: 1.2em;
			color: white;
		}

		.podcastAuthor {
			padding-bottom: 5px;

			a {
				color: white;
		.podcastControls {
			display: flex;
			align-items: center;
			margin-bottom: 5px;
		ul.podcastCategory li {
			display: inline;
			border: 1px solid var(--color-text-maxcontrast);
			border-radius: var(--border-radius);
			margin-right: 5px;
			cursor: pointer;
			color: var(--color-text-maxcontrast);
			padding: 3px 6px;
		}
		ul.podcastCategory li:hover {
			border: 1px solid white;
			color: white;
		}
	}
}

.empty-content {
	margin-top: 10px !important;

	.empty-content__icon {
		margin-bottom: 0px !important;
	}
}

@media only screen and (max-width: 500px) {
	.podcastHeader {
		flex-direction: column;
		align-items: center;

		.podcastImage {
			margin-right: 0px;
			margin-bottom: 25px;
		}
		.podcastDescription {
			text-align: center;

			.podcastControls {
				justify-content: center;
.episodeContent {
	h2 {
		border-bottom: 1px solid #ddd;
		border-top: 1px solid #ddd;
		padding: 10px 30px;
		z-index: 60;
		position: sticky;
		top: 50px;
		background: white;
	}
	p {
		padding: 10px 30px;
		max-width: 700px;
	}
	.menuToggle {
		float: right;
		color: #1976d2;
		cursor: pointer;
		position: relative;
		right: 20px;
		top: -49px;
		z-index: 60;
	}
}

table.chapterTable {
	width: 100%;
	min-width: 250px;
	table-layout:fixed;
	position: relative;

	tbody {

		td {
			padding: 10px 30px;
			font-style: normal;
			border-bottom: 1px solid var(--color-border);
			cursor: pointer;
		}

		tr {
			height: 30px;
			background-color: var(--color-background-light);
			transition: opacity 500ms ease 0s;

			tr:hover, tr:focus, tr.mouseOver td {
				background-color: var(--color-background-hover);
			}

		}

		tr td * {
			cursor: pointer;
		}

		td.timeColumn {
			width: 120px;
			color: #1976d2;
		}
.podcastButton {
	padding-left: 35px;
	padding-right: 15px;
	background-position: 10px center;
}