Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 13ec071aab | |||
| b507b22d9e | |||
| 90455c0c6f | |||
| 846c730d49 | |||
| 490bfceded | |||
| a9322c8457 | |||
| a5b7b6f12f | |||
| 2c32e775df | |||
| cad7db56cf | |||
| 2e260be80c | |||
| 571d16e8cf | |||
| 134c7b7427 | |||
| e11f52ad96 | |||
| eb59bd3d9c | |||
| 017a26164b | |||
| 0e0110aa13 | |||
| 4625c0bda1 | |||
| 14047b78f6 | |||
| 0eabdfe2b4 | |||
| c999ff38f9 | |||
| 1045b09592 |
+5
-5
@@ -94,10 +94,10 @@
|
||||
"@react-native-async-storage/async-storage": "2.1.2",
|
||||
"@react-native-menu/menu": "^1.2.3",
|
||||
"@react-native-picker/picker": "2.11.0",
|
||||
"@react-navigation/bottom-tabs": "^6.5.20",
|
||||
"@react-navigation/drawer": "^6.6.15",
|
||||
"@react-navigation/native": "^6.1.17",
|
||||
"@react-navigation/native-stack": "^6.9.26",
|
||||
"@react-navigation/bottom-tabs": "^7.3.13",
|
||||
"@react-navigation/drawer": "^7.3.12",
|
||||
"@react-navigation/native": "^7.1.9",
|
||||
"@react-navigation/native-stack": "^7.3.13",
|
||||
"@sentry/react-native": "~6.10.0",
|
||||
"@tanstack/query-async-storage-persister": "^5.25.0",
|
||||
"@tanstack/react-query": "^5.8.1",
|
||||
@@ -198,7 +198,7 @@
|
||||
"react-native-reanimated": "~3.17.5",
|
||||
"react-native-root-siblings": "^4.1.1",
|
||||
"react-native-safe-area-context": "5.4.0",
|
||||
"react-native-screens": "~4.10.0",
|
||||
"react-native-screens": "^4.11.1",
|
||||
"react-native-svg": "15.11.2",
|
||||
"react-native-uitextview": "^1.4.0",
|
||||
"react-native-url-polyfill": "^1.3.0",
|
||||
|
||||
+42
-62
@@ -103,7 +103,7 @@ import {
|
||||
import {Wizard} from '#/screens/StarterPack/Wizard'
|
||||
import TopicScreen from '#/screens/Topic'
|
||||
import {VideoFeed} from '#/screens/VideoFeed'
|
||||
import {useTheme} from '#/alf'
|
||||
import {type Theme, useTheme} from '#/alf'
|
||||
import {
|
||||
EmailDialogScreenID,
|
||||
useEmailDialogControl,
|
||||
@@ -127,7 +127,7 @@ const Tab = createBottomTabNavigator<BottomTabNavigatorParams>()
|
||||
/**
|
||||
* These "common screens" are reused across stacks.
|
||||
*/
|
||||
function commonScreens(Stack: typeof HomeTab, unreadCountLabel?: string) {
|
||||
function commonScreens(Stack: typeof Flat, unreadCountLabel?: string) {
|
||||
const title = (page: MessageDescriptor) =>
|
||||
bskyTitle(i18n._(page), unreadCountLabel)
|
||||
|
||||
@@ -499,6 +499,10 @@ function TabsNavigator() {
|
||||
tabBar={tabBar}>
|
||||
<Tab.Screen name="HomeTab" getComponent={() => HomeTabNavigator} />
|
||||
<Tab.Screen name="SearchTab" getComponent={() => SearchTabNavigator} />
|
||||
<Tab.Screen
|
||||
name="MessagesTab"
|
||||
getComponent={() => MessagesTabNavigator}
|
||||
/>
|
||||
<Tab.Screen
|
||||
name="NotificationsTab"
|
||||
getComponent={() => NotificationsTabNavigator}
|
||||
@@ -507,29 +511,26 @@ function TabsNavigator() {
|
||||
name="MyProfileTab"
|
||||
getComponent={() => MyProfileTabNavigator}
|
||||
/>
|
||||
<Tab.Screen
|
||||
name="MessagesTab"
|
||||
getComponent={() => MessagesTabNavigator}
|
||||
/>
|
||||
</Tab.Navigator>
|
||||
)
|
||||
}
|
||||
|
||||
function screenOptions(t: Theme) {
|
||||
return {
|
||||
fullScreenGestureEnabled: true,
|
||||
headerShown: false,
|
||||
contentStyle: t.atoms.bg,
|
||||
} as const
|
||||
}
|
||||
|
||||
function HomeTabNavigator() {
|
||||
const t = useTheme()
|
||||
|
||||
return (
|
||||
<HomeTab.Navigator
|
||||
screenOptions={{
|
||||
animationDuration: 285,
|
||||
gestureEnabled: true,
|
||||
fullScreenGestureEnabled: true,
|
||||
headerShown: false,
|
||||
contentStyle: t.atoms.bg,
|
||||
}}>
|
||||
<HomeTab.Navigator screenOptions={screenOptions(t)} initialRouteName="Home">
|
||||
<HomeTab.Screen name="Home" getComponent={() => HomeScreen} />
|
||||
<HomeTab.Screen name="Start" getComponent={() => HomeScreen} />
|
||||
{commonScreens(HomeTab)}
|
||||
{commonScreens(HomeTab as typeof Flat)}
|
||||
</HomeTab.Navigator>
|
||||
)
|
||||
}
|
||||
@@ -538,15 +539,10 @@ function SearchTabNavigator() {
|
||||
const t = useTheme()
|
||||
return (
|
||||
<SearchTab.Navigator
|
||||
screenOptions={{
|
||||
animationDuration: 285,
|
||||
gestureEnabled: true,
|
||||
fullScreenGestureEnabled: true,
|
||||
headerShown: false,
|
||||
contentStyle: t.atoms.bg,
|
||||
}}>
|
||||
screenOptions={screenOptions(t)}
|
||||
initialRouteName="Search">
|
||||
<SearchTab.Screen name="Search" getComponent={() => SearchScreen} />
|
||||
{commonScreens(SearchTab as typeof HomeTab)}
|
||||
{commonScreens(SearchTab as typeof Flat)}
|
||||
</SearchTab.Navigator>
|
||||
)
|
||||
}
|
||||
@@ -555,19 +551,14 @@ function NotificationsTabNavigator() {
|
||||
const t = useTheme()
|
||||
return (
|
||||
<NotificationsTab.Navigator
|
||||
screenOptions={{
|
||||
animationDuration: 285,
|
||||
gestureEnabled: true,
|
||||
fullScreenGestureEnabled: true,
|
||||
headerShown: false,
|
||||
contentStyle: t.atoms.bg,
|
||||
}}>
|
||||
screenOptions={screenOptions(t)}
|
||||
initialRouteName="Notifications">
|
||||
<NotificationsTab.Screen
|
||||
name="Notifications"
|
||||
getComponent={() => NotificationsScreen}
|
||||
options={{requireAuth: true}}
|
||||
/>
|
||||
{commonScreens(NotificationsTab as typeof HomeTab)}
|
||||
{commonScreens(NotificationsTab as typeof Flat)}
|
||||
</NotificationsTab.Navigator>
|
||||
)
|
||||
}
|
||||
@@ -576,23 +567,16 @@ function MyProfileTabNavigator() {
|
||||
const t = useTheme()
|
||||
return (
|
||||
<MyProfileTab.Navigator
|
||||
screenOptions={{
|
||||
animationDuration: 285,
|
||||
gestureEnabled: true,
|
||||
fullScreenGestureEnabled: true,
|
||||
headerShown: false,
|
||||
contentStyle: t.atoms.bg,
|
||||
}}>
|
||||
screenOptions={screenOptions(t)}
|
||||
initialRouteName="MyProfile">
|
||||
<MyProfileTab.Screen
|
||||
// @ts-ignore // TODO: fix this broken type in ProfileScreen
|
||||
name="MyProfile"
|
||||
// MyProfile is not in AllNavigationParams - asserting as Profile at least
|
||||
// gives us typechecking for initialParams -sfn
|
||||
name={'MyProfile' as 'Profile'}
|
||||
getComponent={() => ProfileScreen}
|
||||
initialParams={{
|
||||
name: 'me',
|
||||
hideBackButton: true,
|
||||
}}
|
||||
initialParams={{name: 'me', hideBackButton: true}}
|
||||
/>
|
||||
{commonScreens(MyProfileTab as typeof HomeTab)}
|
||||
{commonScreens(MyProfileTab as unknown as typeof Flat)}
|
||||
</MyProfileTab.Navigator>
|
||||
)
|
||||
}
|
||||
@@ -601,13 +585,8 @@ function MessagesTabNavigator() {
|
||||
const t = useTheme()
|
||||
return (
|
||||
<MessagesTab.Navigator
|
||||
screenOptions={{
|
||||
animationDuration: 285,
|
||||
gestureEnabled: true,
|
||||
fullScreenGestureEnabled: true,
|
||||
headerShown: false,
|
||||
contentStyle: t.atoms.bg,
|
||||
}}>
|
||||
screenOptions={screenOptions(t)}
|
||||
initialRouteName="Messages">
|
||||
<MessagesTab.Screen
|
||||
name="Messages"
|
||||
getComponent={() => MessagesScreen}
|
||||
@@ -616,7 +595,7 @@ function MessagesTabNavigator() {
|
||||
animationTypeForReplace: route.params?.animation ?? 'push',
|
||||
})}
|
||||
/>
|
||||
{commonScreens(MessagesTab as typeof HomeTab)}
|
||||
{commonScreens(MessagesTab as typeof Flat)}
|
||||
</MessagesTab.Navigator>
|
||||
)
|
||||
}
|
||||
@@ -634,13 +613,7 @@ const FlatNavigator = () => {
|
||||
return (
|
||||
<Flat.Navigator
|
||||
screenListeners={screenListeners}
|
||||
screenOptions={{
|
||||
animationDuration: 285,
|
||||
gestureEnabled: true,
|
||||
fullScreenGestureEnabled: true,
|
||||
headerShown: false,
|
||||
contentStyle: t.atoms.bg,
|
||||
}}>
|
||||
screenOptions={screenOptions(t)}>
|
||||
<Flat.Screen
|
||||
name="Home"
|
||||
getComponent={() => HomeScreen}
|
||||
@@ -666,7 +639,7 @@ const FlatNavigator = () => {
|
||||
getComponent={() => HomeScreen}
|
||||
options={{title: title(msg`Home`)}}
|
||||
/>
|
||||
{commonScreens(Flat as typeof HomeTab, numUnread)}
|
||||
{commonScreens(Flat, numUnread)}
|
||||
</Flat.Navigator>
|
||||
)
|
||||
}
|
||||
@@ -773,7 +746,14 @@ function RoutesContainer({children}: React.PropsWithChildren<{}>) {
|
||||
logModuleInitTime()
|
||||
onReady()
|
||||
logger.metric('router:navigate', {}, {statsig: false})
|
||||
}}>
|
||||
}}
|
||||
// WARNING: Implicit navigation to nested navigators is depreciated in React Navigation 7.x
|
||||
// However, there's a fair amount of places we do that, especially in when popping to the top of stacks.
|
||||
// See BottomBar.tsx for an example of how to handle nested navigators in the tabs correctly.
|
||||
// I'm scared of missing a spot (esp. with push notifications etc) so let's enable this legacy behaviour for now.
|
||||
// We will need to confirm we handle nested navigators correctly by the time we migrate to React Navigation 8.x
|
||||
// -sfn
|
||||
navigationInChildEnabled>
|
||||
{children}
|
||||
</NavigationContainer>
|
||||
</>
|
||||
|
||||
+26
-10
@@ -1,7 +1,11 @@
|
||||
import React from 'react'
|
||||
import React, {useMemo} from 'react'
|
||||
import {type GestureResponderEvent} from 'react-native'
|
||||
import {sanitizeUrl} from '@braintree/sanitize-url'
|
||||
import {StackActions, useLinkProps} from '@react-navigation/native'
|
||||
import {
|
||||
type LinkProps as RNLinkProps,
|
||||
StackActions,
|
||||
useLinkBuilder,
|
||||
} from '@react-navigation/native'
|
||||
|
||||
import {BSKY_DOWNLOAD_URL} from '#/lib/constants'
|
||||
import {useNavigationDeduped} from '#/lib/hooks/useNavigationDeduped'
|
||||
@@ -28,12 +32,11 @@ import {router} from '#/routes'
|
||||
*/
|
||||
export {useButtonContext as useLinkContext} from '#/components/Button'
|
||||
|
||||
type BaseLinkProps = Pick<
|
||||
Parameters<typeof useLinkProps<AllNavigatorParams>>[0],
|
||||
'to'
|
||||
> & {
|
||||
type BaseLinkProps = {
|
||||
testID?: string
|
||||
|
||||
to: RNLinkProps<AllNavigatorParams> | string
|
||||
|
||||
/**
|
||||
* The React Navigation `StackAction` to perform when the link is pressed.
|
||||
*/
|
||||
@@ -92,10 +95,23 @@ export function useLink({
|
||||
shouldProxy?: boolean
|
||||
}) {
|
||||
const navigation = useNavigationDeduped()
|
||||
const {href} = useLinkProps<AllNavigatorParams>({
|
||||
to:
|
||||
typeof to === 'string' ? convertBskyAppUrlIfNeeded(sanitizeUrl(to)) : to,
|
||||
})
|
||||
const {buildHref} = useLinkBuilder()
|
||||
const href = useMemo(() => {
|
||||
return typeof to === 'string'
|
||||
? convertBskyAppUrlIfNeeded(sanitizeUrl(to))
|
||||
: to.screen
|
||||
? buildHref(to.screen, to.params)
|
||||
: to.href
|
||||
? convertBskyAppUrlIfNeeded(sanitizeUrl(to.href))
|
||||
: undefined
|
||||
}, [to, buildHref])
|
||||
|
||||
if (!href) {
|
||||
throw new Error(
|
||||
'Link `to` prop must be a string or an object with `screen` and `params` properties',
|
||||
)
|
||||
}
|
||||
|
||||
const isExternal = isExternalUrl(href)
|
||||
const {openModal, closeModal} = useModalControls()
|
||||
const openLink = useOpenLink()
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import React from 'react'
|
||||
import {useMemo} from 'react'
|
||||
import {useNavigation} from '@react-navigation/core'
|
||||
import {NavigationState} from '@react-navigation/native'
|
||||
import type {NavigationAction} from '@react-navigation/routers'
|
||||
|
||||
import {useDedupe} from '#/lib/hooks/useDedupe'
|
||||
import {AllNavigatorParams, NavigationProp} from '#/lib/routes/types'
|
||||
import {type NavigationProp} from '#/lib/routes/types'
|
||||
|
||||
export type DebouncedNavigationProp = Pick<
|
||||
NavigationProp,
|
||||
@@ -22,46 +20,19 @@ export function useNavigationDeduped() {
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
const dedupe = useDedupe()
|
||||
|
||||
return React.useMemo(
|
||||
(): DebouncedNavigationProp => ({
|
||||
// Types from @react-navigation/routers/lib/typescript/src/StackRouter.ts
|
||||
push: <RouteName extends keyof AllNavigatorParams>(
|
||||
...args: undefined extends AllNavigatorParams[RouteName]
|
||||
?
|
||||
| [screen: RouteName]
|
||||
| [screen: RouteName, params: AllNavigatorParams[RouteName]]
|
||||
: [screen: RouteName, params: AllNavigatorParams[RouteName]]
|
||||
) => {
|
||||
return useMemo<DebouncedNavigationProp>(
|
||||
() => ({
|
||||
push: (...args: Parameters<typeof navigation.push>) => {
|
||||
dedupe(() => navigation.push(...args))
|
||||
},
|
||||
// Types from @react-navigation/core/src/types.tsx
|
||||
navigate: <RouteName extends keyof AllNavigatorParams>(
|
||||
...args: RouteName extends unknown
|
||||
? undefined extends AllNavigatorParams[RouteName]
|
||||
?
|
||||
| [screen: RouteName]
|
||||
| [screen: RouteName, params: AllNavigatorParams[RouteName]]
|
||||
: [screen: RouteName, params: AllNavigatorParams[RouteName]]
|
||||
: never
|
||||
) => {
|
||||
navigate: (...args: Parameters<typeof navigation.navigate>) => {
|
||||
dedupe(() => navigation.navigate(...args))
|
||||
},
|
||||
// Types from @react-navigation/routers/lib/typescript/src/StackRouter.ts
|
||||
replace: <RouteName extends keyof AllNavigatorParams>(
|
||||
...args: undefined extends AllNavigatorParams[RouteName]
|
||||
?
|
||||
| [screen: RouteName]
|
||||
| [screen: RouteName, params: AllNavigatorParams[RouteName]]
|
||||
: [screen: RouteName, params: AllNavigatorParams[RouteName]]
|
||||
) => {
|
||||
replace: (...args: Parameters<typeof navigation.replace>) => {
|
||||
dedupe(() => navigation.replace(...args))
|
||||
},
|
||||
dispatch: (
|
||||
action:
|
||||
| NavigationAction
|
||||
| ((state: NavigationState) => NavigationAction),
|
||||
) => {
|
||||
dedupe(() => navigation.dispatch(action))
|
||||
dispatch: (...args: Parameters<typeof navigation.dispatch>) => {
|
||||
dedupe(() => navigation.dispatch(...args))
|
||||
},
|
||||
popToTop: () => {
|
||||
dedupe(() => navigation.popToTop())
|
||||
|
||||
@@ -92,7 +92,7 @@ export type NotificationsTabNavigatorParams = CommonNavigatorParams & {
|
||||
}
|
||||
|
||||
export type MyProfileTabNavigatorParams = CommonNavigatorParams & {
|
||||
MyProfile: undefined
|
||||
MyProfile: {name: 'me'; hideBackButton: true}
|
||||
}
|
||||
|
||||
export type MessagesTabNavigatorParams = CommonNavigatorParams & {
|
||||
|
||||
+42
-37
@@ -1,20 +1,20 @@
|
||||
import React, {ComponentProps, memo, useMemo} from 'react'
|
||||
import {memo, useCallback, useMemo} from 'react'
|
||||
import {
|
||||
GestureResponderEvent,
|
||||
type GestureResponderEvent,
|
||||
Platform,
|
||||
Pressable,
|
||||
StyleProp,
|
||||
TextProps,
|
||||
TextStyle,
|
||||
TouchableOpacity,
|
||||
type StyleProp,
|
||||
type TextProps,
|
||||
type TextStyle,
|
||||
type TouchableOpacity,
|
||||
View,
|
||||
ViewStyle,
|
||||
type ViewStyle,
|
||||
} from 'react-native'
|
||||
import {sanitizeUrl} from '@braintree/sanitize-url'
|
||||
import {StackActions, useLinkProps} from '@react-navigation/native'
|
||||
import {StackActions} from '@react-navigation/native'
|
||||
|
||||
import {
|
||||
DebouncedNavigationProp,
|
||||
type DebouncedNavigationProp,
|
||||
useNavigationDeduped,
|
||||
} from '#/lib/hooks/useNavigationDeduped'
|
||||
import {useOpenLink} from '#/lib/hooks/useOpenLink'
|
||||
@@ -24,7 +24,7 @@ import {
|
||||
isExternalUrl,
|
||||
linkRequiresWarning,
|
||||
} from '#/lib/strings/url-helpers'
|
||||
import {TypographyVariant} from '#/lib/ThemeContext'
|
||||
import {type TypographyVariant} from '#/lib/ThemeContext'
|
||||
import {isAndroid, isWeb} from '#/platform/detection'
|
||||
import {emitSoftReset} from '#/state/events'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
@@ -38,7 +38,7 @@ type Event =
|
||||
| React.MouseEvent<HTMLAnchorElement, MouseEvent>
|
||||
| GestureResponderEvent
|
||||
|
||||
interface Props extends ComponentProps<typeof TouchableOpacity> {
|
||||
interface Props extends React.ComponentProps<typeof TouchableOpacity> {
|
||||
testID?: string
|
||||
style?: StyleProp<ViewStyle>
|
||||
href?: string
|
||||
@@ -47,7 +47,7 @@ interface Props extends ComponentProps<typeof TouchableOpacity> {
|
||||
hoverStyle?: StyleProp<ViewStyle>
|
||||
noFeedback?: boolean
|
||||
asAnchor?: boolean
|
||||
dataSet?: Object | undefined
|
||||
dataSet?: any
|
||||
anchorNoUnderline?: boolean
|
||||
navigationAction?: 'push' | 'replace' | 'navigate'
|
||||
onPointerEnter?: () => void
|
||||
@@ -69,6 +69,7 @@ export const Link = memo(function Link({
|
||||
onBeforePress,
|
||||
accessibilityActions,
|
||||
onAccessibilityAction,
|
||||
dataSet: dataSetProp,
|
||||
...props
|
||||
}: Props) {
|
||||
const t = useTheme()
|
||||
@@ -77,7 +78,7 @@ export const Link = memo(function Link({
|
||||
const anchorHref = asAnchor ? sanitizeUrl(href) : undefined
|
||||
const openLink = useOpenLink()
|
||||
|
||||
const onPress = React.useCallback(
|
||||
const onPress = useCallback(
|
||||
(e?: Event) => {
|
||||
onBeforePress?.()
|
||||
if (typeof href === 'string') {
|
||||
@@ -99,6 +100,14 @@ export const Link = memo(function Link({
|
||||
{name: 'activate', label: title},
|
||||
]
|
||||
|
||||
const dataSet = useMemo(() => {
|
||||
const ds = {...dataSetProp}
|
||||
if (anchorNoUnderline) {
|
||||
ds.noUnderline = 1
|
||||
}
|
||||
return ds
|
||||
}, [dataSetProp, anchorNoUnderline])
|
||||
|
||||
if (noFeedback) {
|
||||
return (
|
||||
<WebAuxClickWrapper>
|
||||
@@ -129,17 +138,6 @@ export const Link = memo(function Link({
|
||||
)
|
||||
}
|
||||
|
||||
if (anchorNoUnderline) {
|
||||
// @ts-ignore web only -prf
|
||||
props.dataSet = props.dataSet || {}
|
||||
// @ts-ignore web only -prf
|
||||
props.dataSet.noUnderline = 1
|
||||
}
|
||||
|
||||
if (title && !props.accessibilityLabel) {
|
||||
props.accessibilityLabel = title
|
||||
}
|
||||
|
||||
const Com = props.hoverStyle ? PressableWithHover : Pressable
|
||||
return (
|
||||
<Com
|
||||
@@ -148,8 +146,11 @@ export const Link = memo(function Link({
|
||||
onPress={onPress}
|
||||
accessible={accessible}
|
||||
accessibilityRole="link"
|
||||
accessibilityLabel={props.accessibilityLabel ?? title}
|
||||
accessibilityHint={props.accessibilityHint}
|
||||
// @ts-ignore web only -prf
|
||||
href={anchorHref}
|
||||
dataSet={dataSet}
|
||||
{...props}>
|
||||
{children ? children : <Text>{title || 'link'}</Text>}
|
||||
</Com>
|
||||
@@ -164,14 +165,14 @@ export const TextLink = memo(function TextLink({
|
||||
text,
|
||||
numberOfLines,
|
||||
lineHeight,
|
||||
dataSet,
|
||||
dataSet: dataSetProp,
|
||||
title,
|
||||
onPress,
|
||||
onPress: onPressProp,
|
||||
onBeforePress,
|
||||
disableMismatchWarning,
|
||||
navigationAction,
|
||||
anchorNoUnderline,
|
||||
...orgProps
|
||||
...props
|
||||
}: {
|
||||
testID?: string
|
||||
type?: TypographyVariant
|
||||
@@ -187,7 +188,6 @@ export const TextLink = memo(function TextLink({
|
||||
anchorNoUnderline?: boolean
|
||||
onBeforePress?: () => void
|
||||
} & TextProps) {
|
||||
const {...props} = useLinkProps({to: sanitizeUrl(href)})
|
||||
const navigation = useNavigationDeduped()
|
||||
const {openModal, closeModal} = useModalControls()
|
||||
const openLink = useOpenLink()
|
||||
@@ -196,12 +196,15 @@ export const TextLink = memo(function TextLink({
|
||||
console.error('Unable to detect mismatching label')
|
||||
}
|
||||
|
||||
const dataSet = useMemo(() => {
|
||||
const ds = {...dataSetProp}
|
||||
if (anchorNoUnderline) {
|
||||
dataSet = dataSet ?? {}
|
||||
dataSet.noUnderline = 1
|
||||
ds.noUnderline = 1
|
||||
}
|
||||
return ds
|
||||
}, [dataSetProp, anchorNoUnderline])
|
||||
|
||||
props.onPress = React.useCallback(
|
||||
const onPress = useCallback(
|
||||
(e?: Event) => {
|
||||
const requiresWarning =
|
||||
!disableMismatchWarning &&
|
||||
@@ -224,10 +227,10 @@ export const TextLink = memo(function TextLink({
|
||||
return
|
||||
}
|
||||
onBeforePress?.()
|
||||
if (onPress) {
|
||||
if (onPressProp) {
|
||||
e?.preventDefault?.()
|
||||
// @ts-ignore function signature differs by platform -prf
|
||||
return onPress()
|
||||
// @ts-expect-error function signature differs by platform -prf
|
||||
return onPressProp()
|
||||
}
|
||||
return onPressInner(
|
||||
closeModal,
|
||||
@@ -240,7 +243,7 @@ export const TextLink = memo(function TextLink({
|
||||
},
|
||||
[
|
||||
onBeforePress,
|
||||
onPress,
|
||||
onPressProp,
|
||||
closeModal,
|
||||
openModal,
|
||||
navigation,
|
||||
@@ -273,8 +276,10 @@ export const TextLink = memo(function TextLink({
|
||||
title={title}
|
||||
// @ts-ignore web only -prf
|
||||
hrefAttrs={hrefAttrs} // hack to get open in new tab to work on safari. without this, safari will open in a new window
|
||||
{...props}
|
||||
{...orgProps}>
|
||||
onPress={onPress}
|
||||
accessibilityRole="link"
|
||||
href={convertBskyAppUrlIfNeeded(sanitizeUrl(href))}
|
||||
{...props}>
|
||||
{text}
|
||||
</Text>
|
||||
)
|
||||
|
||||
@@ -160,7 +160,7 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => {
|
||||
// =
|
||||
|
||||
const onPressTab = React.useCallback(
|
||||
(tab: string) => {
|
||||
(tab: 'Home' | 'Search' | 'Messages' | 'Notifications' | 'MyProfile') => {
|
||||
const state = navigation.getState()
|
||||
setDrawerOpen(false)
|
||||
if (isWeb) {
|
||||
@@ -168,7 +168,7 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => {
|
||||
if (tab === 'MyProfile') {
|
||||
navigation.navigate('Profile', {name: currentAccount!.handle})
|
||||
} else {
|
||||
// @ts-ignore must be Home, Search, Notifications, or MyProfile
|
||||
// @ts-expect-error struggles with string unions, apparently
|
||||
navigation.navigate(tab)
|
||||
}
|
||||
} else {
|
||||
@@ -176,9 +176,23 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => {
|
||||
if (tabState === TabState.InsideAtRoot) {
|
||||
emitSoftReset()
|
||||
} else if (tabState === TabState.Inside) {
|
||||
navigation.dispatch(StackActions.popToTop())
|
||||
// find the correct navigator in which to pop-to-top
|
||||
const target = state.routes.find(route => route.name === `${tab}Tab`)
|
||||
?.state?.key
|
||||
if (target) {
|
||||
// if we found it, trigger pop-to-top
|
||||
navigation.dispatch({
|
||||
...StackActions.popToTop(),
|
||||
target,
|
||||
})
|
||||
} else {
|
||||
// fallback: reset navigation
|
||||
navigation.reset({
|
||||
index: 0,
|
||||
routes: [{name: `${tab}Tab`}],
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// @ts-ignore must be Home, Search, Notifications, or MyProfile
|
||||
navigation.navigate(`${tab}Tab`)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, {type ComponentProps} from 'react'
|
||||
import {useCallback} from 'react'
|
||||
import {type GestureResponderEvent, View} from 'react-native'
|
||||
import Animated from 'react-native-reanimated'
|
||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||
@@ -52,13 +52,7 @@ import {
|
||||
import {useDemoMode} from '#/storage/hooks/demo-mode'
|
||||
import {styles} from './BottomBarStyles'
|
||||
|
||||
type TabOptions =
|
||||
| 'Home'
|
||||
| 'Search'
|
||||
| 'Notifications'
|
||||
| 'MyProfile'
|
||||
| 'Feeds'
|
||||
| 'Messages'
|
||||
type TabOptions = 'Home' | 'Search' | 'Messages' | 'Notifications' | 'MyProfile'
|
||||
|
||||
export function BottomBar({navigation}: BottomTabBarProps) {
|
||||
const {hasSession, currentAccount} = useSession()
|
||||
@@ -81,48 +75,62 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
||||
const gate = useGate()
|
||||
const iconWidth = 28
|
||||
|
||||
const showSignIn = React.useCallback(() => {
|
||||
const showSignIn = useCallback(() => {
|
||||
closeAllActiveElements()
|
||||
requestSwitchToAccount({requestedAccount: 'none'})
|
||||
}, [requestSwitchToAccount, closeAllActiveElements])
|
||||
|
||||
const showCreateAccount = React.useCallback(() => {
|
||||
const showCreateAccount = useCallback(() => {
|
||||
closeAllActiveElements()
|
||||
requestSwitchToAccount({requestedAccount: 'new'})
|
||||
// setShowLoggedOut(true)
|
||||
}, [requestSwitchToAccount, closeAllActiveElements])
|
||||
|
||||
const onPressTab = React.useCallback(
|
||||
const onPressTab = useCallback(
|
||||
(tab: TabOptions) => {
|
||||
const state = navigation.getState()
|
||||
const tabState = getTabState(state, tab)
|
||||
if (tabState === TabState.InsideAtRoot) {
|
||||
emitSoftReset()
|
||||
} else if (tabState === TabState.Inside) {
|
||||
dedupe(() => navigation.dispatch(StackActions.popToTop()))
|
||||
// find the correct navigator in which to pop-to-top
|
||||
const target = state.routes.find(route => route.name === `${tab}Tab`)
|
||||
?.state?.key
|
||||
dedupe(() => {
|
||||
if (target) {
|
||||
// if we found it, trigger pop-to-top
|
||||
navigation.dispatch({
|
||||
...StackActions.popToTop(),
|
||||
target,
|
||||
})
|
||||
} else {
|
||||
// fallback: reset navigation
|
||||
navigation.reset({
|
||||
index: 0,
|
||||
routes: [{name: `${tab}Tab`}],
|
||||
})
|
||||
}
|
||||
})
|
||||
} else {
|
||||
dedupe(() => navigation.navigate(`${tab}Tab`))
|
||||
}
|
||||
},
|
||||
[navigation, dedupe],
|
||||
)
|
||||
const onPressHome = React.useCallback(() => onPressTab('Home'), [onPressTab])
|
||||
const onPressSearch = React.useCallback(
|
||||
() => onPressTab('Search'),
|
||||
[onPressTab],
|
||||
)
|
||||
const onPressNotifications = React.useCallback(
|
||||
const onPressHome = useCallback(() => onPressTab('Home'), [onPressTab])
|
||||
const onPressSearch = useCallback(() => onPressTab('Search'), [onPressTab])
|
||||
const onPressNotifications = useCallback(
|
||||
() => onPressTab('Notifications'),
|
||||
[onPressTab],
|
||||
)
|
||||
const onPressProfile = React.useCallback(() => {
|
||||
const onPressProfile = useCallback(() => {
|
||||
onPressTab('MyProfile')
|
||||
}, [onPressTab])
|
||||
const onPressMessages = React.useCallback(() => {
|
||||
const onPressMessages = useCallback(() => {
|
||||
onPressTab('Messages')
|
||||
}, [onPressTab])
|
||||
|
||||
const onLongPressProfile = React.useCallback(() => {
|
||||
const onLongPressProfile = useCallback(() => {
|
||||
playHaptic()
|
||||
accountSwitchControl.open()
|
||||
}, [accountSwitchControl, playHaptic])
|
||||
@@ -361,7 +369,7 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
||||
|
||||
interface BtnProps
|
||||
extends Pick<
|
||||
ComponentProps<typeof PressableScale>,
|
||||
React.ComponentProps<typeof PressableScale>,
|
||||
| 'accessible'
|
||||
| 'accessibilityRole'
|
||||
| 'accessibilityHint'
|
||||
|
||||
@@ -1,25 +1,29 @@
|
||||
import * as React from 'react'
|
||||
import {View} from 'react-native'
|
||||
// Based on @react-navigation/native-stack/src/createNativeStackNavigator.ts
|
||||
// Based on @react-navigation/native-stack/src/navigators/createNativeStackNavigator.ts
|
||||
// MIT License
|
||||
// Copyright (c) 2017 React Navigation Contributors
|
||||
import {
|
||||
createNavigatorFactory,
|
||||
type EventArg,
|
||||
type NavigatorTypeBagBase,
|
||||
type ParamListBase,
|
||||
type StackActionHelpers,
|
||||
StackActions,
|
||||
type StackNavigationState,
|
||||
StackRouter,
|
||||
type StackRouterOptions,
|
||||
type StaticConfig,
|
||||
type TypedNavigator,
|
||||
useNavigationBuilder,
|
||||
} from '@react-navigation/native'
|
||||
import {NativeStackView} from '@react-navigation/native-stack'
|
||||
import {
|
||||
type NativeStackNavigationEventMap,
|
||||
type NativeStackNavigationOptions,
|
||||
type NativeStackNavigationProp,
|
||||
type NativeStackNavigatorProps,
|
||||
} from '@react-navigation/native-stack'
|
||||
import {NativeStackView} from '@react-navigation/native-stack'
|
||||
import {type NativeStackNavigatorProps} from '@react-navigation/native-stack/src/types'
|
||||
|
||||
import {PWI_ENABLED} from '#/lib/build-flags'
|
||||
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
|
||||
@@ -48,12 +52,14 @@ function NativeStackNavigator({
|
||||
id,
|
||||
initialRouteName,
|
||||
children,
|
||||
layout,
|
||||
screenListeners,
|
||||
screenOptions,
|
||||
screenLayout,
|
||||
...rest
|
||||
}: NativeStackNavigatorProps) {
|
||||
// --- this is copy and pasted from the original native stack navigator ---
|
||||
const {state, descriptors, navigation, NavigationContent} =
|
||||
const {state, describe, descriptors, navigation, NavigationContent} =
|
||||
useNavigationBuilder<
|
||||
StackNavigationState<ParamListBase>,
|
||||
StackRouterOptions,
|
||||
@@ -64,9 +70,12 @@ function NativeStackNavigator({
|
||||
id,
|
||||
initialRouteName,
|
||||
children,
|
||||
layout,
|
||||
screenListeners,
|
||||
screenOptions,
|
||||
screenLayout,
|
||||
})
|
||||
|
||||
React.useEffect(
|
||||
() =>
|
||||
// @ts-expect-error: there may not be a tab navigator in parent
|
||||
@@ -148,7 +157,8 @@ function NativeStackNavigator({
|
||||
{...rest}
|
||||
state={state}
|
||||
navigation={navigation}
|
||||
descriptors={newDescriptors}
|
||||
descriptors={descriptors}
|
||||
describe={describe}
|
||||
/>
|
||||
</View>
|
||||
{isWeb && (
|
||||
@@ -161,9 +171,25 @@ function NativeStackNavigator({
|
||||
)
|
||||
}
|
||||
|
||||
export const createNativeStackNavigatorWithAuth = createNavigatorFactory<
|
||||
StackNavigationState<ParamListBase>,
|
||||
NativeStackNavigationOptionsWithAuth,
|
||||
NativeStackNavigationEventMap,
|
||||
typeof NativeStackNavigator
|
||||
>(NativeStackNavigator)
|
||||
export function createNativeStackNavigatorWithAuth<
|
||||
const ParamList extends ParamListBase,
|
||||
const NavigatorID extends string | undefined = undefined,
|
||||
const TypeBag extends NavigatorTypeBagBase = {
|
||||
ParamList: ParamList
|
||||
NavigatorID: NavigatorID
|
||||
State: StackNavigationState<ParamList>
|
||||
ScreenOptions: NativeStackNavigationOptionsWithAuth
|
||||
EventMap: NativeStackNavigationEventMap
|
||||
NavigationList: {
|
||||
[RouteName in keyof ParamList]: NativeStackNavigationProp<
|
||||
ParamList,
|
||||
RouteName,
|
||||
NavigatorID
|
||||
>
|
||||
}
|
||||
Navigator: typeof NativeStackNavigator
|
||||
},
|
||||
const Config extends StaticConfig<TypeBag> = StaticConfig<TypeBag>,
|
||||
>(config?: Config): TypedNavigator<TypeBag, Config> {
|
||||
return createNavigatorFactory(NativeStackNavigator)(config)
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import React from 'react'
|
||||
import {useCallback, useMemo, useState} from 'react'
|
||||
import {StyleSheet, View} from 'react-native'
|
||||
import {type AppBskyActorDefs} from '@atproto/api'
|
||||
import {msg, plural, Trans} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {
|
||||
useLinkProps,
|
||||
useLinkTo,
|
||||
useNavigation,
|
||||
useNavigationState,
|
||||
} from '@react-navigation/native'
|
||||
@@ -326,7 +326,7 @@ function NavItem({count, hasNew, href, icon, iconFilled, label}: NavItemProps) {
|
||||
const {_} = useLingui()
|
||||
const {currentAccount} = useSession()
|
||||
const {leftNavMinimal} = useLayoutBreakpoints()
|
||||
const [pathName] = React.useMemo(() => router.matchPath(href), [href])
|
||||
const [pathName] = useMemo(() => router.matchPath(href), [href])
|
||||
const currentRouteInfo = useNavigationState(state => {
|
||||
if (!state) {
|
||||
return {name: 'Home'}
|
||||
@@ -339,8 +339,8 @@ function NavItem({count, hasNew, href, icon, iconFilled, label}: NavItemProps) {
|
||||
(currentRouteInfo.params as CommonNavigatorParams['Profile']).name ===
|
||||
currentAccount?.handle
|
||||
: isTab(currentRouteInfo.name, pathName)
|
||||
const {onPress} = useLinkProps({to: href})
|
||||
const onPressWrapped = React.useCallback(
|
||||
const linkTo = useLinkTo()
|
||||
const onPressWrapped = useCallback(
|
||||
(e: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
|
||||
if (e.ctrlKey || e.metaKey || e.altKey) {
|
||||
return
|
||||
@@ -349,10 +349,10 @@ function NavItem({count, hasNew, href, icon, iconFilled, label}: NavItemProps) {
|
||||
if (isCurrent) {
|
||||
emitSoftReset()
|
||||
} else {
|
||||
onPress()
|
||||
linkTo(href)
|
||||
}
|
||||
},
|
||||
[onPress, isCurrent],
|
||||
[linkTo, href, isCurrent],
|
||||
)
|
||||
|
||||
return (
|
||||
@@ -468,7 +468,7 @@ function ComposeBtn() {
|
||||
const {openComposer} = useOpenComposer()
|
||||
const {_} = useLingui()
|
||||
const {leftNavMinimal} = useLayoutBreakpoints()
|
||||
const [isFetchingHandle, setIsFetchingHandle] = React.useState(false)
|
||||
const [isFetchingHandle, setIsFetchingHandle] = useState(false)
|
||||
const fetchHandle = useFetchHandle()
|
||||
|
||||
const getProfileHandle = async () => {
|
||||
|
||||
@@ -6289,65 +6289,69 @@
|
||||
invariant "^2.2.4"
|
||||
nullthrows "^1.1.1"
|
||||
|
||||
"@react-navigation/bottom-tabs@^6.5.20":
|
||||
version "6.5.20"
|
||||
resolved "https://registry.yarnpkg.com/@react-navigation/bottom-tabs/-/bottom-tabs-6.5.20.tgz#5335e75b02c527ef0569bd97d4f9185d65616e49"
|
||||
integrity sha512-ow6Z06iS4VqBO8d7FP+HsGjJLWt2xTWIvuWjpoCvsM/uQXzCRDIjBv9HaKcXbF0yTW7IMir0oDAbU5PFzEDdgA==
|
||||
"@react-navigation/bottom-tabs@^7.3.13":
|
||||
version "7.3.14"
|
||||
resolved "https://registry.yarnpkg.com/@react-navigation/bottom-tabs/-/bottom-tabs-7.3.14.tgz#9ee02baea86ab24abe267726665bc69c6df0bf4c"
|
||||
integrity sha512-s2qinJggS2HYZdCOey9A+fN+bNpWeEKwiL/FjAVOTcv+uofxPWN6CtEZUZGPEjfRjis/srURBmCmpNZSI6sQ9Q==
|
||||
dependencies:
|
||||
"@react-navigation/elements" "^1.3.30"
|
||||
"@react-navigation/elements" "^2.4.3"
|
||||
color "^4.2.3"
|
||||
warn-once "^0.1.0"
|
||||
|
||||
"@react-navigation/core@^6.4.16":
|
||||
version "6.4.16"
|
||||
resolved "https://registry.yarnpkg.com/@react-navigation/core/-/core-6.4.16.tgz#f9369a134805174536b9aa0f0f483b930511caf9"
|
||||
integrity sha512-UDTJBsHxnzgFETR3ZxhctP+RWr4SkyeZpbhpkQoIGOuwSCkt1SE0qjU48/u6r6w6XlX8OqVudn1Ab0QFXTHxuQ==
|
||||
"@react-navigation/core@^7.10.0":
|
||||
version "7.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@react-navigation/core/-/core-7.10.0.tgz#8205ea6b84ce34b2fc2c196701b4cd9b434211b9"
|
||||
integrity sha512-qZBA5gGm+9liT4+EHk+kl9apwvqh7HqhLF1XeX6SQRmC/n2QI0u1B8OevKc+EPUDEM9Od15IuwT/GRbSs7/Umw==
|
||||
dependencies:
|
||||
"@react-navigation/routers" "^6.1.9"
|
||||
"@react-navigation/routers" "^7.4.0"
|
||||
escape-string-regexp "^4.0.0"
|
||||
nanoid "^3.1.23"
|
||||
nanoid "^3.3.11"
|
||||
query-string "^7.1.3"
|
||||
react-is "^16.13.0"
|
||||
use-latest-callback "^0.1.9"
|
||||
react-is "^19.1.0"
|
||||
use-latest-callback "^0.2.3"
|
||||
use-sync-external-store "^1.5.0"
|
||||
|
||||
"@react-navigation/drawer@^6.6.15":
|
||||
version "6.6.15"
|
||||
resolved "https://registry.yarnpkg.com/@react-navigation/drawer/-/drawer-6.6.15.tgz#fcedba68f735103dbc035911f5959ce926081d62"
|
||||
integrity sha512-GLkFQNxjtmxB/qXSHmu1DfoB89jCzW64tmX68iPndth+9U+0IP27GcCCaMZxQfwj+nI8Kn2zlTlXAZDIIHE+DQ==
|
||||
"@react-navigation/drawer@^7.3.12":
|
||||
version "7.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@react-navigation/drawer/-/drawer-7.4.1.tgz#50517d8c57f09cdbfc20a485c47016066b918e76"
|
||||
integrity sha512-kj5wL31smDLw/6l+0KPR5cjaOZg6oHJCl3RPQonFPuYolUPZBVnuS++uvlifWcD/mqdGmhl3rgLTircRH4vQ7Q==
|
||||
dependencies:
|
||||
"@react-navigation/elements" "^1.3.30"
|
||||
"@react-navigation/elements" "^2.4.3"
|
||||
color "^4.2.3"
|
||||
warn-once "^0.1.0"
|
||||
react-native-drawer-layout "^4.1.10"
|
||||
use-latest-callback "^0.2.3"
|
||||
|
||||
"@react-navigation/elements@^1.3.30":
|
||||
version "1.3.30"
|
||||
resolved "https://registry.yarnpkg.com/@react-navigation/elements/-/elements-1.3.30.tgz#a81371f599af1070b12014f05d6c09b1a611fd9a"
|
||||
integrity sha512-plhc8UvCZs0UkV+sI+3bisIyn78wz9O/BiWZXpounu72k/R/Sj5PuZYFJ1fi6psvriUveMCGh4LeZckAZu2qiQ==
|
||||
|
||||
"@react-navigation/native-stack@^6.9.26":
|
||||
version "6.9.26"
|
||||
resolved "https://registry.yarnpkg.com/@react-navigation/native-stack/-/native-stack-6.9.26.tgz#90facf7783c9927f094bc9f01c613af75b6c241e"
|
||||
integrity sha512-++dueQ+FDj2XkZ902DVrK79ub1vp19nSdAZWxKRgd6+Bc0Niiesua6rMCqymYOVaYh+dagwkA9r00bpt/U5WLw==
|
||||
"@react-navigation/elements@^2.4.3":
|
||||
version "2.4.3"
|
||||
resolved "https://registry.yarnpkg.com/@react-navigation/elements/-/elements-2.4.3.tgz#cc1dde4c98739d35a0c9c23872316063962cfaee"
|
||||
integrity sha512-psoNmnZ0DQIt9nxxPITVLtYW04PGCAfnmd/Pcd3yhiBs93aj+HYKH+SDZDpUnXMf3BN7Wvo4+jPI+/Xjqb+m9w==
|
||||
dependencies:
|
||||
"@react-navigation/elements" "^1.3.30"
|
||||
warn-once "^0.1.0"
|
||||
color "^4.2.3"
|
||||
|
||||
"@react-navigation/native@^6.1.17":
|
||||
version "6.1.17"
|
||||
resolved "https://registry.yarnpkg.com/@react-navigation/native/-/native-6.1.17.tgz#439f15a99809d26ea4682d2a3766081cf2ca31cf"
|
||||
integrity sha512-mer3OvfwWOHoUSMJyLa4vnBH3zpFmCwuzrBPlw7feXklurr/ZDiLjLxUScOot6jLRMz/67GyilEYMmP99LL0RQ==
|
||||
"@react-navigation/native-stack@^7.3.13":
|
||||
version "7.3.14"
|
||||
resolved "https://registry.yarnpkg.com/@react-navigation/native-stack/-/native-stack-7.3.14.tgz#d1c90f2e50cd13bbced923991cf2faee8083f725"
|
||||
integrity sha512-45Sf7ReqSCIySXS5nrKtLGmNlFXm5x+u32YQMwKDONCqVGOBCfo4ryKqeQq1EMJ7Py6IDyOwHMhA+jhNOxnfPw==
|
||||
dependencies:
|
||||
"@react-navigation/core" "^6.4.16"
|
||||
"@react-navigation/elements" "^2.4.3"
|
||||
warn-once "^0.1.1"
|
||||
|
||||
"@react-navigation/native@^7.1.9":
|
||||
version "7.1.10"
|
||||
resolved "https://registry.yarnpkg.com/@react-navigation/native/-/native-7.1.10.tgz#768f674f7c09b6a57215762052aa62a7dc107402"
|
||||
integrity sha512-Ug4IML0DkAxZTMF/E7lyyLXSclkGAYElY2cxZWITwfBjtlVeda0NjsdnTWY5EGjnd7bwvhTIUC+CO6qSlrDn5A==
|
||||
dependencies:
|
||||
"@react-navigation/core" "^7.10.0"
|
||||
escape-string-regexp "^4.0.0"
|
||||
fast-deep-equal "^3.1.3"
|
||||
nanoid "^3.1.23"
|
||||
nanoid "^3.3.11"
|
||||
use-latest-callback "^0.2.3"
|
||||
|
||||
"@react-navigation/routers@^6.1.9":
|
||||
version "6.1.9"
|
||||
resolved "https://registry.yarnpkg.com/@react-navigation/routers/-/routers-6.1.9.tgz#73f5481a15a38e36592a0afa13c3c064b9f90bed"
|
||||
integrity sha512-lTM8gSFHSfkJvQkxacGM6VJtBt61ip2XO54aNfswD+KMw6eeZ4oehl7m0me3CR9hnDE4+60iAZR8sAhvCiI3NA==
|
||||
"@react-navigation/routers@^7.4.0":
|
||||
version "7.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@react-navigation/routers/-/routers-7.4.0.tgz#5bace799713ac163310c18711b98dfbe418c6b36"
|
||||
integrity sha512-th5THnuWKJlmr7GGHiicy979di11ycDWub9iIXbEDvQwmwmsRzppmVbfs2nD8bC/MgyMgqWu/gxfys+HqN+kcw==
|
||||
dependencies:
|
||||
nanoid "^3.1.23"
|
||||
nanoid "^3.3.11"
|
||||
|
||||
"@remirror/core-constants@3.0.0":
|
||||
version "3.0.0"
|
||||
@@ -14962,11 +14966,16 @@ mz@^2.7.0:
|
||||
object-assign "^4.0.1"
|
||||
thenify-all "^1.0.0"
|
||||
|
||||
nanoid@^3.1.23, nanoid@^3.3.1, nanoid@^3.3.6:
|
||||
nanoid@^3.3.1, nanoid@^3.3.6:
|
||||
version "3.3.6"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c"
|
||||
integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==
|
||||
|
||||
nanoid@^3.3.11:
|
||||
version "3.3.11"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b"
|
||||
integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==
|
||||
|
||||
nanoid@^3.3.7:
|
||||
version "3.3.7"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8"
|
||||
@@ -16727,12 +16736,12 @@ react-image-crop@^11.0.7:
|
||||
resolved "https://registry.yarnpkg.com/react-image-crop/-/react-image-crop-11.0.7.tgz#25f3d37ccbb65a05d19d23b4740a5912835c741e"
|
||||
integrity sha512-ZciKWHDYzmm366JDL18CbrVyjnjH0ojufGDmScfS4ZUqLHg4nm6ATY+K62C75W4ZRNt4Ii+tX0bSjNk9LQ2xzQ==
|
||||
|
||||
react-is@19, react-is@^19.0.0:
|
||||
react-is@19, react-is@^19.0.0, react-is@^19.1.0:
|
||||
version "19.1.0"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-19.1.0.tgz#805bce321546b7e14c084989c77022351bbdd11b"
|
||||
integrity sha512-Oe56aUPnkHyyDxxkvqtd7KkdQP5uIUfHxd5XTb3wE9d/kRnZLmKbDB0GWk919tdQ+mxxPtG6EAs6RMT6i1qtHg==
|
||||
|
||||
react-is@^16.13.0, react-is@^16.13.1, react-is@^16.7.0:
|
||||
react-is@^16.13.1, react-is@^16.7.0:
|
||||
version "16.13.1"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
||||
@@ -16764,6 +16773,13 @@ react-native-dotenv@^3.4.11:
|
||||
dependencies:
|
||||
dotenv "^16.4.5"
|
||||
|
||||
react-native-drawer-layout@^4.1.10:
|
||||
version "4.1.10"
|
||||
resolved "https://registry.yarnpkg.com/react-native-drawer-layout/-/react-native-drawer-layout-4.1.10.tgz#9007cb747767ca8e1c9c3337671ad35ed95ad4d9"
|
||||
integrity sha512-wejQo0F+EffCkOkRh+DP6ENWMB+aWEHkXV8Pd564PmtoySZLUsV/ksYrh/mrufh7T7EuvGT8+fNHz7mMRYftWg==
|
||||
dependencies:
|
||||
use-latest-callback "^0.2.3"
|
||||
|
||||
react-native-drawer-layout@^4.1.6:
|
||||
version "4.1.7"
|
||||
resolved "https://registry.yarnpkg.com/react-native-drawer-layout/-/react-native-drawer-layout-4.1.7.tgz#1c741c9bf9c739d6672201692e4ba4839ca0c8ff"
|
||||
@@ -16806,7 +16822,7 @@ react-native-ios-context-menu@^1.15.3:
|
||||
dependencies:
|
||||
"@dominicstop/ts-event-emitter" "^1.1.0"
|
||||
|
||||
react-native-is-edge-to-edge@1.1.7:
|
||||
react-native-is-edge-to-edge@1.1.7, react-native-is-edge-to-edge@^1.1.7:
|
||||
version "1.1.7"
|
||||
resolved "https://registry.yarnpkg.com/react-native-is-edge-to-edge/-/react-native-is-edge-to-edge-1.1.7.tgz#28947688f9fafd584e73a4f935ea9603bd9b1939"
|
||||
integrity sha512-EH6i7E8epJGIcu7KpfXYXiV2JFIYITtq+rVS8uEb+92naMRBdxhTuS8Wn2Q7j9sqyO0B+Xbaaf9VdipIAmGW4w==
|
||||
@@ -16875,12 +16891,13 @@ react-native-safe-area-context@5.4.0:
|
||||
resolved "https://registry.yarnpkg.com/react-native-safe-area-context/-/react-native-safe-area-context-5.4.0.tgz#04b51940408c114f75628a12a93569d30c525454"
|
||||
integrity sha512-JaEThVyJcLhA+vU0NU8bZ0a1ih6GiF4faZ+ArZLqpYbL6j7R3caRqj+mE3lEtKCuHgwjLg3bCxLL1GPUJZVqUA==
|
||||
|
||||
react-native-screens@~4.10.0:
|
||||
version "4.10.0"
|
||||
resolved "https://registry.yarnpkg.com/react-native-screens/-/react-native-screens-4.10.0.tgz#40634aead590c6b7034ded6a9f92465d1d611906"
|
||||
integrity sha512-Tw21NGuXm3PbiUGtZd0AnXirUixaAbPXDjNR0baBH7/WJDaDTTELLcQ7QRXuqAWbmr/EVCrKj1348ei1KFIr8A==
|
||||
react-native-screens@^4.11.1:
|
||||
version "4.11.1"
|
||||
resolved "https://registry.yarnpkg.com/react-native-screens/-/react-native-screens-4.11.1.tgz#7d0f3d313d8ddc1e55437c5e038f15f8805dc991"
|
||||
integrity sha512-F0zOzRVa3ptZfLpD0J8ROdo+y1fEPw+VBFq1MTY/iyDu08al7qFUO5hLMd+EYMda5VXGaTFCa8q7bOppUszhJw==
|
||||
dependencies:
|
||||
react-freeze "^1.0.0"
|
||||
react-native-is-edge-to-edge "^1.1.7"
|
||||
warn-once "^0.1.0"
|
||||
|
||||
react-native-svg@15.11.2:
|
||||
@@ -19388,11 +19405,6 @@ use-isomorphic-layout-effect@^1.1.1:
|
||||
resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz#497cefb13d863d687b08477d9e5a164ad8c1a6fb"
|
||||
integrity sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==
|
||||
|
||||
use-latest-callback@^0.1.9:
|
||||
version "0.1.9"
|
||||
resolved "https://registry.yarnpkg.com/use-latest-callback/-/use-latest-callback-0.1.9.tgz#10191dc54257e65a8e52322127643a8940271e2a"
|
||||
integrity sha512-CL/29uS74AwreI/f2oz2hLTW7ZqVeV5+gxFeGudzQrgkCytrHw33G4KbnQOrRlAEzzAFXi7dDLMC9zhWcVpzmw==
|
||||
|
||||
use-latest-callback@^0.2.3:
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/use-latest-callback/-/use-latest-callback-0.2.3.tgz#2d644d3063040b9bc2d4c55bb525a13ae3de9e16"
|
||||
@@ -19426,6 +19438,11 @@ use-sync-external-store@^1.2.2:
|
||||
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz#c3b6390f3a30eba13200d2302dcdf1e7b57b2ef9"
|
||||
integrity sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==
|
||||
|
||||
use-sync-external-store@^1.5.0:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz#55122e2a3edd2a6c106174c27485e0fd59bcfca0"
|
||||
integrity sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==
|
||||
|
||||
util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
@@ -19527,7 +19544,7 @@ walker@^1.0.7, walker@^1.0.8:
|
||||
dependencies:
|
||||
makeerror "1.0.12"
|
||||
|
||||
warn-once@0.1.1, warn-once@^0.1.0:
|
||||
warn-once@0.1.1, warn-once@^0.1.0, warn-once@^0.1.1:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/warn-once/-/warn-once-0.1.1.tgz#952088f4fb56896e73fd4e6a3767272a3fccce43"
|
||||
integrity sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q==
|
||||
|
||||
Reference in New Issue
Block a user