Skip to content

Commit

Permalink
Added AppRoot component
Browse files Browse the repository at this point in the history
  • Loading branch information
viktor-podzigun committed Oct 24, 2023
1 parent 9cb37dd commit b066449
Show file tree
Hide file tree
Showing 5 changed files with 424 additions and 1 deletion.
16 changes: 16 additions & 0 deletions src/app/AppRoot.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from "react";
import { ThemeType } from "../theme/Theme";
import { DevToolType } from "../tool/DevTool.mjs";

export type MainUi = React.FC | React.ComponentClass<{}>;

export interface LoadResult {
readonly theme: ThemeType;
readonly mainUi: MainUi;
}

export interface AppRootProps {
readonly loadMainUi: (dispatch: (a: any) => void) => Promise<LoadResult>;
readonly initialDevTool: DevToolType;
readonly defaultTheme: ThemeType;
}
108 changes: 108 additions & 0 deletions src/app/AppRoot.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/**
* @typedef {import("./AppRoot").MainUi} MainUi
* @typedef {import("./AppRoot").LoadResult} LoadResult
* @typedef {import("./AppRoot").AppRootProps} AppRootProps
* @typedef {import("../theme/Theme").ThemeType} ThemeType
* @typedef {import("@farjs/blessed").Widgets.BlessedElement} BlessedElement
* @typedef {import("@farjs/blessed").Widgets.Events.IKeyEventArg & {
* defaultPrevented?: boolean
* }} IKeyEventArg
*/
import React, { useLayoutEffect, useReducer, useRef, useState } from "react";
import Theme from "../theme/Theme.mjs";
import DevTool from "../tool/DevTool.mjs";
import DevToolPanel from "../tool/DevToolPanel.mjs";
import LogController from "../tool/LogController.mjs";
import TaskReducer from "../task/TaskReducer.mjs";
import TaskManager from "../task/TaskManager.mjs";

const h = React.createElement;

/**
* @param {AppRootProps} props
*/
const AppRoot = (props) => {
const { taskControllerComp, logControllerComp, devToolPanelComp } = AppRoot;

/** @type {[MainUi | undefined, React.Dispatch<React.SetStateAction<MainUi | undefined>>]} */
const [mainUi, setMainUi] = useState();
const elementRef = /** @type {React.MutableRefObject<BlessedElement>} */ (
useRef()
);
const [devTool, setDevTool] = useState(props.initialDevTool);
const [currTheme, setCurrTheme] = useState(props.defaultTheme);
const [state, dispatch] = useReducer(TaskReducer, undefined);

useLayoutEffect(() => {
const screen = elementRef.current.screen;
/** @type {(ch: any, key: IKeyEventArg) => void} */
const keyListener = (_, key) => {
if (key.full === "f12") {
setDevTool((from) => {
const to = DevTool.getNext(from);
if (DevTool.shouldResize(from, to)) {
//exec on the next tick
Promise.resolve().then(() => {
screen.program.emit("resize");
});
}
return to;
});
}
};
screen.on("keypress", keyListener);

return () => {
screen.off("keypress", keyListener);
};
}, []);

return h(
Theme.Context.Provider,
{ value: currTheme },
h(
"box",
{
ref: elementRef,
width: devTool === DevTool.Hidden ? "100%" : "70%",
},
mainUi
? h(mainUi, null, h(taskControllerComp, { startTask: state }))
: h("text", null, "Loading...")
),

h(logControllerComp, {
onReady: () => {
props
.loadMainUi(dispatch)
.then((loadRes) => {
setCurrTheme(loadRes.theme);
setMainUi(() => loadRes.mainUi);
})
.catch((error) => {
console.error(error);
});
},
render: (content) => {
return devTool !== DevTool.Hidden
? h(
"box",
{ width: "30%", height: "100%", left: "70%" },
h(devToolPanelComp, {
devTool,
logContent: content,
onActivate: setDevTool,
})
)
: null;
},
})
);
};

AppRoot.displayName = "AppRoot";
AppRoot.taskControllerComp = TaskManager;
AppRoot.logControllerComp = LogController;
AppRoot.devToolPanelComp = DevToolPanel;

export default AppRoot;
2 changes: 1 addition & 1 deletion src/tool/LogController.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ import React from "react";

export interface LogControllerProps {
onReady(): void;
render(content: string): React.ReactElement;
render(content: string): React.ReactElement | null;
}
2 changes: 2 additions & 0 deletions test/all.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ await import("./ButtonsPanel.test.mjs");
await import("./TextLine.test.mjs");
await import("./UI.test.mjs");

await import("./app/AppRoot.test.mjs");

await import("./border/DoubleBorder.test.mjs");
await import("./border/HorizontalLine.test.mjs");
await import("./border/SingleBorder.test.mjs");
Expand Down
Loading

0 comments on commit b066449

Please sign in to comment.