fix(mobile): hide payment ui outside apk (#4847)

This commit is contained in:
DIYgod 2026-02-14 21:12:47 +08:00 committed by GitHub
parent 87784b2246
commit 50ed7aae10
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 63 additions and 8 deletions

View File

@ -2,16 +2,18 @@ import { createAtomHooks } from "@follow/utils/jotai"
import type { StatusConfigs } from "@follow-app/client-sdk"
import { atom } from "jotai"
import { isPaymentFeatureEnabled } from "@/src/lib/payment"
export const [, , useServerConfigs, , getServerConfigs, setServerConfigs] = createAtomHooks(
atom<Nullable<StatusConfigs>>(null),
)
export const useIsPaymentEnabled = () => {
const serverConfigs = useServerConfigs()
return Boolean(serverConfigs?.PAYMENT_ENABLED)
return isPaymentFeatureEnabled(serverConfigs?.PAYMENT_ENABLED)
}
export const getIsPaymentEnabled = () => {
const serverConfigs = getServerConfigs()
return Boolean(serverConfigs?.PAYMENT_ENABLED)
return isPaymentFeatureEnabled(serverConfigs?.PAYMENT_ENABLED)
}

View File

@ -112,7 +112,13 @@ export const toastFetchError = (error: Error, { title: _title }: { title?: strin
return
}
const needUpgradeError = status === 402 && getIsPaymentEnabled()
const isPaymentFeatureEnabled = getIsPaymentEnabled()
if (status === 402 && !isPaymentFeatureEnabled) {
return toast.error(t("errors:1004"))
}
const needUpgradeError = status === 402 && isPaymentFeatureEnabled
if (needUpgradeError) {
showUpgradeRequiredDialog({

View File

@ -0,0 +1,32 @@
import DeviceInfo from "react-native-device-info"
import { isAndroid } from "./platform"
const GOOGLE_PLAY_INSTALLER_PACKAGE_NAME = "com.android.vending"
let isAndroidApkInstallCache: boolean | undefined
const isGooglePlayInstall = (installerPackageName?: string | null) =>
installerPackageName === GOOGLE_PLAY_INSTALLER_PACKAGE_NAME
export const isAndroidApkInstall = () => {
if (isAndroidApkInstallCache !== undefined) {
return isAndroidApkInstallCache
}
if (!isAndroid) {
isAndroidApkInstallCache = false
return isAndroidApkInstallCache
}
try {
isAndroidApkInstallCache = !isGooglePlayInstall(DeviceInfo.getInstallerPackageNameSync())
return isAndroidApkInstallCache
} catch {
// Treat unknown installer as APK-style install and keep behavior permissive.
isAndroidApkInstallCache = true
return isAndroidApkInstallCache
}
}
export const isPaymentFeatureEnabled = (paymentEnabled?: boolean | null) =>
Boolean(paymentEnabled) && isAndroidApkInstall()

View File

@ -3,6 +3,7 @@ import { useEffect } from "react"
import { useTranslation } from "react-i18next"
import { View } from "react-native"
import { getIsPaymentEnabled } from "@/src/atoms/server-configs"
import { Text } from "@/src/components/ui/typography/Text"
import type { DialogComponent } from "@/src/lib/dialog"
import { Dialog } from "@/src/lib/dialog"
@ -20,6 +21,10 @@ let currentPayload: UpgradeDialogPayload = defaultPayload
const getPayload = () => currentPayload
export const showUpgradeRequiredDialog = (payload?: UpgradeDialogPayload) => {
if (!getIsPaymentEnabled()) {
return
}
currentPayload = {
title: payload?.title,
message: payload?.message,

View File

@ -7,7 +7,7 @@ import { Fragment, useMemo } from "react"
import { useTranslation } from "react-i18next"
import { Alert, PixelRatio, View } from "react-native"
import { useServerConfigs } from "@/src/atoms/server-configs"
import { getIsPaymentEnabled, useServerConfigs } from "@/src/atoms/server-configs"
import {
GroupedInsetListCard,
GroupedInsetListNavigationLink,
@ -28,6 +28,7 @@ import { UserSettingCuteFiIcon } from "@/src/icons/user_setting_cute_fi"
import { signOut } from "@/src/lib/auth"
import { useNavigation } from "@/src/lib/navigation/hooks"
import type { Navigation } from "@/src/lib/navigation/Navigation"
import { isPaymentFeatureEnabled } from "@/src/lib/payment"
import { accentColor } from "@/src/theme/colors"
import { AboutScreen } from "./routes/About"
@ -109,7 +110,7 @@ const SubscriptionGroupNavigationLinks: GroupNavigationLink[] = [
},
iconBackgroundColor: accentColor,
anonymous: false,
hideIf: (serverConfigs) => !serverConfigs?.PAYMENT_ENABLED,
hideIf: (serverConfigs) => !isPaymentFeatureEnabled(serverConfigs?.PAYMENT_ENABLED),
},
]
@ -210,7 +211,11 @@ const NavigationLinkGroup: FC<{
</GroupedInsetListNavigationLinkIcon>
}
onPress={() => {
if (link.trialNotAllowed && (role === UserRole.Free || role === UserRole.Trial)) {
if (
link.trialNotAllowed &&
(role === UserRole.Free || role === UserRole.Trial) &&
getIsPaymentEnabled()
) {
navigation.presentControllerView(PlanScreen)
} else {
link.onPress({ navigation })

View File

@ -10,7 +10,7 @@ import { useTranslation } from "react-i18next"
import type { LayoutChangeEvent } from "react-native"
import { ActivityIndicator, Animated, Easing, Pressable, StyleSheet, View } from "react-native"
import { useServerConfigs } from "@/src/atoms/server-configs"
import { useIsPaymentEnabled, useServerConfigs } from "@/src/atoms/server-configs"
import {
NavigationBlurEffectHeaderView,
SafeNavigationScrollView,
@ -111,11 +111,11 @@ const isFeatureValueVisible = (value: PaymentFeature[keyof PaymentFeature] | nul
export const PlanScreen: NavigationControllerView = () => {
const { t } = useTranslation("settings")
const serverConfigs = useServerConfigs()
const isPaymentEnabled = useIsPaymentEnabled()
const role = useUserRole()
const roleEndAt = useRoleEndAt()
const plans = useMemo(() => serverConfigs?.PAYMENT_PLAN_LIST ?? [], [serverConfigs])
const isPaymentEnabled = serverConfigs?.PAYMENT_ENABLED
const defaultBillingPeriod: BillingPeriod = "yearly"
const [billingPeriod, setBillingPeriod] = useState<BillingPeriod>(defaultBillingPeriod)

View File

@ -1,6 +1,11 @@
import { getIsPaymentEnabled } from "@/src/atoms/server-configs"
import { Navigation } from "@/src/lib/navigation/Navigation"
export const navigateToPlanScreen = () => {
if (!getIsPaymentEnabled()) {
return Promise.resolve()
}
return import("./Plan")
.then(({ PlanScreen }) => {
Navigation.rootNavigation.pushControllerView(PlanScreen)