diff --git a/src/lib/haptics.ts b/src/lib/haptics.ts index 3971c7e085..02940f793d 100644 --- a/src/lib/haptics.ts +++ b/src/lib/haptics.ts @@ -1,14 +1,20 @@ +import React from 'react' import {impactAsync, ImpactFeedbackStyle} from 'expo-haptics' import {isIOS, isWeb} from 'platform/detection' +import {useHapticsDisabled} from 'state/preferences/disable-haptics' const hapticImpact: ImpactFeedbackStyle = isIOS ? ImpactFeedbackStyle.Medium : ImpactFeedbackStyle.Light // Users said the medium impact was too strong on Android; see APP-537s -export function playHaptic(disabled: boolean) { - if (disabled || isWeb) { - return - } - impactAsync(hapticImpact) +export function useHaptics() { + const isHapticsDisabled = useHapticsDisabled() + + return React.useCallback(() => { + if (isHapticsDisabled || isWeb) { + return + } + impactAsync(hapticImpact) + }, [isHapticsDisabled]) } diff --git a/src/view/com/util/post-ctrls/PostCtrls.tsx b/src/view/com/util/post-ctrls/PostCtrls.tsx index cb49f36615..cd4a363730 100644 --- a/src/view/com/util/post-ctrls/PostCtrls.tsx +++ b/src/view/com/util/post-ctrls/PostCtrls.tsx @@ -16,7 +16,6 @@ import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import {HITSLOP_10, HITSLOP_20} from '#/lib/constants' -import {playHaptic} from '#/lib/haptics' import {CommentBottomArrow, HeartIcon, HeartIconSolid} from '#/lib/icons' import {makeProfileLink} from '#/lib/routes/links' import {shareUrl} from '#/lib/sharing' @@ -32,7 +31,7 @@ import { } from '#/state/queries/post' import {useRequireAuth} from '#/state/session' import {useComposerControls} from '#/state/shell/composer' -import {useHapticsDisabled} from 'state/preferences/disable-haptics' +import {useHaptics} from 'lib/haptics' import {useDialogControl} from '#/components/Dialog' import {ArrowOutOfBox_Stroke2_Corner0_Rounded as ArrowOutOfBox} from '#/components/icons/ArrowOutOfBox' import * as Prompt from '#/components/Prompt' @@ -68,7 +67,7 @@ let PostCtrls = ({ ) const requireAuth = useRequireAuth() const loggedOutWarningPromptControl = useDialogControl() - const isHapticsDisabled = useHapticsDisabled() + const playHaptic = useHaptics() const shouldShowLoggedOutWarning = React.useMemo(() => { return !!post.author.labels?.find( @@ -86,7 +85,7 @@ let PostCtrls = ({ const onPressToggleLike = React.useCallback(async () => { try { if (!post.viewer?.like) { - playHaptic(isHapticsDisabled) + playHaptic() await queueLike() } else { await queueUnlike() @@ -96,13 +95,13 @@ let PostCtrls = ({ throw e } } - }, [isHapticsDisabled, post.viewer?.like, queueLike, queueUnlike]) + }, [playHaptic, post.viewer?.like, queueLike, queueUnlike]) const onRepost = useCallback(async () => { closeModal() try { if (!post.viewer?.repost) { - playHaptic(isHapticsDisabled) + playHaptic() await queueRepost() } else { await queueUnrepost() @@ -112,13 +111,7 @@ let PostCtrls = ({ throw e } } - }, [ - closeModal, - post.viewer?.repost, - isHapticsDisabled, - queueRepost, - queueUnrepost, - ]) + }, [closeModal, post.viewer?.repost, playHaptic, queueRepost, queueUnrepost]) const onQuote = useCallback(() => { closeModal() @@ -131,7 +124,7 @@ let PostCtrls = ({ indexedAt: post.indexedAt, }, }) - playHaptic(isHapticsDisabled) + playHaptic() }, [ closeModal, openComposer, @@ -140,7 +133,7 @@ let PostCtrls = ({ post.author, post.indexedAt, record.text, - isHapticsDisabled, + playHaptic, ]) const onShare = useCallback(() => { diff --git a/src/view/screens/ProfileFeed.tsx b/src/view/screens/ProfileFeed.tsx index 2ab2e631dc..814c1e8558 100644 --- a/src/view/screens/ProfileFeed.tsx +++ b/src/view/screens/ProfileFeed.tsx @@ -27,7 +27,7 @@ import {truncateAndInvalidate} from '#/state/queries/util' import {useSession} from '#/state/session' import {useComposerControls} from '#/state/shell/composer' import {useAnalytics} from 'lib/analytics/analytics' -import {playHaptic} from 'lib/haptics' +import {useHaptics} from 'lib/haptics' import {usePalette} from 'lib/hooks/usePalette' import {useSetTitle} from 'lib/hooks/useSetTitle' import {ComposeIcon2} from 'lib/icons' @@ -39,7 +39,6 @@ import {pluralize} from 'lib/strings/helpers' import {makeRecordUri} from 'lib/strings/url-helpers' import {toShareUrl} from 'lib/strings/url-helpers' import {s} from 'lib/styles' -import {useHapticsDisabled} from 'state/preferences/disable-haptics' import {PagerWithHeader} from 'view/com/pager/PagerWithHeader' import {Feed} from 'view/com/posts/Feed' import {ProfileSubpageHeader} from 'view/com/profile/ProfileSubpageHeader' @@ -160,7 +159,7 @@ export function ProfileFeedScreenInner({ const reportDialogControl = useReportDialogControl() const {openComposer} = useComposerControls() const {track} = useAnalytics() - const isHapticsDisabled = useHapticsDisabled() + const playHaptic = useHaptics() const feedSectionRef = React.useRef(null) const isScreenFocused = useIsFocused() @@ -203,7 +202,7 @@ export function ProfileFeedScreenInner({ const onToggleSaved = React.useCallback(async () => { try { - playHaptic(isHapticsDisabled) + playHaptic() if (isSaved) { await removeFeed({uri: feedInfo.uri}) @@ -223,7 +222,7 @@ export function ProfileFeedScreenInner({ logger.error('Failed up update feeds', {message: err}) } }, [ - isHapticsDisabled, + playHaptic, isSaved, removeFeed, feedInfo, @@ -235,7 +234,7 @@ export function ProfileFeedScreenInner({ const onTogglePinned = React.useCallback(async () => { try { - playHaptic(isHapticsDisabled) + playHaptic() if (isPinned) { await unpinFeed({uri: feedInfo.uri}) @@ -249,7 +248,7 @@ export function ProfileFeedScreenInner({ logger.error('Failed to toggle pinned feed', {message: e}) } }, [ - isHapticsDisabled, + playHaptic, isPinned, unpinFeed, feedInfo, @@ -529,7 +528,7 @@ function AboutSection({ const [likeUri, setLikeUri] = React.useState(feedInfo.likeUri) const {hasSession} = useSession() const {track} = useAnalytics() - const isHapticsDisabled = useHapticsDisabled() + const playHaptic = useHaptics() const {mutateAsync: likeFeed, isPending: isLikePending} = useLikeMutation() const {mutateAsync: unlikeFeed, isPending: isUnlikePending} = useUnlikeMutation() @@ -540,7 +539,7 @@ function AboutSection({ const onToggleLiked = React.useCallback(async () => { try { - playHaptic(isHapticsDisabled) + playHaptic() if (isLiked && likeUri) { await unlikeFeed({uri: likeUri}) @@ -559,16 +558,7 @@ function AboutSection({ ) logger.error('Failed up toggle like', {message: err}) } - }, [ - isHapticsDisabled, - isLiked, - likeUri, - unlikeFeed, - track, - likeFeed, - feedInfo, - _, - ]) + }, [playHaptic, isLiked, likeUri, unlikeFeed, track, likeFeed, feedInfo, _]) return ( diff --git a/src/view/screens/ProfileList.tsx b/src/view/screens/ProfileList.tsx index f6c10c06f2..1d93a9fd7d 100644 --- a/src/view/screens/ProfileList.tsx +++ b/src/view/screens/ProfileList.tsx @@ -33,7 +33,7 @@ import {truncateAndInvalidate} from '#/state/queries/util' import {useSession} from '#/state/session' import {useSetMinimalShellMode} from '#/state/shell' import {useComposerControls} from '#/state/shell/composer' -import {playHaptic} from 'lib/haptics' +import {useHaptics} from 'lib/haptics' import {usePalette} from 'lib/hooks/usePalette' import {useSetTitle} from 'lib/hooks/useSetTitle' import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' @@ -45,7 +45,6 @@ import {shareUrl} from 'lib/sharing' import {sanitizeHandle} from 'lib/strings/handles' import {toShareUrl} from 'lib/strings/url-helpers' import {s} from 'lib/styles' -import {useHapticsDisabled} from 'state/preferences/disable-haptics' import {ListMembers} from '#/view/com/lists/ListMembers' import {PagerWithHeader} from 'view/com/pager/PagerWithHeader' import {Feed} from 'view/com/posts/Feed' @@ -256,7 +255,7 @@ function Header({rkey, list}: {rkey: string; list: AppBskyGraphDefs.ListView}) { const {data: preferences} = usePreferencesQuery() const {mutate: setSavedFeeds} = useSetSaveFeedsMutation() const {track} = useAnalytics() - const isHapticsDisabled = useHapticsDisabled() + const playHaptic = useHaptics() const deleteListPromptControl = useDialogControl() const subscribeMutePromptControl = useDialogControl() @@ -266,7 +265,7 @@ function Header({rkey, list}: {rkey: string; list: AppBskyGraphDefs.ListView}) { const isSaved = preferences?.feeds?.saved?.includes(list.uri) const onTogglePinned = React.useCallback(async () => { - playHaptic(isHapticsDisabled) + playHaptic() try { if (isPinned) { @@ -278,7 +277,7 @@ function Header({rkey, list}: {rkey: string; list: AppBskyGraphDefs.ListView}) { Toast.show(_(msg`There was an issue contacting the server`)) logger.error('Failed to toggle pinned feed', {message: e}) } - }, [isHapticsDisabled, isPinned, unpinFeed, list.uri, pinFeed, _]) + }, [playHaptic, isPinned, unpinFeed, list.uri, pinFeed, _]) const onSubscribeMute = useCallback(async () => { try { diff --git a/src/view/screens/SavedFeeds.tsx b/src/view/screens/SavedFeeds.tsx index 872a07428a..0003dbd5d9 100644 --- a/src/view/screens/SavedFeeds.tsx +++ b/src/view/screens/SavedFeeds.tsx @@ -16,12 +16,11 @@ import { } from '#/state/queries/preferences' import {useSetMinimalShellMode} from '#/state/shell' import {useAnalytics} from 'lib/analytics/analytics' -import {playHaptic} from 'lib/haptics' +import {useHaptics} from 'lib/haptics' import {usePalette} from 'lib/hooks/usePalette' import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' import {CommonNavigatorParams} from 'lib/routes/types' import {colors, s} from 'lib/styles' -import {useHapticsDisabled} from 'state/preferences/disable-haptics' import {FeedSourceCard} from 'view/com/feeds/FeedSourceCard' import {TextLink} from 'view/com/util/Link' import {Text} from 'view/com/util/text/Text' @@ -191,14 +190,14 @@ function ListItem({ }) { const pal = usePalette('default') const {_} = useLingui() - const isHapticsDisabled = useHapticsDisabled() + const playHaptic = useHaptics() const {isPending: isPinPending, mutateAsync: pinFeed} = usePinFeedMutation() const {isPending: isUnpinPending, mutateAsync: unpinFeed} = useUnpinFeedMutation() const isPending = isPinPending || isUnpinPending const onTogglePinned = React.useCallback(async () => { - playHaptic(isHapticsDisabled) + playHaptic() try { resetSaveFeedsMutationState() @@ -213,7 +212,7 @@ function ListItem({ logger.error('Failed to toggle pinned feed', {message: e}) } }, [ - isHapticsDisabled, + playHaptic, resetSaveFeedsMutationState, isPinned, unpinFeed, diff --git a/src/view/shell/bottom-bar/BottomBar.tsx b/src/view/shell/bottom-bar/BottomBar.tsx index 072357d71f..c35fa106d2 100644 --- a/src/view/shell/bottom-bar/BottomBar.tsx +++ b/src/view/shell/bottom-bar/BottomBar.tsx @@ -8,7 +8,7 @@ import {BottomTabBarProps} from '@react-navigation/bottom-tabs' import {StackActions} from '@react-navigation/native' import {useAnalytics} from '#/lib/analytics/analytics' -import {playHaptic} from '#/lib/haptics' +import {useHaptics} from '#/lib/haptics' import {useDedupe} from '#/lib/hooks/useDedupe' import {useMinimalShellMode} from '#/lib/hooks/useMinimalShellMode' import {useNavigationTabState} from '#/lib/hooks/useNavigationTabState' @@ -32,7 +32,6 @@ import {useSession} from '#/state/session' import {useLoggedOutViewControls} from '#/state/shell/logged-out' import {useShellLayout} from '#/state/shell/shell-layout' import {useCloseAllActiveElements} from '#/state/util' -import {useHapticsDisabled} from 'state/preferences/disable-haptics' import {Button} from '#/view/com/util/forms/Button' import {Text} from '#/view/com/util/text/Text' import {UserAvatar} from '#/view/com/util/UserAvatar' @@ -60,7 +59,7 @@ export function BottomBar({navigation}: BottomTabBarProps) { const closeAllActiveElements = useCloseAllActiveElements() const dedupe = useDedupe() const accountSwitchControl = useDialogControl() - const isHapticsDisabled = useHapticsDisabled() + const playHaptic = useHaptics() const showSignIn = React.useCallback(() => { closeAllActiveElements() @@ -106,9 +105,9 @@ export function BottomBar({navigation}: BottomTabBarProps) { }, [onPressTab]) const onLongPressProfile = React.useCallback(() => { - playHaptic(isHapticsDisabled) + playHaptic() accountSwitchControl.open() - }, [accountSwitchControl, isHapticsDisabled]) + }, [accountSwitchControl, playHaptic]) return ( <>