feat: ✨ add notifications and author
This commit is contained in:
parent
514a12d756
commit
2a3d30f018
@ -1,3 +1,9 @@
|
||||
## 3.5.4 - Under the spotlight - 2025-01-03
|
||||
|
||||
### Added
|
||||
- 🧑🎤 Added the episode author on the list and modal
|
||||
- ✨ Added cover image and episode infos on desktop and mobile notifications
|
||||
|
||||
## 3.5.3 - Hangover - 2025-01-03
|
||||
|
||||
### Fixed
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
## Requirements
|
||||
You need to have [GPodderSync](https://apps.nextcloud.com/apps/gpoddersync) installed to use this app!]]></description>
|
||||
<version>3.5.3</version>
|
||||
<version>3.5.4</version>
|
||||
<licence>agpl</licence>
|
||||
<author mail="xefir@crystalyx.net" homepage="https://crystalyx.net">Michel Roux</author>
|
||||
<namespace>RePod</namespace>
|
||||
|
@ -18,6 +18,7 @@ use OCA\GPodderSync\Core\EpisodeAction\EpisodeAction;
|
||||
* name: string,
|
||||
* link: ?string,
|
||||
* image: ?string,
|
||||
* author: ?string,
|
||||
* description: ?string,
|
||||
* fetchedAtUnix: int,
|
||||
* guid: string,
|
||||
@ -36,6 +37,7 @@ class EpisodeActionExtraData implements \JsonSerializable, \Stringable
|
||||
private readonly string $name,
|
||||
private readonly ?string $link,
|
||||
private readonly ?string $image,
|
||||
private readonly ?string $author,
|
||||
private readonly ?string $description,
|
||||
private readonly int $fetchedAtUnix,
|
||||
private readonly string $guid,
|
||||
@ -70,6 +72,10 @@ class EpisodeActionExtraData implements \JsonSerializable, \Stringable
|
||||
return $this->image;
|
||||
}
|
||||
|
||||
public function getAuthor(): ?string {
|
||||
return $this->author;
|
||||
}
|
||||
|
||||
public function getDescription(): ?string {
|
||||
return $this->description;
|
||||
}
|
||||
@ -113,6 +119,7 @@ class EpisodeActionExtraData implements \JsonSerializable, \Stringable
|
||||
'name' => $this->name,
|
||||
'link' => $this->link,
|
||||
'image' => $this->image,
|
||||
'author' => $this->author,
|
||||
'description' => $this->description,
|
||||
'fetchedAtUnix' => $this->fetchedAtUnix,
|
||||
'guid' => $this->guid,
|
||||
|
@ -81,6 +81,13 @@ class EpisodeActionReader extends CoreEpisodeActionReader
|
||||
}
|
||||
}
|
||||
|
||||
// Get episode author
|
||||
if (isset($iTunesItemChildren)) {
|
||||
$author = $this->stringOrNull($iTunesItemChildren->author);
|
||||
} else {
|
||||
$author = $this->stringOrNull($item->author);
|
||||
}
|
||||
|
||||
// Get episode description
|
||||
$itemContent = $item->children('content', true);
|
||||
if (isset($itemContent)) {
|
||||
@ -116,6 +123,7 @@ class EpisodeActionReader extends CoreEpisodeActionReader
|
||||
$name,
|
||||
$link,
|
||||
$image,
|
||||
$author,
|
||||
$description,
|
||||
$fetchedAtUnix ?? (new \DateTime())->getTimestamp(),
|
||||
$guid,
|
||||
|
@ -6,6 +6,8 @@
|
||||
:size="256"
|
||||
:url="episode.image" />
|
||||
<h2>{{ episode.name }}</h2>
|
||||
<i v-if="episode.author">{{ episode.author }}</i>
|
||||
<br />
|
||||
<SafeHtml :source="episode.description || ''" />
|
||||
<div class="flex">
|
||||
<NcButton v-if="episode.link" :href="episode.link" target="_blank">
|
||||
|
@ -2,6 +2,7 @@
|
||||
<NcListItem
|
||||
:active="isCurrentEpisode(episode)"
|
||||
class="episode"
|
||||
:counter-number="episode.duration"
|
||||
:details="
|
||||
!oneLine && episode.pubDate
|
||||
? formatLocaleDate(new Date(episode.pubDate?.date))
|
||||
@ -92,7 +93,7 @@
|
||||
:value="(episode.action.position * 100) / episode.action.total" />
|
||||
</template>
|
||||
<template #subname>
|
||||
{{ episode.duration }}
|
||||
{{ !oneLine ? episode.author : '' }}
|
||||
</template>
|
||||
</NcListItem>
|
||||
</template>
|
||||
@ -218,4 +219,13 @@ export default {
|
||||
flex-basis: auto;
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
.episode .list-item-details__extra {
|
||||
flex-direction: row-reverse;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.episode .list-item-details__counter {
|
||||
max-width: fit-content;
|
||||
}
|
||||
</style>
|
||||
|
@ -48,6 +48,34 @@ export const usePlayer = defineStore('player', {
|
||||
conflict() {
|
||||
this.playCount = 0
|
||||
},
|
||||
metadatas(episode: EpisodeInterface) {
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Media_Session_API
|
||||
navigator.mediaSession.metadata = new MediaMetadata({
|
||||
title: episode.name,
|
||||
artist: episode.author,
|
||||
album: episode.title,
|
||||
artwork: episode.image ? [{ src: episode.image }] : [],
|
||||
})
|
||||
|
||||
navigator.mediaSession.setActionHandler('play', this.play)
|
||||
navigator.mediaSession.setActionHandler('pause', this.pause)
|
||||
navigator.mediaSession.setActionHandler('stop', this.stop)
|
||||
navigator.mediaSession.setActionHandler(
|
||||
'seekbackward',
|
||||
(details: MediaSessionActionDetails) =>
|
||||
this.seek(audio.currentTime - (details.seekOffset || 10)),
|
||||
)
|
||||
navigator.mediaSession.setActionHandler(
|
||||
'seekforward',
|
||||
(details: MediaSessionActionDetails) =>
|
||||
this.seek(audio.currentTime + (details.seekOffset || 30)),
|
||||
)
|
||||
navigator.mediaSession.setActionHandler(
|
||||
'seekto',
|
||||
(details: MediaSessionActionDetails) =>
|
||||
!details.fastSeek && this.seek(details.seekTime || 0),
|
||||
)
|
||||
},
|
||||
async load(episode: EpisodeInterface | null, podcastUrl?: string) {
|
||||
this.episode = episode
|
||||
this.podcastUrl = podcastUrl || null
|
||||
@ -75,6 +103,7 @@ export const usePlayer = defineStore('player', {
|
||||
}
|
||||
|
||||
audio.play()
|
||||
this.metadatas(this.episode)
|
||||
} else {
|
||||
this.loaded = false
|
||||
this.podcastUrl = null
|
||||
|
@ -16,6 +16,7 @@ export interface EpisodeInterface {
|
||||
name: string
|
||||
link?: string
|
||||
image?: string
|
||||
author?: string
|
||||
description?: string
|
||||
fetchedAtUnix: number
|
||||
guid: string
|
||||
|
Loading…
Reference in New Issue
Block a user