From d60af212b0bd9338b9bc4b1275378be9f2a5df7f Mon Sep 17 00:00:00 2001 From: Gavin Date: Sat, 14 Oct 2023 20:06:58 -0700 Subject: [PATCH] swipeable comments plus more refactoring --- src/components/Comment/components/Comment.tsx | 78 ++++++++--- .../Comment/components/CommentChain.tsx | 13 +- .../Common/SwipeableRow/LeftOptions.tsx | 8 +- .../Common/SwipeableRow/RightOptions.tsx | 8 +- .../SwipeableRow/actions/customOption.ts | 9 ++ .../SwipeableRow/actions/swipeableActions.ts | 4 + .../hooks/useCommentSwipeOptions.ts | 77 +++++++++++ .../SwipeableRow/hooks/usePostSwipeOptions.ts | 76 +++++++++++ .../SwipeableRow/hooks/useSwipeOptions.ts | 99 -------------- src/components/Common/SwipeableRow/types.ts | 18 +++ .../Feed/components/Feed/FeedItem.tsx | 25 ++-- .../screens/SettingsGesturesScreen.tsx | 126 +++++++++++++++++- src/state/comment/commentStore.ts | 3 + src/state/settings/actions/index.ts | 3 +- .../actions/setCommentGestureSetting.ts | 17 +++ ...ureSetting.ts => setPostGestureSetting.ts} | 0 src/state/settings/settingsStore.ts | 17 ++- 17 files changed, 438 insertions(+), 143 deletions(-) create mode 100644 src/components/Common/SwipeableRow/actions/customOption.ts create mode 100644 src/components/Common/SwipeableRow/hooks/useCommentSwipeOptions.ts create mode 100644 src/components/Common/SwipeableRow/hooks/usePostSwipeOptions.ts delete mode 100644 src/components/Common/SwipeableRow/hooks/useSwipeOptions.ts create mode 100644 src/state/settings/actions/setCommentGestureSetting.ts rename src/state/settings/actions/{setGestureSetting.ts => setPostGestureSetting.ts} (100%) diff --git a/src/components/Comment/components/Comment.tsx b/src/components/Comment/components/Comment.tsx index d1ae7d870..539eef76f 100644 --- a/src/components/Comment/components/Comment.tsx +++ b/src/components/Comment/components/Comment.tsx @@ -4,12 +4,23 @@ import CommentHeader from '@components/Comment/components/CommentHeader'; import CommentContent from '@components/Comment/components/CommentContent'; import { Pressable } from 'react-native'; import { Separator } from 'tamagui'; +import { SwipeableRow } from '@components/Common/SwipeableRow/SwipeableRow'; +import { useCommentGesturesEnabled } from '@src/state/settings/settingsStore'; +import { LeftOptions } from '@components/Common/SwipeableRow/LeftOptions'; +import { SwipeableActionParams } from '@components/Common/SwipeableRow/actions'; +import { useCommentPostId } from '@src/state/comment/commentStore'; +import { useNavigation } from '@react-navigation/core'; +import { NativeStackNavigationProp } from '@react-navigation/native-stack'; +import { RightOptions } from '@components/Common/SwipeableRow/RightOptions'; +import { ISwipeableOptions } from '@components/Common/SwipeableRow/types'; interface IProps { itemId: number; depth?: number; onPress?: () => unknown | Promise; collapsed?: boolean; + leftOptions?: ISwipeableOptions; + rightOptions?: ISwipeableOptions; } const depthToColor = (depth: number): string => { @@ -36,29 +47,54 @@ function Comment({ depth = 0, onPress, collapsed = false, + leftOptions, + rightOptions, }: IProps): React.JSX.Element { + const navigation = useNavigation>(); + + const postId = useCommentPostId(itemId); + const swipesEnabled = useCommentGesturesEnabled(); + const borderWidth = useMemo(() => (depth > 0 ? 2 : 0), [depth]); const borderColor = useMemo(() => depthToColor(depth), [depth]); - if (onPress != null) { - return ; - } + const actionParams = useMemo( + () => ({ + postId, + commentId: itemId, + navigation, + }), + [itemId], + ); return ( - - - - {!collapsed && } + + ) : undefined + } + rightOption={ + swipesEnabled && rightOptions?.actions.first != null ? ( + + ) : undefined + } + > + + + + {!collapsed && } + + - - + ); } @@ -67,10 +103,18 @@ export const PressableComment = React.memo(function pressableComment({ depth = 0, onPress, collapsed = false, + leftOptions, + rightOptions, }: IProps): React.JSX.Element { return ( - + ); }); diff --git a/src/components/Comment/components/CommentChain.tsx b/src/components/Comment/components/CommentChain.tsx index 595378f43..c6e70049b 100644 --- a/src/components/Comment/components/CommentChain.tsx +++ b/src/components/Comment/components/CommentChain.tsx @@ -3,6 +3,8 @@ import { ICommentInfo } from '@src/types'; import { PressableComment } from '@components/Comment/components/Comment'; import { setPostCommentHidden } from '@src/state/post/actions/setPostCommentHidden'; import CommentShowMoreButton from '@components/Comment/components/CommentShowMoreButton'; +import { useCommentGesturesCollapse } from '@src/state/settings/settingsStore'; +import { useCommentSwipeOptions } from '@components/Common/SwipeableRow/hooks/useCommentSwipeOptions'; interface IProps { commentInfo: ICommentInfo; @@ -13,9 +15,16 @@ function CommentChain({ commentInfo, ignoreLoadMore = false, }: IProps): React.JSX.Element | null { + const collapseOnTap = useCommentGesturesCollapse(); + + const leftOptions = useCommentSwipeOptions('left'); + const rightOptions = useCommentSwipeOptions('right'); + const onCommentPress = useCallback(() => { + if (!collapseOnTap) return; + setPostCommentHidden(commentInfo, !commentInfo.collapsed); - }, [commentInfo.collapsed]); + }, [commentInfo.collapsed, collapseOnTap]); if (commentInfo.hidden) { return null; @@ -31,6 +40,8 @@ function CommentChain({ itemId={commentInfo.commentId} depth={commentInfo.depth} collapsed={commentInfo.collapsed} + leftOptions={leftOptions} + rightOptions={rightOptions} /> ); } diff --git a/src/components/Common/SwipeableRow/LeftOptions.tsx b/src/components/Common/SwipeableRow/LeftOptions.tsx index 3e658e8ca..0293551b8 100644 --- a/src/components/Common/SwipeableRow/LeftOptions.tsx +++ b/src/components/Common/SwipeableRow/LeftOptions.tsx @@ -15,7 +15,7 @@ import { StyleSheet } from 'react-native'; import { playHaptic } from '@helpers/haptics'; import { SwipeableActionParams } from '@components/Common/SwipeableRow/actions'; import { useSwipeableRow } from '@components/Common/SwipeableRow/SwipeableRowProvider'; -import { useSwipeOptions } from '@components/Common/SwipeableRow/hooks/useSwipeOptions'; +import { UsePostSwipeOptions } from '@components/Common/SwipeableRow/hooks/usePostSwipeOptions'; import { IconMap, IconType } from '@src/types/IconMap'; import { styled } from 'tamagui'; @@ -24,7 +24,7 @@ const DEFAULT_STOPS: Stops = [75, 150]; const [firstStop, secondStop] = DEFAULT_STOPS; interface Props { - type: 'post' | 'comment'; + options: UsePostSwipeOptions; flipFlop?: boolean; actionParams: SwipeableActionParams; } @@ -36,14 +36,14 @@ const buzz = (): void => { }; export function LeftOptions({ - type, + options, flipFlop = false, actionParams, }: Props): React.JSX.Element { const isFrozen = useSharedValue(false); const { subscribe, translateX } = useSwipeableRow(); - const { colors, actions, icons } = useSwipeOptions(type, 'left'); + const { colors, actions, icons } = options; const [icon, setIcon] = useState(icons.first); diff --git a/src/components/Common/SwipeableRow/RightOptions.tsx b/src/components/Common/SwipeableRow/RightOptions.tsx index 59e9dca0f..e69837d6e 100644 --- a/src/components/Common/SwipeableRow/RightOptions.tsx +++ b/src/components/Common/SwipeableRow/RightOptions.tsx @@ -17,7 +17,7 @@ import { playHaptic } from '@helpers/haptics'; import { IconMap, IconType } from '@src/types/IconMap'; import { styled } from 'tamagui'; import { SwipeableActionParams } from '@components/Common/SwipeableRow/actions'; -import { useSwipeOptions } from '@components/Common/SwipeableRow/hooks/useSwipeOptions'; +import { UsePostSwipeOptions } from '@components/Common/SwipeableRow/hooks/usePostSwipeOptions'; type Stops = [first: number, second: number]; const DEFAULT_STOPS: Stops = [-75, -150]; @@ -25,7 +25,7 @@ const [firstStop, secondStop] = DEFAULT_STOPS; const SCREEN_WIDTH = Dimensions.get('screen').width; interface Props { - type: 'post' | 'comment'; + options: UsePostSwipeOptions; flipFlop?: boolean; actionParams: SwipeableActionParams; } @@ -37,14 +37,14 @@ const buzz = (): void => { }; export function RightOptions({ - type, + options, flipFlop = false, actionParams, }: Props): React.JSX.Element { const isFrozen = useSharedValue(false); const { subscribe, translateX } = useSwipeableRow(); - const { colors, actions, icons } = useSwipeOptions(type, 'right'); + const { colors, actions, icons } = options; const [icon, setIcon] = useState(icons.first); diff --git a/src/components/Common/SwipeableRow/actions/customOption.ts b/src/components/Common/SwipeableRow/actions/customOption.ts new file mode 100644 index 000000000..ba09a09f4 --- /dev/null +++ b/src/components/Common/SwipeableRow/actions/customOption.ts @@ -0,0 +1,9 @@ +import { SwipeableActionParams } from '@components/Common/SwipeableRow/actions/swipeableActions'; + +export const customOption = (params: SwipeableActionParams): void => { + const { custom } = params; + + if (custom == null) return; + + custom(params); +}; diff --git a/src/components/Common/SwipeableRow/actions/swipeableActions.ts b/src/components/Common/SwipeableRow/actions/swipeableActions.ts index 7f1a9ba4d..8c1f4931b 100644 --- a/src/components/Common/SwipeableRow/actions/swipeableActions.ts +++ b/src/components/Common/SwipeableRow/actions/swipeableActions.ts @@ -6,12 +6,14 @@ import { downvoteCommentOption } from '@components/Common/SwipeableRow/actions/d import { savePostOption } from '@components/Common/SwipeableRow/actions/savePostOption'; import { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { replyOption } from '@components/Common/SwipeableRow/actions/replyOption'; +import { customOption } from '@components/Common/SwipeableRow/actions/customOption'; export interface SwipeableActionParams { commentId?: number; postId?: number; screenId?: string; navigation: NativeStackNavigationProp; + custom?: (params?: SwipeableActionParams) => unknown; } export const postSwipeableActions: Record< @@ -23,6 +25,7 @@ export const postSwipeableActions: Record< save: savePostOption, hide: () => {}, reply: replyOption, + custom: customOption, }; export const commentSwipeableActions: Record< @@ -34,4 +37,5 @@ export const commentSwipeableActions: Record< save: () => {}, collapse: () => {}, reply: () => {}, + hide: () => {}, }; diff --git a/src/components/Common/SwipeableRow/hooks/useCommentSwipeOptions.ts b/src/components/Common/SwipeableRow/hooks/useCommentSwipeOptions.ts new file mode 100644 index 000000000..e682ede62 --- /dev/null +++ b/src/components/Common/SwipeableRow/hooks/useCommentSwipeOptions.ts @@ -0,0 +1,77 @@ +import { useTheme } from 'tamagui'; +import { useMemo } from 'react'; +import { + useCommentGesturesFirstLeft, + useCommentGesturesFirstRight, + useCommentGesturesSecondLeft, + useCommentGesturesSecondRight, +} from '@src/state/settings/settingsStore'; +import { commentSwipeableActions } from '@components/Common/SwipeableRow/actions'; +import { IPostGestureOption } from '@src/types'; +import { + ISwipeableActions, + ISwipeableColors, + ISwipeableOptions, +} from '@components/Common/SwipeableRow/types'; + +export const useCommentSwipeOptions = ( + side: 'right' | 'left', +): ISwipeableOptions => { + const theme = useTheme(); + + const firstLeft = useCommentGesturesFirstLeft(); + const firstRight = useCommentGesturesFirstRight(); + const secondLeft = useCommentGesturesSecondLeft(); + const secondRight = useCommentGesturesSecondRight(); + + const swipeColorOptions = useMemo>( + () => ({ + upvote: theme.upvote.val, + downvote: theme.downvote.val, + save: theme.bookmark.val, + hide: theme.warn.val, + reply: theme.accent.val, + collapse: theme.warn.val, + }), + [theme], + ); + + const swipeActions = useMemo(() => { + const first = side === 'left' ? firstLeft : firstRight; + const second = side === 'left' ? secondLeft : secondRight; + + return { + first: first !== 'none' ? commentSwipeableActions[first] : undefined, + second: second !== 'none' ? commentSwipeableActions[second] : undefined, + }; + }, [firstLeft, firstRight, secondLeft, secondRight]); + + const swipeColors = useMemo(() => { + const first = side === 'left' ? firstLeft : firstRight; + const second = side === 'left' ? secondLeft : secondRight; + + return { + first: + first !== 'none' ? swipeColorOptions[first] ?? '$accent' : '$accent', + second: + second !== 'none' ? swipeColorOptions[second] ?? undefined : undefined, + }; + }, [firstLeft, firstRight, secondLeft, secondRight, swipeColorOptions]); + + // @ts-expect-error TODO Fix this + const swipeIcons = useMemo(() => { + const first = side === 'left' ? firstLeft : firstRight; + const second = side === 'left' ? secondLeft : secondRight; + + return { + first: first !== 'none' ? first : undefined, + second: second !== 'none' ? second : undefined, + }; + }, [firstLeft, firstRight, secondLeft, secondRight]); + + return { + actions: swipeActions, + colors: swipeColors, + icons: swipeIcons, + }; +}; diff --git a/src/components/Common/SwipeableRow/hooks/usePostSwipeOptions.ts b/src/components/Common/SwipeableRow/hooks/usePostSwipeOptions.ts new file mode 100644 index 000000000..cb5ad20bc --- /dev/null +++ b/src/components/Common/SwipeableRow/hooks/usePostSwipeOptions.ts @@ -0,0 +1,76 @@ +import { useTheme } from 'tamagui'; +import { useMemo } from 'react'; +import { + usePostGesturesFirstLeft, + usePostGesturesFirstRight, + usePostGesturesSecondLeft, + usePostGesturesSecondRight, +} from '@src/state/settings/settingsStore'; +import { postSwipeableActions } from '@components/Common/SwipeableRow/actions'; +import { IPostGestureOption } from '@src/types'; +import { + ISwipeableActions, + ISwipeableColors, + ISwipeableOptions, +} from '@components/Common/SwipeableRow/types'; + +export const usePostSwipeOptions = ( + side: 'right' | 'left', +): ISwipeableOptions => { + const theme = useTheme(); + + const firstLeft = usePostGesturesFirstLeft(); + const firstRight = usePostGesturesFirstRight(); + const secondLeft = usePostGesturesSecondLeft(); + const secondRight = usePostGesturesSecondRight(); + + const swipeColorOptions = useMemo>( + () => ({ + upvote: theme.upvote.val, + downvote: theme.downvote.val, + save: theme.bookmark.val, + hide: theme.warn.val, + reply: theme.accent.val, + }), + [theme], + ); + + const swipeActions = useMemo(() => { + const first = side === 'left' ? firstLeft : firstRight; + const second = side === 'left' ? secondLeft : secondRight; + + return { + first: first !== 'none' ? postSwipeableActions[first] : undefined, + second: second !== 'none' ? postSwipeableActions[second] : undefined, + }; + }, [firstLeft, firstRight, secondLeft, secondRight]); + + const swipeColors = useMemo(() => { + const first = side === 'left' ? firstLeft : firstRight; + const second = side === 'left' ? secondLeft : secondRight; + + return { + first: + first !== 'none' ? swipeColorOptions[first] ?? '$accent' : '$accent', + second: + second !== 'none' ? swipeColorOptions[second] ?? undefined : undefined, + }; + }, [firstLeft, firstRight, secondLeft, secondRight, swipeColorOptions]); + + // @ts-expect-error TODO Fix this + const swipeIcons = useMemo(() => { + const first = side === 'left' ? firstLeft : firstRight; + const second = side === 'left' ? secondLeft : secondRight; + + return { + first: first !== 'none' ? first : undefined, + second: second !== 'none' ? second : undefined, + }; + }, [firstLeft, firstRight, secondLeft, secondRight]); + + return { + actions: swipeActions, + colors: swipeColors, + icons: swipeIcons, + }; +}; diff --git a/src/components/Common/SwipeableRow/hooks/useSwipeOptions.ts b/src/components/Common/SwipeableRow/hooks/useSwipeOptions.ts deleted file mode 100644 index 0fa93a11a..000000000 --- a/src/components/Common/SwipeableRow/hooks/useSwipeOptions.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { useTheme } from 'tamagui'; -import { useMemo } from 'react'; -import { - usePostGesturesFirstLeft, - usePostGesturesFirstRight, - usePostGesturesSecondLeft, - usePostGesturesSecondRight, -} from '@src/state/settings/settingsStore'; -import { - postSwipeableActions, - SwipeableActionParams, -} from '@components/Common/SwipeableRow/actions'; -import { IPostGestureOption } from '@src/types'; -import { ISwipeableColors } from '@components/Common/SwipeableRow/types'; -import { IconType } from '@src/types/IconMap'; - -export interface UseSwipeOptions { - actions: ISwipeableActions; - colors: ISwipeableColors; - icons: ISwipeableIcons; -} - -interface ISwipeableActions { - first?: (params: SwipeableActionParams) => unknown; - second?: (params: SwipeableActionParams) => unknown; -} - -interface ISwipeableIcons { - first?: IconType; - second?: IconType; -} - -export const useSwipeOptions = ( - type: 'post' | 'comment', - side: 'right' | 'left', -): UseSwipeOptions => { - const theme = useTheme(); - - const firstLeftPost = usePostGesturesFirstLeft(); - const firstRightPost = usePostGesturesFirstRight(); - const secondLeftPost = usePostGesturesSecondLeft(); - const secondRightPost = usePostGesturesSecondRight(); - - const swipeColorOptions = useMemo>( - () => ({ - upvote: theme.upvote.val, - downvote: theme.downvote.val, - save: theme.bookmark.val, - hide: theme.warn.val, - reply: theme.accent.val, - }), - [theme], - ); - - const swipeActions = useMemo(() => { - const first = side === 'left' ? firstLeftPost : firstRightPost; - const second = side === 'left' ? secondLeftPost : secondRightPost; - - return { - first: first !== 'none' ? postSwipeableActions[first] : undefined, - second: second !== 'none' ? postSwipeableActions[second] : undefined, - }; - }, [firstLeftPost, firstRightPost, secondLeftPost, secondRightPost]); - - const swipeColors = useMemo(() => { - const first = side === 'left' ? firstLeftPost : firstRightPost; - const second = side === 'left' ? secondLeftPost : secondRightPost; - - return { - first: - first !== 'none' ? swipeColorOptions[first] ?? '$accent' : '$accent', - second: - second !== 'none' ? swipeColorOptions[second] ?? undefined : undefined, - }; - }, [ - firstLeftPost, - firstRightPost, - secondLeftPost, - secondRightPost, - swipeColorOptions, - ]); - - // @ts-expect-error TODO Fix this - const swipeIcons = useMemo(() => { - const first = side === 'left' ? firstLeftPost : firstRightPost; - const second = side === 'left' ? secondLeftPost : secondRightPost; - - return { - first: first !== 'none' ? first : undefined, - second: second !== 'none' ? second : undefined, - }; - }, [firstLeftPost, firstRightPost, secondLeftPost, secondRightPost]); - - return { - actions: swipeActions, - colors: swipeColors, - icons: swipeIcons, - }; -}; diff --git a/src/components/Common/SwipeableRow/types.ts b/src/components/Common/SwipeableRow/types.ts index be437e9fd..f77ab9fcd 100644 --- a/src/components/Common/SwipeableRow/types.ts +++ b/src/components/Common/SwipeableRow/types.ts @@ -4,6 +4,8 @@ import { GestureUpdateEvent, PanGestureHandlerEventPayload, } from 'react-native-gesture-handler'; +import { SwipeableActionParams } from '@components/Common/SwipeableRow/actions'; +import { IconType } from '@src/types/IconMap'; export interface SwipeableRowGestureContext { startX: number; @@ -33,3 +35,19 @@ export interface ISwipeableColors { first: string; second?: string; } + +export interface ISwipeableOptions { + actions: ISwipeableActions; + colors: ISwipeableColors; + icons: ISwipeableIcons; +} + +export interface ISwipeableActions { + first?: (params: SwipeableActionParams) => unknown; + second?: (params: SwipeableActionParams) => unknown; +} + +export interface ISwipeableIcons { + first?: IconType; + second?: IconType; +} diff --git a/src/components/Feed/components/Feed/FeedItem.tsx b/src/components/Feed/components/Feed/FeedItem.tsx index 8504a336a..d30aa3074 100644 --- a/src/components/Feed/components/Feed/FeedItem.tsx +++ b/src/components/Feed/components/Feed/FeedItem.tsx @@ -10,12 +10,9 @@ import { NativeStackNavigationProp } from '@react-navigation/native-stack'; import FeedItemContent from '@components/Feed/components/Feed/FeedItem/FeedItemContent'; import { LeftOptions } from '@components/Common/SwipeableRow/LeftOptions'; import { SwipeableRow } from '@components/Common/SwipeableRow/SwipeableRow'; -import { - usePostGesturesEnabled, - usePostGesturesFirstLeft, - usePostGesturesFirstRight, -} from '@src/state/settings/settingsStore'; +import { usePostGesturesEnabled } from '@src/state/settings/settingsStore'; import { RightOptions } from '@components/Common/SwipeableRow/RightOptions'; +import { usePostSwipeOptions } from '@components/Common/SwipeableRow/hooks/usePostSwipeOptions'; interface IProps { itemId: number; @@ -25,8 +22,8 @@ function FeedItem({ itemId }: IProps): React.JSX.Element { const navigation = useNavigation>(); const gesturesEnabled = usePostGesturesEnabled(); - const firstLeft = usePostGesturesFirstLeft(); - const firstRight = usePostGesturesFirstRight(); + const leftSwipeOptions = usePostSwipeOptions('left'); + const rightSwipeOptions = usePostSwipeOptions('right'); const onPress = useCallback(() => { navigation.navigate('Post', { @@ -46,13 +43,19 @@ function FeedItem({ itemId }: IProps): React.JSX.Element { + gesturesEnabled && leftSwipeOptions.actions.first != null ? ( + ) : undefined } rightOption={ - gesturesEnabled && firstRight !== 'none' ? ( - + gesturesEnabled && rightSwipeOptions.actions.first !== null ? ( + ) : undefined } > diff --git a/src/components/Settings/screens/SettingsGesturesScreen.tsx b/src/components/Settings/screens/SettingsGesturesScreen.tsx index cc637317c..0b68939c6 100644 --- a/src/components/Settings/screens/SettingsGesturesScreen.tsx +++ b/src/components/Settings/screens/SettingsGesturesScreen.tsx @@ -1,19 +1,28 @@ -import React from 'react'; +import React, { useMemo } from 'react'; import { createContextMenuOptionsFromStrings } from '@helpers/contextMenu'; import { ScrollView } from 'tamagui'; import Table from '@components/Common/Table/Table'; import { AppContextMenuButton } from '@components/Common/ContextMenu/AppContextMenuButton'; import { useSettingsStore } from '@src/state/settings/settingsStore'; -import { setPostGestureSetting } from '@src/state/settings/actions'; +import { + setCommentGestureSetting, + setPostGestureSetting, +} from '@src/state/settings/actions'; import { capitalizeFirstLetter } from '@helpers/text'; -import { postGestureOptions } from '@src/types'; +import { commentGestureOptions, postGestureOptions } from '@src/types'; import { LayoutAnimation, Switch } from 'react-native'; export default function SettingsGesturesScreen(): React.JSX.Element { const settings = useSettingsStore(); - const postSwipeOptions = - createContextMenuOptionsFromStrings(postGestureOptions); + const postSwipeOptions = useMemo( + () => createContextMenuOptionsFromStrings(postGestureOptions), + [], + ); + const commentSwipeOptions = useMemo( + () => createContextMenuOptionsFromStrings(commentGestureOptions), + [], + ); return ( @@ -109,6 +118,113 @@ export default function SettingsGesturesScreen(): React.JSX.Element { )} + + + { + setCommentGestureSetting('enabled', e.nativeEvent.value); + }} + /> + } + /> + { + setCommentGestureSetting('collapse', e.nativeEvent.value); + }} + /> + } + /> + { + setCommentGestureSetting('firstLeft', e.nativeEvent.actionKey); + + if (e.nativeEvent.actionKey === 'none') { + setCommentGestureSetting('secondLeft', 'none'); + } + }} + > + + + {settings.gestures.comment.firstLeft !== 'none' && ( + { + setCommentGestureSetting('secondLeft', e.nativeEvent.actionKey); + }} + onLayout={() => { + LayoutAnimation.linear(); + }} + > + + + )} + { + setCommentGestureSetting('firstRight', e.nativeEvent.actionKey); + + if (e.nativeEvent.actionKey === 'none') { + setCommentGestureSetting('secondRight', 'none'); + } + }} + > + + + {settings.gestures.comment.firstRight !== 'none' && ( + { + setCommentGestureSetting( + 'secondRight', + e.nativeEvent.actionKey, + ); + }} + onLayout={() => { + LayoutAnimation.linear(); + }} + > + + + )} + ); diff --git a/src/state/comment/commentStore.ts b/src/state/comment/commentStore.ts index a82c0bd94..7f38763fd 100644 --- a/src/state/comment/commentStore.ts +++ b/src/state/comment/commentStore.ts @@ -46,3 +46,6 @@ export const useCommentSaved = (id: number): boolean => export const useCommentMyVote = (id: number): number | undefined => useCommentStore((state) => state.comments.get(id)?.my_vote); + +export const useCommentPostId = (id: number): number | undefined => + useCommentStore((state) => state.comments.get(id)?.post.id); diff --git a/src/state/settings/actions/index.ts b/src/state/settings/actions/index.ts index 9ec76c7f7..59fb4337d 100644 --- a/src/state/settings/actions/index.ts +++ b/src/state/settings/actions/index.ts @@ -1,2 +1,3 @@ -export * from './setGestureSetting'; +export * from './setPostGestureSetting'; export * from './setSetting'; +export * from './setCommentGestureSetting'; diff --git a/src/state/settings/actions/setCommentGestureSetting.ts b/src/state/settings/actions/setCommentGestureSetting.ts new file mode 100644 index 000000000..291291a98 --- /dev/null +++ b/src/state/settings/actions/setCommentGestureSetting.ts @@ -0,0 +1,17 @@ +import { + IGestureCommentSettings, + useSettingsStore, +} from '@src/state/settings/settingsStore'; +import { ICommentGestureOption } from '@src/types'; + +export const setCommentGestureSetting = < + T extends keyof IGestureCommentSettings, +>( + setting: T, + value: ICommentGestureOption | boolean | 'none', +): void => { + useSettingsStore.setState((state) => { + // @ts-expect-error -- T is a key of SettingsStore + state.gestures.comment[setting] = value; + }); +}; diff --git a/src/state/settings/actions/setGestureSetting.ts b/src/state/settings/actions/setPostGestureSetting.ts similarity index 100% rename from src/state/settings/actions/setGestureSetting.ts rename to src/state/settings/actions/setPostGestureSetting.ts diff --git a/src/state/settings/settingsStore.ts b/src/state/settings/settingsStore.ts index 7c8181f24..a22c2e8e6 100644 --- a/src/state/settings/settingsStore.ts +++ b/src/state/settings/settingsStore.ts @@ -1,6 +1,6 @@ import { IPostGestureOption } from '@src/types/IPostGestureOption'; import { CommentSortType, ListingType, SortType } from 'lemmy-js-client'; -import { IThemeOption } from '@src/types'; +import { ICommentGestureOption, IThemeOption } from '@src/types'; import { create } from 'zustand'; import { createJSONStorage, persist } from 'zustand/middleware'; import { immer } from 'zustand/middleware/immer'; @@ -217,3 +217,18 @@ export const usePostGesturesSecondRight = (): IPostGestureOption => useSettingsStore((state) => state.gestures.post.secondRight); export const usePostGesturesSecondLeft = (): IPostGestureOption => useSettingsStore((state) => state.gestures.post.secondLeft); + +export const useCommentGesturesEnabled = (): boolean => + useSettingsStore((state) => state.gestures.comment.enabled); + +export const useCommentGesturesCollapse = (): boolean => + useSettingsStore((state) => state.gestures.comment.collapse); + +export const useCommentGesturesFirstRight = (): ICommentGestureOption => + useSettingsStore((state) => state.gestures.comment.firstRight); +export const useCommentGesturesFirstLeft = (): ICommentGestureOption => + useSettingsStore((state) => state.gestures.comment.firstLeft); +export const useCommentGesturesSecondRight = (): ICommentGestureOption => + useSettingsStore((state) => state.gestures.comment.secondRight); +export const useCommentGesturesSecondLeft = (): ICommentGestureOption => + useSettingsStore((state) => state.gestures.comment.secondLeft);