refactor: 🎨 add prettier and update deps
This commit is contained in:
parent
cbc9654af8
commit
b0a0414fd4
@ -1,9 +1,11 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
extends: [
|
extends: [
|
||||||
'@nextcloud',
|
'@nextcloud',
|
||||||
|
'plugin:prettier/recommended',
|
||||||
],
|
],
|
||||||
rules: {
|
rules: {
|
||||||
'sort-imports': 'error',
|
'sort-imports': 'error',
|
||||||
'vue/attributes-order': ['error', { alphabetical: true }],
|
'vue/attributes-order': ['error', { alphabetical: true }],
|
||||||
|
'vue/first-attribute-linebreak': 'off',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
12
composer.lock
generated
12
composer.lock
generated
@ -94,16 +94,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "php-cs-fixer/shim",
|
"name": "php-cs-fixer/shim",
|
||||||
"version": "v3.51.0",
|
"version": "v3.54.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/PHP-CS-Fixer/shim.git",
|
"url": "https://github.com/PHP-CS-Fixer/shim.git",
|
||||||
"reference": "a792394f7f3934f75a4df9dca544796c6f503027"
|
"reference": "887c350fccbadb2b84278fdb963c25a0c304ac9c"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/PHP-CS-Fixer/shim/zipball/a792394f7f3934f75a4df9dca544796c6f503027",
|
"url": "https://api.github.com/repos/PHP-CS-Fixer/shim/zipball/887c350fccbadb2b84278fdb963c25a0c304ac9c",
|
||||||
"reference": "a792394f7f3934f75a4df9dca544796c6f503027",
|
"reference": "887c350fccbadb2b84278fdb963c25a0c304ac9c",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -140,9 +140,9 @@
|
|||||||
"description": "A tool to automatically fix PHP code style",
|
"description": "A tool to automatically fix PHP code style",
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/PHP-CS-Fixer/shim/issues",
|
"issues": "https://github.com/PHP-CS-Fixer/shim/issues",
|
||||||
"source": "https://github.com/PHP-CS-Fixer/shim/tree/v3.51.0"
|
"source": "https://github.com/PHP-CS-Fixer/shim/tree/v3.54.0"
|
||||||
},
|
},
|
||||||
"time": "2024-02-28T19:51:07+00:00"
|
"time": "2024-04-17T08:23:10+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "psalm/phar",
|
"name": "psalm/phar",
|
||||||
|
7326
package-lock.json
generated
7326
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
20
package.json
20
package.json
@ -19,11 +19,11 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nextcloud/axios": "^2.4.0",
|
"@nextcloud/axios": "^2.4.0",
|
||||||
"@nextcloud/dialogs": "^5.2.0",
|
"@nextcloud/dialogs": "^5.3.1",
|
||||||
"@nextcloud/initial-state": "^2.1.0",
|
"@nextcloud/initial-state": "^2.2.0",
|
||||||
"@nextcloud/l10n": "^2.2.0",
|
"@nextcloud/l10n": "^2.2.0",
|
||||||
"@nextcloud/router": "^3.0.0",
|
"@nextcloud/router": "^3.0.1",
|
||||||
"@nextcloud/vue": "^8.11.0",
|
"@nextcloud/vue": "^8.11.2",
|
||||||
"vue": "^2",
|
"vue": "^2",
|
||||||
"vue-material-design-icons": "^5.3.0",
|
"vue-material-design-icons": "^5.3.0",
|
||||||
"vue-router": "^3",
|
"vue-router": "^3",
|
||||||
@ -36,11 +36,15 @@
|
|||||||
"node": "^20.0.0",
|
"node": "^20.0.0",
|
||||||
"npm": "^9.0.0"
|
"npm": "^9.0.0"
|
||||||
},
|
},
|
||||||
|
"prettier": "@nextcloud/prettier-config",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nextcloud/babel-config": "^1.0.0",
|
"@nextcloud/babel-config": "^1.1.1",
|
||||||
"@nextcloud/browserslist-config": "^3.0.0",
|
"@nextcloud/browserslist-config": "^3.0.1",
|
||||||
"@nextcloud/eslint-config": "^8.3.0",
|
"@nextcloud/eslint-config": "^8.3.0",
|
||||||
"@nextcloud/stylelint-config": "^2.4.0",
|
"@nextcloud/prettier-config": "^1.0.0",
|
||||||
"@nextcloud/webpack-vue-config": "^6.0.1"
|
"@nextcloud/stylelint-config": "^3.0.0",
|
||||||
|
"@nextcloud/webpack-vue-config": "^6.0.1",
|
||||||
|
"eslint-config-prettier": "^9.1.0",
|
||||||
|
"eslint-plugin-prettier": "^5.1.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.padding {
|
.padding {
|
||||||
padding-bottom: 6rem;
|
padding-bottom: 6rem;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -27,7 +27,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.padding {
|
.padding {
|
||||||
padding-bottom: 6rem;
|
padding-bottom: 6rem;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -14,7 +14,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.loading {
|
.loading {
|
||||||
margin: 2rem 0;
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,24 +1,17 @@
|
|||||||
<!-- eslint-disable vue/no-v-html -->
|
<!-- eslint-disable vue/no-v-html -->
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<NcAvatar :display-name="name"
|
<NcAvatar :display-name="name" :is-no-user="true" :size="256" :url="image" />
|
||||||
:is-no-user="true"
|
|
||||||
:size="256"
|
|
||||||
:url="image" />
|
|
||||||
<h2>{{ name }}</h2>
|
<h2>{{ name }}</h2>
|
||||||
<p v-html="strippedDescription" />
|
<p v-html="strippedDescription" />
|
||||||
<div>
|
<div>
|
||||||
<NcButton v-if="link"
|
<NcButton v-if="link" :href="link" target="_blank">
|
||||||
:href="link"
|
|
||||||
target="_blank">
|
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<OpenInNewIcon :size="20" />
|
<OpenInNewIcon :size="20" />
|
||||||
</template>
|
</template>
|
||||||
{{ title }}
|
{{ title }}
|
||||||
</NcButton>
|
</NcButton>
|
||||||
<NcButton v-if="url"
|
<NcButton v-if="url" :href="url" target="_blank">
|
||||||
:href="url"
|
|
||||||
target="_blank">
|
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<DownloadIcon :size="20" />
|
<DownloadIcon :size="20" />
|
||||||
</template>
|
</template>
|
||||||
@ -85,11 +78,11 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
div {
|
div {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
margin: 2rem;
|
margin: 2rem;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<NcAppNavigationList>
|
<NcAppNavigationList>
|
||||||
<NcAppNavigationNewItem :name="t('repod', 'Add a RSS link')" @new-item="addSubscription">
|
<NcAppNavigationNewItem
|
||||||
|
:name="t('repod', 'Add a RSS link')"
|
||||||
|
@new-item="addSubscription">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<PlusIcon :size="20" />
|
<PlusIcon :size="20" />
|
||||||
</template>
|
</template>
|
||||||
@ -29,7 +31,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
ul {
|
ul {
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -2,13 +2,15 @@
|
|||||||
<div>
|
<div>
|
||||||
<Loading v-if="loading" />
|
<Loading v-if="loading" />
|
||||||
<ul v-if="!loading">
|
<ul v-if="!loading">
|
||||||
<NcListItem v-for="feed in feeds"
|
<NcListItem
|
||||||
|
v-for="feed in feeds"
|
||||||
:key="feed.link"
|
:key="feed.link"
|
||||||
:details="formatLocaleDate(new Date(feed.fetchedAtUnix*1000))"
|
:details="formatLocaleDate(new Date(feed.fetchedAtUnix * 1000))"
|
||||||
:name="feed.title"
|
:name="feed.title"
|
||||||
:to="toUrl(feed.link)">
|
:to="toUrl(feed.link)">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<NcAvatar :display-name="feed.author"
|
<NcAvatar
|
||||||
|
:display-name="feed.author"
|
||||||
:is-no-user="true"
|
:is-no-user="true"
|
||||||
:url="feed.imageUrl" />
|
:url="feed.imageUrl" />
|
||||||
</template>
|
</template>
|
||||||
@ -61,9 +63,13 @@ export default {
|
|||||||
try {
|
try {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
const currentSearch = this.value
|
const currentSearch = this.value
|
||||||
const feeds = await axios.get(generateUrl('/apps/repod/search?q={value}', { value: currentSearch }))
|
const feeds = await axios.get(
|
||||||
|
generateUrl('/apps/repod/search?q={value}', { value: currentSearch }),
|
||||||
|
)
|
||||||
if (currentSearch === this.value) {
|
if (currentSearch === this.value) {
|
||||||
this.feeds = [...feeds.data].sort((a, b) => b.fetchedAtUnix - a.fetchedAtUnix)
|
this.feeds = [...feeds.data].sort(
|
||||||
|
(a, b) => b.fetchedAtUnix - a.fetchedAtUnix,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<ul v-if="!loading">
|
<ul v-if="!loading">
|
||||||
<li v-for="top in tops" :key="top.link">
|
<li v-for="top in tops" :key="top.link">
|
||||||
<router-link :to="toUrl(top.link)">
|
<router-link :to="toUrl(top.link)">
|
||||||
<img :src="top.imageUrl" :title="top.author">
|
<img :src="top.imageUrl" :title="top.author" />
|
||||||
</router-link>
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -67,24 +67,24 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
h2 {
|
h2 {
|
||||||
margin: 1rem 0;
|
margin: 1rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
li {
|
li {
|
||||||
flex-basis: 10rem;
|
flex-basis: 10rem;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 2rem;
|
gap: 2rem;
|
||||||
overflow: scroll hidden;
|
overflow: scroll hidden;
|
||||||
padding-bottom: .5rem;
|
padding-bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
<!-- eslint-disable vue/no-v-html -->
|
<!-- eslint-disable vue/no-v-html -->
|
||||||
<template>
|
<template>
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<img class="background" :src="imageUrl">
|
<img class="background" :src="imageUrl" />
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div>
|
<div>
|
||||||
<NcAvatar :display-name="author || title"
|
<NcAvatar
|
||||||
|
:display-name="author || title"
|
||||||
:is-no-user="true"
|
:is-no-user="true"
|
||||||
:size="128"
|
:size="128"
|
||||||
:url="imageUrl" />
|
:url="imageUrl" />
|
||||||
@ -19,12 +20,13 @@
|
|||||||
<a :href="link" target="_blank">
|
<a :href="link" target="_blank">
|
||||||
<i>{{ author }}</i>
|
<i>{{ author }}</i>
|
||||||
</a>
|
</a>
|
||||||
<br><br>
|
<br /><br />
|
||||||
<p>
|
<p>
|
||||||
<small v-html="strippedDescription" />
|
<small v-html="strippedDescription" />
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<NcAppNavigationNew v-if="!isSubscribed"
|
<NcAppNavigationNew
|
||||||
|
v-if="!isSubscribed"
|
||||||
:text="t('repod', 'Subscribe')"
|
:text="t('repod', 'Subscribe')"
|
||||||
@click="addSubscription">
|
@click="addSubscription">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
@ -90,7 +92,10 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
async addSubscription() {
|
async addSubscription() {
|
||||||
try {
|
try {
|
||||||
await axios.post(generateUrl('/apps/gpoddersync/subscription_change/create'), { add: [this.url], remove: [] })
|
await axios.post(generateUrl('/apps/gpoddersync/subscription_change/create'), {
|
||||||
|
add: [this.url],
|
||||||
|
remove: [],
|
||||||
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
showError(t('repod', 'Error while adding the feed'))
|
showError(t('repod', 'Error while adding the feed'))
|
||||||
@ -100,55 +105,55 @@ export default {
|
|||||||
},
|
},
|
||||||
copyFeed() {
|
copyFeed() {
|
||||||
window.navigator.clipboard.writeText(this.url)
|
window.navigator.clipboard.writeText(this.url)
|
||||||
showSuccess(t('repod', 'Feed\'s link copied to the clipboard'))
|
showSuccess(t('repod', "Feed's link copied to the clipboard"))
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.background {
|
.background {
|
||||||
filter: blur(1rem) brightness(50%);
|
filter: blur(1rem) brightness(50%);
|
||||||
height: auto;
|
height: auto;
|
||||||
left: 0;
|
left: 0;
|
||||||
opacity: .4;
|
opacity: 0.4;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
height: 10rem;
|
height: 10rem;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.feed {
|
.feed {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: .2rem;
|
gap: 0.2rem;
|
||||||
margin: .5rem;
|
margin: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
height: 14rem;
|
height: 14rem;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding: 2rem;
|
padding: 2rem;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.infos {
|
.infos {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.inner {
|
.inner {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 768px) {
|
@media only screen and (max-width: 768px) {
|
||||||
.inner {
|
.inner {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -2,17 +2,19 @@
|
|||||||
<div>
|
<div>
|
||||||
<Loading v-if="loading" />
|
<Loading v-if="loading" />
|
||||||
<ul v-if="!loading">
|
<ul v-if="!loading">
|
||||||
<NcListItem v-for="episode in filteredEpisodes"
|
<NcListItem
|
||||||
|
v-for="episode in filteredEpisodes"
|
||||||
:key="episode.guid"
|
:key="episode.guid"
|
||||||
:active="isCurrentEpisode(episode)"
|
:active="isCurrentEpisode(episode)"
|
||||||
:class="hasEnded(episode) ? 'ended': ''"
|
:class="hasEnded(episode) ? 'ended' : ''"
|
||||||
:details="formatLocaleDate(new Date(episode.pubDate?.date))"
|
:details="formatLocaleDate(new Date(episode.pubDate?.date))"
|
||||||
:force-display-actions="true"
|
:force-display-actions="true"
|
||||||
:name="episode.name"
|
:name="episode.name"
|
||||||
:title="episode.description"
|
:title="episode.description"
|
||||||
@click="modalEpisode = episode">
|
@click="modalEpisode = episode">
|
||||||
<template #actions>
|
<template #actions>
|
||||||
<NcActionButton v-if="!isCurrentEpisode(episode)"
|
<NcActionButton
|
||||||
|
v-if="!isCurrentEpisode(episode)"
|
||||||
:aria-label="t('repod', 'Play')"
|
:aria-label="t('repod', 'Play')"
|
||||||
:name="t('repod', 'Play')"
|
:name="t('repod', 'Play')"
|
||||||
:title="t('repod', 'Play')"
|
:title="t('repod', 'Play')"
|
||||||
@ -21,7 +23,8 @@
|
|||||||
<PlayIcon :size="20" />
|
<PlayIcon :size="20" />
|
||||||
</template>
|
</template>
|
||||||
</NcActionButton>
|
</NcActionButton>
|
||||||
<NcActionButton v-if="isCurrentEpisode(episode)"
|
<NcActionButton
|
||||||
|
v-if="isCurrentEpisode(episode)"
|
||||||
:aria-label="t('repod', 'Stop')"
|
:aria-label="t('repod', 'Stop')"
|
||||||
:name="t('repod', 'Stop')"
|
:name="t('repod', 'Stop')"
|
||||||
:title="t('repod', 'Stop')"
|
:title="t('repod', 'Stop')"
|
||||||
@ -33,7 +36,8 @@
|
|||||||
</template>
|
</template>
|
||||||
<template #extra>
|
<template #extra>
|
||||||
<NcActions>
|
<NcActions>
|
||||||
<NcActionButton v-if="episode.duration && !hasEnded(episode)"
|
<NcActionButton
|
||||||
|
v-if="episode.duration && !hasEnded(episode)"
|
||||||
:aria-label="t('repod', 'Mark as read')"
|
:aria-label="t('repod', 'Mark as read')"
|
||||||
:disabled="loadingAction"
|
:disabled="loadingAction"
|
||||||
:name="t('repod', 'Mark as read')"
|
:name="t('repod', 'Mark as read')"
|
||||||
@ -43,7 +47,8 @@
|
|||||||
<PlaylistPlayIcon :size="20" />
|
<PlaylistPlayIcon :size="20" />
|
||||||
</template>
|
</template>
|
||||||
</NcActionButton>
|
</NcActionButton>
|
||||||
<NcActionButton v-if="episode.duration && hasEnded(episode)"
|
<NcActionButton
|
||||||
|
v-if="episode.duration && hasEnded(episode)"
|
||||||
:aria-label="t('repod', 'Mark as unread')"
|
:aria-label="t('repod', 'Mark as unread')"
|
||||||
:disabled="loadingAction"
|
:disabled="loadingAction"
|
||||||
:name="t('repod', 'Mark as unread')"
|
:name="t('repod', 'Mark as unread')"
|
||||||
@ -53,7 +58,8 @@
|
|||||||
<PlaylistRemoveIcon :size="20" />
|
<PlaylistRemoveIcon :size="20" />
|
||||||
</template>
|
</template>
|
||||||
</NcActionButton>
|
</NcActionButton>
|
||||||
<NcActionLink v-if="episode.link"
|
<NcActionLink
|
||||||
|
v-if="episode.link"
|
||||||
:href="episode.link"
|
:href="episode.link"
|
||||||
:name="t('repod', 'Open website')"
|
:name="t('repod', 'Open website')"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
@ -62,7 +68,8 @@
|
|||||||
<OpenInNewIcon :size="20" />
|
<OpenInNewIcon :size="20" />
|
||||||
</template>
|
</template>
|
||||||
</NcActionLink>
|
</NcActionLink>
|
||||||
<NcActionLink v-if="episode.url"
|
<NcActionLink
|
||||||
|
v-if="episode.url"
|
||||||
:href="episode.url"
|
:href="episode.url"
|
||||||
:name="t('repod', 'Download')"
|
:name="t('repod', 'Download')"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
@ -74,14 +81,16 @@
|
|||||||
</NcActions>
|
</NcActions>
|
||||||
</template>
|
</template>
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<NcAvatar :display-name="episode.name"
|
<NcAvatar
|
||||||
|
:display-name="episode.name"
|
||||||
:is-no-user="true"
|
:is-no-user="true"
|
||||||
:url="episode.image" />
|
:url="episode.image" />
|
||||||
</template>
|
</template>
|
||||||
<template #indicator>
|
<template #indicator>
|
||||||
<NcProgressBar v-if="isListening(episode)"
|
<NcProgressBar
|
||||||
|
v-if="isListening(episode)"
|
||||||
class="progress"
|
class="progress"
|
||||||
:value="episode.action.position * 100 / episode.action.total" />
|
:value="(episode.action.position * 100) / episode.action.total" />
|
||||||
</template>
|
</template>
|
||||||
<template #subname>
|
<template #subname>
|
||||||
{{ episode.duration }}
|
{{ episode.duration }}
|
||||||
@ -89,7 +98,8 @@
|
|||||||
</NcListItem>
|
</NcListItem>
|
||||||
</ul>
|
</ul>
|
||||||
<NcModal v-if="modalEpisode" @close="modalEpisode = null">
|
<NcModal v-if="modalEpisode" @close="modalEpisode = null">
|
||||||
<Modal :description="modalEpisode.description"
|
<Modal
|
||||||
|
:description="modalEpisode.description"
|
||||||
:image="modalEpisode.image"
|
:image="modalEpisode.image"
|
||||||
:link="modalEpisode.link"
|
:link="modalEpisode.link"
|
||||||
:name="modalEpisode.name"
|
:name="modalEpisode.name"
|
||||||
@ -101,8 +111,20 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { NcActionButton, NcActionLink, NcActions, NcAvatar, NcListItem, NcModal, NcProgressBar } from '@nextcloud/vue'
|
import {
|
||||||
import { durationToSeconds, formatEpisodeTimestamp, formatLocaleDate } from '../../utils/time.js'
|
NcActionButton,
|
||||||
|
NcActionLink,
|
||||||
|
NcActions,
|
||||||
|
NcAvatar,
|
||||||
|
NcListItem,
|
||||||
|
NcModal,
|
||||||
|
NcProgressBar,
|
||||||
|
} from '@nextcloud/vue'
|
||||||
|
import {
|
||||||
|
durationToSeconds,
|
||||||
|
formatEpisodeTimestamp,
|
||||||
|
formatLocaleDate,
|
||||||
|
} from '../../utils/time.js'
|
||||||
import DownloadIcon from 'vue-material-design-icons/Download.vue'
|
import DownloadIcon from 'vue-material-design-icons/Download.vue'
|
||||||
import { EventBus } from '../../store/bus.js'
|
import { EventBus } from '../../store/bus.js'
|
||||||
import Loading from '../Atoms/Loading.vue'
|
import Loading from '../Atoms/Loading.vue'
|
||||||
@ -175,8 +197,12 @@ export default {
|
|||||||
async mounted() {
|
async mounted() {
|
||||||
try {
|
try {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
const episodes = await axios.get(generateUrl('/apps/repod/episodes/list?url={url}', { url: this.url }))
|
const episodes = await axios.get(
|
||||||
this.episodes = [...episodes.data].sort((a, b) => new Date(b.pubDate?.date) - new Date(a.pubDate?.date))
|
generateUrl('/apps/repod/episodes/list?url={url}', { url: this.url }),
|
||||||
|
)
|
||||||
|
this.episodes = [...episodes.data].sort(
|
||||||
|
(a, b) => new Date(b.pubDate?.date) - new Date(a.pubDate?.date),
|
||||||
|
)
|
||||||
EventBus.$on('updateEpisodesList', this.updateList)
|
EventBus.$on('updateEpisodesList', this.updateList)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
@ -191,18 +217,22 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
formatLocaleDate,
|
formatLocaleDate,
|
||||||
hasEnded(episode) {
|
hasEnded(episode) {
|
||||||
return episode.action
|
return (
|
||||||
&& episode.action.position > 0
|
episode.action &&
|
||||||
&& episode.action.total > 0
|
episode.action.position > 0 &&
|
||||||
&& episode.action.position >= episode.action.total
|
episode.action.total > 0 &&
|
||||||
|
episode.action.position >= episode.action.total
|
||||||
|
)
|
||||||
},
|
},
|
||||||
isCurrentEpisode(episode) {
|
isCurrentEpisode(episode) {
|
||||||
return this.currentEpisode && this.currentEpisode.url === episode.url
|
return this.currentEpisode && this.currentEpisode.url === episode.url
|
||||||
},
|
},
|
||||||
isListening(episode) {
|
isListening(episode) {
|
||||||
return episode.action
|
return (
|
||||||
&& episode.action.action.toLowerCase() === 'play'
|
episode.action &&
|
||||||
&& !this.hasEnded(episode)
|
episode.action.action.toLowerCase() === 'play' &&
|
||||||
|
!this.hasEnded(episode)
|
||||||
|
)
|
||||||
},
|
},
|
||||||
load(episode) {
|
load(episode) {
|
||||||
this.$store.dispatch('player/load', episode)
|
this.$store.dispatch('player/load', episode)
|
||||||
@ -220,7 +250,9 @@ export default {
|
|||||||
position: read ? durationToSeconds(episode.duration) : 0,
|
position: read ? durationToSeconds(episode.duration) : 0,
|
||||||
total: durationToSeconds(episode.duration),
|
total: durationToSeconds(episode.duration),
|
||||||
}
|
}
|
||||||
await axios.post(generateUrl('/apps/gpoddersync/episode_action/create'), [episode.action])
|
await axios.post(generateUrl('/apps/gpoddersync/episode_action/create'), [
|
||||||
|
episode.action,
|
||||||
|
])
|
||||||
this.updateList(episode)
|
this.updateList(episode)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
@ -230,18 +262,18 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
updateList(episode) {
|
updateList(episode) {
|
||||||
this.episodes = this.episodes.map((e) => e.url === episode.url ? episode : e)
|
this.episodes = this.episodes.map((e) => (e.url === episode.url ? episode : e))
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.ended {
|
.ended {
|
||||||
opacity: .4;
|
opacity: 0.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress {
|
.progress {
|
||||||
margin-top: .4rem;
|
margin-top: 0.4rem;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="player.episode" class="footer">
|
<div v-if="player.episode" class="footer">
|
||||||
<img class="background" :src="player.episode.image">
|
<img class="background" :src="player.episode.image" />
|
||||||
<Loading v-if="!player.loaded" />
|
<Loading v-if="!player.loaded" />
|
||||||
<ProgressBar v-if="player.loaded" />
|
<ProgressBar v-if="player.loaded" />
|
||||||
<div v-if="player.loaded" class="player">
|
<div v-if="player.loaded" class="player">
|
||||||
<img :src="player.episode.image">
|
<img :src="player.episode.image" />
|
||||||
<Infos class="infos" />
|
<Infos class="infos" />
|
||||||
<Controls class="controls" />
|
<Controls class="controls" />
|
||||||
<Timer class="timer" />
|
<Timer class="timer" />
|
||||||
@ -40,18 +40,18 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.background {
|
.background {
|
||||||
filter: blur(1rem) brightness(50%);
|
filter: blur(1rem) brightness(50%);
|
||||||
height: auto;
|
height: auto;
|
||||||
left: 0;
|
left: 0;
|
||||||
opacity: .4;
|
opacity: 0.4;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
z-index: -1;
|
z-index: -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer {
|
.footer {
|
||||||
background-color: var(--color-main-background);
|
background-color: var(--color-main-background);
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
height: 6rem;
|
height: 6rem;
|
||||||
@ -59,30 +59,31 @@ export default {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
z-index: 2000;
|
z-index: 2000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.player {
|
.player {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
height: 6rem;
|
height: 6rem;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
.timer {
|
.timer {
|
||||||
width: 30%;
|
width: 30%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.volume {
|
.volume {
|
||||||
width: 10%;
|
width: 10%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 768px) {
|
@media only screen and (max-width: 768px) {
|
||||||
.infos {
|
.infos {
|
||||||
flex: 2;
|
flex: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.timer, .volume {
|
.timer,
|
||||||
|
.volume {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<PauseIcon v-if="!player.paused"
|
<PauseIcon
|
||||||
|
v-if="!player.paused"
|
||||||
class="pointer"
|
class="pointer"
|
||||||
:size="50"
|
:size="50"
|
||||||
@click="$store.dispatch('player/pause')" />
|
@click="$store.dispatch('player/pause')" />
|
||||||
<PlayIcon v-if="player.paused"
|
<PlayIcon
|
||||||
|
v-if="player.paused"
|
||||||
class="pointer"
|
class="pointer"
|
||||||
:size="50"
|
:size="50"
|
||||||
@click="$store.dispatch('player/play')" />
|
@click="$store.dispatch('player/play')" />
|
||||||
@ -30,11 +32,11 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.controls {
|
.controls {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pointer {
|
.pointer {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -7,7 +7,8 @@
|
|||||||
<i>{{ player.episode.title }}</i>
|
<i>{{ player.episode.title }}</i>
|
||||||
</router-link>
|
</router-link>
|
||||||
<NcModal v-if="modal" @close="modal = false">
|
<NcModal v-if="modal" @close="modal = false">
|
||||||
<Modal :description="player.episode.description"
|
<Modal
|
||||||
|
:description="player.episode.description"
|
||||||
:image="player.episode.image"
|
:image="player.episode.image"
|
||||||
:link="player.episode.link"
|
:link="player.episode.link"
|
||||||
:name="player.episode.name"
|
:name="player.episode.name"
|
||||||
@ -46,14 +47,14 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.pointer {
|
.pointer {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.root {
|
.root {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: 40%;
|
width: 40%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<input class="progress"
|
<input
|
||||||
|
class="progress"
|
||||||
:max="player.duration"
|
:max="player.duration"
|
||||||
min="0"
|
min="0"
|
||||||
type="range"
|
type="range"
|
||||||
:value="player.currentTime"
|
:value="player.currentTime"
|
||||||
@change="(event) => $store.dispatch('player/seek', event.target.value)">
|
@change="(event) => $store.dispatch('player/seek', event.target.value)" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -19,11 +20,11 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.progress {
|
.progress {
|
||||||
height: 4px;
|
height: 4px;
|
||||||
min-height: 4px;
|
min-height: 4px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -2px;
|
top: -2px;
|
||||||
width: 99%;
|
width: 99%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<span>{{ formatTimer(new Date(player.currentTime*1000)) }}</span>
|
<span>{{ formatTimer(new Date(player.currentTime * 1000)) }}</span>
|
||||||
<span>/</span>
|
<span>/</span>
|
||||||
<span>{{ formatTimer(new Date(player.duration*1000)) }}</span>
|
<span>{{ formatTimer(new Date(player.duration * 1000)) }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -23,10 +23,10 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
div {
|
div {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 5px;
|
gap: 5px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,27 +1,28 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<VolumeHighIcon v-if="player.volume > 0.7"
|
<VolumeHighIcon v-if="player.volume > 0.7" class="pointer" :size="30" @click="mute" />
|
||||||
|
<VolumeLowIcon
|
||||||
|
v-if="player.volume > 0 && player.volume <= 0.3"
|
||||||
class="pointer"
|
class="pointer"
|
||||||
:size="30"
|
:size="30"
|
||||||
@click="mute" />
|
@click="mute" />
|
||||||
<VolumeLowIcon v-if="player.volume > 0 && player.volume <= 0.3"
|
<VolumeMediumIcon
|
||||||
|
v-if="player.volume > 0.3 && player.volume <= 0.7"
|
||||||
class="pointer"
|
class="pointer"
|
||||||
:size="30"
|
:size="30"
|
||||||
@click="mute" />
|
@click="mute" />
|
||||||
<VolumeMediumIcon v-if="player.volume > 0.3 && player.volume <= 0.7"
|
<VolumeMuteIcon
|
||||||
class="pointer"
|
v-if="player.volume === 0"
|
||||||
:size="30"
|
|
||||||
@click="mute" />
|
|
||||||
<VolumeMuteIcon v-if="player.volume === 0"
|
|
||||||
class="pointer"
|
class="pointer"
|
||||||
:size="30"
|
:size="30"
|
||||||
@click="$store.dispatch('player/volume', volumeMuted)" />
|
@click="$store.dispatch('player/volume', volumeMuted)" />
|
||||||
<input max="1"
|
<input
|
||||||
|
max="1"
|
||||||
min="0"
|
min="0"
|
||||||
step="0.1"
|
step="0.1"
|
||||||
type="range"
|
type="range"
|
||||||
:value="player.volume"
|
:value="player.volume"
|
||||||
@change="(event) => $store.dispatch('player/volume', event.target.value)">
|
@change="(event) => $store.dispatch('player/volume', event.target.value)" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -59,19 +60,19 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
div {
|
div {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 5px;
|
gap: 5px;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
transform: rotate(270deg);
|
transform: rotate(270deg);
|
||||||
width: 4rem;
|
width: 4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pointer {
|
.pointer {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<NcAppNavigationItem :href="generateUrl('/apps/repod/opml/export')"
|
<NcAppNavigationItem
|
||||||
|
:href="generateUrl('/apps/repod/opml/export')"
|
||||||
:name="t('repod', 'Export subscriptions')">
|
:name="t('repod', 'Export subscriptions')">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<ExportIcon :size="20" />
|
<ExportIcon :size="20" />
|
||||||
|
@ -1,23 +1,41 @@
|
|||||||
<template>
|
<template>
|
||||||
<NcAppNavigationItem :allow-collapse="true"
|
<NcAppNavigationItem
|
||||||
|
:allow-collapse="true"
|
||||||
menu-placement="top"
|
menu-placement="top"
|
||||||
:name="t('repod', 'Filtering episodes')">
|
:name="t('repod', 'Filtering episodes')">
|
||||||
<template #actions>
|
<template #actions>
|
||||||
<NcActionCheckbox :checked="all"
|
<NcActionCheckbox
|
||||||
|
:checked="all"
|
||||||
:disabled="all"
|
:disabled="all"
|
||||||
@update:checked="(checked) => $store.commit('settings/filters', { listened: checked, listening: checked, unlistened: checked })">
|
@update:checked="
|
||||||
|
(checked) =>
|
||||||
|
$store.commit('settings/filters', {
|
||||||
|
listened: checked,
|
||||||
|
listening: checked,
|
||||||
|
unlistened: checked,
|
||||||
|
})
|
||||||
|
">
|
||||||
{{ t('repod', 'Show all') }}
|
{{ t('repod', 'Show all') }}
|
||||||
</NcActionCheckbox>
|
</NcActionCheckbox>
|
||||||
<NcActionCheckbox :checked="filters.listened"
|
<NcActionCheckbox
|
||||||
@update:checked="(checked) => $store.commit('settings/filters', { listened: checked })">
|
:checked="filters.listened"
|
||||||
|
@update:checked="
|
||||||
|
(checked) => $store.commit('settings/filters', { listened: checked })
|
||||||
|
">
|
||||||
{{ t('repod', 'Listened') }}
|
{{ t('repod', 'Listened') }}
|
||||||
</NcActionCheckbox>
|
</NcActionCheckbox>
|
||||||
<NcActionCheckbox :checked="filters.listening"
|
<NcActionCheckbox
|
||||||
@update:checked="(checked) => $store.commit('settings/filters', { listening: checked })">
|
:checked="filters.listening"
|
||||||
|
@update:checked="
|
||||||
|
(checked) => $store.commit('settings/filters', { listening: checked })
|
||||||
|
">
|
||||||
{{ t('repod', 'Listening') }}
|
{{ t('repod', 'Listening') }}
|
||||||
</NcActionCheckbox>
|
</NcActionCheckbox>
|
||||||
<NcActionCheckbox :checked="filters.unlistened"
|
<NcActionCheckbox
|
||||||
@update:checked="(checked) => $store.commit('settings/filters', { unlistened: checked })">
|
:checked="filters.unlistened"
|
||||||
|
@update:checked="
|
||||||
|
(checked) => $store.commit('settings/filters', { unlistened: checked })
|
||||||
|
">
|
||||||
{{ t('repod', 'Unlistened') }}
|
{{ t('repod', 'Unlistened') }}
|
||||||
</NcActionCheckbox>
|
</NcActionCheckbox>
|
||||||
</template>
|
</template>
|
||||||
|
@ -4,16 +4,18 @@
|
|||||||
<NcModal v-if="modal" @close="modal = false">
|
<NcModal v-if="modal" @close="modal = false">
|
||||||
<div class="modal">
|
<div class="modal">
|
||||||
<h2>{{ t('repod', 'Import OPML file') }}</h2>
|
<h2>{{ t('repod', 'Import OPML file') }}</h2>
|
||||||
<form v-if="!loading"
|
<form
|
||||||
|
v-if="!loading"
|
||||||
:action="generateUrl('/apps/repod/opml/import')"
|
:action="generateUrl('/apps/repod/opml/import')"
|
||||||
enctype="multipart/form-data"
|
enctype="multipart/form-data"
|
||||||
method="post"
|
method="post"
|
||||||
@submit.prevent="importOpml">
|
@submit.prevent="importOpml">
|
||||||
<input accept="application/xml,.opml"
|
<input
|
||||||
|
accept="application/xml,.opml"
|
||||||
name="import"
|
name="import"
|
||||||
required
|
required
|
||||||
type="file">
|
type="file" />
|
||||||
<input type="submit">
|
<input type="submit" />
|
||||||
</form>
|
</form>
|
||||||
<Loading v-if="loading" />
|
<Loading v-if="loading" />
|
||||||
</div>
|
</div>
|
||||||
@ -64,10 +66,10 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.modal {
|
.modal {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
margin: 2rem;
|
margin: 2rem;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<NcAppNavigationItem href="https://apps.nextcloud.com/apps/repod#comments"
|
<NcAppNavigationItem
|
||||||
|
href="https://apps.nextcloud.com/apps/repod#comments"
|
||||||
:name="t('repod', 'Rate RePod ❤️')">
|
:name="t('repod', 'Rate RePod ❤️')">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<StarIcon :size="20" />
|
<StarIcon :size="20" />
|
||||||
|
@ -2,15 +2,9 @@
|
|||||||
<NcAppNavigationItem :name="t('repod', 'Playback speed')">
|
<NcAppNavigationItem :name="t('repod', 'Playback speed')">
|
||||||
<template #extra>
|
<template #extra>
|
||||||
<div class="extra">
|
<div class="extra">
|
||||||
<MinusIcon class="pointer"
|
<MinusIcon class="pointer" :size="20" @click="changeRate(-0.1)" />
|
||||||
:size="20"
|
<NcCounterBubble class="counter"> x{{ player.rate }} </NcCounterBubble>
|
||||||
@click="changeRate(-.1)" />
|
<PlusIcon class="pointer" :size="20" @click="changeRate(0.1)" />
|
||||||
<NcCounterBubble class="counter">
|
|
||||||
x{{ player.rate }}
|
|
||||||
</NcCounterBubble>
|
|
||||||
<PlusIcon class="pointer"
|
|
||||||
:size="20"
|
|
||||||
@click="changeRate(.1)" />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #icon>
|
<template #icon>
|
||||||
@ -55,17 +49,17 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.counter {
|
.counter {
|
||||||
height: 20px;
|
height: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.extra {
|
.extra {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: .5rem;
|
gap: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pointer {
|
.pointer {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<NcAppNavigationItem :loading="loading"
|
<NcAppNavigationItem :loading="loading" :name="feed ? feed.title : url" :to="hash">
|
||||||
:name="feed ? feed.title : url"
|
|
||||||
:to="hash">
|
|
||||||
<template #actions>
|
<template #actions>
|
||||||
<NcActionButton :aria-label="t(`core`, 'Delete')"
|
<NcActionButton
|
||||||
|
:aria-label="t(`core`, 'Delete')"
|
||||||
:name="t(`core`, 'Delete')"
|
:name="t(`core`, 'Delete')"
|
||||||
:title="t(`core`, 'Delete')"
|
:title="t(`core`, 'Delete')"
|
||||||
@click="deleteSubscription">
|
@click="deleteSubscription">
|
||||||
@ -13,7 +12,8 @@
|
|||||||
</NcActionButton>
|
</NcActionButton>
|
||||||
</template>
|
</template>
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<NcAvatar v-if="feed"
|
<NcAvatar
|
||||||
|
v-if="feed"
|
||||||
:display-name="feed.author || feed.title"
|
:display-name="feed.author || feed.title"
|
||||||
:is-no-user="true"
|
:is-no-user="true"
|
||||||
:url="feed.imageUrl" />
|
:url="feed.imageUrl" />
|
||||||
@ -60,7 +60,11 @@ export default {
|
|||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
try {
|
try {
|
||||||
const podcastData = await axios.get(generateUrl('/apps/gpoddersync/personal_settings/podcast_data?url={url}', { url: this.url }))
|
const podcastData = await axios.get(
|
||||||
|
generateUrl('/apps/gpoddersync/personal_settings/podcast_data?url={url}', {
|
||||||
|
url: this.url,
|
||||||
|
}),
|
||||||
|
)
|
||||||
this.feed = podcastData.data.data
|
this.feed = podcastData.data.data
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.failed = true
|
this.failed = true
|
||||||
@ -74,7 +78,10 @@ export default {
|
|||||||
if (confirm(t('repod', 'Are you sure you want to delete this subscription?'))) {
|
if (confirm(t('repod', 'Are you sure you want to delete this subscription?'))) {
|
||||||
try {
|
try {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
await axios.post(generateUrl('/apps/gpoddersync/subscription_change/create'), { add: [], remove: [this.url] })
|
await axios.post(
|
||||||
|
generateUrl('/apps/gpoddersync/subscription_change/create'),
|
||||||
|
{ add: [], remove: [this.url] },
|
||||||
|
)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
showError(t('repod', 'Error while removing the feed'))
|
showError(t('repod', 'Error while removing the feed'))
|
||||||
|
@ -11,7 +11,8 @@
|
|||||||
</router-link>
|
</router-link>
|
||||||
<Loading v-if="loading" />
|
<Loading v-if="loading" />
|
||||||
<NcAppNavigationList v-if="!loading">
|
<NcAppNavigationList v-if="!loading">
|
||||||
<Item v-for="subscriptionUrl of subscriptions"
|
<Item
|
||||||
|
v-for="subscriptionUrl of subscriptions"
|
||||||
:key="subscriptionUrl"
|
:key="subscriptionUrl"
|
||||||
:url="subscriptionUrl" />
|
:url="subscriptionUrl" />
|
||||||
</NcAppNavigationList>
|
</NcAppNavigationList>
|
||||||
|
@ -14,5 +14,5 @@ export default new Vue({
|
|||||||
el: '#content',
|
el: '#content',
|
||||||
router,
|
router,
|
||||||
store,
|
store,
|
||||||
render: h => h(App),
|
render: (h) => h(App),
|
||||||
})
|
})
|
||||||
|
@ -54,7 +54,11 @@ export const player = {
|
|||||||
audio.load()
|
audio.load()
|
||||||
audio.play()
|
audio.play()
|
||||||
|
|
||||||
if (episode.action && episode.action.position && episode.action.position < episode.action.total) {
|
if (
|
||||||
|
episode.action &&
|
||||||
|
episode.action.position &&
|
||||||
|
episode.action.position < episode.action.total
|
||||||
|
) {
|
||||||
audio.currentTime = episode.action.position
|
audio.currentTime = episode.action.position
|
||||||
state.started = audio.currentTime
|
state.started = audio.currentTime
|
||||||
}
|
}
|
||||||
@ -84,7 +88,9 @@ export const player = {
|
|||||||
load: async (context, episode) => {
|
load: async (context, episode) => {
|
||||||
context.commit('episode', episode)
|
context.commit('episode', episode)
|
||||||
try {
|
try {
|
||||||
const action = await axios.get(generateUrl('/apps/repod/episodes/action?url={url}', { url: episode.url }))
|
const action = await axios.get(
|
||||||
|
generateUrl('/apps/repod/episodes/action?url={url}', { url: episode.url }),
|
||||||
|
)
|
||||||
context.commit('action', action.data)
|
context.commit('action', action.data)
|
||||||
} catch {}
|
} catch {}
|
||||||
},
|
},
|
||||||
@ -118,7 +124,9 @@ export const player = {
|
|||||||
position: Math.round(audio.currentTime),
|
position: Math.round(audio.currentTime),
|
||||||
total: Math.round(audio.duration),
|
total: Math.round(audio.duration),
|
||||||
}
|
}
|
||||||
axios.post(generateUrl('/apps/gpoddersync/episode_action/create'), [episode.action])
|
axios.post(generateUrl('/apps/gpoddersync/episode_action/create'), [
|
||||||
|
episode.action,
|
||||||
|
])
|
||||||
EventBus.$emit('updateEpisodesList', episode)
|
EventBus.$emit('updateEpisodesList', episode)
|
||||||
},
|
},
|
||||||
volume: (_, volume) => {
|
volume: (_, volume) => {
|
||||||
|
@ -13,9 +13,16 @@ export const subscriptions = {
|
|||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
fetch: async (context) => {
|
fetch: async (context) => {
|
||||||
const metrics = await axios.get(generateUrl('/apps/gpoddersync/personal_settings/metrics'))
|
const metrics = await axios.get(
|
||||||
const subs = [...metrics.data.subscriptions].sort((a, b) => b.listenedSeconds - a.listenedSeconds)
|
generateUrl('/apps/gpoddersync/personal_settings/metrics'),
|
||||||
context.commit('set', subs.map(sub => sub.url))
|
)
|
||||||
|
const subs = [...metrics.data.subscriptions].sort(
|
||||||
|
(a, b) => b.listenedSeconds - a.listenedSeconds,
|
||||||
|
)
|
||||||
|
context.commit(
|
||||||
|
'set',
|
||||||
|
subs.map((sub) => sub.url),
|
||||||
|
)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
export const getCookie = (name) => {
|
export const getCookie = (name) => {
|
||||||
const cookies = document.cookie.split('; ')
|
const cookies = document.cookie.split('; ')
|
||||||
const value = cookies
|
const value = cookies.find((c) => c.startsWith(name + '='))?.split('=')[1]
|
||||||
.find(c => c.startsWith(name + '='))
|
|
||||||
?.split('=')[1]
|
|
||||||
if (value === undefined) {
|
if (value === undefined) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
// https://stackoverflow.com/a/53486112
|
// https://stackoverflow.com/a/53486112
|
||||||
export const debounce = (fn, delay) => {
|
export const debounce = (fn, delay) => {
|
||||||
let timeoutID = null
|
let timeoutID = null
|
||||||
return function() {
|
return function () {
|
||||||
clearTimeout(timeoutID)
|
clearTimeout(timeoutID)
|
||||||
const args = arguments
|
const args = arguments
|
||||||
const that = this
|
const that = this
|
||||||
timeoutID = setTimeout(function() {
|
timeoutID = setTimeout(function () {
|
||||||
fn.apply(that, args)
|
fn.apply(that, args)
|
||||||
}, delay)
|
}, delay)
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// https://stackoverflow.com/a/5002618
|
// https://stackoverflow.com/a/5002618
|
||||||
export const cleanHtml = (text) => {
|
export const cleanHtml = (text) => {
|
||||||
const pre = document.createElement('pre')
|
const pre = document.createElement('pre')
|
||||||
pre.innerHTML = text.replace(/<br\s*\/?>/mg, '\n')
|
pre.innerHTML = text.replace(/<br\s*\/?>/gm, '\n')
|
||||||
const strippedText = pre.textContent || pre.innerText || ''
|
const strippedText = pre.textContent || pre.innerText || ''
|
||||||
return strippedText.replace(/\n/mg, '<br>')
|
return strippedText.replace(/\n/gm, '<br>')
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,8 @@ export const formatEpisodeTimestamp = (date) => {
|
|||||||
* @param {Date} date The date
|
* @param {Date} date The date
|
||||||
* @return {string}
|
* @return {string}
|
||||||
*/
|
*/
|
||||||
export const formatLocaleDate = (date) => date.toLocaleDateString(undefined, { dateStyle: 'medium' })
|
export const formatLocaleDate = (date) =>
|
||||||
|
date.toLocaleDateString(undefined, { dateStyle: 'medium' })
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of seconds from a duration feed's entry
|
* Returns the number of seconds from a duration feed's entry
|
||||||
@ -46,7 +47,7 @@ export const formatLocaleDate = (date) => date.toLocaleDateString(undefined, { d
|
|||||||
export const durationToSeconds = (duration) => {
|
export const durationToSeconds = (duration) => {
|
||||||
const splitDuration = duration.split(':').reverse()
|
const splitDuration = duration.split(':').reverse()
|
||||||
let seconds = parseInt(splitDuration[0])
|
let seconds = parseInt(splitDuration[0])
|
||||||
seconds += (splitDuration.length > 1) ? parseInt(splitDuration[1]) * 60 : 0
|
seconds += splitDuration.length > 1 ? parseInt(splitDuration[1]) * 60 : 0
|
||||||
seconds += (splitDuration.length > 2) ? parseInt(splitDuration[2]) * 60 * 60 : 0
|
seconds += splitDuration.length > 2 ? parseInt(splitDuration[2]) * 60 * 60 : 0
|
||||||
return seconds
|
return seconds
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.main {
|
.main {
|
||||||
padding: 15px 51px;
|
padding: 15px 51px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<AppContent>
|
<AppContent>
|
||||||
<Loading v-if="loading" />
|
<Loading v-if="loading" />
|
||||||
<NcEmptyContent v-if="failed"
|
<NcEmptyContent v-if="failed" class="error" :name="t('repod', 'Error loading feed')">
|
||||||
class="error"
|
|
||||||
:name="t('repod', 'Error loading feed')">
|
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<Alert />
|
<Alert />
|
||||||
</template>
|
</template>
|
||||||
</NcEmptyContent>
|
</NcEmptyContent>
|
||||||
<Banner v-if="feed"
|
<Banner
|
||||||
|
v-if="feed"
|
||||||
:author="feed.author"
|
:author="feed.author"
|
||||||
:description="feed.description"
|
:description="feed.description"
|
||||||
:image-url="feed.imageUrl"
|
:image-url="feed.imageUrl"
|
||||||
@ -53,7 +52,9 @@ export default {
|
|||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
try {
|
try {
|
||||||
const podcastData = await axios.get(generateUrl('/apps/repod/podcast?url={url}', { url: this.url }))
|
const podcastData = await axios.get(
|
||||||
|
generateUrl('/apps/repod/podcast?url={url}', { url: this.url }),
|
||||||
|
)
|
||||||
this.feed = podcastData.data
|
this.feed = podcastData.data
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.failed = true
|
this.failed = true
|
||||||
@ -66,7 +67,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.error {
|
.error {
|
||||||
margin: 2rem;
|
margin: 2rem;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -14,11 +14,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {
|
import { NcAppContent, NcButton, NcEmptyContent } from '@nextcloud/vue'
|
||||||
NcAppContent,
|
|
||||||
NcButton,
|
|
||||||
NcEmptyContent,
|
|
||||||
} from '@nextcloud/vue'
|
|
||||||
import Alert from 'vue-material-design-icons/Alert.vue'
|
import Alert from 'vue-material-design-icons/Alert.vue'
|
||||||
import { generateUrl } from '@nextcloud/router'
|
import { generateUrl } from '@nextcloud/router'
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user