Move /platform/detection vars into /env (#9707)
* Add platform vars to env * Replace /platform/detection with /env
This commit is contained in:
@@ -439,9 +439,9 @@ Example from Dialog:
|
|||||||
|
|
||||||
Platform detection:
|
Platform detection:
|
||||||
```tsx
|
```tsx
|
||||||
import {isWeb, isNative, isIOS, isAndroid} from '#/platform/detection'
|
import {IS_WEB, IS_NATIVE, IS_IOS, IS_ANDROID} from '#/env'
|
||||||
|
|
||||||
if (isNative) {
|
if (IS_NATIVE) {
|
||||||
// Native-specific logic
|
// Native-specific logic
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||||
import {requireNativeModule, requireNativeViewManager} from 'expo-modules-core'
|
import {requireNativeModule, requireNativeViewManager} from 'expo-modules-core'
|
||||||
|
|
||||||
import {isIOS} from '#/platform/detection'
|
import {IS_IOS} from '#/env'
|
||||||
import {
|
import {
|
||||||
type BottomSheetState,
|
type BottomSheetState,
|
||||||
type BottomSheetViewProps,
|
type BottomSheetViewProps,
|
||||||
@@ -30,7 +30,7 @@ const NativeView: React.ComponentType<
|
|||||||
|
|
||||||
const NativeModule = requireNativeModule('BottomSheet')
|
const NativeModule = requireNativeModule('BottomSheet')
|
||||||
|
|
||||||
const isIOS15 =
|
const IS_IOS15 =
|
||||||
Platform.OS === 'ios' &&
|
Platform.OS === 'ios' &&
|
||||||
// semvar - can be 3 segments, so can't use Number(Platform.Version)
|
// semvar - can be 3 segments, so can't use Number(Platform.Version)
|
||||||
Number(Platform.Version.split('.').at(0)) < 16
|
Number(Platform.Version.split('.').at(0)) < 16
|
||||||
@@ -91,7 +91,7 @@ export class BottomSheetNativeComponent extends React.Component<
|
|||||||
}
|
}
|
||||||
|
|
||||||
let extraStyles
|
let extraStyles
|
||||||
if (isIOS15 && this.state.viewHeight) {
|
if (IS_IOS15 && this.state.viewHeight) {
|
||||||
const {viewHeight} = this.state
|
const {viewHeight} = this.state
|
||||||
const cornerRadius = this.props.cornerRadius ?? 0
|
const cornerRadius = this.props.cornerRadius ?? 0
|
||||||
if (viewHeight < screenHeight / 2) {
|
if (viewHeight < screenHeight / 2) {
|
||||||
@@ -112,7 +112,7 @@ export class BottomSheetNativeComponent extends React.Component<
|
|||||||
onStateChange={this.onStateChange}
|
onStateChange={this.onStateChange}
|
||||||
extraStyles={extraStyles}
|
extraStyles={extraStyles}
|
||||||
onLayout={e => {
|
onLayout={e => {
|
||||||
if (isIOS15) {
|
if (IS_IOS15) {
|
||||||
const {height} = e.nativeEvent.layout
|
const {height} = e.nativeEvent.layout
|
||||||
this.setState({viewHeight: height})
|
this.setState({viewHeight: height})
|
||||||
}
|
}
|
||||||
@@ -153,7 +153,7 @@ function BottomSheetNativeComponentInner({
|
|||||||
const insets = useSafeAreaInsets()
|
const insets = useSafeAreaInsets()
|
||||||
const cornerRadius = rest.cornerRadius ?? 0
|
const cornerRadius = rest.cornerRadius ?? 0
|
||||||
|
|
||||||
const sheetHeight = isIOS ? screenHeight - insets.top : screenHeight
|
const sheetHeight = IS_IOS ? screenHeight - insets.top : screenHeight
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NativeView
|
<NativeView
|
||||||
|
|||||||
+3
-3
@@ -23,7 +23,6 @@ import {s} from '#/lib/styles'
|
|||||||
import {ThemeProvider} from '#/lib/ThemeContext'
|
import {ThemeProvider} from '#/lib/ThemeContext'
|
||||||
import I18nProvider from '#/locale/i18nProvider'
|
import I18nProvider from '#/locale/i18nProvider'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {isAndroid, isIOS} from '#/platform/detection'
|
|
||||||
import {Provider as A11yProvider} from '#/state/a11y'
|
import {Provider as A11yProvider} from '#/state/a11y'
|
||||||
import {Provider as MutedThreadsProvider} from '#/state/cache/thread-mutes'
|
import {Provider as MutedThreadsProvider} from '#/state/cache/thread-mutes'
|
||||||
import {Provider as DialogStateProvider} from '#/state/dialogs'
|
import {Provider as DialogStateProvider} from '#/state/dialogs'
|
||||||
@@ -69,6 +68,7 @@ import {Provider as VideoVolumeProvider} from '#/components/Post/Embed/VideoEmbe
|
|||||||
import {ToastOutlet} from '#/components/Toast'
|
import {ToastOutlet} from '#/components/Toast'
|
||||||
import {Provider as AgeAssuranceV2Provider} from '#/ageAssurance'
|
import {Provider as AgeAssuranceV2Provider} from '#/ageAssurance'
|
||||||
import {prefetchAgeAssuranceConfig} from '#/ageAssurance'
|
import {prefetchAgeAssuranceConfig} from '#/ageAssurance'
|
||||||
|
import {IS_ANDROID, IS_IOS} from '#/env'
|
||||||
import {
|
import {
|
||||||
prefetchLiveEvents,
|
prefetchLiveEvents,
|
||||||
Provider as LiveEventsProvider,
|
Provider as LiveEventsProvider,
|
||||||
@@ -79,10 +79,10 @@ import {BottomSheetProvider} from '../modules/bottom-sheet'
|
|||||||
import {BackgroundNotificationPreferencesProvider} from '../modules/expo-background-notification-handler/src/BackgroundNotificationHandlerProvider'
|
import {BackgroundNotificationPreferencesProvider} from '../modules/expo-background-notification-handler/src/BackgroundNotificationHandlerProvider'
|
||||||
|
|
||||||
SplashScreen.preventAutoHideAsync()
|
SplashScreen.preventAutoHideAsync()
|
||||||
if (isIOS) {
|
if (IS_IOS) {
|
||||||
SystemUI.setBackgroundColorAsync('black')
|
SystemUI.setBackgroundColorAsync('black')
|
||||||
}
|
}
|
||||||
if (isAndroid) {
|
if (IS_ANDROID) {
|
||||||
// iOS is handled by the config plugin -sfn
|
// iOS is handled by the config plugin -sfn
|
||||||
ScreenOrientation.lockAsync(
|
ScreenOrientation.lockAsync(
|
||||||
ScreenOrientation.OrientationLock.PORTRAIT_UP,
|
ScreenOrientation.OrientationLock.PORTRAIT_UP,
|
||||||
|
|||||||
+6
-6
@@ -44,7 +44,6 @@ import {type RouteParams, type State} from '#/lib/routes/types'
|
|||||||
import {attachRouteToLogEvents, logEvent} from '#/lib/statsig/statsig'
|
import {attachRouteToLogEvents, logEvent} from '#/lib/statsig/statsig'
|
||||||
import {bskyTitle} from '#/lib/strings/headings'
|
import {bskyTitle} from '#/lib/strings/headings'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {isNative, isWeb} from '#/platform/detection'
|
|
||||||
import {useUnreadNotifications} from '#/state/queries/notifications/unread'
|
import {useUnreadNotifications} from '#/state/queries/notifications/unread'
|
||||||
import {useSession} from '#/state/session'
|
import {useSession} from '#/state/session'
|
||||||
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
|
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
|
||||||
@@ -138,6 +137,7 @@ import {
|
|||||||
EmailDialogScreenID,
|
EmailDialogScreenID,
|
||||||
useEmailDialogControl,
|
useEmailDialogControl,
|
||||||
} from '#/components/dialogs/EmailDialog'
|
} from '#/components/dialogs/EmailDialog'
|
||||||
|
import {IS_NATIVE, IS_WEB} from '#/env'
|
||||||
import {router} from '#/routes'
|
import {router} from '#/routes'
|
||||||
import {Referrer} from '../modules/expo-bluesky-swiss-army'
|
import {Referrer} from '../modules/expo-bluesky-swiss-army'
|
||||||
|
|
||||||
@@ -842,11 +842,11 @@ const LINKING = {
|
|||||||
// native, since the home tab and the home screen are defined as initial routes, we don't need to return a state
|
// native, since the home tab and the home screen are defined as initial routes, we don't need to return a state
|
||||||
// since it will be created by react-navigation.
|
// since it will be created by react-navigation.
|
||||||
if (path.includes('intent/')) {
|
if (path.includes('intent/')) {
|
||||||
if (isNative) return
|
if (IS_NATIVE) return
|
||||||
return buildStateObject('Flat', 'Home', params)
|
return buildStateObject('Flat', 'Home', params)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isNative) {
|
if (IS_NATIVE) {
|
||||||
if (name === 'Search') {
|
if (name === 'Search') {
|
||||||
return buildStateObject('SearchTab', 'Search', params)
|
return buildStateObject('SearchTab', 'Search', params)
|
||||||
}
|
}
|
||||||
@@ -921,7 +921,7 @@ function RoutesContainer({children}: React.PropsWithChildren<{}>) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
async function handlePushNotificationEntry() {
|
async function handlePushNotificationEntry() {
|
||||||
if (!isNative) return
|
if (!IS_NATIVE) return
|
||||||
|
|
||||||
// deep links take precedence - on android,
|
// deep links take precedence - on android,
|
||||||
// getLastNotificationResponseAsync returns a "notification"
|
// getLastNotificationResponseAsync returns a "notification"
|
||||||
@@ -1069,7 +1069,7 @@ function reset(): Promise<void> {
|
|||||||
navigationRef.dispatch(
|
navigationRef.dispatch(
|
||||||
CommonActions.reset({
|
CommonActions.reset({
|
||||||
index: 0,
|
index: 0,
|
||||||
routes: [{name: isNative ? 'HomeTab' : 'Home'}],
|
routes: [{name: IS_NATIVE ? 'HomeTab' : 'Home'}],
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
return Promise.race([
|
return Promise.race([
|
||||||
@@ -1103,7 +1103,7 @@ function logModuleInitTime() {
|
|||||||
initMs,
|
initMs,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (isWeb) {
|
if (IS_WEB) {
|
||||||
const referrerInfo = Referrer.getReferrerInfo()
|
const referrerInfo = Referrer.getReferrerInfo()
|
||||||
if (referrerInfo && referrerInfo.hostname !== 'bsky.app') {
|
if (referrerInfo && referrerInfo.hostname !== 'bsky.app') {
|
||||||
logEvent('deepLink:referrerReceived', {
|
logEvent('deepLink:referrerReceived', {
|
||||||
|
|||||||
@@ -10,8 +10,6 @@ import {
|
|||||||
} from '#/lib/hooks/useCreateSupportLink'
|
} from '#/lib/hooks/useCreateSupportLink'
|
||||||
import {dateDiff, useGetTimeAgo} from '#/lib/hooks/useTimeAgo'
|
import {dateDiff, useGetTimeAgo} from '#/lib/hooks/useTimeAgo'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {isWeb} from '#/platform/detection'
|
|
||||||
import {isNative} from '#/platform/detection'
|
|
||||||
import {useIsBirthdateUpdateAllowed} from '#/state/birthdate'
|
import {useIsBirthdateUpdateAllowed} from '#/state/birthdate'
|
||||||
import {useSessionApi} from '#/state/session'
|
import {useSessionApi} from '#/state/session'
|
||||||
import {atoms as a, useBreakpoints, useTheme, web} from '#/alf'
|
import {atoms as a, useBreakpoints, useTheme, web} from '#/alf'
|
||||||
@@ -38,6 +36,8 @@ import {
|
|||||||
isLegacyBirthdateBug,
|
isLegacyBirthdateBug,
|
||||||
useAgeAssuranceRegionConfig,
|
useAgeAssuranceRegionConfig,
|
||||||
} from '#/ageAssurance/util'
|
} from '#/ageAssurance/util'
|
||||||
|
import {IS_WEB} from '#/env'
|
||||||
|
import {IS_NATIVE} from '#/env'
|
||||||
import {useDeviceGeolocationApi} from '#/geolocation'
|
import {useDeviceGeolocationApi} from '#/geolocation'
|
||||||
|
|
||||||
const textStyles = [a.text_md, a.leading_snug]
|
const textStyles = [a.text_md, a.leading_snug]
|
||||||
@@ -74,7 +74,7 @@ export function NoAccessScreen() {
|
|||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const onPressLogout = useCallback(() => {
|
const onPressLogout = useCallback(() => {
|
||||||
if (isWeb) {
|
if (IS_WEB) {
|
||||||
// We're switching accounts, which remounts the entire app.
|
// We're switching accounts, which remounts the entire app.
|
||||||
// On mobile, this gets us Home, but on the web we also need reset the URL.
|
// On mobile, this gets us Home, but on the web we also need reset the URL.
|
||||||
// We can't change the URL via a navigate() call because the navigator
|
// We can't change the URL via a navigate() call because the navigator
|
||||||
@@ -139,7 +139,7 @@ export function NoAccessScreen() {
|
|||||||
contentContainerStyle={[
|
contentContainerStyle={[
|
||||||
a.px_2xl,
|
a.px_2xl,
|
||||||
{
|
{
|
||||||
paddingTop: isWeb
|
paddingTop: IS_WEB
|
||||||
? a.p_5xl.padding
|
? a.p_5xl.padding
|
||||||
: insets.top + a.p_2xl.padding,
|
: insets.top + a.p_2xl.padding,
|
||||||
paddingBottom: 100,
|
paddingBottom: 100,
|
||||||
@@ -359,7 +359,7 @@ function AccessSection() {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<View style={[a.gap_xs]}>
|
<View style={[a.gap_xs]}>
|
||||||
{isNative && (
|
{IS_NATIVE && (
|
||||||
<>
|
<>
|
||||||
<Admonition>
|
<Admonition>
|
||||||
<Trans>
|
<Trans>
|
||||||
|
|||||||
@@ -15,8 +15,6 @@ import {useLingui} from '@lingui/react'
|
|||||||
import {retry} from '#/lib/async/retry'
|
import {retry} from '#/lib/async/retry'
|
||||||
import {wait} from '#/lib/async/wait'
|
import {wait} from '#/lib/async/wait'
|
||||||
import {parseLinkingUrl} from '#/lib/parseLinkingUrl'
|
import {parseLinkingUrl} from '#/lib/parseLinkingUrl'
|
||||||
import {isWeb} from '#/platform/detection'
|
|
||||||
import {isIOS} from '#/platform/detection'
|
|
||||||
import {useAgent, useSession} from '#/state/session'
|
import {useAgent, useSession} from '#/state/session'
|
||||||
import {atoms as a, platform, useBreakpoints, useTheme} from '#/alf'
|
import {atoms as a, platform, useBreakpoints, useTheme} from '#/alf'
|
||||||
import {AgeAssuranceBadge} from '#/components/ageAssurance/AgeAssuranceBadge'
|
import {AgeAssuranceBadge} from '#/components/ageAssurance/AgeAssuranceBadge'
|
||||||
@@ -28,6 +26,8 @@ import {Loader} from '#/components/Loader'
|
|||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
import {refetchAgeAssuranceServerState} from '#/ageAssurance'
|
import {refetchAgeAssuranceServerState} from '#/ageAssurance'
|
||||||
import {logger} from '#/ageAssurance'
|
import {logger} from '#/ageAssurance'
|
||||||
|
import {IS_WEB} from '#/env'
|
||||||
|
import {IS_IOS} from '#/env'
|
||||||
|
|
||||||
export type RedirectOverlayState = {
|
export type RedirectOverlayState = {
|
||||||
result: 'success' | 'unknown'
|
result: 'success' | 'unknown'
|
||||||
@@ -92,7 +92,7 @@ export function Provider({children}: {children?: React.ReactNode}) {
|
|||||||
actorDid: params.get('actorDid') ?? undefined,
|
actorDid: params.get('actorDid') ?? undefined,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (isWeb) {
|
if (IS_WEB) {
|
||||||
// Clear the URL parameters so they don't re-trigger
|
// Clear the URL parameters so they don't re-trigger
|
||||||
history.pushState(null, '', '/')
|
history.pushState(null, '', '/')
|
||||||
}
|
}
|
||||||
@@ -145,7 +145,7 @@ export function RedirectOverlay() {
|
|||||||
// setting a zIndex when using FullWindowOverlay on iOS
|
// setting a zIndex when using FullWindowOverlay on iOS
|
||||||
// means the taps pass straight through to the underlying content (???)
|
// means the taps pass straight through to the underlying content (???)
|
||||||
// so don't set it on iOS. FullWindowOverlay already does the job.
|
// so don't set it on iOS. FullWindowOverlay already does the job.
|
||||||
!isIOS && {zIndex: 9999},
|
!IS_IOS && {zIndex: 9999},
|
||||||
t.atoms.bg,
|
t.atoms.bg,
|
||||||
gtMobile ? a.p_2xl : a.p_xl,
|
gtMobile ? a.p_2xl : a.p_xl,
|
||||||
a.align_center,
|
a.align_center,
|
||||||
|
|||||||
+4
-4
@@ -1,6 +1,6 @@
|
|||||||
import {type TextStyle} from 'react-native'
|
import {type TextStyle} from 'react-native'
|
||||||
|
|
||||||
import {isAndroid, isWeb} from '#/platform/detection'
|
import {IS_ANDROID, IS_WEB} from '#/env'
|
||||||
import {type Device, device} from '#/storage'
|
import {type Device, device} from '#/storage'
|
||||||
|
|
||||||
const WEB_FONT_FAMILIES = `system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"`
|
const WEB_FONT_FAMILIES = `system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"`
|
||||||
@@ -39,7 +39,7 @@ export function setFontFamily(fontFamily: Device['fontFamily']) {
|
|||||||
*/
|
*/
|
||||||
export function applyFonts(style: TextStyle, fontFamily: 'system' | 'theme') {
|
export function applyFonts(style: TextStyle, fontFamily: 'system' | 'theme') {
|
||||||
if (fontFamily === 'theme') {
|
if (fontFamily === 'theme') {
|
||||||
if (isAndroid) {
|
if (IS_ANDROID) {
|
||||||
style.fontFamily =
|
style.fontFamily =
|
||||||
{
|
{
|
||||||
400: 'Inter-Regular',
|
400: 'Inter-Regular',
|
||||||
@@ -71,7 +71,7 @@ export function applyFonts(style: TextStyle, fontFamily: 'system' | 'theme') {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isWeb) {
|
if (IS_WEB) {
|
||||||
// fallback families only supported on web
|
// fallback families only supported on web
|
||||||
style.fontFamily += `, ${WEB_FONT_FAMILIES}`
|
style.fontFamily += `, ${WEB_FONT_FAMILIES}`
|
||||||
}
|
}
|
||||||
@@ -83,7 +83,7 @@ export function applyFonts(style: TextStyle, fontFamily: 'system' | 'theme') {
|
|||||||
style.fontVariant = (style.fontVariant || []).concat('no-contextual')
|
style.fontVariant = (style.fontVariant || []).concat('no-contextual')
|
||||||
} else {
|
} else {
|
||||||
// fallback families only supported on web
|
// fallback families only supported on web
|
||||||
if (isWeb) {
|
if (IS_WEB) {
|
||||||
style.fontFamily = style.fontFamily || WEB_FONT_FAMILIES
|
style.fontFamily = style.fontFamily || WEB_FONT_FAMILIES
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import {type StyleProp, type TextStyle} from 'react-native'
|
|||||||
import {UITextView} from 'react-native-uitextview'
|
import {UITextView} from 'react-native-uitextview'
|
||||||
import createEmojiRegex from 'emoji-regex'
|
import createEmojiRegex from 'emoji-regex'
|
||||||
|
|
||||||
import {isNative} from '#/platform/detection'
|
|
||||||
import {isIOS} from '#/platform/detection'
|
|
||||||
import {type Alf, applyFonts, atoms, flatten} from '#/alf'
|
import {type Alf, applyFonts, atoms, flatten} from '#/alf'
|
||||||
|
import {IS_NATIVE} from '#/env'
|
||||||
|
import {IS_IOS} from '#/env'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensures that `lineHeight` defaults to a relative value of `1`, or applies
|
* Ensures that `lineHeight` defaults to a relative value of `1`, or applies
|
||||||
@@ -34,7 +34,7 @@ export function normalizeTextStyles(
|
|||||||
if (s.lineHeight !== 0 && s.lineHeight <= 2) {
|
if (s.lineHeight !== 0 && s.lineHeight <= 2) {
|
||||||
s.lineHeight = Math.round(s.fontSize * s.lineHeight)
|
s.lineHeight = Math.round(s.fontSize * s.lineHeight)
|
||||||
}
|
}
|
||||||
} else if (!isNative) {
|
} else if (!IS_NATIVE) {
|
||||||
s.lineHeight = s.fontSize
|
s.lineHeight = s.fontSize
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ export function renderChildrenWithEmoji(
|
|||||||
props: Omit<TextProps, 'children'> = {},
|
props: Omit<TextProps, 'children'> = {},
|
||||||
emoji: boolean,
|
emoji: boolean,
|
||||||
) {
|
) {
|
||||||
if (!isIOS || !emoji) {
|
if (!IS_IOS || !emoji) {
|
||||||
return children
|
return children
|
||||||
}
|
}
|
||||||
return Children.map(children, child => {
|
return Children.map(children, child => {
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ import * as SystemUI from 'expo-system-ui'
|
|||||||
import {type Theme} from '@bsky.app/alf'
|
import {type Theme} from '@bsky.app/alf'
|
||||||
|
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {isAndroid} from '#/platform/detection'
|
import {IS_ANDROID} from '#/env'
|
||||||
|
|
||||||
export function setSystemUITheme(themeType: 'theme' | 'lightbox', t: Theme) {
|
export function setSystemUITheme(themeType: 'theme' | 'lightbox', t: Theme) {
|
||||||
if (isAndroid) {
|
if (IS_ANDROID) {
|
||||||
try {
|
try {
|
||||||
if (themeType === 'theme') {
|
if (themeType === 'theme') {
|
||||||
SystemUI.setBackgroundColorAsync(t.atoms.bg.backgroundColor)
|
SystemUI.setBackgroundColorAsync(t.atoms.bg.backgroundColor)
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import React from 'react'
|
|||||||
import {type ColorSchemeName, useColorScheme} from 'react-native'
|
import {type ColorSchemeName, useColorScheme} from 'react-native'
|
||||||
import {type ThemeName} from '@bsky.app/alf'
|
import {type ThemeName} from '@bsky.app/alf'
|
||||||
|
|
||||||
import {isWeb} from '#/platform/detection'
|
|
||||||
import {useThemePrefs} from '#/state/shell'
|
import {useThemePrefs} from '#/state/shell'
|
||||||
import {dark, dim, light} from '#/alf/themes'
|
import {dark, dim, light} from '#/alf/themes'
|
||||||
|
import {IS_WEB} from '#/env'
|
||||||
|
|
||||||
export function useColorModeTheme(): ThemeName {
|
export function useColorModeTheme(): ThemeName {
|
||||||
const theme = useThemeName()
|
const theme = useThemeName()
|
||||||
@@ -40,7 +40,7 @@ function getThemeName(
|
|||||||
|
|
||||||
function updateDocument(theme: ThemeName) {
|
function updateDocument(theme: ThemeName) {
|
||||||
// @ts-ignore web only
|
// @ts-ignore web only
|
||||||
if (isWeb && typeof window !== 'undefined') {
|
if (IS_WEB && typeof window !== 'undefined') {
|
||||||
// @ts-ignore web only
|
// @ts-ignore web only
|
||||||
const html = window.document.documentElement
|
const html = window.document.documentElement
|
||||||
// @ts-ignore web only
|
// @ts-ignore web only
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ import {HITSLOP_10} from '#/lib/constants'
|
|||||||
import {useHaptics} from '#/lib/haptics'
|
import {useHaptics} from '#/lib/haptics'
|
||||||
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {isAndroid, isIOS} from '#/platform/detection'
|
|
||||||
import {atoms as a, platform, tokens, useTheme} from '#/alf'
|
import {atoms as a, platform, tokens, useTheme} from '#/alf'
|
||||||
import {
|
import {
|
||||||
Context,
|
Context,
|
||||||
@@ -71,6 +70,7 @@ import {
|
|||||||
import {useInteractionState} from '#/components/hooks/useInteractionState'
|
import {useInteractionState} from '#/components/hooks/useInteractionState'
|
||||||
import {createPortalGroup} from '#/components/Portal'
|
import {createPortalGroup} from '#/components/Portal'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_ANDROID, IS_IOS} from '#/env'
|
||||||
import {Backdrop} from './Backdrop'
|
import {Backdrop} from './Backdrop'
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@@ -81,14 +81,14 @@ export {
|
|||||||
const {Provider: PortalProvider, Outlet, Portal} = createPortalGroup()
|
const {Provider: PortalProvider, Outlet, Portal} = createPortalGroup()
|
||||||
|
|
||||||
const SPRING_IN: WithSpringConfig = {
|
const SPRING_IN: WithSpringConfig = {
|
||||||
mass: isIOS ? 1.25 : 0.75,
|
mass: IS_IOS ? 1.25 : 0.75,
|
||||||
damping: 50,
|
damping: 50,
|
||||||
stiffness: 1100,
|
stiffness: 1100,
|
||||||
restDisplacementThreshold: 0.01,
|
restDisplacementThreshold: 0.01,
|
||||||
}
|
}
|
||||||
|
|
||||||
const SPRING_OUT: WithSpringConfig = {
|
const SPRING_OUT: WithSpringConfig = {
|
||||||
mass: isIOS ? 1.25 : 0.75,
|
mass: IS_IOS ? 1.25 : 0.75,
|
||||||
damping: 150,
|
damping: 150,
|
||||||
stiffness: 1000,
|
stiffness: 1000,
|
||||||
restDisplacementThreshold: 0.01,
|
restDisplacementThreshold: 0.01,
|
||||||
@@ -209,7 +209,7 @@ export function Root({children}: {children: React.ReactNode}) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isAndroid && context.isOpen) {
|
if (IS_ANDROID && context.isOpen) {
|
||||||
const listener = BackHandler.addEventListener('hardwareBackPress', () => {
|
const listener = BackHandler.addEventListener('hardwareBackPress', () => {
|
||||||
context.close()
|
context.close()
|
||||||
return true
|
return true
|
||||||
@@ -331,7 +331,7 @@ export function Trigger({children, label, contentLabel, style}: TriggerProps) {
|
|||||||
<GestureDetector gesture={composedGestures}>
|
<GestureDetector gesture={composedGestures}>
|
||||||
<View ref={ref} style={[{opacity: context.isOpen ? 0 : 1}, style]}>
|
<View ref={ref} style={[{opacity: context.isOpen ? 0 : 1}, style]}>
|
||||||
{children({
|
{children({
|
||||||
isNative: true,
|
IS_NATIVE: true,
|
||||||
control: {isOpen: context.isOpen, open},
|
control: {isOpen: context.isOpen, open},
|
||||||
state: {
|
state: {
|
||||||
pressed: false,
|
pressed: false,
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ export type TriggerProps = {
|
|||||||
}
|
}
|
||||||
export type TriggerChildProps =
|
export type TriggerChildProps =
|
||||||
| {
|
| {
|
||||||
isNative: true
|
IS_NATIVE: true
|
||||||
control: {
|
control: {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
open: (mode: 'full' | 'auxiliary-only') => void
|
open: (mode: 'full' | 'auxiliary-only') => void
|
||||||
@@ -115,7 +115,7 @@ export type TriggerChildProps =
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
isNative: false
|
IS_NATIVE: false
|
||||||
control: Dialog.DialogOuterProps['control']
|
control: Dialog.DialogOuterProps['control']
|
||||||
state: {
|
state: {
|
||||||
hovered: false
|
hovered: false
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import {BottomSheetSnapPoint} from '../../../modules/bottom-sheet/src/BottomShee
|
|||||||
|
|
||||||
export const Context = createContext<DialogContextProps>({
|
export const Context = createContext<DialogContextProps>({
|
||||||
close: () => {},
|
close: () => {},
|
||||||
isNativeDialog: false,
|
IS_NATIVEDialog: false,
|
||||||
nativeSnapPoint: BottomSheetSnapPoint.Hidden,
|
nativeSnapPoint: BottomSheetSnapPoint.Hidden,
|
||||||
disableDrag: false,
|
disableDrag: false,
|
||||||
setDisableDrag: () => {},
|
setDisableDrag: () => {},
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import {useLingui} from '@lingui/react'
|
|||||||
import {useEnableKeyboardController} from '#/lib/hooks/useEnableKeyboardController'
|
import {useEnableKeyboardController} from '#/lib/hooks/useEnableKeyboardController'
|
||||||
import {ScrollProvider} from '#/lib/ScrollContext'
|
import {ScrollProvider} from '#/lib/ScrollContext'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {isAndroid, isIOS} from '#/platform/detection'
|
|
||||||
import {useA11y} from '#/state/a11y'
|
import {useA11y} from '#/state/a11y'
|
||||||
import {useDialogStateControlContext} from '#/state/dialogs'
|
import {useDialogStateControlContext} from '#/state/dialogs'
|
||||||
import {List, type ListMethods, type ListProps} from '#/view/com/util/List'
|
import {List, type ListMethods, type ListProps} from '#/view/com/util/List'
|
||||||
@@ -39,6 +38,7 @@ import {
|
|||||||
type DialogOuterProps,
|
type DialogOuterProps,
|
||||||
} from '#/components/Dialog/types'
|
} from '#/components/Dialog/types'
|
||||||
import {createInput} from '#/components/forms/TextField'
|
import {createInput} from '#/components/forms/TextField'
|
||||||
|
import {IS_ANDROID, IS_IOS} from '#/env'
|
||||||
import {BottomSheet, BottomSheetSnapPoint} from '../../../modules/bottom-sheet'
|
import {BottomSheet, BottomSheetSnapPoint} from '../../../modules/bottom-sheet'
|
||||||
import {
|
import {
|
||||||
type BottomSheetSnapPointChangeEvent,
|
type BottomSheetSnapPointChangeEvent,
|
||||||
@@ -154,7 +154,7 @@ export function Outer({
|
|||||||
const context = React.useMemo(
|
const context = React.useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
close,
|
close,
|
||||||
isNativeDialog: true,
|
IS_NATIVEDialog: true,
|
||||||
nativeSnapPoint: snapPoint,
|
nativeSnapPoint: snapPoint,
|
||||||
disableDrag,
|
disableDrag,
|
||||||
setDisableDrag,
|
setDisableDrag,
|
||||||
@@ -209,7 +209,7 @@ export const ScrollableInner = React.forwardRef<ScrollView, DialogInnerProps>(
|
|||||||
const {nativeSnapPoint, disableDrag, setDisableDrag} = useDialogContext()
|
const {nativeSnapPoint, disableDrag, setDisableDrag} = useDialogContext()
|
||||||
const insets = useSafeAreaInsets()
|
const insets = useSafeAreaInsets()
|
||||||
|
|
||||||
useEnableKeyboardController(isIOS)
|
useEnableKeyboardController(IS_IOS)
|
||||||
|
|
||||||
const [keyboardHeight, setKeyboardHeight] = React.useState(0)
|
const [keyboardHeight, setKeyboardHeight] = React.useState(0)
|
||||||
|
|
||||||
@@ -224,7 +224,7 @@ export const ScrollableInner = React.forwardRef<ScrollView, DialogInnerProps>(
|
|||||||
)
|
)
|
||||||
|
|
||||||
let paddingBottom = 0
|
let paddingBottom = 0
|
||||||
if (isIOS) {
|
if (IS_IOS) {
|
||||||
paddingBottom += keyboardHeight / 4
|
paddingBottom += keyboardHeight / 4
|
||||||
if (nativeSnapPoint === BottomSheetSnapPoint.Full) {
|
if (nativeSnapPoint === BottomSheetSnapPoint.Full) {
|
||||||
paddingBottom += insets.bottom + tokens.space.md
|
paddingBottom += insets.bottom + tokens.space.md
|
||||||
@@ -240,7 +240,7 @@ export const ScrollableInner = React.forwardRef<ScrollView, DialogInnerProps>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const onScroll = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
|
const onScroll = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
|
||||||
if (!isAndroid) {
|
if (!IS_ANDROID) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const {contentOffset} = e.nativeEvent
|
const {contentOffset} = e.nativeEvent
|
||||||
@@ -260,12 +260,12 @@ export const ScrollableInner = React.forwardRef<ScrollView, DialogInnerProps>(
|
|||||||
contentContainerStyle,
|
contentContainerStyle,
|
||||||
]}
|
]}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
showsVerticalScrollIndicator={isAndroid ? false : undefined}
|
showsVerticalScrollIndicator={IS_ANDROID ? false : undefined}
|
||||||
{...props}
|
{...props}
|
||||||
bounces={nativeSnapPoint === BottomSheetSnapPoint.Full}
|
bounces={nativeSnapPoint === BottomSheetSnapPoint.Full}
|
||||||
bottomOffset={30}
|
bottomOffset={30}
|
||||||
scrollEventThrottle={50}
|
scrollEventThrottle={50}
|
||||||
onScroll={isAndroid ? onScroll : undefined}
|
onScroll={IS_ANDROID ? onScroll : undefined}
|
||||||
keyboardShouldPersistTaps="handled"
|
keyboardShouldPersistTaps="handled"
|
||||||
// TODO: figure out why this positions the header absolutely (rather than stickily)
|
// TODO: figure out why this positions the header absolutely (rather than stickily)
|
||||||
// on Android. fine to disable for now, because we don't have any
|
// on Android. fine to disable for now, because we don't have any
|
||||||
@@ -289,11 +289,11 @@ export const InnerFlatList = React.forwardRef<
|
|||||||
const insets = useSafeAreaInsets()
|
const insets = useSafeAreaInsets()
|
||||||
const {nativeSnapPoint, disableDrag, setDisableDrag} = useDialogContext()
|
const {nativeSnapPoint, disableDrag, setDisableDrag} = useDialogContext()
|
||||||
|
|
||||||
useEnableKeyboardController(isIOS)
|
useEnableKeyboardController(IS_IOS)
|
||||||
|
|
||||||
const onScroll = (e: ScrollEvent) => {
|
const onScroll = (e: ScrollEvent) => {
|
||||||
'worklet'
|
'worklet'
|
||||||
if (!isAndroid) {
|
if (!IS_ANDROID) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const {contentOffset} = e
|
const {contentOffset} = e
|
||||||
@@ -311,7 +311,7 @@ export const InnerFlatList = React.forwardRef<
|
|||||||
bounces={nativeSnapPoint === BottomSheetSnapPoint.Full}
|
bounces={nativeSnapPoint === BottomSheetSnapPoint.Full}
|
||||||
ListFooterComponent={<View style={{height: insets.bottom + 100}} />}
|
ListFooterComponent={<View style={{height: insets.bottom + 100}} />}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
showsVerticalScrollIndicator={isAndroid ? false : undefined}
|
showsVerticalScrollIndicator={IS_ANDROID ? false : undefined}
|
||||||
{...props}
|
{...props}
|
||||||
style={[a.h_full, style]}
|
style={[a.h_full, style]}
|
||||||
/>
|
/>
|
||||||
@@ -326,7 +326,7 @@ export function FlatListFooter({children}: {children: React.ReactNode}) {
|
|||||||
const {height} = useReanimatedKeyboardAnimation()
|
const {height} = useReanimatedKeyboardAnimation()
|
||||||
|
|
||||||
const animatedStyle = useAnimatedStyle(() => {
|
const animatedStyle = useAnimatedStyle(() => {
|
||||||
if (!isIOS) return {}
|
if (!IS_IOS) return {}
|
||||||
return {
|
return {
|
||||||
transform: [{translateY: Math.min(0, height.get() + bottom - 10)}],
|
transform: [{translateY: Math.min(0, height.get() + bottom - 10)}],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ export function Outer({
|
|||||||
const context = React.useMemo(
|
const context = React.useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
close,
|
close,
|
||||||
isNativeDialog: false,
|
IS_NATIVEDialog: false,
|
||||||
nativeSnapPoint: 0,
|
nativeSnapPoint: 0,
|
||||||
disableDrag: false,
|
disableDrag: false,
|
||||||
setDisableDrag: () => {},
|
setDisableDrag: () => {},
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import {useCallback} from 'react'
|
import {useCallback} from 'react'
|
||||||
import {SystemBars} from 'react-native-edge-to-edge'
|
import {SystemBars} from 'react-native-edge-to-edge'
|
||||||
|
|
||||||
import {isIOS} from '#/platform/detection'
|
import {IS_IOS} from '#/env'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If we're calling a system API like the image picker that opens a sheet
|
* If we're calling a system API like the image picker that opens a sheet
|
||||||
@@ -9,7 +9,7 @@ import {isIOS} from '#/platform/detection'
|
|||||||
*/
|
*/
|
||||||
export function useSheetWrapper() {
|
export function useSheetWrapper() {
|
||||||
return useCallback(async <T>(promise: Promise<T>): Promise<T> => {
|
return useCallback(async <T>(promise: Promise<T>): Promise<T> => {
|
||||||
if (isIOS) {
|
if (IS_IOS) {
|
||||||
const entry = SystemBars.pushStackEntry({
|
const entry = SystemBars.pushStackEntry({
|
||||||
style: {
|
style: {
|
||||||
statusBar: 'light',
|
statusBar: 'light',
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export type DialogControlProps = DialogControlRefProps & {
|
|||||||
|
|
||||||
export type DialogContextProps = {
|
export type DialogContextProps = {
|
||||||
close: DialogControlProps['close']
|
close: DialogControlProps['close']
|
||||||
isNativeDialog: boolean
|
IS_NATIVEDialog: boolean
|
||||||
nativeSnapPoint: BottomSheetSnapPoint
|
nativeSnapPoint: BottomSheetSnapPoint
|
||||||
disableDrag: boolean
|
disableDrag: boolean
|
||||||
setDisableDrag: React.Dispatch<React.SetStateAction<boolean>>
|
setDisableDrag: React.Dispatch<React.SetStateAction<boolean>>
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import {type NavigationProp} from '#/lib/routes/types'
|
|||||||
import {logEvent, useGate} from '#/lib/statsig/statsig'
|
import {logEvent, useGate} from '#/lib/statsig/statsig'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {type MetricEvents} from '#/logger/metrics'
|
import {type MetricEvents} from '#/logger/metrics'
|
||||||
import {isIOS} from '#/platform/detection'
|
|
||||||
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
||||||
import {useGetPopularFeedsQuery} from '#/state/queries/feed'
|
import {useGetPopularFeedsQuery} from '#/state/queries/feed'
|
||||||
import {type FeedDescriptor} from '#/state/queries/post-feed'
|
import {type FeedDescriptor} from '#/state/queries/post-feed'
|
||||||
@@ -39,6 +38,7 @@ import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times'
|
|||||||
import {InlineLinkText} from '#/components/Link'
|
import {InlineLinkText} from '#/components/Link'
|
||||||
import * as ProfileCard from '#/components/ProfileCard'
|
import * as ProfileCard from '#/components/ProfileCard'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_IOS} from '#/env'
|
||||||
import type * as bsky from '#/types/bsky'
|
import type * as bsky from '#/types/bsky'
|
||||||
import {FollowDialogWithoutGuide} from './ProgressGuide/FollowDialog'
|
import {FollowDialogWithoutGuide} from './ProgressGuide/FollowDialog'
|
||||||
import {ProgressGuideList} from './ProgressGuide/List'
|
import {ProgressGuideList} from './ProgressGuide/List'
|
||||||
@@ -692,7 +692,7 @@ export function ProfileGrid({
|
|||||||
t.atoms.border_contrast_low,
|
t.atoms.border_contrast_low,
|
||||||
t.atoms.bg_contrast_25,
|
t.atoms.bg_contrast_25,
|
||||||
]}
|
]}
|
||||||
pointerEvents={isIOS ? 'auto' : 'box-none'}>
|
pointerEvents={IS_IOS ? 'auto' : 'box-none'}>
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
a.px_lg,
|
a.px_lg,
|
||||||
@@ -701,7 +701,7 @@ export function ProfileGrid({
|
|||||||
a.align_center,
|
a.align_center,
|
||||||
a.justify_between,
|
a.justify_between,
|
||||||
]}
|
]}
|
||||||
pointerEvents={isIOS ? 'auto' : 'box-none'}>
|
pointerEvents={IS_IOS ? 'auto' : 'box-none'}>
|
||||||
<Text style={[a.text_sm, a.font_semi_bold, t.atoms.text]}>
|
<Text style={[a.text_sm, a.font_semi_bold, t.atoms.text]}>
|
||||||
{isFeedContext ? (
|
{isFeedContext ? (
|
||||||
<Trans>Suggested for you</Trans>
|
<Trans>Suggested for you</Trans>
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import {msg} from '@lingui/macro'
|
|||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
||||||
import {isWeb} from '#/platform/detection'
|
|
||||||
import {DraggableScrollView} from '#/view/com/pager/DraggableScrollView'
|
import {DraggableScrollView} from '#/view/com/pager/DraggableScrollView'
|
||||||
import {atoms as a, tokens, useTheme, web} from '#/alf'
|
import {atoms as a, tokens, useTheme, web} from '#/alf'
|
||||||
import {transparentifyColor} from '#/alf/util/colorGeneration'
|
import {transparentifyColor} from '#/alf/util/colorGeneration'
|
||||||
@@ -19,6 +18,7 @@ import {
|
|||||||
ArrowRight_Stroke2_Corner0_Rounded as ArrowRight,
|
ArrowRight_Stroke2_Corner0_Rounded as ArrowRight,
|
||||||
} from '#/components/icons/Arrow'
|
} from '#/components/icons/Arrow'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_WEB} from '#/env'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tab component that automatically scrolls the selected tab into view - used for interests
|
* Tab component that automatically scrolls the selected tab into view - used for interests
|
||||||
@@ -236,7 +236,7 @@ export function InterestTabs({
|
|||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</DraggableScrollView>
|
</DraggableScrollView>
|
||||||
{isWeb && canScrollLeft && (
|
{IS_WEB && canScrollLeft && (
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
a.absolute,
|
a.absolute,
|
||||||
@@ -270,7 +270,7 @@ export function InterestTabs({
|
|||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
{isWeb && canScrollRight && (
|
{IS_WEB && canScrollRight && (
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
a.absolute,
|
a.absolute,
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ import {
|
|||||||
INTERNATIONAL_TELEPHONE_CODES,
|
INTERNATIONAL_TELEPHONE_CODES,
|
||||||
} from '#/lib/international-telephone-codes'
|
} from '#/lib/international-telephone-codes'
|
||||||
import {regionName} from '#/locale/helpers'
|
import {regionName} from '#/locale/helpers'
|
||||||
import {isWeb} from '#/platform/detection'
|
|
||||||
import {atoms as a, web} from '#/alf'
|
import {atoms as a, web} from '#/alf'
|
||||||
import * as Select from '#/components/Select'
|
import * as Select from '#/components/Select'
|
||||||
|
import {IS_WEB} from '#/env'
|
||||||
import {useGeolocation} from '#/geolocation'
|
import {useGeolocation} from '#/geolocation'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -84,7 +84,7 @@ export function InternationalPhoneCodeSelect({
|
|||||||
<Select.Item value={item.value} label={item.label}>
|
<Select.Item value={item.value} label={item.label}>
|
||||||
<Select.ItemIndicator />
|
<Select.ItemIndicator />
|
||||||
<Select.ItemText style={[a.flex_1]} emoji>
|
<Select.ItemText style={[a.flex_1]} emoji>
|
||||||
{isWeb ? <Flag {...item} /> : item.unicodeFlag + ' '}
|
{IS_WEB ? <Flag {...item} /> : item.unicodeFlag + ' '}
|
||||||
{item.name}
|
{item.name}
|
||||||
</Select.ItemText>
|
</Select.ItemText>
|
||||||
<Select.ItemText style={[a.text_right]}>
|
<Select.ItemText style={[a.text_right]}>
|
||||||
@@ -101,7 +101,7 @@ export function InternationalPhoneCodeSelect({
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Flag({unicodeFlag, svgFlag}: {unicodeFlag: string; svgFlag: any}) {
|
function Flag({unicodeFlag, svgFlag}: {unicodeFlag: string; svgFlag: any}) {
|
||||||
if (isWeb) {
|
if (IS_WEB) {
|
||||||
return (
|
return (
|
||||||
<Image
|
<Image
|
||||||
source={svgFlag}
|
source={svgFlag}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import {useNavigation} from '@react-navigation/native'
|
|||||||
|
|
||||||
import {HITSLOP_30} from '#/lib/constants'
|
import {HITSLOP_30} from '#/lib/constants'
|
||||||
import {type NavigationProp} from '#/lib/routes/types'
|
import {type NavigationProp} from '#/lib/routes/types'
|
||||||
import {isIOS} from '#/platform/detection'
|
|
||||||
import {useSetDrawerOpen} from '#/state/shell'
|
import {useSetDrawerOpen} from '#/state/shell'
|
||||||
import {
|
import {
|
||||||
atoms as a,
|
atoms as a,
|
||||||
@@ -29,6 +28,7 @@ import {
|
|||||||
} from '#/components/Layout/const'
|
} from '#/components/Layout/const'
|
||||||
import {ScrollbarOffsetContext} from '#/components/Layout/context'
|
import {ScrollbarOffsetContext} from '#/components/Layout/context'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_IOS} from '#/env'
|
||||||
|
|
||||||
export function Outer({
|
export function Outer({
|
||||||
children,
|
children,
|
||||||
@@ -91,7 +91,7 @@ export function Content({
|
|||||||
style={[
|
style={[
|
||||||
a.flex_1,
|
a.flex_1,
|
||||||
a.justify_center,
|
a.justify_center,
|
||||||
isIOS && align === 'platform' && a.align_center,
|
IS_IOS && align === 'platform' && a.align_center,
|
||||||
{minHeight: HEADER_SLOT_SIZE},
|
{minHeight: HEADER_SLOT_SIZE},
|
||||||
]}>
|
]}>
|
||||||
<AlignmentContext.Provider value={align}>
|
<AlignmentContext.Provider value={align}>
|
||||||
@@ -186,7 +186,7 @@ export function TitleText({
|
|||||||
a.text_lg,
|
a.text_lg,
|
||||||
a.font_semi_bold,
|
a.font_semi_bold,
|
||||||
a.leading_tight,
|
a.leading_tight,
|
||||||
isIOS && align === 'platform' && a.text_center,
|
IS_IOS && align === 'platform' && a.text_center,
|
||||||
gtMobile && a.text_xl,
|
gtMobile && a.text_xl,
|
||||||
style,
|
style,
|
||||||
]}
|
]}
|
||||||
@@ -205,7 +205,7 @@ export function SubtitleText({children}: {children: React.ReactNode}) {
|
|||||||
style={[
|
style={[
|
||||||
a.text_sm,
|
a.text_sm,
|
||||||
a.leading_snug,
|
a.leading_snug,
|
||||||
isIOS && align === 'platform' && a.text_center,
|
IS_IOS && align === 'platform' && a.text_center,
|
||||||
t.atoms.text_contrast_medium,
|
t.atoms.text_contrast_medium,
|
||||||
]}
|
]}
|
||||||
numberOfLines={2}>
|
numberOfLines={2}>
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import Animated, {
|
|||||||
} from 'react-native-reanimated'
|
} from 'react-native-reanimated'
|
||||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||||
|
|
||||||
import {isWeb} from '#/platform/detection'
|
|
||||||
import {useShellLayout} from '#/state/shell/shell-layout'
|
import {useShellLayout} from '#/state/shell/shell-layout'
|
||||||
import {
|
import {
|
||||||
atoms as a,
|
atoms as a,
|
||||||
@@ -23,6 +22,7 @@ import {
|
|||||||
import {useDialogContext} from '#/components/Dialog'
|
import {useDialogContext} from '#/components/Dialog'
|
||||||
import {CENTER_COLUMN_OFFSET, SCROLLBAR_OFFSET} from '#/components/Layout/const'
|
import {CENTER_COLUMN_OFFSET, SCROLLBAR_OFFSET} from '#/components/Layout/const'
|
||||||
import {ScrollbarOffsetContext} from '#/components/Layout/context'
|
import {ScrollbarOffsetContext} from '#/components/Layout/context'
|
||||||
|
import {IS_WEB} from '#/env'
|
||||||
|
|
||||||
export * from '#/components/Layout/const'
|
export * from '#/components/Layout/const'
|
||||||
export * as Header from '#/components/Layout/Header'
|
export * as Header from '#/components/Layout/Header'
|
||||||
@@ -43,7 +43,7 @@ export const Screen = memo(function Screen({
|
|||||||
const {top} = useSafeAreaInsets()
|
const {top} = useSafeAreaInsets()
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{isWeb && <WebCenterBorders />}
|
{IS_WEB && <WebCenterBorders />}
|
||||||
<View
|
<View
|
||||||
style={[a.util_screen_outer, {paddingTop: noInsetTop ? 0 : top}, style]}
|
style={[a.util_screen_outer, {paddingTop: noInsetTop ? 0 : top}, style]}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -98,7 +98,7 @@ export const Content = memo(
|
|||||||
contentContainerStyle,
|
contentContainerStyle,
|
||||||
]}
|
]}
|
||||||
{...props}>
|
{...props}>
|
||||||
{isWeb ? (
|
{IS_WEB ? (
|
||||||
<Center ignoreTabletLayoutOffset={ignoreTabletLayoutOffset}>
|
<Center ignoreTabletLayoutOffset={ignoreTabletLayoutOffset}>
|
||||||
{/* @ts-expect-error web only -esb */}
|
{/* @ts-expect-error web only -esb */}
|
||||||
{children}
|
{children}
|
||||||
@@ -145,7 +145,7 @@ export const KeyboardAwareContent = memo(function LayoutKeyboardAwareContent({
|
|||||||
]}
|
]}
|
||||||
keyboardShouldPersistTaps="handled"
|
keyboardShouldPersistTaps="handled"
|
||||||
{...props}>
|
{...props}>
|
||||||
{isWeb ? <Center>{children}</Center> : children}
|
{IS_WEB ? <Center>{children}</Center> : children}
|
||||||
</KeyboardAwareScrollView>
|
</KeyboardAwareScrollView>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
+11
-11
@@ -18,12 +18,12 @@ import {
|
|||||||
isExternalUrl,
|
isExternalUrl,
|
||||||
linkRequiresWarning,
|
linkRequiresWarning,
|
||||||
} from '#/lib/strings/url-helpers'
|
} from '#/lib/strings/url-helpers'
|
||||||
import {isNative, isWeb} from '#/platform/detection'
|
|
||||||
import {useModalControls} from '#/state/modals'
|
import {useModalControls} from '#/state/modals'
|
||||||
import {atoms as a, flatten, type TextStyleProp, useTheme, web} from '#/alf'
|
import {atoms as a, flatten, type TextStyleProp, useTheme, web} from '#/alf'
|
||||||
import {Button, type ButtonProps} from '#/components/Button'
|
import {Button, type ButtonProps} from '#/components/Button'
|
||||||
import {useInteractionState} from '#/components/hooks/useInteractionState'
|
import {useInteractionState} from '#/components/hooks/useInteractionState'
|
||||||
import {Text, type TextProps} from '#/components/Typography'
|
import {Text, type TextProps} from '#/components/Typography'
|
||||||
|
import {IS_NATIVE, IS_WEB} from '#/env'
|
||||||
import {router} from '#/routes'
|
import {router} from '#/routes'
|
||||||
import {useGlobalDialogsControlContext} from './dialogs/Context'
|
import {useGlobalDialogsControlContext} from './dialogs/Context'
|
||||||
|
|
||||||
@@ -130,7 +130,7 @@ export function useLink({
|
|||||||
linkRequiresWarning(href, displayText),
|
linkRequiresWarning(href, displayText),
|
||||||
)
|
)
|
||||||
|
|
||||||
if (isWeb) {
|
if (IS_WEB) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,7 +162,7 @@ export function useLink({
|
|||||||
]
|
]
|
||||||
|
|
||||||
// does not apply to web's flat navigator
|
// does not apply to web's flat navigator
|
||||||
if (isNative && screen !== 'NotFound') {
|
if (IS_NATIVE && screen !== 'NotFound') {
|
||||||
const state = navigation.getState()
|
const state = navigation.getState()
|
||||||
// if screen is not in the current navigator, it means it's
|
// if screen is not in the current navigator, it means it's
|
||||||
// most likely a tab screen. note: state can be undefined
|
// most likely a tab screen. note: state can be undefined
|
||||||
@@ -246,7 +246,7 @@ export function useLink({
|
|||||||
(e: GestureResponderEvent) => {
|
(e: GestureResponderEvent) => {
|
||||||
const exitEarlyIfFalse = outerOnLongPress?.(e)
|
const exitEarlyIfFalse = outerOnLongPress?.(e)
|
||||||
if (exitEarlyIfFalse === false) return
|
if (exitEarlyIfFalse === false) return
|
||||||
return isNative && shareOnLongPress ? handleLongPress() : undefined
|
return IS_NATIVE && shareOnLongPress ? handleLongPress() : undefined
|
||||||
},
|
},
|
||||||
[outerOnLongPress, handleLongPress, shareOnLongPress],
|
[outerOnLongPress, handleLongPress, shareOnLongPress],
|
||||||
)
|
)
|
||||||
@@ -501,7 +501,7 @@ export function WebOnlyInlineLinkText({
|
|||||||
onPress,
|
onPress,
|
||||||
...props
|
...props
|
||||||
}: Omit<InlineLinkProps, 'onLongPress'>) {
|
}: Omit<InlineLinkProps, 'onLongPress'>) {
|
||||||
return isWeb ? (
|
return IS_WEB ? (
|
||||||
<InlineLinkText {...props} to={to} onPress={onPress}>
|
<InlineLinkText {...props} to={to} onPress={onPress}>
|
||||||
{children}
|
{children}
|
||||||
</InlineLinkText>
|
</InlineLinkText>
|
||||||
@@ -547,7 +547,7 @@ export function createStaticClickIfUnmodified(
|
|||||||
): {onPress: Exclude<BaseLinkProps['onPress'], undefined>} {
|
): {onPress: Exclude<BaseLinkProps['onPress'], undefined>} {
|
||||||
return {
|
return {
|
||||||
onPress(e: GestureResponderEvent) {
|
onPress(e: GestureResponderEvent) {
|
||||||
if (!isWeb || !isModifiedClickEvent(e)) {
|
if (!IS_WEB || !isModifiedClickEvent(e)) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
onPressHandler(e)
|
onPressHandler(e)
|
||||||
return false
|
return false
|
||||||
@@ -561,7 +561,7 @@ export function createStaticClickIfUnmodified(
|
|||||||
* intends to deviate from default behavior.
|
* intends to deviate from default behavior.
|
||||||
*/
|
*/
|
||||||
export function isClickEventWithMetaKey(e: GestureResponderEvent) {
|
export function isClickEventWithMetaKey(e: GestureResponderEvent) {
|
||||||
if (!isWeb) return false
|
if (!IS_WEB) return false
|
||||||
const event = e as unknown as MouseEvent
|
const event = e as unknown as MouseEvent
|
||||||
return event.metaKey || event.altKey || event.ctrlKey || event.shiftKey
|
return event.metaKey || event.altKey || event.ctrlKey || event.shiftKey
|
||||||
}
|
}
|
||||||
@@ -570,7 +570,7 @@ export function isClickEventWithMetaKey(e: GestureResponderEvent) {
|
|||||||
* Determines if the web click target is anything other than `_self`
|
* Determines if the web click target is anything other than `_self`
|
||||||
*/
|
*/
|
||||||
export function isClickTargetExternal(e: GestureResponderEvent) {
|
export function isClickTargetExternal(e: GestureResponderEvent) {
|
||||||
if (!isWeb) return false
|
if (!IS_WEB) return false
|
||||||
const event = e as unknown as MouseEvent
|
const event = e as unknown as MouseEvent
|
||||||
const el = event.currentTarget as HTMLAnchorElement
|
const el = event.currentTarget as HTMLAnchorElement
|
||||||
return el && el.target && el.target !== '_self'
|
return el && el.target && el.target !== '_self'
|
||||||
@@ -582,7 +582,7 @@ export function isClickTargetExternal(e: GestureResponderEvent) {
|
|||||||
* {@link https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button}
|
* {@link https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button}
|
||||||
*/
|
*/
|
||||||
export function isModifiedClickEvent(e: GestureResponderEvent): boolean {
|
export function isModifiedClickEvent(e: GestureResponderEvent): boolean {
|
||||||
if (!isWeb) return false
|
if (!IS_WEB) return false
|
||||||
const event = e as unknown as MouseEvent
|
const event = e as unknown as MouseEvent
|
||||||
const isPrimaryButton = event.button === 0
|
const isPrimaryButton = event.button === 0
|
||||||
return (
|
return (
|
||||||
@@ -596,8 +596,8 @@ export function isModifiedClickEvent(e: GestureResponderEvent): boolean {
|
|||||||
* {@link https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button}
|
* {@link https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button}
|
||||||
*/
|
*/
|
||||||
export function shouldClickOpenNewTab(e: GestureResponderEvent) {
|
export function shouldClickOpenNewTab(e: GestureResponderEvent) {
|
||||||
if (!isWeb) return false
|
if (!IS_WEB) return false
|
||||||
const event = e as unknown as MouseEvent
|
const event = e as unknown as MouseEvent
|
||||||
const isMiddleClick = isWeb && event.button === 1
|
const isMiddleClick = IS_WEB && event.button === 1
|
||||||
return isClickEventWithMetaKey(e) || isClickTargetExternal(e) || isMiddleClick
|
return isClickEventWithMetaKey(e) || isClickTargetExternal(e) || isMiddleClick
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import {msg, Trans} from '@lingui/macro'
|
|||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import flattenReactChildren from 'react-keyed-flatten-children'
|
import flattenReactChildren from 'react-keyed-flatten-children'
|
||||||
|
|
||||||
import {isAndroid, isIOS, isNative} from '#/platform/detection'
|
|
||||||
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 * as Dialog from '#/components/Dialog'
|
import * as Dialog from '#/components/Dialog'
|
||||||
@@ -30,6 +29,7 @@ import {
|
|||||||
type TriggerProps,
|
type TriggerProps,
|
||||||
} from '#/components/Menu/types'
|
} from '#/components/Menu/types'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_ANDROID, IS_IOS, IS_NATIVE} from '#/env'
|
||||||
|
|
||||||
export {
|
export {
|
||||||
type DialogControlProps as MenuControlProps,
|
type DialogControlProps as MenuControlProps,
|
||||||
@@ -70,7 +70,7 @@ export function Trigger({
|
|||||||
} = useInteractionState()
|
} = useInteractionState()
|
||||||
|
|
||||||
return children({
|
return children({
|
||||||
isNative: true,
|
IS_NATIVE: true,
|
||||||
control: context.control,
|
control: context.control,
|
||||||
state: {
|
state: {
|
||||||
hovered: false,
|
hovered: false,
|
||||||
@@ -111,7 +111,7 @@ export function Outer({
|
|||||||
<Dialog.ScrollableInner label={_(msg`Menu`)}>
|
<Dialog.ScrollableInner label={_(msg`Menu`)}>
|
||||||
<View style={[a.gap_lg]}>
|
<View style={[a.gap_lg]}>
|
||||||
{children}
|
{children}
|
||||||
{isNative && showCancel && <Cancel />}
|
{IS_NATIVE && showCancel && <Cancel />}
|
||||||
</View>
|
</View>
|
||||||
</Dialog.ScrollableInner>
|
</Dialog.ScrollableInner>
|
||||||
</Context.Provider>
|
</Context.Provider>
|
||||||
@@ -137,13 +137,13 @@ export function Item({children, label, style, onPress, ...rest}: ItemProps) {
|
|||||||
onFocus={onFocus}
|
onFocus={onFocus}
|
||||||
onBlur={onBlur}
|
onBlur={onBlur}
|
||||||
onPress={async e => {
|
onPress={async e => {
|
||||||
if (isAndroid) {
|
if (IS_ANDROID) {
|
||||||
/**
|
/**
|
||||||
* Below fix for iOS doesn't work for Android, this does.
|
* Below fix for iOS doesn't work for Android, this does.
|
||||||
*/
|
*/
|
||||||
onPress?.(e)
|
onPress?.(e)
|
||||||
context.control.close()
|
context.control.close()
|
||||||
} else if (isIOS) {
|
} else if (IS_IOS) {
|
||||||
/**
|
/**
|
||||||
* Fixes a subtle bug on iOS
|
* Fixes a subtle bug on iOS
|
||||||
* {@link https://github.com/bluesky-social/social-app/pull/5849/files#diff-de516ef5e7bd9840cd639213301df38cf03acfcad5bda85a1d63efd249ba79deL124-L127}
|
* {@link https://github.com/bluesky-social/social-app/pull/5849/files#diff-de516ef5e7bd9840cd639213301df38cf03acfcad5bda85a1d63efd249ba79deL124-L127}
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ export function Trigger({
|
|||||||
<RadixTriggerPassThrough>
|
<RadixTriggerPassThrough>
|
||||||
{props =>
|
{props =>
|
||||||
children({
|
children({
|
||||||
isNative: false,
|
IS_NATIVE: false,
|
||||||
control,
|
control,
|
||||||
state: {
|
state: {
|
||||||
hovered,
|
hovered,
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ export type TriggerProps = {
|
|||||||
}
|
}
|
||||||
export type TriggerChildProps =
|
export type TriggerChildProps =
|
||||||
| {
|
| {
|
||||||
isNative: true
|
IS_NATIVE: true
|
||||||
control: Dialog.DialogOuterProps['control']
|
control: Dialog.DialogOuterProps['control']
|
||||||
state: {
|
state: {
|
||||||
/**
|
/**
|
||||||
@@ -73,7 +73,7 @@ export type TriggerChildProps =
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
isNative: false
|
IS_NATIVE: false
|
||||||
control: Dialog.DialogOuterProps['control']
|
control: Dialog.DialogOuterProps['control']
|
||||||
state: {
|
state: {
|
||||||
hovered: boolean
|
hovered: boolean
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import {differenceInSeconds} from 'date-fns'
|
|||||||
import {HITSLOP_10} from '#/lib/constants'
|
import {HITSLOP_10} from '#/lib/constants'
|
||||||
import {useGetTimeAgo} from '#/lib/hooks/useTimeAgo'
|
import {useGetTimeAgo} from '#/lib/hooks/useTimeAgo'
|
||||||
import {sanitizeDisplayName} from '#/lib/strings/display-names'
|
import {sanitizeDisplayName} from '#/lib/strings/display-names'
|
||||||
import {isNative} from '#/platform/detection'
|
|
||||||
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
||||||
import {useSession} from '#/state/session'
|
import {useSession} from '#/state/session'
|
||||||
import {atoms as a, useTheme, web} from '#/alf'
|
import {atoms as a, useTheme, web} from '#/alf'
|
||||||
@@ -18,6 +17,7 @@ import {useDialogControl} from '#/components/Dialog'
|
|||||||
import {Newskie} from '#/components/icons/Newskie'
|
import {Newskie} from '#/components/icons/Newskie'
|
||||||
import * as StarterPackCard from '#/components/StarterPack/StarterPackCard'
|
import * as StarterPackCard from '#/components/StarterPack/StarterPackCard'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_NATIVE} from '#/env'
|
||||||
|
|
||||||
export function NewskieDialog({
|
export function NewskieDialog({
|
||||||
profile,
|
profile,
|
||||||
@@ -162,7 +162,7 @@ function DialogInner({
|
|||||||
</StarterPackCard.Link>
|
</StarterPackCard.Link>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{isNative && (
|
{IS_NATIVE && (
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Close`)}
|
label={_(msg`Close`)}
|
||||||
color="secondary"
|
color="secondary"
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import {
|
|||||||
import {LinearGradient} from 'expo-linear-gradient'
|
import {LinearGradient} from 'expo-linear-gradient'
|
||||||
import {utils} from '@bsky.app/alf'
|
import {utils} from '@bsky.app/alf'
|
||||||
|
|
||||||
import {isAndroid, isNative} from '#/platform/detection'
|
|
||||||
import {useA11y} from '#/state/a11y'
|
import {useA11y} from '#/state/a11y'
|
||||||
import {atoms as a, useBreakpoints, useTheme, web} from '#/alf'
|
import {atoms as a, useBreakpoints, useTheme, web} from '#/alf'
|
||||||
import {FocusScope} from '#/components/FocusScope'
|
import {FocusScope} from '#/components/FocusScope'
|
||||||
import {LockScroll} from '#/components/LockScroll'
|
import {LockScroll} from '#/components/LockScroll'
|
||||||
|
import {IS_ANDROID, IS_NATIVE} from '#/env'
|
||||||
|
|
||||||
const GUTTER = 24
|
const GUTTER = 24
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ export function Overlay({
|
|||||||
a.z_20,
|
a.z_20,
|
||||||
a.align_center,
|
a.align_center,
|
||||||
!gtPhone && [a.justify_end, {minHeight: frame.height}],
|
!gtPhone && [a.justify_end, {minHeight: frame.height}],
|
||||||
isNative && [
|
IS_NATIVE && [
|
||||||
{
|
{
|
||||||
paddingBottom: Math.max(insets.bottom, a.p_2xl.padding),
|
paddingBottom: Math.max(insets.bottom, a.p_2xl.padding),
|
||||||
},
|
},
|
||||||
@@ -109,7 +109,7 @@ export function Overlay({
|
|||||||
|
|
||||||
<FocusScope>
|
<FocusScope>
|
||||||
<View
|
<View
|
||||||
accessible={isAndroid}
|
accessible={IS_ANDROID}
|
||||||
role="dialog"
|
role="dialog"
|
||||||
aria-role="dialog"
|
aria-role="dialog"
|
||||||
aria-label={label}
|
aria-label={label}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import {useEffect} from 'react'
|
import {useEffect} from 'react'
|
||||||
import {View} from 'react-native'
|
import {View} from 'react-native'
|
||||||
|
|
||||||
import {isIOS} from '#/platform/detection'
|
|
||||||
import {atoms as a} from '#/alf'
|
import {atoms as a} from '#/alf'
|
||||||
import {FullWindowOverlay} from '#/components/FullWindowOverlay'
|
import {FullWindowOverlay} from '#/components/FullWindowOverlay'
|
||||||
import {usePolicyUpdateContext} from '#/components/PolicyUpdateOverlay/context'
|
import {usePolicyUpdateContext} from '#/components/PolicyUpdateOverlay/context'
|
||||||
import {Portal} from '#/components/PolicyUpdateOverlay/Portal'
|
import {Portal} from '#/components/PolicyUpdateOverlay/Portal'
|
||||||
import {Content} from '#/components/PolicyUpdateOverlay/updates/202508'
|
import {Content} from '#/components/PolicyUpdateOverlay/updates/202508'
|
||||||
|
import {IS_IOS} from '#/env'
|
||||||
|
|
||||||
export {Provider} from '#/components/PolicyUpdateOverlay/context'
|
export {Provider} from '#/components/PolicyUpdateOverlay/context'
|
||||||
export {usePolicyUpdateContext} from '#/components/PolicyUpdateOverlay/context'
|
export {usePolicyUpdateContext} from '#/components/PolicyUpdateOverlay/context'
|
||||||
@@ -39,7 +39,7 @@ export function PolicyUpdateOverlay() {
|
|||||||
// setting a zIndex when using FullWindowOverlay on iOS
|
// setting a zIndex when using FullWindowOverlay on iOS
|
||||||
// means the taps pass straight through to the underlying content (???)
|
// means the taps pass straight through to the underlying content (???)
|
||||||
// so don't set it on iOS. FullWindowOverlay already does the job.
|
// so don't set it on iOS. FullWindowOverlay already does the job.
|
||||||
!isIOS && {zIndex: 9999},
|
!IS_IOS && {zIndex: 9999},
|
||||||
]}>
|
]}>
|
||||||
<Content state={state} />
|
<Content state={state} />
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import {View} from 'react-native'
|
|||||||
import {msg, Trans} from '@lingui/macro'
|
import {msg, Trans} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
import {isAndroid} from '#/platform/detection'
|
|
||||||
import {useA11y} from '#/state/a11y'
|
import {useA11y} from '#/state/a11y'
|
||||||
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'
|
||||||
@@ -12,6 +11,7 @@ import {Badge} from '#/components/PolicyUpdateOverlay/Badge'
|
|||||||
import {Overlay} from '#/components/PolicyUpdateOverlay/Overlay'
|
import {Overlay} from '#/components/PolicyUpdateOverlay/Overlay'
|
||||||
import {type PolicyUpdateState} from '#/components/PolicyUpdateOverlay/usePolicyUpdateState'
|
import {type PolicyUpdateState} from '#/components/PolicyUpdateOverlay/usePolicyUpdateState'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_ANDROID} from '#/env'
|
||||||
|
|
||||||
export function Content({state}: {state: PolicyUpdateState}) {
|
export function Content({state}: {state: PolicyUpdateState}) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
@@ -56,7 +56,7 @@ export function Content({state}: {state: PolicyUpdateState}) {
|
|||||||
size: 'small',
|
size: 'small',
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
const label = isAndroid
|
const label = IS_ANDROID
|
||||||
? _(
|
? _(
|
||||||
msg`We’re updating our Terms of Service, Privacy Policy, and Copyright Policy, effective September 15th, 2025. We're also updating our Community Guidelines, and we want your input! These new guidelines will take effect on October 15th, 2025. Learn more about these changes and how to share your thoughts with us by reading our blog post.`,
|
msg`We’re updating our Terms of Service, Privacy Policy, and Copyright Policy, effective September 15th, 2025. We're also updating our Community Guidelines, and we want your input! These new guidelines will take effect on October 15th, 2025. Learn more about these changes and how to share your thoughts with us by reading our blog post.`,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -10,13 +10,13 @@ import {msg} from '@lingui/macro'
|
|||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
import {type EmbedPlayerParams} from '#/lib/strings/embed-player'
|
import {type EmbedPlayerParams} from '#/lib/strings/embed-player'
|
||||||
import {isIOS, isNative, isWeb} from '#/platform/detection'
|
|
||||||
import {useExternalEmbedsPrefs} from '#/state/preferences'
|
import {useExternalEmbedsPrefs} from '#/state/preferences'
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
import {useDialogControl} from '#/components/Dialog'
|
import {useDialogControl} from '#/components/Dialog'
|
||||||
import {EmbedConsentDialog} from '#/components/dialogs/EmbedConsent'
|
import {EmbedConsentDialog} from '#/components/dialogs/EmbedConsent'
|
||||||
import {Fill} from '#/components/Fill'
|
import {Fill} from '#/components/Fill'
|
||||||
import {PlayButtonIcon} from '#/components/video/PlayButtonIcon'
|
import {PlayButtonIcon} from '#/components/video/PlayButtonIcon'
|
||||||
|
import {IS_IOS, IS_NATIVE, IS_WEB} from '#/env'
|
||||||
|
|
||||||
export function ExternalGif({
|
export function ExternalGif({
|
||||||
link,
|
link,
|
||||||
@@ -66,12 +66,12 @@ export function ExternalGif({
|
|||||||
// Control animation on native
|
// Control animation on native
|
||||||
setIsAnimating(prev => {
|
setIsAnimating(prev => {
|
||||||
if (prev) {
|
if (prev) {
|
||||||
if (isNative) {
|
if (IS_NATIVE) {
|
||||||
imageRef.current?.stopAnimating()
|
imageRef.current?.stopAnimating()
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
} else {
|
} else {
|
||||||
if (isNative) {
|
if (IS_NATIVE) {
|
||||||
imageRef.current?.startAnimating()
|
imageRef.current?.startAnimating()
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@@ -112,7 +112,7 @@ export function ExternalGif({
|
|||||||
<Image
|
<Image
|
||||||
source={{
|
source={{
|
||||||
uri:
|
uri:
|
||||||
!isPrefetched || (isWeb && !isAnimating)
|
!isPrefetched || (IS_WEB && !isAnimating)
|
||||||
? link.thumb
|
? link.thumb
|
||||||
: params.playerUri,
|
: params.playerUri,
|
||||||
}} // Web uses the thumb to control playback
|
}} // Web uses the thumb to control playback
|
||||||
@@ -123,7 +123,7 @@ export function ExternalGif({
|
|||||||
accessibilityIgnoresInvertColors
|
accessibilityIgnoresInvertColors
|
||||||
accessibilityLabel={link.title}
|
accessibilityLabel={link.title}
|
||||||
accessibilityHint={link.title}
|
accessibilityHint={link.title}
|
||||||
cachePolicy={isIOS ? 'disk' : 'memory-disk'} // cant control playback with memory-disk on ios
|
cachePolicy={IS_IOS ? 'disk' : 'memory-disk'} // cant control playback with memory-disk on ios
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{(!isPrefetched || !isAnimating) && (
|
{(!isPrefetched || !isAnimating) && (
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import {
|
|||||||
type EmbedPlayerParams,
|
type EmbedPlayerParams,
|
||||||
getPlayerAspect,
|
getPlayerAspect,
|
||||||
} from '#/lib/strings/embed-player'
|
} from '#/lib/strings/embed-player'
|
||||||
import {isNative} from '#/platform/detection'
|
|
||||||
import {useExternalEmbedsPrefs} from '#/state/preferences'
|
import {useExternalEmbedsPrefs} from '#/state/preferences'
|
||||||
import {EventStopper} from '#/view/com/util/EventStopper'
|
import {EventStopper} from '#/view/com/util/EventStopper'
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
@@ -34,6 +33,7 @@ import {useDialogControl} from '#/components/Dialog'
|
|||||||
import {EmbedConsentDialog} from '#/components/dialogs/EmbedConsent'
|
import {EmbedConsentDialog} from '#/components/dialogs/EmbedConsent'
|
||||||
import {Fill} from '#/components/Fill'
|
import {Fill} from '#/components/Fill'
|
||||||
import {PlayButtonIcon} from '#/components/video/PlayButtonIcon'
|
import {PlayButtonIcon} from '#/components/video/PlayButtonIcon'
|
||||||
|
import {IS_NATIVE} from '#/env'
|
||||||
|
|
||||||
interface ShouldStartLoadRequest {
|
interface ShouldStartLoadRequest {
|
||||||
url: string
|
url: string
|
||||||
@@ -148,7 +148,7 @@ export function ExternalPlayer({
|
|||||||
const {height: winHeight, width: winWidth} = windowDims
|
const {height: winHeight, width: winWidth} = windowDims
|
||||||
|
|
||||||
// Get the proper screen height depending on what is going on
|
// Get the proper screen height depending on what is going on
|
||||||
const realWinHeight = isNative // If it is native, we always want the larger number
|
const realWinHeight = IS_NATIVE // If it is native, we always want the larger number
|
||||||
? winHeight > winWidth
|
? winHeight > winWidth
|
||||||
? winHeight
|
? winHeight
|
||||||
: winWidth
|
: winWidth
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import {useLingui} from '@lingui/react'
|
|||||||
import {HITSLOP_20} from '#/lib/constants'
|
import {HITSLOP_20} from '#/lib/constants'
|
||||||
import {clamp} from '#/lib/numbers'
|
import {clamp} from '#/lib/numbers'
|
||||||
import {type EmbedPlayerParams} from '#/lib/strings/embed-player'
|
import {type EmbedPlayerParams} from '#/lib/strings/embed-player'
|
||||||
import {isWeb} from '#/platform/detection'
|
|
||||||
import {useAutoplayDisabled} from '#/state/preferences'
|
import {useAutoplayDisabled} from '#/state/preferences'
|
||||||
import {useLargeAltBadgeEnabled} from '#/state/preferences/large-alt-badge'
|
import {useLargeAltBadgeEnabled} from '#/state/preferences/large-alt-badge'
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
@@ -22,6 +21,7 @@ import {Loader} from '#/components/Loader'
|
|||||||
import * as Prompt from '#/components/Prompt'
|
import * as Prompt from '#/components/Prompt'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
import {PlayButtonIcon} from '#/components/video/PlayButtonIcon'
|
import {PlayButtonIcon} from '#/components/video/PlayButtonIcon'
|
||||||
|
import {IS_WEB} from '#/env'
|
||||||
import {GifView} from '../../../../../modules/expo-bluesky-gif-view'
|
import {GifView} from '../../../../../modules/expo-bluesky-gif-view'
|
||||||
import {type GifViewStateChangeEvent} from '../../../../../modules/expo-bluesky-gif-view/src/GifView.types'
|
import {type GifViewStateChangeEvent} from '../../../../../modules/expo-bluesky-gif-view/src/GifView.types'
|
||||||
|
|
||||||
@@ -218,18 +218,18 @@ const styles = StyleSheet.create({
|
|||||||
altContainer: {
|
altContainer: {
|
||||||
backgroundColor: 'rgba(0, 0, 0, 0.75)',
|
backgroundColor: 'rgba(0, 0, 0, 0.75)',
|
||||||
borderRadius: 6,
|
borderRadius: 6,
|
||||||
paddingHorizontal: isWeb ? 8 : 6,
|
paddingHorizontal: IS_WEB ? 8 : 6,
|
||||||
paddingVertical: isWeb ? 6 : 3,
|
paddingVertical: IS_WEB ? 6 : 3,
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
// Related to margin/gap hack. This keeps the alt label in the same position
|
// Related to margin/gap hack. This keeps the alt label in the same position
|
||||||
// on all platforms
|
// on all platforms
|
||||||
right: isWeb ? 8 : 5,
|
right: IS_WEB ? 8 : 5,
|
||||||
bottom: isWeb ? 8 : 5,
|
bottom: IS_WEB ? 8 : 5,
|
||||||
zIndex: 2,
|
zIndex: 2,
|
||||||
},
|
},
|
||||||
alt: {
|
alt: {
|
||||||
color: 'white',
|
color: 'white',
|
||||||
fontSize: isWeb ? 10 : 7,
|
fontSize: IS_WEB ? 10 : 7,
|
||||||
fontWeight: '600',
|
fontWeight: '600',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -10,13 +10,13 @@ import {useHaptics} from '#/lib/haptics'
|
|||||||
import {shareUrl} from '#/lib/sharing'
|
import {shareUrl} from '#/lib/sharing'
|
||||||
import {parseEmbedPlayerFromUrl} from '#/lib/strings/embed-player'
|
import {parseEmbedPlayerFromUrl} from '#/lib/strings/embed-player'
|
||||||
import {toNiceDomain} from '#/lib/strings/url-helpers'
|
import {toNiceDomain} from '#/lib/strings/url-helpers'
|
||||||
import {isNative} from '#/platform/detection'
|
|
||||||
import {useExternalEmbedsPrefs} from '#/state/preferences'
|
import {useExternalEmbedsPrefs} from '#/state/preferences'
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
import {Divider} from '#/components/Divider'
|
import {Divider} from '#/components/Divider'
|
||||||
import {Earth_Stroke2_Corner0_Rounded as Globe} from '#/components/icons/Globe'
|
import {Earth_Stroke2_Corner0_Rounded as Globe} from '#/components/icons/Globe'
|
||||||
import {Link} from '#/components/Link'
|
import {Link} from '#/components/Link'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_NATIVE} from '#/env'
|
||||||
import {ExternalGif} from './ExternalGif'
|
import {ExternalGif} from './ExternalGif'
|
||||||
import {ExternalPlayer} from './ExternalPlayer'
|
import {ExternalPlayer} from './ExternalPlayer'
|
||||||
import {GifEmbed} from './Gif'
|
import {GifEmbed} from './Gif'
|
||||||
@@ -53,7 +53,7 @@ export const ExternalEmbed = ({
|
|||||||
}, [playHaptic, onOpen])
|
}, [playHaptic, onOpen])
|
||||||
|
|
||||||
const onShareExternal = useCallback(() => {
|
const onShareExternal = useCallback(() => {
|
||||||
if (link.uri && isNative) {
|
if (link.uri && IS_NATIVE) {
|
||||||
playHaptic('Heavy')
|
playHaptic('Heavy')
|
||||||
shareUrl(link.uri)
|
shareUrl(link.uri)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import React, {
|
|||||||
} from 'react'
|
} from 'react'
|
||||||
import {useWindowDimensions} from 'react-native'
|
import {useWindowDimensions} from 'react-native'
|
||||||
|
|
||||||
import {isNative, isWeb} from '#/platform/detection'
|
import {IS_NATIVE, IS_WEB} from '#/env'
|
||||||
|
|
||||||
const Context = React.createContext<{
|
const Context = React.createContext<{
|
||||||
activeViewId: string | null
|
activeViewId: string | null
|
||||||
@@ -18,7 +18,7 @@ const Context = React.createContext<{
|
|||||||
Context.displayName = 'ActiveVideoWebContext'
|
Context.displayName = 'ActiveVideoWebContext'
|
||||||
|
|
||||||
export function Provider({children}: {children: React.ReactNode}) {
|
export function Provider({children}: {children: React.ReactNode}) {
|
||||||
if (!isWeb) {
|
if (!IS_WEB) {
|
||||||
throw new Error('ActiveVideoWebContext may only be used on web.')
|
throw new Error('ActiveVideoWebContext may only be used on web.')
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ export function Provider({children}: {children: React.ReactNode}) {
|
|||||||
|
|
||||||
const sendViewPosition = useCallback(
|
const sendViewPosition = useCallback(
|
||||||
(viewId: string, y: number) => {
|
(viewId: string, y: number) => {
|
||||||
if (isNative) return
|
if (IS_NATIVE) return
|
||||||
|
|
||||||
if (viewId === activeViewIdRef.current) {
|
if (viewId === activeViewIdRef.current) {
|
||||||
activeViewLocationRef.current = y
|
activeViewLocationRef.current = y
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import type Hls from 'hls.js'
|
|||||||
|
|
||||||
import {isTouchDevice} from '#/lib/browser'
|
import {isTouchDevice} from '#/lib/browser'
|
||||||
import {clamp} from '#/lib/numbers'
|
import {clamp} from '#/lib/numbers'
|
||||||
import {isIPhoneWeb} from '#/platform/detection'
|
|
||||||
import {
|
import {
|
||||||
useAutoplayDisabled,
|
useAutoplayDisabled,
|
||||||
useSetSubtitlesEnabled,
|
useSetSubtitlesEnabled,
|
||||||
@@ -28,6 +27,7 @@ import {Pause_Filled_Corner0_Rounded as PauseIcon} from '#/components/icons/Paus
|
|||||||
import {Play_Filled_Corner0_Rounded as PlayIcon} from '#/components/icons/Play'
|
import {Play_Filled_Corner0_Rounded as PlayIcon} from '#/components/icons/Play'
|
||||||
import {Loader} from '#/components/Loader'
|
import {Loader} from '#/components/Loader'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_WEB_MOBILE_IOS} from '#/env'
|
||||||
import {TimeIndicator} from '../TimeIndicator'
|
import {TimeIndicator} from '../TimeIndicator'
|
||||||
import {ControlButton} from './ControlButton'
|
import {ControlButton} from './ControlButton'
|
||||||
import {Scrubber} from './Scrubber'
|
import {Scrubber} from './Scrubber'
|
||||||
@@ -400,7 +400,7 @@ export function Controls({
|
|||||||
onEndHover={onVolumeEndHover}
|
onEndHover={onVolumeEndHover}
|
||||||
drawFocus={drawFocus}
|
drawFocus={drawFocus}
|
||||||
/>
|
/>
|
||||||
{!isIPhoneWeb && (
|
{!IS_WEB_MOBILE_IOS && (
|
||||||
<ControlButton
|
<ControlButton
|
||||||
active={isFullscreen}
|
active={isFullscreen}
|
||||||
activeLabel={_(msg`Exit fullscreen`)}
|
activeLabel={_(msg`Exit fullscreen`)}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import {type NavigationProp} from '#/lib/routes/types'
|
|||||||
import {shareText, shareUrl} from '#/lib/sharing'
|
import {shareText, shareUrl} from '#/lib/sharing'
|
||||||
import {toShareUrl} from '#/lib/strings/url-helpers'
|
import {toShareUrl} from '#/lib/strings/url-helpers'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {isIOS} from '#/platform/detection'
|
|
||||||
import {useProfileShadow} from '#/state/cache/profile-shadow'
|
import {useProfileShadow} from '#/state/cache/profile-shadow'
|
||||||
import {useSession} from '#/state/session'
|
import {useSession} from '#/state/session'
|
||||||
import * as Toast from '#/view/com/util/Toast'
|
import * as Toast from '#/view/com/util/Toast'
|
||||||
@@ -24,6 +23,7 @@ import {Clipboard_Stroke2_Corner2_Rounded as ClipboardIcon} from '#/components/i
|
|||||||
import {PaperPlane_Stroke2_Corner0_Rounded as PaperPlaneIcon} from '#/components/icons/PaperPlane'
|
import {PaperPlane_Stroke2_Corner0_Rounded as PaperPlaneIcon} from '#/components/icons/PaperPlane'
|
||||||
import * as Menu from '#/components/Menu'
|
import * as Menu from '#/components/Menu'
|
||||||
import {useAgeAssurance} from '#/ageAssurance'
|
import {useAgeAssurance} from '#/ageAssurance'
|
||||||
|
import {IS_IOS} from '#/env'
|
||||||
import {useDevMode} from '#/storage/hooks/dev-mode'
|
import {useDevMode} from '#/storage/hooks/dev-mode'
|
||||||
import {RecentChats} from './RecentChats'
|
import {RecentChats} from './RecentChats'
|
||||||
import {type ShareMenuItemsProps} from './ShareMenuItems.types'
|
import {type ShareMenuItemsProps} from './ShareMenuItems.types'
|
||||||
@@ -63,7 +63,7 @@ let ShareMenuItems = ({
|
|||||||
const onCopyLink = async () => {
|
const onCopyLink = async () => {
|
||||||
logger.metric('share:press:copyLink', {}, {statsig: true})
|
logger.metric('share:press:copyLink', {}, {statsig: true})
|
||||||
const url = toShareUrl(href)
|
const url = toShareUrl(href)
|
||||||
if (isIOS) {
|
if (IS_IOS) {
|
||||||
// iOS only
|
// iOS only
|
||||||
await ExpoClipboard.setUrlAsync(url)
|
await ExpoClipboard.setUrlAsync(url)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import {type NavigationProp} from '#/lib/routes/types'
|
|||||||
import {shareText, shareUrl} from '#/lib/sharing'
|
import {shareText, shareUrl} from '#/lib/sharing'
|
||||||
import {toShareUrl} from '#/lib/strings/url-helpers'
|
import {toShareUrl} from '#/lib/strings/url-helpers'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {isWeb} from '#/platform/detection'
|
|
||||||
import {useProfileShadow} from '#/state/cache/profile-shadow'
|
import {useProfileShadow} from '#/state/cache/profile-shadow'
|
||||||
import {useSession} from '#/state/session'
|
import {useSession} from '#/state/session'
|
||||||
import {useBreakpoints} from '#/alf'
|
import {useBreakpoints} from '#/alf'
|
||||||
@@ -22,6 +21,7 @@ import {CodeBrackets_Stroke2_Corner0_Rounded as CodeBracketsIcon} from '#/compon
|
|||||||
import {PaperPlane_Stroke2_Corner0_Rounded as Send} from '#/components/icons/PaperPlane'
|
import {PaperPlane_Stroke2_Corner0_Rounded as Send} from '#/components/icons/PaperPlane'
|
||||||
import * as Menu from '#/components/Menu'
|
import * as Menu from '#/components/Menu'
|
||||||
import {useAgeAssurance} from '#/ageAssurance'
|
import {useAgeAssurance} from '#/ageAssurance'
|
||||||
|
import {IS_WEB} from '#/env'
|
||||||
import {useDevMode} from '#/storage/hooks/dev-mode'
|
import {useDevMode} from '#/storage/hooks/dev-mode'
|
||||||
import {type ShareMenuItemsProps} from './ShareMenuItems.types'
|
import {type ShareMenuItemsProps} from './ShareMenuItems.types'
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ let ShareMenuItems = ({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const canEmbed = isWeb && gtMobile && !hideInPWI
|
const canEmbed = IS_WEB && gtMobile && !hideInPWI
|
||||||
|
|
||||||
const onShareATURI = () => {
|
const onShareATURI = () => {
|
||||||
shareText(postUri)
|
shareText(postUri)
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import {useLingui} from '@lingui/react'
|
|||||||
import {popularInterests, useInterestsDisplayNames} from '#/lib/interests'
|
import {popularInterests, useInterestsDisplayNames} from '#/lib/interests'
|
||||||
import {logEvent} from '#/lib/statsig/statsig'
|
import {logEvent} from '#/lib/statsig/statsig'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {isWeb} from '#/platform/detection'
|
|
||||||
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
||||||
import {useActorSearch} from '#/state/queries/actor-search'
|
import {useActorSearch} from '#/state/queries/actor-search'
|
||||||
import {usePreferencesQuery} from '#/state/queries/preferences'
|
import {usePreferencesQuery} from '#/state/queries/preferences'
|
||||||
@@ -37,6 +36,7 @@ import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times'
|
|||||||
import {boostInterests, InterestTabs} from '#/components/InterestTabs'
|
import {boostInterests, InterestTabs} from '#/components/InterestTabs'
|
||||||
import * as ProfileCard from '#/components/ProfileCard'
|
import * as ProfileCard from '#/components/ProfileCard'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_WEB} from '#/env'
|
||||||
import type * as bsky from '#/types/bsky'
|
import type * as bsky from '#/types/bsky'
|
||||||
import {ProgressGuideTask} from './Task'
|
import {ProgressGuideTask} from './Task'
|
||||||
|
|
||||||
@@ -431,7 +431,7 @@ function HeaderTop({guide}: {guide?: Follow10ProgressGuide}) {
|
|||||||
<Trans>Find people to follow</Trans>
|
<Trans>Find people to follow</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
{guide && (
|
{guide && (
|
||||||
<View style={isWeb && {paddingRight: 36}}>
|
<View style={IS_WEB && {paddingRight: 36}}>
|
||||||
<ProgressGuideTask
|
<ProgressGuideTask
|
||||||
current={guide.numFollows + 1}
|
current={guide.numFollows + 1}
|
||||||
total={10 + 1}
|
total={10 + 1}
|
||||||
@@ -440,12 +440,12 @@ function HeaderTop({guide}: {guide?: Follow10ProgressGuide}) {
|
|||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
{isWeb ? (
|
{IS_WEB ? (
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Close`)}
|
label={_(msg`Close`)}
|
||||||
size="small"
|
size="small"
|
||||||
shape="round"
|
shape="round"
|
||||||
variant={isWeb ? 'ghost' : 'solid'}
|
variant={IS_WEB ? 'ghost' : 'solid'}
|
||||||
color="secondary"
|
color="secondary"
|
||||||
style={[
|
style={[
|
||||||
a.absolute,
|
a.absolute,
|
||||||
@@ -579,7 +579,7 @@ function FollowProfileCardInner({
|
|||||||
<ProfileCard.Outer>
|
<ProfileCard.Outer>
|
||||||
<ProfileCard.Header>
|
<ProfileCard.Header>
|
||||||
<ProfileCard.Avatar
|
<ProfileCard.Avatar
|
||||||
disabledPreview={!isWeb}
|
disabledPreview={!IS_WEB}
|
||||||
profile={profile}
|
profile={profile}
|
||||||
moderationOpts={moderationOpts}
|
moderationOpts={moderationOpts}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
|||||||
import {msg} from '@lingui/macro'
|
import {msg} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
import {isWeb} from '#/platform/detection'
|
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
import {Portal} from '#/components/Portal'
|
import {Portal} from '#/components/Portal'
|
||||||
|
import {IS_WEB} from '#/env'
|
||||||
import {AnimatedCheck, type AnimatedCheckRef} from '../anim/AnimatedCheck'
|
import {AnimatedCheck, type AnimatedCheckRef} from '../anim/AnimatedCheck'
|
||||||
import {Text} from '../Typography'
|
import {Text} from '../Typography'
|
||||||
|
|
||||||
@@ -108,11 +108,11 @@ export const ProgressGuideToast = React.forwardRef<
|
|||||||
const containerStyle = React.useMemo(() => {
|
const containerStyle = React.useMemo(() => {
|
||||||
let left = 10
|
let left = 10
|
||||||
let right = 10
|
let right = 10
|
||||||
if (isWeb && winDim.width > 400) {
|
if (IS_WEB && winDim.width > 400) {
|
||||||
left = right = (winDim.width - 380) / 2
|
left = right = (winDim.width - 380) / 2
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
position: isWeb ? 'fixed' : 'absolute',
|
position: IS_WEB ? 'fixed' : 'absolute',
|
||||||
top: 0,
|
top: 0,
|
||||||
left,
|
left,
|
||||||
right,
|
right,
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import {useNavigation} from '@react-navigation/native'
|
|||||||
|
|
||||||
import {type NavigationProp} from '#/lib/routes/types'
|
import {type NavigationProp} from '#/lib/routes/types'
|
||||||
import {isInvalidHandle} from '#/lib/strings/handles'
|
import {isInvalidHandle} from '#/lib/strings/handles'
|
||||||
import {isNative, isWeb} from '#/platform/detection'
|
|
||||||
import {
|
import {
|
||||||
usePreferencesQuery,
|
usePreferencesQuery,
|
||||||
useRemoveMutedWordsMutation,
|
useRemoveMutedWordsMutation,
|
||||||
@@ -22,6 +21,7 @@ import {
|
|||||||
} from '#/components/Link'
|
} from '#/components/Link'
|
||||||
import {Loader} from '#/components/Loader'
|
import {Loader} from '#/components/Loader'
|
||||||
import * as Menu from '#/components/Menu'
|
import * as Menu from '#/components/Menu'
|
||||||
|
import {IS_NATIVE, IS_WEB} from '#/env'
|
||||||
|
|
||||||
export function RichTextTag({
|
export function RichTextTag({
|
||||||
tag,
|
tag,
|
||||||
@@ -50,7 +50,7 @@ export function RichTextTag({
|
|||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
const isCashtag = tag.startsWith('$')
|
const isCashtag = tag.startsWith('$')
|
||||||
const label = isCashtag ? _(msg`Cashtag ${tag}`) : _(msg`Hashtag ${tag}`)
|
const label = isCashtag ? _(msg`Cashtag ${tag}`) : _(msg`Hashtag ${tag}`)
|
||||||
const hint = isNative
|
const hint = IS_NATIVE
|
||||||
? _(msg`Long press to open tag menu for ${isCashtag ? tag : `#${tag}`}`)
|
? _(msg`Long press to open tag menu for ${isCashtag ? tag : `#${tag}`}`)
|
||||||
: _(msg`Click to open tag menu for ${isCashtag ? tag : `#${tag}`}`)
|
: _(msg`Click to open tag menu for ${isCashtag ? tag : `#${tag}`}`)
|
||||||
|
|
||||||
@@ -86,9 +86,9 @@ export function RichTextTag({
|
|||||||
}}
|
}}
|
||||||
{...menuProps}
|
{...menuProps}
|
||||||
onPress={e => {
|
onPress={e => {
|
||||||
if (isWeb) {
|
if (IS_WEB) {
|
||||||
return createStaticClickIfUnmodified(() => {
|
return createStaticClickIfUnmodified(() => {
|
||||||
if (!isNative) {
|
if (!IS_NATIVE) {
|
||||||
menuProps.onPress()
|
menuProps.onPress()
|
||||||
}
|
}
|
||||||
}).onPress(e)
|
}).onPress(e)
|
||||||
@@ -99,7 +99,7 @@ export function RichTextTag({
|
|||||||
label={label}
|
label={label}
|
||||||
style={textStyle}
|
style={textStyle}
|
||||||
emoji>
|
emoji>
|
||||||
{isNative ? (
|
{IS_NATIVE ? (
|
||||||
display
|
display
|
||||||
) : (
|
) : (
|
||||||
<RNText ref={menuProps.ref}>{display}</RNText>
|
<RNText ref={menuProps.ref}>{display}</RNText>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import Animated, {
|
|||||||
} from 'react-native-reanimated'
|
} from 'react-native-reanimated'
|
||||||
import type React from 'react'
|
import type React from 'react'
|
||||||
|
|
||||||
import {isWeb} from '#/platform/detection'
|
import {IS_WEB} from '#/env'
|
||||||
|
|
||||||
export function ScreenTransition({
|
export function ScreenTransition({
|
||||||
direction,
|
direction,
|
||||||
@@ -31,8 +31,8 @@ export function ScreenTransition({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Animated.View
|
<Animated.View
|
||||||
entering={isWeb ? webEntering : entering}
|
entering={IS_WEB ? webEntering : entering}
|
||||||
exiting={isWeb ? webExiting : exiting}
|
exiting={IS_WEB ? webExiting : exiting}
|
||||||
style={style}>
|
style={style}>
|
||||||
{children}
|
{children}
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ export function Trigger({children, label}: TriggerProps) {
|
|||||||
|
|
||||||
if (typeof children === 'function') {
|
if (typeof children === 'function') {
|
||||||
return children({
|
return children({
|
||||||
isNative: true,
|
IS_NATIVE: true,
|
||||||
control,
|
control,
|
||||||
state: {
|
state: {
|
||||||
hovered: false,
|
hovered: false,
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ export function Trigger({children, label}: TriggerProps) {
|
|||||||
<RadixTriggerPassThrough>
|
<RadixTriggerPassThrough>
|
||||||
{props =>
|
{props =>
|
||||||
children({
|
children({
|
||||||
isNative: false,
|
IS_NATIVE: false,
|
||||||
state: {
|
state: {
|
||||||
hovered,
|
hovered,
|
||||||
focused,
|
focused,
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ export type TriggerProps = {
|
|||||||
|
|
||||||
export type TriggerChildProps =
|
export type TriggerChildProps =
|
||||||
| {
|
| {
|
||||||
isNative: true
|
IS_NATIVE: true
|
||||||
control: DialogControlProps
|
control: DialogControlProps
|
||||||
state: {
|
state: {
|
||||||
/**
|
/**
|
||||||
@@ -92,7 +92,7 @@ export type TriggerChildProps =
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
isNative: false
|
IS_NATIVE: false
|
||||||
state: {
|
state: {
|
||||||
hovered: boolean
|
hovered: boolean
|
||||||
focused: boolean
|
focused: boolean
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ import {type ListRenderItemInfo, View} from 'react-native'
|
|||||||
import {type AppBskyFeedDefs} from '@atproto/api'
|
import {type AppBskyFeedDefs} from '@atproto/api'
|
||||||
|
|
||||||
import {useBottomBarOffset} from '#/lib/hooks/useBottomBarOffset'
|
import {useBottomBarOffset} from '#/lib/hooks/useBottomBarOffset'
|
||||||
import {isNative, isWeb} from '#/platform/detection'
|
|
||||||
import {List, type ListRef} from '#/view/com/util/List'
|
import {List, type ListRef} from '#/view/com/util/List'
|
||||||
import {type SectionRef} from '#/screens/Profile/Sections/types'
|
import {type SectionRef} from '#/screens/Profile/Sections/types'
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
import * as FeedCard from '#/components/FeedCard'
|
import * as FeedCard from '#/components/FeedCard'
|
||||||
|
import {IS_NATIVE, IS_WEB} from '#/env'
|
||||||
|
|
||||||
function keyExtractor(item: AppBskyFeedDefs.GeneratorView) {
|
function keyExtractor(item: AppBskyFeedDefs.GeneratorView) {
|
||||||
return item.uri
|
return item.uri
|
||||||
@@ -27,7 +27,7 @@ export const FeedsList = React.forwardRef<SectionRef, ProfilesListProps>(
|
|||||||
|
|
||||||
const onScrollToTop = useCallback(() => {
|
const onScrollToTop = useCallback(() => {
|
||||||
scrollElRef.current?.scrollToOffset({
|
scrollElRef.current?.scrollToOffset({
|
||||||
animated: isNative,
|
animated: IS_NATIVE,
|
||||||
offset: -headerHeight,
|
offset: -headerHeight,
|
||||||
})
|
})
|
||||||
}, [scrollElRef, headerHeight])
|
}, [scrollElRef, headerHeight])
|
||||||
@@ -44,7 +44,7 @@ export const FeedsList = React.forwardRef<SectionRef, ProfilesListProps>(
|
|||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
a.p_lg,
|
a.p_lg,
|
||||||
(isWeb || index !== 0) && a.border_t,
|
(IS_WEB || index !== 0) && a.border_t,
|
||||||
t.atoms.border_contrast_low,
|
t.atoms.border_contrast_low,
|
||||||
]}>
|
]}>
|
||||||
<FeedCard.Default view={item} />
|
<FeedCard.Default view={item} />
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ import {View} from 'react-native'
|
|||||||
import {msg} from '@lingui/macro'
|
import {msg} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
import {isNative} from '#/platform/detection'
|
|
||||||
import {type FeedDescriptor} from '#/state/queries/post-feed'
|
import {type FeedDescriptor} from '#/state/queries/post-feed'
|
||||||
import {PostFeed} from '#/view/com/posts/PostFeed'
|
import {PostFeed} from '#/view/com/posts/PostFeed'
|
||||||
import {EmptyState} from '#/view/com/util/EmptyState'
|
import {EmptyState} from '#/view/com/util/EmptyState'
|
||||||
import {type ListRef} from '#/view/com/util/List'
|
import {type ListRef} from '#/view/com/util/List'
|
||||||
import {type SectionRef} from '#/screens/Profile/Sections/types'
|
import {type SectionRef} from '#/screens/Profile/Sections/types'
|
||||||
import {HashtagWide_Stroke1_Corner0_Rounded as HashtagWideIcon} from '#/components/icons/Hashtag'
|
import {HashtagWide_Stroke1_Corner0_Rounded as HashtagWideIcon} from '#/components/icons/Hashtag'
|
||||||
|
import {IS_NATIVE} from '#/env'
|
||||||
|
|
||||||
interface ProfilesListProps {
|
interface ProfilesListProps {
|
||||||
listUri: string
|
listUri: string
|
||||||
@@ -24,7 +24,7 @@ export const PostsList = React.forwardRef<SectionRef, ProfilesListProps>(
|
|||||||
|
|
||||||
const onScrollToTop = useCallback(() => {
|
const onScrollToTop = useCallback(() => {
|
||||||
scrollElRef.current?.scrollToOffset({
|
scrollElRef.current?.scrollToOffset({
|
||||||
animated: isNative,
|
animated: IS_NATIVE,
|
||||||
offset: -headerHeight,
|
offset: -headerHeight,
|
||||||
})
|
})
|
||||||
}, [scrollElRef, headerHeight])
|
}, [scrollElRef, headerHeight])
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import {
|
|||||||
import {useBottomBarOffset} from '#/lib/hooks/useBottomBarOffset'
|
import {useBottomBarOffset} from '#/lib/hooks/useBottomBarOffset'
|
||||||
import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender'
|
import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender'
|
||||||
import {isBlockedOrBlocking} from '#/lib/moderation/blocked-and-muted'
|
import {isBlockedOrBlocking} from '#/lib/moderation/blocked-and-muted'
|
||||||
import {isNative, isWeb} from '#/platform/detection'
|
|
||||||
import {useAllListMembersQuery} from '#/state/queries/list-members'
|
import {useAllListMembersQuery} from '#/state/queries/list-members'
|
||||||
import {useSession} from '#/state/session'
|
import {useSession} from '#/state/session'
|
||||||
import {List, type ListRef} from '#/view/com/util/List'
|
import {List, type ListRef} from '#/view/com/util/List'
|
||||||
@@ -22,6 +21,7 @@ import {type SectionRef} from '#/screens/Profile/Sections/types'
|
|||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
import {ListFooter, ListMaybePlaceholder} from '#/components/Lists'
|
import {ListFooter, ListMaybePlaceholder} from '#/components/Lists'
|
||||||
import {Default as ProfileCard} from '#/components/ProfileCard'
|
import {Default as ProfileCard} from '#/components/ProfileCard'
|
||||||
|
import {IS_NATIVE, IS_WEB} from '#/env'
|
||||||
|
|
||||||
function keyExtractor(item: AppBskyActorDefs.ProfileViewBasic, index: number) {
|
function keyExtractor(item: AppBskyActorDefs.ProfileViewBasic, index: number) {
|
||||||
return `${item.did}-${index}`
|
return `${item.did}-${index}`
|
||||||
@@ -75,7 +75,7 @@ export const ProfilesList = React.forwardRef<SectionRef, ProfilesListProps>(
|
|||||||
}
|
}
|
||||||
const onScrollToTop = useCallback(() => {
|
const onScrollToTop = useCallback(() => {
|
||||||
scrollElRef.current?.scrollToOffset({
|
scrollElRef.current?.scrollToOffset({
|
||||||
animated: isNative,
|
animated: IS_NATIVE,
|
||||||
offset: -headerHeight,
|
offset: -headerHeight,
|
||||||
})
|
})
|
||||||
}, [scrollElRef, headerHeight])
|
}, [scrollElRef, headerHeight])
|
||||||
@@ -93,7 +93,7 @@ export const ProfilesList = React.forwardRef<SectionRef, ProfilesListProps>(
|
|||||||
style={[
|
style={[
|
||||||
a.p_lg,
|
a.p_lg,
|
||||||
t.atoms.border_contrast_low,
|
t.atoms.border_contrast_low,
|
||||||
(isWeb || index !== 0) && a.border_t,
|
(IS_WEB || index !== 0) && a.border_t,
|
||||||
]}>
|
]}>
|
||||||
<ProfileCard
|
<ProfileCard
|
||||||
profile={item}
|
profile={item}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
|
|||||||
import {type NavigationProp} from '#/lib/routes/types'
|
import {type NavigationProp} from '#/lib/routes/types'
|
||||||
import {parseStarterPackUri} from '#/lib/strings/starter-pack'
|
import {parseStarterPackUri} from '#/lib/strings/starter-pack'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {isIOS} from '#/platform/detection'
|
|
||||||
import {useActorStarterPacksQuery} from '#/state/queries/actor-starter-packs'
|
import {useActorStarterPacksQuery} from '#/state/queries/actor-starter-packs'
|
||||||
import {
|
import {
|
||||||
EmptyState,
|
EmptyState,
|
||||||
@@ -36,6 +35,7 @@ import {Loader} from '#/components/Loader'
|
|||||||
import * as Prompt from '#/components/Prompt'
|
import * as Prompt from '#/components/Prompt'
|
||||||
import {Default as StarterPackCard} from '#/components/StarterPack/StarterPackCard'
|
import {Default as StarterPackCard} from '#/components/StarterPack/StarterPackCard'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_IOS} from '#/env'
|
||||||
|
|
||||||
interface SectionRef {
|
interface SectionRef {
|
||||||
scrollToTop: () => void
|
scrollToTop: () => void
|
||||||
@@ -136,7 +136,7 @@ export function ProfileStarterPacks({
|
|||||||
}, [isFetchingNextPage, hasNextPage, isError, fetchNextPage])
|
}, [isFetchingNextPage, hasNextPage, isError, fetchNextPage])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isIOS && enabled && scrollElRef.current) {
|
if (IS_IOS && enabled && scrollElRef.current) {
|
||||||
const nativeTag = findNodeHandle(scrollElRef.current)
|
const nativeTag = findNodeHandle(scrollElRef.current)
|
||||||
setScrollViewTag(nativeTag)
|
setScrollViewTag(nativeTag)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ import type ViewShot from 'react-native-view-shot'
|
|||||||
import {type AppBskyGraphDefs, AppBskyGraphStarterpack} from '@atproto/api'
|
import {type AppBskyGraphDefs, AppBskyGraphStarterpack} from '@atproto/api'
|
||||||
import {Trans} from '@lingui/macro'
|
import {Trans} from '@lingui/macro'
|
||||||
|
|
||||||
import {isWeb} from '#/platform/detection'
|
|
||||||
import {Logo} from '#/view/icons/Logo'
|
import {Logo} from '#/view/icons/Logo'
|
||||||
import {Logotype} from '#/view/icons/Logotype'
|
import {Logotype} from '#/view/icons/Logotype'
|
||||||
import {useTheme} from '#/alf'
|
import {useTheme} from '#/alf'
|
||||||
import {atoms as a} from '#/alf'
|
import {atoms as a} from '#/alf'
|
||||||
import {LinearGradientBackground} from '#/components/LinearGradientBackground'
|
import {LinearGradientBackground} from '#/components/LinearGradientBackground'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_WEB} from '#/env'
|
||||||
import * as bsky from '#/types/bsky'
|
import * as bsky from '#/types/bsky'
|
||||||
|
|
||||||
const LazyViewShot = lazy(
|
const LazyViewShot = lazy(
|
||||||
@@ -121,7 +121,7 @@ export function QrCodeInner({link}: {link: string}) {
|
|||||||
return (
|
return (
|
||||||
<View style={{position: 'relative'}}>
|
<View style={{position: 'relative'}}>
|
||||||
{/* An SVG version of the logo is placed on top of normal `QRCode` `logo` prop, since the PNG fails to load before the export completes on web. */}
|
{/* An SVG version of the logo is placed on top of normal `QRCode` `logo` prop, since the PNG fails to load before the export completes on web. */}
|
||||||
{isWeb && logoArea && (
|
{IS_WEB && logoArea && (
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
@@ -139,9 +139,9 @@ export function QrCodeInner({link}: {link: string}) {
|
|||||||
a.rounded_sm,
|
a.rounded_sm,
|
||||||
{height: 225, width: 225, backgroundColor: '#f3f3f3'},
|
{height: 225, width: 225, backgroundColor: '#f3f3f3'},
|
||||||
]}
|
]}
|
||||||
pieceSize={isWeb ? 8 : 6}
|
pieceSize={IS_WEB ? 8 : 6}
|
||||||
padding={20}
|
padding={20}
|
||||||
pieceBorderRadius={isWeb ? 4.5 : 3.5}
|
pieceBorderRadius={IS_WEB ? 4.5 : 3.5}
|
||||||
outerEyesOptions={{
|
outerEyesOptions={{
|
||||||
topLeft: {
|
topLeft: {
|
||||||
borderRadius: [12, 12, 0, 12],
|
borderRadius: [12, 12, 0, 12],
|
||||||
@@ -159,11 +159,11 @@ export function QrCodeInner({link}: {link: string}) {
|
|||||||
innerEyesOptions={{borderRadius: 3}}
|
innerEyesOptions={{borderRadius: 3}}
|
||||||
logo={{
|
logo={{
|
||||||
href: require('../../../assets/logo.png'),
|
href: require('../../../assets/logo.png'),
|
||||||
...(isWeb && {
|
...(IS_WEB && {
|
||||||
onChange: onLogoAreaChange,
|
onChange: onLogoAreaChange,
|
||||||
padding: 28,
|
padding: 28,
|
||||||
}),
|
}),
|
||||||
...(!isWeb && {
|
...(!IS_WEB && {
|
||||||
padding: 2,
|
padding: 2,
|
||||||
scale: 0.95,
|
scale: 0.95,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import {msg, Trans} from '@lingui/macro'
|
|||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {isNative, isWeb} from '#/platform/detection'
|
|
||||||
import {atoms as a, useBreakpoints} from '#/alf'
|
import {atoms as a, useBreakpoints} from '#/alf'
|
||||||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||||||
import * as Dialog from '#/components/Dialog'
|
import * as Dialog from '#/components/Dialog'
|
||||||
@@ -20,6 +19,7 @@ import {FloppyDisk_Stroke2_Corner0_Rounded as FloppyDiskIcon} from '#/components
|
|||||||
import {Loader} from '#/components/Loader'
|
import {Loader} from '#/components/Loader'
|
||||||
import {QrCode} from '#/components/StarterPack/QrCode'
|
import {QrCode} from '#/components/StarterPack/QrCode'
|
||||||
import * as Toast from '#/components/Toast'
|
import * as Toast from '#/components/Toast'
|
||||||
|
import {IS_NATIVE, IS_WEB} from '#/env'
|
||||||
import * as bsky from '#/types/bsky'
|
import * as bsky from '#/types/bsky'
|
||||||
|
|
||||||
export function QrCodeDialog({
|
export function QrCodeDialog({
|
||||||
@@ -56,7 +56,7 @@ export function QrCodeDialog({
|
|||||||
|
|
||||||
const onSavePress = async () => {
|
const onSavePress = async () => {
|
||||||
ref.current?.capture?.().then(async (uri: string) => {
|
ref.current?.capture?.().then(async (uri: string) => {
|
||||||
if (isNative) {
|
if (IS_NATIVE) {
|
||||||
const res = await requestMediaLibraryPermissionsAsync()
|
const res = await requestMediaLibraryPermissionsAsync()
|
||||||
|
|
||||||
if (!res.granted) {
|
if (!res.granted) {
|
||||||
@@ -111,7 +111,7 @@ export function QrCodeDialog({
|
|||||||
})
|
})
|
||||||
setIsSaveProcessing(false)
|
setIsSaveProcessing(false)
|
||||||
Toast.show(
|
Toast.show(
|
||||||
isWeb
|
IS_WEB
|
||||||
? _(msg`QR code has been downloaded!`)
|
? _(msg`QR code has been downloaded!`)
|
||||||
: _(msg`QR code saved to your camera roll!`),
|
: _(msg`QR code saved to your camera roll!`),
|
||||||
)
|
)
|
||||||
@@ -178,18 +178,18 @@ export function QrCodeDialog({
|
|||||||
label={_(msg`Copy QR code`)}
|
label={_(msg`Copy QR code`)}
|
||||||
color="primary_subtle"
|
color="primary_subtle"
|
||||||
size="large"
|
size="large"
|
||||||
onPress={isWeb ? onCopyPress : onSharePress}>
|
onPress={IS_WEB ? onCopyPress : onSharePress}>
|
||||||
<ButtonIcon
|
<ButtonIcon
|
||||||
icon={
|
icon={
|
||||||
isCopyProcessing
|
isCopyProcessing
|
||||||
? Loader
|
? Loader
|
||||||
: isWeb
|
: IS_WEB
|
||||||
? ChainLinkIcon
|
? ChainLinkIcon
|
||||||
: ShareIcon
|
: ShareIcon
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<ButtonText>
|
<ButtonText>
|
||||||
{isWeb ? <Trans>Copy</Trans> : <Trans>Share</Trans>}
|
{IS_WEB ? <Trans>Copy</Trans> : <Trans>Share</Trans>}
|
||||||
</ButtonText>
|
</ButtonText>
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import {useSaveImageToMediaLibrary} from '#/lib/media/save-image'
|
|||||||
import {shareUrl} from '#/lib/sharing'
|
import {shareUrl} from '#/lib/sharing'
|
||||||
import {getStarterPackOgCard} from '#/lib/strings/starter-pack'
|
import {getStarterPackOgCard} from '#/lib/strings/starter-pack'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {isNative, isWeb} from '#/platform/detection'
|
|
||||||
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
|
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
|
||||||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||||||
import {type DialogControlProps} from '#/components/Dialog'
|
import {type DialogControlProps} from '#/components/Dialog'
|
||||||
@@ -18,6 +17,7 @@ import {Download_Stroke2_Corner0_Rounded as DownloadIcon} from '#/components/ico
|
|||||||
import {QrCode_Stroke2_Corner0_Rounded as QrCodeIcon} from '#/components/icons/QrCode'
|
import {QrCode_Stroke2_Corner0_Rounded as QrCodeIcon} from '#/components/icons/QrCode'
|
||||||
import {Loader} from '#/components/Loader'
|
import {Loader} from '#/components/Loader'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_NATIVE, IS_WEB} from '#/env'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
starterPack: AppBskyGraphDefs.StarterPackView
|
starterPack: AppBskyGraphDefs.StarterPackView
|
||||||
@@ -110,13 +110,17 @@ function ShareDialogInner({
|
|||||||
],
|
],
|
||||||
]}>
|
]}>
|
||||||
<Button
|
<Button
|
||||||
label={isWeb ? _(msg`Copy link`) : _(msg`Share link`)}
|
label={IS_WEB ? _(msg`Copy link`) : _(msg`Share link`)}
|
||||||
color="primary_subtle"
|
color="primary_subtle"
|
||||||
size="large"
|
size="large"
|
||||||
onPress={onShareLink}>
|
onPress={onShareLink}>
|
||||||
<ButtonIcon icon={ChainLinkIcon} />
|
<ButtonIcon icon={ChainLinkIcon} />
|
||||||
<ButtonText>
|
<ButtonText>
|
||||||
{isWeb ? <Trans>Copy Link</Trans> : <Trans>Share link</Trans>}
|
{IS_WEB ? (
|
||||||
|
<Trans>Copy Link</Trans>
|
||||||
|
) : (
|
||||||
|
<Trans>Share link</Trans>
|
||||||
|
)}
|
||||||
</ButtonText>
|
</ButtonText>
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
@@ -133,7 +137,7 @@ function ShareDialogInner({
|
|||||||
<Trans>Share QR code</Trans>
|
<Trans>Share QR code</Trans>
|
||||||
</ButtonText>
|
</ButtonText>
|
||||||
</Button>
|
</Button>
|
||||||
{isNative && (
|
{IS_NATIVE && (
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Save image`)}
|
label={_(msg`Save image`)}
|
||||||
color="secondary"
|
color="secondary"
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import {msg, Trans} from '@lingui/macro'
|
|||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender'
|
import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender'
|
||||||
import {isWeb} from '#/platform/detection'
|
|
||||||
import {type ListMethods} from '#/view/com/util/List'
|
import {type ListMethods} from '#/view/com/util/List'
|
||||||
import {
|
import {
|
||||||
type WizardAction,
|
type WizardAction,
|
||||||
@@ -24,6 +23,7 @@ import {
|
|||||||
WizardProfileCard,
|
WizardProfileCard,
|
||||||
} from '#/components/StarterPack/Wizard/WizardListCard'
|
} from '#/components/StarterPack/Wizard/WizardListCard'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_WEB} from '#/env'
|
||||||
|
|
||||||
function keyExtractor(
|
function keyExtractor(
|
||||||
item: AppBskyActorDefs.ProfileViewBasic | AppBskyFeedDefs.GeneratorView,
|
item: AppBskyActorDefs.ProfileViewBasic | AppBskyFeedDefs.GeneratorView,
|
||||||
@@ -95,7 +95,7 @@ export function WizardEditListDialog({
|
|||||||
a.mb_sm,
|
a.mb_sm,
|
||||||
t.atoms.bg,
|
t.atoms.bg,
|
||||||
t.atoms.border_contrast_medium,
|
t.atoms.border_contrast_medium,
|
||||||
isWeb
|
IS_WEB
|
||||||
? [
|
? [
|
||||||
a.align_center,
|
a.align_center,
|
||||||
{
|
{
|
||||||
@@ -113,7 +113,7 @@ export function WizardEditListDialog({
|
|||||||
)}
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
<View style={{width: 60}}>
|
<View style={{width: 60}}>
|
||||||
{isWeb && (
|
{IS_WEB && (
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Close`)}
|
label={_(msg`Close`)}
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import {View} from 'react-native'
|
import {View} from 'react-native'
|
||||||
|
|
||||||
import {isTouchDevice} from '#/lib/browser'
|
import {isTouchDevice} from '#/lib/browser'
|
||||||
import {isNative, isWeb} from '#/platform/detection'
|
|
||||||
import {atoms as a, useTheme, type ViewStyleProp} from '#/alf'
|
import {atoms as a, useTheme, type ViewStyleProp} from '#/alf'
|
||||||
|
import {IS_NATIVE, IS_WEB} from '#/env'
|
||||||
|
|
||||||
export function SubtleHover({
|
export function SubtleHover({
|
||||||
style,
|
style,
|
||||||
@@ -39,9 +39,9 @@ export function SubtleHover({
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
||||||
if (isWeb && web) {
|
if (IS_WEB && web) {
|
||||||
return isTouchDevice ? null : el
|
return isTouchDevice ? null : el
|
||||||
} else if (isNative && native) {
|
} else if (IS_NATIVE && native) {
|
||||||
return el
|
return el
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import {useLingui} from '@lingui/react'
|
|||||||
import {HITSLOP_10} from '#/lib/constants'
|
import {HITSLOP_10} from '#/lib/constants'
|
||||||
import {makeListLink, makeProfileLink} from '#/lib/routes/links'
|
import {makeListLink, makeProfileLink} from '#/lib/routes/links'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {isNative} from '#/platform/detection'
|
|
||||||
import {
|
import {
|
||||||
type ThreadgateAllowUISetting,
|
type ThreadgateAllowUISetting,
|
||||||
threadgateViewToAllowUISetting,
|
threadgateViewToAllowUISetting,
|
||||||
@@ -37,6 +36,7 @@ import {Earth_Stroke2_Corner0_Rounded as EarthIcon} from '#/components/icons/Glo
|
|||||||
import {Group3_Stroke2_Corner0_Rounded as GroupIcon} from '#/components/icons/Group'
|
import {Group3_Stroke2_Corner0_Rounded as GroupIcon} from '#/components/icons/Group'
|
||||||
import {InlineLinkText} from '#/components/Link'
|
import {InlineLinkText} from '#/components/Link'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_NATIVE} from '#/env'
|
||||||
import * as bsky from '#/types/bsky'
|
import * as bsky from '#/types/bsky'
|
||||||
|
|
||||||
interface WhoCanReplyProps {
|
interface WhoCanReplyProps {
|
||||||
@@ -86,7 +86,7 @@ export function WhoCanReply({post, isThreadAuthor, style}: WhoCanReplyProps) {
|
|||||||
: _(msg`Some people can reply`)
|
: _(msg`Some people can reply`)
|
||||||
|
|
||||||
const onPressOpen = () => {
|
const onPressOpen = () => {
|
||||||
if (isNative && Keyboard.isVisible()) {
|
if (IS_NATIVE && Keyboard.isVisible()) {
|
||||||
Keyboard.dismiss()
|
Keyboard.dismiss()
|
||||||
}
|
}
|
||||||
if (isThreadAuthor) {
|
if (isThreadAuthor) {
|
||||||
@@ -229,7 +229,7 @@ function WhoCanReplyDialog({
|
|||||||
embeddingDisabled={embeddingDisabled}
|
embeddingDisabled={embeddingDisabled}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
{isNative && (
|
{IS_NATIVE && (
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Close`)}
|
label={_(msg`Close`)}
|
||||||
onPress={() => control.close()}
|
onPress={() => control.close()}
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import {createSanitizedDisplayName} from '#/lib/moderation/create-sanitized-disp
|
|||||||
import {cleanError} from '#/lib/strings/errors'
|
import {cleanError} from '#/lib/strings/errors'
|
||||||
import {sanitizeHandle} from '#/lib/strings/handles'
|
import {sanitizeHandle} from '#/lib/strings/handles'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {isWeb} from '#/platform/detection'
|
|
||||||
import {updateProfileShadow} from '#/state/cache/profile-shadow'
|
import {updateProfileShadow} from '#/state/cache/profile-shadow'
|
||||||
import {RQKEY_getActivitySubscriptions} from '#/state/queries/activity-subscriptions'
|
import {RQKEY_getActivitySubscriptions} from '#/state/queries/activity-subscriptions'
|
||||||
import {useAgent} from '#/state/session'
|
import {useAgent} from '#/state/session'
|
||||||
@@ -37,6 +36,7 @@ import * as Toggle from '#/components/forms/Toggle'
|
|||||||
import {Loader} from '#/components/Loader'
|
import {Loader} from '#/components/Loader'
|
||||||
import * as ProfileCard from '#/components/ProfileCard'
|
import * as ProfileCard from '#/components/ProfileCard'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_WEB} from '#/env'
|
||||||
import type * as bsky from '#/types/bsky'
|
import type * as bsky from '#/types/bsky'
|
||||||
|
|
||||||
export function SubscribeProfileDialog({
|
export function SubscribeProfileDialog({
|
||||||
@@ -195,7 +195,7 @@ function DialogInner({
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// on web, a disabled save button feels more natural than a massive close button
|
// on web, a disabled save button feels more natural than a massive close button
|
||||||
if (isWeb) {
|
if (IS_WEB) {
|
||||||
return {
|
return {
|
||||||
label: _(msg`Save changes`),
|
label: _(msg`Save changes`),
|
||||||
color: 'secondary',
|
color: 'secondary',
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import {msg, Trans} from '@lingui/macro'
|
|||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
import {dateDiff, useGetTimeAgo} from '#/lib/hooks/useTimeAgo'
|
import {dateDiff, useGetTimeAgo} from '#/lib/hooks/useTimeAgo'
|
||||||
import {isNative} from '#/platform/detection'
|
|
||||||
import {atoms as a, useBreakpoints, useTheme, type ViewStyleProp} from '#/alf'
|
import {atoms as a, useBreakpoints, useTheme, type ViewStyleProp} from '#/alf'
|
||||||
import {Admonition} from '#/components/Admonition'
|
import {Admonition} from '#/components/Admonition'
|
||||||
import {AgeAssuranceAppealDialog} from '#/components/ageAssurance/AgeAssuranceAppealDialog'
|
import {AgeAssuranceAppealDialog} from '#/components/ageAssurance/AgeAssuranceAppealDialog'
|
||||||
@@ -23,6 +22,7 @@ import * as Toast from '#/components/Toast'
|
|||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
import {logger, useAgeAssurance} from '#/ageAssurance'
|
import {logger, useAgeAssurance} from '#/ageAssurance'
|
||||||
import {useComputeAgeAssuranceRegionAccess} from '#/ageAssurance/useComputeAgeAssuranceRegionAccess'
|
import {useComputeAgeAssuranceRegionAccess} from '#/ageAssurance/useComputeAgeAssuranceRegionAccess'
|
||||||
|
import {IS_NATIVE} from '#/env'
|
||||||
import {useDeviceGeolocationApi} from '#/geolocation'
|
import {useDeviceGeolocationApi} from '#/geolocation'
|
||||||
|
|
||||||
export function AgeAssuranceAccountCard({style}: ViewStyleProp & {}) {
|
export function AgeAssuranceAccountCard({style}: ViewStyleProp & {}) {
|
||||||
@@ -86,7 +86,7 @@ function Inner({style}: ViewStyleProp & {}) {
|
|||||||
<View style={[a.pb_md, a.gap_xs]}>
|
<View style={[a.pb_md, a.gap_xs]}>
|
||||||
<Text style={[a.text_sm, a.leading_snug]}>{copy.notice}</Text>
|
<Text style={[a.text_sm, a.leading_snug]}>{copy.notice}</Text>
|
||||||
|
|
||||||
{isNative && (
|
{IS_NATIVE && (
|
||||||
<>
|
<>
|
||||||
<Text style={[a.text_sm, a.leading_snug]}>
|
<Text style={[a.text_sm, a.leading_snug]}>
|
||||||
<Trans>
|
<Trans>
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import {useLingui} from '@lingui/react'
|
|||||||
|
|
||||||
import {retry} from '#/lib/async/retry'
|
import {retry} from '#/lib/async/retry'
|
||||||
import {wait} from '#/lib/async/wait'
|
import {wait} from '#/lib/async/wait'
|
||||||
import {isNative} from '#/platform/detection'
|
|
||||||
import {useAgent} from '#/state/session'
|
import {useAgent} from '#/state/session'
|
||||||
import {atoms as a, useTheme, web} from '#/alf'
|
import {atoms as a, useTheme, web} from '#/alf'
|
||||||
import {AgeAssuranceBadge} from '#/components/ageAssurance/AgeAssuranceBadge'
|
import {AgeAssuranceBadge} from '#/components/ageAssurance/AgeAssuranceBadge'
|
||||||
@@ -18,6 +17,7 @@ import {Loader} from '#/components/Loader'
|
|||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
import {refetchAgeAssuranceServerState} from '#/ageAssurance'
|
import {refetchAgeAssuranceServerState} from '#/ageAssurance'
|
||||||
import {logger} from '#/ageAssurance'
|
import {logger} from '#/ageAssurance'
|
||||||
|
import {IS_NATIVE} from '#/env'
|
||||||
|
|
||||||
export type AgeAssuranceRedirectDialogState = {
|
export type AgeAssuranceRedirectDialogState = {
|
||||||
result: 'success' | 'unknown'
|
result: 'success' | 'unknown'
|
||||||
@@ -166,7 +166,7 @@ export function Inner({}: {optimisticState?: AgeAssuranceRedirectDialogState}) {
|
|||||||
</Trans>
|
</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
{isNative && (
|
{IS_NATIVE && (
|
||||||
<View style={[a.w_full, a.pt_lg]}>
|
<View style={[a.w_full, a.pt_lg]}>
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Close`)}
|
label={_(msg`Close`)}
|
||||||
@@ -225,7 +225,7 @@ export function Inner({}: {optimisticState?: AgeAssuranceRedirectDialogState}) {
|
|||||||
)}
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
{error && isNative && (
|
{error && IS_NATIVE && (
|
||||||
<View style={[a.w_full, a.pt_lg]}>
|
<View style={[a.w_full, a.pt_lg]}>
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Close`)}
|
label={_(msg`Close`)}
|
||||||
|
|||||||
@@ -8,12 +8,12 @@ import {useLingui} from '@lingui/react'
|
|||||||
import {HITSLOP_10} from '#/lib/constants'
|
import {HITSLOP_10} from '#/lib/constants'
|
||||||
import {useGate} from '#/lib/statsig/statsig'
|
import {useGate} from '#/lib/statsig/statsig'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {isWeb} from '#/platform/detection'
|
|
||||||
import {Nux, useNux, useSaveNux} from '#/state/queries/nuxs'
|
import {Nux, useNux, useSaveNux} from '#/state/queries/nuxs'
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
import {Button} from '#/components/Button'
|
import {Button} from '#/components/Button'
|
||||||
import {TimesLarge_Stroke2_Corner0_Rounded as XIcon} from '#/components/icons/Times'
|
import {TimesLarge_Stroke2_Corner0_Rounded as XIcon} from '#/components/icons/Times'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_WEB} from '#/env'
|
||||||
import {Link} from '../Link'
|
import {Link} from '../Link'
|
||||||
import {useIsFindContactsFeatureEnabledBasedOnGeolocation} from './country-allowlist'
|
import {useIsFindContactsFeatureEnabledBasedOnGeolocation} from './country-allowlist'
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ function useInternalState() {
|
|||||||
const gate = useGate()
|
const gate = useGate()
|
||||||
|
|
||||||
const visible = useMemo(() => {
|
const visible = useMemo(() => {
|
||||||
if (isWeb) return false
|
if (IS_WEB) return false
|
||||||
if (hidden) return false
|
if (hidden) return false
|
||||||
if (nux && nux.completed) return false
|
if (nux && nux.completed) return false
|
||||||
if (!isFeatureEnabled) return false
|
if (!isFeatureEnabled) return false
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ import {msg} from '@lingui/macro'
|
|||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
import {mergeRefs} from '#/lib/merge-refs'
|
import {mergeRefs} from '#/lib/merge-refs'
|
||||||
import {isAndroid, isIOS} from '#/platform/detection'
|
|
||||||
import {atoms as a, ios, platform, useTheme} from '#/alf'
|
import {atoms as a, ios, platform, useTheme} from '#/alf'
|
||||||
import {useInteractionState} from '#/components/hooks/useInteractionState'
|
import {useInteractionState} from '#/components/hooks/useInteractionState'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_ANDROID, IS_IOS} from '#/env'
|
||||||
|
|
||||||
export function OTPInput({
|
export function OTPInput({
|
||||||
label,
|
label,
|
||||||
@@ -95,7 +95,7 @@ export function OTPInput({
|
|||||||
<TextInput
|
<TextInput
|
||||||
// SMS autofill is borked on iOS if you open the keyboard immediately -sfn
|
// SMS autofill is borked on iOS if you open the keyboard immediately -sfn
|
||||||
onLayout={ios(() => setTimeout(() => innerRef.current?.focus(), 100))}
|
onLayout={ios(() => setTimeout(() => innerRef.current?.focus(), 100))}
|
||||||
autoFocus={isAndroid}
|
autoFocus={IS_ANDROID}
|
||||||
accessible
|
accessible
|
||||||
accessibilityLabel={label}
|
accessibilityLabel={label}
|
||||||
accessibilityHint=""
|
accessibilityHint=""
|
||||||
@@ -135,7 +135,7 @@ export function OTPInput({
|
|||||||
android: {opacity: 0},
|
android: {opacity: 0},
|
||||||
}),
|
}),
|
||||||
]}
|
]}
|
||||||
caretHidden={isIOS}
|
caretHidden={IS_IOS}
|
||||||
clearTextOnFocus
|
clearTextOnFocus
|
||||||
/>
|
/>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import {useCleanError} from '#/lib/hooks/useCleanError'
|
|||||||
import {isAppPassword} from '#/lib/jwt'
|
import {isAppPassword} from '#/lib/jwt'
|
||||||
import {getAge, getDateAgo} from '#/lib/strings/time'
|
import {getAge, getDateAgo} from '#/lib/strings/time'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {isIOS, isWeb} from '#/platform/detection'
|
|
||||||
import {
|
import {
|
||||||
useBirthdateMutation,
|
useBirthdateMutation,
|
||||||
useIsBirthdateUpdateAllowed,
|
useIsBirthdateUpdateAllowed,
|
||||||
@@ -26,6 +25,7 @@ import {DateField} from '#/components/forms/DateField'
|
|||||||
import {SimpleInlineLinkText} from '#/components/Link'
|
import {SimpleInlineLinkText} from '#/components/Link'
|
||||||
import {Loader} from '#/components/Loader'
|
import {Loader} from '#/components/Loader'
|
||||||
import {Span, Text} from '#/components/Typography'
|
import {Span, Text} from '#/components/Typography'
|
||||||
|
import {IS_IOS, IS_WEB} from '#/env'
|
||||||
|
|
||||||
export function BirthDateSettingsDialog({
|
export function BirthDateSettingsDialog({
|
||||||
control,
|
control,
|
||||||
@@ -154,7 +154,7 @@ function BirthdayInner({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={a.gap_lg} testID="birthDateSettingsDialog">
|
<View style={a.gap_lg} testID="birthDateSettingsDialog">
|
||||||
<View style={isIOS && [a.w_full, a.align_center]}>
|
<View style={IS_IOS && [a.w_full, a.align_center]}>
|
||||||
<DateField
|
<DateField
|
||||||
testID="birthdayInput"
|
testID="birthdayInput"
|
||||||
value={date}
|
value={date}
|
||||||
@@ -191,7 +191,7 @@ function BirthdayInner({
|
|||||||
<ErrorMessage message={errorMessage} style={[a.rounded_sm]} />
|
<ErrorMessage message={errorMessage} style={[a.rounded_sm]} />
|
||||||
) : undefined}
|
) : undefined}
|
||||||
|
|
||||||
<View style={isWeb && [a.flex_row, a.justify_end]}>
|
<View style={IS_WEB && [a.flex_row, a.justify_end]}>
|
||||||
<Button
|
<Button
|
||||||
label={hasChanged ? _(msg`Save birthdate`) : _(msg`Done`)}
|
label={hasChanged ? _(msg`Save birthdate`) : _(msg`Done`)}
|
||||||
size="large"
|
size="large"
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import {useLingui} from '@lingui/react'
|
|||||||
import {wait} from '#/lib/async/wait'
|
import {wait} from '#/lib/async/wait'
|
||||||
import {isNetworkError, useCleanError} from '#/lib/hooks/useCleanError'
|
import {isNetworkError, useCleanError} from '#/lib/hooks/useCleanError'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {isWeb} from '#/platform/detection'
|
|
||||||
import {atoms as a, useTheme, web} from '#/alf'
|
import {atoms as a, useTheme, web} from '#/alf'
|
||||||
import {Admonition} from '#/components/Admonition'
|
import {Admonition} from '#/components/Admonition'
|
||||||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||||||
@@ -14,6 +13,7 @@ import * as Dialog from '#/components/Dialog'
|
|||||||
import {PinLocation_Stroke2_Corner0_Rounded as LocationIcon} from '#/components/icons/PinLocation'
|
import {PinLocation_Stroke2_Corner0_Rounded as LocationIcon} from '#/components/icons/PinLocation'
|
||||||
import {Loader} from '#/components/Loader'
|
import {Loader} from '#/components/Loader'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_WEB} from '#/env'
|
||||||
import {type Geolocation, useRequestDeviceGeolocation} from '#/geolocation'
|
import {type Geolocation, useRequestDeviceGeolocation} from '#/geolocation'
|
||||||
|
|
||||||
export type Props = {
|
export type Props = {
|
||||||
@@ -138,7 +138,7 @@ function DeviceLocationRequestDialogInner({onLocationAcquired}: Props) {
|
|||||||
disabled={isRequesting}
|
disabled={isRequesting}
|
||||||
label={_(msg`Allow location access`)}
|
label={_(msg`Allow location access`)}
|
||||||
onPress={onPressConfirm}
|
onPress={onPressConfirm}
|
||||||
size={isWeb ? 'small' : 'large'}
|
size={IS_WEB ? 'small' : 'large'}
|
||||||
color="primary">
|
color="primary">
|
||||||
<ButtonIcon icon={isRequesting ? Loader : LocationIcon} />
|
<ButtonIcon icon={isRequesting ? Loader : LocationIcon} />
|
||||||
<ButtonText>
|
<ButtonText>
|
||||||
@@ -147,11 +147,11 @@ function DeviceLocationRequestDialogInner({onLocationAcquired}: Props) {
|
|||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!isWeb && (
|
{!IS_WEB && (
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Cancel`)}
|
label={_(msg`Cancel`)}
|
||||||
onPress={() => close()}
|
onPress={() => close()}
|
||||||
size={isWeb ? 'small' : 'large'}
|
size={IS_WEB ? 'small' : 'large'}
|
||||||
color="secondary">
|
color="secondary">
|
||||||
<ButtonText>
|
<ButtonText>
|
||||||
<Trans>Cancel</Trans>
|
<Trans>Cancel</Trans>
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import {useLingui} from '@lingui/react'
|
|||||||
|
|
||||||
import {logEvent} from '#/lib/statsig/statsig'
|
import {logEvent} from '#/lib/statsig/statsig'
|
||||||
import {cleanError} from '#/lib/strings/errors'
|
import {cleanError} from '#/lib/strings/errors'
|
||||||
import {isWeb} from '#/platform/detection'
|
|
||||||
import {
|
import {
|
||||||
type Gif,
|
type Gif,
|
||||||
tenorUrlToBskyGifUrl,
|
tenorUrlToBskyGifUrl,
|
||||||
@@ -31,6 +30,7 @@ import {useThrottledValue} from '#/components/hooks/useThrottledValue'
|
|||||||
import {ArrowLeft_Stroke2_Corner0_Rounded as Arrow} from '#/components/icons/Arrow'
|
import {ArrowLeft_Stroke2_Corner0_Rounded as Arrow} from '#/components/icons/Arrow'
|
||||||
import {MagnifyingGlass_Stroke2_Corner0_Rounded as Search} from '#/components/icons/MagnifyingGlass'
|
import {MagnifyingGlass_Stroke2_Corner0_Rounded as Search} from '#/components/icons/MagnifyingGlass'
|
||||||
import {ListFooter, ListMaybePlaceholder} from '#/components/Lists'
|
import {ListFooter, ListMaybePlaceholder} from '#/components/Lists'
|
||||||
|
import {IS_WEB} from '#/env'
|
||||||
|
|
||||||
export function GifSelectDialog({
|
export function GifSelectDialog({
|
||||||
controlRef,
|
controlRef,
|
||||||
@@ -149,7 +149,7 @@ function GifList({
|
|||||||
a.pb_sm,
|
a.pb_sm,
|
||||||
t.atoms.bg,
|
t.atoms.bg,
|
||||||
]}>
|
]}>
|
||||||
{!gtMobile && isWeb && (
|
{!gtMobile && IS_WEB && (
|
||||||
<Button
|
<Button
|
||||||
size="small"
|
size="small"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
@@ -161,7 +161,7 @@ function GifList({
|
|||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<TextField.Root style={[!gtMobile && isWeb && a.flex_1]}>
|
<TextField.Root style={[!gtMobile && IS_WEB && a.flex_1]}>
|
||||||
<TextField.Icon icon={Search} />
|
<TextField.Icon icon={Search} />
|
||||||
<TextField.Input
|
<TextField.Input
|
||||||
label={_(msg`Search GIFs`)}
|
label={_(msg`Search GIFs`)}
|
||||||
|
|||||||
@@ -4,19 +4,19 @@ import {msg, Trans} from '@lingui/macro'
|
|||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
import {useOpenLink} from '#/lib/hooks/useOpenLink'
|
import {useOpenLink} from '#/lib/hooks/useOpenLink'
|
||||||
import {isWeb} from '#/platform/detection'
|
|
||||||
import {useSetInAppBrowser} from '#/state/preferences/in-app-browser'
|
import {useSetInAppBrowser} from '#/state/preferences/in-app-browser'
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||||||
import * as Dialog from '#/components/Dialog'
|
import * as Dialog from '#/components/Dialog'
|
||||||
import {SquareArrowTopRight_Stroke2_Corner0_Rounded as External} from '#/components/icons/SquareArrowTopRight'
|
import {SquareArrowTopRight_Stroke2_Corner0_Rounded as External} from '#/components/icons/SquareArrowTopRight'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_WEB} from '#/env'
|
||||||
import {useGlobalDialogsControlContext} from './Context'
|
import {useGlobalDialogsControlContext} from './Context'
|
||||||
|
|
||||||
export function InAppBrowserConsentDialog() {
|
export function InAppBrowserConsentDialog() {
|
||||||
const {inAppBrowserConsentControl} = useGlobalDialogsControlContext()
|
const {inAppBrowserConsentControl} = useGlobalDialogsControlContext()
|
||||||
|
|
||||||
if (isWeb) return null
|
if (IS_WEB) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog.Outer
|
<Dialog.Outer
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import {msg, Trans} from '@lingui/macro'
|
|||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {isNative} from '#/platform/detection'
|
|
||||||
import {
|
import {
|
||||||
usePreferencesQuery,
|
usePreferencesQuery,
|
||||||
useRemoveMutedWordMutation,
|
useRemoveMutedWordMutation,
|
||||||
@@ -32,6 +31,7 @@ import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times'
|
|||||||
import {Loader} from '#/components/Loader'
|
import {Loader} from '#/components/Loader'
|
||||||
import * as Prompt from '#/components/Prompt'
|
import * as Prompt from '#/components/Prompt'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_NATIVE} from '#/env'
|
||||||
|
|
||||||
const ONE_DAY = 24 * 60 * 60 * 1000
|
const ONE_DAY = 24 * 60 * 60 * 1000
|
||||||
|
|
||||||
@@ -406,7 +406,7 @@ function MutedWordsInner() {
|
|||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{isNative && <View style={{height: 20}} />}
|
{IS_NATIVE && <View style={{height: 20}} />}
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<Dialog.Close />
|
<Dialog.Close />
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import {useQueryClient} from '@tanstack/react-query'
|
|||||||
import {useHaptics} from '#/lib/haptics'
|
import {useHaptics} from '#/lib/haptics'
|
||||||
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {isIOS} from '#/platform/detection'
|
|
||||||
import {STALE} from '#/state/queries'
|
import {STALE} from '#/state/queries'
|
||||||
import {useMyListsQuery} from '#/state/queries/my-lists'
|
import {useMyListsQuery} from '#/state/queries/my-lists'
|
||||||
import {useGetPost} from '#/state/queries/post'
|
import {useGetPost} from '#/state/queries/post'
|
||||||
@@ -52,6 +51,7 @@ import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/ico
|
|||||||
import {CloseQuote_Stroke2_Corner1_Rounded as QuoteIcon} from '#/components/icons/Quote'
|
import {CloseQuote_Stroke2_Corner1_Rounded as QuoteIcon} from '#/components/icons/Quote'
|
||||||
import {Loader} from '#/components/Loader'
|
import {Loader} from '#/components/Loader'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_IOS} from '#/env'
|
||||||
|
|
||||||
export type PostInteractionSettingsFormProps = {
|
export type PostInteractionSettingsFormProps = {
|
||||||
canSave?: boolean
|
canSave?: boolean
|
||||||
@@ -531,7 +531,7 @@ export function PostInteractionSettingsForm({
|
|||||||
hitSlop={0}
|
hitSlop={0}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
playHaptic('Light')
|
playHaptic('Light')
|
||||||
if (isIOS && !showLists) {
|
if (IS_IOS && !showLists) {
|
||||||
LayoutAnimation.configureNext({
|
LayoutAnimation.configureNext({
|
||||||
...LayoutAnimation.Presets.linear,
|
...LayoutAnimation.Presets.linear,
|
||||||
duration: 175,
|
duration: 175,
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import {useLingui} from '@lingui/react'
|
|||||||
|
|
||||||
import {sanitizeDisplayName} from '#/lib/strings/display-names'
|
import {sanitizeDisplayName} from '#/lib/strings/display-names'
|
||||||
import {sanitizeHandle} from '#/lib/strings/handles'
|
import {sanitizeHandle} from '#/lib/strings/handles'
|
||||||
import {isWeb} from '#/platform/detection'
|
|
||||||
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
||||||
import {useActorAutocompleteQuery} from '#/state/queries/actor-autocomplete'
|
import {useActorAutocompleteQuery} from '#/state/queries/actor-autocomplete'
|
||||||
import {useListConvosQuery} from '#/state/queries/messages/list-conversations'
|
import {useListConvosQuery} from '#/state/queries/messages/list-conversations'
|
||||||
@@ -29,6 +28,7 @@ import {MagnifyingGlass_Stroke2_Corner0_Rounded as Search} from '#/components/ic
|
|||||||
import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times'
|
import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times'
|
||||||
import * as ProfileCard from '#/components/ProfileCard'
|
import * as ProfileCard from '#/components/ProfileCard'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_WEB} from '#/env'
|
||||||
import type * as bsky from '#/types/bsky'
|
import type * as bsky from '#/types/bsky'
|
||||||
|
|
||||||
export type ProfileItem = {
|
export type ProfileItem = {
|
||||||
@@ -254,7 +254,7 @@ export function SearchablePeopleList({
|
|||||||
)
|
)
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
if (isWeb) {
|
if (IS_WEB) {
|
||||||
setImmediate(() => {
|
setImmediate(() => {
|
||||||
inputRef?.current?.focus()
|
inputRef?.current?.focus()
|
||||||
})
|
})
|
||||||
@@ -290,12 +290,12 @@ export function SearchablePeopleList({
|
|||||||
]}>
|
]}>
|
||||||
{title}
|
{title}
|
||||||
</Text>
|
</Text>
|
||||||
{isWeb ? (
|
{IS_WEB ? (
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Close`)}
|
label={_(msg`Close`)}
|
||||||
size="small"
|
size="small"
|
||||||
shape="round"
|
shape="round"
|
||||||
variant={isWeb ? 'ghost' : 'solid'}
|
variant={IS_WEB ? 'ghost' : 'solid'}
|
||||||
color="secondary"
|
color="secondary"
|
||||||
style={[
|
style={[
|
||||||
a.absolute,
|
a.absolute,
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import {View} from 'react-native'
|
|||||||
import {msg, Trans} from '@lingui/macro'
|
import {msg, Trans} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
import {isNative} from '#/platform/detection'
|
|
||||||
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
|
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
|
||||||
import {useCloseAllActiveElements} from '#/state/util'
|
import {useCloseAllActiveElements} from '#/state/util'
|
||||||
import {Logo} from '#/view/icons/Logo'
|
import {Logo} from '#/view/icons/Logo'
|
||||||
@@ -13,6 +12,7 @@ import {Button, ButtonText} from '#/components/Button'
|
|||||||
import * as Dialog from '#/components/Dialog'
|
import * as Dialog from '#/components/Dialog'
|
||||||
import {useGlobalDialogsControlContext} from '#/components/dialogs/Context'
|
import {useGlobalDialogsControlContext} from '#/components/dialogs/Context'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_NATIVE} from '#/env'
|
||||||
|
|
||||||
export function SigninDialog() {
|
export function SigninDialog() {
|
||||||
const {signinDialogControl: control} = useGlobalDialogsControlContext()
|
const {signinDialogControl: control} = useGlobalDialogsControlContext()
|
||||||
@@ -45,7 +45,7 @@ function SigninDialogInner({}: {control: Dialog.DialogOuterProps['control']}) {
|
|||||||
<Dialog.ScrollableInner
|
<Dialog.ScrollableInner
|
||||||
label={_(msg`Sign in to Bluesky or create a new account`)}
|
label={_(msg`Sign in to Bluesky or create a new account`)}
|
||||||
style={[gtMobile ? {width: 'auto', maxWidth: 420} : a.w_full]}>
|
style={[gtMobile ? {width: 'auto', maxWidth: 420} : a.w_full]}>
|
||||||
<View style={[!isNative && a.p_2xl]}>
|
<View style={[!IS_NATIVE && a.p_2xl]}>
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
a.flex_row,
|
a.flex_row,
|
||||||
@@ -101,7 +101,7 @@ function SigninDialogInner({}: {control: Dialog.DialogOuterProps['control']}) {
|
|||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{isNative && <View style={{height: 10}} />}
|
{IS_NATIVE && <View style={{height: 10}} />}
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<Dialog.Close />
|
<Dialog.Close />
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import {useQueryClient} from '@tanstack/react-query'
|
|||||||
import {useRequireEmailVerification} from '#/lib/hooks/useRequireEmailVerification'
|
import {useRequireEmailVerification} from '#/lib/hooks/useRequireEmailVerification'
|
||||||
import {type NavigationProp} from '#/lib/routes/types'
|
import {type NavigationProp} from '#/lib/routes/types'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {isWeb} from '#/platform/detection'
|
|
||||||
import {
|
import {
|
||||||
invalidateActorStarterPacksWithMembershipQuery,
|
invalidateActorStarterPacksWithMembershipQuery,
|
||||||
useActorStarterPacksWithMembershipsQuery,
|
useActorStarterPacksWithMembershipsQuery,
|
||||||
@@ -32,6 +31,7 @@ import {StarterPack} from '#/components/icons/StarterPack'
|
|||||||
import {TimesLarge_Stroke2_Corner0_Rounded as XIcon} from '#/components/icons/Times'
|
import {TimesLarge_Stroke2_Corner0_Rounded as XIcon} from '#/components/icons/Times'
|
||||||
import {Loader} from '#/components/Loader'
|
import {Loader} from '#/components/Loader'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_WEB} from '#/env'
|
||||||
import * as bsky from '#/types/bsky'
|
import * as bsky from '#/types/bsky'
|
||||||
|
|
||||||
type StarterPackWithMembership =
|
type StarterPackWithMembership =
|
||||||
@@ -91,7 +91,7 @@ function Empty({onStartWizard}: {onStartWizard: () => void}) {
|
|||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[a.gap_2xl, {paddingTop: isWeb ? 100 : 64}]}>
|
<View style={[a.gap_2xl, {paddingTop: IS_WEB ? 100 : 64}]}>
|
||||||
<View style={[a.gap_xs, a.align_center]}>
|
<View style={[a.gap_xs, a.align_center]}>
|
||||||
<StarterPack
|
<StarterPack
|
||||||
width={48}
|
width={48}
|
||||||
@@ -169,7 +169,7 @@ function StarterPackList({
|
|||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
{justifyContent: 'space-between', flexDirection: 'row'},
|
{justifyContent: 'space-between', flexDirection: 'row'},
|
||||||
isWeb ? a.mb_2xl : a.my_lg,
|
IS_WEB ? a.mb_2xl : a.my_lg,
|
||||||
a.align_center,
|
a.align_center,
|
||||||
]}>
|
]}>
|
||||||
<Text style={[a.text_lg, a.font_semi_bold]}>
|
<Text style={[a.text_lg, a.font_semi_bold]}>
|
||||||
@@ -232,7 +232,7 @@ function StarterPackList({
|
|||||||
onEndReachedThreshold={0.1}
|
onEndReachedThreshold={0.1}
|
||||||
ListHeaderComponent={listHeader}
|
ListHeaderComponent={listHeader}
|
||||||
ListEmptyComponent={<Empty onStartWizard={onStartWizard} />}
|
ListEmptyComponent={<Empty onStartWizard={onStartWizard} />}
|
||||||
style={isWeb ? [a.px_md, {minHeight: 500}] : [a.px_2xl, a.pt_lg]}
|
style={IS_WEB ? [a.px_md, {minHeight: 500}] : [a.px_2xl, a.pt_lg]}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import {isOverMaxGraphemeCount} from '#/lib/strings/helpers'
|
|||||||
import {richTextToString} from '#/lib/strings/rich-text-helpers'
|
import {richTextToString} from '#/lib/strings/rich-text-helpers'
|
||||||
import {shortenLinks, stripInvalidMentions} from '#/lib/strings/rich-text-manip'
|
import {shortenLinks, stripInvalidMentions} from '#/lib/strings/rich-text-manip'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {isWeb} from '#/platform/detection'
|
|
||||||
import {type ImageMeta} from '#/state/gallery'
|
import {type ImageMeta} from '#/state/gallery'
|
||||||
import {
|
import {
|
||||||
useListCreateMutation,
|
useListCreateMutation,
|
||||||
@@ -26,6 +25,7 @@ import * as TextField from '#/components/forms/TextField'
|
|||||||
import {Loader} from '#/components/Loader'
|
import {Loader} from '#/components/Loader'
|
||||||
import * as Prompt from '#/components/Prompt'
|
import * as Prompt from '#/components/Prompt'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_WEB} from '#/env'
|
||||||
|
|
||||||
const DISPLAY_NAME_MAX_GRAPHEMES = 64
|
const DISPLAY_NAME_MAX_GRAPHEMES = 64
|
||||||
const DESCRIPTION_MAX_GRAPHEMES = 300
|
const DESCRIPTION_MAX_GRAPHEMES = 300
|
||||||
@@ -48,7 +48,7 @@ export function CreateOrEditListDialog({
|
|||||||
|
|
||||||
// 'You might lose unsaved changes' warning
|
// 'You might lose unsaved changes' warning
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isWeb && dirty) {
|
if (IS_WEB && dirty) {
|
||||||
const abortController = new AbortController()
|
const abortController = new AbortController()
|
||||||
const {signal} = abortController
|
const {signal} = abortController
|
||||||
window.addEventListener('beforeunload', evt => evt.preventDefault(), {
|
window.addEventListener('beforeunload', evt => evt.preventDefault(), {
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ import {Image} from 'expo-image'
|
|||||||
import {msg, Trans} from '@lingui/macro'
|
import {msg, Trans} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
import {isWeb} from '#/platform/detection'
|
|
||||||
import {atoms as a, useTheme, web} from '#/alf'
|
import {atoms as a, useTheme, web} from '#/alf'
|
||||||
import {Button, ButtonText} from '#/components/Button'
|
import {Button, ButtonText} from '#/components/Button'
|
||||||
import * as Dialog from '#/components/Dialog'
|
import * as Dialog from '#/components/Dialog'
|
||||||
import {useNuxDialogContext} from '#/components/dialogs/nuxs'
|
import {useNuxDialogContext} from '#/components/dialogs/nuxs'
|
||||||
import {Sparkle_Stroke2_Corner0_Rounded as SparkleIcon} from '#/components/icons/Sparkle'
|
import {Sparkle_Stroke2_Corner0_Rounded as SparkleIcon} from '#/components/icons/Sparkle'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_WEB} from '#/env'
|
||||||
|
|
||||||
export function ActivitySubscriptionsNUX() {
|
export function ActivitySubscriptionsNUX() {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
@@ -44,8 +44,8 @@ export function ActivitySubscriptionsNUX() {
|
|||||||
a.overflow_hidden,
|
a.overflow_hidden,
|
||||||
t.atoms.bg_contrast_25,
|
t.atoms.bg_contrast_25,
|
||||||
{
|
{
|
||||||
gap: isWeb ? 16 : 24,
|
gap: IS_WEB ? 16 : 24,
|
||||||
paddingTop: isWeb ? 24 : 48,
|
paddingTop: IS_WEB ? 24 : 48,
|
||||||
borderTopLeftRadius: a.rounded_md.borderRadius,
|
borderTopLeftRadius: a.rounded_md.borderRadius,
|
||||||
borderTopRightRadius: a.rounded_md.borderRadius,
|
borderTopRightRadius: a.rounded_md.borderRadius,
|
||||||
},
|
},
|
||||||
@@ -120,7 +120,7 @@ export function ActivitySubscriptionsNUX() {
|
|||||||
style={[
|
style={[
|
||||||
a.align_center,
|
a.align_center,
|
||||||
a.px_xl,
|
a.px_xl,
|
||||||
isWeb ? [a.pt_xl, a.gap_xl, a.pb_sm] : [a.pt_3xl, a.gap_3xl],
|
IS_WEB ? [a.pt_xl, a.gap_xl, a.pb_sm] : [a.pt_3xl, a.gap_3xl],
|
||||||
]}>
|
]}>
|
||||||
<View style={[a.gap_md, a.align_center]}>
|
<View style={[a.gap_md, a.align_center]}>
|
||||||
<Text
|
<Text
|
||||||
@@ -130,7 +130,7 @@ export function ActivitySubscriptionsNUX() {
|
|||||||
a.font_bold,
|
a.font_bold,
|
||||||
a.text_center,
|
a.text_center,
|
||||||
{
|
{
|
||||||
fontSize: isWeb ? 28 : 32,
|
fontSize: IS_WEB ? 28 : 32,
|
||||||
maxWidth: 300,
|
maxWidth: 300,
|
||||||
},
|
},
|
||||||
]}>
|
]}>
|
||||||
@@ -153,7 +153,7 @@ export function ActivitySubscriptionsNUX() {
|
|||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{!isWeb && (
|
{!IS_WEB && (
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Close`)}
|
label={_(msg`Close`)}
|
||||||
size="large"
|
size="large"
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import {LinearGradient} from 'expo-linear-gradient'
|
|||||||
import {msg, Trans} from '@lingui/macro'
|
import {msg, Trans} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
import {isWeb} from '#/platform/detection'
|
|
||||||
import {atoms as a, useTheme, web} from '#/alf'
|
import {atoms as a, useTheme, web} from '#/alf'
|
||||||
import {transparentifyColor} from '#/alf/util/colorGeneration'
|
import {transparentifyColor} from '#/alf/util/colorGeneration'
|
||||||
import {Button, ButtonText} from '#/components/Button'
|
import {Button, ButtonText} from '#/components/Button'
|
||||||
@@ -13,6 +12,7 @@ import * as Dialog from '#/components/Dialog'
|
|||||||
import {useNuxDialogContext} from '#/components/dialogs/nuxs'
|
import {useNuxDialogContext} from '#/components/dialogs/nuxs'
|
||||||
import {Sparkle_Stroke2_Corner0_Rounded as SparkleIcon} from '#/components/icons/Sparkle'
|
import {Sparkle_Stroke2_Corner0_Rounded as SparkleIcon} from '#/components/icons/Sparkle'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_WEB} from '#/env'
|
||||||
|
|
||||||
export function BookmarksAnnouncement() {
|
export function BookmarksAnnouncement() {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
@@ -49,7 +49,7 @@ export function BookmarksAnnouncement() {
|
|||||||
a.overflow_hidden,
|
a.overflow_hidden,
|
||||||
{
|
{
|
||||||
gap: 16,
|
gap: 16,
|
||||||
paddingTop: isWeb ? 24 : 40,
|
paddingTop: IS_WEB ? 24 : 40,
|
||||||
borderTopLeftRadius: a.rounded_md.borderRadius,
|
borderTopLeftRadius: a.rounded_md.borderRadius,
|
||||||
borderTopRightRadius: a.rounded_md.borderRadius,
|
borderTopRightRadius: a.rounded_md.borderRadius,
|
||||||
},
|
},
|
||||||
@@ -90,7 +90,7 @@ export function BookmarksAnnouncement() {
|
|||||||
borderRadius: 24,
|
borderRadius: 24,
|
||||||
aspectRatio: 333 / 104,
|
aspectRatio: 333 / 104,
|
||||||
},
|
},
|
||||||
isWeb
|
IS_WEB
|
||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
boxShadow: `0px 10px 15px -3px ${transparentifyColor(t.palette.black, 0.2)}`,
|
boxShadow: `0px 10px 15px -3px ${transparentifyColor(t.palette.black, 0.2)}`,
|
||||||
@@ -136,7 +136,7 @@ export function BookmarksAnnouncement() {
|
|||||||
a.font_bold,
|
a.font_bold,
|
||||||
a.text_center,
|
a.text_center,
|
||||||
{
|
{
|
||||||
fontSize: isWeb ? 28 : 32,
|
fontSize: IS_WEB ? 28 : 32,
|
||||||
maxWidth: 300,
|
maxWidth: 300,
|
||||||
},
|
},
|
||||||
]}>
|
]}>
|
||||||
@@ -158,7 +158,7 @@ export function BookmarksAnnouncement() {
|
|||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{!isWeb && (
|
{!IS_WEB && (
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Close`)}
|
label={_(msg`Close`)}
|
||||||
size="large"
|
size="large"
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import {msg, Trans} from '@lingui/macro'
|
|||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {isNative, isWeb} from '#/platform/detection'
|
|
||||||
import {atoms as a, useTheme, web} from '#/alf'
|
import {atoms as a, useTheme, web} from '#/alf'
|
||||||
import {Button, ButtonText} from '#/components/Button'
|
import {Button, ButtonText} from '#/components/Button'
|
||||||
import {isFindContactsFeatureEnabled} from '#/components/contacts/country-allowlist'
|
import {isFindContactsFeatureEnabled} from '#/components/contacts/country-allowlist'
|
||||||
@@ -17,13 +16,14 @@ import {
|
|||||||
isExistingUserAsOf,
|
isExistingUserAsOf,
|
||||||
} from '#/components/dialogs/nuxs/utils'
|
} from '#/components/dialogs/nuxs/utils'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_NATIVE, IS_WEB} from '#/env'
|
||||||
import {IS_E2E} from '#/env'
|
import {IS_E2E} from '#/env'
|
||||||
import {navigate} from '#/Navigation'
|
import {navigate} from '#/Navigation'
|
||||||
|
|
||||||
export const enabled = createIsEnabledCheck(props => {
|
export const enabled = createIsEnabledCheck(props => {
|
||||||
return (
|
return (
|
||||||
!IS_E2E &&
|
!IS_E2E &&
|
||||||
isNative &&
|
IS_NATIVE &&
|
||||||
isExistingUserAsOf(
|
isExistingUserAsOf(
|
||||||
'2025-12-16T00:00:00.000Z',
|
'2025-12-16T00:00:00.000Z',
|
||||||
props.currentProfile.createdAt,
|
props.currentProfile.createdAt,
|
||||||
@@ -89,7 +89,7 @@ export function FindContactsAnnouncement() {
|
|||||||
a.font_bold,
|
a.font_bold,
|
||||||
a.text_center,
|
a.text_center,
|
||||||
{
|
{
|
||||||
fontSize: isWeb ? 28 : 32,
|
fontSize: IS_WEB ? 28 : 32,
|
||||||
maxWidth: 300,
|
maxWidth: 300,
|
||||||
},
|
},
|
||||||
]}>
|
]}>
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import {useLingui} from '@lingui/react'
|
|||||||
|
|
||||||
import {urls} from '#/lib/constants'
|
import {urls} from '#/lib/constants'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {isNative} from '#/platform/detection'
|
|
||||||
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
|
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
|
||||||
import {Button, ButtonText} from '#/components/Button'
|
import {Button, ButtonText} from '#/components/Button'
|
||||||
import * as Dialog from '#/components/Dialog'
|
import * as Dialog from '#/components/Dialog'
|
||||||
@@ -15,6 +14,7 @@ import {Sparkle_Stroke2_Corner0_Rounded as SparkleIcon} from '#/components/icons
|
|||||||
import {VerifierCheck} from '#/components/icons/VerifierCheck'
|
import {VerifierCheck} from '#/components/icons/VerifierCheck'
|
||||||
import {Link} from '#/components/Link'
|
import {Link} from '#/components/Link'
|
||||||
import {Span, Text} from '#/components/Typography'
|
import {Span, Text} from '#/components/Typography'
|
||||||
|
import {IS_NATIVE} from '#/env'
|
||||||
|
|
||||||
export function InitialVerificationAnnouncement() {
|
export function InitialVerificationAnnouncement() {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
@@ -173,7 +173,7 @@ export function InitialVerificationAnnouncement() {
|
|||||||
<Trans>Read blog post</Trans>
|
<Trans>Read blog post</Trans>
|
||||||
</ButtonText>
|
</ButtonText>
|
||||||
</Link>
|
</Link>
|
||||||
{isNative && (
|
{IS_NATIVE && (
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Close`)}
|
label={_(msg`Close`)}
|
||||||
size="small"
|
size="small"
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import {LinearGradient} from 'expo-linear-gradient'
|
|||||||
import {msg, Trans} from '@lingui/macro'
|
import {msg, Trans} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
import {isWeb} from '#/platform/detection'
|
|
||||||
import {atoms as a, select, useTheme, utils, web} from '#/alf'
|
import {atoms as a, select, useTheme, utils, web} from '#/alf'
|
||||||
import {Button, ButtonText} from '#/components/Button'
|
import {Button, ButtonText} from '#/components/Button'
|
||||||
import * as Dialog from '#/components/Dialog'
|
import * as Dialog from '#/components/Dialog'
|
||||||
@@ -16,6 +15,7 @@ import {
|
|||||||
} from '#/components/dialogs/nuxs/utils'
|
} from '#/components/dialogs/nuxs/utils'
|
||||||
import {Beaker_Stroke2_Corner2_Rounded as BeakerIcon} from '#/components/icons/Beaker'
|
import {Beaker_Stroke2_Corner2_Rounded as BeakerIcon} from '#/components/icons/Beaker'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_WEB} from '#/env'
|
||||||
import {IS_E2E} from '#/env'
|
import {IS_E2E} from '#/env'
|
||||||
|
|
||||||
export const enabled = createIsEnabledCheck(props => {
|
export const enabled = createIsEnabledCheck(props => {
|
||||||
@@ -72,7 +72,7 @@ export function LiveNowBetaDialog() {
|
|||||||
a.overflow_hidden,
|
a.overflow_hidden,
|
||||||
{
|
{
|
||||||
gap: 16,
|
gap: 16,
|
||||||
paddingTop: isWeb ? 24 : 40,
|
paddingTop: IS_WEB ? 24 : 40,
|
||||||
borderTopLeftRadius: a.rounded_md.borderRadius,
|
borderTopLeftRadius: a.rounded_md.borderRadius,
|
||||||
borderTopRightRadius: a.rounded_md.borderRadius,
|
borderTopRightRadius: a.rounded_md.borderRadius,
|
||||||
},
|
},
|
||||||
@@ -116,7 +116,7 @@ export function LiveNowBetaDialog() {
|
|||||||
borderRadius: 24,
|
borderRadius: 24,
|
||||||
aspectRatio: 652 / 211,
|
aspectRatio: 652 / 211,
|
||||||
},
|
},
|
||||||
isWeb
|
IS_WEB
|
||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
boxShadow: `0px 10px 15px -3px ${shadowColor}`,
|
boxShadow: `0px 10px 15px -3px ${shadowColor}`,
|
||||||
@@ -163,7 +163,7 @@ export function LiveNowBetaDialog() {
|
|||||||
a.font_bold,
|
a.font_bold,
|
||||||
a.text_center,
|
a.text_center,
|
||||||
{
|
{
|
||||||
fontSize: isWeb ? 28 : 32,
|
fontSize: IS_WEB ? 28 : 32,
|
||||||
maxWidth: 360,
|
maxWidth: 360,
|
||||||
},
|
},
|
||||||
]}>
|
]}>
|
||||||
@@ -186,7 +186,7 @@ export function LiveNowBetaDialog() {
|
|||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{!isWeb && (
|
{!IS_WEB && (
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Close`)}
|
label={_(msg`Close`)}
|
||||||
size="large"
|
size="large"
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export function ActionsWrapper({
|
|||||||
<MessageContextMenu message={message}>
|
<MessageContextMenu message={message}>
|
||||||
{trigger =>
|
{trigger =>
|
||||||
// will always be true, since this file is platform split
|
// will always be true, since this file is platform split
|
||||||
trigger.isNative && (
|
trigger.IS_NATIVE && (
|
||||||
<View style={[a.flex_1, a.relative]}>
|
<View style={[a.flex_1, a.relative]}>
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
|
|||||||
@@ -89,9 +89,9 @@ export function ActionsWrapper({
|
|||||||
: [a.ml_xs, {marginRight: 'auto'}],
|
: [a.ml_xs, {marginRight: 'auto'}],
|
||||||
]}>
|
]}>
|
||||||
<EmojiReactionPicker message={message} onEmojiSelect={onEmojiSelect}>
|
<EmojiReactionPicker message={message} onEmojiSelect={onEmojiSelect}>
|
||||||
{({props, state, isNative, control}) => {
|
{({props, state, IS_NATIVE, control}) => {
|
||||||
// always false, file is platform split
|
// always false, file is platform split
|
||||||
if (isNative) return null
|
if (IS_NATIVE) return null
|
||||||
const showMenuTrigger = showActions || control.isOpen ? 1 : 0
|
const showMenuTrigger = showActions || control.isOpen ? 1 : 0
|
||||||
return (
|
return (
|
||||||
<Pressable
|
<Pressable
|
||||||
@@ -111,9 +111,9 @@ export function ActionsWrapper({
|
|||||||
}}
|
}}
|
||||||
</EmojiReactionPicker>
|
</EmojiReactionPicker>
|
||||||
<MessageContextMenu message={message}>
|
<MessageContextMenu message={message}>
|
||||||
{({props, state, isNative, control}) => {
|
{({props, state, IS_NATIVE, control}) => {
|
||||||
// always false, file is platform split
|
// always false, file is platform split
|
||||||
if (isNative) return null
|
if (IS_NATIVE) return null
|
||||||
const showMenuTrigger = showActions || control.isOpen ? 1 : 0
|
const showMenuTrigger = showActions || control.isOpen ? 1 : 0
|
||||||
return (
|
return (
|
||||||
<Pressable
|
<Pressable
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import {StackActions, useNavigation} from '@react-navigation/native'
|
|||||||
import type React from 'react'
|
import type React from 'react'
|
||||||
|
|
||||||
import {type NavigationProp} from '#/lib/routes/types'
|
import {type NavigationProp} from '#/lib/routes/types'
|
||||||
import {isNative} from '#/platform/detection'
|
|
||||||
import {useProfileShadow} from '#/state/cache/profile-shadow'
|
import {useProfileShadow} from '#/state/cache/profile-shadow'
|
||||||
import {useLeaveConvo} from '#/state/queries/messages/leave-conversation'
|
import {useLeaveConvo} from '#/state/queries/messages/leave-conversation'
|
||||||
import {
|
import {
|
||||||
@@ -21,6 +20,7 @@ import * as Dialog from '#/components/Dialog'
|
|||||||
import * as Toggle from '#/components/forms/Toggle'
|
import * as Toggle from '#/components/forms/Toggle'
|
||||||
import {Loader} from '#/components/Loader'
|
import {Loader} from '#/components/Loader'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_NATIVE} from '#/env'
|
||||||
|
|
||||||
type ReportDialogParams = {
|
type ReportDialogParams = {
|
||||||
convoId: string
|
convoId: string
|
||||||
@@ -130,7 +130,7 @@ function DoneStep({
|
|||||||
onMutate: () => {
|
onMutate: () => {
|
||||||
if (currentScreen === 'conversation') {
|
if (currentScreen === 'conversation') {
|
||||||
navigation.dispatch(
|
navigation.dispatch(
|
||||||
StackActions.replace('Messages', isNative ? {animation: 'pop'} : {}),
|
StackActions.replace('Messages', IS_NATIVE ? {animation: 'pop'} : {}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ import {useLingui} from '@lingui/react'
|
|||||||
import {ScaleAndFadeIn} from '#/lib/custom-animations/ScaleAndFade'
|
import {ScaleAndFadeIn} from '#/lib/custom-animations/ScaleAndFade'
|
||||||
import {ShrinkAndPop} from '#/lib/custom-animations/ShrinkAndPop'
|
import {ShrinkAndPop} from '#/lib/custom-animations/ShrinkAndPop'
|
||||||
import {useHaptics} from '#/lib/haptics'
|
import {useHaptics} from '#/lib/haptics'
|
||||||
import {isWeb} from '#/platform/detection'
|
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_WEB} from '#/env'
|
||||||
|
|
||||||
const AnimatedPressable = Animated.createAnimatedComponent(Pressable)
|
const AnimatedPressable = Animated.createAnimatedComponent(Pressable)
|
||||||
|
|
||||||
@@ -41,12 +41,12 @@ export function ChatEmptyPill() {
|
|||||||
}, [_])
|
}, [_])
|
||||||
|
|
||||||
const onPressIn = React.useCallback(() => {
|
const onPressIn = React.useCallback(() => {
|
||||||
if (isWeb) return
|
if (IS_WEB) return
|
||||||
scale.set(() => withTiming(1.075, {duration: 100}))
|
scale.set(() => withTiming(1.075, {duration: 100}))
|
||||||
}, [scale])
|
}, [scale])
|
||||||
|
|
||||||
const onPressOut = React.useCallback(() => {
|
const onPressOut = React.useCallback(() => {
|
||||||
if (isWeb) return
|
if (IS_WEB) return
|
||||||
scale.set(() => withTiming(1, {duration: 100}))
|
scale.set(() => withTiming(1, {duration: 100}))
|
||||||
}, [scale])
|
}, [scale])
|
||||||
|
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ import {useLingui} from '@lingui/react'
|
|||||||
import {StackActions, useNavigation} from '@react-navigation/native'
|
import {StackActions, useNavigation} from '@react-navigation/native'
|
||||||
|
|
||||||
import {type NavigationProp} from '#/lib/routes/types'
|
import {type NavigationProp} from '#/lib/routes/types'
|
||||||
import {isNative} from '#/platform/detection'
|
|
||||||
import {useLeaveConvo} from '#/state/queries/messages/leave-conversation'
|
import {useLeaveConvo} from '#/state/queries/messages/leave-conversation'
|
||||||
import * as Toast from '#/view/com/util/Toast'
|
import * as Toast from '#/view/com/util/Toast'
|
||||||
import {type DialogOuterProps} from '#/components/Dialog'
|
import {type DialogOuterProps} from '#/components/Dialog'
|
||||||
import * as Prompt from '#/components/Prompt'
|
import * as Prompt from '#/components/Prompt'
|
||||||
|
import {IS_NATIVE} from '#/env'
|
||||||
|
|
||||||
export function LeaveConvoPrompt({
|
export function LeaveConvoPrompt({
|
||||||
control,
|
control,
|
||||||
@@ -27,7 +27,7 @@ export function LeaveConvoPrompt({
|
|||||||
onMutate: () => {
|
onMutate: () => {
|
||||||
if (currentScreen === 'conversation') {
|
if (currentScreen === 'conversation') {
|
||||||
navigation.dispatch(
|
navigation.dispatch(
|
||||||
StackActions.replace('Messages', isNative ? {animation: 'pop'} : {}),
|
StackActions.replace('Messages', IS_NATIVE ? {animation: 'pop'} : {}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import {useLingui} from '@lingui/react'
|
|||||||
import {useTranslate} from '#/lib/hooks/useTranslate'
|
import {useTranslate} from '#/lib/hooks/useTranslate'
|
||||||
import {richTextToString} from '#/lib/strings/rich-text-helpers'
|
import {richTextToString} from '#/lib/strings/rich-text-helpers'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {isNative} from '#/platform/detection'
|
|
||||||
import {useConvoActive} from '#/state/messages/convo'
|
import {useConvoActive} from '#/state/messages/convo'
|
||||||
import {useLanguagePrefs} from '#/state/preferences'
|
import {useLanguagePrefs} from '#/state/preferences'
|
||||||
import {useSession} from '#/state/session'
|
import {useSession} from '#/state/session'
|
||||||
@@ -23,6 +22,7 @@ import {Warning_Stroke2_Corner0_Rounded as Warning} from '#/components/icons/War
|
|||||||
import {ReportDialog} from '#/components/moderation/ReportDialog'
|
import {ReportDialog} from '#/components/moderation/ReportDialog'
|
||||||
import * as Prompt from '#/components/Prompt'
|
import * as Prompt from '#/components/Prompt'
|
||||||
import {usePromptControl} from '#/components/Prompt'
|
import {usePromptControl} from '#/components/Prompt'
|
||||||
|
import {IS_NATIVE} from '#/env'
|
||||||
import {EmojiReactionPicker} from './EmojiReactionPicker'
|
import {EmojiReactionPicker} from './EmojiReactionPicker'
|
||||||
import {hasReachedReactionLimit} from './util'
|
import {hasReachedReactionLimit} from './util'
|
||||||
|
|
||||||
@@ -112,7 +112,7 @@ export let MessageContextMenu = ({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ContextMenu.Root>
|
<ContextMenu.Root>
|
||||||
{isNative && (
|
{IS_NATIVE && (
|
||||||
<ContextMenu.AuxiliaryView align={isFromSelf ? 'right' : 'left'}>
|
<ContextMenu.AuxiliaryView align={isFromSelf ? 'right' : 'left'}>
|
||||||
<EmojiReactionPicker
|
<EmojiReactionPicker
|
||||||
message={message}
|
message={message}
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import {msg} from '@lingui/macro'
|
|||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
import {sanitizeDisplayName} from '#/lib/strings/display-names'
|
import {sanitizeDisplayName} from '#/lib/strings/display-names'
|
||||||
import {isNative} from '#/platform/detection'
|
|
||||||
import {useConvoActive} from '#/state/messages/convo'
|
import {useConvoActive} from '#/state/messages/convo'
|
||||||
import {type ConvoItem} from '#/state/messages/convo/types'
|
import {type ConvoItem} from '#/state/messages/convo/types'
|
||||||
import {useSession} from '#/state/session'
|
import {useSession} from '#/state/session'
|
||||||
@@ -32,6 +31,7 @@ import {ActionsWrapper} from '#/components/dms/ActionsWrapper'
|
|||||||
import {InlineLinkText} from '#/components/Link'
|
import {InlineLinkText} from '#/components/Link'
|
||||||
import {RichText} from '#/components/RichText'
|
import {RichText} from '#/components/RichText'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_NATIVE} from '#/env'
|
||||||
import {DateDivider} from './DateDivider'
|
import {DateDivider} from './DateDivider'
|
||||||
import {MessageItemEmbed} from './MessageItemEmbed'
|
import {MessageItemEmbed} from './MessageItemEmbed'
|
||||||
import {localDateString} from './util'
|
import {localDateString} from './util'
|
||||||
@@ -218,10 +218,10 @@ let MessageItem = ({
|
|||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isNative && appliedReactions}
|
{IS_NATIVE && appliedReactions}
|
||||||
</ActionsWrapper>
|
</ActionsWrapper>
|
||||||
|
|
||||||
{!isNative && appliedReactions}
|
{!IS_NATIVE && appliedReactions}
|
||||||
|
|
||||||
{isLastInGroup && (
|
{isLastInGroup && (
|
||||||
<MessageItemMetadata
|
<MessageItemMetadata
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import {useLingui} from '@lingui/react'
|
|||||||
|
|
||||||
import {makeProfileLink} from '#/lib/routes/links'
|
import {makeProfileLink} from '#/lib/routes/links'
|
||||||
import {sanitizeDisplayName} from '#/lib/strings/display-names'
|
import {sanitizeDisplayName} from '#/lib/strings/display-names'
|
||||||
import {isWeb} from '#/platform/detection'
|
|
||||||
import {type Shadow} from '#/state/cache/profile-shadow'
|
import {type Shadow} from '#/state/cache/profile-shadow'
|
||||||
import {isConvoActive, useConvo} from '#/state/messages/convo'
|
import {isConvoActive, useConvo} from '#/state/messages/convo'
|
||||||
import {type ConvoItem} from '#/state/messages/convo/types'
|
import {type ConvoItem} from '#/state/messages/convo/types'
|
||||||
@@ -24,8 +23,9 @@ import {PostAlerts} from '#/components/moderation/PostAlerts'
|
|||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
import {useSimpleVerificationState} from '#/components/verification'
|
import {useSimpleVerificationState} from '#/components/verification'
|
||||||
import {VerificationCheck} from '#/components/verification/VerificationCheck'
|
import {VerificationCheck} from '#/components/verification/VerificationCheck'
|
||||||
|
import {IS_WEB} from '#/env'
|
||||||
|
|
||||||
const PFP_SIZE = isWeb ? 40 : Layout.HEADER_SLOT_SIZE
|
const PFP_SIZE = IS_WEB ? 40 : Layout.HEADER_SLOT_SIZE
|
||||||
|
|
||||||
export function MessagesListHeader({
|
export function MessagesListHeader({
|
||||||
profile,
|
profile,
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ import {
|
|||||||
ScaleAndFadeOut,
|
ScaleAndFadeOut,
|
||||||
} from '#/lib/custom-animations/ScaleAndFade'
|
} from '#/lib/custom-animations/ScaleAndFade'
|
||||||
import {useHaptics} from '#/lib/haptics'
|
import {useHaptics} from '#/lib/haptics'
|
||||||
import {isAndroid, isIOS, isWeb} from '#/platform/detection'
|
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_ANDROID, IS_IOS, IS_WEB} from '#/env'
|
||||||
|
|
||||||
const AnimatedPressable = Animated.createAnimatedComponent(Pressable)
|
const AnimatedPressable = Animated.createAnimatedComponent(Pressable)
|
||||||
|
|
||||||
@@ -28,18 +28,18 @@ export function NewMessagesPill({
|
|||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const playHaptic = useHaptics()
|
const playHaptic = useHaptics()
|
||||||
const {bottom: bottomInset} = useSafeAreaInsets()
|
const {bottom: bottomInset} = useSafeAreaInsets()
|
||||||
const bottomBarHeight = isIOS ? 42 : isAndroid ? 60 : 0
|
const bottomBarHeight = IS_IOS ? 42 : IS_ANDROID ? 60 : 0
|
||||||
const bottomOffset = isWeb ? 0 : bottomInset + bottomBarHeight
|
const bottomOffset = IS_WEB ? 0 : bottomInset + bottomBarHeight
|
||||||
|
|
||||||
const scale = useSharedValue(1)
|
const scale = useSharedValue(1)
|
||||||
|
|
||||||
const onPressIn = React.useCallback(() => {
|
const onPressIn = React.useCallback(() => {
|
||||||
if (isWeb) return
|
if (IS_WEB) return
|
||||||
scale.set(() => withTiming(1.075, {duration: 100}))
|
scale.set(() => withTiming(1.075, {duration: 100}))
|
||||||
}, [scale])
|
}, [scale])
|
||||||
|
|
||||||
const onPressOut = React.useCallback(() => {
|
const onPressOut = React.useCallback(() => {
|
||||||
if (isWeb) return
|
if (IS_WEB) return
|
||||||
scale.set(() => withTiming(1, {duration: 100}))
|
scale.set(() => withTiming(1, {duration: 100}))
|
||||||
}, [scale])
|
}, [scale])
|
||||||
|
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ import {msg} from '@lingui/macro'
|
|||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
import {HITSLOP_10} from '#/lib/constants'
|
import {HITSLOP_10} from '#/lib/constants'
|
||||||
import {isNative} from '#/platform/detection'
|
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
import {Button, ButtonIcon} from '#/components/Button'
|
import {Button, ButtonIcon} from '#/components/Button'
|
||||||
import * as TextField from '#/components/forms/TextField'
|
import * as TextField from '#/components/forms/TextField'
|
||||||
import {MagnifyingGlass_Stroke2_Corner0_Rounded as MagnifyingGlassIcon} from '#/components/icons/MagnifyingGlass'
|
import {MagnifyingGlass_Stroke2_Corner0_Rounded as MagnifyingGlassIcon} from '#/components/icons/MagnifyingGlass'
|
||||||
import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times'
|
import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times'
|
||||||
|
import {IS_NATIVE} from '#/env'
|
||||||
|
|
||||||
type SearchInputProps = Omit<TextField.InputProps, 'label'> & {
|
type SearchInputProps = Omit<TextField.InputProps, 'label'> & {
|
||||||
label?: TextField.InputProps['label']
|
label?: TextField.InputProps['label']
|
||||||
@@ -36,7 +36,7 @@ export const SearchInput = React.forwardRef<TextInput, SearchInputProps>(
|
|||||||
placeholder={_(msg`Search`)}
|
placeholder={_(msg`Search`)}
|
||||||
returnKeyType="search"
|
returnKeyType="search"
|
||||||
keyboardAppearance={t.scheme}
|
keyboardAppearance={t.scheme}
|
||||||
selectTextOnFocus={isNative}
|
selectTextOnFocus={IS_NATIVE}
|
||||||
autoFocus={false}
|
autoFocus={false}
|
||||||
accessibilityRole="search"
|
accessibilityRole="search"
|
||||||
autoCorrect={false}
|
autoCorrect={false}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import Animated, {Easing, LinearTransition} from 'react-native-reanimated'
|
|||||||
|
|
||||||
import {HITSLOP_10} from '#/lib/constants'
|
import {HITSLOP_10} from '#/lib/constants'
|
||||||
import {useHaptics} from '#/lib/haptics'
|
import {useHaptics} from '#/lib/haptics'
|
||||||
import {isNative} from '#/platform/detection'
|
|
||||||
import {
|
import {
|
||||||
atoms as a,
|
atoms as a,
|
||||||
native,
|
native,
|
||||||
@@ -22,6 +21,7 @@ import {
|
|||||||
import {useInteractionState} from '#/components/hooks/useInteractionState'
|
import {useInteractionState} from '#/components/hooks/useInteractionState'
|
||||||
import {CheckThick_Stroke2_Corner0_Rounded as Checkmark} from '#/components/icons/Check'
|
import {CheckThick_Stroke2_Corner0_Rounded as Checkmark} from '#/components/icons/Check'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_NATIVE} from '#/env'
|
||||||
|
|
||||||
export * from './Panel'
|
export * from './Panel'
|
||||||
|
|
||||||
@@ -562,4 +562,4 @@ export function BaseRadio({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Platform = isNative ? Switch : Checkbox
|
export const Platform = IS_NATIVE ? Switch : Checkbox
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
} from 'react'
|
} from 'react'
|
||||||
|
|
||||||
import {isFirefox, isSafari} from '#/lib/browser'
|
import {isFirefox, isSafari} from '#/lib/browser'
|
||||||
import {isWeb} from '#/platform/detection'
|
import {IS_WEB} from '#/env'
|
||||||
|
|
||||||
function fullscreenSubscribe(onChange: () => void) {
|
function fullscreenSubscribe(onChange: () => void) {
|
||||||
document.addEventListener('fullscreenchange', onChange)
|
document.addEventListener('fullscreenchange', onChange)
|
||||||
@@ -15,7 +15,7 @@ function fullscreenSubscribe(onChange: () => void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function useFullscreen(ref?: React.RefObject<HTMLElement | null>) {
|
export function useFullscreen(ref?: React.RefObject<HTMLElement | null>) {
|
||||||
if (!isWeb) throw new Error("'useFullscreen' is a web-only hook")
|
if (!IS_WEB) throw new Error("'useFullscreen' is a web-only hook")
|
||||||
const isFullscreen = useSyncExternalStore(fullscreenSubscribe, () =>
|
const isFullscreen = useSyncExternalStore(fullscreenSubscribe, () =>
|
||||||
Boolean(document.fullscreenElement),
|
Boolean(document.fullscreenElement),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import {
|
|||||||
createStarterPackLinkFromAndroidReferrer,
|
createStarterPackLinkFromAndroidReferrer,
|
||||||
httpStarterPackUriToAtUri,
|
httpStarterPackUriToAtUri,
|
||||||
} from '#/lib/strings/starter-pack'
|
} from '#/lib/strings/starter-pack'
|
||||||
import {isAndroid} from '#/platform/detection'
|
|
||||||
import {useHasCheckedForStarterPack} from '#/state/preferences/used-starter-packs'
|
import {useHasCheckedForStarterPack} from '#/state/preferences/used-starter-packs'
|
||||||
import {useSetActiveStarterPack} from '#/state/shell/starter-pack'
|
import {useSetActiveStarterPack} from '#/state/shell/starter-pack'
|
||||||
|
import {IS_ANDROID} from '#/env'
|
||||||
import {Referrer, SharedPrefs} from '../../../modules/expo-bluesky-swiss-army'
|
import {Referrer, SharedPrefs} from '../../../modules/expo-bluesky-swiss-army'
|
||||||
|
|
||||||
export function useStarterPackEntry() {
|
export function useStarterPackEntry() {
|
||||||
@@ -32,7 +32,7 @@ export function useStarterPackEntry() {
|
|||||||
;(async () => {
|
;(async () => {
|
||||||
let uri: string | null | undefined
|
let uri: string | null | undefined
|
||||||
|
|
||||||
if (isAndroid) {
|
if (IS_ANDROID) {
|
||||||
const res = await Referrer.getGooglePlayReferrerInfoAsync()
|
const res = await Referrer.getGooglePlayReferrerInfoAsync()
|
||||||
|
|
||||||
if (res && res.installReferrer) {
|
if (res && res.installReferrer) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import {useEffect, useState} from 'react'
|
import {useEffect, useState} from 'react'
|
||||||
|
|
||||||
import {isWeb} from '#/platform/detection'
|
|
||||||
import {useSession} from '#/state/session'
|
import {useSession} from '#/state/session'
|
||||||
|
import {IS_WEB} from '#/env'
|
||||||
|
|
||||||
export function useWelcomeModal() {
|
export function useWelcomeModal() {
|
||||||
const {hasSession} = useSession()
|
const {hasSession} = useSession()
|
||||||
@@ -22,7 +22,7 @@ export function useWelcomeModal() {
|
|||||||
// 2. We're on the web (this is a web-only feature)
|
// 2. We're on the web (this is a web-only feature)
|
||||||
// 3. We're on the homepage (path is '/' or '/home')
|
// 3. We're on the homepage (path is '/' or '/home')
|
||||||
// 4. User hasn't actively closed the modal in this session
|
// 4. User hasn't actively closed the modal in this session
|
||||||
if (isWeb && !hasSession && typeof window !== 'undefined') {
|
if (IS_WEB && !hasSession && typeof window !== 'undefined') {
|
||||||
const currentPath = window.location.pathname
|
const currentPath = window.location.pathname
|
||||||
const isHomePage = currentPath === '/'
|
const isHomePage = currentPath === '/'
|
||||||
const hasUserClosedModal =
|
const hasUserClosedModal =
|
||||||
|
|||||||
@@ -11,12 +11,12 @@ import {msg} from '@lingui/macro'
|
|||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
import {type Dimensions} from '#/lib/media/types'
|
import {type Dimensions} from '#/lib/media/types'
|
||||||
import {isNative} from '#/platform/detection'
|
|
||||||
import {useLargeAltBadgeEnabled} from '#/state/preferences/large-alt-badge'
|
import {useLargeAltBadgeEnabled} from '#/state/preferences/large-alt-badge'
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
import {ArrowsDiagonalOut_Stroke2_Corner0_Rounded as Fullscreen} from '#/components/icons/ArrowsDiagonal'
|
import {ArrowsDiagonalOut_Stroke2_Corner0_Rounded as Fullscreen} from '#/components/icons/ArrowsDiagonal'
|
||||||
import {MediaInsetBorder} from '#/components/MediaInsetBorder'
|
import {MediaInsetBorder} from '#/components/MediaInsetBorder'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_NATIVE} from '#/env'
|
||||||
|
|
||||||
export function ConstrainedImage({
|
export function ConstrainedImage({
|
||||||
aspectRatio,
|
aspectRatio,
|
||||||
@@ -35,7 +35,7 @@ export function ConstrainedImage({
|
|||||||
* the height of the image.
|
* the height of the image.
|
||||||
*/
|
*/
|
||||||
const outerAspectRatio = useMemo<DimensionValue>(() => {
|
const outerAspectRatio = useMemo<DimensionValue>(() => {
|
||||||
const ratio = isNative
|
const ratio = IS_NATIVE
|
||||||
? Math.min(1 / aspectRatio, minMobileAspectRatio ?? 16 / 9) // 9:16 bounding box
|
? Math.min(1 / aspectRatio, minMobileAspectRatio ?? 16 / 9) // 9:16 bounding box
|
||||||
: Math.min(1 / aspectRatio, 1) // 1:1 bounding box
|
: Math.min(1 / aspectRatio, 1) // 1:1 bounding box
|
||||||
return `${ratio * 100}%`
|
return `${ratio * 100}%`
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import {View} from 'react-native'
|
|||||||
import {msg, Trans} from '@lingui/macro'
|
import {msg, Trans} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
import {isNative} from '#/platform/detection'
|
|
||||||
import {useAgent, useSession} from '#/state/session'
|
import {useAgent, useSession} from '#/state/session'
|
||||||
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
|
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
|
||||||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||||||
@@ -15,6 +14,7 @@ import {ArrowRotateCounterClockwise_Stroke2_Corner0_Rounded as Resend} from '#/c
|
|||||||
import {useIntentDialogs} from '#/components/intents/IntentDialogs'
|
import {useIntentDialogs} from '#/components/intents/IntentDialogs'
|
||||||
import {Loader} from '#/components/Loader'
|
import {Loader} from '#/components/Loader'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_NATIVE} from '#/env'
|
||||||
|
|
||||||
export function VerifyEmailIntentDialog() {
|
export function VerifyEmailIntentDialog() {
|
||||||
const {verifyEmailDialogControl: control} = useIntentDialogs()
|
const {verifyEmailDialogControl: control} = useIntentDialogs()
|
||||||
@@ -68,7 +68,7 @@ function Inner({}: {control: DialogControlProps}) {
|
|||||||
<Loader size="xl" fill={t.atoms.text_contrast_low.color} />
|
<Loader size="xl" fill={t.atoms.text_contrast_low.color} />
|
||||||
</View>
|
</View>
|
||||||
) : status === 'success' ? (
|
) : status === 'success' ? (
|
||||||
<View style={[a.gap_sm, isNative && a.pb_xl]}>
|
<View style={[a.gap_sm, IS_NATIVE && a.pb_xl]}>
|
||||||
<Text style={[a.font_bold, a.text_2xl]}>
|
<Text style={[a.font_bold, a.text_2xl]}>
|
||||||
<Trans>Email Verified</Trans>
|
<Trans>Email Verified</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
@@ -93,7 +93,7 @@ function Inner({}: {control: DialogControlProps}) {
|
|||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
) : (
|
) : (
|
||||||
<View style={[a.gap_sm, isNative && a.pb_xl]}>
|
<View style={[a.gap_sm, IS_NATIVE && a.pb_xl]}>
|
||||||
<Text style={[a.font_bold, a.text_2xl]}>
|
<Text style={[a.font_bold, a.text_2xl]}>
|
||||||
<Trans>Email Resent</Trans>
|
<Trans>Email Resent</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import {useLabelInfo} from '#/lib/moderation/useLabelInfo'
|
|||||||
import {makeProfileLink} from '#/lib/routes/links'
|
import {makeProfileLink} from '#/lib/routes/links'
|
||||||
import {sanitizeHandle} from '#/lib/strings/handles'
|
import {sanitizeHandle} from '#/lib/strings/handles'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {isAndroid} from '#/platform/detection'
|
|
||||||
import {useAgent, useSession} from '#/state/session'
|
import {useAgent, useSession} from '#/state/session'
|
||||||
import * as Toast from '#/view/com/util/Toast'
|
import * as Toast from '#/view/com/util/Toast'
|
||||||
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
|
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
|
||||||
@@ -20,6 +19,7 @@ import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
|||||||
import * as Dialog from '#/components/Dialog'
|
import * as Dialog from '#/components/Dialog'
|
||||||
import {InlineLinkText} from '#/components/Link'
|
import {InlineLinkText} from '#/components/Link'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_ANDROID} from '#/env'
|
||||||
import {Admonition} from '../Admonition'
|
import {Admonition} from '../Admonition'
|
||||||
import {Divider} from '../Divider'
|
import {Divider} from '../Divider'
|
||||||
import {Loader} from '../Loader'
|
import {Loader} from '../Loader'
|
||||||
@@ -344,7 +344,7 @@ function AppealForm({
|
|||||||
{isPending && <ButtonIcon icon={Loader} />}
|
{isPending && <ButtonIcon icon={Loader} />}
|
||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
{isAndroid && <View style={{height: 300}} />}
|
{IS_ANDROID && <View style={{height: 300}} />}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ import {useGetTimeAgo} from '#/lib/hooks/useTimeAgo'
|
|||||||
import {useModerationCauseDescription} from '#/lib/moderation/useModerationCauseDescription'
|
import {useModerationCauseDescription} from '#/lib/moderation/useModerationCauseDescription'
|
||||||
import {makeProfileLink} from '#/lib/routes/links'
|
import {makeProfileLink} from '#/lib/routes/links'
|
||||||
import {listUriToHref} from '#/lib/strings/url-helpers'
|
import {listUriToHref} from '#/lib/strings/url-helpers'
|
||||||
import {isNative} from '#/platform/detection'
|
|
||||||
import {useSession} from '#/state/session'
|
import {useSession} from '#/state/session'
|
||||||
import {atoms as a, useGutters, useTheme} from '#/alf'
|
import {atoms as a, useGutters, useTheme} from '#/alf'
|
||||||
import * as Dialog from '#/components/Dialog'
|
import * as Dialog from '#/components/Dialog'
|
||||||
import {InlineLinkText} from '#/components/Link'
|
import {InlineLinkText} from '#/components/Link'
|
||||||
import {type AppModerationCause} from '#/components/Pills'
|
import {type AppModerationCause} from '#/components/Pills'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_NATIVE} from '#/env'
|
||||||
|
|
||||||
export {useDialogControl as useModerationDetailsDialogControl} from '#/components/Dialog'
|
export {useDialogControl as useModerationDetailsDialogControl} from '#/components/Dialog'
|
||||||
|
|
||||||
@@ -158,7 +158,7 @@ function ModerationDetailsDialogInner({
|
|||||||
xGutters,
|
xGutters,
|
||||||
a.py_md,
|
a.py_md,
|
||||||
a.border_t,
|
a.border_t,
|
||||||
!isNative && t.atoms.bg_contrast_25,
|
!IS_NATIVE && t.atoms.bg_contrast_25,
|
||||||
t.atoms.border_contrast_low,
|
t.atoms.border_contrast_low,
|
||||||
{
|
{
|
||||||
borderBottomLeftRadius: a.rounded_md.borderRadius,
|
borderBottomLeftRadius: a.rounded_md.borderRadius,
|
||||||
@@ -219,7 +219,7 @@ function ModerationDetailsDialogInner({
|
|||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isNative && <View style={{height: 40}} />}
|
{IS_NATIVE && <View style={{height: 40}} />}
|
||||||
|
|
||||||
<Dialog.Close />
|
<Dialog.Close />
|
||||||
</Dialog.ScrollableInner>
|
</Dialog.ScrollableInner>
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import {wait} from '#/lib/async/wait'
|
|||||||
import {getLabelingServiceTitle} from '#/lib/moderation'
|
import {getLabelingServiceTitle} from '#/lib/moderation'
|
||||||
import {sanitizeHandle} from '#/lib/strings/handles'
|
import {sanitizeHandle} from '#/lib/strings/handles'
|
||||||
import {Logger} from '#/logger'
|
import {Logger} from '#/logger'
|
||||||
import {isNative} from '#/platform/detection'
|
|
||||||
import {useMyLabelersQuery} from '#/state/queries/preferences'
|
import {useMyLabelersQuery} from '#/state/queries/preferences'
|
||||||
import {CharProgress} from '#/view/com/composer/char-progress/CharProgress'
|
import {CharProgress} from '#/view/com/composer/char-progress/CharProgress'
|
||||||
import {UserAvatar} from '#/view/com/util/UserAvatar'
|
import {UserAvatar} from '#/view/com/util/UserAvatar'
|
||||||
@@ -29,6 +28,7 @@ import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times'
|
|||||||
import {createStaticClick, InlineLinkText, Link} from '#/components/Link'
|
import {createStaticClick, InlineLinkText, Link} from '#/components/Link'
|
||||||
import {Loader} from '#/components/Loader'
|
import {Loader} from '#/components/Loader'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {IS_NATIVE} from '#/env'
|
||||||
import {useSubmitReportMutation} from './action'
|
import {useSubmitReportMutation} from './action'
|
||||||
import {
|
import {
|
||||||
BSKY_LABELER_ONLY_REPORT_REASONS,
|
BSKY_LABELER_ONLY_REPORT_REASONS,
|
||||||
@@ -253,7 +253,7 @@ function Inner(props: ReportDialogProps) {
|
|||||||
label={_(msg`Report dialog`)}
|
label={_(msg`Report dialog`)}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
style={[a.w_full, {maxWidth: 500}]}>
|
style={[a.w_full, {maxWidth: 500}]}>
|
||||||
<View style={[a.gap_2xl, isNative && a.pt_md]}>
|
<View style={[a.gap_2xl, IS_NATIVE && a.pt_md]}>
|
||||||
<StepOuter>
|
<StepOuter>
|
||||||
<StepTitle
|
<StepTitle
|
||||||
index={1}
|
index={1}
|
||||||
|
|||||||
Vendored
+11
@@ -1,3 +1,4 @@
|
|||||||
|
import {Platform} from 'react-native'
|
||||||
import {nativeBuildVersion} from 'expo-application'
|
import {nativeBuildVersion} from 'expo-application'
|
||||||
|
|
||||||
import {BUNDLE_IDENTIFIER, IS_TESTFLIGHT, RELEASE_VERSION} from '#/env/common'
|
import {BUNDLE_IDENTIFIER, IS_TESTFLIGHT, RELEASE_VERSION} from '#/env/common'
|
||||||
@@ -17,3 +18,13 @@ export const APP_VERSION = `${RELEASE_VERSION}.${nativeBuildVersion}`
|
|||||||
export const APP_METADATA = `${BUNDLE_IDENTIFIER.slice(0, 7)} (${
|
export const APP_METADATA = `${BUNDLE_IDENTIFIER.slice(0, 7)} (${
|
||||||
__DEV__ ? 'dev' : IS_TESTFLIGHT ? 'tf' : 'prod'
|
__DEV__ ? 'dev' : IS_TESTFLIGHT ? 'tf' : 'prod'
|
||||||
})`
|
})`
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Platform detection
|
||||||
|
*/
|
||||||
|
export const IS_IOS: boolean = Platform.OS === 'ios'
|
||||||
|
export const IS_ANDROID: boolean = Platform.OS === 'android'
|
||||||
|
export const IS_NATIVE: boolean = true
|
||||||
|
export const IS_WEB: boolean = false
|
||||||
|
export const IS_WEB_MOBILE: boolean = false
|
||||||
|
export const IS_WEB_MOBILE_IOS: boolean = false
|
||||||
|
|||||||
Vendored
+13
@@ -13,3 +13,16 @@ export const APP_VERSION = RELEASE_VERSION
|
|||||||
* The short commit hash and environment of the current bundle.
|
* The short commit hash and environment of the current bundle.
|
||||||
*/
|
*/
|
||||||
export const APP_METADATA = `${BUNDLE_IDENTIFIER.slice(0, 7)} (${__DEV__ ? 'dev' : 'prod'})`
|
export const APP_METADATA = `${BUNDLE_IDENTIFIER.slice(0, 7)} (${__DEV__ ? 'dev' : 'prod'})`
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Platform detection
|
||||||
|
*/
|
||||||
|
export const IS_IOS: boolean = false
|
||||||
|
export const IS_ANDROID: boolean = false
|
||||||
|
export const IS_NATIVE: boolean = false
|
||||||
|
export const IS_WEB: boolean = true
|
||||||
|
// @ts-ignore we know window exists -prf
|
||||||
|
export const IS_WEB_MOBILE: boolean = global.window.matchMedia(
|
||||||
|
'only screen and (max-width: 1300px)',
|
||||||
|
)?.matches
|
||||||
|
export const IS_WEB_MOBILE_IOS: boolean = /iPhone/.test(navigator.userAgent)
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import {msg, Trans} from '@lingui/macro'
|
|||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
import {useCleanError} from '#/lib/hooks/useCleanError'
|
import {useCleanError} from '#/lib/hooks/useCleanError'
|
||||||
import {isNative} from '#/platform/detection'
|
|
||||||
import {atoms as a, web} from '#/alf'
|
import {atoms as a, web} from '#/alf'
|
||||||
import {Admonition} from '#/components/Admonition'
|
import {Admonition} from '#/components/Admonition'
|
||||||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||||||
@@ -11,6 +10,7 @@ import * as Dialog from '#/components/Dialog'
|
|||||||
import {Loader} from '#/components/Loader'
|
import {Loader} from '#/components/Loader'
|
||||||
import * as Toast from '#/components/Toast'
|
import * as Toast from '#/components/Toast'
|
||||||
import {Span, Text} from '#/components/Typography'
|
import {Span, Text} from '#/components/Typography'
|
||||||
|
import {IS_NATIVE} from '#/env'
|
||||||
import {useUpdateLiveEventPreferences} from '#/features/liveEvents/preferences'
|
import {useUpdateLiveEventPreferences} from '#/features/liveEvents/preferences'
|
||||||
import {
|
import {
|
||||||
type LiveEventFeed,
|
type LiveEventFeed,
|
||||||
@@ -146,7 +146,7 @@ function Inner({
|
|||||||
</ButtonText>
|
</ButtonText>
|
||||||
{isHidingAllFeeds && <ButtonIcon icon={Loader} />}
|
{isHidingAllFeeds && <ButtonIcon icon={Loader} />}
|
||||||
</Button>
|
</Button>
|
||||||
{isNative && (
|
{IS_NATIVE && (
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Cancel`)}
|
label={_(msg`Cancel`)}
|
||||||
size="large"
|
size="large"
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ import {type Agent, AppBskyActorDefs, asPredicate} from '@atproto/api'
|
|||||||
import {useMutation, useQueryClient} from '@tanstack/react-query'
|
import {useMutation, useQueryClient} from '@tanstack/react-query'
|
||||||
|
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {isWeb} from '#/platform/detection'
|
|
||||||
import {
|
import {
|
||||||
preferencesQueryKey,
|
preferencesQueryKey,
|
||||||
usePreferencesQuery,
|
usePreferencesQuery,
|
||||||
} from '#/state/queries/preferences'
|
} from '#/state/queries/preferences'
|
||||||
import {useAgent} from '#/state/session'
|
import {useAgent} from '#/state/session'
|
||||||
|
import {IS_WEB} from '#/env'
|
||||||
import * as env from '#/env'
|
import * as env from '#/env'
|
||||||
import {
|
import {
|
||||||
type LiveEventFeed,
|
type LiveEventFeed,
|
||||||
@@ -41,7 +41,7 @@ function useWebOnlyDebugLiveEventPreferences() {
|
|||||||
const agent = useAgent()
|
const agent = useAgent()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (env.IS_DEV && isWeb && typeof window !== 'undefined') {
|
if (env.IS_DEV && IS_WEB && typeof window !== 'undefined') {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
window.__updateLiveEventPreferences = async (
|
window.__updateLiveEventPreferences = async (
|
||||||
action: LiveEventPreferencesAction,
|
action: LiveEventPreferencesAction,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {Platform} from 'react-native'
|
|||||||
import * as Location from 'expo-location'
|
import * as Location from 'expo-location'
|
||||||
import {createPermissionHook} from 'expo-modules-core'
|
import {createPermissionHook} from 'expo-modules-core'
|
||||||
|
|
||||||
import {isNative} from '#/platform/detection'
|
import {IS_NATIVE} from '#/env'
|
||||||
import * as debug from '#/geolocation/debug'
|
import * as debug from '#/geolocation/debug'
|
||||||
import {logger} from '#/geolocation/logger'
|
import {logger} from '#/geolocation/logger'
|
||||||
import {type Geolocation} from '#/geolocation/types'
|
import {type Geolocation} from '#/geolocation/types'
|
||||||
@@ -118,7 +118,7 @@ export function useSyncDeviceGeolocationOnStartup(
|
|||||||
const synced = useRef(false)
|
const synced = useRef(false)
|
||||||
const [status] = useForegroundPermissions()
|
const [status] = useForegroundPermissions()
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isNative) return
|
if (!IS_NATIVE) return
|
||||||
|
|
||||||
async function get() {
|
async function get() {
|
||||||
// no need to set this more than once per session
|
// no need to set this more than once per session
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import {type LocationGeocodedAddress} from 'expo-location'
|
import {type LocationGeocodedAddress} from 'expo-location'
|
||||||
|
|
||||||
import {isAndroid} from '#/platform/detection'
|
import {IS_ANDROID} from '#/env'
|
||||||
import {logger} from '#/geolocation/logger'
|
import {logger} from '#/geolocation/logger'
|
||||||
import {type Geolocation} from '#/geolocation/types'
|
import {type Geolocation} from '#/geolocation/types'
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ export function normalizeDeviceLocation(
|
|||||||
/*
|
/*
|
||||||
* Android doesn't give us ISO 3166-2 short codes. We need these for US
|
* Android doesn't give us ISO 3166-2 short codes. We need these for US
|
||||||
*/
|
*/
|
||||||
if (isAndroid) {
|
if (IS_ANDROID) {
|
||||||
if (region && isoCountryCode === 'US') {
|
if (region && isoCountryCode === 'US') {
|
||||||
/*
|
/*
|
||||||
* We need short codes for US states. If we can't remap it, just drop it
|
* We need short codes for US states. If we can't remap it, just drop it
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user