From 4c4ebd0510df48b136e9bf6aee5cdf348d428e1c Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Tue, 9 Jun 2026 17:20:34 +0300 Subject: [PATCH] Catch NotAllowedError in web GIF player + lint modules/ (#10806) --- eslint-suppressions.json | 109 ++++++++++++++++++ .../expo-bluesky-gif-view/src/GifView.web.tsx | 13 ++- .../src/VisibilityView/index.native.tsx | 6 +- package.json | 2 +- 4 files changed, 125 insertions(+), 5 deletions(-) diff --git a/eslint-suppressions.json b/eslint-suppressions.json index fffa450d37..59b062cc7b 100644 --- a/eslint-suppressions.json +++ b/eslint-suppressions.json @@ -1,4 +1,113 @@ { + "modules/bottom-sheet/src/BottomSheetNativeComponent.tsx": { + "@typescript-eslint/no-explicit-any": { + "count": 2 + }, + "@typescript-eslint/no-unsafe-call": { + "count": 2 + }, + "@typescript-eslint/no-unsafe-member-access": { + "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": { + "@typescript-eslint/require-await": { + "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 + }, + "@typescript-eslint/no-unsafe-member-access": { + "count": 3 + } + }, + "modules/expo-bluesky-swiss-army/src/Referrer/index.android.ts": { + "@typescript-eslint/no-unsafe-call": { + "count": 2 + }, + "@typescript-eslint/no-unsafe-member-access": { + "count": 2 + } + }, + "modules/expo-bluesky-swiss-army/src/SharedPrefs/index.native.ts": { + "@typescript-eslint/no-explicit-any": { + "count": 1 + }, + "@typescript-eslint/no-unsafe-call": { + "count": 9 + }, + "@typescript-eslint/no-unsafe-member-access": { + "count": 9 + } + }, + "modules/expo-bluesky-swiss-army/src/VisibilityView/index.native.tsx": { + "@typescript-eslint/no-unsafe-call": { + "count": 1 + }, + "@typescript-eslint/no-unsafe-member-access": { + "count": 1 + }, + "no-restricted-imports": { + "count": 1 + } + }, + "modules/expo-bluesky-swiss-army/src/VisibilityView/index.tsx": { + "@typescript-eslint/require-await": { + "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 diff --git a/modules/expo-bluesky-gif-view/src/GifView.web.tsx b/modules/expo-bluesky-gif-view/src/GifView.web.tsx index c9f439bffe..e51b9bf9fc 100644 --- a/modules/expo-bluesky-gif-view/src/GifView.web.tsx +++ b/modules/expo-bluesky-gif-view/src/GifView.web.tsx @@ -67,7 +67,18 @@ export class GifView extends PureComponent { } async playAsync(): Promise { - this.videoPlayerRef.current?.play() + try { + await this.videoPlayerRef.current?.play() + } catch (err) { + // `play()` rejects with a NotAllowedError when the browser blocks + // playback (e.g. Safari low-power mode or autoplay policy). This is + // expected and benign - the GIF simply stays paused - so swallow it + // rather than letting it surface as an unhandled rejection. + if (err instanceof DOMException && err.name === 'NotAllowedError') { + return + } + throw err + } } async pauseAsync(): Promise { 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 9d0e8cf220..aba96c6d4b 100644 --- a/modules/expo-bluesky-swiss-army/src/VisibilityView/index.native.tsx +++ b/modules/expo-bluesky-swiss-army/src/VisibilityView/index.native.tsx @@ -1,12 +1,12 @@ import React from 'react' -import {StyleProp, ViewStyle} from 'react-native' +import {type StyleProp, type ViewStyle} from 'react-native' import {requireNativeModule, requireNativeViewManager} from 'expo-modules-core' -import {VisibilityViewProps} from './types' +import {type VisibilityViewProps} from './types' const NativeView: React.ComponentType<{ onChangeStatus: (e: {nativeEvent: {isActive: boolean}}) => void children: React.ReactNode - enabled: Boolean + enabled: boolean style: StyleProp }> = requireNativeViewManager('ExpoBlueskyVisibilityView') diff --git a/package.json b/package.json index e054aca94a..8853eb2210 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "test-watch": "NODE_ENV=test jest --watchAll", "test-ci": "NODE_ENV=test jest --ci --forceExit --reporters=default --reporters=jest-junit", "test-coverage": "NODE_ENV=test jest --coverage", - "lint": "eslint --cache --quiet src", + "lint": "eslint --cache --quiet src modules", "lint-native": "swiftlint ./modules && ktlint ./modules", "lint-native:fix": "swiftlint --fix ./modules && ktlint --format ./modules", "typecheck": "tsgo --project ./tsconfig.check.json",