about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorPaul Frazee <pfrazee@gmail.com>2023-12-08 14:01:20 -0800
committerPaul Frazee <pfrazee@gmail.com>2023-12-08 14:01:20 -0800
commit565979e71f99064506af933493a118a2e22a044a (patch)
tree6193be73348fc6fb8248879efceab97e30ff353b /src
parent282879b6452b0f575369d30139d15b234f7a3f28 (diff)
parent7b686b5592a8cd01278c5c30e115385ffd676248 (diff)
downloadvoidsky-565979e71f99064506af933493a118a2e22a044a.tar.zst
Merge branch 'main' of github.com:bluesky-social/social-app into main
Diffstat (limited to 'src')
-rw-r--r--src/locale/i18n.ts3
-rw-r--r--src/locale/i18n.web.ts3
-rw-r--r--src/locale/locales/en/messages.po26
-rw-r--r--src/locale/locales/hi/messages.po28
-rw-r--r--src/state/queries/post-feed.ts177
-rw-r--r--src/view/com/modals/SwitchAccount.tsx8
-rw-r--r--src/view/screens/Profile.tsx14
7 files changed, 178 insertions, 81 deletions
diff --git a/src/locale/i18n.ts b/src/locale/i18n.ts
index 2b9be60a4..4fe3cedd6 100644
--- a/src/locale/i18n.ts
+++ b/src/locale/i18n.ts
@@ -7,10 +7,7 @@ import {messages as messagesHi} from '#/locale/locales/hi/messages'
 
 export const locales = {
   en: 'English',
-  cs: 'Česky',
-  fr: 'Français',
   hi: 'हिंदी',
-  es: 'Español',
 }
 export const defaultLocale = 'en'
 
diff --git a/src/locale/i18n.web.ts b/src/locale/i18n.web.ts
index 18b05fb8e..4e8b8d95d 100644
--- a/src/locale/i18n.web.ts
+++ b/src/locale/i18n.web.ts
@@ -5,10 +5,7 @@ import {useLanguagePrefs} from '#/state/preferences'
 
 export const locales = {
   en: 'English',
-  cs: 'Česky',
-  fr: 'Français',
   hi: 'हिंदी',
-  es: 'Español',
 }
 export const defaultLocale = 'en'
 
diff --git a/src/locale/locales/en/messages.po b/src/locale/locales/en/messages.po
index c8fde9952..8e413a545 100644
--- a/src/locale/locales/en/messages.po
+++ b/src/locale/locales/en/messages.po
@@ -827,6 +827,7 @@ msgid "Feedback"
 msgstr ""
 
 #: src/view/screens/Feeds.tsx:475
+#: src/view/screens/Profile.tsx:164
 #: src/view/shell/bottom-bar/BottomBar.tsx:168
 #: src/view/shell/desktop/LeftNav.tsx:341
 #: src/view/shell/Drawer.tsx:463
@@ -1132,6 +1133,10 @@ msgstr ""
 msgid "Liked by"
 msgstr ""
 
+#: src/view/screens/Profile.tsx:163
+msgid "Likes"
+msgstr ""
+
 #: src/view/screens/Moderation.tsx:203
 #~ msgid "Limit the visibility of my account"
 #~ msgstr ""
@@ -1148,6 +1153,7 @@ msgstr ""
 msgid "List Name"
 msgstr ""
 
+#: src/view/screens/Profile.tsx:165
 #: src/view/shell/desktop/LeftNav.tsx:381
 #: src/view/shell/Drawer.tsx:479
 #: src/view/shell/Drawer.tsx:480
@@ -1191,6 +1197,10 @@ msgstr ""
 msgid "Make sure this is where you intend to go!"
 msgstr ""
 
+#: src/view/screens/Profile.tsx:162
+msgid "Media"
+msgstr ""
+
 #: src/view/screens/Search/Search.tsx:503
 msgid "Menu"
 msgstr ""
