This commit is contained in:
Mike Sawka 2024-10-25 18:36:09 -07:00 committed by GitHub
parent da57427e8c
commit a782d83628
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 85 additions and 40 deletions

View File

@ -1,7 +1,14 @@
// Copyright 2024, Command Line Inc. // Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
import { BlockComponentModel2, BlockProps } from "@/app/block/blocktypes"; import {
BlockComponentModel2,
BlockNodeModel,
BlockProps,
FullBlockProps,
FullSubBlockProps,
SubBlockProps,
} from "@/app/block/blocktypes";
import { PlotView } from "@/app/view/plotview/plotview"; import { PlotView } from "@/app/view/plotview/plotview";
import { PreviewModel, PreviewView, makePreviewModel } from "@/app/view/preview/preview"; import { PreviewModel, PreviewView, makePreviewModel } from "@/app/view/preview/preview";
import { SysinfoView, SysinfoViewModel, makeSysinfoViewModel } from "@/app/view/sysinfo/sysinfo"; import { SysinfoView, SysinfoViewModel, makeSysinfoViewModel } from "@/app/view/sysinfo/sysinfo";
@ -9,7 +16,7 @@ import { VDomView, makeVDomModel } from "@/app/view/vdom/vdom";
import { VDomModel } from "@/app/view/vdom/vdom-model"; import { VDomModel } from "@/app/view/vdom/vdom-model";
import { ErrorBoundary } from "@/element/errorboundary"; import { ErrorBoundary } from "@/element/errorboundary";
import { CenteredDiv } from "@/element/quickelems"; import { CenteredDiv } from "@/element/quickelems";
import { NodeModel, useDebouncedNodeInnerRect } from "@/layout/index"; import { useDebouncedNodeInnerRect } from "@/layout/index";
import { import {
counterInc, counterInc,
getBlockComponentModel, getBlockComponentModel,
@ -30,14 +37,7 @@ import "./block.less";
import { BlockFrame } from "./blockframe"; import { BlockFrame } from "./blockframe";
import { blockViewToIcon, blockViewToName } from "./blockutil"; import { blockViewToIcon, blockViewToName } from "./blockutil";
type FullBlockProps = { function makeViewModel(blockId: string, blockView: string, nodeModel: BlockNodeModel): ViewModel {
isSubBlock?: boolean;
preview: boolean;
nodeModel: NodeModel;
viewModel: ViewModel;
};
function makeViewModel(blockId: string, blockView: string, nodeModel: NodeModel): ViewModel {
if (blockView === "term") { if (blockView === "term") {
return makeTerminalModel(blockId, nodeModel); return makeTerminalModel(blockId, nodeModel);
} }
@ -146,7 +146,7 @@ const BlockPreview = memo(({ nodeModel, viewModel }: FullBlockProps) => {
); );
}); });
const BlockSubBlock = memo(({ nodeModel, viewModel }: FullBlockProps) => { const BlockSubBlock = memo(({ nodeModel, viewModel }: FullSubBlockProps) => {
const [blockData] = useWaveObjectValue<Block>(makeORef("block", nodeModel.blockId)); const [blockData] = useWaveObjectValue<Block>(makeORef("block", nodeModel.blockId));
const blockRef = useRef<HTMLDivElement>(null); const blockRef = useRef<HTMLDivElement>(null);
const contentRef = useRef<HTMLDivElement>(null); const contentRef = useRef<HTMLDivElement>(null);
@ -304,10 +304,29 @@ const Block = memo((props: BlockProps) => {
if (props.preview) { if (props.preview) {
return <BlockPreview {...props} viewModel={viewModel} />; return <BlockPreview {...props} viewModel={viewModel} />;
} }
if (props.isSubBlock) {
return <BlockSubBlock {...props} viewModel={viewModel} />;
}
return <BlockFull {...props} viewModel={viewModel} />; return <BlockFull {...props} viewModel={viewModel} />;
}); });
export { Block }; const SubBlock = memo((props: SubBlockProps) => {
counterInc("render-Block");
counterInc("render-Block-" + props.nodeModel?.blockId?.substring(0, 8));
const [blockData, loading] = useWaveObjectValue<Block>(makeORef("block", props.nodeModel.blockId));
const bcm = getBlockComponentModel(props.nodeModel.blockId);
let viewModel = bcm?.viewModel;
if (viewModel == null || viewModel.viewType != blockData?.meta?.view) {
viewModel = makeViewModel(props.nodeModel.blockId, blockData?.meta?.view, props.nodeModel);
registerBlockComponentModel(props.nodeModel.blockId, { viewModel });
}
useEffect(() => {
return () => {
unregisterBlockComponentModel(props.nodeModel.blockId);
viewModel?.dispose?.();
};
}, []);
if (loading || isBlank(props.nodeModel.blockId) || blockData == null) {
return null;
}
return <BlockSubBlock {...props} viewModel={viewModel} />;
});
export { Block, SubBlock };

View File

@ -2,10 +2,33 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
import { NodeModel } from "@/layout/index"; import { NodeModel } from "@/layout/index";
export interface BlockProps { import { Atom } from "jotai";
isSubBlock?: boolean;
export interface BlockNodeModel {
blockId: string;
isFocused: Atom<boolean>;
onClose: () => void;
focusNode: () => void;
}
export type FullBlockProps = {
preview: boolean; preview: boolean;
nodeModel: NodeModel; nodeModel: NodeModel;
viewModel: ViewModel;
};
export interface BlockProps {
preview: boolean;
nodeModel: NodeModel;
}
export type FullSubBlockProps = {
nodeModel: BlockNodeModel;
viewModel: ViewModel;
};
export interface SubBlockProps {
nodeModel: BlockNodeModel;
} }
export interface BlockComponentModel2 { export interface BlockComponentModel2 {

View File

@ -54,7 +54,7 @@
font: var(--fixed-font); font: var(--fixed-font);
font-size: 0.85em; font-size: 0.85em;
color: var(--keybinding-color); color: var(--keybinding-color);
background-color: var(--keybinding-bg-color); background-color: var(--highlight-bg-color);
border-radius: 4px; border-radius: 4px;
border: 1px solid var(--keybinding-border-color); border: 1px solid var(--keybinding-border-color);
box-shadow: none; box-shadow: none;

View File

@ -1,16 +1,16 @@
// Copyright 2024, Command Line Inc. // Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
import { BlockNodeModel } from "@/app/block/blocktypes";
import { getApi } from "@/app/store/global"; import { getApi } from "@/app/store/global";
import { WebView, WebViewModel } from "@/app/view/webview/webview"; import { WebView, WebViewModel } from "@/app/view/webview/webview";
import { NodeModel } from "@/layout/index";
import { fireAndForget } from "@/util/util"; import { fireAndForget } from "@/util/util";
import { atom, useAtomValue } from "jotai"; import { atom, useAtomValue } from "jotai";
import { useCallback } from "react"; import { useCallback } from "react";
import "./helpview.less"; import "./helpview.less";
class HelpViewModel extends WebViewModel { class HelpViewModel extends WebViewModel {
constructor(blockId: string, nodeModel: NodeModel) { constructor(blockId: string, nodeModel: BlockNodeModel) {
super(blockId, nodeModel); super(blockId, nodeModel);
this.getSettingsMenuItems = undefined; this.getSettingsMenuItems = undefined;
this.viewText = atom((get) => { this.viewText = atom((get) => {
@ -44,7 +44,7 @@ class HelpViewModel extends WebViewModel {
} }
} }
function makeHelpViewModel(blockId: string, nodeModel: NodeModel) { function makeHelpViewModel(blockId: string, nodeModel: BlockNodeModel) {
return new HelpViewModel(blockId, nodeModel); return new HelpViewModel(blockId, nodeModel);
} }

View File

@ -1,6 +1,7 @@
// Copyright 2024, Command Line Inc. // Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
import { BlockNodeModel } from "@/app/block/blocktypes";
import { CenteredDiv } from "@/app/element/quickelems"; import { CenteredDiv } from "@/app/element/quickelems";
import { TypeAheadModal } from "@/app/modals/typeaheadmodal"; import { TypeAheadModal } from "@/app/modals/typeaheadmodal";
import { ContextMenuModel } from "@/app/store/contextmenu"; import { ContextMenuModel } from "@/app/store/contextmenu";
@ -9,7 +10,6 @@ import { RpcApi } from "@/app/store/wshclientapi";
import { TabRpcClient } from "@/app/store/wshrpcutil"; import { TabRpcClient } from "@/app/store/wshrpcutil";
import { CodeEditor } from "@/app/view/codeeditor/codeeditor"; import { CodeEditor } from "@/app/view/codeeditor/codeeditor";
import { Markdown } from "@/element/markdown"; import { Markdown } from "@/element/markdown";
import { NodeModel } from "@/layout/index";
import { atoms, createBlock, getConnStatusAtom, getSettingsKeyAtom, globalStore, refocusNode } from "@/store/global"; import { atoms, createBlock, getConnStatusAtom, getSettingsKeyAtom, globalStore, refocusNode } from "@/store/global";
import * as services from "@/store/services"; import * as services from "@/store/services";
import * as WOS from "@/store/wos"; import * as WOS from "@/store/wos";
@ -98,7 +98,7 @@ function isStreamingType(mimeType: string): boolean {
export class PreviewModel implements ViewModel { export class PreviewModel implements ViewModel {
viewType: string; viewType: string;
blockId: string; blockId: string;
nodeModel: NodeModel; nodeModel: BlockNodeModel;
blockAtom: Atom<Block>; blockAtom: Atom<Block>;
viewIcon: Atom<string | IconButtonDecl>; viewIcon: Atom<string | IconButtonDecl>;
viewName: Atom<string>; viewName: Atom<string>;
@ -141,7 +141,7 @@ export class PreviewModel implements ViewModel {
directoryKeyDownHandler: (waveEvent: WaveKeyboardEvent) => boolean; directoryKeyDownHandler: (waveEvent: WaveKeyboardEvent) => boolean;
codeEditKeyDownHandler: (waveEvent: WaveKeyboardEvent) => boolean; codeEditKeyDownHandler: (waveEvent: WaveKeyboardEvent) => boolean;
constructor(blockId: string, nodeModel: NodeModel) { constructor(blockId: string, nodeModel: BlockNodeModel) {
this.viewType = "preview"; this.viewType = "preview";
this.blockId = blockId; this.blockId = blockId;
this.nodeModel = nodeModel; this.nodeModel = nodeModel;
@ -733,7 +733,7 @@ export class PreviewModel implements ViewModel {
} }
} }
function makePreviewModel(blockId: string, nodeModel: NodeModel): PreviewModel { function makePreviewModel(blockId: string, nodeModel: BlockNodeModel): PreviewModel {
const previewModel = new PreviewModel(blockId, nodeModel); const previewModel = new PreviewModel(blockId, nodeModel);
return previewModel; return previewModel;
} }

View File

@ -1,7 +1,8 @@
// Copyright 2024, Command Line Inc. // Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
import { Block } from "@/app/block/block"; import { Block, SubBlock } from "@/app/block/block";
import { BlockNodeModel } from "@/app/block/blocktypes";
import { getAllGlobalKeyBindings } from "@/app/store/keymodel"; import { getAllGlobalKeyBindings } from "@/app/store/keymodel";
import { waveEventSubscribe } from "@/app/store/wps"; import { waveEventSubscribe } from "@/app/store/wps";
import { RpcApi } from "@/app/store/wshclientapi"; import { RpcApi } from "@/app/store/wshclientapi";
@ -9,7 +10,6 @@ import { makeFeBlockRouteId } from "@/app/store/wshrouter";
import { DefaultRouter, TabRpcClient } from "@/app/store/wshrpcutil"; import { DefaultRouter, TabRpcClient } from "@/app/store/wshrpcutil";
import { TermWshClient } from "@/app/view/term/term-wsh"; import { TermWshClient } from "@/app/view/term/term-wsh";
import { VDomModel } from "@/app/view/vdom/vdom-model"; import { VDomModel } from "@/app/view/vdom/vdom-model";
import { NodeModel } from "@/layout/index";
import { import {
WOS, WOS,
atoms, atoms,
@ -41,7 +41,7 @@ type InitialLoadDataType = {
class TermViewModel { class TermViewModel {
viewType: string; viewType: string;
nodeModel: NodeModel; nodeModel: BlockNodeModel;
connected: boolean; connected: boolean;
termRef: React.RefObject<TermWrap>; termRef: React.RefObject<TermWrap>;
blockAtom: jotai.Atom<Block>; blockAtom: jotai.Atom<Block>;
@ -59,7 +59,7 @@ class TermViewModel {
fontSizeAtom: jotai.Atom<number>; fontSizeAtom: jotai.Atom<number>;
termThemeNameAtom: jotai.Atom<string>; termThemeNameAtom: jotai.Atom<string>;
constructor(blockId: string, nodeModel: NodeModel) { constructor(blockId: string, nodeModel: BlockNodeModel) {
this.viewType = "term"; this.viewType = "term";
this.blockId = blockId; this.blockId = blockId;
this.termWshClient = new TermWshClient(blockId, this); this.termWshClient = new TermWshClient(blockId, this);
@ -351,7 +351,7 @@ class TermViewModel {
} }
} }
function makeTerminalModel(blockId: string, nodeModel: NodeModel): TermViewModel { function makeTerminalModel(blockId: string, nodeModel: BlockNodeModel): TermViewModel {
return new TermViewModel(blockId, nodeModel); return new TermViewModel(blockId, nodeModel);
} }
@ -407,6 +407,9 @@ const TermVDomNodeSingleId = ({ vdomBlockId, blockId, model }: TerminalViewProps
let vdomNodeModel = { let vdomNodeModel = {
blockId: vdomBlockId, blockId: vdomBlockId,
isFocused: isFocusedAtom, isFocused: isFocusedAtom,
focusNode: () => {
model.nodeModel.focusNode();
},
onClose: () => { onClose: () => {
if (vdomBlockId != null) { if (vdomBlockId != null) {
RpcApi.DeleteSubBlockCommand(TabRpcClient, { blockid: vdomBlockId }); RpcApi.DeleteSubBlockCommand(TabRpcClient, { blockid: vdomBlockId });
@ -415,7 +418,7 @@ const TermVDomNodeSingleId = ({ vdomBlockId, blockId, model }: TerminalViewProps
}; };
return ( return (
<div key="htmlElem" className="term-htmlelem"> <div key="htmlElem" className="term-htmlelem">
<Block key="vdom" isSubBlock={true} preview={false} nodeModel={vdomNodeModel} /> <SubBlock key="vdom" nodeModel={vdomNodeModel} />
</div> </div>
); );
}; };

View File

@ -1,6 +1,7 @@
// Copyright 2024, Command Line Inc. // Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
import { BlockNodeModel } from "@/app/block/blocktypes";
import { getBlockMetaKeyAtom, globalStore, WOS } from "@/app/store/global"; import { getBlockMetaKeyAtom, globalStore, WOS } from "@/app/store/global";
import { makeORef } from "@/app/store/wos"; import { makeORef } from "@/app/store/wos";
import { waveEventSubscribe } from "@/app/store/wps"; import { waveEventSubscribe } from "@/app/store/wps";
@ -8,7 +9,6 @@ import { RpcResponseHelper, WshClient } from "@/app/store/wshclient";
import { RpcApi } from "@/app/store/wshclientapi"; import { RpcApi } from "@/app/store/wshclientapi";
import { makeFeBlockRouteId } from "@/app/store/wshrouter"; import { makeFeBlockRouteId } from "@/app/store/wshrouter";
import { DefaultRouter, TabRpcClient } from "@/app/store/wshrpcutil"; import { DefaultRouter, TabRpcClient } from "@/app/store/wshrpcutil";
import { NodeModel } from "@/layout/index";
import { adaptFromReactOrNativeKeyEvent, checkKeyPressed } from "@/util/keyutil"; import { adaptFromReactOrNativeKeyEvent, checkKeyPressed } from "@/util/keyutil";
import debug from "debug"; import debug from "debug";
import * as jotai from "jotai"; import * as jotai from "jotai";
@ -79,7 +79,7 @@ class VDomWshClient extends WshClient {
export class VDomModel { export class VDomModel {
blockId: string; blockId: string;
nodeModel: NodeModel; nodeModel: BlockNodeModel;
viewType: string; viewType: string;
viewIcon: jotai.Atom<string>; viewIcon: jotai.Atom<string>;
viewName: jotai.Atom<string>; viewName: jotai.Atom<string>;
@ -109,7 +109,7 @@ export class VDomModel {
routeGoneUnsub: () => void; routeGoneUnsub: () => void;
routeConfirmed: boolean = false; routeConfirmed: boolean = false;
constructor(blockId: string, nodeModel: NodeModel) { constructor(blockId: string, nodeModel: BlockNodeModel) {
this.viewType = "vdom"; this.viewType = "vdom";
this.blockId = blockId; this.blockId = blockId;
this.nodeModel = nodeModel; this.nodeModel = nodeModel;

View File

@ -9,8 +9,8 @@ import debug from "debug";
import * as jotai from "jotai"; import * as jotai from "jotai";
import * as React from "react"; import * as React from "react";
import { BlockNodeModel } from "@/app/block/blocktypes";
import { convertVDomId, getTextChildren, validateAndWrapCss } from "@/app/view/vdom/vdom-utils"; import { convertVDomId, getTextChildren, validateAndWrapCss } from "@/app/view/vdom/vdom-utils";
import { NodeModel } from "@/layout/index";
import "./vdom.less"; import "./vdom.less";
const TextTag = "#text"; const TextTag = "#text";
@ -331,7 +331,7 @@ function VDomRoot({ model }: { model: VDomModel }) {
return <div className="vdom">{rtn}</div>; return <div className="vdom">{rtn}</div>;
} }
function makeVDomModel(blockId: string, nodeModel: NodeModel): VDomModel { function makeVDomModel(blockId: string, nodeModel: BlockNodeModel): VDomModel {
return new VDomModel(blockId, nodeModel); return new VDomModel(blockId, nodeModel);
} }

View File

@ -1,12 +1,12 @@
// Copyright 2024, Command Line Inc. // Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
import { BlockNodeModel } from "@/app/block/blocktypes";
import { getApi, getSettingsKeyAtom, openLink } from "@/app/store/global"; import { getApi, getSettingsKeyAtom, openLink } from "@/app/store/global";
import { getSimpleControlShiftAtom } from "@/app/store/keymodel"; import { getSimpleControlShiftAtom } from "@/app/store/keymodel";
import { ObjectService } from "@/app/store/services"; import { ObjectService } from "@/app/store/services";
import { RpcApi } from "@/app/store/wshclientapi"; import { RpcApi } from "@/app/store/wshclientapi";
import { TabRpcClient } from "@/app/store/wshrpcutil"; import { TabRpcClient } from "@/app/store/wshrpcutil";
import { NodeModel } from "@/layout/index";
import { WOS, globalStore } from "@/store/global"; import { WOS, globalStore } from "@/store/global";
import { adaptFromReactOrNativeKeyEvent, checkKeyPressed } from "@/util/keyutil"; import { adaptFromReactOrNativeKeyEvent, checkKeyPressed } from "@/util/keyutil";
import { fireAndForget } from "@/util/util"; import { fireAndForget } from "@/util/util";
@ -44,12 +44,12 @@ export class WebViewModel implements ViewModel {
refreshIcon: PrimitiveAtom<string>; refreshIcon: PrimitiveAtom<string>;
webviewRef: React.RefObject<WebviewTag>; webviewRef: React.RefObject<WebviewTag>;
urlInputRef: React.RefObject<HTMLInputElement>; urlInputRef: React.RefObject<HTMLInputElement>;
nodeModel: NodeModel; nodeModel: BlockNodeModel;
endIconButtons?: Atom<IconButtonDecl[]>; endIconButtons?: Atom<IconButtonDecl[]>;
mediaPlaying: PrimitiveAtom<boolean>; mediaPlaying: PrimitiveAtom<boolean>;
mediaMuted: PrimitiveAtom<boolean>; mediaMuted: PrimitiveAtom<boolean>;
constructor(blockId: string, nodeModel: NodeModel) { constructor(blockId: string, nodeModel: BlockNodeModel) {
this.nodeModel = nodeModel; this.nodeModel = nodeModel;
this.viewType = "web"; this.viewType = "web";
this.blockId = blockId; this.blockId = blockId;
@ -459,7 +459,7 @@ export class WebViewModel implements ViewModel {
} }
} }
function makeWebViewModel(blockId: string, nodeModel: NodeModel): WebViewModel { function makeWebViewModel(blockId: string, nodeModel: BlockNodeModel): WebViewModel {
const webviewModel = new WebViewModel(blockId, nodeModel); const webviewModel = new WebViewModel(blockId, nodeModel);
return webviewModel; return webviewModel;
} }