feat: multiselect finished
All checks were successful
repod / xml (push) Successful in 22s
repod / php (push) Successful in 54s
repod / nodejs (push) Successful in 1m11s
repod / release (push) Has been skipped

This commit is contained in:
Michel Roux 2024-12-11 11:41:44 +01:00
parent 69d1ce44a4
commit 4163f10c81
4 changed files with 210 additions and 66 deletions

View File

@ -80,7 +80,7 @@
:url="episode.image"
@click.stop="$emit('select', episode)">
<template #icon>
<CheckIcon v-if="selected" class="progress" :size="20" />
<CheckIcon v-if="episode.selected" class="progress" :size="20" />
</template>
</NcAvatar>
</template>
@ -161,10 +161,6 @@ export default {
type: Boolean,
default: false,
},
selected: {
type: Boolean,
default: false,
},
url: {
type: String,
required: true,

View File

@ -2,29 +2,112 @@
<div>
<Loading v-if="loading" />
<ul v-if="!loading">
<NcListItem
v-if="!episodes.every((e) => !e.selected)"
:active="true"
:force-display-actions="true"
:name="
n(
'repod',
'%n episode selected',
'%n episodes selected',
episodes.filter((e) => e.selected).length,
)
"
:one-line="true">
<template #actions>
<NcActionButton
v-if="
episodes
.filter((e) => e.selected)
.filter((e) => !hasEnded(e)).length
"
:aria-label="t('repod', 'Read all')"
:disabled="
!episodes
.filter((e) => e.selected)
.every((e) => e.duration)
"
:name="t('repod', 'Read all')"
:title="t('repod', 'Read all')"
@click="markAs(true)">
<template #icon>
<PlaylistPlayIcon :size="20" />
</template>
</NcActionButton>
<NcActionButton
v-if="
episodes
.filter((e) => e.selected)
.every((e) => hasEnded(e))
"
:aria-label="t('repod', 'Unread all')"
:disabled="
!episodes
.filter((e) => e.selected)
.every((e) => e.duration)
"
:name="t('repod', 'Unread all')"
:title="t('repod', 'Unread all')"
@click="markAs(false)">
<template #icon>
<PlaylistRemoveIcon :size="20" />
</template>
</NcActionButton>
</template>
<template #icon>
<NcAvatar
:display-name="t('repod', 'Select all')"
:is-no-user="true">
<template #icon>
<SelectAllIcon
v-if="
episodes.filter((e) => e.selected).length <
episodes.length
"
class="progress"
:size="20"
@click="select(true)" />
<SelectRemoveIcon
v-if="
episodes.filter((e) => e.selected).length >=
episodes.length
"
class="progress"
:size="20"
@click="select(false)" />
</template>
</NcAvatar>
</template>
</NcListItem>
<Episode
v-for="episode in filteredEpisodes"
:key="episode.guid"
:display-actions="!selected.length"
:display-actions="episodes.every((e) => !e.selected)"
:episode="episode"
:selected="selected.includes(episode)"
:url="url"
@select="select" />
@select="episode.selected = !episode.selected" />
</ul>
</div>
</template>
<script lang="ts">
import { NcActionButton, NcAvatar, NcListItem } from '@nextcloud/vue'
import { durationToSeconds, formatEpisodeTimestamp } from '../../utils/time.ts'
import { hasEnded, isListening } from '../../utils/status.ts'
import { n, t } from '@nextcloud/l10n'
import Episode from './Episode.vue'
import type { EpisodeInterface } from '../../utils/types.ts'
import Loading from '../Atoms/Loading.vue'
import PlaylistPlayIcon from 'vue-material-design-icons/PlaylistPlay.vue'
import PlaylistRemoveIcon from 'vue-material-design-icons/PlaylistRemove.vue'
import SelectAllIcon from 'vue-material-design-icons/SelectAll.vue'
import SelectRemoveIcon from 'vue-material-design-icons/SelectRemove.vue'
import axios from '@nextcloud/axios'
import { decodeUrl } from '../../utils/url.ts'
import { generateUrl } from '@nextcloud/router'
import { mapState } from 'pinia'
import { showError } from '../../utils/toast.ts'
import { t } from '@nextcloud/l10n'
import { usePlayer } from '../../store/player.ts'
import { useSettings } from '../../store/settings.ts'
@ -33,11 +116,17 @@ export default {
components: {
Episode,
Loading,
NcActionButton,
NcAvatar,
NcListItem,
PlaylistPlayIcon,
PlaylistRemoveIcon,
SelectAllIcon,
SelectRemoveIcon,
},
data: () => ({
episodes: [] as EpisodeInterface[],
loading: true,
selected: [] as EpisodeInterface[],
}),
computed: {
...mapState(usePlayer, ['episode']),
@ -92,13 +181,48 @@ export default {
methods: {
hasEnded,
isListening,
select(episode: EpisodeInterface) {
if (this.selected.includes(episode)) {
this.selected = this.selected.filter((e) => e !== episode)
} else {
this.selected.push(episode)
n,
t,
async markAs(read: boolean) {
try {
this.episodes = this.episodes.map((episode) => {
if (episode.selected) {
episode.action = {
podcast: this.url,
episode: episode.url,
guid: episode.guid,
action: 'play',
timestamp: formatEpisodeTimestamp(new Date()),
started: episode.action?.started || 0,
position: read
? durationToSeconds(episode.duration || '')
: 0,
total: durationToSeconds(episode.duration || ''),
}
}
return episode
})
await axios.post(
generateUrl('/apps/gpoddersync/episode_action/create'),
this.episodes.filter((e) => e.selected).map((e) => e.action),
)
} catch (e) {
console.error(e)
showError(t('repod', 'Could not change the status of the episode'))
}
},
select(all: boolean) {
this.episodes = this.episodes.map((episode) => {
episode.selected = all
return episode
})
},
},
}
</script>
<style scoped>
.progress {
margin-top: 0.4rem;
}
</style>

View File

@ -28,6 +28,7 @@ export interface EpisodeInterface {
}
duration?: string
action?: EpisodeActionInterface
selected?: boolean
}
export interface FiltersInterface {

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Nextcloud 3.14159\n"
"Report-Msgid-Bugs-To: translations\\@example.com\n"
"POT-Creation-Date: 2024-11-12 20:57+0000\n"
"POT-Creation-Date: 2024-12-11 10:38+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -106,7 +106,7 @@ msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:16
#: /app/specialVueFakeDummyForL10nScript.js:17
#: /app/specialVueFakeDummyForL10nScript.js:32
#: /app/specialVueFakeDummyForL10nScript.js:41
msgid "Play"
msgstr ""
@ -127,143 +127,166 @@ msgid "Open website"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:27
#: /app/specialVueFakeDummyForL10nScript.js:36
msgid "Could not change the status of the episode"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:28
#: /app/specialVueFakeDummyForL10nScript.js:29
msgid "Could not fetch episodes"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:30
msgid "Rewind 10 seconds"
msgid "Read all"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:31
msgid "Pause"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:32
#: /app/specialVueFakeDummyForL10nScript.js:33
msgid "Fast forward 30 seconds"
msgid "Unread all"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:34
msgid "Select all"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:35
#: /app/specialVueFakeDummyForL10nScript.js:36
msgid "Mute"
#: /app/specialVueFakeDummyForL10nScript.js:38
msgid "Could not fetch episodes"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:37
msgid "Unmute"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:38
msgid "Export subscriptions"
msgstr ""
msgid "%n episode selected"
msgid_plural "%n episodes selected"
msgstr[0] ""
msgstr[1] ""
#: /app/specialVueFakeDummyForL10nScript.js:39
msgid "Filtering episodes"
msgid "Rewind 10 seconds"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:40
msgid "Show all"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:41
msgid "Listened"
msgid "Pause"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:42
msgid "Listening"
msgid "Fast forward 30 seconds"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:43
msgid "Unlistened"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:44
msgid "Import subscriptions"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:45
msgid "Import OPML file"
msgid "Mute"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:46
msgid "Rate RePod ❤️"
msgid "Unmute"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:47
msgid "Sleep timer"
msgid "Export subscriptions"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:48
msgid "Minutes"
msgid "Filtering episodes"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:49
msgid "Show all"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:50
msgid "Listened"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:51
msgid "Listening"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:52
msgid "Unlistened"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:53
msgid "Import subscriptions"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:54
msgid "Import OPML file"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:55
msgid "Rate RePod ❤️"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:56
msgid "Sleep timer"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:57
msgid "Minutes"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:58
msgid "%n min"
msgid_plural "%n mins"
msgstr[0] ""
msgstr[1] ""
#: /app/specialVueFakeDummyForL10nScript.js:50
#: /app/specialVueFakeDummyForL10nScript.js:59
msgid "%n sec"
msgid_plural "%n secs"
msgstr[0] ""
msgstr[1] ""
#: /app/specialVueFakeDummyForL10nScript.js:51
#: /app/specialVueFakeDummyForL10nScript.js:60
msgid "Playback speed"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:52
#: /app/specialVueFakeDummyForL10nScript.js:53
#: /app/specialVueFakeDummyForL10nScript.js:54
#: /app/specialVueFakeDummyForL10nScript.js:61
#: /app/specialVueFakeDummyForL10nScript.js:62
#: /app/specialVueFakeDummyForL10nScript.js:63
msgid "Favorite"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:55
#: /app/specialVueFakeDummyForL10nScript.js:64
msgid "Are you sure you want to delete this subscription?"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:56
#: /app/specialVueFakeDummyForL10nScript.js:65
msgid "Error while removing the feed"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:57
#: /app/specialVueFakeDummyForL10nScript.js:66
msgid "You can only have 10 favorites"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:58
#: /app/specialVueFakeDummyForL10nScript.js:67
msgid "Add a podcast"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:59
#: /app/specialVueFakeDummyForL10nScript.js:68
msgid "Could not fetch subscriptions"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:60
#: /app/specialVueFakeDummyForL10nScript.js:69
msgid "Find a podcast"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:61
#: /app/specialVueFakeDummyForL10nScript.js:70
msgid "Error loading feed"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:62
#: /app/specialVueFakeDummyForL10nScript.js:71
msgid "Missing required app"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:63
#: /app/specialVueFakeDummyForL10nScript.js:72
msgid "Install GPodder Sync"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:64
#: /app/specialVueFakeDummyForL10nScript.js:73
msgid "Pin some subscriptions to see their latest updates"
msgstr ""
#: /app/specialVueFakeDummyForL10nScript.js:65
#: /app/specialVueFakeDummyForL10nScript.js:74
msgid "No favorites"
msgstr ""