@@ -1534,6 +1544,10 @@ msgstr ""
 msgid "Post not found"
 msgstr ""
 
+#: src/view/screens/Profile.tsx:160
+msgid "Posts"
+msgstr ""
+
 #: src/view/com/modals/LinkWarning.tsx:44
 msgid "Potentially Misleading Link"
 msgstr ""
@@ -1649,6 +1663,10 @@ msgstr ""
 msgid "Removed from list"
 msgstr ""
 
+#: src/view/screens/Profile.tsx:161
+msgid "Replies"
+msgstr ""
+
 #: src/view/screens/PreferencesHomeFeed.tsx:135
 msgid "Reply Filters"
 msgstr ""
@@ -1951,8 +1969,8 @@ msgstr ""
 msgid "Sign into"
 msgstr ""
 
-#: src/view/com/modals/SwitchAccount.tsx:60
-#: src/view/com/modals/SwitchAccount.tsx:63
+#: src/view/com/modals/SwitchAccount.tsx:64
+#: src/view/com/modals/SwitchAccount.tsx:67
 msgid "Sign out"
 msgstr ""
 
@@ -2020,7 +2038,7 @@ msgstr ""
 msgid "Support"
 msgstr ""
 
-#: src/view/com/modals/SwitchAccount.tsx:111
+#: src/view/com/modals/SwitchAccount.tsx:115
 msgid "Switch Account"
 msgstr ""
 
@@ -2421,7 +2439,7 @@ msgstr ""
 msgid "Your posts, likes, and blocks are public. Mutes are private."
 msgstr ""
 
-#: src/view/com/modals/SwitchAccount.tsx:78
+#: src/view/com/modals/SwitchAccount.tsx:82
 msgid "Your profile"
 msgstr ""
 
diff --git a/src/locale/locales/hi/messages.po b/src/locale/locales/hi/messages.po
index a075ab9c9..039b2b3b8 100644
--- a/src/locale/locales/hi/messages.po
+++ b/src/locale/locales/hi/messages.po
@@ -823,6 +823,7 @@ msgid "Feedback"
 msgstr "प्रतिक्रिया"
 
 #: src/view/screens/Feeds.tsx:475
+#: src/view/screens/Profile.tsx:164
 #: src/view/shell/bottom-bar/BottomBar.tsx:168
 #: src/view/shell/desktop/LeftNav.tsx:341
 #: src/view/shell/Drawer.tsx:463
@@ -1124,6 +1125,10 @@ msgstr "इस फ़ीड को लाइक करो"
 msgid "Liked by"
 msgstr "इन यूजर ने लाइक किया है"
 
+#: src/view/screens/Profile.tsx:163
+msgid "Likes"
+msgstr ""
+
 #: src/view/screens/Moderation.tsx:203
 #~ msgid "Limit the visibility of my account"
 #~ msgstr ""
@@ -1140,6 +1145,7 @@ msgstr "सूची अवतार"
 msgid "List Name"
 msgstr "सूची का नाम"
 
+#: src/view/screens/Profile.tsx:165
 #: src/view/shell/desktop/LeftNav.tsx:381
 #: src/view/shell/Drawer.tsx:479
 #: src/view/shell/Drawer.tsx:480
@@ -1183,6 +1189,10 @@ msgstr ""
 msgid "Make sure this is where you intend to go!"
 msgstr "यह सुनिश्चित करने के लिए कि आप कहाँ जाना चाहते हैं!"
 
+#: src/view/screens/Profile.tsx:162
+msgid "Media"
+msgstr ""
+
 #: src/view/screens/Search/Search.tsx:503
 msgid "Menu"
 msgstr "मेनू"
@@ -1526,6 +1536,10 @@ msgstr "पोस्ट भाषा"
 msgid "Post not found"
 msgstr "पोस्ट नहीं मिला"
 
+#: src/view/screens/Profile.tsx:160
+msgid "Posts"
+msgstr ""
+
 #: src/view/com/modals/LinkWarning.tsx:44
 msgid "Potentially Misleading Link"
 msgstr "शायद एक भ्रामक लिंक"
