diff options
Diffstat (limited to 'src/state/models')
-rw-r--r-- | src/state/models/content/post-thread.ts | 37 | ||||
-rw-r--r-- | src/state/models/ui/preferences.ts | 30 |
2 files changed, 60 insertions, 7 deletions
diff --git a/src/state/models/content/post-thread.ts b/src/state/models/content/post-thread.ts index 7e3650948..2d3a3d64a 100644 --- a/src/state/models/content/post-thread.ts +++ b/src/state/models/content/post-thread.ts @@ -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)) } } diff --git a/src/state/models/ui/preferences.ts b/src/state/models/ui/preferences.ts index 3790b3a92..03f08bc1b 100644 --- a/src/state/models/ui/preferences.ts +++ b/src/state/models/ui/preferences.ts @@ -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 } |