From 66c49bc5426fbae9da32fa584762dd16e53b8c86 Mon Sep 17 00:00:00 2001 From: Sultan Date: Wed, 4 Dec 2024 11:07:53 +0100 Subject: [PATCH 1/4] remove unnecessary if statement --- src/app/Scenes/HomeView/Sections/HomeViewSectionTasks.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/app/Scenes/HomeView/Sections/HomeViewSectionTasks.tsx b/src/app/Scenes/HomeView/Sections/HomeViewSectionTasks.tsx index b8eeb616d0c..1b9235a51f9 100644 --- a/src/app/Scenes/HomeView/Sections/HomeViewSectionTasks.tsx +++ b/src/app/Scenes/HomeView/Sections/HomeViewSectionTasks.tsx @@ -93,10 +93,6 @@ export const HomeViewSectionTasks: React.FC = ({ }, [shouldStartOnboardingAnimation]) const handleClearTask = (task: Task) => { - if (!task) { - return - } - setClearedTasks((prev) => [...prev, task.internalID]) } From a0a262eb312d64e0ab39b5d37cafb3c263ee9e8d Mon Sep 17 00:00:00 2001 From: Sultan Date: Wed, 4 Dec 2024 17:08:30 +0100 Subject: [PATCH 2/4] update tasks list through the relay store --- src/app/Components/Tasks/Task.tsx | 49 +++++++++++++++---- .../Sections/HomeViewSectionTasks.tsx | 27 ++++------ src/app/utils/mutations/useAcknowledgeTask.ts | 47 +++++++++++++++--- src/app/utils/mutations/useDismissTask.ts | 46 ++++++++++++++--- 4 files changed, 130 insertions(+), 39 deletions(-) diff --git a/src/app/Components/Tasks/Task.tsx b/src/app/Components/Tasks/Task.tsx index 463ca6efb9e..ac2bec48237 100644 --- a/src/app/Components/Tasks/Task.tsx +++ b/src/app/Components/Tasks/Task.tsx @@ -1,5 +1,6 @@ import { ContextModule } from "@artsy/cohesion" import { Flex, Image, Text, Touchable } from "@artsy/palette-mobile" +import { captureMessage } from "@sentry/react-native" import { Task_task$key } from "__generated__/Task_task.graphql" import { Swipeable } from "app/Components/Swipeable/Swipeable" import { useHomeViewTracking } from "app/Scenes/HomeView/hooks/useHomeViewTracking" @@ -15,37 +16,64 @@ const TASK_IMAGE_SIZE = 60 interface TaskProps { disableSwipeable?: boolean - onClearTask: () => void + onClearTask?: () => void onPress?: () => void task: Task_task$key } export const Task = forwardRef( ({ disableSwipeable, onClearTask, onPress, ...restProps }, ref) => { + const task = useFragment(taskFragment, restProps.task) const { tappedTaskGroup, tappedClearTask } = useHomeViewTracking() - const { submitMutation: dismissTask } = useDismissTask() - const { submitMutation: acknowledgeTask } = useAcknowledgeTask() + const [dismissTask, dismissInProgress] = useDismissTask(task.id) + const [acknowledgeTask, acknowledgeInProgress] = useAcknowledgeTask(task.id) const fontScale = PixelRatio.getFontScale() - const task = useFragment(taskFragment, restProps.task) - const handlePressTask = async () => { if (onPress) { onPress() return } - await acknowledgeTask({ variables: { taskID: task.internalID } }) + if (acknowledgeInProgress) { + return + } + + acknowledgeTask({ + variables: { taskID: task.internalID }, + onError: (error) => { + if (__DEV__) { + console.error("[useAcknowledgeTaskMutation] Error: ", error.message) + } else { + captureMessage(`useAcknowledgeTaskMutation ${error.message}`) + } + }, + }) + tappedTaskGroup(ContextModule.actNow, task.actionLink, task.internalID, task.taskType) - onClearTask() + onClearTask?.() navigate(task.actionLink) } const handleClearTask = async () => { - await dismissTask({ variables: { taskID: task.internalID } }) + if (dismissInProgress) { + return + } + + dismissTask({ + variables: { taskID: task.internalID }, + onError: (error) => { + if (__DEV__) { + console.error("[useDismissTaskMutation] Error: ", error.message) + } else { + captureMessage(`useDismissTaskMutation ${error.message}`) + } + }, + }) + tappedClearTask(ContextModule.actNow, task.actionLink, task.internalID, task.taskType) - onClearTask() + onClearTask?.() } return ( @@ -62,7 +90,7 @@ export const Task = forwardRef( enabled={!disableSwipeable} > - + ( const taskFragment = graphql` fragment Task_task on Task { + id actionLink imageUrl internalID diff --git a/src/app/Scenes/HomeView/Sections/HomeViewSectionTasks.tsx b/src/app/Scenes/HomeView/Sections/HomeViewSectionTasks.tsx index 1b9235a51f9..c3144a4e3f5 100644 --- a/src/app/Scenes/HomeView/Sections/HomeViewSectionTasks.tsx +++ b/src/app/Scenes/HomeView/Sections/HomeViewSectionTasks.tsx @@ -38,7 +38,7 @@ const MAX_NUMBER_OF_TASKS = 10 // Height of each task + seperator const TASK_CARD_HEIGHT = 92 -type Task = ExtractNodeType +type Task = ExtractNodeType interface HomeViewSectionTasksProps extends FlexProps { section: HomeViewSectionTasks_section$key @@ -52,17 +52,15 @@ export const HomeViewSectionTasks: React.FC = ({ }) => { const swipeableRef = useRef(null) const section = useFragment(tasksFragment, sectionProp) - const tasks = extractNodes(section.tasksConnection) + const tasks = extractNodes(section.tasks) const isFocused = useIsFocused() const { isDismissed } = GlobalStore.useAppState((state) => state.progressiveOnboarding) const { dismiss } = GlobalStore.actions.progressiveOnboarding - const [clearedTasks, setClearedTasks] = useState([]) const [showAll, setShowAll] = useState(false) - const filteredTasks = tasks.filter((task) => !clearedTasks.includes(task.internalID)) - const displayTaskStack = filteredTasks.length > 1 && !showAll + const displayTaskStack = tasks.length > 1 && !showAll const HeaderIconComponent = showAll ? ArrowUpIcon : ArrowDownIcon const task = tasks?.[0] @@ -92,10 +90,6 @@ export const HomeViewSectionTasks: React.FC = ({ } }, [shouldStartOnboardingAnimation]) - const handleClearTask = (task: Task) => { - setClearedTasks((prev) => [...prev, task.internalID]) - } - const renderCell = useCallback(({ index, ...rest }: CellRendererProps) => { return }, []) @@ -124,7 +118,6 @@ export const HomeViewSectionTasks: React.FC = ({ > handleClearTask(item)} onPress={displayTaskStack ? () => setShowAll((prev) => !prev) : undefined} ref={swipeableRef} task={item} @@ -133,7 +126,7 @@ export const HomeViewSectionTasks: React.FC = ({ ) }, - [displayTaskStack, handleClearTask, showAll] + [displayTaskStack, showAll] ) const motiViewHeight = useMemo(() => { @@ -144,12 +137,12 @@ export const HomeViewSectionTasks: React.FC = ({ return singleTaskHeight } - return singleTaskHeight + (filteredTasks.length - 1) * TASK_CARD_HEIGHT - }, [filteredTasks, showAll]) + return singleTaskHeight + (tasks.length - 1) * TASK_CARD_HEIGHT + }, [tasks, showAll]) return ( - {!!filteredTasks.length && ( + {!!tasks.length && ( = ({ { - if (filteredTasks.length < 2) { + if (tasks.length < 2) { return null } @@ -179,7 +172,7 @@ export const HomeViewSectionTasks: React.FC = ({ item.internalID} CellRendererComponent={renderCell} ItemSeparatorComponent={() => } @@ -207,7 +200,7 @@ const tasksFragment = graphql` component { title } - tasksConnection(first: $numberOfTasks) { + tasks: tasksConnection(first: $numberOfTasks) @connection(key: "HomeViewSectionTasks_tasks") { edges { node { internalID diff --git a/src/app/utils/mutations/useAcknowledgeTask.ts b/src/app/utils/mutations/useAcknowledgeTask.ts index c4d965cd363..a2401fa1556 100644 --- a/src/app/utils/mutations/useAcknowledgeTask.ts +++ b/src/app/utils/mutations/useAcknowledgeTask.ts @@ -1,11 +1,46 @@ import { useAcknowledgeTaskMutation } from "__generated__/useAcknowledgeTaskMutation.graphql" -import { useMutation } from "app/utils/useMutation" -import { graphql } from "react-relay" +import { ConnectionHandler, graphql, useMutation, UseMutationConfig } from "react-relay" -export const useAcknowledgeTask = () => { - return useMutation({ - mutation: AcknowledgeTaskMutation, - }) +type MutationConfig = UseMutationConfig +type MutationResult = [(config: MutationConfig) => void, boolean] + +export const useAcknowledgeTask = (taskID: string): MutationResult => { + const [initialCommit, isInProgress] = + useMutation(AcknowledgeTaskMutation) + + const commit = (config: MutationConfig) => { + return initialCommit({ + ...config, + updater: (store, data) => { + const response = data.ackTask?.taskOrError + const homeViewTaskSection = store + .getRoot() + .getLinkedRecord("homeView") + ?.getLinkedRecord("section", { id: "home-view-section-tasks" }) + + if (!homeViewTaskSection || !response) { + return + } + + const task = store.get(taskID) + const key = "HomeViewSectionTasks_tasks" + const tasksConnection = ConnectionHandler.getConnection(homeViewTaskSection, key) + const mutationPayload = store.getRootField("ackTask") + const taskOrError = mutationPayload?.getLinkedRecord("taskOrError") + const taskAcknowledged = taskOrError?.getLinkedRecord("task") + + if (!tasksConnection || !task || !taskAcknowledged) { + return + } + + if (!!taskAcknowledged) { + ConnectionHandler.deleteNode(tasksConnection, taskID) + } + }, + }) + } + + return [commit, isInProgress] } const AcknowledgeTaskMutation = graphql` diff --git a/src/app/utils/mutations/useDismissTask.ts b/src/app/utils/mutations/useDismissTask.ts index 77b2fefc0c9..dae111fa07a 100644 --- a/src/app/utils/mutations/useDismissTask.ts +++ b/src/app/utils/mutations/useDismissTask.ts @@ -1,11 +1,45 @@ import { useDismissTaskMutation } from "__generated__/useDismissTaskMutation.graphql" -import { useMutation } from "app/utils/useMutation" -import { graphql } from "react-relay" +import { ConnectionHandler, graphql, useMutation, UseMutationConfig } from "react-relay" -export const useDismissTask = () => { - return useMutation({ - mutation: DismissTaskMutation, - }) +type MutationConfig = UseMutationConfig +type MutationResult = [(config: MutationConfig) => void, boolean] + +export const useDismissTask = (taskID: string): MutationResult => { + const [initialCommit, isInProgress] = useMutation(DismissTaskMutation) + + const commit = (config: MutationConfig) => { + return initialCommit({ + ...config, + updater: (store, data) => { + const response = data.dismissTask?.taskOrError + const homeViewTaskSection = store + .getRoot() + .getLinkedRecord("homeView") + ?.getLinkedRecord("section", { id: "home-view-section-tasks" }) + + if (!homeViewTaskSection || !response) { + return + } + + const task = store.get(taskID) + const key = "HomeViewSectionTasks_tasks" + const tasksConnection = ConnectionHandler.getConnection(homeViewTaskSection, key) + const mutationPayload = store.getRootField("dismissTask") + const taskOrError = mutationPayload?.getLinkedRecord("taskOrError") + const taskDismissed = taskOrError?.getLinkedRecord("task") + + if (!tasksConnection || !task || !taskDismissed) { + return + } + + if (!!taskDismissed) { + ConnectionHandler.deleteNode(tasksConnection, taskID) + } + }, + }) + } + + return [commit, isInProgress] } const DismissTaskMutation = graphql` From d8cf63a76bf3d36773f6951d030f3767fd4aa75c Mon Sep 17 00:00:00 2001 From: Sultan Date: Wed, 4 Dec 2024 18:26:15 +0100 Subject: [PATCH 3/4] remove unnecessary `async` --- src/app/Components/Tasks/Task.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/Components/Tasks/Task.tsx b/src/app/Components/Tasks/Task.tsx index ac2bec48237..251168deaec 100644 --- a/src/app/Components/Tasks/Task.tsx +++ b/src/app/Components/Tasks/Task.tsx @@ -29,7 +29,7 @@ export const Task = forwardRef( const [acknowledgeTask, acknowledgeInProgress] = useAcknowledgeTask(task.id) const fontScale = PixelRatio.getFontScale() - const handlePressTask = async () => { + const handlePressTask = () => { if (onPress) { onPress() return @@ -56,7 +56,7 @@ export const Task = forwardRef( navigate(task.actionLink) } - const handleClearTask = async () => { + const handleClearTask = () => { if (dismissInProgress) { return } From 12a2179604169e9d0d208967e6b803c3bc732847 Mon Sep 17 00:00:00 2001 From: Sultan Date: Wed, 4 Dec 2024 18:30:02 +0100 Subject: [PATCH 4/4] update tests --- src/app/Components/Tasks/Task.tests.tsx | 4 ++-- .../Sections/__tests__/HomeViewSectionTasks.tests.tsx | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/app/Components/Tasks/Task.tests.tsx b/src/app/Components/Tasks/Task.tests.tsx index 331c37e0774..f8e0f784349 100644 --- a/src/app/Components/Tasks/Task.tests.tsx +++ b/src/app/Components/Tasks/Task.tests.tsx @@ -11,11 +11,11 @@ const mockDissmissTask = jest.fn() const mockAcknowledgeTask = jest.fn() jest.mock("app/utils/mutations/useDismissTask", () => ({ - useDismissTask: () => ({ submitMutation: mockDissmissTask }), + useDismissTask: () => [mockDissmissTask], })) jest.mock("app/utils/mutations/useAcknowledgeTask.ts", () => ({ - useAcknowledgeTask: () => ({ submitMutation: mockAcknowledgeTask }), + useAcknowledgeTask: () => [mockAcknowledgeTask], })) describe("Task Component", () => { diff --git a/src/app/Scenes/HomeView/Sections/__tests__/HomeViewSectionTasks.tests.tsx b/src/app/Scenes/HomeView/Sections/__tests__/HomeViewSectionTasks.tests.tsx index 3acc5a408df..14104fa5b48 100644 --- a/src/app/Scenes/HomeView/Sections/__tests__/HomeViewSectionTasks.tests.tsx +++ b/src/app/Scenes/HomeView/Sections/__tests__/HomeViewSectionTasks.tests.tsx @@ -39,7 +39,7 @@ describe("HomeViewSectionTasks", () => { component: { title: "Act Now", }, - tasksConnection: mockTasks, + tasks: mockTasks, }), }) @@ -64,7 +64,7 @@ describe("HomeViewSectionTasks", () => { component: { title: "Act Now", }, - tasksConnection: { + tasks: { edges: [ { node: { @@ -94,7 +94,7 @@ describe("HomeViewSectionTasks", () => { component: { title: "Act Now", }, - tasksConnection: mockTasks, + tasks: mockTasks, }), }) @@ -129,7 +129,7 @@ describe("HomeViewSectionTasks", () => { component: { title: "Act Now", }, - tasksConnection: mockTasks, + tasks: mockTasks, }), })