diff --git a/eslint-suppressions.json b/eslint-suppressions.json index 06ac176613..1692a6b1a2 100644 --- a/eslint-suppressions.json +++ b/eslint-suppressions.json @@ -10,22 +10,9 @@ "count": 2 } }, - "modules/bottom-sheet/src/BottomSheetPortal.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, - "modules/bottom-sheet/src/lib/Portal.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "modules/expo-background-notification-handler/src/BackgroundNotificationHandlerProvider.tsx": { "@typescript-eslint/no-floating-promises": { "count": 1 - }, - "no-restricted-imports": { - "count": 1 } }, "modules/expo-background-notification-handler/src/ExpoBackgroundNotificationHandlerModule.web.ts": { @@ -33,28 +20,6 @@ "count": 4 } }, - "modules/expo-bluesky-gif-view/src/GifView.tsx": { - "@typescript-eslint/no-explicit-any": { - "count": 2 - }, - "@typescript-eslint/no-unsafe-call": { - "count": 4 - }, - "@typescript-eslint/no-unsafe-member-access": { - "count": 4 - }, - "no-restricted-imports": { - "count": 1 - } - }, - "modules/expo-bluesky-gif-view/src/GifView.web.tsx": { - "@typescript-eslint/no-floating-promises": { - "count": 2 - }, - "@typescript-eslint/require-await": { - "count": 2 - } - }, "modules/expo-bluesky-swiss-army/src/PlatformInfo/index.native.ts": { "@typescript-eslint/no-unsafe-call": { "count": 3 @@ -88,9 +53,6 @@ }, "@typescript-eslint/no-unsafe-member-access": { "count": 1 - }, - "no-restricted-imports": { - "count": 1 } }, "modules/expo-bluesky-swiss-army/src/VisibilityView/index.tsx": { @@ -98,16 +60,6 @@ "count": 1 } }, - "modules/expo-bluesky-swiss-army/src/VisibilityView/types.ts": { - "no-restricted-imports": { - "count": 1 - } - }, - "modules/expo-emoji-picker/src/EmojiPickerView.tsx": { - "no-restricted-imports": { - "count": 1 - } - }, "src/Navigation.tsx": { "@typescript-eslint/no-floating-promises": { "count": 1 @@ -2118,11 +2070,6 @@ "count": 1 } }, - "src/view/com/composer/videos/pickVideo.web.ts": { - "@typescript-eslint/no-misused-promises": { - "count": 1 - } - }, "src/view/com/feeds/ComposerPrompt.tsx": { "@typescript-eslint/no-explicit-any": { "count": 2 diff --git a/modules/bottom-sheet/src/BottomSheetPortal.tsx b/modules/bottom-sheet/src/BottomSheetPortal.tsx index e259a28626..c02504575f 100644 --- a/modules/bottom-sheet/src/BottomSheetPortal.tsx +++ b/modules/bottom-sheet/src/BottomSheetPortal.tsx @@ -1,20 +1,20 @@ -import React from 'react' +import {createContext, useContext, useMemo} from 'react' import {createPortalGroup_INTERNAL} from './lib/Portal' type PortalContext = React.ElementType<{children: React.ReactNode}> -export const Context = React.createContext({} as PortalContext) +export const Context = createContext({} as PortalContext) Context.displayName = 'BottomSheetPortalContext' -export const useBottomSheetPortal_INTERNAL = () => React.useContext(Context) +export const useBottomSheetPortal_INTERNAL = () => useContext(Context) export function BottomSheetPortalProvider({ children, }: { children: React.ReactNode }) { - const portal = React.useMemo(() => { + const portal = useMemo(() => { return createPortalGroup_INTERNAL() }, []) diff --git a/modules/bottom-sheet/src/lib/Portal.tsx b/modules/bottom-sheet/src/lib/Portal.tsx index 4dad2d8d2b..5c4d953fc2 100644 --- a/modules/bottom-sheet/src/lib/Portal.tsx +++ b/modules/bottom-sheet/src/lib/Portal.tsx @@ -1,4 +1,14 @@ -import React from 'react' +import { + createContext, + Fragment, + useCallback, + useContext, + useEffect, + useId, + useMemo, + useRef, + useState, +} from 'react' type Component = React.ReactElement @@ -13,7 +23,7 @@ type ComponentMap = { } export function createPortalGroup_INTERNAL() { - const Context = React.createContext({ + const Context = createContext({ outlet: null, append: () => {}, remove: () => {}, @@ -21,21 +31,21 @@ export function createPortalGroup_INTERNAL() { Context.displayName = 'BottomSheetPortalContext' function Provider(props: React.PropsWithChildren<{}>) { - const map = React.useRef({}) - const [outlet, setOutlet] = React.useState(null) + const map = useRef({}) + const [outlet, setOutlet] = useState(null) - const append = React.useCallback((id, component) => { + const append = useCallback((id, component) => { if (map.current[id]) return - map.current[id] = {component} + map.current[id] = {component} setOutlet(<>{Object.values(map.current)}) }, []) - const remove = React.useCallback(id => { + const remove = useCallback(id => { delete map.current[id] setOutlet(<>{Object.values(map.current)}) }, []) - const contextValue = React.useMemo( + const contextValue = useMemo( () => ({ outlet, append, @@ -50,14 +60,14 @@ export function createPortalGroup_INTERNAL() { } function Outlet() { - const ctx = React.useContext(Context) + const ctx = useContext(Context) return ctx.outlet } function Portal({children}: React.PropsWithChildren<{}>) { - const {append, remove} = React.useContext(Context) - const id = React.useId() - React.useEffect(() => { + const {append, remove} = useContext(Context) + const id = useId() + useEffect(() => { append(id, children as Component) return () => remove(id) }, [id, children, append, remove]) diff --git a/modules/expo-background-notification-handler/src/BackgroundNotificationHandlerProvider.tsx b/modules/expo-background-notification-handler/src/BackgroundNotificationHandlerProvider.tsx index fed40c38bf..51e4d61863 100644 --- a/modules/expo-background-notification-handler/src/BackgroundNotificationHandlerProvider.tsx +++ b/modules/expo-background-notification-handler/src/BackgroundNotificationHandlerProvider.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import {createContext, useContext, useEffect, useMemo, useState} from 'react' import {type BackgroundNotificationHandlerPreferences} from './ExpoBackgroundNotificationHandler.types' import {BackgroundNotificationHandler} from './ExpoBackgroundNotificationHandlerModule' @@ -11,11 +11,10 @@ interface BackgroundNotificationPreferencesContext { ) => void } -const Context = React.createContext( +const Context = createContext( {} as BackgroundNotificationPreferencesContext, ) -export const useBackgroundNotificationPreferences = () => - React.useContext(Context) +export const useBackgroundNotificationPreferences = () => useContext(Context) export function BackgroundNotificationPreferencesProvider({ children, @@ -23,18 +22,18 @@ export function BackgroundNotificationPreferencesProvider({ children: React.ReactNode }) { const [preferences, setPreferences] = - React.useState({ + useState({ playSoundChat: true, }) - React.useEffect(() => { + useEffect(() => { ;(async () => { const prefs = await BackgroundNotificationHandler.getAllPrefsAsync() setPreferences(prefs) })() }, []) - const value = React.useMemo( + const value = useMemo( () => ({ preferences, setPref: async < diff --git a/modules/expo-bluesky-gif-view/src/GifView.tsx b/modules/expo-bluesky-gif-view/src/GifView.tsx index 0cca26cf5e..c1d6ecddc0 100644 --- a/modules/expo-bluesky-gif-view/src/GifView.tsx +++ b/modules/expo-bluesky-gif-view/src/GifView.tsx @@ -1,17 +1,24 @@ -import React from 'react' +import {createRef, PureComponent} from 'react' import {requireNativeModule} from 'expo' import {requireNativeViewManager} from 'expo-modules-core' import {type GifViewProps} from './GifView.types' -const NativeModule = requireNativeModule('ExpoBlueskyGifView') +interface GifViewNativeRef { + playAsync: () => Promise + pauseAsync: () => Promise + toggleAsync: () => Promise +} + +const NativeModule: { + prefetchAsync: (sources: string[]) => Promise +} = requireNativeModule('ExpoBlueskyGifView') const NativeView: React.ComponentType< - GifViewProps & {ref: React.RefObject} + GifViewProps & {ref: React.RefObject} > = requireNativeViewManager('ExpoBlueskyGifView') -export class GifView extends React.PureComponent { - // TODO native types, should all be the same as those in this class - private nativeRef: React.RefObject = React.createRef() +export class GifView extends PureComponent { + private nativeRef: React.RefObject = createRef() constructor(props: GifViewProps | Readonly) { super(props) @@ -22,15 +29,15 @@ export class GifView extends React.PureComponent { } async playAsync(): Promise { - await this.nativeRef.current.playAsync() + await this.nativeRef.current?.playAsync() } async pauseAsync(): Promise { - await this.nativeRef.current.pauseAsync() + await this.nativeRef.current?.pauseAsync() } async toggleAsync(): Promise { - await this.nativeRef.current.toggleAsync() + await this.nativeRef.current?.toggleAsync() } render() { diff --git a/modules/expo-bluesky-gif-view/src/GifView.web.tsx b/modules/expo-bluesky-gif-view/src/GifView.web.tsx index e51b9bf9fc..379ced95ca 100644 --- a/modules/expo-bluesky-gif-view/src/GifView.web.tsx +++ b/modules/expo-bluesky-gif-view/src/GifView.web.tsx @@ -1,10 +1,11 @@ -import {createRef, PureComponent, type RefObject} from 'react' +import {createRef, PureComponent} from 'react' import {StyleSheet} from 'react-native' import {type GifViewProps} from './GifView.types' export class GifView extends PureComponent { - private readonly videoPlayerRef: RefObject = createRef() + private readonly videoPlayerRef: React.RefObject = + createRef() private isLoaded = false constructor(props: GifViewProps | Readonly) { @@ -18,9 +19,9 @@ export class GifView extends PureComponent { componentDidUpdate(prevProps: Readonly) { if (prevProps.autoplay !== this.props.autoplay) { if (this.props.autoplay) { - this.playAsync() + void this.playAsync() } else { - this.pauseAsync() + void this.pauseAsync() } } } @@ -29,6 +30,7 @@ export class GifView extends PureComponent { document.removeEventListener('visibilitychange', this.onVisibilityChange) } + // eslint-disable-next-line @typescript-eslint/require-await static async prefetchAsync(_: string[]): Promise { console.warn('prefetchAsync is not supported on web') } @@ -81,6 +83,7 @@ export class GifView extends PureComponent { } } + // eslint-disable-next-line @typescript-eslint/require-await async pauseAsync(): Promise { this.videoPlayerRef.current?.pause() } @@ -102,12 +105,12 @@ export class GifView extends PureComponent { // When `` children are present, omit `src` so the browser // walks the source list and picks via canPlayType. src={useSources ? undefined : source} - autoPlay={autoplay ? 'autoplay' : undefined} + autoPlay={autoplay ? true : undefined} preload={autoplay ? 'auto' : undefined} playsInline={true} - loop="loop" - muted="muted" - style={StyleSheet.flatten(style)} + loop={true} + muted={true} + style={StyleSheet.flatten(style) as React.CSSProperties} onCanPlay={this.onLoad} onPlay={this.firePlayerStateChangeEvent} onPause={this.firePlayerStateChangeEvent} diff --git a/modules/expo-bluesky-swiss-army/src/VisibilityView/index.native.tsx b/modules/expo-bluesky-swiss-army/src/VisibilityView/index.native.tsx index aba96c6d4b..71e0515040 100644 --- a/modules/expo-bluesky-swiss-army/src/VisibilityView/index.native.tsx +++ b/modules/expo-bluesky-swiss-army/src/VisibilityView/index.native.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import {useCallback} from 'react' import {type StyleProp, type ViewStyle} from 'react-native' import {requireNativeModule, requireNativeViewManager} from 'expo-modules-core' @@ -21,7 +21,7 @@ export default function VisibilityView({ onChangeStatus: onChangeStatusOuter, enabled, }: VisibilityViewProps) { - const onChangeStatus = React.useCallback( + const onChangeStatus = useCallback( (e: {nativeEvent: {isActive: boolean}}) => { onChangeStatusOuter(e.nativeEvent.isActive) }, diff --git a/modules/expo-bluesky-swiss-army/src/VisibilityView/types.ts b/modules/expo-bluesky-swiss-army/src/VisibilityView/types.ts index f0852cf120..1c10bf3c57 100644 --- a/modules/expo-bluesky-swiss-army/src/VisibilityView/types.ts +++ b/modules/expo-bluesky-swiss-army/src/VisibilityView/types.ts @@ -1,4 +1,3 @@ -import type React from 'react' export interface VisibilityViewProps { children: React.ReactNode onChangeStatus: (isActive: boolean) => void diff --git a/modules/expo-emoji-picker/src/EmojiPickerView.tsx b/modules/expo-emoji-picker/src/EmojiPickerView.tsx index 0dff25fb55..05f2e75086 100644 --- a/modules/expo-emoji-picker/src/EmojiPickerView.tsx +++ b/modules/expo-emoji-picker/src/EmojiPickerView.tsx @@ -1,5 +1,4 @@ import {requireNativeView} from 'expo' -import type * as React from 'react' import { type EmojiPickerNativeViewProps, diff --git a/tsconfig.check.json b/tsconfig.check.json index fbe94ed1a4..f9f1370f6d 100644 --- a/tsconfig.check.json +++ b/tsconfig.check.json @@ -1,4 +1,4 @@ { "extends": "./tsconfig.json", - "include": ["src", "app.config.js"] + "include": ["src", "modules", "app.config.js"] }