Improved activity editor re-renders (#4149)

* Refactor task count

* Fixed show page rerender

* Less rerenders and way better title and body UX

* Finished breaking down activity editor subscriptions

* Removed console.log

* Last console.log

* Fixed bugs and cleaned
This commit is contained in:
Lucas Bordeau
2024-02-23 17:54:27 +01:00
committed by GitHub
parent 5de1c2c31d
commit fb920a92e7
48 changed files with 1114 additions and 527 deletions

View File

@ -90,7 +90,7 @@ export const useActivities = ({
const loading = loadingActivities || loadingActivityTargets;
// TODO: fix connection in relation => automatically change to an array
const activities = activitiesWithConnection
const activities: Activity[] = activitiesWithConnection
?.map(makeActivityWithoutConnection as any)
.map(({ activity }: any) => activity);

View File

@ -10,7 +10,10 @@ export const useActivityTargetsForTargetableObjects = ({
targetableObjects,
skip,
}: {
targetableObjects: ActivityTargetableObject[];
targetableObjects: Pick<
ActivityTargetableObject,
'id' | 'targetObjectNameSingular'
>[];
skip?: boolean;
}) => {
const activityTargetsFilter = getActivityTargetsFilter({

View File

@ -1,4 +1,4 @@
import { useRecoilValue } from 'recoil';
import { useRecoilCallback, useRecoilValue } from 'recoil';
import { v4 } from 'uuid';
import { useAttachRelationInBothDirections } from '@/activities/hooks/useAttachRelationInBothDirections';
@ -6,13 +6,15 @@ import { useInjectIntoActivityTargetInlineCellCache } from '@/activities/inline-
import { Activity, ActivityType } from '@/activities/types/Activity';
import { ActivityTarget } from '@/activities/types/ActivityTarget';
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
import { getActivityTargetsToCreateFromTargetableObjects } from '@/activities/utils/getActivityTargetsToCreateFromTargetableObjects';
import { makeActivityTargetsToCreateFromTargetableObjects } from '@/activities/utils/getActivityTargetsToCreateFromTargetableObjects';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useCreateManyRecordsInCache } from '@/object-record/hooks/useCreateManyRecordsInCache';
import { useCreateOneRecordInCache } from '@/object-record/hooks/useCreateOneRecordInCache';
import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember';
import { isDefined } from '~/utils/isDefined';
export const useCreateActivityInCache = () => {
const { createManyRecordsInCache: createManyActivityTargetsInCache } =
@ -39,58 +41,86 @@ export const useCreateActivityInCache = () => {
const { attachRelationInBothDirections } =
useAttachRelationInBothDirections();
const createActivityInCache = ({
type,
targetableObjects,
customAssignee,
}: {
type: ActivityType;
targetableObjects: ActivityTargetableObject[];
customAssignee?: WorkspaceMember;
}) => {
const activityId = v4();
const createdActivityInCache = createOneActivityInCache({
id: activityId,
author: currentWorkspaceMemberRecord,
authorId: currentWorkspaceMemberRecord?.id,
assignee: customAssignee ?? currentWorkspaceMemberRecord,
assigneeId: customAssignee?.id ?? currentWorkspaceMemberRecord?.id,
type,
});
const activityTargetsToCreate =
getActivityTargetsToCreateFromTargetableObjects({
activityId,
const createActivityInCache = useRecoilCallback(
({ snapshot, set }) =>
({
type,
targetableObjects,
});
customAssignee,
}: {
type: ActivityType;
targetableObjects: ActivityTargetableObject[];
customAssignee?: WorkspaceMember;
}) => {
const activityId = v4();
const createdActivityTargetsInCache = createManyActivityTargetsInCache(
activityTargetsToCreate,
);
const createdActivityInCache = createOneActivityInCache({
id: activityId,
author: currentWorkspaceMemberRecord,
authorId: currentWorkspaceMemberRecord?.id,
assignee: customAssignee ?? currentWorkspaceMemberRecord,
assigneeId: customAssignee?.id ?? currentWorkspaceMemberRecord?.id,
type,
});
injectIntoActivityTargetInlineCellCache({
activityId,
activityTargetsToInject: createdActivityTargetsInCache,
});
const targetObjectRecords = targetableObjects
.map((targetableObject) => {
const targetObject = snapshot
.getLoadable(recordStoreFamilyState(targetableObject.id))
.getValue();
attachRelationInBothDirections({
sourceRecord: createdActivityInCache,
fieldNameOnSourceRecord: 'activityTargets',
sourceObjectNameSingular: CoreObjectNameSingular.Activity,
fieldNameOnTargetRecord: 'activity',
targetObjectNameSingular: CoreObjectNameSingular.ActivityTarget,
targetRecords: createdActivityTargetsInCache,
});
return targetObject;
})
.filter(isDefined);
return {
createdActivityInCache: {
...createdActivityInCache,
activityTargets: createdActivityTargetsInCache,
const activityTargetsToCreate =
makeActivityTargetsToCreateFromTargetableObjects({
activityId,
targetableObjects,
targetObjectRecords,
});
const createdActivityTargetsInCache = createManyActivityTargetsInCache(
activityTargetsToCreate,
);
injectIntoActivityTargetInlineCellCache({
activityId,
activityTargetsToInject: createdActivityTargetsInCache,
});
attachRelationInBothDirections({
sourceRecord: createdActivityInCache,
fieldNameOnSourceRecord: 'activityTargets',
sourceObjectNameSingular: CoreObjectNameSingular.Activity,
fieldNameOnTargetRecord: 'activity',
targetObjectNameSingular: CoreObjectNameSingular.ActivityTarget,
targetRecords: createdActivityTargetsInCache,
});
// TODO: should refactor when refactoring make activity connection utils
set(recordStoreFamilyState(activityId), {
...createdActivityInCache,
activityTargets: createdActivityTargetsInCache,
comments: [],
});
return {
createdActivityInCache: {
...createdActivityInCache,
activityTargets: createdActivityTargetsInCache,
},
createdActivityTargetsInCache,
};
},
createdActivityTargetsInCache,
};
};
[
attachRelationInBothDirections,
createManyActivityTargetsInCache,
createOneActivityInCache,
currentWorkspaceMemberRecord,
injectIntoActivityTargetInlineCellCache,
],
);
return {
createActivityInCache,

View File

@ -1,7 +1,6 @@
import { useRecoilState } from 'recoil';
import { activityInDrawerState } from '@/activities/states/activityInDrawerState';
import { Activity } from '@/activities/types/Activity';
import { activityIdInDrawerState } from '@/activities/states/activityIdInDrawerState';
import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer';
import { RightDrawerHotkeyScope } from '@/ui/layout/right-drawer/types/RightDrawerHotkeyScope';
import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPages';
@ -15,21 +14,21 @@ export const useOpenActivityRightDrawer = () => {
const [viewableActivityId, setViewableActivityId] = useRecoilState(
viewableActivityIdState,
);
const [, setActivityInDrawer] = useRecoilState(activityInDrawerState);
const [, setActivityIdInDrawer] = useRecoilState(activityIdInDrawerState);
const setHotkeyScope = useSetHotkeyScope();
return (activity: Activity) => {
return (activityId: string) => {
if (
isRightDrawerOpen &&
rightDrawerPage === RightDrawerPages.EditActivity &&
viewableActivityId === activity.id
viewableActivityId === activityId
) {
return;
}
setHotkeyScope(RightDrawerHotkeyScope.RightDrawer, { goto: false });
setViewableActivityId(activity.id);
setActivityInDrawer(activity);
setViewableActivityId(activityId);
setActivityIdInDrawer(activityId);
openRightDrawer(RightDrawerPages.EditActivity);
};
};

View File

@ -1,7 +1,7 @@
import { useRecoilState, useSetRecoilState } from 'recoil';
import { useCreateActivityInCache } from '@/activities/hooks/useCreateActivityInCache';
import { activityInDrawerState } from '@/activities/states/activityInDrawerState';
import { activityIdInDrawerState } from '@/activities/states/activityIdInDrawerState';
import { activityTargetableEntityArrayState } from '@/activities/states/activityTargetableEntityArrayState';
import { isActivityInCreateModeState } from '@/activities/states/isActivityInCreateModeState';
import { isUpsertingActivityInDBState } from '@/activities/states/isCreatingActivityInDBState';
@ -34,7 +34,7 @@ export const useOpenCreateActivityDrawer = () => {
temporaryActivityForEditorState,
);
const setActivityInDrawer = useSetRecoilState(activityInDrawerState);
const setActivityIdInDrawer = useSetRecoilState(activityIdInDrawerState);
const [, setIsUpsertingActivityInDB] = useRecoilState(
isUpsertingActivityInDBState,
@ -55,7 +55,7 @@ export const useOpenCreateActivityDrawer = () => {
customAssignee,
});
setActivityInDrawer(createdActivityInCache);
setActivityIdInDrawer(createdActivityInCache.id);
setTemporaryActivityForEditor(createdActivityInCache);
setIsCreatingActivity(true);
setHotkeyScope(RightDrawerHotkeyScope.RightDrawer, { goto: false });

View File

@ -6,13 +6,13 @@ import { useCreateActivityInDB } from '@/activities/hooks/useCreateActivityInDB'
import { useInjectIntoActivitiesQueries } from '@/activities/hooks/useInjectIntoActivitiesQueries';
import { useInjectIntoActivityTargetsQueries } from '@/activities/hooks/useInjectIntoActivityTargetsQueries';
import { currentNotesQueryVariablesState } from '@/activities/notes/states/currentNotesQueryVariablesState';
import { activityInDrawerState } from '@/activities/states/activityInDrawerState';
import { activityIdInDrawerState } from '@/activities/states/activityIdInDrawerState';
import { isActivityInCreateModeState } from '@/activities/states/isActivityInCreateModeState';
import { isUpsertingActivityInDBState } from '@/activities/states/isCreatingActivityInDBState';
import { currentCompletedTaskQueryVariablesState } from '@/activities/tasks/states/currentCompletedTaskQueryVariablesState';
import { currentIncompleteTaskQueryVariablesState } from '@/activities/tasks/states/currentIncompleteTaskQueryVariablesState';
import { useInjectIntoTimelineActivitiesQueries } from '@/activities/timeline/hooks/useInjectIntoTimelineActivitiesQueries';
import { objectShowPageTargetableObjectState } from '@/activities/timeline/states/objectShowPageTargetableObjectState';
import { objectShowPageTargetableObjectState } from '@/activities/timeline/states/objectShowPageTargetableObjectIdState';
import { Activity } from '@/activities/types/Activity';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
@ -34,7 +34,7 @@ export const useUpsertActivity = () => {
isUpsertingActivityInDBState,
);
const setActivityInDrawer = useSetRecoilState(activityInDrawerState);
const setActivityIdInDrawer = useSetRecoilState(activityIdInDrawerState);
const objectShowPageTargetableObject = useRecoilValue(
objectShowPageTargetableObjectState,
@ -169,7 +169,7 @@ export const useUpsertActivity = () => {
await createActivityInDB(activityToCreate);
setActivityInDrawer(activityToCreate);
setActivityIdInDrawer(activityToCreate.id);
setIsActivityInCreateMode(false);
} else {