Skip to content
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

Respect playlist sort order in watch-video-playlist #5013

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
c07dfb9
Implement playlist sorting
kommunarr Apr 10, 2024
5c03d60
Hide sort menu for remote playlists
kommunarr Apr 10, 2024
d91792a
Remove 'Custom (descending)' sort order
kommunarr Apr 11, 2024
318fe08
Adjust sort order & align dropdown with 'More Options' button
kommunarr Apr 11, 2024
9db7e48
Make 'Latest added first' default option instead of custom
kommunarr Apr 11, 2024
95a6403
Remove unlikely-to-be-implemented 'Date published' sorting options
kommunarr Apr 11, 2024
b2b77eb
Merge branch 'development' of github.com:FreeTubeApp/FreeTube into fe…
kommunarr Apr 11, 2024
10aac78
Update to use sortOrder as main variable throughout
kommunarr Apr 11, 2024
8fd5055
Hide sort menu for playlists of length <2
kommunarr Apr 11, 2024
af09a76
Send sorted user playlist to watch-video-playlist
kommunarr Apr 13, 2024
c589aba
Merge branch 'development' of github.com:FreeTubeApp/FreeTube into fe…
kommunarr Apr 16, 2024
4028551
Merge branch 'development' of github.com:FreeTubeApp/FreeTube into fe…
kommunarr Apr 24, 2024
61a5885
Implement minor reversing optimization / cleanup
kommunarr Apr 24, 2024
1cf9f7e
Update src/renderer/helpers/playlists.js
kommunarr May 13, 2024
33399a1
Merge branch 'development' of github.com:FreeTubeApp/FreeTube into fe…
kommunarr May 22, 2024
d4124a1
Merge branch 'development' of github.com:FreeTubeApp/FreeTube into fe…
kommunarr May 22, 2024
b91d925
Change Playlist.js logic to cache user playlists, and pass the sorted…
kommunarr May 30, 2024
093c3e6
Merge branch 'development' of github.com:FreeTubeApp/FreeTube into fe…
kommunarr Jun 6, 2024
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 @@ -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',
Expand Down Expand Up @@ -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'
},
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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)
Expand Down
52 changes: 52 additions & 0 deletions src/renderer/helpers/playlists.js
Original file line number Diff line number Diff line change
@@ -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'])
Copy link
Collaborator

Choose a reason for hiding this comment

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

(Optional) I know nothing about Intl.Collator
But I would like to know if using a constant object be possible (map of locale to Collator objects lazily created)
(No idea how much it helps, if too complicated might not worth it

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'll mark it as a chore, although I'm skeptical if the access time would be considerably less than the creation time of this

}

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
}
}
39 changes: 4 additions & 35 deletions src/renderer/views/Playlist/Playlist.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand All @@ -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,
})
}
Expand Down Expand Up @@ -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) {
Expand Down