config.tsx 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. import React from "react";
  2. import { defaultConfig, defaultJson } from "src/constants/data";
  3. import {
  4. ConfigActionType,
  5. ReducerAction,
  6. useConfigReducer,
  7. } from "src/reducer/reducer";
  8. import { ReactComponent, StorageConfig } from "src/typings/global";
  9. import { isValidJson } from "src/utils/isValidJson";
  10. import { useRouter } from "next/router";
  11. import { decode } from "js-base64";
  12. export interface AppConfig {
  13. json: string;
  14. settings: StorageConfig;
  15. }
  16. export const initialStates: AppConfig = {
  17. json: JSON.stringify(defaultJson),
  18. settings: defaultConfig,
  19. };
  20. interface Config {
  21. json: string;
  22. settings: StorageConfig;
  23. dispatch: React.Dispatch<ReducerAction>;
  24. }
  25. const defaultContext: Config = {
  26. ...initialStates,
  27. dispatch: () => {},
  28. };
  29. const ConfigContext: React.Context<Config> =
  30. React.createContext(defaultContext);
  31. const useConfig = () => React.useContext(ConfigContext);
  32. const WithConfig: ReactComponent = ({ children }) => {
  33. const [render, setRender] = React.useState(false);
  34. const [states, dispatch] = React.useReducer(useConfigReducer, initialStates);
  35. const value = {
  36. dispatch,
  37. json: states.json,
  38. settings: states.settings,
  39. };
  40. const router = useRouter();
  41. const { json } = router.query;
  42. React.useEffect(() => {
  43. const jsonStored = localStorage.getItem("json");
  44. const jsonDecode = decode(String(json));
  45. if (isValidJson(jsonDecode)) {
  46. dispatch({ type: ConfigActionType.SET_JSON, payload: jsonDecode });
  47. } else if (jsonStored) {
  48. dispatch({ type: ConfigActionType.SET_JSON, payload: jsonStored });
  49. }
  50. const configStored = localStorage.getItem("config");
  51. if (configStored) {
  52. dispatch({
  53. type: ConfigActionType.SET_CONFIG,
  54. payload: JSON.parse(configStored),
  55. });
  56. }
  57. setRender(true);
  58. }, [dispatch, json]);
  59. React.useEffect(() => {
  60. if (render)
  61. localStorage.setItem(
  62. "config",
  63. JSON.stringify({
  64. ...states.settings,
  65. zoomPanPinch: undefined,
  66. performance: undefined,
  67. })
  68. );
  69. }, [states.settings, render]);
  70. return (
  71. <ConfigContext.Provider value={value}>{children}</ConfigContext.Provider>
  72. );
  73. };
  74. const withConfig = <P extends object>(
  75. Component: React.ComponentType<P>
  76. ): React.FC => {
  77. return (props) => (
  78. <WithConfig>
  79. <Component {...(props as P)} />
  80. </WithConfig>
  81. );
  82. };
  83. export { WithConfig, useConfig, ConfigContext, withConfig };