diff --git a/apps/mobile/src/modules/settings/routes/Plan.tsx b/apps/mobile/src/modules/settings/routes/Plan.tsx
index 542db97fd..1aa015f4b 100644
--- a/apps/mobile/src/modules/settings/routes/Plan.tsx
+++ b/apps/mobile/src/modules/settings/routes/Plan.tsx
@@ -316,7 +316,6 @@ export const PlanScreen: NavigationControllerView = () => {
isPurchasing,
isRestoring,
loadSubscriptions,
- openSubscriptionManagement,
requestSubscriptionPurchase,
restoreSubscriptionPurchases,
} = useAppleIAP()
@@ -485,15 +484,8 @@ export const PlanScreen: NavigationControllerView = () => {
})
const handleManageSubscription = useCallback(() => {
- if (activeSubscription?.source === "apple") {
- void openSubscriptionManagement().catch(() => {
- toast.error(t("subscription.actions.manage_error"))
- })
- return
- }
-
billingPortalMutation.mutate()
- }, [activeSubscription?.source, billingPortalMutation, openSubscriptionManagement, t])
+ }, [billingPortalMutation])
if (!isPaymentEnabled || sortedPlans.length === 0) {
return (
@@ -971,6 +963,7 @@ const PlanAction = ({
const { t } = useTranslation("settings")
const canManageSubscription = !!activeSubscription?.canManage
+ const isAppleSubscription = activeSubscription?.source === "apple"
const isCanceled = activeSubscription?.status === "canceled"
const periodEnd = activeSubscription?.trialEnd ?? activeSubscription?.periodEnd
const effectivePeriodEnd = periodEnd ? new Date(periodEnd) : null
@@ -1025,23 +1018,29 @@ const PlanAction = ({
)}
-
- {isManaging ? (
-
- ) : (
-
- {canManageSubscription ? t("plan.manage_subscription") : t("plan.current_plan")}
-
- )}
-
+ {isAppleSubscription ? (
+
+ {t("plan.manage_subscription_hint_apple")}
+
+ ) : (
+
+ {isManaging ? (
+
+ ) : (
+
+ {canManageSubscription ? t("plan.manage_subscription") : t("plan.current_plan")}
+
+ )}
+
+ )}
)
}
diff --git a/apps/mobile/src/providers/AppleIAPProvider.tsx b/apps/mobile/src/providers/AppleIAPProvider.tsx
index 35b7a8053..a5b75cec0 100644
--- a/apps/mobile/src/providers/AppleIAPProvider.tsx
+++ b/apps/mobile/src/providers/AppleIAPProvider.tsx
@@ -2,8 +2,7 @@ import { whoamiQueryKey } from "@follow/store/user/hooks"
import { userSyncService } from "@follow/store/user/store"
import { requireNativeModule } from "expo"
import type { ProductPurchase, SubscriptionProduct } from "expo-iap"
-import { getTransactionJws, showManageSubscriptions, useIAP } from "expo-iap"
-import { openURL } from "expo-linking"
+import { getTransactionJws, useIAP } from "expo-iap"
import type { PropsWithChildren } from "react"
import { createContext, use, useCallback, useEffect, useMemo, useRef, useState } from "react"
import { useTranslation } from "react-i18next"
@@ -15,7 +14,6 @@ import { proxyEnv } from "@/src/lib/proxy-env"
import { queryClient } from "@/src/lib/query-client"
import { toast } from "@/src/lib/toast"
-const APPLE_SUBSCRIPTION_MANAGEMENT_URL = "https://apps.apple.com/account/subscriptions"
const billingSubscriptionQueryKey = ["billingSubscription"]
type BillingSubscriptionResponse = {
@@ -40,12 +38,17 @@ type AppleIAPContextValue = {
appAccountToken?: string | null
}) => Promise
restoreSubscriptionPurchases: () => Promise
- openSubscriptionManagement: () => Promise
}
const AppleIAPContext = createContext(null)
-const noopAsync = async () => {}
+const refreshBillingState = async () => {
+ await Promise.allSettled([
+ userSyncService.whoami(),
+ queryClient.invalidateQueries({ queryKey: whoamiQueryKey }),
+ queryClient.invalidateQueries({ queryKey: billingSubscriptionQueryKey }),
+ ])
+}
export const AppleIAPProvider = ({ children }: PropsWithChildren) => {
const { t } = useTranslation("settings")
@@ -107,14 +110,6 @@ export const AppleIAPProvider = ({ children }: PropsWithChildren) => {
availablePurchasesRef.current = availablePurchases
}, [availablePurchases])
- const refreshBillingState = useCallback(async () => {
- await Promise.allSettled([
- userSyncService.whoami(),
- queryClient.invalidateQueries({ queryKey: whoamiQueryKey }),
- queryClient.invalidateQueries({ queryKey: billingSubscriptionQueryKey }),
- ])
- }, [])
-
const verifyPurchase = useCallback(
async (purchase: ProductPurchase) => {
const productId = purchase.id
@@ -186,14 +181,7 @@ export const AppleIAPProvider = ({ children }: PropsWithChildren) => {
setIsProcessingPurchase(false)
}
})()
- }, [
- currentPurchase,
- finishTransaction,
- knownSubscriptionIds,
- refreshBillingState,
- t,
- verifyPurchase,
- ])
+ }, [currentPurchase, finishTransaction, knownSubscriptionIds, t, verifyPurchase])
useEffect(() => {
if (!currentPurchaseError) {
@@ -267,7 +255,7 @@ export const AppleIAPProvider = ({ children }: PropsWithChildren) => {
throw error
}
},
- [refreshBillingState, requestPurchase, storeKitTestHelper],
+ [requestPurchase, storeKitTestHelper],
)
const restoreSubscriptionPurchases = useCallback(async () => {
@@ -322,20 +310,7 @@ export const AppleIAPProvider = ({ children }: PropsWithChildren) => {
} finally {
setIsRestoring(false)
}
- }, [knownSubscriptionIds, refreshBillingState, restorePurchases, t, verifyPurchase])
-
- const openSubscriptionManagement = useCallback(async () => {
- if (Platform.OS !== "ios") {
- await noopAsync()
- return
- }
-
- try {
- await showManageSubscriptions()
- } catch {
- await openURL(APPLE_SUBSCRIPTION_MANAGEMENT_URL)
- }
- }, [])
+ }, [knownSubscriptionIds, restorePurchases, t, verifyPurchase])
const contextValue = useMemo(
() => ({
@@ -347,7 +322,6 @@ export const AppleIAPProvider = ({ children }: PropsWithChildren) => {
loadSubscriptions,
requestSubscriptionPurchase,
restoreSubscriptionPurchases,
- openSubscriptionManagement,
}),
[
connected,
@@ -358,7 +332,6 @@ export const AppleIAPProvider = ({ children }: PropsWithChildren) => {
loadSubscriptions,
requestSubscriptionPurchase,
restoreSubscriptionPurchases,
- openSubscriptionManagement,
],
)
diff --git a/locales/settings/en.json b/locales/settings/en.json
index 8be6da422..600f8be5f 100644
--- a/locales/settings/en.json
+++ b/locales/settings/en.json
@@ -615,6 +615,7 @@
"plan.features.PRIVATE_SUBSCRIPTION": "Private Subscriptions",
"plan.features.SECURE_IMAGE_PROXY": "Secure Image Proxy",
"plan.manage_subscription": "Manage Subscription",
+ "plan.manage_subscription_hint_apple": "Manage: Apple Account > Subscriptions",
"plan.renews": "Renews {{date}}",
"plan.trial_ends": "Trial ends {{date}}",
"privacy.privacy": "Privacy",
diff --git a/locales/settings/fr-FR.json b/locales/settings/fr-FR.json
index db7f15002..9d36ee9f8 100644
--- a/locales/settings/fr-FR.json
+++ b/locales/settings/fr-FR.json
@@ -615,6 +615,7 @@
"plan.features.PRIVATE_SUBSCRIPTION": "Abonnements privés",
"plan.features.SECURE_IMAGE_PROXY": "Proxy d'image sécurisé",
"plan.manage_subscription": "Gérer l'abonnement",
+ "plan.manage_subscription_hint_apple": "Gérer : Compte Apple > Abonnements",
"plan.renews": "Renouvellement le {{date}}",
"plan.trial_ends": "L'essai se termine le {{date}}",
"privacy.privacy": "Confidentialité",
diff --git a/locales/settings/ja.json b/locales/settings/ja.json
index 0c6b01ab0..9c235141b 100644
--- a/locales/settings/ja.json
+++ b/locales/settings/ja.json
@@ -615,6 +615,7 @@
"plan.features.PRIVATE_SUBSCRIPTION": "プライベートサブスクリプション",
"plan.features.SECURE_IMAGE_PROXY": "セキュア画像プロキシ",
"plan.manage_subscription": "サブスクリプションを管理",
+ "plan.manage_subscription_hint_apple": "管理:Apple Account > サブスクリプション",
"plan.renews": "更新日 {{date}}",
"plan.trial_ends": "トライアル終了日 {{date}}",
"privacy.privacy": "プライバシー",
diff --git a/locales/settings/zh-CN.json b/locales/settings/zh-CN.json
index 1aac46598..4072df4fe 100644
--- a/locales/settings/zh-CN.json
+++ b/locales/settings/zh-CN.json
@@ -615,6 +615,7 @@
"plan.features.PRIVATE_SUBSCRIPTION": "私有订阅",
"plan.features.SECURE_IMAGE_PROXY": "安全图片代理",
"plan.manage_subscription": "管理订阅",
+ "plan.manage_subscription_hint_apple": "管理:Apple 账户 > 订阅",
"plan.renews": "续订日期 {{date}}",
"plan.trial_ends": "试用期至 {{date}}",
"privacy.privacy": "隐私政策",
diff --git a/locales/settings/zh-TW.json b/locales/settings/zh-TW.json
index b401ccfc3..1e53bde73 100644
--- a/locales/settings/zh-TW.json
+++ b/locales/settings/zh-TW.json
@@ -615,6 +615,7 @@
"plan.features.PRIVATE_SUBSCRIPTION": "私有訂閱",
"plan.features.SECURE_IMAGE_PROXY": "安全圖片代理",
"plan.manage_subscription": "管理訂閱",
+ "plan.manage_subscription_hint_apple": "管理:Apple 帳號 > 訂閱",
"plan.renews": "續訂日期 {{date}}",
"plan.trial_ends": "試用期至 {{date}}",
"privacy.privacy": "隱私政策",