Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions android/app/capacitor.build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ android {
apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
dependencies {
implementation project(':capacitor-app')
implementation project(':capacitor-app-launcher')
implementation project(':capacitor-browser')
implementation project(':capacitor-camera')
implementation project(':capacitor-clipboard')
Expand All @@ -20,6 +21,7 @@ dependencies {
implementation project(':capacitor-splash-screen')
implementation project(':capacitor-status-bar')
implementation project(':capgo-capacitor-crisp')
implementation project(':capgo-capacitor-in-app-review')
implementation project(':capgo-capacitor-native-biometric')
implementation project(':capgo-capacitor-passkey')
implementation project(':capgo-capacitor-updater')
Expand Down
6 changes: 6 additions & 0 deletions android/capacitor.settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ project(':capacitor-android').projectDir = new File('../node_modules/.pnpm/@capa
include ':capacitor-app'
project(':capacitor-app').projectDir = new File('../node_modules/.pnpm/@capacitor+app@8.1.0_@capacitor+core@8.2.0/node_modules/@capacitor/app/android')

include ':capacitor-app-launcher'
project(':capacitor-app-launcher').projectDir = new File('../node_modules/.pnpm/@capacitor+app-launcher@8.0.1_@capacitor+core@8.2.0/node_modules/@capacitor/app-launcher/android')

include ':capacitor-browser'
project(':capacitor-browser').projectDir = new File('../node_modules/.pnpm/@capacitor+browser@8.0.3_@capacitor+core@8.2.0/node_modules/@capacitor/browser/android')

Expand Down Expand Up @@ -35,6 +38,9 @@ project(':capacitor-status-bar').projectDir = new File('../node_modules/.pnpm/@c
include ':capgo-capacitor-crisp'
project(':capgo-capacitor-crisp').projectDir = new File('../node_modules/.pnpm/@capgo+capacitor-crisp@8.0.27_@capacitor+core@8.2.0/node_modules/@capgo/capacitor-crisp/android')

include ':capgo-capacitor-in-app-review'
project(':capgo-capacitor-in-app-review').projectDir = new File('../node_modules/.pnpm/@capgo+capacitor-in-app-review@8.2.3_@capacitor+core@8.2.0/node_modules/@capgo/capacitor-in-app-review/android')

include ':capgo-capacitor-native-biometric'
project(':capgo-capacitor-native-biometric').projectDir = new File('../node_modules/.pnpm/@capgo+capacitor-native-biometric@8.6.0_@capacitor+core@8.2.0/node_modules/@capgo/capacitor-native-biometric/android')

Expand Down
9 changes: 8 additions & 1 deletion instrumentation-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { withoutBrowserTracing } from '@/utils/sentry-integrations'
import { posthogErrorMirror } from '@/utils/sentry-posthog-mirror'
import { whenIdle } from '@/utils/defer-analytics'
import { startWebVitalsShim } from '@/utils/web-vitals-shim'
import { noteAppReviewFriction } from '@/utils/app-review-friction'
import { installPaymentNetworkGoogleAnalyticsGuard, isPaymentNetworkExplorerPath } from '@/utils/private-routes'

// Same conditions as the GA bootstrap in app/layout.tsx: with no GA to disable
Expand Down Expand Up @@ -49,7 +50,13 @@ if (
capture_pageleave: true,
// The payment explorer contains team-only identity and relationship data.
// Drop every event on client navigation; direct loads skip init above.
before_send: (event) => (isPaymentNetworkExplorerPath(window.location.pathname) ? null : event),
// Doubles as the review nudge's friction tap: every money-flow failure
// already funnels through here, so the suppressor needs no call sites.
before_send: (event) => {
if (isPaymentNetworkExplorerPath(window.location.pathname)) return null
if (event?.event) noteAppReviewFriction(event.event)
return event
},
// autocapture walks the DOM ancestor chain on every tap, which costs frames
// in the in-app WebView renderer for data that 220+ explicit
// posthog.capture calls already cover. Native keeps the explicit events only.
Expand Down
4 changes: 4 additions & 0 deletions ios/App/CapApp-SPM/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ let package = Package(
dependencies: [
.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", exact: "8.2.0"),
.package(name: "CapacitorApp", path: "../../../node_modules/.pnpm/@capacitor+app@8.1.0_@capacitor+core@8.2.0/node_modules/@capacitor/app"),
.package(name: "CapacitorAppLauncher", path: "../../../node_modules/.pnpm/@capacitor+app-launcher@8.0.1_@capacitor+core@8.2.0/node_modules/@capacitor/app-launcher"),
.package(name: "CapacitorBrowser", path: "../../../node_modules/.pnpm/@capacitor+browser@8.0.3_@capacitor+core@8.2.0/node_modules/@capacitor/browser"),
.package(name: "CapacitorCamera", path: "../../../node_modules/.pnpm/@capacitor+camera@8.2.0_@capacitor+core@8.2.0/node_modules/@capacitor/camera"),
.package(name: "CapacitorClipboard", path: "../../../node_modules/.pnpm/@capacitor+clipboard@8.0.1_@capacitor+core@8.2.0/node_modules/@capacitor/clipboard"),
Expand All @@ -23,6 +24,7 @@ let package = Package(
.package(name: "CapacitorSplashScreen", path: "../../../node_modules/.pnpm/@capacitor+splash-screen@8.0.1_@capacitor+core@8.2.0/node_modules/@capacitor/splash-screen"),
.package(name: "CapacitorStatusBar", path: "../../../node_modules/.pnpm/@capacitor+status-bar@8.0.2_@capacitor+core@8.2.0/node_modules/@capacitor/status-bar"),
.package(name: "CapgoCapacitorCrisp", path: "../../../node_modules/.pnpm/@capgo+capacitor-crisp@8.0.27_@capacitor+core@8.2.0/node_modules/@capgo/capacitor-crisp"),
.package(name: "CapgoCapacitorInAppReview", path: "../../../node_modules/.pnpm/@capgo+capacitor-in-app-review@8.2.3_@capacitor+core@8.2.0/node_modules/@capgo/capacitor-in-app-review"),
.package(name: "CapgoCapacitorNativeBiometric", path: "../../../node_modules/.pnpm/@capgo+capacitor-native-biometric@8.6.0_@capacitor+core@8.2.0/node_modules/@capgo/capacitor-native-biometric"),
.package(name: "CapgoCapacitorPasskey", path: "../../../node_modules/@capgo/capacitor-passkey"),
.package(name: "CapgoCapacitorUpdater", path: "../../../node_modules/.pnpm/@capgo+capacitor-updater@8.51.14_@capacitor+core@8.2.0/node_modules/@capgo/capacitor-updater"),
Expand All @@ -36,6 +38,7 @@ let package = Package(
.product(name: "Capacitor", package: "capacitor-swift-pm"),
.product(name: "Cordova", package: "capacitor-swift-pm"),
.product(name: "CapacitorApp", package: "CapacitorApp"),
.product(name: "CapacitorAppLauncher", package: "CapacitorAppLauncher"),
.product(name: "CapacitorBrowser", package: "CapacitorBrowser"),
.product(name: "CapacitorCamera", package: "CapacitorCamera"),
.product(name: "CapacitorClipboard", package: "CapacitorClipboard"),
Expand All @@ -46,6 +49,7 @@ let package = Package(
.product(name: "CapacitorSplashScreen", package: "CapacitorSplashScreen"),
.product(name: "CapacitorStatusBar", package: "CapacitorStatusBar"),
.product(name: "CapgoCapacitorCrisp", package: "CapgoCapacitorCrisp"),
.product(name: "CapgoCapacitorInAppReview", package: "CapgoCapacitorInAppReview"),
.product(name: "CapgoCapacitorNativeBiometric", package: "CapgoCapacitorNativeBiometric"),
.product(name: "CapgoCapacitorPasskey", package: "CapgoCapacitorPasskey"),
.product(name: "CapgoCapacitorUpdater", package: "CapgoCapacitorUpdater"),
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"dependencies": {
"@capacitor/android": "8.2.0",
"@capacitor/app": "^8.1.0",
"@capacitor/app-launcher": "8.0.1",
Comment thread
innolope-dev marked this conversation as resolved.
"@capacitor/browser": "^8.0.3",
"@capacitor/camera": "^8.2.0",
"@capacitor/cli": "8.2.0",
Expand All @@ -65,6 +66,7 @@
"@capacitor/splash-screen": "^8.0.1",
"@capacitor/status-bar": "^8.0.2",
"@capgo/capacitor-crisp": "^8.0.27",
"@capgo/capacitor-in-app-review": "8.2.3",
"@capgo/capacitor-native-biometric": "8.6.0",
"@capgo/capacitor-passkey": "^8.2.2",
"@capgo/capacitor-updater": "8.51.14",
Expand Down
24 changes: 24 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions scripts/native-fingerprint.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ let repoRoot = defaultRoot
export const NATIVE_DEPENDENCIES = [
'@capacitor/android',
'@capacitor/app',
'@capacitor/app-launcher',
'@capacitor/browser',
'@capacitor/camera',
'@capacitor/clipboard',
Expand All @@ -96,6 +97,7 @@ export const NATIVE_DEPENDENCIES = [
'@capacitor/splash-screen',
'@capacitor/status-bar',
'@capgo/capacitor-crisp',
'@capgo/capacitor-in-app-review',
'@capgo/capacitor-native-biometric',
'@capgo/capacitor-passkey',
'@capgo/capacitor-updater',
Expand Down
5 changes: 5 additions & 0 deletions src/app/(mobile-ui)/qr-pay/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ import { STAR_STRAIGHT_ICON } from '@/assets/icons'
import { useAuth } from '@/context/authContext'
import { PointsAction } from '@/services/services.types'
import { usePointsConfetti } from '@/hooks/usePointsConfetti'
import { useAppReviewNudge } from '@/hooks/useAppReviewNudge'
import { usePointsCalculation } from '@/hooks/usePointsCalculation'
import { useModalsContext } from '@/context/ModalsContext'
import maintenanceConfig from '@/config/underMaintenance.config'
Expand Down Expand Up @@ -1221,6 +1222,10 @@ export default function QRPayPage() {
}
}, [isSuccess, queryClient])

// the success here is optimistic — a post-factum claim failure keeps the
// user on this screen with an error, and that is not a moment to ask
useAppReviewNudge(user?.user.userId, 'qr_payment_completed', isSuccess && !errorMessage)

useEffect(() => {
if (waitingForMerchantAmount && !isLoadingPaymentLock) {
setWaitingForMerchantAmount(false)
Expand Down
4 changes: 4 additions & 0 deletions src/components/Claim/Link/Onchain/Success.view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import CreateAccountButton from '@/components/Global/CreateAccountButton'
import { PeanutCheering } from '@/assets/mascot'
import Image from 'next/image'
import { useAppHaptic } from '@/hooks/useAppHaptic'
import { useAppReviewNudge } from '@/hooks/useAppReviewNudge'
import { useTranslations } from 'next-intl'
import { Notification } from '@/components/0_Bruddle/Notification'
import Loading from '@/components/Global/Loading'
Expand Down Expand Up @@ -181,6 +182,9 @@ export const SuccessClaimLinkView = ({
triggerHaptic()
}, [isClaimed, triggerHaptic])

// same gate as the haptic: a confirmed claim, never the optimistic mount
useAppReviewNudge(authUser?.user.userId, 'money_received', isClaimed && !claimFailure)

// The optimistic 202 lands here with no outcome yet. Hold the processing
// state until the claim is confirmed — rendering success before that would
// claim money that has not moved.
Expand Down
6 changes: 6 additions & 0 deletions src/components/Home/HomeCarouselCTA/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { useAuth } from '@/context/authContext'
import { useWebSocket } from '@/hooks/useWebSocket'
import { extractInviteeName } from '@/utils/general.utils'
import PerkClaimModal from '../PerkClaimModal'
import { useAppReviewNudge } from '@/hooks/useAppReviewNudge'

const HomeCarouselCTA = () => {
const t = useTranslations('home.carousel')
Expand Down Expand Up @@ -86,6 +87,11 @@ const HomeCarouselCTA = () => {
setSelectedPerk(null)
}, [])

// reward claimed and our modal gone: a friend joined, money landed, and
// nothing of ours is on screen. Lives here rather than in PerkClaimModal,
// which unmounts with `selectedPerk` and would take the pending ask with it.
useAppReviewNudge(user?.user.userId, 'reward_claimed', claimedPerkIds.size > 0 && !selectedPerk)

// don't render carousel if there are no CTAs
if (!allCTAs.length) return null

Expand Down
90 changes: 0 additions & 90 deletions src/components/Migration/ReviewPromptModal.tsx

This file was deleted.

28 changes: 28 additions & 0 deletions src/components/Profile/views/About.view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import { LEGAL_POLICIES } from '@/constants/legal-policies'
import { useAuth } from '@/context/authContext'
import { claimPeanutTeamBadge } from '@/services/peanut-team-badge'
import { useAppVersion } from '@/hooks/useAppVersion'
import { DeviceType, useDeviceType } from '@/hooks/useGetDeviceType'
import { openStoreReviewPage } from '@/utils/app-review'
import { isNativeBridge } from '@/utils/capacitor'
import { useSafeBack } from '@/hooks/useSafeBack'
import { useTranslations } from 'next-intl'
import { useEffect, useRef, useState } from 'react'
Expand All @@ -32,6 +35,12 @@ export const AboutView = ({ appVersion }: { appVersion: string }) => {
const betaAccess = useBetaUpdatesAccess()
const betaCardRef = useRef<HTMLDivElement>(null)
const { fetchUser } = useAuth()
const { deviceType } = useDeviceType()
const store = deviceType === DeviceType.ANDROID ? 'android' : 'ios'
// false through SSR and the first client render — a render-time bridge check
// disagrees with the prerendered html and hard-fails hydration in the WebView
const [isNative, setIsNative] = useState(false)
useEffect(() => setIsNative(isNativeBridge()), [])

useEffect(() => {
if (betaRevealed) betaCardRef.current?.scrollIntoView?.({ behavior: 'smooth', block: 'nearest' })
Expand Down Expand Up @@ -88,6 +97,25 @@ export const AboutView = ({ appVersion }: { appVersion: string }) => {
))}
</div>

{/* Native only: the web has no store listing to review against.
A row the user taps themselves, never a prompt — see
utils/app-review.ts for why that distinction is the whole rule. */}
{isNative && (
<div>
<h1 className="mb-2 font-bold text-black">{t('rateHeading')}</h1>
<Card position="first">
<button
type="button"
onClick={() => void openStoreReviewPage(store)}
className="flex w-full cursor-pointer justify-between py-1"
>
<span className="text-body-s text-black">{t('rate')}</span>
<NavigationArrow size={24} className="fill-black" />
</button>
</Card>
</div>
)}

{betaRevealed && (
<div ref={betaCardRef}>
<BetaUpdatesCard />
Expand Down
Loading
Loading