diff --git a/src/renderer/components/watch-video-playlist/watch-video-playlist.js b/src/renderer/components/watch-video-playlist/watch-video-playlist.js index 535ad18a16b0c..e9fad636e8999 100644 --- a/src/renderer/components/watch-video-playlist/watch-video-playlist.js +++ b/src/renderer/components/watch-video-playlist/watch-video-playlist.js @@ -10,6 +10,7 @@ import { untilEndOfLocalPlayList, } from '../../helpers/api/local' import { invidiousGetPlaylistInfo } from '../../helpers/api/invidious' +import { getSortedPlaylistItems, SORT_BY_VALUES } from '../../helpers/playlists' export default defineComponent({ name: 'WatchVideoPlaylist', @@ -66,7 +67,9 @@ export default defineComponent({ backendFallback: function () { return this.$store.getters.getBackendFallback }, - + currentLocale: function () { + return this.$i18n.locale.replace('_', '-') + }, isUserPlaylist: function () { return this.playlistType === 'user' }, @@ -134,6 +137,12 @@ export default defineComponent({ }, } }, + userPlaylistSortOrder: function () { + return this.$store.getters.getUserPlaylistSortOrder + }, + sortOrder: function () { + return this.isUserPlaylist ? this.userPlaylistSortOrder : SORT_BY_VALUES.Custom + }, }, watch: { userPlaylistsReady: function() { @@ -495,11 +504,7 @@ export default defineComponent({ this.prevVideoBeforeDeletion = this.playlistItems[targetVideoIndex] } - let playlistItems = playlist.videos - if (this.reversePlaylist) { - playlistItems = playlistItems.toReversed() - } - this.playlistItems = playlistItems + this.playlistItems = getSortedPlaylistItems(playlist.videos, this.sortOrder, this.currentLocale, this.reversePlaylist) // grab the first video of the parsed playlit if the current video is not in either the current or parsed data // (e.g., reloading the page after the current video has already been removed from the playlist) diff --git a/src/renderer/helpers/playlists.js b/src/renderer/helpers/playlists.js new file mode 100644 index 0000000000000..5f53972f4b43d --- /dev/null +++ b/src/renderer/helpers/playlists.js @@ -0,0 +1,52 @@ +export const SORT_BY_VALUES = { + DateAddedNewest: 'date_added_descending', + DateAddedOldest: 'date_added_ascending', + AuthorAscending: 'author_ascending', + AuthorDescending: 'author_descending', + VideoTitleAscending: 'video_title_ascending', + VideoTitleDescending: 'video_title_descending', + Custom: 'custom' +} + +export function getSortedPlaylistItems(playlistItems, sortOrder, locale, reversed = false) { + if (sortOrder === SORT_BY_VALUES.Custom) { + return reversed ? playlistItems.toReversed() : playlistItems + } + + let collator + + if ( + sortOrder === SORT_BY_VALUES.VideoTitleAscending || + sortOrder === SORT_BY_VALUES.VideoTitleDescending || + sortOrder === SORT_BY_VALUES.AuthorAscending || + sortOrder === SORT_BY_VALUES.AuthorDescending + ) { + collator = new Intl.Collator([locale, 'en']) + } + + return playlistItems.toSorted((a, b) => { + const first = !reversed ? a : b + const second = !reversed ? b : a + return compareTwoPlaylistItems(first, second, sortOrder, collator) + }) +} + +function compareTwoPlaylistItems(a, b, sortOrder, collator) { + switch (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.VideoTitleAscending: + return collator.compare(a.title, b.title) + case SORT_BY_VALUES.VideoTitleDescending: + return collator.compare(b.title, a.title) + case SORT_BY_VALUES.AuthorAscending: + return collator.compare(a.author, b.author) + case SORT_BY_VALUES.AuthorDescending: + return collator.compare(b.author, a.author) + default: + console.error(`Unknown sortOrder: ${sortOrder}`) + return 0 + } +} diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js index 9e10adfe5e8e0..6a6983eb0ea78 100644 --- a/src/renderer/views/Playlist/Playlist.js +++ b/src/renderer/views/Playlist/Playlist.js @@ -22,19 +22,10 @@ import { showToast, } from '../../helpers/utils' import { invidiousGetPlaylistInfo, youtubeImageUrlToInvidious } from '../../helpers/api/invidious' +import { getSortedPlaylistItems, SORT_BY_VALUES } from '../../helpers/playlists' import packageDetails from '../../../../package.json' import { MOBILE_WIDTH_THRESHOLD, PLAYLIST_HEIGHT_FORCE_LIST_THRESHOLD } from '../../../constants' -const SORT_BY_VALUES = { - DateAddedNewest: 'date_added_descending', - DateAddedOldest: 'date_added_ascending', - AuthorAscending: 'author_ascending', - AuthorDescending: 'author_descending', - VideoTitleAscending: 'video_title_ascending', - VideoTitleDescending: 'video_title_descending', - Custom: 'custom', -} - export default defineComponent({ name: 'Playlist', components: { @@ -49,13 +40,13 @@ export default defineComponent({ 'ft-auto-load-next-page-wrapper': FtAutoLoadNextPageWrapper, }, beforeRouteLeave(to, from, next) { - if (!this.isLoading && !this.isUserPlaylistRequested && to.path.startsWith('/watch') && to.query.playlistId === this.playlistId) { + if (!this.isLoading && to.path.startsWith('/watch') && to.query.playlistId === this.playlistId) { this.setCachedPlaylist({ id: this.playlistId, title: this.playlistTitle, channelName: this.channelName, channelId: this.channelId, - items: this.playlistItems, + items: this.sortedPlaylistItems, continuationData: this.continuationData, }) } @@ -189,29 +180,7 @@ export default defineComponent({ return this.sortOrder === SORT_BY_VALUES.Custom }, sortedPlaylistItems: function () { - if (this.sortOrder === SORT_BY_VALUES.Custom) { - return this.playlistItems - } - - 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.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.sortOrder}`) - return 0 - } - }) + return getSortedPlaylistItems(this.playlistItems, this.sortOrder, this.currentLocale) }, visiblePlaylistItems: function () { if (!this.isUserPlaylistRequested) {