Fix React Rules violations, enable strict lint
This commit is contained in:
+3
-1
@@ -1,3 +1,5 @@
|
|||||||
|
const reactCompilerConfig = require('./react-compiler.config.js')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
root: true,
|
root: true,
|
||||||
extends: [
|
extends: [
|
||||||
@@ -79,7 +81,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
'simple-import-sort/exports': 'error',
|
'simple-import-sort/exports': 'error',
|
||||||
'react-compiler/react-compiler': 'error',
|
'react-compiler/react-compiler': ['error', reactCompilerConfig],
|
||||||
'no-restricted-imports': [
|
'no-restricted-imports': [
|
||||||
'error',
|
'error',
|
||||||
{
|
{
|
||||||
|
|||||||
+3
-1
@@ -1,3 +1,5 @@
|
|||||||
|
const reactCompilerConfig = require('./react-compiler.config.js')
|
||||||
|
|
||||||
module.exports = function (api) {
|
module.exports = function (api) {
|
||||||
api.cache(true)
|
api.cache(true)
|
||||||
const isTestEnv = process.env.NODE_ENV === 'test'
|
const isTestEnv = process.env.NODE_ENV === 'test'
|
||||||
@@ -17,7 +19,7 @@ module.exports = function (api) {
|
|||||||
],
|
],
|
||||||
plugins: [
|
plugins: [
|
||||||
'macros',
|
'macros',
|
||||||
['babel-plugin-react-compiler', {target: '18'}],
|
['babel-plugin-react-compiler', reactCompilerConfig],
|
||||||
[
|
[
|
||||||
'module:react-native-dotenv',
|
'module:react-native-dotenv',
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
target: '18',
|
||||||
|
environment: {
|
||||||
|
enableTreatRefLikeIdentifiersAsRefs: true,
|
||||||
|
validateRefAccessDuringRender: false, // TODO: Make it `true`.
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -56,7 +56,6 @@ type Props = {
|
|||||||
const AnimatedLogo = Animated.createAnimatedComponent(Logo)
|
const AnimatedLogo = Animated.createAnimatedComponent(Logo)
|
||||||
|
|
||||||
export function Splash(props: React.PropsWithChildren<Props>) {
|
export function Splash(props: React.PropsWithChildren<Props>) {
|
||||||
'use no memo'
|
|
||||||
const insets = useSafeAreaInsets()
|
const insets = useSafeAreaInsets()
|
||||||
const intro = useSharedValue(0)
|
const intro = useSharedValue(0)
|
||||||
const outroLogo = useSharedValue(0)
|
const outroLogo = useSharedValue(0)
|
||||||
|
|||||||
@@ -29,10 +29,10 @@ export function useDialogControl(): DialogOuterProps['control'] {
|
|||||||
const {activeDialogs} = useDialogStateContext()
|
const {activeDialogs} = useDialogStateContext()
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
activeDialogs.current.set(id, control)
|
const map = activeDialogs.current
|
||||||
|
map.set(id, control)
|
||||||
return () => {
|
return () => {
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
map.delete(id)
|
||||||
activeDialogs.current.delete(id)
|
|
||||||
}
|
}
|
||||||
}, [id, activeDialogs])
|
}, [id, activeDialogs])
|
||||||
|
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ function Inner({
|
|||||||
|
|
||||||
if (IS_DEV && typeof window !== 'undefined') {
|
if (IS_DEV && typeof window !== 'undefined') {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
// eslint-disable-next-line react-compiler/react-compiler
|
||||||
window.clearNuxDialog = (id: Nux) => {
|
window.clearNuxDialog = (id: Nux) => {
|
||||||
if (!IS_DEV || !id) return
|
if (!IS_DEV || !id) return
|
||||||
removeNuxs([id])
|
removeNuxs([id])
|
||||||
|
|||||||
@@ -68,6 +68,8 @@ export function ContentHider({
|
|||||||
if (hasAdultContentLabel) {
|
if (hasAdultContentLabel) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
// https://github.com/facebook/react/issues/31569
|
||||||
|
// eslint-disable-next-line react-compiler/react-compiler
|
||||||
hasAdultContentLabel = true
|
hasAdultContentLabel = true
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
import * as React from 'react'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper hook to run persistent timers on views
|
|
||||||
*/
|
|
||||||
export function useTimer(time: number, handler: () => void) {
|
|
||||||
const timer = React.useRef<undefined | NodeJS.Timeout>(undefined)
|
|
||||||
|
|
||||||
// function to restart the timer
|
|
||||||
const reset = React.useCallback(() => {
|
|
||||||
if (timer.current) {
|
|
||||||
clearTimeout(timer.current)
|
|
||||||
}
|
|
||||||
timer.current = setTimeout(handler, time)
|
|
||||||
}, [time, timer, handler])
|
|
||||||
|
|
||||||
// function to cancel the timer
|
|
||||||
const cancel = React.useCallback(() => {
|
|
||||||
if (timer.current) {
|
|
||||||
clearTimeout(timer.current)
|
|
||||||
timer.current = undefined
|
|
||||||
}
|
|
||||||
}, [timer])
|
|
||||||
|
|
||||||
// start the timer immediately
|
|
||||||
React.useEffect(() => {
|
|
||||||
reset()
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
return [reset, cancel]
|
|
||||||
}
|
|
||||||
@@ -9,20 +9,24 @@ if ('scrollRestoration' in history) {
|
|||||||
|
|
||||||
function createInitialScrollState() {
|
function createInitialScrollState() {
|
||||||
return {
|
return {
|
||||||
scrollYs: new Map(),
|
// Not used for rendering.
|
||||||
focusedKey: null as string | null,
|
// Treat it as a ref so that we can mutate it without upsetting the compiler.
|
||||||
|
current: {
|
||||||
|
scrollYs: new Map(),
|
||||||
|
focusedKey: null as string | null,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useWebScrollRestoration() {
|
export function useWebScrollRestoration() {
|
||||||
const [state] = useState(createInitialScrollState)
|
const [ref] = useState(createInitialScrollState)
|
||||||
const navigation = useNavigation()
|
const navigation = useNavigation()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
function onDispatch() {
|
function onDispatch() {
|
||||||
if (state.focusedKey) {
|
if (ref.current.focusedKey) {
|
||||||
// Remember where we were for later.
|
// Remember where we were for later.
|
||||||
state.scrollYs.set(state.focusedKey, window.scrollY)
|
ref.current.scrollYs.set(ref.current.focusedKey, window.scrollY)
|
||||||
// TODO: Strictly speaking, this is a leak. We never clean up.
|
// TODO: Strictly speaking, this is a leak. We never clean up.
|
||||||
// This is because I'm not sure when it's appropriate to clean it up.
|
// This is because I'm not sure when it's appropriate to clean it up.
|
||||||
// It doesn't seem like popstate is enough because it can still Forward-Back again.
|
// It doesn't seem like popstate is enough because it can still Forward-Back again.
|
||||||
@@ -36,17 +40,17 @@ export function useWebScrollRestoration() {
|
|||||||
return () => {
|
return () => {
|
||||||
navigation.removeListener('__unsafe_action__' as any, onDispatch)
|
navigation.removeListener('__unsafe_action__' as any, onDispatch)
|
||||||
}
|
}
|
||||||
}, [state, navigation])
|
}, [ref, navigation])
|
||||||
|
|
||||||
const screenListeners = useMemo(
|
const screenListeners = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
focus(e: EventArg<'focus', boolean | undefined, unknown>) {
|
focus(e: EventArg<'focus', boolean | undefined, unknown>) {
|
||||||
const scrollY = state.scrollYs.get(e.target) ?? 0
|
const scrollY = ref.current.scrollYs.get(e.target) ?? 0
|
||||||
window.scrollTo(0, scrollY)
|
window.scrollTo(0, scrollY)
|
||||||
state.focusedKey = e.target ?? null
|
ref.current.focusedKey = e.target ?? null
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
[state],
|
[ref],
|
||||||
)
|
)
|
||||||
return screenListeners
|
return screenListeners
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,6 +80,8 @@ export function Signup({onPressBack}: {onPressBack: () => void}) {
|
|||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (state.pendingSubmit) {
|
if (state.pendingSubmit) {
|
||||||
if (!state.pendingSubmit.mutableProcessed) {
|
if (!state.pendingSubmit.mutableProcessed) {
|
||||||
|
// FIXME
|
||||||
|
// eslint-disable-next-line react-compiler/react-compiler
|
||||||
state.pendingSubmit.mutableProcessed = true
|
state.pendingSubmit.mutableProcessed = true
|
||||||
submit(state, dispatch)
|
submit(state, dispatch)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -173,6 +173,8 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
|||||||
return wasActive
|
return wasActive
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// FIXME
|
||||||
|
// eslint-disable-next-line react-compiler/react-compiler
|
||||||
unstable__openModal = openModal
|
unstable__openModal = openModal
|
||||||
unstable__closeModal = closeModal
|
unstable__closeModal = closeModal
|
||||||
|
|
||||||
|
|||||||
@@ -18,14 +18,14 @@ const RQKEY_ROOT = 'actor-autocomplete'
|
|||||||
export const RQKEY = (prefix: string) => [RQKEY_ROOT, prefix]
|
export const RQKEY = (prefix: string) => [RQKEY_ROOT, prefix]
|
||||||
|
|
||||||
export function useActorAutocompleteQuery(
|
export function useActorAutocompleteQuery(
|
||||||
prefix: string,
|
rawPrefix: string,
|
||||||
maintainData?: boolean,
|
maintainData?: boolean,
|
||||||
limit?: number,
|
limit?: number,
|
||||||
) {
|
) {
|
||||||
const moderationOpts = useModerationOpts()
|
const moderationOpts = useModerationOpts()
|
||||||
const agent = useAgent()
|
const agent = useAgent()
|
||||||
|
|
||||||
prefix = prefix.toLowerCase().trim()
|
let prefix = rawPrefix.toLowerCase().trim()
|
||||||
if (prefix.endsWith('.')) {
|
if (prefix.endsWith('.')) {
|
||||||
// Going from "foo" to "foo." should not clear matches.
|
// Going from "foo" to "foo." should not clear matches.
|
||||||
prefix = prefix.slice(0, -1)
|
prefix = prefix.slice(0, -1)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {useQueryClient} from '@tanstack/react-query'
|
|||||||
import EventEmitter from 'eventemitter3'
|
import EventEmitter from 'eventemitter3'
|
||||||
|
|
||||||
import BroadcastChannel from '#/lib/broadcast'
|
import BroadcastChannel from '#/lib/broadcast'
|
||||||
|
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
||||||
import {resetBadgeCount} from '#/lib/notifications/notifications'
|
import {resetBadgeCount} from '#/lib/notifications/notifications'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {useAgent, useSession} from '#/state/session'
|
import {useAgent, useSession} from '#/state/session'
|
||||||
@@ -50,7 +51,6 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
|||||||
|
|
||||||
const [numUnread, setNumUnread] = React.useState('')
|
const [numUnread, setNumUnread] = React.useState('')
|
||||||
|
|
||||||
const checkUnreadRef = React.useRef<ApiContext['checkUnread'] | null>(null)
|
|
||||||
const cacheRef = React.useRef<CachedFeedPage>({
|
const cacheRef = React.useRef<CachedFeedPage>({
|
||||||
usableInFeed: false,
|
usableInFeed: false,
|
||||||
syncedAt: new Date(),
|
syncedAt: new Date(),
|
||||||
@@ -70,19 +70,6 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
|||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
// periodic sync
|
|
||||||
React.useEffect(() => {
|
|
||||||
if (!hasSession || !checkUnreadRef.current) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
checkUnreadRef.current() // fire on init
|
|
||||||
const interval = setInterval(
|
|
||||||
() => checkUnreadRef.current?.({isPoll: true}),
|
|
||||||
UPDATE_INTERVAL,
|
|
||||||
)
|
|
||||||
return () => clearInterval(interval)
|
|
||||||
}, [hasSession])
|
|
||||||
|
|
||||||
// listen for broadcasts
|
// listen for broadcasts
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const listener = ({data}: MessageEvent) => {
|
const listener = ({data}: MessageEvent) => {
|
||||||
@@ -190,7 +177,21 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}, [setNumUnread, queryClient, moderationOpts, agent])
|
}, [setNumUnread, queryClient, moderationOpts, agent])
|
||||||
checkUnreadRef.current = api.checkUnread
|
|
||||||
|
const checkUnread = useNonReactiveCallback(api.checkUnread)
|
||||||
|
|
||||||
|
// periodic sync
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (!hasSession) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
checkUnread() // fire on init
|
||||||
|
const interval = setInterval(
|
||||||
|
() => checkUnread({isPoll: true}),
|
||||||
|
UPDATE_INTERVAL,
|
||||||
|
)
|
||||||
|
return () => clearInterval(interval)
|
||||||
|
}, [hasSession, checkUnread])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<stateContext.Provider value={numUnread}>
|
<stateContext.Provider value={numUnread}>
|
||||||
|
|||||||
@@ -187,6 +187,8 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
|||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (state.needsPersist) {
|
if (state.needsPersist) {
|
||||||
|
// FIXME
|
||||||
|
// eslint-disable-next-line react-compiler/react-compiler
|
||||||
state.needsPersist = false
|
state.needsPersist = false
|
||||||
const persistedData = {
|
const persistedData = {
|
||||||
accounts: state.accounts,
|
accounts: state.accounts,
|
||||||
|
|||||||
@@ -61,14 +61,17 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
|||||||
const {mutateAsync, variables, isPending} =
|
const {mutateAsync, variables, isPending} =
|
||||||
useSetActiveProgressGuideMutation()
|
useSetActiveProgressGuideMutation()
|
||||||
|
|
||||||
const activeProgressGuide = (
|
let activeProgressGuide = (
|
||||||
isPending ? variables : preferences?.bskyAppState?.activeProgressGuide
|
isPending ? variables : preferences?.bskyAppState?.activeProgressGuide
|
||||||
) as ProgressGuide
|
) as ProgressGuide
|
||||||
|
|
||||||
// ensure the unspecced attributes have the correct types
|
// ensure the unspecced attributes have the correct types
|
||||||
if (activeProgressGuide?.guide === 'like-10-and-follow-7') {
|
if (activeProgressGuide?.guide === 'like-10-and-follow-7') {
|
||||||
activeProgressGuide.numLikes = Number(activeProgressGuide.numLikes) || 0
|
activeProgressGuide = {
|
||||||
activeProgressGuide.numFollows = Number(activeProgressGuide.numFollows) || 0
|
...activeProgressGuide,
|
||||||
|
numLikes: Number(activeProgressGuide.numLikes) || 0,
|
||||||
|
numFollows: Number(activeProgressGuide.numFollows) || 0,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const [localGuideState, setLocalGuideState] =
|
const [localGuideState, setLocalGuideState] =
|
||||||
|
|||||||
@@ -303,6 +303,8 @@ export const TextInput = React.forwardRef(function TextInputImpl(
|
|||||||
React.useLayoutEffect(() => {
|
React.useLayoutEffect(() => {
|
||||||
let node = editor?.view.dom
|
let node = editor?.view.dom
|
||||||
if (node) {
|
if (node) {
|
||||||
|
// FIXME
|
||||||
|
// eslint-disable-next-line react-compiler/react-compiler
|
||||||
node.style.minHeight = webForceMinHeight ? '140px' : ''
|
node.style.minHeight = webForceMinHeight ? '140px' : ''
|
||||||
}
|
}
|
||||||
}, [editor, webForceMinHeight])
|
}, [editor, webForceMinHeight])
|
||||||
|
|||||||
@@ -87,7 +87,6 @@ export default function ImageViewRoot({
|
|||||||
onPressSave: (uri: string) => void
|
onPressSave: (uri: string) => void
|
||||||
onPressShare: (uri: string) => void
|
onPressShare: (uri: string) => void
|
||||||
}) {
|
}) {
|
||||||
'use no memo'
|
|
||||||
const ref = useAnimatedRef<View>()
|
const ref = useAnimatedRef<View>()
|
||||||
const [activeLightbox, setActiveLightbox] = useState(nextLightbox)
|
const [activeLightbox, setActiveLightbox] = useState(nextLightbox)
|
||||||
const openProgress = useSharedValue(0)
|
const openProgress = useSharedValue(0)
|
||||||
|
|||||||
+67
-56
@@ -129,15 +129,15 @@ export const Link = memo(function Link({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let dataSet = props.dataSet
|
||||||
if (anchorNoUnderline) {
|
if (anchorNoUnderline) {
|
||||||
// @ts-ignore web only -prf
|
// @ts-ignore web only -prf
|
||||||
props.dataSet = props.dataSet || {}
|
dataSet = {...dataSet, noUnderline: 1}
|
||||||
// @ts-ignore web only -prf
|
|
||||||
props.dataSet.noUnderline = 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (title && !props.accessibilityLabel) {
|
let accessibilityLabel = props.accessibilityLabel
|
||||||
props.accessibilityLabel = title
|
if (title && !accessibilityLabel) {
|
||||||
|
accessibilityLabel = title
|
||||||
}
|
}
|
||||||
|
|
||||||
const Com = props.hoverStyle ? PressableWithHover : Pressable
|
const Com = props.hoverStyle ? PressableWithHover : Pressable
|
||||||
@@ -150,7 +150,11 @@ export const Link = memo(function Link({
|
|||||||
accessibilityRole="link"
|
accessibilityRole="link"
|
||||||
// @ts-ignore web only -prf
|
// @ts-ignore web only -prf
|
||||||
href={anchorHref}
|
href={anchorHref}
|
||||||
{...props}>
|
{...props}
|
||||||
|
// @ts-ignore web only
|
||||||
|
dataSet={dataSet}
|
||||||
|
accessibilityLabel={accessibilityLabel}
|
||||||
|
accessibilityHint={props.accessibilityHint}>
|
||||||
{children ? children : <Text>{title || 'link'}</Text>}
|
{children ? children : <Text>{title || 'link'}</Text>}
|
||||||
</Com>
|
</Com>
|
||||||
)
|
)
|
||||||
@@ -164,7 +168,7 @@ export const TextLink = memo(function TextLink({
|
|||||||
text,
|
text,
|
||||||
numberOfLines,
|
numberOfLines,
|
||||||
lineHeight,
|
lineHeight,
|
||||||
dataSet,
|
dataSet: rawDataSet,
|
||||||
title,
|
title,
|
||||||
onPress,
|
onPress,
|
||||||
onBeforePress,
|
onBeforePress,
|
||||||
@@ -187,7 +191,7 @@ export const TextLink = memo(function TextLink({
|
|||||||
anchorNoUnderline?: boolean
|
anchorNoUnderline?: boolean
|
||||||
onBeforePress?: () => void
|
onBeforePress?: () => void
|
||||||
} & TextProps) {
|
} & TextProps) {
|
||||||
const {...props} = useLinkProps({to: sanitizeUrl(href)})
|
let {...props} = useLinkProps({to: sanitizeUrl(href)})
|
||||||
const navigation = useNavigationDeduped()
|
const navigation = useNavigationDeduped()
|
||||||
const {openModal, closeModal} = useModalControls()
|
const {openModal, closeModal} = useModalControls()
|
||||||
const openLink = useOpenLink()
|
const openLink = useOpenLink()
|
||||||
@@ -196,61 +200,68 @@ export const TextLink = memo(function TextLink({
|
|||||||
console.error('Unable to detect mismatching label')
|
console.error('Unable to detect mismatching label')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let dataSet = rawDataSet
|
||||||
if (anchorNoUnderline) {
|
if (anchorNoUnderline) {
|
||||||
dataSet = dataSet ?? {}
|
dataSet = {
|
||||||
dataSet.noUnderline = 1
|
...dataSet,
|
||||||
|
noUnderline: 1,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
props.onPress = React.useCallback(
|
props = {
|
||||||
(e?: Event) => {
|
...props,
|
||||||
const requiresWarning =
|
onPress: React.useCallback(
|
||||||
!disableMismatchWarning &&
|
(e?: Event) => {
|
||||||
linkRequiresWarning(href, typeof text === 'string' ? text : '')
|
const requiresWarning =
|
||||||
if (requiresWarning) {
|
!disableMismatchWarning &&
|
||||||
e?.preventDefault?.()
|
linkRequiresWarning(href, typeof text === 'string' ? text : '')
|
||||||
openModal({
|
if (requiresWarning) {
|
||||||
name: 'link-warning',
|
e?.preventDefault?.()
|
||||||
text: typeof text === 'string' ? text : '',
|
openModal({
|
||||||
href,
|
name: 'link-warning',
|
||||||
})
|
text: typeof text === 'string' ? text : '',
|
||||||
}
|
href,
|
||||||
if (
|
})
|
||||||
isWeb &&
|
}
|
||||||
href !== '#' &&
|
if (
|
||||||
e != null &&
|
isWeb &&
|
||||||
isModifiedEvent(e as React.MouseEvent)
|
href !== '#' &&
|
||||||
) {
|
e != null &&
|
||||||
// Let the browser handle opening in new tab etc.
|
isModifiedEvent(e as React.MouseEvent)
|
||||||
return
|
) {
|
||||||
}
|
// Let the browser handle opening in new tab etc.
|
||||||
onBeforePress?.()
|
return
|
||||||
if (onPress) {
|
}
|
||||||
e?.preventDefault?.()
|
onBeforePress?.()
|
||||||
// @ts-ignore function signature differs by platform -prf
|
if (onPress) {
|
||||||
return onPress()
|
e?.preventDefault?.()
|
||||||
}
|
// @ts-ignore function signature differs by platform -prf
|
||||||
return onPressInner(
|
return onPress()
|
||||||
|
}
|
||||||
|
return onPressInner(
|
||||||
|
closeModal,
|
||||||
|
navigation,
|
||||||
|
sanitizeUrl(href),
|
||||||
|
navigationAction,
|
||||||
|
openLink,
|
||||||
|
e,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
[
|
||||||
|
onBeforePress,
|
||||||
|
onPress,
|
||||||
closeModal,
|
closeModal,
|
||||||
|
openModal,
|
||||||
navigation,
|
navigation,
|
||||||
sanitizeUrl(href),
|
href,
|
||||||
|
text,
|
||||||
|
disableMismatchWarning,
|
||||||
navigationAction,
|
navigationAction,
|
||||||
openLink,
|
openLink,
|
||||||
e,
|
],
|
||||||
)
|
),
|
||||||
},
|
}
|
||||||
[
|
|
||||||
onBeforePress,
|
|
||||||
onPress,
|
|
||||||
closeModal,
|
|
||||||
openModal,
|
|
||||||
navigation,
|
|
||||||
href,
|
|
||||||
text,
|
|
||||||
disableMismatchWarning,
|
|
||||||
navigationAction,
|
|
||||||
openLink,
|
|
||||||
],
|
|
||||||
)
|
|
||||||
const hrefAttrs = useMemo(() => {
|
const hrefAttrs = useMemo(() => {
|
||||||
const isExternal = isExternalUrl(href)
|
const isExternal = isExternalUrl(href)
|
||||||
if (isExternal) {
|
if (isExternal) {
|
||||||
|
|||||||
@@ -96,6 +96,8 @@ export const FlatList_INTERNAL = React.forwardRef(function FlatListImpl<ItemT>(
|
|||||||
paddingTop: Math.abs(contentOffset.y),
|
paddingTop: Math.abs(contentOffset.y),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// @ts-ignore web only -prf
|
||||||
|
let dataSet = props.dataSet
|
||||||
if (desktopFixedHeight) {
|
if (desktopFixedHeight) {
|
||||||
if (typeof desktopFixedHeight === 'number') {
|
if (typeof desktopFixedHeight === 'number') {
|
||||||
// @ts-ignore Web only -prf
|
// @ts-ignore Web only -prf
|
||||||
@@ -114,10 +116,10 @@ export const FlatList_INTERNAL = React.forwardRef(function FlatListImpl<ItemT>(
|
|||||||
// around this, we set data-stable-gutters which can then be
|
// around this, we set data-stable-gutters which can then be
|
||||||
// styled in our external CSS.
|
// styled in our external CSS.
|
||||||
// -prf
|
// -prf
|
||||||
// @ts-ignore web only -prf
|
dataSet = {
|
||||||
props.dataSet = props.dataSet || {}
|
...dataSet,
|
||||||
// @ts-ignore web only -prf
|
stableGutters: '1',
|
||||||
props.dataSet.stableGutters = '1'
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
@@ -131,6 +133,8 @@ export const FlatList_INTERNAL = React.forwardRef(function FlatListImpl<ItemT>(
|
|||||||
style={style}
|
style={style}
|
||||||
contentOffset={contentOffset}
|
contentOffset={contentOffset}
|
||||||
{...props}
|
{...props}
|
||||||
|
// @ts-ignore web only -prf
|
||||||
|
dataSet={dataSet}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user