import {useState} from 'react' import {View} from 'react-native' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {wait} from '#/lib/async/wait' import {isNetworkError, useCleanError} from '#/lib/hooks/useCleanError' import {logger} from '#/logger' import {isWeb} from '#/platform/detection' import { computeGeolocationStatus, type GeolocationStatus, useGeolocationConfig, } from '#/state/geolocation' import {useRequestDeviceLocation} from '#/state/geolocation/useRequestDeviceLocation' import {atoms as a, useTheme, web} from '#/alf' import {Admonition} from '#/components/Admonition' import {Button, ButtonIcon, ButtonText} from '#/components/Button' import * as Dialog from '#/components/Dialog' import {PinLocation_Stroke2_Corner0_Rounded as LocationIcon} from '#/components/icons/PinLocation' import {Loader} from '#/components/Loader' import {Text} from '#/components/Typography' export type Props = { onLocationAcquired?: (props: { geolocationStatus: GeolocationStatus setDialogError: (error: string) => void disableDialogAction: () => void closeDialog: (callback?: () => void) => void }) => void } export function DeviceLocationRequestDialog({ control, onLocationAcquired, }: Props & { control: Dialog.DialogOuterProps['control'] }) { const {_} = useLingui() return ( ) } function DeviceLocationRequestDialogInner({onLocationAcquired}: Props) { const t = useTheme() const {_} = useLingui() const {close} = Dialog.useDialogContext() const requestDeviceLocation = useRequestDeviceLocation() const {config} = useGeolocationConfig() const cleanError = useCleanError() const [isRequesting, setIsRequesting] = useState(false) const [error, setError] = useState('') const [dialogDisabled, setDialogDisabled] = useState(false) const onPressConfirm = async () => { setError('') setIsRequesting(true) try { const req = await wait(1e3, requestDeviceLocation()) if (req.granted) { const location = req.location if (location && location.countryCode) { const geolocationStatus = computeGeolocationStatus(location, config) onLocationAcquired?.({ geolocationStatus, setDialogError: setError, disableDialogAction: () => setDialogDisabled(true), closeDialog: close, }) } else { setError(_(msg`Failed to resolve location. Please try again.`)) } } else { setError( _( msg`Unable to access location. You'll need to visit your system settings to enable location services for Bluesky.`, ), ) } } catch (e: any) { const {clean, raw} = cleanError(e) setError(clean || raw || e.message) if (!isNetworkError(e)) { logger.error(`blockedGeoOverlay: unexpected error`, { safeMessage: e.message, }) } } finally { setIsRequesting(false) } } return ( Confirm your location Tap below to allow Bluesky to access your GPS location. We will then use that data to more accurately determine the content and features available in your region. Your location data is not tracked and does not leave your device. {error && ( {error} )} {!dialogDisabled && ( )} {!isWeb && ( )} ) }