Просмотр исходного кода

add scheduleToPutUserUISettings method

Yuki Takei 4 лет назад
Родитель
Сommit
f50b7f1799

+ 5 - 5
packages/app/src/components/Sidebar.tsx

@@ -8,13 +8,13 @@ import {
   useCurrentSidebarContents,
   useCurrentSidebarContents,
   useCurrentProductNavWidth,
   useCurrentProductNavWidth,
   useSidebarResizeDisabled,
   useSidebarResizeDisabled,
-  putUserUISettings,
 } from '~/stores/ui';
 } from '~/stores/ui';
 
 
 import DrawerToggler from './Navbar/DrawerToggler';
 import DrawerToggler from './Navbar/DrawerToggler';
 
 
 import SidebarNav from './Sidebar/SidebarNav';
 import SidebarNav from './Sidebar/SidebarNav';
 import SidebarContents from './Sidebar/SidebarContents';
 import SidebarContents from './Sidebar/SidebarContents';
+import { scheduleToPutUserUISettings } from '~/services/user-ui-settings';
 
 
 const sidebarMinWidth = 240;
 const sidebarMinWidth = 240;
 const sidebarMinimizeWidth = 20;
 const sidebarMinimizeWidth = 20;
@@ -34,7 +34,7 @@ const GlobalNavigation = () => {
     }
     }
 
 
     mutateSidebarCollapsed(newValue, false);
     mutateSidebarCollapsed(newValue, false);
-    putUserUISettings({ isSidebarCollapsed: newValue });
+    scheduleToPutUserUISettings({ isSidebarCollapsed: newValue });
 
 
   }, [currentContents, isCollapsed, mutateSidebarCollapsed]);
   }, [currentContents, isCollapsed, mutateSidebarCollapsed]);
 
 
