add android handling

This commit is contained in:
Hailey
2024-06-16 21:24:50 -07:00
parent a09d699249
commit af124cc8b8
5 changed files with 50 additions and 15 deletions
+1
View File
@@ -1,3 +1,4 @@
export const isSafari = false export const isSafari = false
export const isFirefox = false export const isFirefox = false
export const isTouchDevice = true export const isTouchDevice = true
export const isAndroidWeb = false
+2
View File
@@ -5,3 +5,5 @@ export const isSafari = /^((?!chrome|android).)*safari/i.test(
export const isFirefox = /firefox|fxios/i.test(navigator.userAgent) export const isFirefox = /firefox|fxios/i.test(navigator.userAgent)
export const isTouchDevice = export const isTouchDevice =
'ontouchstart' in window || navigator.maxTouchPoints > 1 'ontouchstart' in window || navigator.maxTouchPoints > 1
export const isAndroidWeb =
/android/i.test(navigator.userAgent) && isTouchDevice
@@ -5,6 +5,7 @@ import {AppBskyGraphDefs, AppBskyGraphStarterpack} from '@atproto/api'
import {msg, Trans} from '@lingui/macro' import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {isAndroidWeb} from 'lib/browser'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import { import {
useSetUsedStarterPack, useSetUsedStarterPack,
@@ -17,15 +18,27 @@ import {CenteredView} from 'view/com/util/Views'
import {Logo} from 'view/icons/Logo' import {Logo} from 'view/icons/Logo'
import {atoms as a, useTheme} from '#/alf' import {atoms as a, useTheme} from '#/alf'
import {Button, ButtonText} from '#/components/Button' import {Button, ButtonText} from '#/components/Button'
import {useDialogControl} from '#/components/Dialog'
import {Divider} from '#/components/Divider' import {Divider} from '#/components/Divider'
import * as FeedCard from '#/components/FeedCard' import * as FeedCard from '#/components/FeedCard'
import {LinearGradientBackground} from '#/components/LinearGradientBackground' import {LinearGradientBackground} from '#/components/LinearGradientBackground'
import {ListMaybePlaceholder} from '#/components/Lists' import {ListMaybePlaceholder} from '#/components/Lists'
import {Default as ProfileCardInner} from '#/components/ProfileCard' import {Default as ProfileCardInner} from '#/components/ProfileCard'
import * as Prompt from '#/components/Prompt'
import {Text} from '#/components/Typography' import {Text} from '#/components/Typography'
const AnimatedPressable = Animated.createAnimatedComponent(Pressable) const AnimatedPressable = Animated.createAnimatedComponent(Pressable)
interface AppClipMessage {
action: 'present' | 'store'
keyToStoreAs?: string
jsonToStore?: string
}
function postAppClipMessage(message: AppClipMessage) {
window.webkit.messageHandlers.onMessage.postMessage(JSON.stringify(message))
}
function parseStarterPackHttpUri(uri: string): {name?: string; rkey?: string} { function parseStarterPackHttpUri(uri: string): {name?: string; rkey?: string} {
const parsed = new URL(uri) const parsed = new URL(uri)
const [_, _path, name, rkey] = parsed.pathname.split('/') const [_, _path, name, rkey] = parsed.pathname.split('/')
@@ -35,14 +48,8 @@ function parseStarterPackHttpUri(uri: string): {name?: string; rkey?: string} {
} }
} }
interface AppClipMessage { function createGooglePlayLink(name: string, rkey: string) {
action: 'present' | 'store' return `https://play.google.com/store/apps/details?id=xyz.blueskyweb.app&referrer=utm_source%3Dbluesky%26utm_medium%3Dstarterpack%26utm_content%3Dstarterpack-${name}-${rkey}`
keyToStoreAs?: string
jsonToStore?: string
}
function postAppClipMessage(message: AppClipMessage) {
window.webkit.messageHandlers.onMessage.postMessage(JSON.stringify(message))
} }
export function LandingScreen({ export function LandingScreen({
@@ -104,24 +111,30 @@ function LandingScreenInner({
const setUsedStarterPack = useSetUsedStarterPack() const setUsedStarterPack = useSetUsedStarterPack()
const usedStarterPack = useUsedStarterPack() const usedStarterPack = useUsedStarterPack()
const {isTabletOrDesktop} = useWebMediaQueries() const {isTabletOrDesktop} = useWebMediaQueries()
const androidDialogControl = useDialogControl()
const [appClipOverlayVisible, setAppClipOverlayVisible] = const [appClipOverlayVisible, setAppClipOverlayVisible] =
React.useState(false) React.useState(false)
const listItemsCount = starterPack.list?.listItemCount ?? 0 const listItemsCount = starterPack.list?.listItemCount ?? 0
const onContinue = () => {
setUsedStarterPack({
uri: starterPack.uri,
})
setScreenState(LoggedOutScreenState.S_CreateAccount)
}
const onJoinPress = () => { const onJoinPress = () => {
if (usedStarterPack?.isClip) { if (usedStarterPack?.isClip) {
setAppClipOverlayVisible(true) setAppClipOverlayVisible(true)
postAppClipMessage({ postAppClipMessage({
action: 'present', action: 'present',
}) })
} else if (isAndroidWeb) {
androidDialogControl.open()
} else { } else {
setUsedStarterPack({ onContinue()
uri: starterPack.uri,
cid: starterPack.cid,
})
setScreenState(LoggedOutScreenState.S_CreateAccount)
} }
} }
@@ -275,6 +288,27 @@ function LandingScreenInner({
visible={appClipOverlayVisible} visible={appClipOverlayVisible}
setIsVisible={setAppClipOverlayVisible} setIsVisible={setAppClipOverlayVisible}
/> />
<Prompt.Outer control={androidDialogControl}>
<Prompt.TitleText />
<Prompt.DescriptionText />
<Prompt.Actions>
<Prompt.Action
cta="Continue on web"
color="secondary"
onPress={onContinue}
/>
<Prompt.Action
cta="Download on Google Play"
color="primary"
onPress={() => {
const rkey = parseStarterPackHttpUri(starterPack.uri).rkey
if (!rkey) return
window.location.href = createGooglePlayLink(creator.handle, rkey)
}}
/>
</Prompt.Actions>
</Prompt.Outer>
</CenteredView> </CenteredView>
) )
} }
-1
View File
@@ -91,7 +91,6 @@ export const schema = z.object({
usedStarterPack: z usedStarterPack: z
.object({ .object({
uri: z.string(), uri: z.string(),
cid: z.string().optional(),
initialFeed: z.string().optional(), initialFeed: z.string().optional(),
isClip: z.boolean().optional(), isClip: z.boolean().optional(),
lastUsedUri: z.string().optional(), lastUsedUri: z.string().optional(),
-1
View File
@@ -5,7 +5,6 @@ import * as persisted from '#/state/persisted'
type StateContext = type StateContext =
| { | {
uri: string uri: string
cid?: string
initialFeed?: string initialFeed?: string
isClip?: boolean isClip?: boolean
lastUsedUri?: string lastUsedUri?: string