diff --git a/native/account/registration/keyserver-selection.react.js b/native/account/registration/keyserver-selection.react.js --- a/native/account/registration/keyserver-selection.react.js +++ b/native/account/registration/keyserver-selection.react.js @@ -2,7 +2,7 @@ import invariant from 'invariant'; import * as React from 'react'; -import { Text, View } from 'react-native'; +import { Text, View, TextInput } from 'react-native'; import { useGetVersion, @@ -59,7 +59,8 @@ const [customKeyserver, setCustomKeyserver] = React.useState( initialKeyserverURL === defaultURLPrefix ? '' : initialKeyserverURL, ); - const customKeyserverTextInputRef = React.useRef(); + const customKeyserverTextInputRef = + React.useRef>(); let initialSelection; if (initialKeyserverURL === defaultURLPrefix) { diff --git a/native/account/registration/password-selection.react.js b/native/account/registration/password-selection.react.js --- a/native/account/registration/password-selection.react.js +++ b/native/account/registration/password-selection.react.js @@ -2,7 +2,7 @@ import invariant from 'invariant'; import * as React from 'react'; -import { View, Text, Platform } from 'react-native'; +import { View, Text, Platform, TextInput } from 'react-native'; import sleep from 'lib/utils/sleep.js'; @@ -112,7 +112,8 @@ errorText = Password cannot be empty; } - const confirmPasswordInputRef = React.useRef(); + const confirmPasswordInputRef = + React.useRef>(); const focusConfirmPasswordInput = React.useCallback(() => { confirmPasswordInputRef.current?.focus(); }, []); @@ -136,7 +137,7 @@ [confirmPasswordEmpty], ); - const passwordInputRef = React.useRef(); + const passwordInputRef = React.useRef>(); const passwordLength = password.length; const onChangePasswordInput = React.useCallback( (input: string) => { diff --git a/native/account/siwe-panel.react.js b/native/account/siwe-panel.react.js --- a/native/account/siwe-panel.react.js +++ b/native/account/siwe-panel.react.js @@ -145,7 +145,7 @@ }, [onSuccessfulWalletSignature, onClosing, closeBottomSheet], ); - const prevClosingRef = React.useRef(); + const prevClosingRef = React.useRef(); React.useEffect(() => { if (closing && !prevClosingRef.current) { closeBottomSheet?.(); diff --git a/native/chat/chat-context.js b/native/chat/chat-context.js --- a/native/chat/chat-context.js +++ b/native/chat/chat-context.js @@ -40,7 +40,7 @@ const chatContext = React.useContext(ChatContext); invariant(chatContext, 'Chat context should be set'); - const measureRegistrationRef = React.useRef(); + const measureRegistrationRef = React.useRef(); if (!measureRegistrationRef.current) { measureRegistrationRef.current = chatContext.registerMeasurer(); } diff --git a/native/chat/chat-thread-list.react.js b/native/chat/chat-thread-list.react.js --- a/native/chat/chat-thread-list.react.js +++ b/native/chat/chat-thread-list.react.js @@ -17,6 +17,7 @@ Platform, TouchableWithoutFeedback, BackHandler, + TextInput, } from 'react-native'; import { FloatingAction } from 'react-native-floating-action'; @@ -111,7 +112,7 @@ }, []); const scrollPos = React.useRef(0); - const flatListRef = React.useRef(); + const flatListRef = React.useRef>(); const onScroll = React.useCallback( (event: ScrollEvent) => { @@ -174,7 +175,7 @@ clearSearch(); }, [clearSearch, onChangeSearchText]); - const searchInputRef = React.useRef(); + const searchInputRef = React.useRef>(); const onPressItem = React.useCallback( (threadInfo: ThreadInfo, pendingPersonalThreadUserInfo?: UserInfo) => { diff --git a/native/chat/compose-subchannel.react.js b/native/chat/compose-subchannel.react.js --- a/native/chat/compose-subchannel.react.js +++ b/native/chat/compose-subchannel.react.js @@ -29,7 +29,10 @@ import { useNavigateToThread } from './message-list-types.js'; import ParentThreadHeader from './parent-thread-header.react.js'; import LinkButton from '../components/link-button.react.js'; -import { createTagInput } from '../components/tag-input.react.js'; +import { + createTagInput, + type BaseTagInput, +} from '../components/tag-input.react.js'; import ThreadList from '../components/thread-list.react.js'; import UserList from '../components/user-list.react.js'; import { useCalendarQuery } from '../navigation/nav-selectors.js'; @@ -65,7 +68,7 @@ const [createButtonEnabled, setCreateButtonEnabled] = React.useState(true); - const tagInputRef = React.useRef(); + const tagInputRef = React.useRef>(); const onUnknownErrorAlertAcknowledged = React.useCallback(() => { setUsernameInputText(''); tagInputRef.current?.focus(); diff --git a/native/chat/message-editing-context-provider.react.js b/native/chat/message-editing-context-provider.react.js --- a/native/chat/message-editing-context-provider.react.js +++ b/native/chat/message-editing-context-provider.react.js @@ -20,7 +20,7 @@ function MessageEditingContextProvider(props: Props): React.Node { const [editState, setEditState] = React.useState(defaultEditState); - const pendingCallbacksRef = React.useRef([]); + const pendingCallbacksRef = React.useRef void>>([]); const setEditedMessage = React.useCallback( (editedMessage: ?MessageInfo, callback?: () => void) => { diff --git a/native/chat/message-reactions-modal.react.js b/native/chat/message-reactions-modal.react.js --- a/native/chat/message-reactions-modal.react.js +++ b/native/chat/message-reactions-modal.react.js @@ -49,7 +49,7 @@ const navigateToUserProfileBottomSheet = useNavigateToUserProfileBottomSheet(); - const [selectedUserID, setSelectedUserID] = React.useState(); + const [selectedUserID, setSelectedUserID] = React.useState(); // This useEffect will call navigateToUserProfileBottomSheet whenever the // MessageReactionsModal is unmounting and there is a selectedUserID. diff --git a/native/chat/message-results-screen.react.js b/native/chat/message-results-screen.react.js --- a/native/chat/message-results-screen.react.js +++ b/native/chat/message-results-screen.react.js @@ -11,6 +11,7 @@ createMessageInfo, isInvalidPinSourceForThread, } from 'lib/shared/message-utils.js'; +import type { RawMessageInfo } from 'lib/types/message-types.js'; import type { MinimallyEncodedThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js'; import type { ThreadInfo } from 'lib/types/thread-types.js'; @@ -22,6 +23,7 @@ import { useSelector } from '../redux/redux-utils.js'; import { useStyles } from '../themes/colors.js'; import type { ChatMessageItemWithHeight } from '../types/chat-types.js'; +import type { VerticalBounds } from '../types/layout-types.js'; export type MessageResultsScreenParams = { +threadInfo: ThreadInfo | MinimallyEncodedThreadInfo, @@ -37,13 +39,18 @@ const { threadInfo } = route.params; const styles = useStyles(unboundStyles); const { id: threadID } = threadInfo; - const [rawMessageResults, setRawMessageResults] = React.useState([]); + const [rawMessageResults, setRawMessageResults] = React.useState< + $ReadOnlyArray, + >([]); const measureMessages = useHeightMeasurer(); - const [measuredMessages, setMeasuredMessages] = React.useState([]); + const [measuredMessages, setMeasuredMessages] = React.useState< + $ReadOnlyArray, + >([]); - const [messageVerticalBounds, setMessageVerticalBounds] = React.useState(); - const scrollViewContainerRef = React.useRef(); + const [messageVerticalBounds, setMessageVerticalBounds] = + React.useState(); + const scrollViewContainerRef = React.useRef>(); const callFetchPinnedMessages = useFetchPinnedMessages(); const userInfos = useSelector(state => state.userStore.userInfos); diff --git a/native/chat/settings/add-users-modal.react.js b/native/chat/settings/add-users-modal.react.js --- a/native/chat/settings/add-users-modal.react.js +++ b/native/chat/settings/add-users-modal.react.js @@ -23,7 +23,10 @@ import Button from '../../components/button.react.js'; import Modal from '../../components/modal.react.js'; -import { createTagInput } from '../../components/tag-input.react.js'; +import { + createTagInput, + type BaseTagInput, +} from '../../components/tag-input.react.js'; import UserList from '../../components/user-list.react.js'; import type { RootNavigationProp } from '../../navigation/root-navigator.react.js'; import type { NavigationRoute } from '../../navigation/route-names.js'; @@ -56,7 +59,7 @@ $ReadOnlyArray, >([]); - const tagInputRef = React.useRef(); + const tagInputRef = React.useRef>(); const onUnknownErrorAlertAcknowledged = React.useCallback(() => { setUsernameInputText(''); setUserInfoInputArray([]); diff --git a/native/chat/settings/thread-settings-media-gallery.react.js b/native/chat/settings/thread-settings-media-gallery.react.js --- a/native/chat/settings/thread-settings-media-gallery.react.js +++ b/native/chat/settings/thread-settings-media-gallery.react.js @@ -48,7 +48,7 @@ const galleryItemWidth = (width - 32 - (numColumns - 1) * galleryItemGap) / numColumns; const { threadID, limit, verticalBounds, offset, activeTab } = props; - const [mediaInfos, setMediaInfos] = React.useState([]); + const [mediaInfos, setMediaInfos] = React.useState<$ReadOnlyArray>([]); const callFetchThreadMedia = useFetchThreadMedia(); React.useEffect(() => { @@ -153,7 +153,7 @@ function MediaGalleryItem(props: MediaGalleryItemProps): React.Node { const navigation = useNavigation(); const route = useRoute(); - const ref = React.useRef(null); + const ref = React.useRef>(null); const onLayout = React.useCallback(() => {}, []); const { threadID, verticalBounds, memoizedStyles, item, index } = props; diff --git a/native/chat/swipeable-thread.react.js b/native/chat/swipeable-thread.react.js --- a/native/chat/swipeable-thread.react.js +++ b/native/chat/swipeable-thread.react.js @@ -3,6 +3,8 @@ import MaterialIcon from '@expo/vector-icons/MaterialCommunityIcons.js'; import { useNavigation } from '@react-navigation/native'; import * as React from 'react'; +// eslint-disable-next-line import/extensions +import SwipeableComponent from 'react-native-gesture-handler/Swipeable'; import useToggleUnreadStatus from 'lib/hooks/toggle-unread-status.js'; import type { ThreadInfo } from 'lib/types/thread-types.js'; @@ -18,7 +20,7 @@ +children: React.Node, }; function SwipeableThread(props: Props): React.Node { - const swipeable = React.useRef(); + const swipeable = React.useRef(); const navigation = useNavigation(); React.useEffect(() => { return navigation.addListener('blur', () => { diff --git a/native/chat/thread-list-modal.react.js b/native/chat/thread-list-modal.react.js --- a/native/chat/thread-list-modal.react.js +++ b/native/chat/thread-list-modal.react.js @@ -61,7 +61,8 @@ modalTitle, } = props; - const searchTextInputRef = React.useRef(); + const searchTextInputRef = + React.useRef>(); const setSearchTextInputRef = React.useCallback( async (textInput: ?React.ElementRef) => { searchTextInputRef.current = textInput; diff --git a/native/community-creation/community-creation-members.react.js b/native/community-creation/community-creation-members.react.js --- a/native/community-creation/community-creation-members.react.js +++ b/native/community-creation/community-creation-members.react.js @@ -25,7 +25,10 @@ import RegistrationContainer from '../account/registration/registration-container.react.js'; import { useNavigateToThread } from '../chat/message-list-types.js'; import LinkButton from '../components/link-button.react.js'; -import { createTagInput } from '../components/tag-input.react.js'; +import { + createTagInput, + type BaseTagInput, +} from '../components/tag-input.react.js'; import UserList from '../components/user-list.react.js'; import type { NavigationRoute } from '../navigation/route-names.js'; import { useSelector } from '../redux/redux-utils.js'; @@ -175,7 +178,7 @@ [otherUserInfos, selectedUserIDs], ); - const tagInputRef = React.useRef(); + const tagInputRef = React.useRef>(); return ( diff --git a/native/components/gesture-touchable-opacity.react.js b/native/components/gesture-touchable-opacity.react.js --- a/native/components/gesture-touchable-opacity.react.js +++ b/native/components/gesture-touchable-opacity.react.js @@ -116,12 +116,12 @@ const curOpacity = useValue(1); - const pressClockRef = React.useRef(); + const pressClockRef = React.useRef(); if (!pressClockRef.current) { pressClockRef.current = new Clock(); } const pressClock = pressClockRef.current; - const resetClockRef = React.useRef(); + const resetClockRef = React.useRef(); if (!resetClockRef.current) { resetClockRef.current = new Clock(); } diff --git a/native/components/search.react.js b/native/components/search.react.js --- a/native/components/search.react.js +++ b/native/components/search.react.js @@ -39,7 +39,7 @@ const loggedIn = useSelector(isLoggedIn); const styles = useStyles(unboundStyles); const colors = useColors(); - const prevLoggedInRef = React.useRef(); + const prevLoggedInRef = React.useRef(); React.useEffect(() => { const prevLoggedIn = prevLoggedInRef.current; prevLoggedInRef.current = loggedIn; diff --git a/native/media/video-playback-modal.react.js b/native/media/video-playback-modal.react.js --- a/native/media/video-playback-modal.react.js +++ b/native/media/video-playback-modal.react.js @@ -41,6 +41,11 @@ NativeMethods, >; +type VideoRef = { + +seek: number => mixed, + ... +}; + /* eslint-disable import/no-named-as-default-member */ const { Extrapolate, @@ -175,7 +180,7 @@ const footerY = useValue(-1); const footerWidth = useValue(-1); const footerHeight = useValue(-1); - const footerRef = React.useRef(); + const footerRef = React.useRef>(); const footer = footerRef.current; const onFooterLayoutCalledRef = React.useRef(false); const onFooterLayout = React.useCallback(() => { @@ -571,7 +576,7 @@ const [spinnerVisible, setSpinnerVisible] = useState(true); const [timeElapsed, setTimeElapsed] = useState('0:00'); const [totalDuration, setTotalDuration] = useState('0:00'); - const videoRef = React.useRef(); + const videoRef = React.useRef(); const backgroundedOrInactive = useIsAppBackgroundedOrInactive(); React.useEffect(() => { diff --git a/native/navigation/deep-links-context-provider.react.js b/native/navigation/deep-links-context-provider.react.js --- a/native/navigation/deep-links-context-provider.react.js +++ b/native/navigation/deep-links-context-provider.react.js @@ -44,7 +44,7 @@ }; function DeepLinksContextProvider(props: Props): React.Node { const { children } = props; - const [currentLink, setCurrentLink] = React.useState(null); + const [currentLink, setCurrentLink] = React.useState(null); React.useEffect(() => { // This listener listens for an event where a user clicked a link when the diff --git a/native/navigation/disconnected-bar.react.js b/native/navigation/disconnected-bar.react.js --- a/native/navigation/disconnected-bar.react.js +++ b/native/navigation/disconnected-bar.react.js @@ -25,7 +25,7 @@ }; function DisconnectedBar(props: Props): React.Node { const { shouldShowDisconnectedBar } = useShouldShowDisconnectedBar(); - const showingRef = React.useRef(); + const showingRef = React.useRef(); if (!showingRef.current) { showingRef.current = new Animated.Value(shouldShowDisconnectedBar ? 1 : 0); } diff --git a/native/navigation/navigation-handler.react.js b/native/navigation/navigation-handler.react.js --- a/native/navigation/navigation-handler.react.js +++ b/native/navigation/navigation-handler.react.js @@ -66,7 +66,7 @@ const loggedIn = hasCurrentUserInfo && hasUserCookie; const navLoggedIn = useIsAppLoggedIn(); - const prevLoggedInRef = React.useRef(); + const prevLoggedInRef = React.useRef(); React.useEffect(() => { if (loggedIn === prevLoggedInRef.current) { diff --git a/native/navigation/tab-bar.react.js b/native/navigation/tab-bar.react.js --- a/native/navigation/tab-bar.react.js +++ b/native/navigation/tab-bar.react.js @@ -8,7 +8,10 @@ import { useDispatch } from 'lib/utils/redux-utils.js'; -import { KeyboardContext } from '../keyboard/keyboard-state.js'; +import { + KeyboardContext, + type KeyboardState, +} from '../keyboard/keyboard-state.js'; import { updateDimensionsActiveType } from '../redux/action-types.js'; import { useSelector } from '../redux/redux-utils.js'; import type { LayoutEvent } from '../types/react-native.js'; @@ -21,7 +24,7 @@ type Props = React.ElementConfig; function TabBar(props: Props) { - const tabBarVisibleRef = React.useRef(); + const tabBarVisibleRef = React.useRef(); if (!tabBarVisibleRef.current) { tabBarVisibleRef.current = new Value(1); } @@ -30,7 +33,7 @@ const keyboardState = React.useContext(KeyboardContext); const shouldHideTabBar = keyboardState?.mediaGalleryOpen; - const prevKeyboardStateRef = React.useRef(); + const prevKeyboardStateRef = React.useRef(); React.useEffect(() => { prevKeyboardStateRef.current = keyboardState; }, [keyboardState]); @@ -54,7 +57,7 @@ [keyboardState, prevKeyboardState, tabBarVisible], ); - const prevShouldHideTabBarRef = React.useRef(false); + const prevShouldHideTabBarRef = React.useRef(false); React.useEffect(() => { const prevShouldHideTabBar = prevShouldHideTabBarRef.current; if (shouldHideTabBar && !prevShouldHideTabBar) { diff --git a/native/profile/keyserver-selection-bottom-sheet.react.js b/native/profile/keyserver-selection-bottom-sheet.react.js --- a/native/profile/keyserver-selection-bottom-sheet.react.js +++ b/native/profile/keyserver-selection-bottom-sheet.react.js @@ -48,7 +48,8 @@ invariant(bottomSheetContext, 'bottomSheetContext should be set'); const { setContentHeight } = bottomSheetContext; - const removeKeyserverContainerRef = React.useRef(); + const removeKeyserverContainerRef = + React.useRef>(); const bottomSheetRef = React.useRef(); const colors = useColors(); diff --git a/native/profile/secondary-device-qr-code-scanner.react.js b/native/profile/secondary-device-qr-code-scanner.react.js --- a/native/profile/secondary-device-qr-code-scanner.react.js +++ b/native/profile/secondary-device-qr-code-scanner.react.js @@ -20,7 +20,7 @@ }; // eslint-disable-next-line no-unused-vars function SecondaryDeviceQRCodeScanner(props: Props): React.Node { - const [hasPermission, setHasPermission] = React.useState(null); + const [hasPermission, setHasPermission] = React.useState(null); const [scanned, setScanned] = React.useState(false); const styles = useStyles(unboundStyles); diff --git a/native/redux/dimensions-updater.react.js b/native/redux/dimensions-updater.react.js --- a/native/redux/dimensions-updater.react.js +++ b/native/redux/dimensions-updater.react.js @@ -62,7 +62,7 @@ const frame = useSafeAreaFrame(); const insets = useSafeAreaInsets(); - const keyboardShowingRef = React.useRef(); + const keyboardShowingRef = React.useRef(); const keyboardShow = React.useCallback(() => { keyboardShowingRef.current = true; }, []); diff --git a/native/root.react.js b/native/root.react.js --- a/native/root.react.js +++ b/native/root.react.js @@ -6,6 +6,7 @@ import type { PossiblyStaleNavigationState, UnsafeContainerActionEvent, + GenericNavigationAction, } from '@react-navigation/core'; import { useReduxDevToolsExtension } from '@react-navigation/devtools'; import { NavigationContainer } from '@react-navigation/native'; @@ -50,7 +51,10 @@ import { defaultNavigationState } from './navigation/default-state.js'; import DisconnectedBarVisibilityHandler from './navigation/disconnected-bar-visibility-handler.react.js'; import { setGlobalNavContext } from './navigation/icky-global.js'; -import { NavContext } from './navigation/navigation-context.js'; +import { + NavContext, + type NavContextType, +} from './navigation/navigation-context.js'; import NavigationHandler from './navigation/navigation-handler.react.js'; import { validNavState } from './navigation/navigation-utils.js'; import OrientationHandler from './navigation/orientation-handler.react.js'; @@ -86,15 +90,20 @@ SplashScreen.preventAutoHideAsync().catch(console.log); function Root() { - const navStateRef = React.useRef(); - const navDispatchRef = React.useRef(); + const navStateRef = React.useRef(); + const navDispatchRef = + React.useRef GenericNavigationAction), + ) => void>(); const navStateInitializedRef = React.useRef(false); // We call this here to start the loading process // We gate the UI on the fonts loading in AppNavigator useLoadCommFonts(); - const [navContext, setNavContext] = React.useState(null); + const [navContext, setNavContext] = React.useState(null); const updateNavContext = React.useCallback(() => { if ( !navStateRef.current || @@ -165,7 +174,7 @@ ); const frozen = useSelector(state => state.frozen); - const queuedActionsRef = React.useRef([]); + const queuedActionsRef = React.useRef>([]); const onNavigationStateChange = React.useCallback( (state: ?PossiblyStaleNavigationState) => { invariant(state, 'nav state should be non-null'); @@ -200,7 +209,8 @@ [updateNavContext, frozen], ); - const navContainerRef = React.useRef(); + const navContainerRef = + React.useRef>(); const containerRef = React.useCallback( (navContainer: ?React.ElementRef) => { navContainerRef.current = navContainer; diff --git a/native/search/message-search.react.js b/native/search/message-search.react.js --- a/native/search/message-search.react.js +++ b/native/search/message-search.react.js @@ -26,6 +26,7 @@ import { useSelector } from '../redux/redux-utils.js'; import { useStyles } from '../themes/colors.js'; import type { ChatMessageItemWithHeight } from '../types/chat-types.js'; +import type { VerticalBounds } from '../types/layout-types.js'; export type MessageSearchParams = { +threadInfo: ThreadInfo | MinimallyEncodedThreadInfo, @@ -47,7 +48,9 @@ }, [props.navigation, clearQuery]); const [lastID, setLastID] = React.useState(); - const [searchResults, setSearchResults] = React.useState([]); + const [searchResults, setSearchResults] = React.useState< + $ReadOnlyArray, + >([]); const [endReached, setEndReached] = React.useState(false); const appendSearchResults = React.useCallback( @@ -112,7 +115,9 @@ return result; }, [chatMessageInfos, endReached, translatedSearchResults]); - const [measuredMessages, setMeasuredMessages] = React.useState([]); + const [measuredMessages, setMeasuredMessages] = React.useState< + $ReadOnlyArray, + >([]); const measureMessages = useHeightMeasurer(); const measureCallback = React.useCallback( @@ -126,8 +131,9 @@ measureMessages(filteredChatMessageInfos, threadInfo, measureCallback); }, [filteredChatMessageInfos, measureCallback, measureMessages, threadInfo]); - const [messageVerticalBounds, setMessageVerticalBounds] = React.useState(); - const scrollViewContainerRef = React.useRef(); + const [messageVerticalBounds, setMessageVerticalBounds] = + React.useState(); + const scrollViewContainerRef = React.useRef>(); const onLayout = React.useCallback(() => { scrollViewContainerRef.current?.measure( diff --git a/native/user-profile/user-profile-avatar.react.js b/native/user-profile/user-profile-avatar.react.js --- a/native/user-profile/user-profile-avatar.react.js +++ b/native/user-profile/user-profile-avatar.react.js @@ -25,7 +25,7 @@ const overlayContext = React.useContext(OverlayContext); - const avatarRef = React.useRef(); + const avatarRef = React.useRef>(); const onPressAvatar = React.useCallback(() => { invariant(overlayContext, 'UserProfileAvatar should have OverlayContext'); diff --git a/native/user-profile/user-profile-menu-button.react.js b/native/user-profile/user-profile-menu-button.react.js --- a/native/user-profile/user-profile-menu-button.react.js +++ b/native/user-profile/user-profile-menu-button.react.js @@ -42,7 +42,7 @@ const overlayContext = React.useContext(OverlayContext); - const menuButtonRef = React.useRef(); + const menuButtonRef = React.useRef>(); const visibleTooltipActionEntryIDs = React.useMemo(() => { const result = []; diff --git a/native/utils/animation-utils.js b/native/utils/animation-utils.js --- a/native/utils/animation-utils.js +++ b/native/utils/animation-utils.js @@ -184,7 +184,7 @@ } function useReanimatedValueForBoolean(booleanValue: boolean): Value { - const reanimatedValueRef = React.useRef(); + const reanimatedValueRef = React.useRef(); if (!reanimatedValueRef.current) { reanimatedValueRef.current = new Value(booleanValue ? 1 : 0); }