add haptics to save, like, and pin actions on feed
parent
64e303d911
commit
dfcdd37087
|
@ -0,0 +1,24 @@
|
||||||
|
import { isIOS } from 'platform/detection'
|
||||||
|
import ReactNativeHapticFeedback, {
|
||||||
|
HapticFeedbackTypes,
|
||||||
|
} from 'react-native-haptic-feedback'
|
||||||
|
|
||||||
|
|
||||||
|
const hapticImpact: HapticFeedbackTypes = isIOS ? 'impactMedium' : 'impactLight' // Users said the medium impact was too strong on Android; see APP-537s
|
||||||
|
|
||||||
|
|
||||||
|
export class Haptics {
|
||||||
|
static default = () => ReactNativeHapticFeedback.trigger(hapticImpact)
|
||||||
|
static impact = (type: HapticFeedbackTypes = hapticImpact) => ReactNativeHapticFeedback.trigger(type)
|
||||||
|
static selection = () => ReactNativeHapticFeedback.trigger('selection')
|
||||||
|
static notification = (type: 'success' | 'warning' | 'error') => {
|
||||||
|
switch (type) {
|
||||||
|
case 'success':
|
||||||
|
return ReactNativeHapticFeedback.trigger('notificationSuccess')
|
||||||
|
case 'warning':
|
||||||
|
return ReactNativeHapticFeedback.trigger('notificationWarning')
|
||||||
|
case 'error':
|
||||||
|
return ReactNativeHapticFeedback.trigger('notificationError')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,9 +10,6 @@ import {
|
||||||
FontAwesomeIcon,
|
FontAwesomeIcon,
|
||||||
FontAwesomeIconStyle,
|
FontAwesomeIconStyle,
|
||||||
} from '@fortawesome/react-native-fontawesome'
|
} from '@fortawesome/react-native-fontawesome'
|
||||||
import ReactNativeHapticFeedback, {
|
|
||||||
HapticFeedbackTypes,
|
|
||||||
} from 'react-native-haptic-feedback'
|
|
||||||
// DISABLED see #135
|
// DISABLED see #135
|
||||||
// import {
|
// import {
|
||||||
// TriggerableAnimated,
|
// TriggerableAnimated,
|
||||||
|
@ -24,8 +21,9 @@ import {HeartIcon, HeartIconSolid, CommentBottomArrow} from 'lib/icons'
|
||||||
import {s, colors} from 'lib/styles'
|
import {s, colors} from 'lib/styles'
|
||||||
import {useTheme} from 'lib/ThemeContext'
|
import {useTheme} from 'lib/ThemeContext'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {isIOS, isNative} from 'platform/detection'
|
import {isNative} from 'platform/detection'
|
||||||
import {RepostButton} from './RepostButton'
|
import {RepostButton} from './RepostButton'
|
||||||
|
import {Haptics} from 'lib/haptics'
|
||||||
|
|
||||||
interface PostCtrlsOpts {
|
interface PostCtrlsOpts {
|
||||||
itemUri: string
|
itemUri: string
|
||||||
|
@ -58,7 +56,6 @@ interface PostCtrlsOpts {
|
||||||
}
|
}
|
||||||
|
|
||||||
const HITSLOP = {top: 5, left: 5, bottom: 5, right: 5}
|
const HITSLOP = {top: 5, left: 5, bottom: 5, right: 5}
|
||||||
const hapticImpact: HapticFeedbackTypes = isIOS ? 'impactMedium' : 'impactLight' // Users said the medium impact was too strong on Android; see APP-537
|
|
||||||
|
|
||||||
// DISABLED see #135
|
// DISABLED see #135
|
||||||
/*
|
/*
|
||||||
|
@ -112,7 +109,7 @@ export function PostCtrls(opts: PostCtrlsOpts) {
|
||||||
store.shell.closeModal()
|
store.shell.closeModal()
|
||||||
if (!opts.isReposted) {
|
if (!opts.isReposted) {
|
||||||
if (isNative) {
|
if (isNative) {
|
||||||
ReactNativeHapticFeedback.trigger(hapticImpact)
|
Haptics.default()
|
||||||
}
|
}
|
||||||
opts.onPressToggleRepost().catch(_e => undefined)
|
opts.onPressToggleRepost().catch(_e => undefined)
|
||||||
// DISABLED see #135
|
// DISABLED see #135
|
||||||
|
@ -141,7 +138,7 @@ export function PostCtrls(opts: PostCtrlsOpts) {
|
||||||
})
|
})
|
||||||
|
|
||||||
if (isNative) {
|
if (isNative) {
|
||||||
ReactNativeHapticFeedback.trigger(hapticImpact)
|
Haptics.default()
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
opts.author,
|
opts.author,
|
||||||
|
@ -154,7 +151,9 @@ export function PostCtrls(opts: PostCtrlsOpts) {
|
||||||
|
|
||||||
const onPressToggleLikeWrapper = async () => {
|
const onPressToggleLikeWrapper = async () => {
|
||||||
if (!opts.isLiked) {
|
if (!opts.isLiked) {
|
||||||
ReactNativeHapticFeedback.trigger(hapticImpact)
|
if (isNative) {
|
||||||
|
Haptics.default()
|
||||||
|
}
|
||||||
await opts.onPressToggleLike().catch(_e => undefined)
|
await opts.onPressToggleLike().catch(_e => undefined)
|
||||||
// DISABLED see #135
|
// DISABLED see #135
|
||||||
// likeRef.current?.trigger(
|
// likeRef.current?.trigger(
|
||||||
|
|
|
@ -24,6 +24,9 @@ import {isDesktopWeb} from 'platform/detection'
|
||||||
import {useSetTitle} from 'lib/hooks/useSetTitle'
|
import {useSetTitle} from 'lib/hooks/useSetTitle'
|
||||||
import {shareUrl} from 'lib/sharing'
|
import {shareUrl} from 'lib/sharing'
|
||||||
import {toShareUrl} from 'lib/strings/url-helpers'
|
import {toShareUrl} from 'lib/strings/url-helpers'
|
||||||
|
import { Haptics } from 'lib/haptics'
|
||||||
|
|
||||||
|
const HITSLOP = {top: 5, left: 5, bottom: 5, right: 5}
|
||||||
|
|
||||||
type Props = NativeStackScreenProps<CommonNavigatorParams, 'CustomFeed'>
|
type Props = NativeStackScreenProps<CommonNavigatorParams, 'CustomFeed'>
|
||||||
export const CustomFeedScreen = withAuthRequired(
|
export const CustomFeedScreen = withAuthRequired(
|
||||||
|
@ -49,6 +52,7 @@ export const CustomFeedScreen = withAuthRequired(
|
||||||
|
|
||||||
const onToggleSaved = React.useCallback(async () => {
|
const onToggleSaved = React.useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
|
Haptics.default()
|
||||||
if (currentFeed?.isSaved) {
|
if (currentFeed?.isSaved) {
|
||||||
await currentFeed?.unsave()
|
await currentFeed?.unsave()
|
||||||
} else {
|
} else {
|
||||||
|
@ -63,6 +67,7 @@ export const CustomFeedScreen = withAuthRequired(
|
||||||
}, [store, currentFeed])
|
}, [store, currentFeed])
|
||||||
|
|
||||||
const onToggleLiked = React.useCallback(async () => {
|
const onToggleLiked = React.useCallback(async () => {
|
||||||
|
Haptics.default()
|
||||||
try {
|
try {
|
||||||
if (currentFeed?.isLiked) {
|
if (currentFeed?.isLiked) {
|
||||||
await currentFeed?.unlike()
|
await currentFeed?.unlike()
|
||||||
|
|
|
@ -28,6 +28,7 @@ import {CustomFeed} from 'view/com/feeds/CustomFeed'
|
||||||
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
||||||
import {CustomFeedModel} from 'state/models/feeds/custom-feed'
|
import {CustomFeedModel} from 'state/models/feeds/custom-feed'
|
||||||
import * as Toast from 'view/com/util/Toast'
|
import * as Toast from 'view/com/util/Toast'
|
||||||
|
import {Haptics} from 'lib/haptics'
|
||||||
|
|
||||||
type Props = NativeStackScreenProps<CommonNavigatorParams, 'SavedFeeds'>
|
type Props = NativeStackScreenProps<CommonNavigatorParams, 'SavedFeeds'>
|
||||||
|
|
||||||
|
@ -128,14 +129,13 @@ const ListItem = observer(
|
||||||
const savedFeeds = useMemo(() => store.me.savedFeeds, [store])
|
const savedFeeds = useMemo(() => store.me.savedFeeds, [store])
|
||||||
const isPinned = savedFeeds.isPinned(item)
|
const isPinned = savedFeeds.isPinned(item)
|
||||||
|
|
||||||
const onTogglePinned = useCallback(
|
const onTogglePinned = useCallback(() => {
|
||||||
() =>
|
Haptics.default()
|
||||||
savedFeeds.togglePinnedFeed(item).catch(e => {
|
savedFeeds.togglePinnedFeed(item).catch(e => {
|
||||||
Toast.show('There was an issue contacting the server')
|
Toast.show('There was an issue contacting the server')
|
||||||
store.log.error('Failed to toggle pinned feed', {e})
|
store.log.error('Failed to toggle pinned feed', {e})
|
||||||
}),
|
})
|
||||||
[savedFeeds, item, store],
|
}, [savedFeeds, item, store])
|
||||||
)
|
|
||||||
const onPressUp = useCallback(
|
const onPressUp = useCallback(
|
||||||
() =>
|
() =>
|
||||||
savedFeeds.movePinnedFeed(item, 'up').catch(e => {
|
savedFeeds.movePinnedFeed(item, 'up').catch(e => {
|
||||||
|
|
Loading…
Reference in New Issue