about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/screens/Settings/ThreadPreferences.tsx6
-rw-r--r--src/state/queries/post-thread.ts21
-rw-r--r--src/state/queries/preferences/const.ts2
-rw-r--r--src/state/queries/preferences/types.ts2
4 files changed, 28 insertions, 3 deletions
diff --git a/src/screens/Settings/ThreadPreferences.tsx b/src/screens/Settings/ThreadPreferences.tsx
index c27cea7de..d29daa58b 100644
--- a/src/screens/Settings/ThreadPreferences.tsx
+++ b/src/screens/Settings/ThreadPreferences.tsx
@@ -56,6 +56,12 @@ export function ThreadPreferencesScreen({}: Props) {
                 values={sortReplies ? [sortReplies] : []}
                 onChange={values => setThreadViewPrefs({sort: values[0]})}>
                 <View style={[a.gap_sm, a.flex_1]}>
+                  <Toggle.Item name="hotness" label={_(msg`Hot replies first`)}>
+                    <Toggle.Radio />
+                    <Toggle.LabelText>
+                      <Trans>Hot replies first</Trans>
+                    </Toggle.LabelText>
+                  </Toggle.Item>
                   <Toggle.Item
                     name="oldest"
                     label={_(msg`Oldest replies first`)}>
diff --git a/src/state/queries/post-thread.ts b/src/state/queries/post-thread.ts
index 93e3a5c3b..4784a9d75 100644
--- a/src/state/queries/post-thread.ts
+++ b/src/state/queries/post-thread.ts
@@ -237,7 +237,11 @@ export function sortThread(
         }
       }
 
-      if (opts.sort === 'oldest') {
+      if (opts.sort === 'hotness') {
+        const aHotness = getHotness(a.post)
+        const bHotness = getHotness(b.post)
+        return bHotness - aHotness
+      } else if (opts.sort === 'oldest') {
         return a.post.indexedAt.localeCompare(b.post.indexedAt)
       } else if (opts.sort === 'newest') {
         return b.post.indexedAt.localeCompare(a.post.indexedAt)
@@ -269,6 +273,21 @@ export function sortThread(
 // internal methods
 // =
 
+// Inspired by https://join-lemmy.org/docs/contributors/07-ranking-algo.html
+// We want to give recent comments a real chance (and not bury them deep below the fold)
+// while also surfacing well-liked comments from the past. In the future, we can explore
+// something more sophisticated, but we don't have much data on the client right now.
+function getHotness(post: AppBskyFeedDefs.PostView) {
+  const hoursAgo =
+    (new Date().getTime() - new Date(post.indexedAt).getTime()) /
+    (1000 * 60 * 60)
+  const likeCount = post.likeCount ?? 0
+  const likeOrder = Math.log(3 + likeCount)
+  const timePenaltyExponent = 1.5 + 1.5 / (1 + Math.log(1 + likeCount))
+  const timePenalty = Math.pow(hoursAgo + 2, timePenaltyExponent)
+  return likeOrder / timePenalty
+}
+
 function responseToThreadNodes(
   node: ThreadViewNode,
   depth = 0,
diff --git a/src/state/queries/preferences/const.ts b/src/state/queries/preferences/const.ts
index e07f40ec5..549f7ce29 100644
--- a/src/state/queries/preferences/const.ts
+++ b/src/state/queries/preferences/const.ts
@@ -15,7 +15,7 @@ export const DEFAULT_HOME_FEED_PREFS: UsePreferencesQueryResponse['feedViewPrefs
   }
 
 export const DEFAULT_THREAD_VIEW_PREFS: ThreadViewPreferences = {
-  sort: 'newest',
+  sort: 'hotness',
   prioritizeFollowedUsers: true,
   lab_treeViewEnabled: false,
 }
diff --git a/src/state/queries/preferences/types.ts b/src/state/queries/preferences/types.ts
index 928bb90da..8f523fcf2 100644
--- a/src/state/queries/preferences/types.ts
+++ b/src/state/queries/preferences/types.ts
@@ -22,6 +22,6 @@ export type ThreadViewPreferences = Pick<
   BskyThreadViewPreference,
   'prioritizeFollowedUsers'
 > & {
-  sort: 'oldest' | 'newest' | 'most-likes' | 'random' | string
+  sort: 'hotness' | 'oldest' | 'newest' | 'most-likes' | 'random' | string
   lab_treeViewEnabled?: boolean
 }