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
|
## 3.5.3 - Hangover - 2025-01-03
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
You need to have [GPodderSync](https://apps.nextcloud.com/apps/gpoddersync) installed to use this app!]]></description>
|
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>
|
<licence>agpl</licence>
|
||||||
<author mail="xefir@crystalyx.net" homepage="https://crystalyx.net">Michel Roux</author>
|
<author mail="xefir@crystalyx.net" homepage="https://crystalyx.net">Michel Roux</author>
|
||||||
<namespace>RePod</namespace>
|
<namespace>RePod</namespace>
|
||||||
|
@ -18,6 +18,7 @@ use OCA\GPodderSync\Core\EpisodeAction\EpisodeAction;
|
|||||||
* name: string,
|
* name: string,
|
||||||
* link: ?string,
|
* link: ?string,
|
||||||
* image: ?string,
|
* image: ?string,
|
||||||
|
* author: ?string,
|
||||||
* description: ?string,
|
* description: ?string,
|
||||||
* fetchedAtUnix: int,
|
* fetchedAtUnix: int,
|
||||||
* guid: string,
|
* guid: string,
|
||||||
@ -36,6 +37,7 @@ class EpisodeActionExtraData implements \JsonSerializable, \Stringable
|
|||||||
private readonly string $name,
|
private readonly string $name,
|
||||||
private readonly ?string $link,
|
private readonly ?string $link,
|
||||||
private readonly ?string $image,
|
private readonly ?string $image,
|
||||||
|
private readonly ?string $author,
|
||||||
private readonly ?string $description,
|
private readonly ?string $description,
|
||||||
private readonly int $fetchedAtUnix,
|
private readonly int $fetchedAtUnix,
|
||||||
private readonly string $guid,
|
private readonly string $guid,
|
||||||
@ -70,6 +72,10 @@ class EpisodeActionExtraData implements \JsonSerializable, \Stringable
|
|||||||
return $this->image;
|
return $this->image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getAuthor(): ?string {
|
||||||
|
return $this->author;
|
||||||
|
}
|
||||||
|
|
||||||
public function getDescription(): ?string {
|
public function getDescription(): ?string {
|
||||||
return $this->description;
|
return $this->description;
|
||||||
}
|
}
|
||||||
@ -113,6 +119,7 @@ class EpisodeActionExtraData implements \JsonSerializable, \Stringable
|
|||||||
'name' => $this->name,
|
'name' => $this->name,
|
||||||
'link' => $this->link,
|
'link' => $this->link,
|
||||||
'image' => $this->image,
|
'image' => $this->image,
|
||||||
|
'author' => $this->author,
|
||||||
'description' => $this->description,
|
'description' => $this->description,
|
||||||
'fetchedAtUnix' => $this->fetchedAtUnix,
|
'fetchedAtUnix' => $this->fetchedAtUnix,
|
||||||
'guid' => $this->guid,
|
'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
|
// Get episode description
|
||||||
$itemContent = $item->children('content', true);
|
$itemContent = $item->children('content', true);
|
||||||
if (isset($itemContent)) {
|
if (isset($itemContent)) {
|
||||||
@ -116,6 +123,7 @@ class EpisodeActionReader extends CoreEpisodeActionReader
|
|||||||
$name,
|
$name,
|
||||||
$link,
|
$link,
|
||||||
$image,
|
$image,
|
||||||
|
$author,
|
||||||
$description,
|
$description,
|
||||||
$fetchedAtUnix ?? (new \DateTime())->getTimestamp(),
|
$fetchedAtUnix ?? (new \DateTime())->getTimestamp(),
|
||||||
$guid,
|
$guid,
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
:size="256"
|
:size="256"
|
||||||
:url="episode.image" />
|
:url="episode.image" />
|
||||||
<h2>{{ episode.name }}</h2>
|
<h2>{{ episode.name }}</h2>
|
||||||
|
<i v-if="episode.author">{{ episode.author }}</i>
|
||||||
|
<br />
|
||||||
<SafeHtml :source="episode.description || ''" />
|
<SafeHtml :source="episode.description || ''" />
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<NcButton v-if="episode.link" :href="episode.link" target="_blank">
|
<NcButton v-if="episode.link" :href="episode.link" target="_blank">
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
<NcListItem
|
<NcListItem
|
||||||
:active="isCurrentEpisode(episode)"
|
:active="isCurrentEpisode(episode)"
|
||||||
class="episode"
|
class="episode"
|
||||||
|
:counter-number="episode.duration"
|
||||||
:details="
|
:details="
|
||||||
!oneLine && episode.pubDate
|
!oneLine && episode.pubDate
|
||||||
? formatLocaleDate(new Date(episode.pubDate?.date))
|
? formatLocaleDate(new Date(episode.pubDate?.date))
|
||||||
@ -92,7 +93,7 @@
|
|||||||
:value="(episode.action.position * 100) / episode.action.total" />
|
:value="(episode.action.position * 100) / episode.action.total" />
|
||||||
</template>
|
</template>
|
||||||
<template #subname>
|
<template #subname>
|
||||||
{{ episode.duration }}
|
{{ !oneLine ? episode.author : '' }}
|
||||||
</template>
|
</template>
|
||||||
</NcListItem>
|
</NcListItem>
|
||||||
</template>
|
</template>
|
||||||
@ -218,4 +219,13 @@ export default {
|
|||||||
flex-basis: auto;
|
flex-basis: auto;
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.episode .list-item-details__extra {
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.episode .list-item-details__counter {
|
||||||
|
max-width: fit-content;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -48,6 +48,34 @@ export const usePlayer = defineStore('player', {
|
|||||||
conflict() {
|
conflict() {
|
||||||
this.playCount = 0
|
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) {
|
async load(episode: EpisodeInterface | null, podcastUrl?: string) {
|
||||||
this.episode = episode
|
this.episode = episode
|
||||||
this.podcastUrl = podcastUrl || null
|
this.podcastUrl = podcastUrl || null
|
||||||
@ -75,6 +103,7 @@ export const usePlayer = defineStore('player', {
|
|||||||
}
|
}
|
||||||
|
|
||||||
audio.play()
|
audio.play()
|
||||||
|
this.metadatas(this.episode)
|
||||||
} else {
|
} else {
|
||||||
this.loaded = false
|
this.loaded = false
|
||||||
this.podcastUrl = null
|
this.podcastUrl = null
|
||||||
|
@ -16,6 +16,7 @@ export interface EpisodeInterface {
|
|||||||
name: string
|
name: string
|
||||||
link?: string
|
link?: string
|
||||||
image?: string
|
image?: string
|
||||||
|
author?: string
|
||||||
description?: string
|
description?: string
|
||||||
fetchedAtUnix: number
|
fetchedAtUnix: number
|
||||||
guid: string
|
guid: string
|
||||||
|
Loading…
Reference in New Issue
Block a user