2cdf5ae75b
### Description This pull request resolves an issue where the application switched to light mode after login even when the user’s system was set to dark mode. Before authentication the app correctly followed system preferences through CSS media queries, but that behavior broke once the user logged in. **Before** https://github.com/user-attachments/assets/75e73712-9cb2-42f9-9e25-3a22dc911b8d **After** https://github.com/user-attachments/assets/6bba45ce-3817-4e3d-9b45-ff0c7725cf82
220 lines
7.5 KiB
TypeScript
220 lines
7.5 KiB
TypeScript
import { useRecoilCallback, useRecoilState, useSetRecoilState } from 'recoil';
|
|
|
|
import { useIsLogged } from '@/auth/hooks/useIsLogged';
|
|
import { availableWorkspacesState } from '@/auth/states/availableWorkspacesState';
|
|
import { currentUserState } from '@/auth/states/currentUserState';
|
|
import { currentUserWorkspaceState } from '@/auth/states/currentUserWorkspaceState';
|
|
import { currentWorkspaceDeletedMembersState } from '@/auth/states/currentWorkspaceDeletedMembersState';
|
|
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
|
import { currentWorkspaceMembersState } from '@/auth/states/currentWorkspaceMembersState';
|
|
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
|
import { isCurrentUserLoadedState } from '@/auth/states/isCurrentUserLoadedState';
|
|
import { useInitializeFormatPreferences } from '@/localization/hooks/useInitializeFormatPreferences';
|
|
import { getDateFnsLocale } from '@/ui/field/display/utils/getDateFnsLocale.util';
|
|
import { coreViewsState } from '@/views/states/coreViewState';
|
|
import { type CoreViewWithRelations } from '@/views/types/CoreViewWithRelations';
|
|
import { type ColorScheme } from '@/workspace-member/types/WorkspaceMember';
|
|
import { enUS } from 'date-fns/locale';
|
|
import { useEffect, useState } from 'react';
|
|
import { useLocation } from 'react-router-dom';
|
|
import { type APP_LOCALES, SOURCE_LOCALE } from 'twenty-shared/translations';
|
|
import { AppPath, type ObjectPermissions } from 'twenty-shared/types';
|
|
import { isDefined } from 'twenty-shared/utils';
|
|
import {
|
|
type WorkspaceMember,
|
|
useFindAllCoreViewsQuery,
|
|
useGetCurrentUserQuery,
|
|
} from '~/generated-metadata/graphql';
|
|
import { dateLocaleState } from '~/localization/states/dateLocaleState';
|
|
import { dynamicActivate } from '~/utils/i18n/dynamicActivate';
|
|
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
|
import { isMatchingLocation } from '~/utils/isMatchingLocation';
|
|
|
|
export const UserAndViewsProviderEffect = () => {
|
|
const location = useLocation();
|
|
|
|
const [isCurrentUserLoaded, setIsCurrentUserLoaded] = useRecoilState(
|
|
isCurrentUserLoadedState,
|
|
);
|
|
|
|
const [localIsCurrentUserLoaded, setLocalIsCurrentUserLoaded] =
|
|
useState(false);
|
|
const [localAreViewsLoaded, setLocalAreViewsLoaded] = useState(false);
|
|
|
|
const setCurrentUser = useSetRecoilState(currentUserState);
|
|
const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState);
|
|
const setCurrentUserWorkspace = useSetRecoilState(currentUserWorkspaceState);
|
|
const setAvailableWorkspaces = useSetRecoilState(availableWorkspacesState);
|
|
const { initializeFormatPreferences } = useInitializeFormatPreferences();
|
|
const isLoggedIn = useIsLogged();
|
|
|
|
const updateLocaleCatalog = useRecoilCallback(
|
|
({ snapshot, set }) =>
|
|
async (newLocale: keyof typeof APP_LOCALES) => {
|
|
const localeValue = snapshot.getLoadable(dateLocaleState).getValue();
|
|
if (localeValue.locale !== newLocale) {
|
|
getDateFnsLocale(newLocale).then((localeCatalog) => {
|
|
set(dateLocaleState, {
|
|
locale: newLocale,
|
|
localeCatalog: localeCatalog || enUS,
|
|
});
|
|
});
|
|
}
|
|
},
|
|
[],
|
|
);
|
|
|
|
const setCoreViews = useRecoilCallback(
|
|
({ set, snapshot }) =>
|
|
(coreViews: CoreViewWithRelations[]) => {
|
|
const existingCoreViews = snapshot
|
|
.getLoadable(coreViewsState)
|
|
.getValue();
|
|
|
|
if (!isDeeplyEqual(existingCoreViews, coreViews)) {
|
|
set(coreViewsState, coreViews);
|
|
}
|
|
},
|
|
[],
|
|
);
|
|
|
|
const setCurrentWorkspaceMember = useSetRecoilState(
|
|
currentWorkspaceMemberState,
|
|
);
|
|
const setCurrentWorkspaceMembers = useSetRecoilState(
|
|
currentWorkspaceMembersState,
|
|
);
|
|
const setCurrentWorkspaceMembersWithDeleted = useSetRecoilState(
|
|
currentWorkspaceDeletedMembersState,
|
|
);
|
|
|
|
const shouldSkip =
|
|
!isLoggedIn ||
|
|
isCurrentUserLoaded ||
|
|
isMatchingLocation(location, AppPath.Verify) ||
|
|
isMatchingLocation(location, AppPath.VerifyEmail);
|
|
|
|
const { data: userQueryData, loading: userQueryLoading } =
|
|
useGetCurrentUserQuery({
|
|
skip: shouldSkip,
|
|
});
|
|
|
|
const { data: queryDataCoreViews, loading: queryLoadingCoreViews } =
|
|
useFindAllCoreViewsQuery({
|
|
skip: shouldSkip,
|
|
});
|
|
|
|
useEffect(() => {
|
|
if (!userQueryLoading) {
|
|
setLocalIsCurrentUserLoaded(true);
|
|
}
|
|
|
|
if (!isDefined(userQueryData?.currentUser)) return;
|
|
|
|
setCurrentUser(userQueryData.currentUser);
|
|
|
|
if (isDefined(userQueryData.currentUser.currentWorkspace)) {
|
|
setCurrentWorkspace({
|
|
...userQueryData.currentUser.currentWorkspace,
|
|
defaultRole:
|
|
userQueryData.currentUser.currentWorkspace.defaultRole ?? null,
|
|
workspaceCustomApplication:
|
|
userQueryData.currentUser.currentWorkspace
|
|
.workspaceCustomApplication ?? null,
|
|
});
|
|
}
|
|
|
|
if (isDefined(userQueryData.currentUser.currentUserWorkspace)) {
|
|
setCurrentUserWorkspace({
|
|
permissionFlags:
|
|
userQueryData.currentUser.currentUserWorkspace.permissionFlags ?? [],
|
|
twoFactorAuthenticationMethodSummary:
|
|
userQueryData.currentUser.currentUserWorkspace
|
|
.twoFactorAuthenticationMethodSummary ?? [],
|
|
objectsPermissions:
|
|
(userQueryData.currentUser.currentUserWorkspace
|
|
.objectsPermissions as Array<
|
|
ObjectPermissions & { objectMetadataId: string }
|
|
>) ?? [],
|
|
});
|
|
}
|
|
|
|
const {
|
|
workspaceMember,
|
|
workspaceMembers,
|
|
deletedWorkspaceMembers,
|
|
availableWorkspaces,
|
|
} = userQueryData.currentUser;
|
|
|
|
const affectDefaultValuesOnEmptyWorkspaceMemberFields = (
|
|
workspaceMember: WorkspaceMember,
|
|
) => {
|
|
return {
|
|
...workspaceMember,
|
|
colorScheme: (workspaceMember.colorScheme as ColorScheme) ?? 'System',
|
|
locale:
|
|
(workspaceMember.locale as keyof typeof APP_LOCALES) ?? SOURCE_LOCALE,
|
|
};
|
|
};
|
|
|
|
if (isDefined(workspaceMember)) {
|
|
const updatedWorkspaceMember =
|
|
affectDefaultValuesOnEmptyWorkspaceMemberFields(workspaceMember);
|
|
setCurrentWorkspaceMember(updatedWorkspaceMember);
|
|
|
|
updateLocaleCatalog(updatedWorkspaceMember.locale);
|
|
|
|
// Initialize format preferences from workspace member
|
|
initializeFormatPreferences(updatedWorkspaceMember);
|
|
|
|
dynamicActivate(
|
|
(workspaceMember.locale as keyof typeof APP_LOCALES) ?? SOURCE_LOCALE,
|
|
);
|
|
}
|
|
|
|
if (isDefined(workspaceMembers)) {
|
|
setCurrentWorkspaceMembers(workspaceMembers);
|
|
}
|
|
|
|
if (isDefined(deletedWorkspaceMembers)) {
|
|
setCurrentWorkspaceMembersWithDeleted(deletedWorkspaceMembers);
|
|
}
|
|
|
|
if (isDefined(availableWorkspaces)) {
|
|
setAvailableWorkspaces(availableWorkspaces);
|
|
}
|
|
}, [
|
|
userQueryLoading,
|
|
userQueryData?.currentUser,
|
|
setCurrentUser,
|
|
setCurrentUserWorkspace,
|
|
setCurrentWorkspaceMembers,
|
|
setAvailableWorkspaces,
|
|
setCurrentWorkspace,
|
|
setCurrentWorkspaceMember,
|
|
setIsCurrentUserLoaded,
|
|
initializeFormatPreferences,
|
|
setCurrentWorkspaceMembersWithDeleted,
|
|
updateLocaleCatalog,
|
|
setCoreViews,
|
|
]);
|
|
|
|
useEffect(() => {
|
|
if (!queryLoadingCoreViews) {
|
|
setLocalAreViewsLoaded(true);
|
|
}
|
|
|
|
if (!isDefined(queryDataCoreViews?.getCoreViews)) return;
|
|
|
|
setCoreViews(queryDataCoreViews.getCoreViews);
|
|
}, [queryDataCoreViews?.getCoreViews, setCoreViews, queryLoadingCoreViews]);
|
|
|
|
useEffect(() => {
|
|
if (localIsCurrentUserLoaded && localAreViewsLoaded) {
|
|
setIsCurrentUserLoaded(true);
|
|
}
|
|
}, [localIsCurrentUserLoaded, localAreViewsLoaded, setIsCurrentUserLoaded]);
|
|
|
|
return null;
|
|
};
|