-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Sort videos within playlist #4921
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
c07dfb9
5c03d60
d91792a
318fe08
9db7e48
95a6403
b2b77eb
10aac78
8fd5055
a101de7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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, | ||
|
|
@@ -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', | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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: { | ||
|
|
@@ -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) { | ||
|
|
@@ -64,6 +80,7 @@ export default defineComponent({ | |
| videoSearchQuery: '', | ||
|
|
||
| promptOpen: false, | ||
| localSortOrder: SORT_BY_VALUES.Custom | ||
| } | ||
| }, | ||
| computed: { | ||
|
|
@@ -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('_', '-') | ||
| }, | ||
|
|
@@ -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) { | ||
|
|
@@ -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 () { | ||
|
|
@@ -480,6 +569,7 @@ export default defineComponent({ | |
| ...mapActions([ | ||
| 'updateSubscriptionDetails', | ||
| 'updatePlaylist', | ||
| 'updateUserPlaylistSortOrder', | ||
| 'removeVideo', | ||
| ]), | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -185,7 +185,6 @@ User Playlists: | |
|
|
||
| LatestPlayedFirst: 'Recently Played' | ||
| EarliestPlayedFirst: 'Earliest Played' | ||
|
|
||
| SinglePlaylistView: | ||
| Search for Videos: Search for Videos | ||
|
|
||
|
|
@@ -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) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I guess this means "user specified" order |
||
| Default: Default | ||
| DefaultDescending: Default (descending) | ||
|
kommunarr marked this conversation as resolved.
Outdated
|
||
| DateAddedNewest: Date added (newest) | ||
| DateAddedOldest: Date added (oldest) | ||
| DatePublishedNewest: Date published (newest) | ||
| DatePublishedOldest: Date published (oldest) | ||
|
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 | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.