Merge branch 'main' of github.com:bluesky-social/social-app into main

zio/stable
Paul Frazee 2023-12-08 14:01:20 -08:00
commit 565979e71f
8 changed files with 181 additions and 84 deletions

View File

@ -1,6 +1,6 @@
/** @type {import('@lingui/conf').LinguiConfig} */ /** @type {import('@lingui/conf').LinguiConfig} */
module.exports = { module.exports = {
locales: ['en', 'cs', 'fr', 'hi', 'es'], locales: ['en', 'hi'],
catalogs: [ catalogs: [
{ {
path: '<rootDir>/src/locale/locales/{locale}/messages', path: '<rootDir>/src/locale/locales/{locale}/messages',

View File

@ -7,10 +7,7 @@ import {messages as messagesHi} from '#/locale/locales/hi/messages'
export const locales = { export const locales = {
en: 'English', en: 'English',
cs: 'Česky',
fr: 'Français',
hi: 'हिंदी', hi: 'हिंदी',
es: 'Español',
} }
export const defaultLocale = 'en' export const defaultLocale = 'en'

View File

@ -5,10 +5,7 @@ import {useLanguagePrefs} from '#/state/preferences'
export const locales = { export const locales = {
en: 'English', en: 'English',
cs: 'Česky',
fr: 'Français',
hi: 'हिंदी', hi: 'हिंदी',
es: 'Español',
} }
export const defaultLocale = 'en' export const defaultLocale = 'en'

View File

@ -827,6 +827,7 @@ msgid "Feedback"
msgstr "" msgstr ""
#: src/view/screens/Feeds.tsx:475 #: src/view/screens/Feeds.tsx:475
#: src/view/screens/Profile.tsx:164
#: src/view/shell/bottom-bar/BottomBar.tsx:168 #: src/view/shell/bottom-bar/BottomBar.tsx:168
#: src/view/shell/desktop/LeftNav.tsx:341 #: src/view/shell/desktop/LeftNav.tsx:341
#: src/view/shell/Drawer.tsx:463 #: src/view/shell/Drawer.tsx:463
@ -1132,6 +1133,10 @@ msgstr ""
msgid "Liked by" msgid "Liked by"
msgstr "" msgstr ""
#: src/view/screens/Profile.tsx:163
msgid "Likes"
msgstr ""
#: src/view/screens/Moderation.tsx:203 #: src/view/screens/Moderation.tsx:203
#~ msgid "Limit the visibility of my account" #~ msgid "Limit the visibility of my account"
#~ msgstr "" #~ msgstr ""
@ -1148,6 +1153,7 @@ msgstr ""
msgid "List Name" msgid "List Name"
msgstr "" msgstr ""
#: src/view/screens/Profile.tsx:165
#: src/view/shell/desktop/LeftNav.tsx:381 #: src/view/shell/desktop/LeftNav.tsx:381
#: src/view/shell/Drawer.tsx:479 #: src/view/shell/Drawer.tsx:479
#: src/view/shell/Drawer.tsx:480 #: src/view/shell/Drawer.tsx:480
@ -1191,6 +1197,10 @@ msgstr ""
msgid "Make sure this is where you intend to go!" msgid "Make sure this is where you intend to go!"
msgstr "" msgstr ""
#: src/view/screens/Profile.tsx:162
msgid "Media"
msgstr ""
#: src/view/screens/Search/Search.tsx:503 #: src/view/screens/Search/Search.tsx:503
msgid "Menu" msgid "Menu"
msgstr "" msgstr ""
@ -1534,6 +1544,10 @@ msgstr ""
msgid "Post not found" msgid "Post not found"
msgstr "" msgstr ""
#: src/view/screens/Profile.tsx:160
msgid "Posts"
msgstr ""
#: src/view/com/modals/LinkWarning.tsx:44 #: src/view/com/modals/LinkWarning.tsx:44
msgid "Potentially Misleading Link" msgid "Potentially Misleading Link"
msgstr "" msgstr ""
@ -1649,6 +1663,10 @@ msgstr ""
msgid "Removed from list" msgid "Removed from list"
msgstr "" msgstr ""
#: src/view/screens/Profile.tsx:161
msgid "Replies"
msgstr ""
#: src/view/screens/PreferencesHomeFeed.tsx:135 #: src/view/screens/PreferencesHomeFeed.tsx:135
msgid "Reply Filters" msgid "Reply Filters"
msgstr "" msgstr ""
@ -1951,8 +1969,8 @@ msgstr ""
msgid "Sign into" msgid "Sign into"
msgstr "" msgstr ""
#: src/view/com/modals/SwitchAccount.tsx:60 #: src/view/com/modals/SwitchAccount.tsx:64
#: src/view/com/modals/SwitchAccount.tsx:63 #: src/view/com/modals/SwitchAccount.tsx:67
msgid "Sign out" msgid "Sign out"
msgstr "" msgstr ""
@ -2020,7 +2038,7 @@ msgstr ""
msgid "Support" msgid "Support"
msgstr "" msgstr ""
#: src/view/com/modals/SwitchAccount.tsx:111 #: src/view/com/modals/SwitchAccount.tsx:115
msgid "Switch Account" msgid "Switch Account"
msgstr "" msgstr ""
@ -2421,7 +2439,7 @@ msgstr ""
msgid "Your posts, likes, and blocks are public. Mutes are private." msgid "Your posts, likes, and blocks are public. Mutes are private."
msgstr "" msgstr ""
#: src/view/com/modals/SwitchAccount.tsx:78 #: src/view/com/modals/SwitchAccount.tsx:82
msgid "Your profile" msgid "Your profile"
msgstr "" msgstr ""

View File

@ -823,6 +823,7 @@ msgid "Feedback"
msgstr "प्रतिक्रिया" msgstr "प्रतिक्रिया"
#: src/view/screens/Feeds.tsx:475 #: src/view/screens/Feeds.tsx:475
#: src/view/screens/Profile.tsx:164
#: src/view/shell/bottom-bar/BottomBar.tsx:168 #: src/view/shell/bottom-bar/BottomBar.tsx:168
#: src/view/shell/desktop/LeftNav.tsx:341 #: src/view/shell/desktop/LeftNav.tsx:341
#: src/view/shell/Drawer.tsx:463 #: src/view/shell/Drawer.tsx:463
@ -1124,6 +1125,10 @@ msgstr "इस फ़ीड को लाइक करो"
msgid "Liked by" msgid "Liked by"
msgstr "इन यूजर ने लाइक किया है" msgstr "इन यूजर ने लाइक किया है"
#: src/view/screens/Profile.tsx:163
msgid "Likes"
msgstr ""
#: src/view/screens/Moderation.tsx:203 #: src/view/screens/Moderation.tsx:203
#~ msgid "Limit the visibility of my account" #~ msgid "Limit the visibility of my account"
#~ msgstr "" #~ msgstr ""
@ -1140,6 +1145,7 @@ msgstr "सूची अवतार"
msgid "List Name" msgid "List Name"
msgstr "सूची का नाम" msgstr "सूची का नाम"
#: src/view/screens/Profile.tsx:165
#: src/view/shell/desktop/LeftNav.tsx:381 #: src/view/shell/desktop/LeftNav.tsx:381
#: src/view/shell/Drawer.tsx:479 #: src/view/shell/Drawer.tsx:479
#: src/view/shell/Drawer.tsx:480 #: src/view/shell/Drawer.tsx:480
@ -1183,6 +1189,10 @@ msgstr ""
msgid "Make sure this is where you intend to go!" msgid "Make sure this is where you intend to go!"
msgstr "यह सुनिश्चित करने के लिए कि आप कहाँ जाना चाहते हैं!" msgstr "यह सुनिश्चित करने के लिए कि आप कहाँ जाना चाहते हैं!"
#: src/view/screens/Profile.tsx:162
msgid "Media"
msgstr ""
#: src/view/screens/Search/Search.tsx:503 #: src/view/screens/Search/Search.tsx:503
msgid "Menu" msgid "Menu"
msgstr "मेनू" msgstr "मेनू"
@ -1526,6 +1536,10 @@ msgstr "पोस्ट भाषा"
msgid "Post not found" msgid "Post not found"
msgstr "पोस्ट नहीं मिला" msgstr "पोस्ट नहीं मिला"
#: src/view/screens/Profile.tsx:160
msgid "Posts"
msgstr ""
#: src/view/com/modals/LinkWarning.tsx:44 #: src/view/com/modals/LinkWarning.tsx:44
msgid "Potentially Misleading Link" msgid "Potentially Misleading Link"
msgstr "शायद एक भ्रामक लिंक" msgstr "शायद एक भ्रामक लिंक"
@ -1641,6 +1655,10 @@ msgstr "इस फ़ीड को सहेजे गए फ़ीड से
msgid "Removed from list" msgid "Removed from list"
msgstr "" msgstr ""
#: src/view/screens/Profile.tsx:161
msgid "Replies"
msgstr ""
#: src/view/screens/PreferencesHomeFeed.tsx:135 #: src/view/screens/PreferencesHomeFeed.tsx:135
msgid "Reply Filters" msgid "Reply Filters"
msgstr "फिल्टर" msgstr "फिल्टर"
@ -1943,8 +1961,8 @@ msgstr "... के रूप में साइन इन करें"
msgid "Sign into" msgid "Sign into"
msgstr "साइन इन करें" msgstr "साइन इन करें"
#: src/view/com/modals/SwitchAccount.tsx:60 #: src/view/com/modals/SwitchAccount.tsx:64
#: src/view/com/modals/SwitchAccount.tsx:63 #: src/view/com/modals/SwitchAccount.tsx:67
msgid "Sign out" msgid "Sign out"
msgstr "साइन आउट" msgstr "साइन आउट"
@ -1993,7 +2011,7 @@ msgstr "Storybook"
#: src/view/com/modals/AppealLabel.tsx:101 #: src/view/com/modals/AppealLabel.tsx:101
msgid "Submit" msgid "Submit"
msgstr ">>>>>>> cb8a33b6 (Fix translations)" msgstr ""
#: src/view/screens/ProfileList.tsx:597 #: src/view/screens/ProfileList.tsx:597
msgid "Subscribe" msgid "Subscribe"
@ -2012,7 +2030,7 @@ msgstr "अनुशंसित लोग"
msgid "Support" msgid "Support"
msgstr "सहायता" msgstr "सहायता"
#: src/view/com/modals/SwitchAccount.tsx:111 #: src/view/com/modals/SwitchAccount.tsx:115
msgid "Switch Account" msgid "Switch Account"
msgstr "खाते बदलें" msgstr "खाते बदलें"
@ -2413,7 +2431,7 @@ msgstr ""
msgid "Your posts, likes, and blocks are public. Mutes are private." msgid "Your posts, likes, and blocks are public. Mutes are private."
msgstr "आपकी पोस्ट, पसंद और ब्लॉक सार्वजनिक हैं। म्यूट निजी हैं।।" msgstr "आपकी पोस्ट, पसंद और ब्लॉक सार्वजनिक हैं। म्यूट निजी हैं।।"
#: src/view/com/modals/SwitchAccount.tsx:78 #: src/view/com/modals/SwitchAccount.tsx:82
msgid "Your profile" msgid "Your profile"
msgstr "आपकी प्रोफ़ाइल" msgstr "आपकी प्रोफ़ाइल"

View File

@ -1,4 +1,4 @@
import {useCallback, useEffect} from 'react' import React, {useCallback, useEffect} from 'react'
import { import {
AppBskyFeedDefs, AppBskyFeedDefs,
AppBskyFeedPost, AppBskyFeedPost,
@ -97,6 +97,22 @@ export function usePostFeedQuery(
const feedTuners = useFeedTuners(feedDesc) const feedTuners = useFeedTuners(feedDesc)
const moderationOpts = useModerationOpts() const moderationOpts = useModerationOpts()
const enabled = opts?.enabled !== false && Boolean(moderationOpts) 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< const query = useInfiniteQuery<
FeedPageUnselected, FeedPageUnselected,
@ -147,69 +163,116 @@ export function usePostFeedQuery(
: undefined, : undefined,
select: useCallback( select: useCallback(
(data: InfiniteData<FeedPageUnselected, RQPageParam>) => { (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 NoopFeedTuner()
: new FeedTuner(feedTuners) : new FeedTuner(feedTuners)
return {
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 // Keep track of the last run and whether we can reuse
for (let i = 0; i < slice.items.length; i++) { // some already selected pages from there.
if ( let reusedPages = []
moderations[i]?.content.filter && if (lastRun.current) {
slice.items[i].post.author.did !== opts?.ignoreFilterFor const {
) { data: lastData,
return undefined args: lastArgs,
} result: lastResult,
} } = lastRun.current
let canReuse = true
return { for (let key in selectArgs) {
_reactKey: slice._reactKey, if (selectArgs.hasOwnProperty(key)) {
rootUri: slice.rootItem.post.uri, if ((selectArgs as any)[key] !== (lastArgs as any)[key]) {
isThread: // Can't do reuse anything if any input has changed.
slice.items.length > 1 && canReuse = false
slice.items.every( break
item => }
item.post.author.did === slice.items[0].post.author.did, }
), }
items: slice.items if (canReuse) {
.map((item, i) => { for (let i = 0; i < data.pages.length; i++) {
if ( if (data.pages[i] && lastData.pages[i] === data.pages[i]) {
AppBskyFeedPost.isRecord(item.post.record) && reusedPages.push(lastResult.pages[i])
AppBskyFeedPost.validateRecord(item.post.record).success // Keep the tuner in sync so that the end result is deterministic.
) { tuner.tune(lastData.pages[i].feed)
return { continue
_reactKey: `${slice._reactKey}-${i}`, }
uri: item.post.uri, // Stop as soon as pages stop matching up.
post: item.post, break
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[],
})),
} }
const result = {
pageParams: data.pageParams,
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 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. */],
), ),
}) })

View File

@ -20,6 +20,7 @@ import {Trans, msg} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {useSession, useSessionApi, SessionAccount} from '#/state/session' import {useSession, useSessionApi, SessionAccount} from '#/state/session'
import {useProfileQuery} from '#/state/queries/profile' import {useProfileQuery} from '#/state/queries/profile'
import {useCloseAllActiveElements} from '#/state/util'
export const snapPoints = ['40%', '90%'] export const snapPoints = ['40%', '90%']
@ -32,11 +33,14 @@ function SwitchAccountCard({account}: {account: SessionAccount}) {
const {data: profile} = useProfileQuery({did: account.did}) const {data: profile} = useProfileQuery({did: account.did})
const isCurrentAccount = account.did === currentAccount?.did const isCurrentAccount = account.did === currentAccount?.did
const {onPressSwitchAccount} = useAccountSwitcher() const {onPressSwitchAccount} = useAccountSwitcher()
const closeAllActiveElements = useCloseAllActiveElements()
const onPressSignout = React.useCallback(() => { const onPressSignout = React.useCallback(() => {
track('Settings:SignOutButtonClicked') track('Settings:SignOutButtonClicked')
logout() closeAllActiveElements()
}, [track, logout]) // needs to be in timeout or the modal re-opens
setTimeout(() => logout(), 0)
}, [track, logout, closeAllActiveElements])
const contents = ( const contents = (
<View style={[pal.view, styles.linkCard]}> <View style={[pal.view, styles.linkCard]}>

View File

@ -157,14 +157,14 @@ function ProfileScreenLoaded({
const showListsTab = hasSession && (isMe || extraInfoQuery.data?.hasLists) const showListsTab = hasSession && (isMe || extraInfoQuery.data?.hasLists)
const sectionTitles = useMemo<string[]>(() => { const sectionTitles = useMemo<string[]>(() => {
return [ return [
'Posts', _(msg`Posts`),
showRepliesTab ? 'Replies' : undefined, showRepliesTab ? _(msg`Replies`) : undefined,
'Media', _(msg`Media`),
showLikesTab ? 'Likes' : undefined, showLikesTab ? _(msg`Likes`) : undefined,
showFeedsTab ? 'Feeds' : undefined, showFeedsTab ? _(msg`Feeds`) : undefined,
showListsTab ? 'Lists' : undefined, showListsTab ? _(msg`Lists`) : undefined,
].filter(Boolean) as string[] ].filter(Boolean) as string[]
}, [showRepliesTab, showLikesTab, showFeedsTab, showListsTab]) }, [showRepliesTab, showLikesTab, showFeedsTab, showListsTab, _])
let nextIndex = 0 let nextIndex = 0
const postsIndex = nextIndex++ const postsIndex = nextIndex++