From 0acb04bdef77e2be60d0a7d4db521c03448f81d9 Mon Sep 17 00:00:00 2001 From: wadackel Date: Sun, 28 Apr 2024 11:49:06 +0900 Subject: [PATCH] refactor: migrate to jotai from unstated-next --- package.json | 3 +- src/App/App.tsx | 90 +++----- src/App/index.tsx | 38 +--- src/components/ChoiceGroup/ChoiceGroup.tsx | 52 ++--- src/components/Dialog/Dialog.css.ts | 1 + src/components/Dialog/Dialog.tsx | 23 +- src/components/Header/Header.tsx | 11 +- src/components/Main/Main.tsx | 23 +- src/components/Notification/index.tsx | 6 +- src/components/Sidebar/Sidebar.tsx | 25 ++- .../Sidebar/internal/Desktop/Desktop.tsx | 8 +- .../Sidebar/internal/Mobile/Mobile.tsx | 37 ++-- .../internal/SidebarInner/SidebarInner.tsx | 55 +++-- src/components/Viewer/Viewer.tsx | 209 ++++++++---------- src/components/Viewer/index.tsx | 141 ++++++++++-- src/containers/entity/EntityContainer.ts | 103 --------- .../notification/NotificationContainer.ts | 30 --- src/containers/sidebar/SidebarContainer.ts | 69 ------ src/containers/viewer/ViewerContainer.ts | 146 ------------ src/hooks/useKey.ts | 27 +++ src/hooks/useMousetrap.ts | 35 --- src/hooks/usePrevious.ts | 11 + src/index.tsx | 22 +- src/states/entity.ts | 110 +++++++++ src/states/notification.ts | 50 +++++ src/states/sidebar.ts | 75 +++++++ src/states/worker.ts | 17 ++ src/types/store.ts | 3 + yarn.lock | 15 +- 29 files changed, 704 insertions(+), 731 deletions(-) delete mode 100644 src/containers/entity/EntityContainer.ts delete mode 100644 src/containers/notification/NotificationContainer.ts delete mode 100644 src/containers/sidebar/SidebarContainer.ts delete mode 100644 src/containers/viewer/ViewerContainer.ts create mode 100644 src/hooks/useKey.ts delete mode 100644 src/hooks/useMousetrap.ts create mode 100644 src/hooks/usePrevious.ts create mode 100644 src/states/entity.ts create mode 100644 src/states/notification.ts create mode 100644 src/states/sidebar.ts create mode 100644 src/states/worker.ts create mode 100644 src/types/store.ts diff --git a/package.json b/package.json index 8739f81..efe277d 100644 --- a/package.json +++ b/package.json @@ -55,9 +55,9 @@ "focus-trap": "^7.5.4", "fuse.js": "^7.0.0", "history": "^5.3.0", + "jotai": "^2.8.0", "keycode": "^2.2.0", "mitt": "^3.0.1", - "mousetrap": "^1.6.5", "query-string": "^7.0.1", "rc-slider": "^10.5.0", "re-resizable": "^6.9.11", @@ -65,6 +65,7 @@ "react-dom": "18.2.0", "react-md-spinner": "^1.0.0", "react-transition-group": "^4.4.5", + "tinykeys": "^2.1.0", "unstated-next": "^1.1.0", "use-intersection": "^0.2.1", "x-img-diff-js": "^0.3.5" diff --git a/src/App/App.tsx b/src/App/App.tsx index 8312020..86f3509 100644 --- a/src/App/App.tsx +++ b/src/App/App.tsx @@ -8,20 +8,19 @@ import { Notification } from '../components/Notification'; import { Sidebar } from '../components/Sidebar'; import { Viewer } from '../components/Viewer'; import { HelpIcon } from '../components/icons/HelpIcon'; -import { EntityContainer } from '../containers/entity/EntityContainer'; -import { SidebarContainer } from '../containers/sidebar/SidebarContainer'; -import { useMousetrap } from '../hooks/useMousetrap'; -import { findFirstFocusable } from '../utils/selector'; +import { useKey } from '../hooks/useKey'; +import { useEntities } from '../states/entity'; +import { useSidebarMutators } from '../states/sidebar'; import { Color } from '../styles/variables.css'; +import { findFirstFocusable } from '../utils/selector'; import * as styles from './App.css'; export type Props = {}; export const App = () => { - const sidebar = SidebarContainer.useContainer(); + const { toggle: toggleSidebar } = useSidebarMutators(); - const { newItems, failedItems, deletedItems, passedItems } = - EntityContainer.useContainer(); + const { newItems, failedItems, deletedItems, passedItems } = useEntities(); const [helpDialogOpen, setHelpDialogOpen] = useState(false); @@ -37,7 +36,7 @@ export const App = () => { setHelpDialogOpen(false); }, []); - useMousetrap(['/', 's'], null, (e) => { + useKey(null, ['/', 's'], (e) => { e.preventDefault(); if (filterRef.current != null) { @@ -45,7 +44,7 @@ export const App = () => { } }); - useMousetrap('g s', null, () => { + useKey(null, ['g s'], () => { const { current: list } = listRef; if (list == null) { return; @@ -59,60 +58,35 @@ export const App = () => { first.focus(); }); - useMousetrap( - 'g c', - null, - () => { - if (failedItems.length > 0) { - window.location.hash = 'changed'; - } - }, - [failedItems], - ); + useKey(null, ['g c'], () => { + if (failedItems.length > 0) { + window.location.hash = 'changed'; + } + }); - useMousetrap( - 'g n', - null, - () => { - if (newItems.length > 0) { - window.location.hash = 'new'; - } - }, - [newItems], - ); + useKey(null, ['g n'], () => { + if (newItems.length > 0) { + window.location.hash = 'new'; + } + }); - useMousetrap( - 'g d', - null, - () => { - if (deletedItems.length > 0) { - window.location.hash = 'deleted'; - } - }, - [deletedItems], - ); + useKey(null, ['g d'], () => { + if (deletedItems.length > 0) { + window.location.hash = 'deleted'; + } + }); - useMousetrap( - 'g p', - null, - () => { - if (passedItems.length > 0) { - window.location.hash = 'passed'; - } - }, - [passedItems], - ); + useKey(null, ['g p'], () => { + if (passedItems.length > 0) { + window.location.hash = 'passed'; + } + }); - useMousetrap( - 'f', - null, - () => { - sidebar.toggle(); - }, - [sidebar], - ); + useKey(null, ['f'], () => { + toggleSidebar(); + }); - useMousetrap('?', null, () => { + useKey(null, ['Shift+?'], () => { setHelpDialogOpen(true); }); diff --git a/src/App/index.tsx b/src/App/index.tsx index d24559f..d3b012d 100644 --- a/src/App/index.tsx +++ b/src/App/index.tsx @@ -1,34 +1,20 @@ +import { Provider } from 'jotai'; import React from 'react'; -import type { RegData } from '../types/reg'; -import { EntityContainer } from '../containers/entity/EntityContainer'; -import { ViewerContainer } from '../containers/viewer/ViewerContainer'; -import { NotificationContainer } from '../containers/notification/NotificationContainer'; -import { HistoryContextProvider } from '../context/HistoryContext'; import { AnchorScrollProvider } from '../context/AnchorScrollContext'; -import type { WorkerClient } from '../worker-client'; -import { WorkerContext } from '../context/WorkerContext'; -import { SidebarContainer } from '../containers/sidebar/SidebarContainer'; +import { HistoryContextProvider } from '../context/HistoryContext'; +import type { Store } from '../types/store'; import { App as Component } from './App'; export type Props = { - data: RegData; - worker: WorkerClient; + store: Store; }; -export const App = ({ data, worker }: Props) => ( - - - - - - - - - - - - - - - +export const App = ({ store }: Props) => ( + + + + + + + ); diff --git a/src/components/ChoiceGroup/ChoiceGroup.tsx b/src/components/ChoiceGroup/ChoiceGroup.tsx index cb12eec..3060737 100644 --- a/src/components/ChoiceGroup/ChoiceGroup.tsx +++ b/src/components/ChoiceGroup/ChoiceGroup.tsx @@ -5,7 +5,7 @@ import React, { useMemo, useRef, } from 'react'; -import { useMousetrap } from '../../hooks/useMousetrap'; +import { useKey } from '../../hooks/useKey'; import type { Modify } from '../../utils/types'; import * as styles from './ChoiceGroup.css'; import { ChoiceButton } from './internal/ChoiceButton'; @@ -64,41 +64,31 @@ export const ChoiceGroup = ({ value, options, onChange, ...rest }: Props) => { changedByKey.current = false; }, [buttonRefList, options, value]); - useMousetrap( - ['right', 'l'], - rootRef.current, - (e) => { - e.stopPropagation(); + useKey(rootRef, ['right', 'l'], (e) => { + e.stopPropagation(); - const current = getValueIndex(options, value); - const next = current + 1; - if (next >= options.length) { - return; - } + const current = getValueIndex(options, value); + const next = current + 1; + if (next >= options.length) { + return; + } - changedByKey.current = true; - onChange(options[next].value, next); - }, - [options, value, onChange], - ); + changedByKey.current = true; + onChange(options[next].value, next); + }); - useMousetrap( - ['left', 'h'], - rootRef.current, - (e) => { - e.stopPropagation(); + useKey(rootRef, ['left', 'h'], (e) => { + e.stopPropagation(); - const current = getValueIndex(options, value); - const previous = current - 1; - if (previous < 0) { - return; - } + const current = getValueIndex(options, value); + const previous = current - 1; + if (previous < 0) { + return; + } - changedByKey.current = true; - onChange(options[previous].value, previous); - }, - [options, value, onChange], - ); + changedByKey.current = true; + onChange(options[previous].value, previous); + }); return (