feat: add export opml
This commit is contained in:
parent
2ed16a316e
commit
c28abc7564
@ -15,6 +15,7 @@ return [
|
||||
['name' => 'page#index', 'url' => '/', 'verb' => 'GET'],
|
||||
['name' => 'episodes#action', 'url' => '/episodes/action', 'verb' => 'GET'],
|
||||
['name' => 'episodes#list', 'url' => '/episodes/list', 'verb' => 'GET'],
|
||||
['name' => 'opml#export', 'url' => '/opml/export', 'verb' => 'GET'],
|
||||
['name' => 'podcast#index', 'url' => '/podcast', 'verb' => 'GET'],
|
||||
['name' => 'search#index', 'url' => '/search', 'verb' => 'GET'],
|
||||
['name' => 'tops#hot', 'url' => '/tops/hot', 'verb' => 'GET'],
|
||||
|
75
lib/Controller/OpmlController.php
Normal file
75
lib/Controller/OpmlController.php
Normal file
@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OCA\RePod\Controller;
|
||||
|
||||
use OCA\GPodderSync\Core\PodcastData\PodcastDataReader;
|
||||
use OCA\GPodderSync\Core\PodcastData\PodcastMetricsReader;
|
||||
use OCA\RePod\AppInfo\Application;
|
||||
use OCA\RePod\Service\UserService;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http\DataDownloadResponse;
|
||||
use OCP\IL10N;
|
||||
use OCP\IRequest;
|
||||
|
||||
class OpmlController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
IRequest $request,
|
||||
private IL10N $l10n,
|
||||
private PodcastDataReader $podcastDataReader,
|
||||
private PodcastMetricsReader $podcastMetricsReader,
|
||||
private UserService $userService
|
||||
) {
|
||||
parent::__construct(Application::APP_ID, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
*/
|
||||
public function export(): DataDownloadResponse {
|
||||
// https://github.com/AntennaPod/AntennaPod/blob/master/core/src/main/java/de/danoeh/antennapod/core/export/opml/OpmlWriter.java
|
||||
$xml = new \SimpleXMLElement('<opml/>', namespaceOrPrefix: 'http://xmlpull.org/v1/doc/features.html#indent-output');
|
||||
$xml->addAttribute('version', '2.0');
|
||||
|
||||
$dateCreated = new \DateTime();
|
||||
$head = $xml->addChild('head');
|
||||
|
||||
if (isset($head)) {
|
||||
$head->addChild('title', $this->l10n->t('RePod Subscriptions'));
|
||||
$head->addChild('dateCreated', $dateCreated->format(\DateTime::RFC822));
|
||||
}
|
||||
|
||||
$body = $xml->addChild('body');
|
||||
|
||||
if (isset($body)) {
|
||||
$subscriptions = $this->podcastMetricsReader->metrics($this->userService->getUserUID());
|
||||
|
||||
foreach ($subscriptions as $subscription) {
|
||||
$podcast = $this->podcastDataReader->getCachedOrFetchPodcastData($subscription->getUrl(), $this->userService->getUserUID());
|
||||
|
||||
if ($podcast) {
|
||||
$outline = $body->addChild('outline');
|
||||
|
||||
if (isset($outline)) {
|
||||
$title = $podcast->getTitle();
|
||||
$link = $podcast->getLink();
|
||||
|
||||
if ($title) {
|
||||
$outline->addAttribute('text', $title);
|
||||
$outline->addAttribute('title', $title);
|
||||
}
|
||||
|
||||
if ($link) {
|
||||
$outline->addAttribute('xmlUrl', $link);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new DataDownloadResponse((string) $xml->asXML(), 'repod-'.$dateCreated->getTimestamp().'.opml', ' application/xml');
|
||||
}
|
||||
}
|
@ -1,33 +1,46 @@
|
||||
<template>
|
||||
<NcAppNavigationSettings>
|
||||
<div class="setting">
|
||||
<label>
|
||||
<NcAppNavigationItem :name="t('repod', 'Playback speed')">
|
||||
<template #icon>
|
||||
<SpeedometerSlow v-if="player.rate < 1" :size="20" />
|
||||
<SpeedometerMedium v-if="player.rate === 1" :size="20" />
|
||||
<Speedometer v-if="player.rate > 1" :size="20" />
|
||||
{{ t('repod', 'Playback speed') }}
|
||||
</label>
|
||||
<div>
|
||||
<Minus class="pointer" :size="20" @click="changeRate(-.5)" />
|
||||
<NcCounterBubble>x{{ player.rate }}</NcCounterBubble>
|
||||
<Plus class="pointer" :size="20" @click="changeRate(.5)" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #extra>
|
||||
<div class="extra">
|
||||
<Minus class="pointer" :size="20" @click="changeRate(-.5)" />
|
||||
<NcCounterBubble class="counter">
|
||||
x{{ player.rate }}
|
||||
</NcCounterBubble>
|
||||
<Plus class="pointer" :size="20" @click="changeRate(.5)" />
|
||||
</div>
|
||||
</template>
|
||||
</NcAppNavigationItem>
|
||||
<NcAppNavigationItem :href="generateUrl('/apps/repod/opml/export')"
|
||||
:name="t('repod', 'Export subscriptions')">
|
||||
<template #icon>
|
||||
<Export :size="20" />
|
||||
</template>
|
||||
</NcAppNavigationItem>
|
||||
</NcAppNavigationSettings>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { NcAppNavigationSettings, NcCounterBubble } from '@nextcloud/vue'
|
||||
import { NcAppNavigationItem, NcAppNavigationSettings, NcCounterBubble } from '@nextcloud/vue'
|
||||
import Export from 'vue-material-design-icons/Export.vue'
|
||||
import Minus from 'vue-material-design-icons/Minus.vue'
|
||||
import Plus from 'vue-material-design-icons/Plus.vue'
|
||||
import Speedometer from 'vue-material-design-icons/Speedometer.vue'
|
||||
import SpeedometerMedium from 'vue-material-design-icons/SpeedometerMedium.vue'
|
||||
import SpeedometerSlow from 'vue-material-design-icons/SpeedometerSlow.vue'
|
||||
import { generateUrl } from '@nextcloud/router'
|
||||
|
||||
export default {
|
||||
name: 'Settings',
|
||||
components: {
|
||||
Export,
|
||||
Minus,
|
||||
NcAppNavigationItem,
|
||||
NcAppNavigationSettings,
|
||||
NcCounterBubble,
|
||||
Plus,
|
||||
@ -41,6 +54,7 @@ export default {
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
generateUrl,
|
||||
changeRate(diff) {
|
||||
if (this.player.rate + diff > 0) {
|
||||
this.$store.dispatch('player/rate', this.player.rate + diff)
|
||||
@ -51,18 +65,17 @@ export default {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.pointer {
|
||||
cursor: pointer;
|
||||
.counter {
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.setting {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.setting > label,
|
||||
.setting > div {
|
||||
.extra {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
gap: .5rem;
|
||||
}
|
||||
|
||||
.pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
Loading…
Reference in New Issue
Block a user