···11-import React from 'react'
11+import {useEffect} from 'react'
2233import {type DialogControlProps} from '#/components/Dialog/types'
4455export function useAutoOpen(control: DialogControlProps, showTimeout?: number) {
66- React.useEffect(() => {
66+ useEffect(() => {
77 if (showTimeout) {
88 const timeout = setTimeout(() => {
99 control.open()
-1
src/components/Fill.tsx
···11import {View} from 'react-native'
22-import type React from 'react'
3243import {atoms as a, type ViewStyleProp} from '#/alf'
54
+4-6
src/components/KnownFollowers.tsx
···11-import React from 'react'
11+import {useRef} from 'react'
22import {View} from 'react-native'
33import {
44 type AppBskyActorDefs,
···4646 minimal?: boolean
4747 showIfEmpty?: boolean
4848}) {
4949- const cache = React.useRef<Map<string, AppBskyActorDefs.KnownFollowers>>(
5050- new Map(),
5151- )
4949+ const cache = useRef<Map<string, AppBskyActorDefs.KnownFollowers>>(new Map())
52505351 /*
5452 * Results for `knownFollowers` are not sorted consistently, so when
···190188 numberOfLines={2}>
191189 {slice.length >= 2 ? (
192190 // 2-n followers, including blocks
193193- serverCount > 2 ? (
191191+ serverCount > 2 ? ( // only 2
194192 <Trans>
195193 Followed by{' '}
196194 <Text emoji key={slice[0].profile.did} style={textStyle}>
···206204 one="# other"
207205 other="# others"
208206 />
209209- </Trans> // only 2
207207+ </Trans>
210208 ) : (
211209 <Trans>
212210 Followed by{' '}
-1
src/components/LabelingServiceCard/index.tsx
···33import {msg} from '@lingui/core/macro'
44import {useLingui} from '@lingui/react'
55import {Plural, Trans} from '@lingui/react/macro'
66-import type React from 'react'
7687import {getLabelingServiceTitle} from '#/lib/moderation'
98import {sanitizeHandle} from '#/lib/strings/handles'
+2-2
src/components/LanguageSelect.tsx
···11-import React from 'react'
11+import {useCallback} from 'react'
22import {msg} from '@lingui/core/macro'
33import {useLingui} from '@lingui/react'
44···2222}) {
2323 const {_} = useLingui()
24242525- const handleOnChange = React.useCallback(
2525+ const handleOnChange = useCallback(
2626 (value: string) => {
2727 if (!value) return
2828 onChange(sanitizeAppLanguageSetting(value))
···11import {type StyleProp, type ViewStyle} from 'react-native'
22import {LinearGradient} from 'expo-linear-gradient'
33-import type React from 'react'
4354import {gradients} from '#/alf/tokens'
65
···11import {StyleSheet} from 'react-native'
22-import type React from 'react'
3243import {atoms as a, platform, useTheme, type ViewStyleProp} from '#/alf'
54import {Fill} from '#/components/Fill'
+5-5
src/components/Menu/context.tsx
···11-import React from 'react'
11+import {createContext, useContext} from 'react'
2233import {type ContextType, type ItemContextType} from '#/components/Menu/types'
4455-export const Context = React.createContext<ContextType | null>(null)
55+export const Context = createContext<ContextType | null>(null)
66Context.displayName = 'MenuContext'
7788-export const ItemContext = React.createContext<ItemContextType | null>(null)
88+export const ItemContext = createContext<ItemContextType | null>(null)
99ItemContext.displayName = 'MenuItemContext'
10101111export function useMenuContext() {
1212- const context = React.useContext(Context)
1212+ const context = useContext(Context)
13131414 if (!context) {
1515 throw new Error('useMenuContext must be used within a Context.Provider')
···1919}
20202121export function useMenuItemContext() {
2222- const context = React.useContext(ItemContext)
2222+ const context = useContext(ItemContext)
23232424 if (!context) {
2525 throw new Error('useMenuItemContext must be used within a Context.Provider')
-1
src/components/Menu/types.ts
···44 type GestureResponderEvent,
55 type PressableProps,
66} from 'react-native'
77-import type React from 'react'
8798import {type TextStyleProp, type ViewStyleProp} from '#/alf'
109import type * as Dialog from '#/components/Dialog'
···11-import React from 'react'
11+import {createContext, useContext, useMemo, useState} from 'react'
2233-const Context = React.createContext<{
44- // native
33+const Context = createContext<{
54 muted: boolean
65 setMuted: React.Dispatch<React.SetStateAction<boolean>>
76 // web
···1110Context.displayName = 'VideoVolumeContext'
12111312export function Provider({children}: {children: React.ReactNode}) {
1414- const [muted, setMuted] = React.useState(true)
1515- const [volume, setVolume] = React.useState(1)
1313+ const [muted, setMuted] = useState(true)
1414+ const [volume, setVolume] = useState(1)
16151717- const value = React.useMemo(
1616+ const value = useMemo(
1817 () => ({
1918 muted,
2019 setMuted,
···2827}
29283029export function useVideoVolumeState() {
3131- const context = React.useContext(Context)
3030+ const context = useContext(Context)
3231 if (!context) {
3332 throw new Error(
3433 'useVideoVolumeState must be used within a VideoVolumeProvider',
···3837}
39384039export function useVideoMuteState() {
4141- const context = React.useContext(Context)
4040+ const context = useContext(Context)
4241 if (!context) {
4342 throw new Error(
4443 'useVideoMuteState must be used within a VideoVolumeProvider',
-1
src/components/PostControls/BookmarkButton.tsx
···44import {msg} from '@lingui/core/macro'
55import {useLingui} from '@lingui/react'
66import {Trans} from '@lingui/react/macro'
77-import type React from 'react'
8798import {useCleanError} from '#/lib/hooks/useCleanError'
109import {type Shadow} from '#/state/cache/post-shadow'
···11-import React from 'react'
11+import {useMemo} from 'react'
22import {type StyleProp, Text as RNText, type TextStyle} from 'react-native'
33import {msg} from '@lingui/core/macro'
44import {useLingui} from '@lingui/react'
···6868 /*
6969 * Mute word records that exactly match the tag in question.
7070 */
7171- const removeableMuteWords = React.useMemo(() => {
7171+ const removeableMuteWords = useMemo(() => {
7272 return (
7373 preferences?.moderationPrefs.mutedWords?.filter(word => {
7474 return word.value === tag
-1
src/components/ScreenTransition.tsx
···66 SlideInLeft,
77 SlideInRight,
88} from 'react-native-reanimated'
99-import type React from 'react'
1091110import {IS_WEB} from '#/env'
1211
···55import {useLingui} from '@lingui/react'
66import {Trans} from '@lingui/react/macro'
77import {StackActions, useNavigation} from '@react-navigation/native'
88-import type React from 'react'
98109import {type NavigationProp} from '#/lib/routes/types'
1110import {useProfileShadow} from '#/state/cache/profile-shadow'
···11-import React from 'react'
11+import {useEffect, useState} from 'react'
2233import {
44 createStarterPackLinkFromAndroidReferrer,
···1010import {Referrer, SharedPrefs} from '../../../modules/expo-bluesky-swiss-army'
11111212export function useStarterPackEntry() {
1313- const [ready, setReady] = React.useState(false)
1313+ const [ready, setReady] = useState(false)
1414 const setActiveStarterPack = useSetActiveStarterPack()
1515 const hasCheckedForStarterPack = useHasCheckedForStarterPack()
16161717- React.useEffect(() => {
1717+ useEffect(() => {
1818 if (ready) return
19192020 // On Android, we cannot clear the referral link. It gets stored for 90 days and all we can do is query for it. So,
···22import {i18n} from '@lingui/core'
33import {I18nProvider as DefaultI18nProvider} from '@lingui/react'
44import {type Locale} from 'date-fns'
55-import type React from 'react'
6576import {useLocaleLanguage} from './i18n'
87
+7-7
src/screens/Deactivated.tsx
···11-import React from 'react'
11+import {useCallback, useState} from 'react'
22import {View} from 'react-native'
33import {useSafeAreaInsets} from 'react-native-safe-area-context'
44import {msg} from '@lingui/core/macro'
···3838 const hasOtherAccounts = accounts.length > 1
3939 const {logoutCurrentAccount} = useSessionApi()
4040 const agent = useAgent()
4141- const [pending, setPending] = React.useState(false)
4242- const [error, setError] = React.useState<string | undefined>()
4141+ const [pending, setPending] = useState(false)
4242+ const [error, setError] = useState<string | undefined>()
4343 const queryClient = useQueryClient()
44444545- const onSelectAccount = React.useCallback(
4545+ const onSelectAccount = useCallback(
4646 (account: SessionAccount) => {
4747 if (account.did !== currentAccount?.did) {
4848 onPressSwitchAccount(account, 'SwitchAccount')
···5151 [currentAccount, onPressSwitchAccount],
5252 )
53535454- const onPressAddAccount = React.useCallback(() => {
5454+ const onPressAddAccount = useCallback(() => {
5555 setShowLoggedOut(true)
5656 }, [setShowLoggedOut])
57575858- const onPressLogout = React.useCallback(() => {
5858+ const onPressLogout = useCallback(() => {
5959 if (IS_WEB) {
6060 // We're switching accounts, which remounts the entire app.
6161 // On mobile, this gets us Home, but on the web we also need reset the URL.
···6767 logoutCurrentAccount('Deactivated')
6868 }, [logoutCurrentAccount])
69697070- const handleActivate = React.useCallback(async () => {
7070+ const handleActivate = useCallback(async () => {
7171 try {
7272 setPending(true)
7373 await agent.com.atproto.server.activateAccount()
+2-2
src/screens/E2E/SharedPreferencesTesterScreen.tsx
···11-import React from 'react'
11+import {useState} from 'react'
22import {View} from 'react-native'
3344import {ScrollView} from '#/view/com/util/Views'
···99import {SharedPrefs} from '../../../modules/expo-bluesky-swiss-army'
10101111export function SharedPreferencesTesterScreen() {
1212- const [currentTestOutput, setCurrentTestOutput] = React.useState<string>('')
1212+ const [currentTestOutput, setCurrentTestOutput] = useState<string>('')
13131414 return (
1515 <Layout.Screen>
···11import {type StyleProp, View, type ViewStyle} from 'react-native'
22-import type React from 'react'
3243import {atoms as a, useBreakpoints, useGutters} from '#/alf'
54import {Text} from '#/components/Typography'
+4-4
src/screens/Messages/Conversation.tsx
···11-import React, {useCallback, useEffect} from 'react'
11+import {useCallback, useEffect, useMemo, useState} from 'react'
22import {View} from 'react-native'
33import {
44 type AppBskyActorDefs,
···105105 })
106106 const recipient = useMaybeProfileShadow(recipientUnshadowed)
107107108108- const moderation = React.useMemo(() => {
108108+ const moderation = useMemo(() => {
109109 if (!recipient || !moderationOpts) return null
110110 return moderateProfile(recipient, moderationOpts)
111111 }, [recipient, moderationOpts])
···113113 // Because we want to give the list a chance to asynchronously scroll to the end before it is visible to the user,
114114 // we use `hasScrolled` to determine when to render. With that said however, there is a chance that the chat will be
115115 // empty. So, we also check for that possible state as well and render once we can.
116116- const [hasScrolled, setHasScrolled] = React.useState(false)
116116+ const [hasScrolled, setHasScrolled] = useState(false)
117117 const readyToShow =
118118 hasScrolled ||
119119 (isConvoActive(convoState) &&
···122122123123 // Any time that we re-render the `Initializing` state, we have to reset `hasScrolled` to false. After entering this
124124 // state, we know that we're resetting the list of messages and need to re-scroll to the bottom when they get added.
125125- React.useEffect(() => {
125125+ useEffect(() => {
126126 if (convoState.status === ConvoStatus.Initializing) {
127127 setHasScrolled(false)
128128 }
···11-import React from 'react'
11+import {useCallback, useEffect, useMemo, useState} from 'react'
22import {type AppBskyActorDefs} from '@atproto/api'
33import {msg} from '@lingui/core/macro'
44import {useLingui} from '@lingui/react'
···71717272 const isFollowing = !!profile.viewer?.following
7373 const isFollowedBy = !!profile.viewer?.followedBy
7474- const [wasFollowing, setWasFollowing] = React.useState<boolean>(isFollowing)
7474+ const [wasFollowing, setWasFollowing] = useState<boolean>(isFollowing)
75757676 // This prevents the button from disappearing as soon as we follow.
7777- const showFollowBtn = React.useMemo(
7777+ const showFollowBtn = useMemo(
7878 () => !isFollowing || !wasFollowing,
7979 [isFollowing, wasFollowing],
8080 )
···9090 * sudden rendering of the button. However, on web if we do this, there's an obvious flicker once the
9191 * button renders. So, we update the state in both cases.
9292 */
9393- React.useEffect(() => {
9393+ useEffect(() => {
9494 const updateWasFollowing = () => {
9595 if (wasFollowing !== isFollowing) {
9696 setWasFollowing(isFollowing)
···106106 }
107107 }, [isFollowing, wasFollowing, navigation])
108108109109- const onPress = React.useCallback(() => {
109109+ const onPress = useCallback(() => {
110110 if (!isFollowing) {
111111 requireAuth(async () => {
112112 try {
+2-2
src/screens/Profile/ErrorState.tsx
···11-import React from 'react'
11+import {useCallback} from 'react'
22import {View} from 'react-native'
33import {msg} from '@lingui/core/macro'
44import {useLingui} from '@lingui/react'
···1616 const {_} = useLingui()
1717 const navigation = useNavigation<NavigationProp>()
18181919- const onPressBack = React.useCallback(() => {
1919+ const onPressBack = useCallback(() => {
2020 if (navigation.canGoBack()) {
2121 navigation.goBack()
2222 } else {
-1
src/screens/Profile/Header/GrowableAvatar.tsx
···55 type SharedValue,
66 useAnimatedStyle,
77} from 'react-native-reanimated'
88-import type React from 'react'
98109import {usePagerHeaderContext} from '#/view/com/pager/PagerHeaderContext'
1110import {IS_IOS} from '#/env'
-1
src/screens/Profile/Header/GrowableBanner.tsx
···1313import {useSafeAreaInsets} from 'react-native-safe-area-context'
1414import {BlurView} from 'expo-blur'
1515import {useIsFetching} from '@tanstack/react-query'
1616-import type React from 'react'
17161817import {RQKEY_ROOT as STARTERPACK_RQKEY_ROOT} from '#/state/queries/actor-starter-packs'
1918import {RQKEY_ROOT as FEED_RQKEY_ROOT} from '#/state/queries/post-feed'
···11-import React from 'react'
11+import {createContext, useContext, useEffect, useState} from 'react'
22import {AppState} from 'react-native'
3344import {MessagesEventBus} from '#/state/messages/events/agent'
55import {useAgent, useSession} from '#/state/session'
6677-const MessagesEventBusContext = React.createContext<MessagesEventBus | null>(
88- null,
99-)
77+const MessagesEventBusContext = createContext<MessagesEventBus | null>(null)
108MessagesEventBusContext.displayName = 'MessagesEventBusContext'
1191210export function useMessagesEventBus() {
1313- const ctx = React.useContext(MessagesEventBusContext)
1111+ const ctx = useContext(MessagesEventBusContext)
1412 if (!ctx) {
1513 throw new Error(
1614 'useMessagesEventBus must be used within a MessagesEventBusProvider',
···4543 children: React.ReactNode
4644}) {
4745 const agent = useAgent()
4848- const [bus] = React.useState(
4646+ const [bus] = useState(
4947 () =>
5048 new MessagesEventBus({
5149 agent,
5250 }),
5351 )
54525555- React.useEffect(() => {
5353+ useEffect(() => {
5654 bus.resume()
57555856 return () => {
···6058 }
6159 }, [bus])
62606363- React.useEffect(() => {
6161+ useEffect(() => {
6462 const handleAppStateChange = (nextAppState: string) => {
6563 if (nextAppState === 'active') {
6664 bus.resume()
-2
src/state/messages/index.tsx
···11-import type React from 'react'
22-31import {CurrentConvoIdProvider} from '#/state/messages/current-convo-id'
42import {MessagesEventBusProvider} from '#/state/messages/events'
53import {ListConvosProvider} from '#/state/queries/messages/list-conversations'
+10-3
src/state/messages/message-drafts.tsx
···11-import React, {useEffect, useMemo, useReducer, useRef} from 'react'
11+import {
22+ createContext,
33+ useContext,
44+ useEffect,
55+ useMemo,
66+ useReducer,
77+ useRef,
88+} from 'react'
29310import {useCurrentConvoId} from './current-convo-id'
41155-const MessageDraftsContext = React.createContext<{
1212+const MessageDraftsContext = createContext<{
613 state: State
714 dispatch: React.Dispatch<Actions>
815} | null>(null)
916MessageDraftsContext.displayName = 'MessageDraftsContext'
10171118function useMessageDraftsContext() {
1212- const ctx = React.useContext(MessageDraftsContext)
1919+ const ctx = useContext(MessageDraftsContext)
1320 if (!ctx) {
1421 throw new Error(
1522 'useMessageDrafts must be used within a MessageDraftsContext',
···11-import type React from 'react'
22-31import {Provider as AltTextRequiredProvider} from './alt-text-required'
42import {Provider as AutoplayProvider} from './autoplay'
53import {Provider as DisableHapticsProvider} from './disable-haptics'
+13-9
src/state/preferences/kawaii.tsx
···11-import React from 'react'
11+import {
22+ createContext,
33+ useCallback,
44+ useContext,
55+ useEffect,
66+ useState,
77+} from 'react'
2839import * as persisted from '#/state/persisted'
410import {IS_WEB} from '#/env'
511612type StateContext = persisted.Schema['kawaii']
71388-const stateContext = React.createContext<StateContext>(
99- persisted.defaults.kawaii,
1010-)
1414+const stateContext = createContext<StateContext>(persisted.defaults.kawaii)
1115stateContext.displayName = 'KawaiiStateContext'
12161317export function Provider({children}: React.PropsWithChildren<{}>) {
1414- const [state, setState] = React.useState(persisted.get('kawaii'))
1818+ const [state, setState] = useState(persisted.get('kawaii'))
15191616- const setStateWrapped = React.useCallback(
2020+ const setStateWrapped = useCallback(
1721 (kawaii: persisted.Schema['kawaii']) => {
1822 setState(kawaii)
1923 persisted.write('kawaii', kawaii)
···2125 [setState],
2226 )
23272424- React.useEffect(() => {
2828+ useEffect(() => {
2529 return persisted.onUpdate('kawaii', nextKawaii => {
2630 setState(nextKawaii)
2731 })
2832 }, [setStateWrapped])
29333030- React.useEffect(() => {
3434+ useEffect(() => {
3135 // dumb and stupid but it's web only so just refresh the page if you want to change it
32363337 if (IS_WEB) {
···4751}
48524953export function useKawaiiMode() {
5050- return React.useContext(stateContext)
5454+ return useContext(stateContext)
5155}
+3-3
src/state/preferences/label-defs.tsx
···11-import React from 'react'
11+import {createContext, useContext} from 'react'
22import {
33 type AppBskyLabelerDefs,
44 type InterpretedLabelValueDefinition,
···1111 labelers: AppBskyLabelerDefs.LabelerViewDetailed[]
1212}
13131414-const stateContext = React.createContext<StateContext>({
1414+const stateContext = createContext<StateContext>({
1515 labelDefs: {},
1616 labelers: [],
1717})
···2323}
24242525export function useLabelDefinitions() {
2626- return React.useContext(stateContext)
2626+ return useContext(stateContext)
2727}
···11-import React from 'react'
11+import {useState} from 'react'
2233const LIKE_WINDOW = 100
44const FOLLOW_WINDOW = 100
···4545}
46464747export function useActionHistorySnapshot() {
4848- return React.useState(() => getActionHistory())[0]
4848+ return useState(() => getActionHistory())[0]
4949}
50505151export function like(postUris: string[]) {
+3-3
src/view/com/auth/SplashScreen.web.tsx
···11-import React from 'react'
11+import {useEffect, useState} from 'react'
22import {Pressable, View} from 'react-native'
33import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
44import {msg} from '@lingui/core/macro'
···3333 const {_} = useLingui()
3434 const t = useTheme()
3535 const {isTabletOrMobile: IS_WEB_MOBILE} = useWebMediaQueries()
3636- const [showClipOverlay, setShowClipOverlay] = React.useState(false)
3636+ const [showClipOverlay, setShowClipOverlay] = useState(false)
37373838- React.useEffect(() => {
3838+ useEffect(() => {
3939 const getParams = new URLSearchParams(window.location.search)
4040 const clip = getParams.get('clip')
4141 if (clip === 'true') {
-1
src/view/com/composer/AltTextCounterWrapper.tsx
···11import {View} from 'react-native'
22-import type React from 'react'
3243import {MAX_ALT_TEXT} from '#/lib/constants'
54import {CharProgress} from '#/view/com/composer/char-progress/CharProgress'
···11import {View} from 'react-native'
22import {KeyboardStickyView} from 'react-native-keyboard-controller'
33import {useSafeAreaInsets} from 'react-native-safe-area-context'
44-import type React from 'react'
5465import {atoms as a, useTheme} from '#/alf'
76import {IS_WEB} from '#/env'
···33import {msg} from '@lingui/core/macro'
44import {useLingui} from '@lingui/react'
55import {Trans} from '@lingui/react/macro'
66-import type React from 'react'
7687import {logger} from '#/logger'
98import * as Toast from '#/view/com/util/Toast'
···22import {View} from 'react-native'
33import {msg} from '@lingui/core/macro'
44import {useLingui} from '@lingui/react'
55-import type React from 'react'
6576import {HITSLOP_10} from '#/lib/constants'
87import {useKawaiiMode} from '#/state/preferences/kawaii'
···88import {type BottomSheetBackdropProps} from '@discord/bottom-sheet/src'
99import {msg} from '@lingui/core/macro'
1010import {useLingui} from '@lingui/react'
1111-import type React from 'react'
12111312export function createCustomBackdrop(
1413 onClose?: () => void,
+3-3
src/view/com/util/EmptyState.tsx
···11-import React from 'react'
11+import {isValidElement} from 'react'
22import {type StyleProp, type TextStyle, type ViewStyle} from 'react-native'
33import {View} from 'react-native'
44···4545 return placeholderIcon
4646 }
47474848- if (React.isValidElement(icon)) {
4848+ if (isValidElement(icon)) {
4949 return icon
5050 }
5151···7777 a.rounded_full,
7878 a.mt_5xl,
7979 {height: 64, width: 64},
8080- React.isValidElement(icon)
8080+ isValidElement(icon)
8181 ? a.bg_transparent
8282 : [isTabletOrDesktop && {marginTop: 50}],
8383 ]}>
···11import {Platform} from 'react-native'
22-import type React from 'react'
3243const onMouseUp = (e: React.MouseEvent & {target: HTMLElement}) => {
54 // Only handle whenever it is the middle button
···11import {ScrollView, StyleSheet, View} from 'react-native'
22-import type React from 'react'
3243import {useColorSchemeStyle} from '#/lib/hooks/useColorSchemeStyle'
54import {useIsKeyboardVisible} from '#/lib/hooks/useIsKeyboardVisible'