@@ -1641,6 +1655,10 @@ msgstr "इस फ़ीड को सहेजे गए फ़ीड से 
 msgid "Removed from list"
 msgstr ""
 
+#: src/view/screens/Profile.tsx:161
+msgid "Replies"
+msgstr ""
+
 #: src/view/screens/PreferencesHomeFeed.tsx:135
 msgid "Reply Filters"
 msgstr "फिल्टर"
@@ -1943,8 +1961,8 @@ msgstr "... के रूप में साइन इन करें"
 msgid "Sign into"
 msgstr "साइन इन करें"
 
-#: src/view/com/modals/SwitchAccount.tsx:60
-#: src/view/com/modals/SwitchAccount.tsx:63
+#: src/view/com/modals/SwitchAccount.tsx:64
+#: src/view/com/modals/SwitchAccount.tsx:67
 msgid "Sign out"
 msgstr "साइन आउट"
 
@@ -1993,7 +2011,7 @@ msgstr "Storybook"
 
 #: src/view/com/modals/AppealLabel.tsx:101
 msgid "Submit"
-msgstr ">>>>>>> cb8a33b6 (Fix translations)"
+msgstr ""
 
 #: src/view/screens/ProfileList.tsx:597
 msgid "Subscribe"
@@ -2012,7 +2030,7 @@ msgstr "अनुशंसित लोग"
 msgid "Support"
 msgstr "सहायता"
 
-#: src/view/com/modals/SwitchAccount.tsx:111
+#: src/view/com/modals/SwitchAccount.tsx:115
 msgid "Switch Account"
 msgstr "खाते बदलें"
 
@@ -2413,7 +2431,7 @@ msgstr ""
 msgid "Your posts, likes, and blocks are public. Mutes are private."
 msgstr "आपकी पोस्ट, पसंद और ब्लॉक सार्वजनिक हैं। म्यूट निजी हैं।।"
 
-#: src/view/com/modals/SwitchAccount.tsx:78
+#: src/view/com/modals/SwitchAccount.tsx:82
 msgid "Your profile"
 msgstr "आपकी प्रोफ़ाइल"
 
