diff options
author | Shin'ya Ueoka <ueokande@i-beam.org> | 2021-04-11 22:30:41 +0900 |
---|---|---|
committer | Shin'ya Ueoka <ueokande@i-beam.org> | 2021-04-11 22:34:55 +0900 |
commit | 8a5bba1da639355a25da8c279a9f1cf0a7300a9f (patch) | |
tree | 2f82e9184e2a249cff4a607764f88b724fae1013 /src/console/app | |
parent | 6767b38c8e57c9f436936dc02ad1c8c4ffd043b2 (diff) |
Replace app state with Custom Hooks
Diffstat (limited to 'src/console/app')
-rw-r--r-- | src/console/app/actions.ts | 82 | ||||
-rw-r--r-- | src/console/app/contexts.ts | 9 | ||||
-rw-r--r-- | src/console/app/hooks.ts | 115 | ||||
-rw-r--r-- | src/console/app/provider.tsx | 14 | ||||
-rw-r--r-- | src/console/app/recuer.ts | 52 |
5 files changed, 272 insertions, 0 deletions
diff --git a/src/console/app/actions.ts b/src/console/app/actions.ts new file mode 100644 index 0000000..5538ae5 --- /dev/null +++ b/src/console/app/actions.ts @@ -0,0 +1,82 @@ +export const SHOW_COMMAND = "show.command"; +export const SHOW_ERROR = "show.error"; +export const SHOW_INFO = "show.info"; +export const HIDE_COMMAND = "hide.command"; +export const SHOW_FIND = "show.find"; +export const HIDE = "hide"; + +export interface HideAction { + type: typeof HIDE; +} + +export interface ShowCommand { + type: typeof SHOW_COMMAND; + text: string; +} + +export interface ShowFindAction { + type: typeof SHOW_FIND; +} + +export interface ShowErrorAction { + type: typeof SHOW_ERROR; + text: string; +} + +export interface ShowInfoAction { + type: typeof SHOW_INFO; + text: string; +} + +export interface HideCommandAction { + type: typeof HIDE_COMMAND; +} + +export type AppAction = + | HideAction + | ShowCommand + | ShowFindAction + | ShowErrorAction + | ShowInfoAction + | HideCommandAction; + +const hide = (): HideAction => { + return { + type: HIDE, + }; +}; + +const showCommand = (text: string): ShowCommand => { + return { + type: SHOW_COMMAND, + text, + }; +}; + +const showFind = (): ShowFindAction => { + return { + type: SHOW_FIND, + }; +}; + +const showError = (text: string): ShowErrorAction => { + return { + type: SHOW_ERROR, + text: text, + }; +}; + +const showInfo = (text: string): ShowInfoAction => { + return { + type: SHOW_INFO, + text: text, + }; +}; + +const hideCommand = (): HideCommandAction => { + return { + type: HIDE_COMMAND, + }; +}; + +export { hide, showCommand, showFind, showError, showInfo, hideCommand }; diff --git a/src/console/app/contexts.ts b/src/console/app/contexts.ts new file mode 100644 index 0000000..7e4f323 --- /dev/null +++ b/src/console/app/contexts.ts @@ -0,0 +1,9 @@ +import React from "react"; +import { State, defaultState } from "./recuer"; +import { AppAction } from "./actions"; + +export const AppStateContext = React.createContext<State>(defaultState); + +export const AppDispatchContext = React.createContext< + (action: AppAction) => void +>(() => {}); diff --git a/src/console/app/hooks.ts b/src/console/app/hooks.ts new file mode 100644 index 0000000..eefdea3 --- /dev/null +++ b/src/console/app/hooks.ts @@ -0,0 +1,115 @@ +import React from "react"; +import * as actions from "./actions"; +import { AppDispatchContext, AppStateContext } from "./contexts"; +import * as messages from "../../shared/messages"; + +export const useHide = () => { + const dispatch = React.useContext(AppDispatchContext); + const hide = React.useCallback(() => { + window.top.postMessage( + JSON.stringify({ + type: messages.CONSOLE_UNFOCUS, + }), + "*" + ); + dispatch(actions.hide()); + }, [dispatch]); + + return hide; +}; + +export const useCommandMode = () => { + const state = React.useContext(AppStateContext); + const dispatch = React.useContext(AppDispatchContext); + + const show = React.useCallback( + (initialInputValue: string) => { + dispatch(actions.showCommand(initialInputValue)); + }, + [dispatch] + ); + + return { + visible: state.mode === "command", + initialInputValue: state.consoleText, + show, + }; +}; + +export const useFindMode = () => { + const state = React.useContext(AppStateContext); + const dispatch = React.useContext(AppDispatchContext); + + const show = React.useCallback(() => { + dispatch(actions.showFind()); + }, [dispatch]); + + return { + visible: state.mode === "find", + show, + }; +}; + +export const useInfoMessage = () => { + const state = React.useContext(AppStateContext); + const dispatch = React.useContext(AppDispatchContext); + + const show = React.useCallback( + (message: string) => { + dispatch(actions.showInfo(message)); + }, + [dispatch] + ); + + return { + visible: state.mode === "info", + message: state.mode === "info" ? state.messageText : "", + show, + }; +}; + +export const useErrorMessage = () => { + const state = React.useContext(AppStateContext); + const dispatch = React.useContext(AppDispatchContext); + + const show = React.useCallback( + (message: string) => { + dispatch(actions.showError(message)); + }, + [dispatch] + ); + + return { + visible: state.mode === "error", + message: state.mode === "error" ? state.messageText : "", + show, + }; +}; + +export const getInitialInputValue = () => { + const state = React.useContext(AppStateContext); + return state.consoleText; +}; + +export const useExecCommand = () => { + const execCommand = React.useCallback((text: string) => { + browser.runtime.sendMessage({ + type: messages.CONSOLE_ENTER_COMMAND, + text, + }); + }, []); + return execCommand; +}; + +export const useExecFind = () => { + const execFind = React.useCallback((text?: string) => { + window.top.postMessage( + JSON.stringify({ + type: messages.CONSOLE_ENTER_FIND, + text, + }), + "*" + ); + }, []); + return execFind; +}; diff --git a/src/console/app/provider.tsx b/src/console/app/provider.tsx new file mode 100644 index 0000000..397f165 --- /dev/null +++ b/src/console/app/provider.tsx @@ -0,0 +1,14 @@ +import React from "react"; +import reducer, { defaultState } from "./recuer"; +import { AppDispatchContext, AppStateContext } from "./contexts"; + +export const AppProvider: React.FC = ({ children }) => { + const [state, dispatch] = React.useReducer(reducer, defaultState); + return ( + <AppStateContext.Provider value={state}> + <AppDispatchContext.Provider value={dispatch}> + {children} + </AppDispatchContext.Provider> + </AppStateContext.Provider> + ); +}; diff --git a/src/console/app/recuer.ts b/src/console/app/recuer.ts new file mode 100644 index 0000000..e3043ee --- /dev/null +++ b/src/console/app/recuer.ts @@ -0,0 +1,52 @@ +import { + HIDE, + HIDE_COMMAND, + SHOW_COMMAND, + SHOW_ERROR, + SHOW_FIND, + SHOW_INFO, + AppAction, +} from "./actions"; + +export interface State { + mode: string; + messageText: string; + consoleText: string; +} + +export const defaultState = { + mode: "", + messageText: "", + consoleText: "", +}; + +// eslint-disable-next-line max-lines-per-function +export default function reducer( + state: State = defaultState, + action: AppAction +): State { + switch (action.type) { + case HIDE: + return { ...state, mode: "" }; + case SHOW_COMMAND: + return { + ...state, + mode: "command", + consoleText: action.text, + }; + case SHOW_FIND: + return { ...state, mode: "find", consoleText: "" }; + case SHOW_ERROR: + return { ...state, mode: "error", messageText: action.text }; + case SHOW_INFO: + return { ...state, mode: "info", messageText: action.text }; + case HIDE_COMMAND: + return { + ...state, + mode: + state.mode === "command" || state.mode === "find" ? "" : state.mode, + }; + default: + return state; + } +} |