From de4e651196502cffa56cedfdaf84d9bb665559e1 Mon Sep 17 00:00:00 2001
From: Shin'ya Ueoka <ueokande@i-beam.org>
Date: Sun, 4 Apr 2021 11:01:40 +0900
Subject: Replace Console component with a React Hooks

---
 src/console/index.tsx | 79 +++++++++++++++++++++++++++++++--------------------
 1 file changed, 48 insertions(+), 31 deletions(-)

(limited to 'src/console/index.tsx')

diff --git a/src/console/index.tsx b/src/console/index.tsx
index f9313a0..cf9367b 100644
--- a/src/console/index.tsx
+++ b/src/console/index.tsx
@@ -1,42 +1,59 @@
 import * as messages from "../shared/messages";
-import reducers from "./reducers";
-import { createStore, applyMiddleware } from "redux";
-import promise from "redux-promise";
+import reducers, { defaultState } from "./reducers";
 import * as consoleActions from "./actions/console";
-import { Provider } from "react-redux";
 import Console from "./components/Console";
+import AppContext from "./components/AppContext";
 import "./index.css";
 import React from "react";
 import ReactDOM from "react-dom";
 
-const store = createStore(reducers, applyMiddleware(promise));
+const wrapAsync = <T extends unknown>(
+  dispatch: React.Dispatch<T>
+): React.Dispatch<T | Promise<T>> => {
+  return (action: T | Promise<T>) => {
+    if (action instanceof Promise) {
+      action.then((a) => dispatch(a)).catch(console.error);
+    } else {
+      dispatch(action);
+    }
+  };
+};
 
-window.addEventListener("DOMContentLoaded", () => {
-  const wrapper = document.getElementById("vimvixen-console");
-  ReactDOM.render(
-    <Provider store={store}>
-      <Console></Console>
-    </Provider>,
-    wrapper
-  );
-});
+const RootComponent: React.FC = () => {
+  const [state, dispatch] = React.useReducer(reducers, defaultState);
+
+  React.useEffect(() => {
+    const onMessage = async (message: any): Promise<any> => {
+      const msg = messages.valueOf(message);
+      switch (msg.type) {
+        case messages.CONSOLE_SHOW_COMMAND:
+          return dispatch(await consoleActions.showCommand(msg.command));
+        case messages.CONSOLE_SHOW_FIND:
+          return dispatch(consoleActions.showFind());
+        case messages.CONSOLE_SHOW_ERROR:
+          return dispatch(consoleActions.showError(msg.text));
+        case messages.CONSOLE_SHOW_INFO:
+          return dispatch(consoleActions.showInfo(msg.text));
+        case messages.CONSOLE_HIDE:
+          return dispatch(consoleActions.hide());
+      }
+    };
 
-const onMessage = async (message: any): Promise<any> => {
-  const msg = messages.valueOf(message);
-  switch (msg.type) {
-    case messages.CONSOLE_SHOW_COMMAND:
-      return store.dispatch(await consoleActions.showCommand(msg.command));
-    case messages.CONSOLE_SHOW_FIND:
-      return store.dispatch(consoleActions.showFind());
-    case messages.CONSOLE_SHOW_ERROR:
-      return store.dispatch(consoleActions.showError(msg.text));
-    case messages.CONSOLE_SHOW_INFO:
-      return store.dispatch(consoleActions.showInfo(msg.text));
-    case messages.CONSOLE_HIDE:
-      return store.dispatch(consoleActions.hide());
-  }
+    browser.runtime.onMessage.addListener(onMessage);
+    const port = browser.runtime.connect(undefined, {
+      name: "vimvixen-console",
+    });
+    port.onMessage.addListener(onMessage);
+  }, []);
+
+  return (
+    <AppContext.Provider value={{ state, dispatch: wrapAsync(dispatch) }}>
+      <Console />
+    </AppContext.Provider>
+  );
 };
 
-browser.runtime.onMessage.addListener(onMessage);
-const port = browser.runtime.connect(undefined, { name: "vimvixen-console" });
-port.onMessage.addListener(onMessage);
+window.addEventListener("DOMContentLoaded", () => {
+  const wrapper = document.getElementById("vimvixen-console");
+  ReactDOM.render(<RootComponent />, wrapper);
+});
-- 
cgit v1.2.3

