diff --git a/CHANGELOG.md b/CHANGELOG.md
index c99cd20..f1b44ee 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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
diff --git a/appinfo/info.xml b/appinfo/info.xml
index 4e80990..07195fa 100644
--- a/appinfo/info.xml
+++ b/appinfo/info.xml
@@ -14,7 +14,7 @@
## Requirements
You need to have [GPodderSync](https://apps.nextcloud.com/apps/gpoddersync) installed to use this app!]]>
- 3.5.3
+ 3.5.4
agpl
Michel Roux
RePod
diff --git a/lib/Core/EpisodeAction/EpisodeActionExtraData.php b/lib/Core/EpisodeAction/EpisodeActionExtraData.php
index 1422176..860c4e9 100644
--- a/lib/Core/EpisodeAction/EpisodeActionExtraData.php
+++ b/lib/Core/EpisodeAction/EpisodeActionExtraData.php
@@ -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,
diff --git a/lib/Core/EpisodeAction/EpisodeActionReader.php b/lib/Core/EpisodeAction/EpisodeActionReader.php
index c21f256..6a13682 100644
--- a/lib/Core/EpisodeAction/EpisodeActionReader.php
+++ b/lib/Core/EpisodeAction/EpisodeActionReader.php
@@ -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,
diff --git a/src/components/Atoms/Modal.vue b/src/components/Atoms/Modal.vue
index 500c844..b4945e1 100644
--- a/src/components/Atoms/Modal.vue
+++ b/src/components/Atoms/Modal.vue
@@ -6,6 +6,8 @@
:size="256"
:url="episode.image" />
{{ episode.name }}
+ {{ episode.author }}
+
diff --git a/src/components/Feed/Episode.vue b/src/components/Feed/Episode.vue
index b0c9f3a..3dbe6c4 100644
--- a/src/components/Feed/Episode.vue
+++ b/src/components/Feed/Episode.vue
@@ -2,6 +2,7 @@
- {{ episode.duration }}
+ {{ !oneLine ? episode.author : '' }}
@@ -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;
+}
diff --git a/src/store/player.ts b/src/store/player.ts
index f4872c6..17b51df 100644
--- a/src/store/player.ts
+++ b/src/store/player.ts
@@ -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
diff --git a/src/utils/types.ts b/src/utils/types.ts
index b16dd49..851dd34 100644
--- a/src/utils/types.ts
+++ b/src/utils/types.ts
@@ -16,6 +16,7 @@ export interface EpisodeInterface {
name: string
link?: string
image?: string
+ author?: string
description?: string
fetchedAtUnix: number
guid: string