feat: ✨ add favorites (missing homepage)
This commit is contained in:
parent
6bc8d70016
commit
a30678bfd2
@ -19,7 +19,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<template #actions>
|
<template #actions>
|
||||||
<NcActionButton
|
<NcActionButton
|
||||||
v-if="!subscriptions.includes(feed.link)"
|
v-if="!subs.includes(feed.link)"
|
||||||
:aria-label="t('repod', 'Subscribe')"
|
:aria-label="t('repod', 'Subscribe')"
|
||||||
:name="t('repod', 'Subscribe')"
|
:name="t('repod', 'Subscribe')"
|
||||||
:title="t('repod', 'Subscribe')"
|
:title="t('repod', 'Subscribe')"
|
||||||
@ -69,7 +69,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(useSubscriptions, ['subscriptions']),
|
...mapState(useSubscriptions, ['subs']),
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
value() {
|
value() {
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
<SafeHtml :source="description" />
|
<SafeHtml :source="description" />
|
||||||
</div>
|
</div>
|
||||||
<NcAppNavigationNew
|
<NcAppNavigationNew
|
||||||
v-if="!subscriptions.includes(url)"
|
v-if="!subs.includes(url)"
|
||||||
:text="t('repod', 'Subscribe')"
|
:text="t('repod', 'Subscribe')"
|
||||||
@click="addSubscription">
|
@click="addSubscription">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
@ -79,7 +79,7 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(useSubscriptions, ['subscriptions']),
|
...mapState(useSubscriptions, ['subs']),
|
||||||
url() {
|
url() {
|
||||||
return decodeUrl(this.$route.params.url)
|
return decodeUrl(this.$route.params.url)
|
||||||
},
|
},
|
||||||
|
@ -44,7 +44,6 @@ import { NcActionCheckbox, NcAppNavigationItem } from '@nextcloud/vue'
|
|||||||
import { mapActions, mapState } from 'pinia'
|
import { mapActions, mapState } from 'pinia'
|
||||||
import FilterIcon from 'vue-material-design-icons/Filter.vue'
|
import FilterIcon from 'vue-material-design-icons/Filter.vue'
|
||||||
import FilterSettingsIcon from 'vue-material-design-icons/FilterSettings.vue'
|
import FilterSettingsIcon from 'vue-material-design-icons/FilterSettings.vue'
|
||||||
import { getCookie } from '../../utils/cookies.js'
|
|
||||||
import { useSettings } from '../../store/settings.js'
|
import { useSettings } from '../../store/settings.js'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -65,12 +64,6 @@ export default {
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
|
||||||
try {
|
|
||||||
const filters = getCookie('repod.filters')
|
|
||||||
this.filters = JSON.parse(filters)
|
|
||||||
} catch {}
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions(useSettings, ['setFilters']),
|
...mapActions(useSettings, ['setFilters']),
|
||||||
},
|
},
|
||||||
|
@ -4,6 +4,17 @@
|
|||||||
:name="feed ? feed.title : url"
|
:name="feed ? feed.title : url"
|
||||||
:to="hash">
|
:to="hash">
|
||||||
<template #actions>
|
<template #actions>
|
||||||
|
<NcActionButton
|
||||||
|
:aria-label="t('repod', 'Favorite')"
|
||||||
|
:model-value="isFavorite"
|
||||||
|
:name="t('repod', 'Favorite')"
|
||||||
|
:title="t('repod', 'Favorite')"
|
||||||
|
@update:modelValue="switchFavorite($event)">
|
||||||
|
<template #icon>
|
||||||
|
<StarPlusIcon v-if="!isFavorite" :size="20" />
|
||||||
|
<StarRemoveIcon v-if="isFavorite" :size="20" />
|
||||||
|
</template>
|
||||||
|
</NcActionButton>
|
||||||
<NcActionButton
|
<NcActionButton
|
||||||
:aria-label="t(`core`, 'Delete')"
|
:aria-label="t(`core`, 'Delete')"
|
||||||
:name="t(`core`, 'Delete')"
|
:name="t(`core`, 'Delete')"
|
||||||
@ -20,6 +31,7 @@
|
|||||||
: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" />
|
||||||
|
<StarIcon v-if="feed && isFavorite" class="star" :size="20" />
|
||||||
<AlertIcon v-if="failed" />
|
<AlertIcon v-if="failed" />
|
||||||
</template>
|
</template>
|
||||||
</NcAppNavigationItem>
|
</NcAppNavigationItem>
|
||||||
@ -27,11 +39,14 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { NcActionButton, NcAppNavigationItem, NcAvatar } from '@nextcloud/vue'
|
import { NcActionButton, NcAppNavigationItem, NcAvatar } from '@nextcloud/vue'
|
||||||
|
import { mapActions, mapState } from 'pinia'
|
||||||
import AlertIcon from 'vue-material-design-icons/Alert.vue'
|
import AlertIcon from 'vue-material-design-icons/Alert.vue'
|
||||||
import DeleteIcon from 'vue-material-design-icons/Delete.vue'
|
import DeleteIcon from 'vue-material-design-icons/Delete.vue'
|
||||||
|
import StarIcon from 'vue-material-design-icons/Star.vue'
|
||||||
|
import StarPlusIcon from 'vue-material-design-icons/StarPlus.vue'
|
||||||
|
import StarRemoveIcon from 'vue-material-design-icons/StarRemove.vue'
|
||||||
import axios from '@nextcloud/axios'
|
import axios from '@nextcloud/axios'
|
||||||
import { generateUrl } from '@nextcloud/router'
|
import { generateUrl } from '@nextcloud/router'
|
||||||
import { mapActions } from 'pinia'
|
|
||||||
import { showError } from '../../utils/toast.js'
|
import { showError } from '../../utils/toast.js'
|
||||||
import { toUrl } from '../../utils/url.js'
|
import { toUrl } from '../../utils/url.js'
|
||||||
import { useSubscriptions } from '../../store/subscriptions.js'
|
import { useSubscriptions } from '../../store/subscriptions.js'
|
||||||
@ -44,6 +59,9 @@ export default {
|
|||||||
NcActionButton,
|
NcActionButton,
|
||||||
NcAppNavigationItem,
|
NcAppNavigationItem,
|
||||||
NcAvatar,
|
NcAvatar,
|
||||||
|
StarIcon,
|
||||||
|
StarPlusIcon,
|
||||||
|
StarRemoveIcon,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
url: {
|
url: {
|
||||||
@ -59,9 +77,13 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapState(useSubscriptions, ['favorites']),
|
||||||
hash() {
|
hash() {
|
||||||
return toUrl(this.url)
|
return toUrl(this.url)
|
||||||
},
|
},
|
||||||
|
isFavorite() {
|
||||||
|
return this.favorites.includes(this.url)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
try {
|
try {
|
||||||
@ -82,7 +104,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions(useSubscriptions, ['fetch']),
|
...mapActions(useSubscriptions, ['fetch', 'addFavorite', 'removeFavorite']),
|
||||||
async deleteSubscription() {
|
async deleteSubscription() {
|
||||||
if (
|
if (
|
||||||
confirm(
|
confirm(
|
||||||
@ -99,11 +121,33 @@ export default {
|
|||||||
console.error(e)
|
console.error(e)
|
||||||
showError(t('repod', 'Error while removing the feed'))
|
showError(t('repod', 'Error while removing the feed'))
|
||||||
} finally {
|
} finally {
|
||||||
|
this.removeFavorite(this.url)
|
||||||
this.loading = false
|
this.loading = false
|
||||||
this.fetch()
|
this.fetch()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
switchFavorite(value) {
|
||||||
|
if (value) {
|
||||||
|
if (this.favorites.length >= 10) {
|
||||||
|
showError(t('repod', 'You can only have 10 favorites'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.addFavorite(this.url)
|
||||||
|
} else {
|
||||||
|
this.removeFavorite(this.url)
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.star {
|
||||||
|
bottom: 2px;
|
||||||
|
color: yellow;
|
||||||
|
left: 22px;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<AppNavigation>
|
<AppNavigation>
|
||||||
<template #list>
|
<template #list>
|
||||||
<NcAppContentList>
|
<NcAppContentList>
|
||||||
<router-link to="/">
|
<router-link to="/discover">
|
||||||
<NcAppNavigationNew :text="t('repod', 'Add a podcast')">
|
<NcAppNavigationNew :text="t('repod', 'Add a podcast')">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<PlusIcon :size="20" />
|
<PlusIcon :size="20" />
|
||||||
@ -11,10 +11,7 @@
|
|||||||
</router-link>
|
</router-link>
|
||||||
<Loading v-if="loading" />
|
<Loading v-if="loading" />
|
||||||
<NcAppNavigationList v-if="!loading">
|
<NcAppNavigationList v-if="!loading">
|
||||||
<Item
|
<Item v-for="url of subs" :key="url" :url="url" />
|
||||||
v-for="subscriptionUrl of subscriptions"
|
|
||||||
:key="subscriptionUrl"
|
|
||||||
:url="subscriptionUrl" />
|
|
||||||
</NcAppNavigationList>
|
</NcAppNavigationList>
|
||||||
</NcAppContentList>
|
</NcAppContentList>
|
||||||
</template>
|
</template>
|
||||||
@ -57,7 +54,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(useSubscriptions, ['subscriptions']),
|
...mapState(useSubscriptions, ['subs']),
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
try {
|
try {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { createRouter, createWebHashHistory } from 'vue-router'
|
import { createRouter, createWebHashHistory } from 'vue-router'
|
||||||
import Discover from './views/Discover.vue'
|
import Discover from './views/Discover.vue'
|
||||||
import Feed from './views/Feed.vue'
|
import Feed from './views/Feed.vue'
|
||||||
|
import Home from './views/Home.vue'
|
||||||
import { generateUrl } from '@nextcloud/router'
|
import { generateUrl } from '@nextcloud/router'
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
@ -8,6 +9,10 @@ const router = createRouter({
|
|||||||
routes: [
|
routes: [
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
|
component: Home,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/discover',
|
||||||
component: Discover,
|
component: Discover,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1,14 +1,27 @@
|
|||||||
|
import { getCookie, setCookie } from '../utils/cookies.js'
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { setCookie } from '../utils/cookies.js'
|
|
||||||
|
|
||||||
export const useSettings = defineStore('settings', {
|
export const useSettings = defineStore('settings', {
|
||||||
state: () => ({
|
state: () => {
|
||||||
|
try {
|
||||||
|
const filters = JSON.parse(getCookie('repod.filters'))
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
listened: filters.listened,
|
||||||
|
listening: filters.listening,
|
||||||
|
unlistened: filters.unlistened,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
listened: true,
|
listened: true,
|
||||||
listening: true,
|
listening: true,
|
||||||
unlistened: true,
|
unlistened: true,
|
||||||
},
|
},
|
||||||
}),
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
actions: {
|
actions: {
|
||||||
setFilters(filters) {
|
setFilters(filters) {
|
||||||
this.filters = { ...this.filters, ...filters }
|
this.filters = { ...this.filters, ...filters }
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
|
import { getCookie, setCookie } from '../utils/cookies.js'
|
||||||
import axios from '@nextcloud/axios'
|
import axios from '@nextcloud/axios'
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { generateUrl } from '@nextcloud/router'
|
import { generateUrl } from '@nextcloud/router'
|
||||||
|
|
||||||
export const useSubscriptions = defineStore('subscriptions', {
|
export const useSubscriptions = defineStore('subscriptions', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
subscriptions: [],
|
subs: [],
|
||||||
|
favorites: [],
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
async fetch() {
|
async fetch() {
|
||||||
@ -14,7 +16,19 @@ export const useSubscriptions = defineStore('subscriptions', {
|
|||||||
const subs = [...metrics.data.subscriptions].sort(
|
const subs = [...metrics.data.subscriptions].sort(
|
||||||
(a, b) => b.listenedSeconds - a.listenedSeconds,
|
(a, b) => b.listenedSeconds - a.listenedSeconds,
|
||||||
)
|
)
|
||||||
this.subscriptions = subs.map((sub) => sub.url)
|
this.subs = subs.map((sub) => sub.url)
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.favorites = JSON.parse(getCookie('repod.favorites')) || []
|
||||||
|
} catch {}
|
||||||
|
},
|
||||||
|
addFavorite(url) {
|
||||||
|
this.favorites.push(url)
|
||||||
|
setCookie('repod.favorites', JSON.stringify(this.favorites), 365)
|
||||||
|
},
|
||||||
|
removeFavorite(url) {
|
||||||
|
this.favorites = this.favorites.filter((favorite) => favorite !== url)
|
||||||
|
setCookie('repod.favorites', JSON.stringify(this.favorites), 365)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
7
src/views/Home.vue
Normal file
7
src/views/Home.vue
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<template><div /></template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'Home',
|
||||||
|
}
|
||||||
|
</script>
|
Loading…
Reference in New Issue
Block a user