Activity cache injection (#3791)

* WIP

* Minor fixes

* Added TODO

* Fix post merge

* Fix

* Fixed warnings

* Fixed comments

* Fixed comments

* Fixed naming

* Removed comment

* WIP

* WIP 2

* Finished working version

* Fixes

* Fixed typing

* Fixes

* Fixes

* Fixes

* Naming fixes

* WIP

* Fix import

* WIP

* Working version on title

* Fixed create record id overwrite

* Removed unecessary callback

* Masterpiece

* Fixed delete on click outside drawer or delete

* Cleaned

* Cleaned

* Cleaned

* Minor fixes

* Fixes

* Fixed naming

* WIP

* Fix

* Fixed create from target inline cell

* Removed console.log

* Fixed delete activity optimistic effect

* Fixed no title

* Fixed debounce and title body creation

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Lucas Bordeau
2024-02-09 14:51:30 +01:00
committed by GitHub
parent 9ceff84bbf
commit cca72da708
87 changed files with 2195 additions and 1058 deletions

View File

@ -1,3 +1,4 @@
import { clickOutsideListenerCallbacksStateScopeMap } from '@/ui/utilities/pointer-event/states/clickOutsideListenerCallbacksStateScopeMap';
import { clickOutsideListenerIsActivatedStateScopeMap } from '@/ui/utilities/pointer-event/states/clickOutsideListenerIsActivatedStateScopeMap';
import { clickOutsideListenerIsMouseDownInsideStateScopeMap } from '@/ui/utilities/pointer-event/states/clickOutsideListenerIsMouseDownInsideStateScopeMap';
import { lockedListenerIdState } from '@/ui/utilities/pointer-event/states/lockedListenerIdState';
@ -9,6 +10,10 @@ export const useClickOustideListenerStates = (componentId: string) => {
return {
scopeId,
getClickOutsideListenerCallbacksState: getState(
clickOutsideListenerCallbacksStateScopeMap,
scopeId,
),
getClickOutsideListenerIsMouseDownInsideState: getState(
clickOutsideListenerIsMouseDownInsideStateScopeMap,
scopeId,

View File

@ -1,3 +1,4 @@
import { useEffect } from 'react';
import { useRecoilCallback } from 'recoil';
import { useClickOustideListenerStates } from '@/ui/utilities/pointer-event/hooks/useClickOustideListenerStates';
@ -5,14 +6,18 @@ import {
ClickOutsideListenerProps,
useListenClickOutsideV2,
} from '@/ui/utilities/pointer-event/hooks/useListenClickOutsideV2';
import { ClickOutsideListenerCallback } from '@/ui/utilities/pointer-event/types/ClickOutsideListenerCallback';
import { getScopeIdFromComponentId } from '@/ui/utilities/recoil-scope/utils/getScopeIdFromComponentId';
import { isDefined } from '~/utils/isDefined';
export const useClickOutsideListener = (componentId: string) => {
// TODO: improve typing
const scopeId = getScopeIdFromComponentId(componentId) ?? '';
const { getClickOutsideListenerIsActivatedState } =
useClickOustideListenerStates(componentId);
const {
getClickOutsideListenerIsActivatedState,
getClickOutsideListenerCallbacksState,
} = useClickOustideListenerStates(componentId);
const useListenClickOutside = <T extends Element>({
callback,
@ -23,7 +28,21 @@ export const useClickOutsideListener = (componentId: string) => {
return useListenClickOutsideV2({
listenerId: componentId,
refs,
callback,
callback: useRecoilCallback(
({ snapshot }) =>
(event) => {
callback(event);
const additionalCallbacks = snapshot
.getLoadable(getClickOutsideListenerCallbacksState())
.getValue();
additionalCallbacks.forEach((additionalCallback) => {
additionalCallback.callbackFunction(event);
});
},
[callback],
),
enabled,
mode,
});
@ -37,9 +56,97 @@ export const useClickOutsideListener = (componentId: string) => {
[getClickOutsideListenerIsActivatedState],
);
const registerOnClickOutsideCallback = useRecoilCallback(
({ set, snapshot }) =>
({ callbackFunction, callbackId }: ClickOutsideListenerCallback) => {
const existingCallbacks = snapshot
.getLoadable(getClickOutsideListenerCallbacksState())
.getValue();
const existingCallbackWithSameId = existingCallbacks.find(
(callback) => callback.callbackId === callbackId,
);
if (!isDefined(existingCallbackWithSameId)) {
const existingCallbacksWithNewCallback = existingCallbacks.concat({
callbackId,
callbackFunction,
});
set(
getClickOutsideListenerCallbacksState(),
existingCallbacksWithNewCallback,
);
} else {
const existingCallbacksWithOverwrittenCallback = [
...existingCallbacks,
];
const indexOfExistingCallbackWithSameId =
existingCallbacksWithOverwrittenCallback.findIndex(
(callback) => callback.callbackId === callbackId,
);
existingCallbacksWithOverwrittenCallback[
indexOfExistingCallbackWithSameId
] = {
callbackId,
callbackFunction,
};
set(
getClickOutsideListenerCallbacksState(),
existingCallbacksWithOverwrittenCallback,
);
}
},
[getClickOutsideListenerCallbacksState],
);
const unregisterOnClickOutsideCallback = useRecoilCallback(
({ set, snapshot }) =>
({ callbackId }: { callbackId: string }) => {
const existingCallbacks = snapshot
.getLoadable(getClickOutsideListenerCallbacksState())
.getValue();
const indexOfCallbackToUnsubscribe = existingCallbacks.findIndex(
(callback) => callback.callbackId === callbackId,
);
const callbackToUnsubscribeIsFound = indexOfCallbackToUnsubscribe > -1;
if (callbackToUnsubscribeIsFound) {
const newCallbacksWithoutCallbackToUnsubscribe =
existingCallbacks.toSpliced(indexOfCallbackToUnsubscribe, 1);
set(
getClickOutsideListenerCallbacksState(),
newCallbacksWithoutCallbackToUnsubscribe,
);
}
},
[getClickOutsideListenerCallbacksState],
);
const useRegisterClickOutsideListenerCallback = (
callback: ClickOutsideListenerCallback,
) => {
useEffect(() => {
registerOnClickOutsideCallback(callback);
return () => {
unregisterOnClickOutsideCallback({
callbackId: callback.callbackId,
});
};
}, [callback]);
};
return {
scopeId,
useListenClickOutside,
toggleClickOutsideListener,
useRegisterClickOutsideListenerCallback,
};
};

View File

@ -0,0 +1,9 @@
import { ClickOutsideListenerCallback } from '@/ui/utilities/pointer-event/types/ClickOutsideListenerCallback';
import { createStateScopeMap } from '@/ui/utilities/recoil-scope/utils/createStateScopeMap';
export const clickOutsideListenerCallbacksStateScopeMap = createStateScopeMap<
ClickOutsideListenerCallback[]
>({
key: 'clickOutsideListenerCallbacksStateScopeMap',
defaultValue: [],
});

View File

@ -0,0 +1,6 @@
import { ClickOutsideListenerCallbackFunction } from '@/ui/utilities/pointer-event/types/ClickOutsideListenerCallbackFunction';
export type ClickOutsideListenerCallback = {
callbackId: string;
callbackFunction: ClickOutsideListenerCallbackFunction;
};

View File

@ -0,0 +1,3 @@
export type ClickOutsideListenerCallbackFunction = (
event: MouseEvent | TouchEvent,
) => void;