Create codemod for addressing ESLint warnings (#10032)
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
import {useEffect, useState} from 'react'
|
||||
import {Pressable, View} from 'react-native'
|
||||
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
@@ -33,9 +33,9 @@ export const SplashScreen = ({
|
||||
const {_} = useLingui()
|
||||
const t = useTheme()
|
||||
const {isTabletOrMobile: IS_WEB_MOBILE} = useWebMediaQueries()
|
||||
const [showClipOverlay, setShowClipOverlay] = React.useState(false)
|
||||
const [showClipOverlay, setShowClipOverlay] = useState(false)
|
||||
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
const getParams = new URLSearchParams(window.location.search)
|
||||
const clip = getParams.get('clip')
|
||||
if (clip === 'true') {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import {View} from 'react-native'
|
||||
import type React from 'react'
|
||||
|
||||
import {MAX_ALT_TEXT} from '#/lib/constants'
|
||||
import {CharProgress} from '#/view/com/composer/char-progress/CharProgress'
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import React, {
|
||||
import {
|
||||
Fragment,
|
||||
memo,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useImperativeHandle,
|
||||
@@ -299,7 +301,7 @@ export const ComposePost = ({
|
||||
[activePost.id],
|
||||
)
|
||||
|
||||
const selectVideo = React.useCallback(
|
||||
const selectVideo = useCallback(
|
||||
(postId: string, asset: ImagePickerAsset) => {
|
||||
const abortController = new AbortController()
|
||||
composerDispatch({
|
||||
@@ -485,7 +487,7 @@ export const ComposePost = ({
|
||||
[_, agent, currentDid, composerDispatch],
|
||||
)
|
||||
|
||||
const handleSelectDraft = React.useCallback(
|
||||
const handleSelectDraft = useCallback(
|
||||
async (draftSummary: DraftSummary) => {
|
||||
logger.debug('loading draft for editing', {
|
||||
draftId: draftSummary.id,
|
||||
@@ -553,7 +555,7 @@ export const ComposePost = ({
|
||||
revokeAllMediaUrls()
|
||||
}, [closeComposer, queryClient])
|
||||
|
||||
const getDraftSaveError = React.useCallback(
|
||||
const getDraftSaveError = useCallback(
|
||||
(e: unknown): string => {
|
||||
if (e instanceof AppBskyDraftCreateDraft.DraftLimitReachedError) {
|
||||
return _(msg`You've reached the maximum number of drafts`)
|
||||
@@ -563,7 +565,7 @@ export const ComposePost = ({
|
||||
[_],
|
||||
)
|
||||
|
||||
const validateDraftTextOrError = React.useCallback((): boolean => {
|
||||
const validateDraftTextOrError = useCallback((): boolean => {
|
||||
const tooLong = composerState.thread.posts.some(
|
||||
post => post.richtext.graphemeLength > MAX_DRAFT_GRAPHEME_LENGTH,
|
||||
)
|
||||
@@ -578,7 +580,7 @@ export const ComposePost = ({
|
||||
return true
|
||||
}, [composerState.thread.posts, _])
|
||||
|
||||
const handleSaveDraft = React.useCallback(async () => {
|
||||
const handleSaveDraft = useCallback(async () => {
|
||||
setError('')
|
||||
if (!validateDraftTextOrError()) {
|
||||
return
|
||||
@@ -621,7 +623,7 @@ export const ComposePost = ({
|
||||
])
|
||||
|
||||
// Save without closing - for use by DraftsButton
|
||||
const saveCurrentDraft = React.useCallback(async (): Promise<{
|
||||
const saveCurrentDraft = useCallback(async (): Promise<{
|
||||
success: boolean
|
||||
}> => {
|
||||
setError('')
|
||||
@@ -648,7 +650,7 @@ export const ComposePost = ({
|
||||
])
|
||||
|
||||
// Handle discard action - fires metric and closes composer
|
||||
const handleDiscard = React.useCallback(() => {
|
||||
const handleDiscard = useCallback(() => {
|
||||
const posts = thread.posts
|
||||
const hasContent = posts.some(
|
||||
post =>
|
||||
@@ -665,7 +667,7 @@ export const ComposePost = ({
|
||||
}, [thread.posts, ax, onClose])
|
||||
|
||||
// Check if composer is empty (no content to save)
|
||||
const isComposerEmpty = React.useMemo(() => {
|
||||
const isComposerEmpty = useMemo(() => {
|
||||
// Has multiple posts means it's not empty
|
||||
if (thread.posts.length > 1) return false
|
||||
|
||||
@@ -683,7 +685,7 @@ export const ComposePost = ({
|
||||
}, [thread.posts])
|
||||
|
||||
// Clear the composer (discard current content)
|
||||
const handleClearComposer = React.useCallback(() => {
|
||||
const handleClearComposer = useCallback(() => {
|
||||
composerDispatch({
|
||||
type: 'clear',
|
||||
initInteractionSettings: preferences?.postInteractionSettings,
|
||||
@@ -794,7 +796,7 @@ export const ComposePost = ({
|
||||
),
|
||||
)
|
||||
|
||||
const onPressPublish = React.useCallback(async () => {
|
||||
const onPressPublish = useCallback(async () => {
|
||||
if (isPublishing) {
|
||||
return
|
||||
}
|
||||
@@ -1015,7 +1017,7 @@ export const ComposePost = ({
|
||||
onPressPublish()
|
||||
})
|
||||
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
if (publishOnUpload) {
|
||||
let erroredVideos = 0
|
||||
let uploadingVideos = 0
|
||||
@@ -1181,7 +1183,7 @@ export const ComposePost = ({
|
||||
onLayout={onScrollViewLayout}>
|
||||
{replyTo ? <ComposerReplyTo replyTo={replyTo} /> : undefined}
|
||||
{thread.posts.map((post, index) => (
|
||||
<React.Fragment key={post.id + (composerState.draftId ?? '')}>
|
||||
<Fragment key={post.id + (composerState.draftId ?? '')}>
|
||||
<ComposerPost
|
||||
post={post}
|
||||
dispatch={composerDispatch}
|
||||
@@ -1201,7 +1203,7 @@ export const ComposePost = ({
|
||||
{IS_WEBFooterSticky && post.id === activePost.id && (
|
||||
<View style={styles.stickyFooterWeb}>{footer}</View>
|
||||
)}
|
||||
</React.Fragment>
|
||||
</Fragment>
|
||||
))}
|
||||
</Animated.ScrollView>
|
||||
{!IS_WEBFooterSticky && footer}
|
||||
@@ -1273,7 +1275,7 @@ export const ComposePost = ({
|
||||
)
|
||||
}
|
||||
|
||||
let ComposerPost = React.memo(function ComposerPost({
|
||||
let ComposerPost = memo(function ComposerPost({
|
||||
post,
|
||||
dispatch,
|
||||
textInput,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {View} from 'react-native'
|
||||
import {KeyboardStickyView} from 'react-native-keyboard-controller'
|
||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||
import type React from 'react'
|
||||
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {IS_WEB} from '#/env'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, {useState} from 'react'
|
||||
import {memo, useMemo, useState} from 'react'
|
||||
import {
|
||||
findNodeHandle,
|
||||
type ImageStyle,
|
||||
@@ -37,7 +37,7 @@ interface GalleryProps {
|
||||
}
|
||||
|
||||
export let Gallery = (props: GalleryProps): React.ReactNode => {
|
||||
const [containerInfo, setContainerInfo] = React.useState<Dimensions>()
|
||||
const [containerInfo, setContainerInfo] = useState<Dimensions>()
|
||||
|
||||
const onLayout = (evt: LayoutChangeEvent) => {
|
||||
const {width, height} = evt.nativeEvent.layout
|
||||
@@ -55,7 +55,7 @@ export let Gallery = (props: GalleryProps): React.ReactNode => {
|
||||
</View>
|
||||
)
|
||||
}
|
||||
Gallery = React.memo(Gallery)
|
||||
Gallery = memo(Gallery)
|
||||
|
||||
interface GalleryInnerProps extends GalleryProps {
|
||||
containerInfo: Dimensions
|
||||
@@ -64,39 +64,38 @@ interface GalleryInnerProps extends GalleryProps {
|
||||
const GalleryInner = ({images, containerInfo, dispatch}: GalleryInnerProps) => {
|
||||
const {isMobile} = useWebMediaQueries()
|
||||
|
||||
const {altTextControlStyle, imageControlsStyle, imageStyle} =
|
||||
React.useMemo(() => {
|
||||
const side =
|
||||
images.length === 1
|
||||
? 250
|
||||
: (containerInfo.width - IMAGE_GAP * (images.length - 1)) /
|
||||
images.length
|
||||
const {altTextControlStyle, imageControlsStyle, imageStyle} = useMemo(() => {
|
||||
const side =
|
||||
images.length === 1
|
||||
? 250
|
||||
: (containerInfo.width - IMAGE_GAP * (images.length - 1)) /
|
||||
images.length
|
||||
|
||||
const isOverflow = isMobile && images.length > 2
|
||||
const isOverflow = isMobile && images.length > 2
|
||||
|
||||
return {
|
||||
altTextControlStyle: isOverflow
|
||||
? {left: 4, bottom: 4}
|
||||
return {
|
||||
altTextControlStyle: isOverflow
|
||||
? {left: 4, bottom: 4}
|
||||
: !isMobile && images.length < 3
|
||||
? {left: 8, top: 8}
|
||||
: {left: 4, top: 4},
|
||||
imageControlsStyle: {
|
||||
display: 'flex' as const,
|
||||
flexDirection: 'row' as const,
|
||||
position: 'absolute' as const,
|
||||
...(isOverflow
|
||||
? {top: 4, right: 4, gap: 4}
|
||||
: !isMobile && images.length < 3
|
||||
? {left: 8, top: 8}
|
||||
: {left: 4, top: 4},
|
||||
imageControlsStyle: {
|
||||
display: 'flex' as const,
|
||||
flexDirection: 'row' as const,
|
||||
position: 'absolute' as const,
|
||||
...(isOverflow
|
||||
? {top: 4, right: 4, gap: 4}
|
||||
: !isMobile && images.length < 3
|
||||
? {top: 8, right: 8, gap: 8}
|
||||
: {top: 4, right: 4, gap: 4}),
|
||||
zIndex: 1,
|
||||
},
|
||||
imageStyle: {
|
||||
height: side,
|
||||
width: side,
|
||||
},
|
||||
}
|
||||
}, [images.length, containerInfo, isMobile])
|
||||
? {top: 8, right: 8, gap: 8}
|
||||
: {top: 4, right: 4, gap: 4}),
|
||||
zIndex: 1,
|
||||
},
|
||||
imageStyle: {
|
||||
height: side,
|
||||
width: side,
|
||||
},
|
||||
}
|
||||
}, [images.length, containerInfo, isMobile])
|
||||
|
||||
return images.length !== 0 ? (
|
||||
<>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
import {useEffect, useMemo, useRef} from 'react'
|
||||
import {Pressable, useWindowDimensions, View} from 'react-native'
|
||||
import Picker from '@emoji-mart/react'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
@@ -52,9 +52,9 @@ export function EmojiPicker({state, close, pinToTop}: IProps) {
|
||||
const {_} = useLingui()
|
||||
const {height, width} = useWindowDimensions()
|
||||
|
||||
const isShiftDown = React.useRef(false)
|
||||
const isShiftDown = useRef(false)
|
||||
|
||||
const position = React.useMemo(() => {
|
||||
const position = useMemo(() => {
|
||||
if (pinToTop) {
|
||||
return {
|
||||
top: state.pos.top - PICKER_HEIGHT + HEIGHT_OFFSET - 10,
|
||||
@@ -86,7 +86,7 @@ export function EmojiPicker({state, close, pinToTop}: IProps) {
|
||||
}
|
||||
}, [state.pos, height, width, pinToTop])
|
||||
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
if (!state.isOpen) return
|
||||
|
||||
const onKeyDown = (e: KeyboardEvent) => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
import {useCallback} from 'react'
|
||||
import {init} from 'emoji-mart'
|
||||
|
||||
/**
|
||||
@@ -11,7 +11,7 @@ let loadRequested = false
|
||||
* {@link https://github.com/missive/emoji-mart/blob/16978d04a766eec6455e2e8bb21cd8dc0b3c7436/README.md?plain=1#L194}
|
||||
*/
|
||||
export function useWebPreloadEmoji({immediate}: {immediate?: boolean} = {}) {
|
||||
const preload = React.useCallback(async () => {
|
||||
const preload = useCallback(async () => {
|
||||
if (loadRequested) return
|
||||
loadRequested = true
|
||||
try {
|
||||
|
||||
@@ -3,7 +3,6 @@ import {View} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
import type React from 'react'
|
||||
|
||||
import {logger} from '#/logger'
|
||||
import * as Toast from '#/view/com/util/Toast'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
import {useCallback, useMemo} from 'react'
|
||||
import {useNavigation} from '@react-navigation/native'
|
||||
|
||||
import {type NavigationProp} from '#/lib/routes/types'
|
||||
@@ -19,7 +19,7 @@ export function HomeHeader(
|
||||
const {hasSession} = useSession()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
|
||||
const hasPinnedCustom = React.useMemo<boolean>(() => {
|
||||
const hasPinnedCustom = useMemo<boolean>(() => {
|
||||
if (!hasSession) return false
|
||||
return feeds.some(tab => {
|
||||
const isFollowing = tab.uri === 'following'
|
||||
@@ -27,7 +27,7 @@ export function HomeHeader(
|
||||
})
|
||||
}, [feeds, hasSession])
|
||||
|
||||
const items = React.useMemo(() => {
|
||||
const items = useMemo(() => {
|
||||
const pinnedNames = feeds.map(f => f.displayName)
|
||||
if (!hasPinnedCustom) {
|
||||
return pinnedNames.concat('Feeds ✨')
|
||||
@@ -35,11 +35,11 @@ export function HomeHeader(
|
||||
return pinnedNames
|
||||
}, [hasPinnedCustom, feeds])
|
||||
|
||||
const onPressFeedsLink = React.useCallback(() => {
|
||||
const onPressFeedsLink = useCallback(() => {
|
||||
navigation.navigate('Feeds')
|
||||
}, [navigation])
|
||||
|
||||
const onSelect = React.useCallback(
|
||||
const onSelect = useCallback(
|
||||
(index: number) => {
|
||||
if (!hasPinnedCustom && index === items.length - 1) {
|
||||
onPressFeedsLink()
|
||||
|
||||
@@ -2,7 +2,6 @@ import {type JSX} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import type React from 'react'
|
||||
|
||||
import {HITSLOP_10} from '#/lib/constants'
|
||||
import {useKawaiiMode} from '#/state/preferences/kawaii'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, {useState} from 'react'
|
||||
import {memo, useState} from 'react'
|
||||
import {ActivityIndicator, StyleSheet} from 'react-native'
|
||||
import {
|
||||
Gesture,
|
||||
@@ -472,4 +472,4 @@ function withClampedSpring(value: any) {
|
||||
return withSpring(value, {overshootClamping: true})
|
||||
}
|
||||
|
||||
export default React.memo(ImageItem)
|
||||
export default memo(ImageItem)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
import React, {useState} from 'react'
|
||||
import {memo, useState} from 'react'
|
||||
import {ActivityIndicator, StyleSheet} from 'react-native'
|
||||
import {
|
||||
Gesture,
|
||||
@@ -363,4 +363,4 @@ const getZoomRectAfterDoubleTap = (
|
||||
}
|
||||
}
|
||||
|
||||
export default React.memo(ImageItem)
|
||||
export default memo(ImageItem)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// default implementation fallback for web
|
||||
|
||||
import React from 'react'
|
||||
import {memo} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {type PanGesture} from 'react-native-gesture-handler'
|
||||
import {type SharedValue} from 'react-native-reanimated'
|
||||
@@ -44,4 +44,4 @@ const ImageItem = (_props: Props) => {
|
||||
return <View />
|
||||
}
|
||||
|
||||
export default React.memo(ImageItem)
|
||||
export default memo(ImageItem)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
// Original code copied and simplified from the link below as the codebase is currently not maintained:
|
||||
// https://github.com/jobtoday/react-native-image-viewing
|
||||
import React, {useCallback, useEffect, useMemo, useState} from 'react'
|
||||
import {useCallback, useEffect, useMemo, useRef, useState} from 'react'
|
||||
import {
|
||||
LayoutAnimation,
|
||||
PixelRatio,
|
||||
@@ -104,7 +104,7 @@ export default function ImageViewRoot({
|
||||
setActiveLightbox(nextLightbox)
|
||||
}
|
||||
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
if (!nextLightbox) {
|
||||
return
|
||||
}
|
||||
@@ -150,7 +150,7 @@ export default function ImageViewRoot({
|
||||
},
|
||||
)
|
||||
|
||||
const onFlyAway = React.useCallback(() => {
|
||||
const onFlyAway = useCallback(() => {
|
||||
'worklet'
|
||||
openProgress.set(0)
|
||||
runOnJS(onRequestClose)()
|
||||
@@ -216,7 +216,7 @@ function ImageView({
|
||||
const [isDragging, setIsDragging] = useState(false)
|
||||
const [imageIndex, setImageIndex] = useState(initialImageIndex)
|
||||
const [showControls, setShowControls] = useState(true)
|
||||
const [isAltExpanded, setAltExpanded] = React.useState(false)
|
||||
const [isAltExpanded, setAltExpanded] = useState(false)
|
||||
const dismissSwipeTranslateY = useSharedValue(0)
|
||||
const isFlyingAway = useSharedValue(false)
|
||||
|
||||
@@ -418,7 +418,7 @@ function LightboxImage({
|
||||
openProgress: SharedValue<number>
|
||||
dismissSwipeTranslateY: SharedValue<number>
|
||||
}) {
|
||||
const [fetchedDims, setFetchedDims] = React.useState<Dimensions | null>(null)
|
||||
const [fetchedDims, setFetchedDims] = useState<Dimensions | null>(null)
|
||||
const dims = fetchedDims ?? imageSrc.dimensions ?? imageSrc.thumbDimensions
|
||||
let imageAspect: number | undefined
|
||||
if (dims) {
|
||||
@@ -432,7 +432,7 @@ function LightboxImage({
|
||||
width: widthDelayedForJSThreadOnly,
|
||||
height: heightDelayedForJSThreadOnly,
|
||||
} = useWindowDimensions()
|
||||
const measureSafeArea = React.useCallback(() => {
|
||||
const measureSafeArea = useCallback(() => {
|
||||
'worklet'
|
||||
let safeArea: Rect | null = measure(safeAreaRef)
|
||||
if (!safeArea) {
|
||||
@@ -563,7 +563,7 @@ function LightboxFooter({
|
||||
onPressShare: (uri: string) => void
|
||||
}) {
|
||||
const {alt: altText, uri} = images[index]
|
||||
const isMomentumScrolling = React.useRef(false)
|
||||
const isMomentumScrolling = useRef(false)
|
||||
return (
|
||||
<ScrollView
|
||||
style={styles.footerScrollView}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, {type JSX, useCallback} from 'react'
|
||||
import {type JSX, useCallback, useMemo, useState} from 'react'
|
||||
import {
|
||||
Dimensions,
|
||||
type GestureResponderEvent,
|
||||
@@ -57,7 +57,7 @@ export function ListMembers({
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const [isRefreshing, setIsRefreshing] = React.useState(false)
|
||||
const [isRefreshing, setIsRefreshing] = useState(false)
|
||||
const {openModal} = useModalControls()
|
||||
const {currentAccount} = useSession()
|
||||
const moderationOpts = useModerationOpts()
|
||||
@@ -77,7 +77,7 @@ export function ListMembers({
|
||||
const isOwner =
|
||||
currentAccount && data?.pages[0].list.creator.did === currentAccount.did
|
||||
|
||||
const items = React.useMemo(() => {
|
||||
const items = useMemo(() => {
|
||||
let items: any[] = []
|
||||
if (isFetched) {
|
||||
if (isEmpty && isError) {
|
||||
@@ -102,7 +102,7 @@ export function ListMembers({
|
||||
// events
|
||||
// =
|
||||
|
||||
const onRefresh = React.useCallback(async () => {
|
||||
const onRefresh = useCallback(async () => {
|
||||
setIsRefreshing(true)
|
||||
try {
|
||||
await refetch()
|
||||
@@ -112,7 +112,7 @@ export function ListMembers({
|
||||
setIsRefreshing(false)
|
||||
}, [refetch, setIsRefreshing])
|
||||
|
||||
const onEndReached = React.useCallback(async () => {
|
||||
const onEndReached = useCallback(async () => {
|
||||
if (isFetching || !hasNextPage || isError) return
|
||||
try {
|
||||
await fetchNextPage()
|
||||
@@ -121,11 +121,11 @@ export function ListMembers({
|
||||
}
|
||||
}, [isFetching, hasNextPage, isError, fetchNextPage])
|
||||
|
||||
const onPressRetryLoadMore = React.useCallback(() => {
|
||||
const onPressRetryLoadMore = useCallback(() => {
|
||||
fetchNextPage()
|
||||
}, [fetchNextPage])
|
||||
|
||||
const onPressEditMembership = React.useCallback(
|
||||
const onPressEditMembership = useCallback(
|
||||
(e: GestureResponderEvent, profile: bsky.profile.AnyProfileView) => {
|
||||
e.preventDefault()
|
||||
openModal({
|
||||
@@ -141,7 +141,7 @@ export function ListMembers({
|
||||
// rendering
|
||||
// =
|
||||
|
||||
const renderItem = React.useCallback(
|
||||
const renderItem = useCallback(
|
||||
({item}: {item: any}) => {
|
||||
if (item === EMPTY_ITEM) {
|
||||
return renderEmptyState()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, {type JSX} from 'react'
|
||||
import {type JSX, useCallback, useMemo, useState} from 'react'
|
||||
import {
|
||||
ActivityIndicator,
|
||||
FlatList as RNFlatList,
|
||||
@@ -45,12 +45,12 @@ export function MyLists({
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const moderationOpts = useModerationOpts()
|
||||
const [isPTRing, setIsPTRing] = React.useState(false)
|
||||
const [isPTRing, setIsPTRing] = useState(false)
|
||||
const {data, isFetching, isFetched, isError, error, refetch} =
|
||||
useMyListsQuery(filter)
|
||||
const isEmpty = !isFetching && !data?.length
|
||||
|
||||
const items = React.useMemo(() => {
|
||||
const items = useMemo(() => {
|
||||
let items: any[] = []
|
||||
if (isError && isEmpty) {
|
||||
items = items.concat([ERROR_ITEM])
|
||||
@@ -85,7 +85,7 @@ export function MyLists({
|
||||
// events
|
||||
// =
|
||||
|
||||
const onRefresh = React.useCallback(async () => {
|
||||
const onRefresh = useCallback(async () => {
|
||||
setIsPTRing(true)
|
||||
try {
|
||||
await refetch()
|
||||
@@ -98,7 +98,7 @@ export function MyLists({
|
||||
// rendering
|
||||
// =
|
||||
|
||||
const renderItemInner = React.useCallback(
|
||||
const renderItemInner = useCallback(
|
||||
({item, index}: {item: any; index: number}) => {
|
||||
if (item === EMPTY) {
|
||||
return (
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, {useCallback} from 'react'
|
||||
import {useCallback, useMemo, useState} from 'react'
|
||||
import {
|
||||
ActivityIndicator,
|
||||
StyleSheet,
|
||||
@@ -56,7 +56,7 @@ export function Component({
|
||||
closeModal()
|
||||
}, [closeModal])
|
||||
|
||||
const listStyle = React.useMemo(() => {
|
||||
const listStyle = useMemo(() => {
|
||||
if (IS_WEB_MOBILE) {
|
||||
return [pal.border, {height: screenHeight / 2}]
|
||||
} else if (IS_WEB) {
|
||||
@@ -141,8 +141,8 @@ function ListItem({
|
||||
const pal = usePalette('default')
|
||||
const {_} = useLingui()
|
||||
const {currentAccount} = useSession()
|
||||
const [isProcessing, setIsProcessing] = React.useState(false)
|
||||
const membership = React.useMemo(
|
||||
const [isProcessing, setIsProcessing] = useState(false)
|
||||
const membership = useMemo(
|
||||
() => getMembership(memberships, list.uri, subject),
|
||||
[memberships, list.uri, subject],
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
import {useCallback, useEffect, useMemo, useState} from 'react'
|
||||
import {
|
||||
ActivityIndicator,
|
||||
type ListRenderItemInfo,
|
||||
@@ -45,7 +45,7 @@ export function NotificationFeed({
|
||||
refreshNotifications: () => Promise<void>
|
||||
}) {
|
||||
const initialNumToRender = useInitialNumToRender()
|
||||
const [isPTRing, setIsPTRing] = React.useState(false)
|
||||
const [isPTRing, setIsPTRing] = useState(false)
|
||||
const {_} = useLingui()
|
||||
const moderationOpts = useModerationOpts()
|
||||
const trackPostView = usePostViewTracking('Notifications')
|
||||
@@ -70,7 +70,7 @@ export function NotificationFeed({
|
||||
const isEmpty =
|
||||
!isFetching && !data?.pages.find(page => page.items.length > 0)
|
||||
|
||||
const items = React.useMemo(() => {
|
||||
const items = useMemo(() => {
|
||||
let arr: any[] = []
|
||||
if (isFetched) {
|
||||
if (isEmpty) {
|
||||
@@ -89,7 +89,7 @@ export function NotificationFeed({
|
||||
return arr
|
||||
}, [isFetched, isError, isEmpty, data])
|
||||
|
||||
const onRefresh = React.useCallback(async () => {
|
||||
const onRefresh = useCallback(async () => {
|
||||
try {
|
||||
setIsPTRing(true)
|
||||
await refreshNotifications()
|
||||
@@ -102,7 +102,7 @@ export function NotificationFeed({
|
||||
}
|
||||
}, [refreshNotifications, setIsPTRing])
|
||||
|
||||
const onEndReached = React.useCallback(async () => {
|
||||
const onEndReached = useCallback(async () => {
|
||||
if (isFetching || !hasNextPage || isError) return
|
||||
|
||||
try {
|
||||
@@ -112,11 +112,11 @@ export function NotificationFeed({
|
||||
}
|
||||
}, [isFetching, hasNextPage, isError, fetchNextPage])
|
||||
|
||||
const onPressRetryLoadMore = React.useCallback(() => {
|
||||
const onPressRetryLoadMore = useCallback(() => {
|
||||
fetchNextPage()
|
||||
}, [fetchNextPage])
|
||||
|
||||
const renderItem = React.useCallback(
|
||||
const renderItem = useCallback(
|
||||
({item, index}: ListRenderItemInfo<any>) => {
|
||||
if (item === EMPTY_FEED_ITEM) {
|
||||
return (
|
||||
@@ -150,7 +150,7 @@ export function NotificationFeed({
|
||||
[moderationOpts, _, onPressRetryLoadMore, filter],
|
||||
)
|
||||
|
||||
const FeedFooter = React.useCallback(
|
||||
const FeedFooter = useCallback(
|
||||
() =>
|
||||
isFetchingNextPage ? (
|
||||
<View style={styles.feedFooter}>
|
||||
@@ -162,7 +162,7 @@ export function NotificationFeed({
|
||||
[isFetchingNextPage],
|
||||
)
|
||||
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
if (!enabled) {
|
||||
setIsPTRing(false)
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import React, {useContext} from 'react'
|
||||
import {createContext, useContext, useMemo} from 'react'
|
||||
import {type SharedValue} from 'react-native-reanimated'
|
||||
|
||||
import {IS_NATIVE} from '#/env'
|
||||
|
||||
export const PagerHeaderContext = React.createContext<{
|
||||
export const PagerHeaderContext = createContext<{
|
||||
scrollY: SharedValue<number>
|
||||
headerHeight: number
|
||||
} | null>(null)
|
||||
@@ -24,7 +24,7 @@ export function PagerHeaderProvider({
|
||||
headerHeight: number
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
const value = React.useMemo(
|
||||
const value = useMemo(
|
||||
() => ({scrollY, headerHeight}),
|
||||
[scrollY, headerHeight],
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, {useEffect} from 'react'
|
||||
import {useCallback, useEffect, useRef} from 'react'
|
||||
import {StyleSheet, View} from 'react-native'
|
||||
import {
|
||||
FontAwesomeIcon,
|
||||
@@ -23,7 +23,7 @@ export function CustomFeedEmptyState() {
|
||||
const ax = useAnalytics()
|
||||
const feedFeedback = useFeedFeedbackContext()
|
||||
const {currentAccount} = useSession()
|
||||
const hasLoggedDiscoverEmptyErrorRef = React.useRef(false)
|
||||
const hasLoggedDiscoverEmptyErrorRef = useRef(false)
|
||||
|
||||
useEffect(() => {
|
||||
// Log the empty feed error event
|
||||
@@ -44,7 +44,7 @@ export function CustomFeedEmptyState() {
|
||||
const palInverted = usePalette('inverted')
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
|
||||
const onPressFindAccounts = React.useCallback(() => {
|
||||
const onPressFindAccounts = useCallback(() => {
|
||||
if (IS_WEB) {
|
||||
navigation.navigate('Search', {})
|
||||
} else {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
import {useCallback} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
@@ -38,7 +38,7 @@ export function FeedShutdownMsg({feedUri}: {feedUri: string}) {
|
||||
const hasFeedPinned = Boolean(feedConfig)
|
||||
const hasDiscoverPinned = Boolean(discoverFeedConfig?.pinned)
|
||||
|
||||
const onRemoveFeed = React.useCallback(async () => {
|
||||
const onRemoveFeed = useCallback(async () => {
|
||||
try {
|
||||
if (feedConfig) {
|
||||
await removeFeed(feedConfig)
|
||||
@@ -58,7 +58,7 @@ export function FeedShutdownMsg({feedUri}: {feedUri: string}) {
|
||||
}
|
||||
}, [removeFeed, feedConfig, _, hasDiscoverPinned, setSelectedFeed])
|
||||
|
||||
const onReplaceFeed = React.useCallback(async () => {
|
||||
const onReplaceFeed = useCallback(async () => {
|
||||
try {
|
||||
await replaceFeedWithDiscover({
|
||||
forYouFeedConfig: feedConfig,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
import {useCallback} from 'react'
|
||||
import {StyleSheet, View} from 'react-native'
|
||||
import {
|
||||
FontAwesomeIcon,
|
||||
@@ -20,7 +20,7 @@ export function FollowingEmptyState() {
|
||||
const palInverted = usePalette('inverted')
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
|
||||
const onPressFindAccounts = React.useCallback(() => {
|
||||
const onPressFindAccounts = useCallback(() => {
|
||||
if (IS_WEB) {
|
||||
navigation.navigate('Search', {})
|
||||
} else {
|
||||
@@ -29,7 +29,7 @@ export function FollowingEmptyState() {
|
||||
}
|
||||
}, [navigation])
|
||||
|
||||
const onPressDiscoverFeeds = React.useCallback(() => {
|
||||
const onPressDiscoverFeeds = useCallback(() => {
|
||||
navigation.navigate('Feeds')
|
||||
}, [navigation])
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
import {useCallback} from 'react'
|
||||
import {Dimensions, StyleSheet, View} from 'react-native'
|
||||
import {
|
||||
FontAwesomeIcon,
|
||||
@@ -19,7 +19,7 @@ export function FollowingEndOfFeed() {
|
||||
const palInverted = usePalette('inverted')
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
|
||||
const onPressFindAccounts = React.useCallback(() => {
|
||||
const onPressFindAccounts = useCallback(() => {
|
||||
if (IS_WEB) {
|
||||
navigation.navigate('Search', {})
|
||||
} else {
|
||||
@@ -28,7 +28,7 @@ export function FollowingEndOfFeed() {
|
||||
}
|
||||
}, [navigation])
|
||||
|
||||
const onPressDiscoverFeeds = React.useCallback(() => {
|
||||
const onPressDiscoverFeeds = useCallback(() => {
|
||||
navigation.navigate('Feeds')
|
||||
}, [navigation])
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
import {useCallback, useMemo} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {
|
||||
type AppBskyActorDefs,
|
||||
@@ -48,7 +48,7 @@ export function PostFeedErrorMessage({
|
||||
savedFeedConfig?: AppBskyActorDefs.SavedFeed
|
||||
}) {
|
||||
const {_: _l} = useLingui()
|
||||
const knownError = React.useMemo(
|
||||
const knownError = useMemo(
|
||||
() => detectKnownError(feedDesc, error),
|
||||
[feedDesc, error],
|
||||
)
|
||||
@@ -101,7 +101,7 @@ function FeedgenErrorMessage({
|
||||
const pal = usePalette('default')
|
||||
const {_: _l} = useLingui()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
const msg = React.useMemo(
|
||||
const msg = useMemo(
|
||||
() =>
|
||||
({
|
||||
[KnownError.Unknown]: '',
|
||||
@@ -135,15 +135,15 @@ function FeedgenErrorMessage({
|
||||
const removePromptControl = Prompt.usePromptControl()
|
||||
const {mutateAsync: removeFeed} = useRemoveFeedMutation()
|
||||
|
||||
const onViewProfile = React.useCallback(() => {
|
||||
const onViewProfile = useCallback(() => {
|
||||
navigation.navigate('Profile', {name: ownerDid})
|
||||
}, [navigation, ownerDid])
|
||||
|
||||
const onPressRemoveFeed = React.useCallback(() => {
|
||||
const onPressRemoveFeed = useCallback(() => {
|
||||
removePromptControl.open()
|
||||
}, [removePromptControl])
|
||||
|
||||
const onRemoveFeed = React.useCallback(async () => {
|
||||
const onRemoveFeed = useCallback(async () => {
|
||||
try {
|
||||
if (!savedFeedConfig) return
|
||||
await removeFeed(savedFeedConfig)
|
||||
@@ -158,7 +158,7 @@ function FeedgenErrorMessage({
|
||||
}
|
||||
}, [removeFeed, _l, savedFeedConfig])
|
||||
|
||||
const cta = React.useMemo(() => {
|
||||
const cta = useMemo(() => {
|
||||
switch (knownError) {
|
||||
case KnownError.FeedSignedInOnly: {
|
||||
return null
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
import {useMemo} from 'react'
|
||||
import {StyleSheet, View} from 'react-native'
|
||||
import Svg, {Circle, Line} from 'react-native-svg'
|
||||
import {AtUri} from '@atproto/api'
|
||||
@@ -19,7 +19,7 @@ export function ViewFullThread({uri}: {uri: string}) {
|
||||
onOut: onHoverOut,
|
||||
} = useInteractionState()
|
||||
const pal = usePalette('default')
|
||||
const itemHref = React.useMemo(() => {
|
||||
const itemHref = useMemo(() => {
|
||||
const urip = new AtUri(uri)
|
||||
return makeProfileLink({did: urip.hostname, handle: ''}, 'post', urip.rkey)
|
||||
}, [uri])
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
import {useCallback, useEffect, useMemo, useRef, useState} from 'react'
|
||||
import {type AppBskyActorDefs as ActorDefs} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
@@ -47,7 +47,7 @@ export function ProfileFollowers({name}: {name: string}) {
|
||||
const initialNumToRender = useInitialNumToRender()
|
||||
const {currentAccount} = useSession()
|
||||
|
||||
const [isPTRing, setIsPTRing] = React.useState(false)
|
||||
const [isPTRing, setIsPTRing] = useState(false)
|
||||
const {
|
||||
data: resolvedDid,
|
||||
isLoading: isDidLoading,
|
||||
@@ -66,7 +66,7 @@ export function ProfileFollowers({name}: {name: string}) {
|
||||
const isError = !!resolveError || !!error
|
||||
const isMe = resolvedDid === currentAccount?.did
|
||||
|
||||
const followers = React.useMemo(() => {
|
||||
const followers = useMemo(() => {
|
||||
if (data?.pages) {
|
||||
return data.pages.flatMap(page => page.followers)
|
||||
}
|
||||
@@ -74,11 +74,11 @@ export function ProfileFollowers({name}: {name: string}) {
|
||||
}, [data])
|
||||
|
||||
// Track pagination events - fire for page 3+ (pages 1-2 may auto-load)
|
||||
const paginationTrackingRef = React.useRef<{
|
||||
const paginationTrackingRef = useRef<{
|
||||
did: string | undefined
|
||||
page: number
|
||||
}>({did: undefined, page: 0})
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
const currentPageCount = data?.pages?.length || 0
|
||||
// Reset tracking when profile changes
|
||||
if (paginationTrackingRef.current.did !== resolvedDid) {
|
||||
@@ -99,7 +99,7 @@ export function ProfileFollowers({name}: {name: string}) {
|
||||
paginationTrackingRef.current.page = currentPageCount
|
||||
}, [ax, data?.pages?.length, resolvedDid, followers.length])
|
||||
|
||||
const onRefresh = React.useCallback(async () => {
|
||||
const onRefresh = useCallback(async () => {
|
||||
setIsPTRing(true)
|
||||
try {
|
||||
await refetch()
|
||||
@@ -109,7 +109,7 @@ export function ProfileFollowers({name}: {name: string}) {
|
||||
setIsPTRing(false)
|
||||
}, [refetch, setIsPTRing])
|
||||
|
||||
const onEndReached = React.useCallback(async () => {
|
||||
const onEndReached = useCallback(async () => {
|
||||
if (isFetchingNextPage || !hasNextPage || !!error) return
|
||||
try {
|
||||
await fetchNextPage()
|
||||
@@ -118,14 +118,14 @@ export function ProfileFollowers({name}: {name: string}) {
|
||||
}
|
||||
}, [isFetchingNextPage, hasNextPage, error, fetchNextPage])
|
||||
|
||||
const renderItemWithContext = React.useCallback(
|
||||
const renderItemWithContext = useCallback(
|
||||
({item, index}: {item: ActorDefs.ProfileView; index: number}) =>
|
||||
renderItem({item, index, contextProfileDid: resolvedDid}),
|
||||
[resolvedDid],
|
||||
)
|
||||
|
||||
// track pageview
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
if (resolvedDid) {
|
||||
ax.metric('profile:followers:view', {
|
||||
contextProfileDid: resolvedDid,
|
||||
@@ -135,11 +135,11 @@ export function ProfileFollowers({name}: {name: string}) {
|
||||
}, [ax, resolvedDid, isMe])
|
||||
|
||||
// track seen items
|
||||
const seenItemsRef = React.useRef<Set<string>>(new Set())
|
||||
React.useEffect(() => {
|
||||
const seenItemsRef = useRef<Set<string>>(new Set())
|
||||
useEffect(() => {
|
||||
seenItemsRef.current.clear()
|
||||
}, [resolvedDid])
|
||||
const onItemSeen = React.useCallback(
|
||||
const onItemSeen = useCallback(
|
||||
(item: ActorDefs.ProfileView) => {
|
||||
if (seenItemsRef.current.has(item.did)) {
|
||||
return
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
import {useCallback, useEffect, useMemo, useRef, useState} from 'react'
|
||||
import {type AppBskyActorDefs as ActorDefs} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
@@ -50,7 +50,7 @@ export function ProfileFollows({name}: {name: string}) {
|
||||
const {currentAccount} = useSession()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
|
||||
const onPressFindAccounts = React.useCallback(() => {
|
||||
const onPressFindAccounts = useCallback(() => {
|
||||
if (IS_WEB) {
|
||||
navigation.navigate('Search', {})
|
||||
} else {
|
||||
@@ -59,7 +59,7 @@ export function ProfileFollows({name}: {name: string}) {
|
||||
}
|
||||
}, [navigation])
|
||||
|
||||
const [isPTRing, setIsPTRing] = React.useState(false)
|
||||
const [isPTRing, setIsPTRing] = useState(false)
|
||||
const {
|
||||
data: resolvedDid,
|
||||
isLoading: isDidLoading,
|
||||
@@ -78,7 +78,7 @@ export function ProfileFollows({name}: {name: string}) {
|
||||
const isError = !!resolveError || !!error
|
||||
const isMe = resolvedDid === currentAccount?.did
|
||||
|
||||
const follows = React.useMemo(() => {
|
||||
const follows = useMemo(() => {
|
||||
if (data?.pages) {
|
||||
return data.pages.flatMap(page => page.follows)
|
||||
}
|
||||
@@ -86,11 +86,11 @@ export function ProfileFollows({name}: {name: string}) {
|
||||
}, [data])
|
||||
|
||||
// Track pagination events - fire for page 3+ (pages 1-2 may auto-load)
|
||||
const paginationTrackingRef = React.useRef<{
|
||||
const paginationTrackingRef = useRef<{
|
||||
did: string | undefined
|
||||
page: number
|
||||
}>({did: undefined, page: 0})
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
const currentPageCount = data?.pages?.length || 0
|
||||
// Reset tracking when profile changes
|
||||
if (paginationTrackingRef.current.did !== resolvedDid) {
|
||||
@@ -111,7 +111,7 @@ export function ProfileFollows({name}: {name: string}) {
|
||||
paginationTrackingRef.current.page = currentPageCount
|
||||
}, [ax, data?.pages?.length, resolvedDid, follows.length])
|
||||
|
||||
const onRefresh = React.useCallback(async () => {
|
||||
const onRefresh = useCallback(async () => {
|
||||
setIsPTRing(true)
|
||||
try {
|
||||
await refetch()
|
||||
@@ -121,7 +121,7 @@ export function ProfileFollows({name}: {name: string}) {
|
||||
setIsPTRing(false)
|
||||
}, [refetch, setIsPTRing])
|
||||
|
||||
const onEndReached = React.useCallback(async () => {
|
||||
const onEndReached = useCallback(async () => {
|
||||
if (isFetchingNextPage || !hasNextPage || !!error) return
|
||||
try {
|
||||
await fetchNextPage()
|
||||
@@ -130,14 +130,14 @@ export function ProfileFollows({name}: {name: string}) {
|
||||
}
|
||||
}, [isFetchingNextPage, hasNextPage, error, fetchNextPage])
|
||||
|
||||
const renderItemWithContext = React.useCallback(
|
||||
const renderItemWithContext = useCallback(
|
||||
({item, index}: {item: ActorDefs.ProfileView; index: number}) =>
|
||||
renderItem({item, index, contextProfileDid: resolvedDid}),
|
||||
[resolvedDid],
|
||||
)
|
||||
|
||||
// track pageview
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
if (resolvedDid) {
|
||||
ax.metric('profile:following:view', {
|
||||
contextProfileDid: resolvedDid,
|
||||
@@ -147,11 +147,11 @@ export function ProfileFollows({name}: {name: string}) {
|
||||
}, [ax, resolvedDid, isMe])
|
||||
|
||||
// track seen items
|
||||
const seenItemsRef = React.useRef<Set<string>>(new Set())
|
||||
React.useEffect(() => {
|
||||
const seenItemsRef = useRef<Set<string>>(new Set())
|
||||
useEffect(() => {
|
||||
seenItemsRef.current.clear()
|
||||
}, [resolvedDid])
|
||||
const onItemSeen = React.useCallback(
|
||||
const onItemSeen = useCallback(
|
||||
(item: ActorDefs.ProfileView) => {
|
||||
if (seenItemsRef.current.has(item.did)) {
|
||||
return
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, {memo} from 'react'
|
||||
import {memo, useCallback, useMemo} from 'react'
|
||||
import {type AppBskyActorDefs} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
@@ -108,29 +108,29 @@ let ProfileMenu = ({
|
||||
const goLiveDisabledDialogControl = useDialogControl()
|
||||
const addToStarterPacksDialogControl = useDialogControl()
|
||||
|
||||
const showLoggedOutWarning = React.useMemo(() => {
|
||||
const showLoggedOutWarning = useMemo(() => {
|
||||
return (
|
||||
profile.did !== currentAccount?.did &&
|
||||
!!profile.labels?.find(label => label.val === '!no-unauthenticated')
|
||||
)
|
||||
}, [currentAccount, profile])
|
||||
|
||||
const invalidateProfileQuery = React.useCallback(() => {
|
||||
const invalidateProfileQuery = useCallback(() => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: profileQueryKey(profile.did),
|
||||
})
|
||||
}, [queryClient, profile.did])
|
||||
|
||||
const onPressAddToStarterPacks = React.useCallback(() => {
|
||||
const onPressAddToStarterPacks = useCallback(() => {
|
||||
ax.metric('profile:addToStarterPack', {})
|
||||
addToStarterPacksDialogControl.open()
|
||||
}, [addToStarterPacksDialogControl])
|
||||
|
||||
const onPressShare = React.useCallback(() => {
|
||||
const onPressShare = useCallback(() => {
|
||||
shareUrl(toShareUrl(makeProfileLink(profile)))
|
||||
}, [profile])
|
||||
|
||||
const onPressAddRemoveLists = React.useCallback(() => {
|
||||
const onPressAddRemoveLists = useCallback(() => {
|
||||
openModal({
|
||||
name: 'user-add-remove-lists',
|
||||
subject: profile.did,
|
||||
@@ -141,7 +141,7 @@ let ProfileMenu = ({
|
||||
})
|
||||
}, [profile, openModal, invalidateProfileQuery])
|
||||
|
||||
const onPressMuteAccount = React.useCallback(async () => {
|
||||
const onPressMuteAccount = useCallback(async () => {
|
||||
if (profile.viewer?.muted) {
|
||||
try {
|
||||
await queueUnmute()
|
||||
@@ -165,7 +165,7 @@ let ProfileMenu = ({
|
||||
}
|
||||
}, [ax, profile.viewer?.muted, queueUnmute, _, queueMute])
|
||||
|
||||
const blockAccount = React.useCallback(async () => {
|
||||
const blockAccount = useCallback(async () => {
|
||||
if (profile.viewer?.blocking) {
|
||||
try {
|
||||
await queueUnblock()
|
||||
@@ -189,7 +189,7 @@ let ProfileMenu = ({
|
||||
}
|
||||
}, [ax, profile.viewer?.blocking, _, queueUnblock, queueBlock])
|
||||
|
||||
const onPressFollowAccount = React.useCallback(async () => {
|
||||
const onPressFollowAccount = useCallback(async () => {
|
||||
try {
|
||||
await queueFollow()
|
||||
Toast.show(_(msg({message: 'Account followed', context: 'toast'})))
|
||||
@@ -201,7 +201,7 @@ let ProfileMenu = ({
|
||||
}
|
||||
}, [_, ax, queueFollow])
|
||||
|
||||
const onPressUnfollowAccount = React.useCallback(async () => {
|
||||
const onPressUnfollowAccount = useCallback(async () => {
|
||||
try {
|
||||
await queueUnfollow()
|
||||
Toast.show(_(msg({message: 'Account unfollowed', context: 'toast'})))
|
||||
@@ -213,19 +213,19 @@ let ProfileMenu = ({
|
||||
}
|
||||
}, [_, ax, queueUnfollow])
|
||||
|
||||
const onPressReportAccount = React.useCallback(() => {
|
||||
const onPressReportAccount = useCallback(() => {
|
||||
reportDialogControl.open()
|
||||
}, [reportDialogControl])
|
||||
|
||||
const onPressShareATUri = React.useCallback(() => {
|
||||
const onPressShareATUri = useCallback(() => {
|
||||
shareText(`at://${profile.did}`)
|
||||
}, [profile.did])
|
||||
|
||||
const onPressShareDID = React.useCallback(() => {
|
||||
const onPressShareDID = useCallback(() => {
|
||||
shareText(profile.did)
|
||||
}, [profile.did])
|
||||
|
||||
const onPressSearch = React.useCallback(() => {
|
||||
const onPressSearch = useCallback(() => {
|
||||
navigation.navigate('ProfileSearch', {name: profile.handle})
|
||||
}, [navigation, profile.handle])
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
import {useCallback} from 'react'
|
||||
import {Pressable, View} from 'react-native'
|
||||
import Animated, {
|
||||
measure,
|
||||
@@ -60,7 +60,7 @@ export function ProfileSubpageHeader({
|
||||
const canGoBack = navigation.canGoBack()
|
||||
const aviRef = useAnimatedRef()
|
||||
|
||||
const _openLightbox = React.useCallback(
|
||||
const _openLightbox = useCallback(
|
||||
(uri: string, thumbRect: MeasuredDimensions | null) => {
|
||||
openLightbox({
|
||||
images: [
|
||||
@@ -83,7 +83,7 @@ export function ProfileSubpageHeader({
|
||||
[openLightbox],
|
||||
)
|
||||
|
||||
const onPressAvi = React.useCallback(() => {
|
||||
const onPressAvi = useCallback(() => {
|
||||
if (
|
||||
avatar // TODO && !(view.moderation.avatar.blur && view.moderation.avatar.noOverride)
|
||||
) {
|
||||
|
||||
@@ -8,7 +8,6 @@ import Animated, {
|
||||
import {type BottomSheetBackdropProps} from '@discord/bottom-sheet/src'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import type React from 'react'
|
||||
|
||||
export function createCustomBackdrop(
|
||||
onClose?: () => void,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
import {isValidElement} from 'react'
|
||||
import {type StyleProp, type TextStyle, type ViewStyle} from 'react-native'
|
||||
import {View} from 'react-native'
|
||||
|
||||
@@ -45,7 +45,7 @@ export function EmptyState({
|
||||
return placeholderIcon
|
||||
}
|
||||
|
||||
if (React.isValidElement(icon)) {
|
||||
if (isValidElement(icon)) {
|
||||
return icon
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ export function EmptyState({
|
||||
a.rounded_full,
|
||||
a.mt_5xl,
|
||||
{height: 64, width: 64},
|
||||
React.isValidElement(icon)
|
||||
isValidElement(icon)
|
||||
? a.bg_transparent
|
||||
: [isTabletOrDesktop && {marginTop: 50}],
|
||||
]}>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, {useCallback, useEffect} from 'react'
|
||||
import {useCallback, useEffect} from 'react'
|
||||
import {type NativeScrollEvent} from 'react-native'
|
||||
import {
|
||||
clamp,
|
||||
@@ -25,7 +25,7 @@ export function MainScrollProvider({children}: {children: React.ReactNode}) {
|
||||
const startMode = useSharedValue<number | null>(null)
|
||||
const didJustRestoreScroll = useSharedValue<boolean>(false)
|
||||
|
||||
const setMode = React.useCallback(
|
||||
const setMode = useCallback(
|
||||
(v: boolean) => {
|
||||
'worklet'
|
||||
headerMode.set(() =>
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
import React, {type JSX, useEffect, useState} from 'react'
|
||||
import {
|
||||
forwardRef,
|
||||
type JSX,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useImperativeHandle,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react'
|
||||
import {
|
||||
type NativeScrollEvent,
|
||||
type NativeSyntheticEvent,
|
||||
@@ -25,7 +34,7 @@ export type ViewSelectorHandle = {
|
||||
scrollToTop: () => void
|
||||
}
|
||||
|
||||
export const ViewSelector = React.forwardRef<
|
||||
export const ViewSelector = forwardRef<
|
||||
ViewSelectorHandle,
|
||||
{
|
||||
sections: string[]
|
||||
@@ -61,14 +70,14 @@ export const ViewSelector = React.forwardRef<
|
||||
) {
|
||||
const pal = usePalette('default')
|
||||
const [selectedIndex, setSelectedIndex] = useState<number>(0)
|
||||
const flatListRef = React.useRef<FlatList_INTERNAL>(null)
|
||||
const flatListRef = useRef<FlatList_INTERNAL>(null)
|
||||
|
||||
// events
|
||||
// =
|
||||
|
||||
const keyExtractor = React.useCallback((item: any) => item._reactKey, [])
|
||||
const keyExtractor = useCallback((item: any) => item._reactKey, [])
|
||||
|
||||
const onPressSelection = React.useCallback(
|
||||
const onPressSelection = useCallback(
|
||||
(index: number) => setSelectedIndex(clamp(index, 0, sections.length)),
|
||||
[setSelectedIndex, sections],
|
||||
)
|
||||
@@ -76,7 +85,7 @@ export const ViewSelector = React.forwardRef<
|
||||
onSelectView?.(selectedIndex)
|
||||
}, [selectedIndex, onSelectView])
|
||||
|
||||
React.useImperativeHandle(ref, () => ({
|
||||
useImperativeHandle(ref, () => ({
|
||||
scrollToTop: () => {
|
||||
flatListRef.current?.scrollToOffset({offset: 0})
|
||||
},
|
||||
@@ -85,7 +94,7 @@ export const ViewSelector = React.forwardRef<
|
||||
// rendering
|
||||
// =
|
||||
|
||||
const renderItemInternal = React.useCallback(
|
||||
const renderItemInternal = useCallback(
|
||||
({item}: {item: any}) => {
|
||||
if (item === HEADER_ITEM) {
|
||||
if (renderHeader) {
|
||||
@@ -107,10 +116,7 @@ export const ViewSelector = React.forwardRef<
|
||||
[sections, selectedIndex, onPressSelection, renderHeader, renderItem],
|
||||
)
|
||||
|
||||
const data = React.useMemo(
|
||||
() => [HEADER_ITEM, SELECTOR_ITEM, ...items],
|
||||
[items],
|
||||
)
|
||||
const data = useMemo(() => [HEADER_ITEM, SELECTOR_ITEM, ...items], [items])
|
||||
return (
|
||||
<FlatList_INTERNAL
|
||||
// @ts-expect-error FlatList_INTERNAL ref type is wrong -sfn
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* need to match layout but which aren't scrolled.
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import {forwardRef} from 'react'
|
||||
import {
|
||||
type FlatList,
|
||||
type FlatListProps,
|
||||
@@ -37,7 +37,7 @@ interface AddedProps {
|
||||
/**
|
||||
* @deprecated use `Layout` components
|
||||
*/
|
||||
export const CenteredView = React.forwardRef(function CenteredView(
|
||||
export const CenteredView = forwardRef(function CenteredView(
|
||||
{
|
||||
style,
|
||||
topBorder,
|
||||
@@ -66,7 +66,7 @@ export const CenteredView = React.forwardRef(function CenteredView(
|
||||
return <View ref={ref} style={style} {...props} />
|
||||
})
|
||||
|
||||
export const FlatList_INTERNAL = React.forwardRef(function FlatListImpl<ItemT>(
|
||||
export const FlatList_INTERNAL = forwardRef(function FlatListImpl<ItemT>(
|
||||
{
|
||||
contentContainerStyle,
|
||||
style,
|
||||
@@ -141,7 +141,7 @@ export const FlatList_INTERNAL = React.forwardRef(function FlatListImpl<ItemT>(
|
||||
/**
|
||||
* @deprecated use `Layout` components
|
||||
*/
|
||||
export const ScrollView = React.forwardRef(function ScrollViewImpl(
|
||||
export const ScrollView = forwardRef(function ScrollViewImpl(
|
||||
{contentContainerStyle, ...props}: React.PropsWithChildren<ScrollViewProps>,
|
||||
ref: React.Ref<Animated.ScrollView>,
|
||||
) {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import {Platform} from 'react-native'
|
||||
import type React from 'react'
|
||||
|
||||
const onMouseUp = (e: React.MouseEvent & {target: HTMLElement}) => {
|
||||
// Only handle whenever it is the middle button
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
import {useCallback, useState} from 'react'
|
||||
import {
|
||||
ActivityIndicator,
|
||||
type GestureResponderEvent,
|
||||
@@ -148,8 +148,8 @@ export function Button({
|
||||
},
|
||||
)
|
||||
|
||||
const [isLoading, setIsLoading] = React.useState(false)
|
||||
const onPressWrapped = React.useCallback(
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const onPressWrapped = useCallback(
|
||||
async (event: GestureResponderEvent) => {
|
||||
event.stopPropagation()
|
||||
event.preventDefault()
|
||||
@@ -160,7 +160,7 @@ export function Button({
|
||||
[onPress, withLoading],
|
||||
)
|
||||
|
||||
const getStyle = React.useCallback(
|
||||
const getStyle = useCallback(
|
||||
(state: PressableStateCallbackType) => {
|
||||
const arr = [typeOuterStyle, styles.outer, style]
|
||||
if (state.pressed) {
|
||||
@@ -173,7 +173,7 @@ export function Button({
|
||||
[typeOuterStyle, style],
|
||||
)
|
||||
|
||||
const renderChildern = React.useCallback(() => {
|
||||
const renderChildern = useCallback(() => {
|
||||
if (!label) {
|
||||
return children
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import {ScrollView, StyleSheet, View} from 'react-native'
|
||||
import type React from 'react'
|
||||
|
||||
import {useColorSchemeStyle} from '#/lib/hooks/useColorSchemeStyle'
|
||||
import {useIsKeyboardVisible} from '#/lib/hooks/useIsKeyboardVisible'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
import {useMemo} from 'react'
|
||||
import {StyleSheet, type TextProps} from 'react-native'
|
||||
import {UITextView} from 'react-native-uitextview'
|
||||
|
||||
@@ -57,7 +57,7 @@ function Text_DEPRECATED({
|
||||
}
|
||||
}
|
||||
|
||||
const textProps = React.useMemo(() => {
|
||||
const textProps = useMemo(() => {
|
||||
const typography = theme.typography[type]
|
||||
const lineHeightStyle = lineHeight ? lh(theme, type, lineHeight) : undefined
|
||||
|
||||
|
||||
Reference in New Issue
Block a user