Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 () {
Comment thread
This conversation was marked as resolved.
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
100 changes: 95 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,20 @@ 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',
// TODO: store video.published for user playlists
// DatePublishedNewest: 'date_published_newest',
// DatePublishedOldest: 'date_published_oldest',

@absidue absidue Apr 11, 2024

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to implement this, you'll have to keep in mind that shorts don't have a published date on the shorts channel tab or in shorts only playlists (not returned in youtube's response, thats's why we always use RSS on the shorts tab on the subscriptions page), so if someone were to add a video to a playlist from there, it would make it impossible to sort by published. Also the Invidious API never returns published dates inside playlists, so if someone were to copy a playlist while using the Invidious API, the published dates would be missing for all videos.

For the watch history we just don't store the published date if it isn't available, but we also don't have any sorting functionality that would depend on it.

Also unlike the watch history where marking as watched from a list is probably quite uncommon (most people probably let the watch page do it automatically), adding to a playlist from a list is probably a lot more common (especially the quick bookmark).

TL;DR: I don't think we should even attempt to support it, due to all of the situations where it wouldn't be possible.

@kommunarr kommunarr Apr 11, 2024

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this context absidue. Just removed the code for these.

VideoTitleAscending: 'video_title_ascending',
VideoTitleDescending: 'video_title_descending',
AuthorAscending: 'author_ascending',
AuthorDescending: 'author_descending',
}

export default defineComponent({
name: 'Playlist',
components: {
Expand All @@ -23,7 +38,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 +80,7 @@ export default defineComponent({
videoSearchQuery: '',

promptOpen: false,
localSortOrder: SORT_BY_VALUES.Custom
}
},
computed: {
Expand All @@ -76,6 +93,9 @@ export default defineComponent({
currentInvidiousInstance: function () {
return this.$store.getters.getCurrentInvidiousInstance
},
userPlaylistSortOrder: function () {
return this.$store.getters.getUserPlaylistSortOrder
},
currentLocale: function () {
return this.$i18n.locale.replace('_', '-')
},
Expand Down Expand Up @@ -138,17 +158,54 @@ 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() {
return Object.values(SORT_BY_VALUES)
},
isSortOrderCustom() {
return this.userPlaylistSortOrder === SORT_BY_VALUES.Custom || this.userPlaylistSortOrder === SORT_BY_VALUES.CustomDescending
},
sortedPlaylistItems: function () {
if (this.userPlaylistSortOrder === SORT_BY_VALUES.Custom) {
return this.playlistItems
} else if (this.userPlaylistSortOrder === SORT_BY_VALUES.CustomDescending) {
return this.playlistItems.toReversed()
}

return this.playlistItems.toSorted((a, b) => {
switch (this.userPlaylistSortOrder) {
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.AuthorAscending:
return a.author.localeCompare(b.author, this.currentLocale)
case SORT_BY_VALUES.AuthorDescending:
return b.author.localeCompare(a.author, this.currentLocale)
default:
console.error(`Unknown sortOrder: ${this.userPlaylistSortOrder}`)
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 +217,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.$t('Playlist.Sort By.Custom')
case SORT_BY_VALUES.CustomDescending:
return this.$t('Playlist.Sort By.CustomDescending')
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.AuthorAscending:
return this.$t('Playlist.Sort By.AuthorAscending')
case SORT_BY_VALUES.AuthorDescending:
return this.$t('Playlist.Sort By.AuthorDescending')
default:
console.error(`Unknown sort: ${k}`)
return k
}
})
},
sortBySelectValues() {
return this.sortByValues
},
},
watch: {
$route () {
Expand Down Expand Up @@ -480,6 +569,7 @@ export default defineComponent({
...mapActions([
'updateSubscriptionDetails',
'updatePlaylist',
'updateUserPlaylistSortOrder',
'removeVideo',
]),

Expand Down
17 changes: 13 additions & 4 deletions src/renderer/views/Playlist/Playlist.vue
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@
<template
v-if="playlistItems.length > 0"
>
<ft-select
v-if="isUserPlaylistRequested"
class="sortSelect"
:value="userPlaylistSortOrder"
:select-names="sortBySelectNames"
:select-values="sortBySelectValues"
:placeholder="$t('Playlist.Sort By.Sort By')"
@change="updateUserPlaylistSortOrder"
/>
<template
v-if="visiblePlaylistItems.length > 0"
>
Expand All @@ -64,13 +73,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="userPlaylistSortOrder !== 'custom_descending' ? moveVideoUp(item.videoId, item.playlistItemId) : moveVideoDown(item.videoId, item.playlistItemId)"
@move-video-down="userPlaylistSortOrder !== '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)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Custom already sound a bit weird to me
Custom (descending) makes it even more weird

I guess this means "user specified" order
User-defined? (Suggest a better if you can

Default: Default
DefaultDescending: Default (descending)
Comment thread
kommunarr marked this conversation as resolved.
Outdated
DateAddedNewest: Date added (newest)
DateAddedOldest: Date added (oldest)
DatePublishedNewest: Date published (newest)
DatePublishedOldest: Date published (oldest)
Comment thread
kommunarr marked this conversation as resolved.
Outdated
VideoTitleAscending: Title (A-Z)
VideoTitleDescending: Title (Z-A)
AuthorAscending: Author (A-Z)
AuthorDescending: Author (Z-A)

# On Video Watch Page
#* Published
Expand Down