feat(release): prepare 1.1.0 candidate
This commit is contained in:
parent
5a34f66981
commit
5205dcdfa9
736 changed files with 115667 additions and 12203 deletions
98
apps/mobile-rn/src/components/FreeTierBanner.tsx
Normal file
98
apps/mobile-rn/src/components/FreeTierBanner.tsx
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
import { useEffect, useState } from 'react'
|
||||
import { StyleSheet, View } from 'react-native'
|
||||
import {
|
||||
BannerAd,
|
||||
BannerAdSize,
|
||||
} from 'react-native-google-mobile-ads'
|
||||
import { useMobileAds } from '../lib/mobile-ads-context'
|
||||
import { useMobilePreferences } from '../lib/preferences-context'
|
||||
import { ThemeText } from '../theme/themed-components'
|
||||
|
||||
const INITIAL_RETRY_DELAY_MS = 30_000
|
||||
const MAX_RETRY_DELAY_MS = 5 * 60_000
|
||||
|
||||
export default function FreeTierBanner(): React.ReactElement | null {
|
||||
const ads = useMobileAds()
|
||||
const { palette } = useMobilePreferences()
|
||||
const [loaded, setLoaded] = useState(false)
|
||||
const [failed, setFailed] = useState(false)
|
||||
const [retryAttempt, setRetryAttempt] = useState(0)
|
||||
const [retryKey, setRetryKey] = useState(0)
|
||||
|
||||
useEffect(() => {
|
||||
setLoaded(false)
|
||||
setFailed(false)
|
||||
setRetryAttempt(0)
|
||||
setRetryKey(0)
|
||||
}, [ads.bannerUnitId])
|
||||
|
||||
useEffect(() => {
|
||||
if (!failed || !ads.bannerUnitId) return undefined
|
||||
const delay = Math.min(
|
||||
INITIAL_RETRY_DELAY_MS * (2 ** retryAttempt),
|
||||
MAX_RETRY_DELAY_MS,
|
||||
)
|
||||
const timer = setTimeout(() => {
|
||||
setLoaded(false)
|
||||
setFailed(false)
|
||||
setRetryAttempt((current) => current + 1)
|
||||
setRetryKey((current) => current + 1)
|
||||
}, delay)
|
||||
return () => clearTimeout(timer)
|
||||
}, [ads.bannerUnitId, failed, retryAttempt])
|
||||
|
||||
if (!ads.eligible) return null
|
||||
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
styles.slot,
|
||||
{
|
||||
backgroundColor: palette.bg.inset,
|
||||
borderTopColor: palette.border.subtle,
|
||||
},
|
||||
]}
|
||||
testID="free-tier-ad-slot"
|
||||
accessibilityLabel="Sponsored"
|
||||
>
|
||||
{ads.bannerUnitId && !failed ? (
|
||||
<BannerAd
|
||||
key={`${ads.bannerUnitId}:${retryKey}`}
|
||||
unitId={ads.bannerUnitId}
|
||||
size={BannerAdSize.ANCHORED_ADAPTIVE_BANNER}
|
||||
requestOptions={{ requestNonPersonalizedAdsOnly: true }}
|
||||
onAdLoaded={() => {
|
||||
setLoaded(true)
|
||||
setFailed(false)
|
||||
setRetryAttempt(0)
|
||||
}}
|
||||
onAdFailedToLoad={() => {
|
||||
setLoaded(false)
|
||||
setFailed(true)
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<ThemeText variant="label" color="muted" style={styles.statusText}>
|
||||
{failed ? 'AD UNAVAILABLE' : ads.status === 'ready' ? 'AD LOADING' : 'AD CONSENT'}
|
||||
</ThemeText>
|
||||
)}
|
||||
{ads.bannerUnitId && !loaded && !failed && (
|
||||
<ThemeText variant="label" color="muted" style={styles.loadingOverlay}>
|
||||
AD LOADING
|
||||
</ThemeText>
|
||||
)}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
slot: {
|
||||
minHeight: 50,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
borderTopWidth: 1,
|
||||
overflow: 'hidden',
|
||||
},
|
||||
statusText: { fontSize: 9, letterSpacing: 1.2 },
|
||||
loadingOverlay: { position: 'absolute', fontSize: 9, letterSpacing: 1.2 },
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue