Add thread sort settings (#1475)
* Add thread sorting preferences * UI tweaks * Tweak settings * Tune the copy
This commit is contained in:
parent
9c4374f66a
commit
da8499c881
9 changed files with 256 additions and 13 deletions
|
@ -241,7 +241,7 @@ export class PostThreadModel {
|
|||
res.data.thread as AppBskyFeedDefs.ThreadViewPost,
|
||||
thread.uri,
|
||||
)
|
||||
sortThread(thread)
|
||||
sortThread(thread, this.rootStore.preferences)
|
||||
this.thread = thread
|
||||
}
|
||||
}
|
||||
|
@ -263,11 +263,16 @@ function pruneReplies(post: MaybePost) {
|
|||
}
|
||||
}
|
||||
|
||||
interface SortSettings {
|
||||
threadDefaultSort: string
|
||||
threadFollowedUsersFirst: boolean
|
||||
}
|
||||
|
||||
type MaybeThreadItem =
|
||||
| PostThreadItemModel
|
||||
| AppBskyFeedDefs.NotFoundPost
|
||||
| AppBskyFeedDefs.BlockedPost
|
||||
function sortThread(item: MaybeThreadItem) {
|
||||
function sortThread(item: MaybeThreadItem, opts: SortSettings) {
|
||||
if ('notFound' in item) {
|
||||
return
|
||||
}
|
||||
|
@ -296,13 +301,31 @@ function sortThread(item: MaybeThreadItem) {
|
|||
if (modScore(a.moderation) !== modScore(b.moderation)) {
|
||||
return modScore(a.moderation) - modScore(b.moderation)
|
||||
}
|
||||
if (a.post.likeCount === b.post.likeCount) {
|
||||
return b.post.indexedAt.localeCompare(a.post.indexedAt) // newest
|
||||
} else {
|
||||
return (b.post.likeCount || 0) - (a.post.likeCount || 0) // most likes
|
||||
if (opts.threadFollowedUsersFirst) {
|
||||
const af = a.post.author.viewer?.following
|
||||
const bf = b.post.author.viewer?.following
|
||||
if (af && !bf) {
|
||||
return -1
|
||||
} else if (!af && bf) {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
if (opts.threadDefaultSort === 'oldest') {
|
||||
return a.post.indexedAt.localeCompare(b.post.indexedAt)
|
||||
} else if (opts.threadDefaultSort === 'newest') {
|
||||
return b.post.indexedAt.localeCompare(a.post.indexedAt)
|
||||
} else if (opts.threadDefaultSort === 'most-likes') {
|
||||
if (a.post.likeCount === b.post.likeCount) {
|
||||
return b.post.indexedAt.localeCompare(a.post.indexedAt) // newest
|
||||
} else {
|
||||
return (b.post.likeCount || 0) - (a.post.likeCount || 0) // most likes
|
||||
}
|
||||
} else if (opts.threadDefaultSort === 'random') {
|
||||
return 0.5 - Math.random() // this is vaguely criminal but we can get away with it
|
||||
}
|
||||
return b.post.indexedAt.localeCompare(a.post.indexedAt)
|
||||
})
|
||||
item.replies.forEach(reply => sortThread(reply))
|
||||
item.replies.forEach(reply => sortThread(reply, opts))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ const VISIBILITY_VALUES = ['ignore', 'warn', 'hide']
|
|||
const DEFAULT_LANG_CODES = (deviceLocales || [])
|
||||
.concat(['en', 'ja', 'pt', 'de'])
|
||||
.slice(0, 6)
|
||||
const THREAD_SORT_VALUES = ['oldest', 'newest', 'most-likes', 'random']
|
||||
|
||||
export class LabelPreferencesModel {
|
||||
nsfw: LabelPreference = 'hide'
|
||||
|
@ -55,6 +56,8 @@ export class PreferencesModel {
|
|||
homeFeedRepostsEnabled: boolean = true
|
||||
homeFeedQuotePostsEnabled: boolean = true
|
||||
homeFeedMergeFeedEnabled: boolean = false
|
||||
threadDefaultSort: string = 'oldest'
|
||||
threadFollowedUsersFirst: boolean = true
|
||||
requireAltTextEnabled: boolean = false
|
||||
|
||||
// used to linearize async modifications to state
|
||||
|
@ -86,6 +89,8 @@ export class PreferencesModel {
|
|||
homeFeedRepostsEnabled: this.homeFeedRepostsEnabled,
|
||||
homeFeedQuotePostsEnabled: this.homeFeedQuotePostsEnabled,
|
||||
homeFeedMergeFeedEnabled: this.homeFeedMergeFeedEnabled,
|
||||
threadDefaultSort: this.threadDefaultSort,
|
||||
threadFollowedUsersFirst: this.threadFollowedUsersFirst,
|
||||
requireAltTextEnabled: this.requireAltTextEnabled,
|
||||
}
|
||||
}
|
||||
|
@ -189,6 +194,21 @@ export class PreferencesModel {
|
|||
) {
|
||||
this.homeFeedMergeFeedEnabled = v.homeFeedMergeFeedEnabled
|
||||
}
|
||||
// check if thread sort order is set in preferences, then hydrate
|
||||
if (
|
||||
hasProp(v, 'threadDefaultSort') &&
|
||||
typeof v.threadDefaultSort === 'string' &&
|
||||
THREAD_SORT_VALUES.includes(v.threadDefaultSort)
|
||||
) {
|
||||
this.threadDefaultSort = v.threadDefaultSort
|
||||
}
|
||||
// check if tread followed-users-first is enabled in preferences, then hydrate
|
||||
if (
|
||||
hasProp(v, 'threadFollowedUsersFirst') &&
|
||||
typeof v.threadFollowedUsersFirst === 'boolean'
|
||||
) {
|
||||
this.threadFollowedUsersFirst = v.threadFollowedUsersFirst
|
||||
}
|
||||
// check if requiring alt text is enabled in preferences, then hydrate
|
||||
if (
|
||||
hasProp(v, 'requireAltTextEnabled') &&
|
||||
|
@ -494,6 +514,16 @@ export class PreferencesModel {
|
|||
this.homeFeedMergeFeedEnabled = !this.homeFeedMergeFeedEnabled
|
||||
}
|
||||
|
||||
setThreadDefaultSort(v: string) {
|
||||
if (THREAD_SORT_VALUES.includes(v)) {
|
||||
this.threadDefaultSort = v
|
||||
}
|
||||
}
|
||||
|
||||
toggleThreadFollowedUsersFirst() {
|
||||
this.threadFollowedUsersFirst = !this.threadFollowedUsersFirst
|
||||
}
|
||||
|
||||
toggleRequireAltTextEnabled() {
|
||||
this.requireAltTextEnabled = !this.requireAltTextEnabled
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue