new homepage based on favorites (fixes #130 #59) #131

Merged
Xefir merged 23 commits from favorites into main 2024-09-02 09:28:09 +00:00
9 changed files with 102 additions and 29 deletions
Showing only changes of commit a30678bfd2 - Show all commits

View File

@ -19,7 +19,7 @@
</template>
<template #actions>
<NcActionButton
v-if="!subscriptions.includes(feed.link)"
v-if="!subs.includes(feed.link)"
:aria-label="t('repod', 'Subscribe')"
:name="t('repod', 'Subscribe')"
:title="t('repod', 'Subscribe')"
@ -69,7 +69,7 @@ export default {
}
},
computed: {
...mapState(useSubscriptions, ['subscriptions']),
...mapState(useSubscriptions, ['subs']),
},
watch: {
value() {

View File

@ -23,7 +23,7 @@
<SafeHtml :source="description" />
</div>
<NcAppNavigationNew
v-if="!subscriptions.includes(url)"
v-if="!subs.includes(url)"
:text="t('repod', 'Subscribe')"
@click="addSubscription">
<template #icon>
@ -79,7 +79,7 @@ export default {
},
},
computed: {
...mapState(useSubscriptions, ['subscriptions']),
...mapState(useSubscriptions, ['subs']),
url() {
return decodeUrl(this.$route.params.url)
},

View File

@ -44,7 +44,6 @@ import { NcActionCheckbox, NcAppNavigationItem } from '@nextcloud/vue'
import { mapActions, mapState } from 'pinia'
import FilterIcon from 'vue-material-design-icons/Filter.vue'
import FilterSettingsIcon from 'vue-material-design-icons/FilterSettings.vue'
import { getCookie } from '../../utils/cookies.js'
import { useSettings } from '../../store/settings.js'
export default {
@ -65,12 +64,6 @@ export default {
)
},
},
mounted() {
try {
const filters = getCookie('repod.filters')
this.filters = JSON.parse(filters)
} catch {}
},
methods: {
...mapActions(useSettings, ['setFilters']),
},

View File

@ -4,6 +4,17 @@
:name="feed ? feed.title : url"
:to="hash">
<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
:aria-label="t(`core`, 'Delete')"
:name="t(`core`, 'Delete')"
@ -20,6 +31,7 @@
:display-name="feed.author || feed.title"
:is-no-user="true"
:url="feed.imageUrl" />
<StarIcon v-if="feed && isFavorite" class="star" :size="20" />
<AlertIcon v-if="failed" />
</template>
</NcAppNavigationItem>
@ -27,11 +39,14 @@
<script>
import { NcActionButton, NcAppNavigationItem, NcAvatar } from '@nextcloud/vue'
import { mapActions, mapState } from 'pinia'
import AlertIcon from 'vue-material-design-icons/Alert.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 { generateUrl } from '@nextcloud/router'
import { mapActions } from 'pinia'
import { showError } from '../../utils/toast.js'
import { toUrl } from '../../utils/url.js'
import { useSubscriptions } from '../../store/subscriptions.js'
@ -44,6 +59,9 @@ export default {
NcActionButton,
NcAppNavigationItem,
NcAvatar,
StarIcon,
StarPlusIcon,
StarRemoveIcon,
},
props: {
url: {
@ -59,9 +77,13 @@ export default {
}
},
computed: {
...mapState(useSubscriptions, ['favorites']),
hash() {
return toUrl(this.url)
},
isFavorite() {
return this.favorites.includes(this.url)
},
},
async mounted() {
try {
@ -82,7 +104,7 @@ export default {
}
},
methods: {
...mapActions(useSubscriptions, ['fetch']),
...mapActions(useSubscriptions, ['fetch', 'addFavorite', 'removeFavorite']),
async deleteSubscription() {
if (
confirm(
@ -99,11 +121,33 @@ export default {
console.error(e)
showError(t('repod', 'Error while removing the feed'))
} finally {
this.removeFavorite(this.url)
this.loading = false
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>
<style scoped>
.star {
bottom: 2px;
color: yellow;
left: 22px;
position: absolute;
}
</style>

View File

@ -2,7 +2,7 @@
<AppNavigation>
<template #list>
<NcAppContentList>
<router-link to="/">
<router-link to="/discover">
<NcAppNavigationNew :text="t('repod', 'Add a podcast')">
<template #icon>
<PlusIcon :size="20" />
@ -11,10 +11,7 @@
</router-link>
<Loading v-if="loading" />
<NcAppNavigationList v-if="!loading">
<Item
v-for="subscriptionUrl of subscriptions"
:key="subscriptionUrl"
:url="subscriptionUrl" />
<Item v-for="url of subs" :key="url" :url="url" />
</NcAppNavigationList>
</NcAppContentList>
</template>
@ -57,7 +54,7 @@ export default {
}
},
computed: {
...mapState(useSubscriptions, ['subscriptions']),
...mapState(useSubscriptions, ['subs']),
},
async mounted() {
try {

View File

@ -1,6 +1,7 @@
import { createRouter, createWebHashHistory } from 'vue-router'
import Discover from './views/Discover.vue'
import Feed from './views/Feed.vue'
import Home from './views/Home.vue'
import { generateUrl } from '@nextcloud/router'
const router = createRouter({
@ -8,6 +9,10 @@ const router = createRouter({
routes: [
{
path: '/',
component: Home,
},
{
path: '/discover',
component: Discover,
},
{

View File

@ -1,14 +1,27 @@
import { getCookie, setCookie } from '../utils/cookies.js'
import { defineStore } from 'pinia'
import { setCookie } from '../utils/cookies.js'
export const useSettings = defineStore('settings', {
state: () => ({
filters: {
listened: true,
listening: true,
unlistened: true,
},
}),
state: () => {
try {
const filters = JSON.parse(getCookie('repod.filters'))
return {
filters: {
listened: filters.listened,
listening: filters.listening,
unlistened: filters.unlistened,
},
}
} catch {
return {
filters: {
listened: true,
listening: true,
unlistened: true,
},
}
}
},
actions: {
setFilters(filters) {
this.filters = { ...this.filters, ...filters }

View File

@ -1,10 +1,12 @@
import { getCookie, setCookie } from '../utils/cookies.js'
import axios from '@nextcloud/axios'
import { defineStore } from 'pinia'
import { generateUrl } from '@nextcloud/router'
export const useSubscriptions = defineStore('subscriptions', {
state: () => ({
subscriptions: [],
subs: [],
favorites: [],
}),
actions: {
async fetch() {
@ -14,7 +16,19 @@ export const useSubscriptions = defineStore('subscriptions', {
const subs = [...metrics.data.subscriptions].sort(
(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
View File

@ -0,0 +1,7 @@
<template><div /></template>
<script>
export default {
name: 'Home',
}
</script>