test gemini
This commit is contained in:
@@ -1,150 +1,44 @@
|
|||||||
diff --git a/Dockerfile b/Dockerfile
|
|
||||||
index 371e8402c..2e139503e 100644
|
|
||||||
--- a/Dockerfile
|
|
||||||
+++ b/Dockerfile
|
|
||||||
@@ -66,7 +66,8 @@ RUN \. "$NVM_DIR/nvm.sh" && \
|
|
||||||
echo "EXPO_PUBLIC_BUNDLE_DATE=$(date -u +"%y%m%d%H")" >> .env && \
|
|
||||||
echo "EXPO_PUBLIC_SENTRY_DSN=$EXPO_PUBLIC_SENTRY_DSN" >> .env && \
|
|
||||||
npm install --global yarn && \
|
|
||||||
- yarn && \
|
|
||||||
+ yarn config set registry https://registry.npmjs.org/ && \
|
|
||||||
+ yarn install --frozen-lockfile --network-timeout 100000 && \
|
|
||||||
yarn intl:build 2>&1 | tee i18n.log && \
|
|
||||||
if grep -q "invalid syntax" "i18n.log"; then echo "\n\nFound compilation errors!\n\n" && exit 1; else echo "\n\nNo compile errors!\n\n"; fi && \
|
|
||||||
SENTRY_AUTH_TOKEN=$SENTRY_AUTH_TOKEN SENTRY_RELEASE=$EXPO_PUBLIC_RELEASE_VERSION SENTRY_DIST=$EXPO_PUBLIC_BUNDLE_IDENTIFIER yarn build-web
|
|
||||||
diff --git a/app.config.js b/app.config.js
|
diff --git a/app.config.js b/app.config.js
|
||||||
index 246d8abd3..a6582864b 100644
|
index 246d8abd3..56f42202b 100644
|
||||||
--- a/app.config.js
|
--- a/app.config.js
|
||||||
+++ b/app.config.js
|
+++ b/app.config.js
|
||||||
@@ -33,8 +33,8 @@ module.exports = function (_config) {
|
@@ -40,7 +40,7 @@ module.exports = function (_config) {
|
||||||
return {
|
|
||||||
expo: {
|
|
||||||
version: VERSION,
|
|
||||||
- name: 'Bluesky',
|
|
||||||
- slug: 'bluesky',
|
|
||||||
+ name: 'Aiat',
|
|
||||||
+ slug: 'aiat',
|
|
||||||
scheme: 'bluesky',
|
|
||||||
owner: 'blueskysocial',
|
|
||||||
runtimeVersion: {
|
runtimeVersion: {
|
||||||
@@ -45,15 +45,20 @@ module.exports = function (_config) {
|
policy: 'appVersion',
|
||||||
|
},
|
||||||
|
- icon: './assets/app-icons/ios_icon_default_next.png',
|
||||||
|
+ icon: './assets/icon.png',
|
||||||
|
userInterfaceStyle: 'automatic',
|
||||||
primaryColor: '#1083fe',
|
primaryColor: '#1083fe',
|
||||||
newArchEnabled: false,
|
newArchEnabled: false,
|
||||||
ios: {
|
@@ -213,9 +213,9 @@ module.exports = function (_config) {
|
||||||
+ infoPlist: {
|
: undefined,
|
||||||
+ NSAppTransportSecurity: {
|
codeSigningMetadata: UPDATES_ENABLED
|
||||||
+ NSAllowsArbitraryLoads: true,
|
? {
|
||||||
+ },
|
- keyid: 'main',
|
||||||
+ },
|
- alg: 'rsa-v1_5-sha256',
|
||||||
supportsTablet: false,
|
- }
|
||||||
- bundleIdentifier: 'xyz.blueskyweb.app',
|
+ keyid: 'main',
|
||||||
+ bundleIdentifier: 'ai.syui.at',
|
+ alg: 'rsa-v1_5-sha256',
|
||||||
config: {
|
+ }
|
||||||
usesNonExemptEncryption: false,
|
: undefined,
|
||||||
},
|
|
||||||
icon:
|
|
||||||
PLATFORM === 'web' // web build doesn't like .icon files
|
|
||||||
? './assets/app-icons/ios_icon_default_next.png'
|
|
||||||
- : './assets/app-icons/ios_icon_default.icon',
|
|
||||||
+ : './assets/app-icons/ios_icon_default_next.png',
|
|
||||||
infoPlist: {
|
|
||||||
UIBackgroundModes: ['remote-notification'],
|
|
||||||
NSCameraUsageDescription:
|
|
||||||
@@ -113,7 +118,7 @@ module.exports = function (_config) {
|
|
||||||
entitlements: {
|
|
||||||
'com.apple.developer.kernel.increased-memory-limit': true,
|
|
||||||
'com.apple.developer.kernel.extended-virtual-addressing': true,
|
|
||||||
- 'com.apple.security.application-groups': 'group.app.bsky',
|
|
||||||
+ 'com.apple.security.application-groups': 'group.ai.syui.at',
|
|
||||||
},
|
|
||||||
privacyManifests: {
|
|
||||||
NSPrivacyCollectedDataTypes: [
|
|
||||||
@@ -182,7 +187,7 @@ module.exports = function (_config) {
|
|
||||||
backgroundColor: '#006AFF',
|
|
||||||
},
|
|
||||||
googleServicesFile: './google-services.json',
|
|
||||||
- package: 'xyz.blueskyweb.app',
|
|
||||||
+ package: 'ai.syui.at',
|
|
||||||
intentFilters: [
|
|
||||||
{
|
|
||||||
action: 'VIEW',
|
|
||||||
@@ -220,7 +225,7 @@ module.exports = function (_config) {
|
|
||||||
checkAutomatically: 'NEVER',
|
checkAutomatically: 'NEVER',
|
||||||
},
|
},
|
||||||
plugins: [
|
@@ -225,7 +225,7 @@ module.exports = function (_config) {
|
||||||
- 'expo-video',
|
|
||||||
+ 'expo-video', './plugins/withCodeSignEntitlements.js',
|
|
||||||
'expo-localization',
|
|
||||||
'expo-web-browser',
|
'expo-web-browser',
|
||||||
[
|
[
|
||||||
@@ -239,6 +244,11 @@ module.exports = function (_config) {
|
'react-native-edge-to-edge',
|
||||||
'expo-build-properties',
|
- {android: {enforceNavigationBarContrast: false}},
|
||||||
{
|
+ { android: { enforceNavigationBarContrast: false } },
|
||||||
ios: {
|
],
|
||||||
+ infoPlist: {
|
USE_SENTRY && [
|
||||||
+ NSAppTransportSecurity: {
|
'@sentry/react-native/expo',
|
||||||
+ NSAllowsArbitraryLoads: true,
|
@@ -386,7 +386,7 @@ module.exports = function (_config) {
|
||||||
+ },
|
|
||||||
+ },
|
|
||||||
deploymentTarget: '15.1',
|
|
||||||
buildReactNativeFromSource: true,
|
|
||||||
},
|
},
|
||||||
@@ -264,7 +274,6 @@ module.exports = function (_config) {
|
|
||||||
networkInstrumentation: true,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
- './plugins/starterPackAppClipExtension/withStarterPackAppClip.js',
|
- ['expo-screen-orientation', {initialOrientation: 'PORTRAIT_UP'}],
|
||||||
'./plugins/withGradleJVMHeapSizeIncrease.js',
|
+ ['expo-screen-orientation', { initialOrientation: 'PORTRAIT_UP' }],
|
||||||
'./plugins/withAndroidManifestLargeHeapPlugin.js',
|
['expo-location'],
|
||||||
'./plugins/withAndroidManifestFCMIconPlugin.js',
|
].filter(Boolean),
|
||||||
@@ -296,6 +305,11 @@ module.exports = function (_config) {
|
extra: {
|
||||||
'expo-splash-screen',
|
|
||||||
{
|
|
||||||
ios: {
|
|
||||||
+ infoPlist: {
|
|
||||||
+ NSAppTransportSecurity: {
|
|
||||||
+ NSAllowsArbitraryLoads: true,
|
|
||||||
+ },
|
|
||||||
+ },
|
|
||||||
enableFullScreenImage_legacy: true,
|
|
||||||
backgroundColor: '#ffffff',
|
|
||||||
image: './assets/splash.png',
|
|
||||||
@@ -394,29 +408,30 @@ module.exports = function (_config) {
|
|
||||||
build: {
|
|
||||||
experimental: {
|
|
||||||
ios: {
|
|
||||||
+ infoPlist: {
|
|
||||||
+ NSAppTransportSecurity: {
|
|
||||||
+ NSAllowsArbitraryLoads: true,
|
|
||||||
+ },
|
|
||||||
+ },
|
|
||||||
appExtensions: [
|
|
||||||
{
|
|
||||||
targetName: 'Share-with-Bluesky',
|
|
||||||
- bundleIdentifier: 'xyz.blueskyweb.app.Share-with-Bluesky',
|
|
||||||
+ bundleIdentifier: 'ai.syui.at.Share-with-Bluesky',
|
|
||||||
entitlements: {
|
|
||||||
'com.apple.security.application-groups': [
|
|
||||||
- 'group.app.bsky',
|
|
||||||
+ 'group.ai.syui.at',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
targetName: 'BlueskyNSE',
|
|
||||||
- bundleIdentifier: 'xyz.blueskyweb.app.BlueskyNSE',
|
|
||||||
+ bundleIdentifier: 'ai.syui.at.BlueskyNSE',
|
|
||||||
entitlements: {
|
|
||||||
'com.apple.security.application-groups': [
|
|
||||||
- 'group.app.bsky',
|
|
||||||
+ 'group.ai.syui.at',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
- {
|
|
||||||
- targetName: 'BlueskyClip',
|
|
||||||
- bundleIdentifier: 'xyz.blueskyweb.app.AppClip',
|
|
||||||
- },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|||||||
@@ -1,37 +1,54 @@
|
|||||||
diff --git a/src/view/com/auth/SplashScreen.tsx b/src/view/com/auth/SplashScreen.tsx
|
diff --git a/src/view/com/auth/SplashScreen.tsx b/src/view/com/auth/SplashScreen.tsx
|
||||||
index 3442d1bdf..2b059af52 100644
|
index 3442d1bdf..034310a17 100644
|
||||||
--- a/src/view/com/auth/SplashScreen.tsx
|
--- a/src/view/com/auth/SplashScreen.tsx
|
||||||
+++ b/src/view/com/auth/SplashScreen.tsx
|
+++ b/src/view/com/auth/SplashScreen.tsx
|
||||||
@@ -40,16 +40,6 @@ export const SplashScreen = ({
|
@@ -1,18 +1,18 @@
|
||||||
<View style={[a.pb_sm, a.pt_5xl]}>
|
-import {View} from 'react-native'
|
||||||
<Logotype width={161} fill={t.atoms.text.color} />
|
-import Animated, {FadeIn, FadeOut} from 'react-native-reanimated'
|
||||||
</View>
|
-import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||||
-
|
-import {msg, Trans} from '@lingui/macro'
|
||||||
- <Text
|
-import {useLingui} from '@lingui/react'
|
||||||
- style={[
|
+import { View } from 'react-native'
|
||||||
- a.text_md,
|
+import Animated, { FadeIn, FadeOut } from 'react-native-reanimated'
|
||||||
- a.font_semi_bold,
|
+import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
||||||
- t.atoms.text_contrast_medium,
|
+import { msg, Trans } from '@lingui/macro'
|
||||||
- a.text_center,
|
+import { useLingui } from '@lingui/react'
|
||||||
- ]}>
|
|
||||||
- <Trans>What's up?</Trans>
|
|
||||||
- </Text>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<View
|
-import {useHaptics} from '#/lib/haptics'
|
||||||
@@ -94,7 +84,7 @@ export const SplashScreen = ({
|
-import {ErrorBoundary} from '#/view/com/util/ErrorBoundary'
|
||||||
style={[
|
-import {CenteredView} from '#/view/com/util/Views'
|
||||||
a.px_lg,
|
-import {Logo} from '#/view/icons/Logo'
|
||||||
a.pt_md,
|
-import {Logotype} from '#/view/icons/Logotype'
|
||||||
- a.pb_2xl,
|
-import {atoms as a, useTheme} from '#/alf'
|
||||||
+ a.pb_md,
|
-import {AppLanguageDropdown} from '#/components/AppLanguageDropdown'
|
||||||
a.justify_center,
|
-import {Button, ButtonText} from '#/components/Button'
|
||||||
a.align_center,
|
-import {Text} from '#/components/Typography'
|
||||||
]}>
|
+import { useHaptics } from '#/lib/haptics'
|
||||||
@@ -102,6 +92,17 @@ export const SplashScreen = ({
|
+import { ErrorBoundary } from '#/view/com/util/ErrorBoundary'
|
||||||
|
+import { CenteredView } from '#/view/com/util/Views'
|
||||||
|
+import { Logo } from '#/view/icons/Logo'
|
||||||
|
+import { Logotype } from '#/view/icons/Logotype'
|
||||||
|
+import { atoms as a, useTheme } from '#/alf'
|
||||||
|
+import { AppLanguageDropdown } from '#/components/AppLanguageDropdown'
|
||||||
|
+import { Button, ButtonText } from '#/components/Button'
|
||||||
|
+import { Text } from '#/components/Typography'
|
||||||
|
|
||||||
|
export const SplashScreen = ({
|
||||||
|
onPressSignin,
|
||||||
|
@@ -22,7 +22,7 @@ export const SplashScreen = ({
|
||||||
|
onPressCreateAccount: () => void
|
||||||
|
}) => {
|
||||||
|
const t = useTheme()
|
||||||
|
- const {_} = useLingui()
|
||||||
|
+ const { _ } = useLingui()
|
||||||
|
|
||||||
|
const playHaptic = useHaptics()
|
||||||
|
const insets = useSafeAreaInsets()
|
||||||
|
@@ -102,7 +102,18 @@ export const SplashScreen = ({
|
||||||
<AppLanguageDropdown />
|
<AppLanguageDropdown />
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
- <View style={{height: insets.bottom}} />
|
||||||
+ <View
|
+ <View
|
||||||
+ style={[
|
+ style={[
|
||||||
+ a.px_lg,
|
+ a.px_lg,
|
||||||
@@ -43,75 +60,7 @@ index 3442d1bdf..2b059af52 100644
|
|||||||
+ © syui
|
+ © syui
|
||||||
+ </Text>
|
+ </Text>
|
||||||
+ </View>
|
+ </View>
|
||||||
<View style={{height: insets.bottom}} />
|
+ <View style={{ height: insets.bottom }} />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
diff --git a/src/view/com/auth/SplashScreen.web.tsx b/src/view/com/auth/SplashScreen.web.tsx
|
</CenteredView>
|
||||||
index 22dd23d7f..08cd8aa33 100644
|
|
||||||
--- a/src/view/com/auth/SplashScreen.web.tsx
|
|
||||||
+++ b/src/view/com/auth/SplashScreen.web.tsx
|
|
||||||
@@ -3,7 +3,9 @@ import {Pressable, View} from 'react-native'
|
|
||||||
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
|
||||||
import {msg, Trans} from '@lingui/macro'
|
|
||||||
import {useLingui} from '@lingui/react'
|
|
||||||
+import {useNavigation} from '@react-navigation/native'
|
|
||||||
|
|
||||||
+import {NavigationProp} from '#/lib/routes/types'
|
|
||||||
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
|
|
||||||
import {useKawaiiMode} from '#/state/preferences/kawaii'
|
|
||||||
import {ErrorBoundary} from '#/view/com/util/ErrorBoundary'
|
|
||||||
@@ -93,15 +95,6 @@ export const SplashScreen = ({
|
|
||||||
<Logotype width={161} fill={t.atoms.text.color} />
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
-
|
|
||||||
- <Text
|
|
||||||
- style={[
|
|
||||||
- a.text_md,
|
|
||||||
- a.font_semi_bold,
|
|
||||||
- t.atoms.text_contrast_medium,
|
|
||||||
- ]}>
|
|
||||||
- <Trans>What's up?</Trans>
|
|
||||||
- </Text>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<View
|
|
||||||
@@ -150,7 +143,6 @@ export const SplashScreen = ({
|
|
||||||
|
|
||||||
function Footer() {
|
|
||||||
const t = useTheme()
|
|
||||||
- const {_} = useLingui()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View
|
|
||||||
@@ -168,26 +160,12 @@ function Footer() {
|
|
||||||
a.flex_1,
|
|
||||||
t.atoms.border_contrast_medium,
|
|
||||||
]}>
|
|
||||||
- <InlineLinkText
|
|
||||||
- label={_(msg`Learn more about Bluesky`)}
|
|
||||||
- to="https://bsky.social">
|
|
||||||
- <Trans>Business</Trans>
|
|
||||||
- </InlineLinkText>
|
|
||||||
- <InlineLinkText
|
|
||||||
- label={_(msg`Read the Bluesky blog`)}
|
|
||||||
- to="https://bsky.social/about/blog">
|
|
||||||
- <Trans>Blog</Trans>
|
|
||||||
- </InlineLinkText>
|
|
||||||
- <InlineLinkText
|
|
||||||
- label={_(msg`See jobs at Bluesky`)}
|
|
||||||
- to="https://bsky.social/about/join">
|
|
||||||
- <Trans comment="Link to a page with job openings at Bluesky">
|
|
||||||
- Jobs
|
|
||||||
- </Trans>
|
|
||||||
- </InlineLinkText>
|
|
||||||
-
|
|
||||||
<View style={a.flex_1} />
|
|
||||||
|
|
||||||
+ <Text style={[a.text_xs, t.atoms.text_contrast_low]}>
|
|
||||||
+ © syui
|
|
||||||
+ </Text>
|
|
||||||
+
|
|
||||||
<AppLanguageDropdown />
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
--- a/b/src/ageAssurance/index.tsx 2025-12-07 15:18:15
|
diff --git a/src/ageAssurance/index.tsx b/src/ageAssurance/index.tsx
|
||||||
+++ b/src/ageAssurance/index.tsx 2025-12-07 15:18:16
|
index 9a0a9c9d5..5da399795 100644
|
||||||
|
--- a/src/ageAssurance/index.tsx
|
||||||
|
+++ b/src/ageAssurance/index.tsx
|
||||||
@@ -1,10 +1,10 @@
|
@@ -1,10 +1,10 @@
|
||||||
-import {createContext, useCallback, useContext, useEffect, useMemo} from 'react'
|
-import {createContext, useCallback, useContext, useEffect, useMemo} from 'react'
|
||||||
+import { createContext, useCallback, useContext, useEffect, useMemo } from 'react'
|
+import { createContext, useCallback, useContext, useEffect, useMemo } from 'react'
|
||||||
@@ -17,7 +19,7 @@
|
|||||||
import {
|
import {
|
||||||
useAgeAssuranceState,
|
useAgeAssuranceState,
|
||||||
useOnAgeAssuranceAccessUpdate,
|
useOnAgeAssuranceAccessUpdate,
|
||||||
@@ -14,7 +14,7 @@
|
@@ -14,7 +14,7 @@ import {
|
||||||
type AgeAssuranceState,
|
type AgeAssuranceState,
|
||||||
AgeAssuranceStatus,
|
AgeAssuranceStatus,
|
||||||
} from '#/ageAssurance/types'
|
} from '#/ageAssurance/types'
|
||||||
@@ -26,7 +28,7 @@
|
|||||||
|
|
||||||
export {
|
export {
|
||||||
prefetchConfig as prefetchAgeAssuranceConfig,
|
prefetchConfig as prefetchAgeAssuranceConfig,
|
||||||
@@ -23,7 +23,7 @@
|
@@ -23,7 +23,7 @@ export {
|
||||||
usePatchOtherRequiredData as usePatchAgeAssuranceOtherRequiredData,
|
usePatchOtherRequiredData as usePatchAgeAssuranceOtherRequiredData,
|
||||||
usePatchServerState as usePatchAgeAssuranceServerState,
|
usePatchServerState as usePatchAgeAssuranceServerState,
|
||||||
} from '#/ageAssurance/data'
|
} from '#/ageAssurance/data'
|
||||||
@@ -35,7 +37,7 @@
|
|||||||
|
|
||||||
const AgeAssuranceStateContext = createContext<{
|
const AgeAssuranceStateContext = createContext<{
|
||||||
Access: typeof AgeAssuranceAccess
|
Access: typeof AgeAssuranceAccess
|
||||||
@@ -56,7 +56,7 @@
|
@@ -56,7 +56,7 @@ export function useAgeAssurance() {
|
||||||
return useContext(AgeAssuranceStateContext)
|
return useContext(AgeAssuranceStateContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +46,7 @@
|
|||||||
return (
|
return (
|
||||||
<AgeAssuranceDataProvider>
|
<AgeAssuranceDataProvider>
|
||||||
<InnerProvider>
|
<InnerProvider>
|
||||||
@@ -66,9 +66,9 @@
|
@@ -66,9 +66,9 @@ export function Provider({children}: {children: React.ReactNode}) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,7 +58,7 @@
|
|||||||
const getAndRegisterPushToken = useGetAndRegisterPushToken()
|
const getAndRegisterPushToken = useGetAndRegisterPushToken()
|
||||||
|
|
||||||
const handleAccessUpdate = useCallback(
|
const handleAccessUpdate = useCallback(
|
||||||
@@ -82,28 +82,25 @@
|
@@ -82,7 +82,7 @@ function InnerProvider({children}: {children: React.ReactNode}) {
|
||||||
useOnAgeAssuranceAccessUpdate(handleAccessUpdate)
|
useOnAgeAssuranceAccessUpdate(handleAccessUpdate)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -65,14 +67,7 @@
|
|||||||
}, [state])
|
}, [state])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AgeAssuranceStateContext.Provider
|
@@ -97,7 +97,10 @@ function InnerProvider({children}: {children: React.ReactNode}) {
|
||||||
value={useMemo(() => {
|
|
||||||
- const chatDisabled = state.access !== AgeAssuranceAccess.Full
|
|
||||||
- const isUnderage = data?.birthdate
|
|
||||||
- ? isUserUnderAdultAge(data.birthdate)
|
|
||||||
- : true
|
|
||||||
- const adultContentDisabled =
|
|
||||||
- state.access !== AgeAssuranceAccess.Full || isUnderage
|
|
||||||
return {
|
return {
|
||||||
Access: AgeAssuranceAccess,
|
Access: AgeAssuranceAccess,
|
||||||
Status: AgeAssuranceStatus,
|
Status: AgeAssuranceStatus,
|
||||||
@@ -82,14 +77,5 @@
|
|||||||
+ access: AgeAssuranceAccess.Full,
|
+ access: AgeAssuranceAccess.Full,
|
||||||
+ },
|
+ },
|
||||||
flags: {
|
flags: {
|
||||||
- adultContentDisabled,
|
adultContentDisabled,
|
||||||
- chatDisabled,
|
chatDisabled,
|
||||||
+ adultContentDisabled: false,
|
|
||||||
+ chatDisabled: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
- }, [state, data])}>
|
|
||||||
+ }, [state])}>
|
|
||||||
{children}
|
|
||||||
</AgeAssuranceStateContext.Provider>
|
|
||||||
)
|
|
||||||
|
|||||||
445
ios/patching/021-social-app-ios-clean-feed.patch
Normal file
445
ios/patching/021-social-app-ios-clean-feed.patch
Normal file
@@ -0,0 +1,445 @@
|
|||||||
|
diff --git a/src/view/screens/Home.tsx b/src/view/screens/Home.tsx
|
||||||
|
index e058e2883..1d6bc4f45 100644
|
||||||
|
--- a/src/view/screens/Home.tsx
|
||||||
|
+++ b/src/view/screens/Home.tsx
|
||||||
|
@@ -1,342 +1,139 @@
|
||||||
|
import React from 'react'
|
||||||
|
-import {ActivityIndicator, StyleSheet} from 'react-native'
|
||||||
|
-import {useFocusEffect} from '@react-navigation/native'
|
||||||
|
-
|
||||||
|
-import {PROD_DEFAULT_FEED} from '#/lib/constants'
|
||||||
|
-import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
||||||
|
-import {useOTAUpdates} from '#/lib/hooks/useOTAUpdates'
|
||||||
|
-import {useSetTitle} from '#/lib/hooks/useSetTitle'
|
||||||
|
-import {useRequestNotificationsPermission} from '#/lib/notifications/notifications'
|
||||||
|
-import {
|
||||||
|
- type HomeTabNavigatorParams,
|
||||||
|
- type NativeStackScreenProps,
|
||||||
|
-} from '#/lib/routes/types'
|
||||||
|
-import {logEvent} from '#/lib/statsig/statsig'
|
||||||
|
-import {isWeb} from '#/platform/detection'
|
||||||
|
-import {emitSoftReset} from '#/state/events'
|
||||||
|
-import {
|
||||||
|
- type SavedFeedSourceInfo,
|
||||||
|
- usePinnedFeedsInfos,
|
||||||
|
-} from '#/state/queries/feed'
|
||||||
|
-import {type FeedDescriptor, type FeedParams} from '#/state/queries/post-feed'
|
||||||
|
-import {usePreferencesQuery} from '#/state/queries/preferences'
|
||||||
|
-import {type UsePreferencesQueryResponse} from '#/state/queries/preferences/types'
|
||||||
|
-import {useSession} from '#/state/session'
|
||||||
|
-import {useSetMinimalShellMode} from '#/state/shell'
|
||||||
|
-import {useLoggedOutViewControls} from '#/state/shell/logged-out'
|
||||||
|
-import {useSelectedFeed, useSetSelectedFeed} from '#/state/shell/selected-feed'
|
||||||
|
-import {FeedPage} from '#/view/com/feeds/FeedPage'
|
||||||
|
-import {HomeHeader} from '#/view/com/home/HomeHeader'
|
||||||
|
-import {
|
||||||
|
- Pager,
|
||||||
|
- type PagerRef,
|
||||||
|
- type RenderTabBarFnProps,
|
||||||
|
-} from '#/view/com/pager/Pager'
|
||||||
|
-import {CustomFeedEmptyState} from '#/view/com/posts/CustomFeedEmptyState'
|
||||||
|
-import {FollowingEmptyState} from '#/view/com/posts/FollowingEmptyState'
|
||||||
|
-import {FollowingEndOfFeed} from '#/view/com/posts/FollowingEndOfFeed'
|
||||||
|
-import {NoFeedsPinned} from '#/screens/Home/NoFeedsPinned'
|
||||||
|
+import { ActivityIndicator, StyleSheet } from 'react-native'
|
||||||
|
+import { useFocusEffect } from '@react-navigation/native'
|
||||||
|
+import { PROD_DEFAULT_FEED } from '#/lib/constants'
|
||||||
|
+import { useNonReactiveCallback } from '#/lib/hooks/useNonReactiveCallback'
|
||||||
|
+import { useOTAUpdates } from '#/lib/hooks/useOTAUpdates'
|
||||||
|
+import { useSetTitle } from '#/lib/hooks/useSetTitle'
|
||||||
|
+import { useRequestNotificationsPermission } from '#/lib/notifications/notifications'
|
||||||
|
+import { type HomeTabNavigatorParams, type NativeStackScreenProps } from '#/lib/routes/types'
|
||||||
|
+import { logEvent } from '#/lib/statsig/statsig'
|
||||||
|
+import { isWeb } from '#/platform/detection'
|
||||||
|
+import { emitSoftReset } from '#/state/events'
|
||||||
|
+import { type SavedFeedSourceInfo, usePinnedFeedsInfos } from '#/state/queries/feed'
|
||||||
|
+import { type FeedDescriptor, type FeedParams } from '#/state/queries/post-feed'
|
||||||
|
+import { usePreferencesQuery } from '#/state/queries/preferences'
|
||||||
|
+import { type UsePreferencesQueryResponse } from '#/state/queries/preferences/types'
|
||||||
|
+import { useSession } from '#/state/session'
|
||||||
|
+import { useSetMinimalShellMode } from '#/state/shell'
|
||||||
|
+import { useLoggedOutViewControls } from '#/state/shell/logged-out'
|
||||||
|
+import { useSelectedFeed, useSetSelectedFeed } from '#/state/shell/selected-feed'
|
||||||
|
+import { FeedPage } from '#/view/com/feeds/FeedPage'
|
||||||
|
+import { HomeHeader } from '#/view/com/home/HomeHeader'
|
||||||
|
+import { Pager, type PagerRef, type RenderTabBarFnProps } from '#/view/com/pager/Pager'
|
||||||
|
+import { CustomFeedEmptyState } from '#/view/com/posts/CustomFeedEmptyState'
|
||||||
|
+import { FollowingEmptyState } from '#/view/com/posts/FollowingEmptyState'
|
||||||
|
+import { FollowingEndOfFeed } from '#/view/com/posts/FollowingEndOfFeed'
|
||||||
|
+import { NoFeedsPinned } from '#/screens/Home/NoFeedsPinned'
|
||||||
|
import * as Layout from '#/components/Layout'
|
||||||
|
-import {useDemoMode} from '#/storage/hooks/demo-mode'
|
||||||
|
+import { useDemoMode } from '#/storage/hooks/demo-mode'
|
||||||
|
+
|
||||||
|
+const DEFAULT_PINNED_FEEDS = [{
|
||||||
|
+ feedDescriptor: 'following',
|
||||||
|
+ displayName: 'Following',
|
||||||
|
+ id: 'following',
|
||||||
|
+ type: 'feed',
|
||||||
|
+ savedFeed: undefined,
|
||||||
|
+ pinned: true,
|
||||||
|
+}]
|
||||||
|
|
||||||
|
type Props = NativeStackScreenProps<HomeTabNavigatorParams, 'Home' | 'Start'>
|
||||||
|
export function HomeScreen(props: Props) {
|
||||||
|
- const {setShowLoggedOut} = useLoggedOutViewControls()
|
||||||
|
- const {data: preferences} = usePreferencesQuery()
|
||||||
|
- const {currentAccount} = useSession()
|
||||||
|
- const {data: pinnedFeedInfos, isLoading: isPinnedFeedsLoading} =
|
||||||
|
- usePinnedFeedsInfos()
|
||||||
|
+ const { setShowLoggedOut } = useLoggedOutViewControls()
|
||||||
|
+ const { data: preferences } = usePreferencesQuery()
|
||||||
|
+ const { currentAccount } = useSession()
|
||||||
|
+ const { data: pinnedFeedInfos } = usePinnedFeedsInfos()
|
||||||
|
+
|
||||||
|
+ const safePreferences = preferences || { feedViewPrefs: { lab_mergeFeedEnabled: false }, savedFeeds: [] } as any
|
||||||
|
+ const safePinnedFeedInfos = [{
|
||||||
|
+ feedDescriptor: 'following',
|
||||||
|
+ displayName: 'Following',
|
||||||
|
+ id: 'following',
|
||||||
|
+ type: 'feed',
|
||||||
|
+ savedFeed: undefined,
|
||||||
|
+ pinned: true,
|
||||||
|
+ }]
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (isWeb && !currentAccount) {
|
||||||
|
const getParams = new URLSearchParams(window.location.search)
|
||||||
|
const splash = getParams.get('splash')
|
||||||
|
- if (splash === 'true') {
|
||||||
|
- setShowLoggedOut(true)
|
||||||
|
- return
|
||||||
|
- }
|
||||||
|
+ if (splash === 'true') { setShowLoggedOut(true); return }
|
||||||
|
}
|
||||||
|
-
|
||||||
|
const params = props.route.params
|
||||||
|
- if (
|
||||||
|
- currentAccount &&
|
||||||
|
- props.route.name === 'Start' &&
|
||||||
|
- params?.name &&
|
||||||
|
- params?.rkey
|
||||||
|
- ) {
|
||||||
|
- props.navigation.navigate('StarterPack', {
|
||||||
|
- rkey: params.rkey,
|
||||||
|
- name: params.name,
|
||||||
|
- })
|
||||||
|
+ if (currentAccount && props.route.name === 'Start' && params?.name && params?.rkey) {
|
||||||
|
+ props.navigation.navigate('StarterPack', { rkey: params.rkey, name: params.name })
|
||||||
|
}
|
||||||
|
- }, [
|
||||||
|
- currentAccount,
|
||||||
|
- props.navigation,
|
||||||
|
- props.route.name,
|
||||||
|
- props.route.params,
|
||||||
|
- setShowLoggedOut,
|
||||||
|
- ])
|
||||||
|
+ }, [currentAccount, props.navigation, props.route.name, props.route.params, setShowLoggedOut])
|
||||||
|
|
||||||
|
- if (preferences && pinnedFeedInfos && !isPinnedFeedsLoading) {
|
||||||
|
- return (
|
||||||
|
- <Layout.Screen testID="HomeScreen">
|
||||||
|
- <HomeScreenReady
|
||||||
|
- {...props}
|
||||||
|
- preferences={preferences}
|
||||||
|
- pinnedFeedInfos={pinnedFeedInfos}
|
||||||
|
- />
|
||||||
|
- </Layout.Screen>
|
||||||
|
- )
|
||||||
|
- } else {
|
||||||
|
- return (
|
||||||
|
- <Layout.Screen>
|
||||||
|
- <Layout.Center style={styles.loading}>
|
||||||
|
- <ActivityIndicator size="large" />
|
||||||
|
- </Layout.Center>
|
||||||
|
- </Layout.Screen>
|
||||||
|
- )
|
||||||
|
- }
|
||||||
|
+ return (
|
||||||
|
+ <Layout.Screen testID="HomeScreen">
|
||||||
|
+ <HomeScreenReady {...props} preferences={safePreferences} pinnedFeedInfos={safePinnedFeedInfos as any} />
|
||||||
|
+ </Layout.Screen>
|
||||||
|
+ )
|
||||||
|
}
|
||||||
|
|
||||||
|
-function HomeScreenReady({
|
||||||
|
- preferences,
|
||||||
|
- pinnedFeedInfos,
|
||||||
|
-}: Props & {
|
||||||
|
- preferences: UsePreferencesQueryResponse
|
||||||
|
- pinnedFeedInfos: SavedFeedSourceInfo[]
|
||||||
|
-}) {
|
||||||
|
- const allFeeds = React.useMemo(
|
||||||
|
- () => pinnedFeedInfos.map(f => f.feedDescriptor),
|
||||||
|
- [pinnedFeedInfos],
|
||||||
|
- )
|
||||||
|
- const maybeRawSelectedFeed: FeedDescriptor | undefined =
|
||||||
|
- useSelectedFeed() ?? allFeeds[0]
|
||||||
|
+function HomeScreenReady({ preferences, pinnedFeedInfos }: any) {
|
||||||
|
+ const allFeeds = React.useMemo(() => pinnedFeedInfos.map(f => f.feedDescriptor), [pinnedFeedInfos])
|
||||||
|
+ const maybeRawSelectedFeed = useSelectedFeed() ?? allFeeds[0]
|
||||||
|
const setSelectedFeed = useSetSelectedFeed()
|
||||||
|
const maybeFoundIndex = allFeeds.indexOf(maybeRawSelectedFeed)
|
||||||
|
const selectedIndex = Math.max(0, maybeFoundIndex)
|
||||||
|
- const maybeSelectedFeed: FeedDescriptor | undefined = allFeeds[selectedIndex]
|
||||||
|
+ const maybeSelectedFeed = allFeeds[selectedIndex]
|
||||||
|
const requestNotificationsPermission = useRequestNotificationsPermission()
|
||||||
|
|
||||||
|
useSetTitle(pinnedFeedInfos[selectedIndex]?.displayName)
|
||||||
|
useOTAUpdates()
|
||||||
|
-
|
||||||
|
- React.useEffect(() => {
|
||||||
|
- requestNotificationsPermission('Home')
|
||||||
|
- }, [requestNotificationsPermission])
|
||||||
|
+ React.useEffect(() => { requestNotificationsPermission('Home') }, [requestNotificationsPermission])
|
||||||
|
|
||||||
|
const pagerRef = React.useRef<PagerRef>(null)
|
||||||
|
const lastPagerReportedIndexRef = React.useRef(selectedIndex)
|
||||||
|
React.useLayoutEffect(() => {
|
||||||
|
- // Since the pager is not a controlled component, adjust it imperatively
|
||||||
|
- // if the selected index gets out of sync with what it last reported.
|
||||||
|
- // This is supposed to only happen on the web when you use the right nav.
|
||||||
|
if (selectedIndex !== lastPagerReportedIndexRef.current) {
|
||||||
|
lastPagerReportedIndexRef.current = selectedIndex
|
||||||
|
pagerRef.current?.setPage(selectedIndex)
|
||||||
|
}
|
||||||
|
}, [selectedIndex])
|
||||||
|
|
||||||
|
- const {hasSession} = useSession()
|
||||||
|
+ const { hasSession } = useSession()
|
||||||
|
const setMinimalShellMode = useSetMinimalShellMode()
|
||||||
|
- useFocusEffect(
|
||||||
|
- React.useCallback(() => {
|
||||||
|
- setMinimalShellMode(false)
|
||||||
|
- }, [setMinimalShellMode]),
|
||||||
|
- )
|
||||||
|
-
|
||||||
|
- useFocusEffect(
|
||||||
|
- useNonReactiveCallback(() => {
|
||||||
|
- if (maybeSelectedFeed) {
|
||||||
|
- logEvent('home:feedDisplayed', {
|
||||||
|
- index: selectedIndex,
|
||||||
|
- feedType: maybeSelectedFeed.split('|')[0],
|
||||||
|
- feedUrl: maybeSelectedFeed,
|
||||||
|
- reason: 'focus',
|
||||||
|
- })
|
||||||
|
- }
|
||||||
|
- }),
|
||||||
|
- )
|
||||||
|
+ useFocusEffect(React.useCallback(() => { setMinimalShellMode(false) }, [setMinimalShellMode]))
|
||||||
|
|
||||||
|
- const onPageSelected = React.useCallback(
|
||||||
|
- (index: number) => {
|
||||||
|
- setMinimalShellMode(false)
|
||||||
|
- const maybeFeed = allFeeds[index]
|
||||||
|
-
|
||||||
|
- // Mutate the ref before setting state to avoid the imperative syncing effect
|
||||||
|
- // above from starting a loop on Android when swiping back and forth.
|
||||||
|
- lastPagerReportedIndexRef.current = index
|
||||||
|
- setSelectedFeed(maybeFeed)
|
||||||
|
-
|
||||||
|
- if (maybeFeed) {
|
||||||
|
- logEvent('home:feedDisplayed', {
|
||||||
|
- index,
|
||||||
|
- feedType: maybeFeed.split('|')[0],
|
||||||
|
- feedUrl: maybeFeed,
|
||||||
|
- })
|
||||||
|
- }
|
||||||
|
- },
|
||||||
|
- [setSelectedFeed, setMinimalShellMode, allFeeds],
|
||||||
|
- )
|
||||||
|
+ const onPageSelected = React.useCallback((index) => {
|
||||||
|
+ setMinimalShellMode(false)
|
||||||
|
+ const maybeFeed = allFeeds[index]
|
||||||
|
+ lastPagerReportedIndexRef.current = index
|
||||||
|
+ setSelectedFeed(maybeFeed)
|
||||||
|
+ }, [setSelectedFeed, setMinimalShellMode, allFeeds])
|
||||||
|
|
||||||
|
- const onPressSelected = React.useCallback(() => {
|
||||||
|
- emitSoftReset()
|
||||||
|
- }, [])
|
||||||
|
-
|
||||||
|
- const onPageScrollStateChanged = React.useCallback(
|
||||||
|
- (state: 'idle' | 'dragging' | 'settling') => {
|
||||||
|
- 'worklet'
|
||||||
|
- if (state === 'dragging') {
|
||||||
|
- setMinimalShellMode(false)
|
||||||
|
- }
|
||||||
|
- },
|
||||||
|
- [setMinimalShellMode],
|
||||||
|
- )
|
||||||
|
+ const onPressSelected = React.useCallback(() => { emitSoftReset() }, [])
|
||||||
|
+ const onPageScrollStateChanged = React.useCallback((state) => {
|
||||||
|
+ 'worklet'
|
||||||
|
+ if (state === 'dragging') setMinimalShellMode(false)
|
||||||
|
+ }, [setMinimalShellMode])
|
||||||
|
|
||||||
|
const [demoMode] = useDemoMode()
|
||||||
|
-
|
||||||
|
- const renderTabBar = React.useCallback(
|
||||||
|
- (props: RenderTabBarFnProps) => {
|
||||||
|
- if (demoMode) {
|
||||||
|
- return (
|
||||||
|
- <HomeHeader
|
||||||
|
- key="FEEDS_TAB_BAR"
|
||||||
|
- {...props}
|
||||||
|
- testID="homeScreenFeedTabs"
|
||||||
|
- onPressSelected={onPressSelected}
|
||||||
|
- // @ts-ignore
|
||||||
|
- feeds={[{displayName: 'Following'}, {displayName: 'Discover'}]}
|
||||||
|
- />
|
||||||
|
- )
|
||||||
|
- }
|
||||||
|
- return (
|
||||||
|
- <HomeHeader
|
||||||
|
- key="FEEDS_TAB_BAR"
|
||||||
|
- {...props}
|
||||||
|
- testID="homeScreenFeedTabs"
|
||||||
|
- onPressSelected={onPressSelected}
|
||||||
|
- feeds={pinnedFeedInfos}
|
||||||
|
- />
|
||||||
|
- )
|
||||||
|
- },
|
||||||
|
- [onPressSelected, pinnedFeedInfos, demoMode],
|
||||||
|
- )
|
||||||
|
-
|
||||||
|
- const renderFollowingEmptyState = React.useCallback(() => {
|
||||||
|
- return <FollowingEmptyState />
|
||||||
|
- }, [])
|
||||||
|
-
|
||||||
|
- const renderCustomFeedEmptyState = React.useCallback(() => {
|
||||||
|
- return <CustomFeedEmptyState />
|
||||||
|
- }, [])
|
||||||
|
-
|
||||||
|
- const homeFeedParams = React.useMemo<FeedParams>(() => {
|
||||||
|
- return {
|
||||||
|
- mergeFeedEnabled: Boolean(preferences.feedViewPrefs.lab_mergeFeedEnabled),
|
||||||
|
- mergeFeedSources: preferences.feedViewPrefs.lab_mergeFeedEnabled
|
||||||
|
- ? preferences.savedFeeds
|
||||||
|
- .filter(f => f.type === 'feed' || f.type === 'list')
|
||||||
|
- .map(f => f.value)
|
||||||
|
- : [],
|
||||||
|
- }
|
||||||
|
- }, [preferences])
|
||||||
|
-
|
||||||
|
- if (demoMode) {
|
||||||
|
- return (
|
||||||
|
- <Pager
|
||||||
|
- ref={pagerRef}
|
||||||
|
- testID="homeScreen"
|
||||||
|
- onPageSelected={onPageSelected}
|
||||||
|
- onPageScrollStateChanged={onPageScrollStateChanged}
|
||||||
|
- renderTabBar={renderTabBar}
|
||||||
|
- initialPage={selectedIndex}>
|
||||||
|
- <FeedPage
|
||||||
|
- testID="demoFeedPage"
|
||||||
|
- isPageFocused
|
||||||
|
- isPageAdjacent={false}
|
||||||
|
- feed="demo"
|
||||||
|
- renderEmptyState={renderCustomFeedEmptyState}
|
||||||
|
- feedInfo={pinnedFeedInfos[0]}
|
||||||
|
- />
|
||||||
|
- <FeedPage
|
||||||
|
- testID="customFeedPage"
|
||||||
|
- isPageFocused
|
||||||
|
- isPageAdjacent={false}
|
||||||
|
- feed={`feedgen|${PROD_DEFAULT_FEED('whats-hot')}`}
|
||||||
|
- renderEmptyState={renderCustomFeedEmptyState}
|
||||||
|
- feedInfo={pinnedFeedInfos[0]}
|
||||||
|
- />
|
||||||
|
- </Pager>
|
||||||
|
- )
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- return hasSession ? (
|
||||||
|
- <Pager
|
||||||
|
- key={allFeeds.join(',')}
|
||||||
|
- ref={pagerRef}
|
||||||
|
- testID="homeScreen"
|
||||||
|
- initialPage={selectedIndex}
|
||||||
|
- onPageSelected={onPageSelected}
|
||||||
|
- onPageScrollStateChanged={onPageScrollStateChanged}
|
||||||
|
- renderTabBar={renderTabBar}>
|
||||||
|
- {pinnedFeedInfos.length ? (
|
||||||
|
- pinnedFeedInfos.map((feedInfo, index) => {
|
||||||
|
- const feed = feedInfo.feedDescriptor
|
||||||
|
- if (feed === 'following') {
|
||||||
|
- return (
|
||||||
|
- <FeedPage
|
||||||
|
- key={feed}
|
||||||
|
- testID="followingFeedPage"
|
||||||
|
- isPageFocused={maybeSelectedFeed === feed}
|
||||||
|
- isPageAdjacent={Math.abs(selectedIndex - index) === 1}
|
||||||
|
- feed={feed}
|
||||||
|
- feedParams={homeFeedParams}
|
||||||
|
- renderEmptyState={renderFollowingEmptyState}
|
||||||
|
- renderEndOfFeed={FollowingEndOfFeed}
|
||||||
|
- feedInfo={feedInfo}
|
||||||
|
- />
|
||||||
|
- )
|
||||||
|
- }
|
||||||
|
- const savedFeedConfig = feedInfo.savedFeed
|
||||||
|
- return (
|
||||||
|
- <FeedPage
|
||||||
|
- key={feed}
|
||||||
|
- testID="customFeedPage"
|
||||||
|
- isPageFocused={maybeSelectedFeed === feed}
|
||||||
|
- isPageAdjacent={Math.abs(selectedIndex - index) === 1}
|
||||||
|
- feed={feed}
|
||||||
|
- renderEmptyState={renderCustomFeedEmptyState}
|
||||||
|
- savedFeedConfig={savedFeedConfig}
|
||||||
|
- feedInfo={feedInfo}
|
||||||
|
- />
|
||||||
|
- )
|
||||||
|
- })
|
||||||
|
- ) : (
|
||||||
|
- <NoFeedsPinned preferences={preferences} />
|
||||||
|
- )}
|
||||||
|
- </Pager>
|
||||||
|
- ) : (
|
||||||
|
- <Pager
|
||||||
|
- testID="homeScreen"
|
||||||
|
- onPageSelected={onPageSelected}
|
||||||
|
- onPageScrollStateChanged={onPageScrollStateChanged}
|
||||||
|
- renderTabBar={renderTabBar}>
|
||||||
|
- <FeedPage
|
||||||
|
- testID="customFeedPage"
|
||||||
|
- isPageFocused
|
||||||
|
- isPageAdjacent={false}
|
||||||
|
- feed={`feedgen|${PROD_DEFAULT_FEED('whats-hot')}`}
|
||||||
|
- renderEmptyState={renderCustomFeedEmptyState}
|
||||||
|
- feedInfo={pinnedFeedInfos[0]}
|
||||||
|
- />
|
||||||
|
+ const renderTabBar = React.useCallback((props) => {
|
||||||
|
+ return <HomeHeader key="FEEDS_TAB_BAR" {...props} testID="homeScreenFeedTabs" onPressSelected={onPressSelected} feeds={pinnedFeedInfos} />
|
||||||
|
+ }, [onPressSelected, pinnedFeedInfos])
|
||||||
|
+
|
||||||
|
+ const renderFollowingEmptyState = React.useCallback(() => <FollowingEmptyState />, [])
|
||||||
|
+ const renderCustomFeedEmptyState = React.useCallback(() => <CustomFeedEmptyState />, [])
|
||||||
|
+
|
||||||
|
+ const homeFeedParams = React.useMemo(() => ({
|
||||||
|
+ mergeFeedEnabled: false, mergeFeedSources: []
|
||||||
|
+ }), [preferences])
|
||||||
|
+
|
||||||
|
+ return (
|
||||||
|
+ <Pager ref={pagerRef} testID="homeScreen" initialPage={selectedIndex} onPageSelected={onPageSelected} onPageScrollStateChanged={onPageScrollStateChanged} renderTabBar={renderTabBar}>
|
||||||
|
+ {pinnedFeedInfos.map((feedInfo, index) => {
|
||||||
|
+ const feed = feedInfo.feedDescriptor
|
||||||
|
+ if (feed === 'following') {
|
||||||
|
+ return <FeedPage key={feed} testID="followingFeedPage" isPageFocused={maybeSelectedFeed === feed} isPageAdjacent={Math.abs(selectedIndex - index) === 1} feed={feed} feedParams={homeFeedParams} renderEmptyState={renderFollowingEmptyState} renderEndOfFeed={FollowingEndOfFeed} feedInfo={feedInfo} />
|
||||||
|
+ }
|
||||||
|
+ return <FeedPage key={feed} testID="customFeedPage" isPageFocused={maybeSelectedFeed === feed} isPageAdjacent={Math.abs(selectedIndex - index) === 1} feed={feed} renderEmptyState={renderCustomFeedEmptyState} savedFeedConfig={feedInfo.savedFeed} feedInfo={feedInfo} />
|
||||||
|
+ })}
|
||||||
|
</Pager>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
-
|
||||||
|
-const styles = StyleSheet.create({
|
||||||
|
- loading: {
|
||||||
|
- height: '100%',
|
||||||
|
- alignContent: 'center',
|
||||||
|
- justifyContent: 'center',
|
||||||
|
- paddingBottom: 100,
|
||||||
|
- },
|
||||||
|
-})
|
||||||
|
+const styles = StyleSheet.create({ loading: { height: '100%', alignContent: 'center', justifyContent: 'center', paddingBottom: 100 } })
|
||||||
Reference in New Issue
Block a user