aboutsummaryrefslogtreecommitdiff
path: root/src/console/app
diff options
context:
space:
mode:
authorShin'ya Ueoka <ueokande@i-beam.org>2021-04-11 22:30:41 +0900
committerShin'ya Ueoka <ueokande@i-beam.org>2021-04-11 22:34:55 +0900
commit8a5bba1da639355a25da8c279a9f1cf0a7300a9f (patch)
tree2f82e9184e2a249cff4a607764f88b724fae1013 /src/console/app
parent6767b38c8e57c9f436936dc02ad1c8c4ffd043b2 (diff)
Replace app state with Custom Hooks
Diffstat (limited to 'src/console/app')
-rw-r--r--src/console/app/actions.ts82
-rw-r--r--src/console/app/contexts.ts9
-rw-r--r--src/console/app/hooks.ts115
-rw-r--r--src/console/app/provider.tsx14
-rw-r--r--src/console/app/recuer.ts52
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;
+ }
+}