select all episodes (fix #81) #220

Merged
Xefir merged 4 commits from multiselect into main 2024-12-11 14:01:21 +00:00
2 changed files with 30 additions and 3 deletions
Showing only changes of commit 69d1ce44a4 - Show all commits

View File

@ -33,7 +33,7 @@
</NcActionButton> </NcActionButton>
</template> </template>
<template #extra> <template #extra>
<NcActions> <NcActions v-if="displayActions">
<NcActionButton <NcActionButton
v-if="episode.duration" v-if="episode.duration"
:aria-label="t('repod', 'Read')" :aria-label="t('repod', 'Read')"
@ -77,7 +77,12 @@
<NcAvatar <NcAvatar
:display-name="episode.name" :display-name="episode.name"
:is-no-user="true" :is-no-user="true"
:url="episode.image" /> :url="episode.image"
@click.stop="$emit('select', episode)">
<template #icon>
<CheckIcon v-if="selected" class="progress" :size="20" />
</template>
</NcAvatar>
</template> </template>
<template #indicator> <template #indicator>
<NcProgressBar <NcProgressBar
@ -108,6 +113,7 @@ import {
} from '../../utils/time.ts' } from '../../utils/time.ts'
import { hasEnded, isListening } from '../../utils/status.ts' import { hasEnded, isListening } from '../../utils/status.ts'
import { mapActions, mapState } from 'pinia' import { mapActions, mapState } from 'pinia'
import CheckIcon from 'vue-material-design-icons/Check.vue'
import DownloadIcon from 'vue-material-design-icons/Download.vue' import DownloadIcon from 'vue-material-design-icons/Download.vue'
import type { EpisodeInterface } from '../../utils/types.ts' import type { EpisodeInterface } from '../../utils/types.ts'
import Modal from '../Atoms/Modal.vue' import Modal from '../Atoms/Modal.vue'
@ -126,6 +132,7 @@ import { usePlayer } from '../../store/player.ts'
export default { export default {
name: 'Episode', name: 'Episode',
components: { components: {
CheckIcon,
DownloadIcon, DownloadIcon,
Modal, Modal,
NcActionButton, NcActionButton,
@ -142,6 +149,10 @@ export default {
StopIcon, StopIcon,
}, },
props: { props: {
displayActions: {
type: Boolean,
default: true,
},
episode: { episode: {
type: Object as () => EpisodeInterface, type: Object as () => EpisodeInterface,
required: true, required: true,
@ -150,11 +161,16 @@ export default {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
selected: {
type: Boolean,
default: false,
},
url: { url: {
type: String, type: String,
required: true, required: true,
}, },
}, },
emits: ['select'],
data: () => ({ data: () => ({
loading: false, loading: false,
modalEpisode: null as EpisodeInterface | null, modalEpisode: null as EpisodeInterface | null,

View File

@ -5,8 +5,11 @@
<Episode <Episode
v-for="episode in filteredEpisodes" v-for="episode in filteredEpisodes"
:key="episode.guid" :key="episode.guid"
:display-actions="!selected.length"
:episode="episode" :episode="episode"
:url="url" /> :selected="selected.includes(episode)"
:url="url"
@select="select" />
</ul> </ul>
</div> </div>
</template> </template>
@ -34,6 +37,7 @@ export default {
data: () => ({ data: () => ({
episodes: [] as EpisodeInterface[], episodes: [] as EpisodeInterface[],
loading: true, loading: true,
selected: [] as EpisodeInterface[],
}), }),
computed: { computed: {
...mapState(usePlayer, ['episode']), ...mapState(usePlayer, ['episode']),
@ -88,6 +92,13 @@ export default {
methods: { methods: {
hasEnded, hasEnded,
isListening, isListening,
select(episode: EpisodeInterface) {
if (this.selected.includes(episode)) {
this.selected = this.selected.filter((e) => e !== episode)
} else {
this.selected.push(episode)
}
},
}, },
} }
</script> </script>