Skip to content

Commit

Permalink
Implement playlist sorting
Browse files Browse the repository at this point in the history
  • Loading branch information
kommunarr committed Apr 10, 2024
1 parent ff9c9e8 commit b1b1df7
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,9 @@ export default defineComponent({
newPlaylistDefaultProperties: function () {
return this.$store.getters.getNewPlaylistDefaultProperties
},

locale: function () {
return this.$i18n.locale.replace('_', '-')
},
processedQuery: function() {
return this.query.trim().toLowerCase()
},
Expand Down
1 change: 1 addition & 0 deletions src/renderer/store/modules/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ const state = {
thumbnailPreference: '',
blurThumbnails: false,
useProxy: false,
userPlaylistSortOrder: 'custom',
useRssFeeds: false,
useSponsorBlock: false,
videoVolumeMouseScroll: false,
Expand Down
125 changes: 120 additions & 5 deletions src/renderer/views/Playlist/Playlist.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import PlaylistInfo from '../../components/playlist-info/playlist-info.vue'
import FtListVideoNumbered from '../../components/ft-list-video-numbered/ft-list-video-numbered.vue'
import FtFlexBox from '../../components/ft-flex-box/ft-flex-box.vue'
import FtButton from '../../components/ft-button/ft-button.vue'
import FtSelect from '../../components/ft-select/ft-select.vue'
import {
getLocalPlaylist,
getLocalPlaylistContinuation,
Expand All @@ -15,6 +16,29 @@ import {
import { extractNumberFromString, setPublishedTimestampsInvidious, showToast } from '../../helpers/utils'
import { invidiousGetPlaylistInfo, youtubeImageUrlToInvidious } from '../../helpers/api/invidious'

const SORT_BY_VALUES = {
Custom: 'custom',
CustomDescending: 'custom_descending',
DateAddedNewest: 'date_added_descending',
DateAddedOldest: 'date_added_ascending',
DatePublishedNewest: 'date_published_newest',
DatePublishedOldest: 'date_published_oldest',
VideoTitleAscending: 'video_title_ascending',
VideoTitleDescending: 'video_title_descending',
ChannelNameAscending: 'channel_name_ascending',
ChannelNameDescending: 'channel_name_descending',
}

const USER_PLAYLIST_ONLY_SORT_BY_VALUES = [
SORT_BY_VALUES.DateAddedNewest,
SORT_BY_VALUES.DateAddedOldest
]

const REMOTE_PLAYLIST_ONLY_SORT_BY_VALUES = [
SORT_BY_VALUES.DatePublishedNewest,
SORT_BY_VALUES.DatePublishedOldest
]

export default defineComponent({
name: 'Playlist',
components: {
Expand All @@ -23,7 +47,8 @@ export default defineComponent({
'playlist-info': PlaylistInfo,
'ft-list-video-numbered': FtListVideoNumbered,
'ft-flex-box': FtFlexBox,
'ft-button': FtButton
'ft-button': FtButton,
'ft-select': FtSelect
},
beforeRouteLeave(to, from, next) {
if (!this.isLoading && !this.isUserPlaylistRequested && to.path.startsWith('/watch') && to.query.playlistId === this.playlistId) {
Expand Down Expand Up @@ -64,6 +89,7 @@ export default defineComponent({
videoSearchQuery: '',

promptOpen: false,
localSortOrder: SORT_BY_VALUES.Custom
}
},
computed: {
Expand All @@ -76,6 +102,12 @@ export default defineComponent({
currentInvidiousInstance: function () {
return this.$store.getters.getCurrentInvidiousInstance
},
userPlaylistSortOrder: function () {
return this.$store.getters.getUserPlaylistSortOrder
},
sortOrder: function () {
return this.isUserPlaylistRequested ? this.userPlaylistSortOrder : this.localSortOrder
},
currentLocale: function () {
return this.$i18n.locale.replace('_', '-')
},
Expand Down Expand Up @@ -138,17 +170,59 @@ export default defineComponent({
},

sometimesFilteredUserPlaylistItems() {
if (!this.isUserPlaylistRequested) { return this.playlistItems }
if (this.processedVideoSearchQuery === '') { return this.playlistItems }
if (!this.isUserPlaylistRequested) { return this.sortedPlaylistItems }
if (this.processedVideoSearchQuery === '') { return this.sortedPlaylistItems }

return this.playlistItems.filter((v) => {
return this.sortedPlaylistItems.filter((v) => {
return v.title.toLowerCase().includes(this.processedVideoSearchQuery)
})
},
sortByValues() {
const sortByValues = Object.values(SORT_BY_VALUES)
if (!this.isUserPlaylistRequested) {
return sortByValues.filter((k) => !USER_PLAYLIST_ONLY_SORT_BY_VALUES.includes(k))
} else {
return sortByValues.filter((k) => !REMOTE_PLAYLIST_ONLY_SORT_BY_VALUES.includes(k))
}
},
isSortOrderCustom() {
return this.sortOrder === SORT_BY_VALUES.Custom || this.sortOrder === SORT_BY_VALUES.CustomDescending
},
sortedPlaylistItems: function () {
if (this.sortOrder === SORT_BY_VALUES.Custom) {
return this.playlistItems
} else if (this.sortOrder === SORT_BY_VALUES.CustomDescending) {
return this.playlistItems.toReversed()
}

return this.playlistItems.toSorted((a, b) => {
switch (this.sortOrder) {
case SORT_BY_VALUES.DateAddedNewest:
return b.timeAdded - a.timeAdded
case SORT_BY_VALUES.DateAddedOldest:
return a.timeAdded - b.timeAdded
case SORT_BY_VALUES.DatePublishedNewest:
return b.published - a.published
case SORT_BY_VALUES.DatePublishedOldest:
return a.published - b.published
case SORT_BY_VALUES.VideoTitleAscending:
return a.title.localeCompare(b.title, this.currentLocale)
case SORT_BY_VALUES.VideoTitleDescending:
return b.title.localeCompare(a.title, this.currentLocale)
case SORT_BY_VALUES.ChannelNameAscending:
return a.author.localeCompare(b.author, this.currentLocale)
case SORT_BY_VALUES.ChannelNameDescending:
return b.author.localeCompare(a.author, this.currentLocale)
default:
console.error(`Unknown sortOrder: ${this.sortOrder}`)
return 0
}
})
},
visiblePlaylistItems: function () {
if (!this.isUserPlaylistRequested) {
// No filtering for non user playlists yet
return this.playlistItems
return this.sortedPlaylistItems
}

if (this.userPlaylistVisibleLimit < this.sometimesFilteredUserPlaylistItems.length) {
Expand All @@ -160,6 +234,38 @@ export default defineComponent({
processedVideoSearchQuery() {
return this.videoSearchQuery.trim().toLowerCase()
},
sortBySelectNames() {
return this.sortByValues.map((k) => {
switch (k) {
case SORT_BY_VALUES.Custom:
return this.isUserPlaylistRequested ? this.$t('Playlist.Sort By.Custom') : this.$t('Playlist.Sort By.Default')
case SORT_BY_VALUES.CustomDescending:
return this.isUserPlaylistRequested ? this.$t('Playlist.Sort By.CustomDescending') : this.$t('Playlist.Sort By.DefaultDescending')
case SORT_BY_VALUES.DateAddedNewest:
return this.$t('Playlist.Sort By.DateAddedNewest')
case SORT_BY_VALUES.DateAddedOldest:
return this.$t('Playlist.Sort By.DateAddedOldest')
case SORT_BY_VALUES.DatePublishedNewest:
return this.$t('Playlist.Sort By.DatePublishedNewest')
case SORT_BY_VALUES.DatePublishedOldest:
return this.$t('Playlist.Sort By.DatePublishedOldest')
case SORT_BY_VALUES.VideoTitleAscending:
return this.$t('Playlist.Sort By.VideoTitleAscending')
case SORT_BY_VALUES.VideoTitleDescending:
return this.$t('Playlist.Sort By.VideoTitleDescending')
case SORT_BY_VALUES.ChannelNameAscending:
return this.$t('Playlist.Sort By.ChannelNameAscending')
case SORT_BY_VALUES.ChannelNameDescending:
return this.$t('Playlist.Sort By.ChannelNameDescending')
default:
console.error(`Unknown sort: ${k}`)
return k
}
})
},
sortBySelectValues() {
return this.sortByValues
},
},
watch: {
$route () {
Expand Down Expand Up @@ -477,9 +583,18 @@ export default defineComponent({
}
},

updateSortOrder: function (sortOrder) {
if (this.isUserPlaylistRequested) {
this.updateUserPlaylistSortOrder(sortOrder)
} else {
this.localSortOrder = sortOrder
}
},

...mapActions([
'updateSubscriptionDetails',
'updatePlaylist',
'updateUserPlaylistSortOrder',
'removeVideo',
]),

Expand Down
16 changes: 12 additions & 4 deletions src/renderer/views/Playlist/Playlist.vue
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@
<template
v-if="playlistItems.length > 0"
>
<ft-select
class="sortSelect"
:value="sortOrder"
:select-names="sortBySelectNames"
:select-values="sortBySelectValues"
:placeholder="$t('Playlist.Sort By.Sort By')"
@change="updateSortOrder($event)"
/>
<template
v-if="visiblePlaylistItems.length > 0"
>
Expand All @@ -64,13 +72,13 @@
appearance="result"
:always-show-add-to-playlist-button="true"
:quick-bookmark-button-enabled="quickBookmarkButtonEnabled"
:can-move-video-up="index > 0 && !playlistInVideoSearchMode"
:can-move-video-down="index < playlistItems.length - 1 && !playlistInVideoSearchMode"
:can-move-video-up="index > 0 && !playlistInVideoSearchMode && isSortOrderCustom"
:can-move-video-down="index < playlistItems.length - 1 && !playlistInVideoSearchMode && isSortOrderCustom"
:can-remove-from-playlist="true"
:video-index="playlistInVideoSearchMode ? playlistItems.findIndex(i => i === item) : index"
:initial-visible-state="index < 10"
@move-video-up="moveVideoUp(item.videoId, item.playlistItemId)"
@move-video-down="moveVideoDown(item.videoId, item.playlistItemId)"
@move-video-up="sortOrder !== 'custom_descending' ? moveVideoUp(item.videoId, item.playlistItemId) : moveVideoDown(item.videoId, item.playlistItemId)"
@move-video-down="sortOrder !== 'custom_descending' ? moveVideoDown(item.videoId, item.playlistItemId) : moveVideoUp(item.videoId, item.playlistItemId)"
@remove-from-playlist="removeVideoFromPlaylist(item.videoId, item.playlistItemId)"
/>
</transition-group>
Expand Down
15 changes: 14 additions & 1 deletion static/locales/en-US.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,6 @@ User Playlists:

LatestPlayedFirst: 'Recently Played'
EarliestPlayedFirst: 'Earliest Played'

SinglePlaylistView:
Search for Videos: Search for Videos

Expand Down Expand Up @@ -871,6 +870,20 @@ Playlist:
View: View
Views: Views
Last Updated On: Last Updated On
Sort By:
Sort By: Sort By
Custom: Custom
CustomDescending: Custom (descending)
Default: Default
DefaultDescending: Default (descending)
DateAddedNewest: Date added (newest)
DateAddedOldest: Date added (oldest)
DatePublishedNewest: Date published (newest)
DatePublishedOldest: Date published (oldest)
VideoTitleAscending: Title (A-Z)
VideoTitleDescending: Title (Z-A)
ChannelNameAscending: Author (A-Z)
ChannelNameDescending: Author (Z-A)

# On Video Watch Page
#* Published
Expand Down

0 comments on commit b1b1df7

Please sign in to comment.