index.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. // contexts/User/index.jsx
  2. import React, { useState, useEffect, useCallback } from 'react';
  3. import { useLocation } from 'react-router-dom';
  4. import { isMobile as getIsMobile } from '../../helpers/index.js';
  5. export const StyleContext = React.createContext({
  6. dispatch: () => null,
  7. });
  8. export const StyleProvider = ({ children }) => {
  9. const location = useLocation();
  10. const initialIsMobile = getIsMobile();
  11. const initialPathname = location.pathname;
  12. let initialShowSiderValue = false;
  13. let initialInnerPaddingValue = false;
  14. if (initialPathname.includes('/console')) {
  15. initialShowSiderValue = !initialIsMobile;
  16. initialInnerPaddingValue = true;
  17. }
  18. const [state, setState] = useState({
  19. isMobile: initialIsMobile,
  20. showSider: initialShowSiderValue,
  21. siderCollapsed: false,
  22. shouldInnerPadding: initialInnerPaddingValue,
  23. manualSiderControl: false,
  24. });
  25. const dispatch = useCallback((action) => {
  26. if ('type' in action) {
  27. switch (action.type) {
  28. case 'TOGGLE_SIDER':
  29. setState((prev) => ({
  30. ...prev,
  31. showSider: !prev.showSider,
  32. manualSiderControl: true
  33. }));
  34. break;
  35. case 'SET_SIDER':
  36. setState((prev) => ({
  37. ...prev,
  38. showSider: action.payload,
  39. manualSiderControl: action.manual || false
  40. }));
  41. break;
  42. case 'SET_MOBILE':
  43. setState((prev) => ({ ...prev, isMobile: action.payload }));
  44. break;
  45. case 'SET_SIDER_COLLAPSED':
  46. setState((prev) => ({ ...prev, siderCollapsed: action.payload }));
  47. break;
  48. case 'SET_INNER_PADDING':
  49. setState((prev) => ({ ...prev, shouldInnerPadding: action.payload }));
  50. break;
  51. default:
  52. setState((prev) => ({ ...prev, ...action }));
  53. }
  54. } else {
  55. setState((prev) => ({ ...prev, ...action }));
  56. }
  57. }, []);
  58. useEffect(() => {
  59. const updateMobileStatus = () => {
  60. const currentIsMobile = getIsMobile();
  61. if (!currentIsMobile &&
  62. (location.pathname === '/console' || location.pathname.startsWith('/console/'))) {
  63. dispatch({ type: 'SET_SIDER', payload: true, manual: false });
  64. }
  65. dispatch({ type: 'SET_MOBILE', payload: currentIsMobile });
  66. };
  67. window.addEventListener('resize', updateMobileStatus);
  68. return () => window.removeEventListener('resize', updateMobileStatus);
  69. }, [dispatch, location.pathname]);
  70. useEffect(() => {
  71. if (state.isMobile && state.showSider && !state.manualSiderControl) {
  72. dispatch({ type: 'SET_SIDER', payload: false });
  73. }
  74. }, [state.isMobile, state.showSider, state.manualSiderControl, dispatch]);
  75. useEffect(() => {
  76. const currentPathname = location.pathname;
  77. const currentlyMobile = getIsMobile();
  78. if (currentPathname === '/console' || currentPathname.startsWith('/console/')) {
  79. dispatch({
  80. type: 'SET_SIDER',
  81. payload: !currentlyMobile,
  82. manual: false
  83. });
  84. dispatch({ type: 'SET_INNER_PADDING', payload: true });
  85. } else {
  86. dispatch({
  87. type: 'SET_SIDER',
  88. payload: false,
  89. manual: false
  90. });
  91. dispatch({ type: 'SET_INNER_PADDING', payload: false });
  92. }
  93. }, [location.pathname, dispatch]);
  94. useEffect(() => {
  95. const isCollapsed =
  96. localStorage.getItem('default_collapse_sidebar') === 'true';
  97. dispatch({ type: 'SET_SIDER_COLLAPSED', payload: isCollapsed });
  98. }, [dispatch]);
  99. return (
  100. <StyleContext.Provider value={[state, dispatch]}>
  101. {children}
  102. </StyleContext.Provider>
  103. );
  104. };