@@ -209,7 +209,7 @@ const Sidebar: FC<Props> = (props: Props) => {
   const toggleNavigationBtnClickHandler = useCallback(() => {
   const toggleNavigationBtnClickHandler = useCallback(() => {
     const newValue = !isCollapsed;
     const newValue = !isCollapsed;
     mutateSidebarCollapsed(newValue, false);
     mutateSidebarCollapsed(newValue, false);
-    putUserUISettings({ isSidebarCollapsed: newValue });
+    scheduleToPutUserUISettings({ isSidebarCollapsed: newValue });
   }, [isCollapsed, mutateSidebarCollapsed]);
   }, [isCollapsed, mutateSidebarCollapsed]);
 
 
   useEffect(() => {
   useEffect(() => {
@@ -243,12 +243,12 @@ const Sidebar: FC<Props> = (props: Props) => {
       // force collapsed
       // force collapsed
       mutateSidebarCollapsed(true, false);
       mutateSidebarCollapsed(true, false);
       mutateProductNavWidth(sidebarMinWidth, false);
       mutateProductNavWidth(sidebarMinWidth, false);
-      putUserUISettings({ isSidebarCollapsed: true, currentProductNavWidth: sidebarMinWidth });
+      scheduleToPutUserUISettings({ isSidebarCollapsed: true, currentProductNavWidth: sidebarMinWidth });
     }
     }
     else {
     else {
       const newWidth = resizableContainer.current.clientWidth;
       const newWidth = resizableContainer.current.clientWidth;
       mutateProductNavWidth(newWidth, false);
       mutateProductNavWidth(newWidth, false);
-      putUserUISettings({ currentProductNavWidth: newWidth });
+      scheduleToPutUserUISettings({ currentProductNavWidth: newWidth });
     }
     }
 
 
     resizableContainer.current.classList.remove('dragging');
     resizableContainer.current.classList.remove('dragging');

+ 6 - 5
packages/app/src/components/Sidebar/SidebarNav.tsx

@@ -1,8 +1,9 @@
-import React, { FC, useCallback } from 'react';
+import React, { FC, memo, useCallback } from 'react';
 
 
 import { SidebarContentsType } from '~/interfaces/ui';
 import { SidebarContentsType } from '~/interfaces/ui';
+import { scheduleToPutUserUISettings } from '~/services/user-ui-settings';
 import { useCurrentUser, useIsSharedUser } from '~/stores/context';
 import { useCurrentUser, useIsSharedUser } from '~/stores/context';
-import { useCurrentSidebarContents, putUserUISettings } from '~/stores/ui';
+import { useCurrentSidebarContents } from '~/stores/ui';
 
 
 
 
 type PrimaryItemProps = {
 type PrimaryItemProps = {
@@ -29,7 +30,7 @@ const PrimaryItem: FC<PrimaryItemProps> = (props: PrimaryItemProps) => {
     }
     }
 
 
     mutate(contents, false);
     mutate(contents, false);
-    putUserUISettings({ currentSidebarContents: contents });
+    scheduleToPutUserUISettings({ currentSidebarContents: contents });
   }, [contents, mutate, onItemSelected]);
   }, [contents, mutate, onItemSelected]);
 
 
   return (
   return (
@@ -50,7 +51,7 @@ type SecondaryItemProps = {
   isBlank?: boolean,
   isBlank?: boolean,
 }
 }
 
 
-const SecondaryItem: FC<SecondaryItemProps> = (props: SecondaryItemProps) => {
+const SecondaryItem: FC<SecondaryItemProps> = memo((props: SecondaryItemProps) => {
   const { iconName, href, isBlank } = props;
   const { iconName, href, isBlank } = props;
 
 
   return (
   return (
@@ -58,7 +59,7 @@ const SecondaryItem: FC<SecondaryItemProps> = (props: SecondaryItemProps) => {
       <i className="material-icons">{iconName}</i>
       <i className="material-icons">{iconName}</i>
     </a>
     </a>
   );
   );
-};
+});
 
 
 
 
 type Props = {
 type Props = {

+ 28 - 0
packages/app/src/services/user-ui-settings.ts

@@ -0,0 +1,28 @@
+// eslint-disable-next-line no-restricted-imports
+import { AxiosResponse } from 'axios';
+
+import { debounce } from 'throttle-debounce';
+
+import { apiv3Put } from '~/client/util/apiv3-client';
+import { IUserUISettings } from '~/interfaces/user-ui-settings';
+
+let settingsForBulk: Partial<IUserUISettings> = {};
+const _putUserUISettingsInBulk = (): Promise<AxiosResponse<IUserUISettings>> => {
+  const result = apiv3Put<IUserUISettings>('/user-ui-settings', { settings: settingsForBulk });
+
+  // clear partial
+  settingsForBulk = {};
+
+  return result;
+};
+
+const _putUserUISettingsInBulkDebounced = debounce(1500, false, _putUserUISettingsInBulk);
+
+export const scheduleToPutUserUISettings = (settings: Partial<IUserUISettings>): Promise<AxiosResponse<IUserUISettings>> => {
+  settingsForBulk = {
+    ...settingsForBulk,
+    ...settings,
+  };
+
+  return _putUserUISettingsInBulkDebounced();
+};

+ 1 - 7
packages/app/src/stores/ui.tsx

@@ -3,11 +3,9 @@ import {
 } from 'swr';
 } from 'swr';
 import useSWRImmutable from 'swr/immutable';
 import useSWRImmutable from 'swr/immutable';
 
 
-// eslint-disable-next-line no-restricted-imports
-import { AxiosResponse } from 'axios';
-
 import { Breakpoint, addBreakpointListener } from '@growi/ui';
 import { Breakpoint, addBreakpointListener } from '@growi/ui';
 
 
+import { apiv3Get } from '~/client/util/apiv3-client';
 import { SidebarContentsType } from '~/interfaces/ui';
 import { SidebarContentsType } from '~/interfaces/ui';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
 
 
@@ -130,10 +128,6 @@ export const useSWRxUserUISettings = (): SWRResponse<IUserUISettings, Error> =>
   );
   );
 };
 };
 
 
-export const putUserUISettings = async(settings: Partial<IUserUISettings>): Promise<AxiosResponse<IUserUISettings>> => {
-  return apiv3Put<IUserUISettings>('/user-ui-settings', { settings });
-};
-
 export const useSidebarCollapsed = (): SWRResponse<boolean, Error> => {
 export const useSidebarCollapsed = (): SWRResponse<boolean, Error> => {
   const { data } = useSWRxUserUISettings();
   const { data } = useSWRxUserUISettings();
   const key = data === undefined ? null : 'isSidebarCollapsed';
   const key = data === undefined ? null : 'isSidebarCollapsed';