diff --git a/src/state/queries/post-feed.ts b/src/state/queries/post-feed.ts
index 9bd1dacb3..14ffeb0da 100644
--- a/src/state/queries/post-feed.ts
+++ b/src/state/queries/post-feed.ts
@@ -1,4 +1,4 @@
-import {useCallback, useEffect} from 'react'
+import React, {useCallback, useEffect} from 'react'
 import {
   AppBskyFeedDefs,
   AppBskyFeedPost,
@@ -97,6 +97,22 @@ export function usePostFeedQuery(
   const feedTuners = useFeedTuners(feedDesc)
   const moderationOpts = useModerationOpts()
   const enabled = opts?.enabled !== false && Boolean(moderationOpts)
+  const lastRun = React.useRef<{
+    data: InfiniteData<FeedPageUnselected>
+    args: typeof selectArgs
+    result: InfiniteData<FeedPage>
+  } | null>(null)
+
+  // Make sure this doesn't invalidate unless really needed.
+  const selectArgs = React.useMemo(
+    () => ({
+      feedTuners,
+      disableTuner: params?.disableTuner,
+      moderationOpts,
+      ignoreFilterFor: opts?.ignoreFilterFor,
+    }),
+    [feedTuners, params?.disableTuner, moderationOpts, opts?.ignoreFilterFor],
+  )
 
   const query = useInfiniteQuery<
     FeedPageUnselected,
@@ -147,69 +163,116 @@ export function usePostFeedQuery(
         : undefined,
     select: useCallback(
       (data: InfiniteData<FeedPageUnselected, RQPageParam>) => {
-        const tuner = params?.disableTuner
+        // If the selection depends on some data, that data should
+        // be included in the selectArgs object and read here.
+        const {feedTuners, disableTuner, moderationOpts, ignoreFilterFor} =
+          selectArgs
+
+        const tuner = disableTuner
           ? new NoopFeedTuner()
           : new FeedTuner(feedTuners)
-        return {
+
+        // Keep track of the last run and whether we can reuse
+        // some already selected pages from there.
+        let reusedPages = []
+        if (lastRun.current) {
+          const {
+            data: lastData,
+            args: lastArgs,
+            result: lastResult,
+          } = lastRun.current
+          let canReuse = true
+          for (let key in selectArgs) {
+            if (selectArgs.hasOwnProperty(key)) {
+              if ((selectArgs as any)[key] !== (lastArgs as any)[key]) {
+                // Can't do reuse anything if any input has changed.
+                canReuse = false
+                break
+              }
+            }
+          }
+          if (canReuse) {
+            for (let i = 0; i < data.pages.length; i++) {
+              if (data.pages[i] && lastData.pages[i] === data.pages[i]) {
+                reusedPages.push(lastResult.pages[i])
+                // Keep the tuner in sync so that the end result is deterministic.
+                tuner.tune(lastData.pages[i].feed)
+                continue
+              }
+              // Stop as soon as pages stop matching up.
+              break
+            }
+          }
+        }
+
+        const result = {
           pageParams: data.pageParams,
-          pages: data.pages.map(page => ({
-            api: page.api,
-            tuner,
-            cursor: page.cursor,
-            slices: tuner
-              .tune(page.feed)
-              .map(slice => {
-                const moderations = slice.items.map(item =>
-                  moderatePost(item.post, moderationOpts!),
-                )
-
-                // apply moderation filter
-                for (let i = 0; i < slice.items.length; i++) {
-                  if (
-                    moderations[i]?.content.filter &&
-                    slice.items[i].post.author.did !== opts?.ignoreFilterFor
-                  ) {
-                    return undefined
+          pages: [
+            ...reusedPages,
+            ...data.pages.slice(reusedPages.length).map(page => ({
+              api: page.api,
+              tuner,
+              cursor: page.cursor,
+              slices: tuner
+                .tune(page.feed)
+                .map(slice => {
+                  const moderations = slice.items.map(item =>
+                    moderatePost(item.post, moderationOpts!),
+                  )
+
+                  // apply moderation filter
+                  for (let i = 0; i < slice.items.length; i++) {
+                    if (
+                      moderations[i]?.content.filter &&
+                      slice.items[i].post.author.did !== ignoreFilterFor
+                    ) {
+                      return undefined
+                    }
                   }
-                }
-
-                return {
-                  _reactKey: slice._reactKey,
-                  rootUri: slice.rootItem.post.uri,
-                  isThread:
-                    slice.items.length > 1 &&
-                    slice.items.every(
-                      item =>
-                        item.post.author.did === slice.items[0].post.author.did,
-                    ),
-                  items: slice.items
-                    .map((item, i) => {
-                      if (
-                        AppBskyFeedPost.isRecord(item.post.record) &&
-                        AppBskyFeedPost.validateRecord(item.post.record).success
-                      ) {
-                        return {
-                          _reactKey: `${slice._reactKey}-${i}`,
-                          uri: item.post.uri,
-                          post: item.post,
-                          record: item.post.record,
-                          reason:
-                            i === 0 && slice.source
-                              ? slice.source
-                              : item.reason,
-                          moderation: moderations[i],
+
+                  return {
+                    _reactKey: slice._reactKey,
+                    rootUri: slice.rootItem.post.uri,
+                    isThread:
+                      slice.items.length > 1 &&
+                      slice.items.every(
+                        item =>
+                          item.post.author.did ===
+                          slice.items[0].post.author.did,
+                      ),
+                    items: slice.items
+                      .map((item, i) => {
+                        if (
+                          AppBskyFeedPost.isRecord(item.post.record) &&
+                          AppBskyFeedPost.validateRecord(item.post.record)
+                            .success
+                        ) {
+                          return {
+                            _reactKey: `${slice._reactKey}-${i}`,
+                            uri: item.post.uri,
+                            post: item.post,
+                            record: item.post.record,
+                            reason:
+                              i === 0 && slice.source
+                                ? slice.source
+                                : item.reason,
+                            moderation: moderations[i],
+                          }
                         }
-                      }
-                      return undefined
-                    })
-                    .filter(Boolean) as FeedPostSliceItem[],
-                }
-              })
-              .filter(Boolean) as FeedPostSlice[],
-          })),
+                        return undefined
+                      })
+                      .filter(Boolean) as FeedPostSliceItem[],
+                  }
+                })
+                .filter(Boolean) as FeedPostSlice[],
+            })),
+          ],
         }
+        // Save for memoization.
+        lastRun.current = {data, result, args: selectArgs}
+        return result
       },
-      [feedTuners, params?.disableTuner, moderationOpts, opts?.ignoreFilterFor],
+      [selectArgs /* Don't change. Everything needs to go into selectArgs. */],
     ),
   })
 
diff --git a/src/view/com/modals/SwitchAccount.tsx b/src/view/com/modals/SwitchAccount.tsx
index 38e1ce1e0..37691e717 100644
--- a/src/view/com/modals/SwitchAccount.tsx
+++ b/src/view/com/modals/SwitchAccount.tsx
@@ -20,6 +20,7 @@ import {Trans, msg} from '@lingui/macro'
 import {useLingui} from '@lingui/react'
 import {useSession, useSessionApi, SessionAccount} from '#/state/session'
 import {useProfileQuery} from '#/state/queries/profile'
+import {useCloseAllActiveElements} from '#/state/util'
 
 export const snapPoints = ['40%', '90%']
 
@@ -32,11 +33,14 @@ function SwitchAccountCard({account}: {account: SessionAccount}) {
   const {data: profile} = useProfileQuery({did: account.did})
   const isCurrentAccount = account.did === currentAccount?.did
   const {onPressSwitchAccount} = useAccountSwitcher()
+  const closeAllActiveElements = useCloseAllActiveElements()
 
   const onPressSignout = React.useCallback(() => {
     track('Settings:SignOutButtonClicked')
-    logout()
-  }, [track, logout])
+    closeAllActiveElements()
+    // needs to be in timeout or the modal re-opens
+    setTimeout(() => logout(), 0)
+  }, [track, logout, closeAllActiveElements])
 
   const contents = (
     <View style={[pal.view, styles.linkCard]}>
diff --git a/src/view/screens/Profile.tsx b/src/view/screens/Profile.tsx
index 21353e5d3..ae5270386 100644
--- a/src/view/screens/Profile.tsx
+++ b/src/view/screens/Profile.tsx
@@ -157,14 +157,14 @@ function ProfileScreenLoaded({
   const showListsTab = hasSession && (isMe || extraInfoQuery.data?.hasLists)
   const sectionTitles = useMemo<string[]>(() => {
     return [
-      'Posts',
-      showRepliesTab ? 'Replies' : undefined,
-      'Media',
-      showLikesTab ? 'Likes' : undefined,
-      showFeedsTab ? 'Feeds' : undefined,
-      showListsTab ? 'Lists' : undefined,
+      _(msg`Posts`),
+      showRepliesTab ? _(msg`Replies`) : undefined,
+      _(msg`Media`),
+      showLikesTab ? _(msg`Likes`) : undefined,
+      showFeedsTab ? _(msg`Feeds`) : undefined,
+      showListsTab ? _(msg`Lists`) : undefined,
     ].filter(Boolean) as string[]
-  }, [showRepliesTab, showLikesTab, showFeedsTab, showListsTab])
+  }, [showRepliesTab, showLikesTab, showFeedsTab, showListsTab, _])
 
   let nextIndex = 0
   const postsIndex = nextIndex++