Skip to content

Commit

Permalink
vdom 6 (#1145)
Browse files Browse the repository at this point in the history
  • Loading branch information
sawka authored Oct 26, 2024
1 parent da57427 commit a782d83
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 39 deletions.
49 changes: 34 additions & 15 deletions frontend/app/block/block.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
// Copyright 2024, Command Line Inc.
// 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 { PreviewModel, PreviewView, makePreviewModel } from "@/app/view/preview/preview";
import { SysinfoView, SysinfoViewModel, makeSysinfoViewModel } from "@/app/view/sysinfo/sysinfo";
import { VDomView, makeVDomModel } from "@/app/view/vdom/vdom";
import { VDomModel } from "@/app/view/vdom/vdom-model";
import { ErrorBoundary } from "@/element/errorboundary";
import { CenteredDiv } from "@/element/quickelems";
import { NodeModel, useDebouncedNodeInnerRect } from "@/layout/index";
import { useDebouncedNodeInnerRect } from "@/layout/index";
import {
counterInc,
getBlockComponentModel,
Expand All @@ -30,14 +37,7 @@ import "./block.less";
import { BlockFrame } from "./blockframe";
import { blockViewToIcon, blockViewToName } from "./blockutil";

type FullBlockProps = {
isSubBlock?: boolean;
preview: boolean;
nodeModel: NodeModel;
viewModel: ViewModel;
};

function makeViewModel(blockId: string, blockView: string, nodeModel: NodeModel): ViewModel {
function makeViewModel(blockId: string, blockView: string, nodeModel: BlockNodeModel): ViewModel {
if (blockView === "term") {
return makeTerminalModel(blockId, nodeModel);
}
Expand Down Expand Up @@ -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 blockRef = useRef<HTMLDivElement>(null);
const contentRef = useRef<HTMLDivElement>(null);
Expand Down Expand Up @@ -304,10 +304,29 @@ const Block = memo((props: BlockProps) => {
if (props.preview) {
return <BlockPreview {...props} viewModel={viewModel} />;
}
if (props.isSubBlock) {
return <BlockSubBlock {...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 };
25 changes: 24 additions & 1 deletion frontend/app/block/blocktypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,35 @@
// SPDX-License-Identifier: Apache-2.0

import { NodeModel } from "@/layout/index";
import { Atom } from "jotai";

export interface BlockNodeModel {
blockId: string;
isFocused: Atom<boolean>;
onClose: () => void;
focusNode: () => void;
}

export type FullBlockProps = {
preview: boolean;
nodeModel: NodeModel;
viewModel: ViewModel;
};

export interface BlockProps {
isSubBlock?: boolean;
preview: boolean;
nodeModel: NodeModel;
}

export type FullSubBlockProps = {
nodeModel: BlockNodeModel;
viewModel: ViewModel;
};

export interface SubBlockProps {
nodeModel: BlockNodeModel;
}

export interface BlockComponentModel2 {
onClick?: () => void;
onFocusCapture?: React.FocusEventHandler<HTMLDivElement>;
Expand Down
2 changes: 1 addition & 1 deletion frontend/app/element/quicktips.less
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
font: var(--fixed-font);
font-size: 0.85em;
color: var(--keybinding-color);
background-color: var(--keybinding-bg-color);
background-color: var(--highlight-bg-color);
border-radius: 4px;
border: 1px solid var(--keybinding-border-color);
box-shadow: none;
Expand Down
6 changes: 3 additions & 3 deletions frontend/app/view/helpview/helpview.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
// Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0

import { BlockNodeModel } from "@/app/block/blocktypes";
import { getApi } from "@/app/store/global";
import { WebView, WebViewModel } from "@/app/view/webview/webview";
import { NodeModel } from "@/layout/index";
import { fireAndForget } from "@/util/util";
import { atom, useAtomValue } from "jotai";
import { useCallback } from "react";
import "./helpview.less";

class HelpViewModel extends WebViewModel {
constructor(blockId: string, nodeModel: NodeModel) {
constructor(blockId: string, nodeModel: BlockNodeModel) {
super(blockId, nodeModel);
this.getSettingsMenuItems = undefined;
this.viewText = atom((get) => {
Expand Down Expand Up @@ -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);
}

Expand Down
8 changes: 4 additions & 4 deletions frontend/app/view/preview/preview.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0

import { BlockNodeModel } from "@/app/block/blocktypes";
import { CenteredDiv } from "@/app/element/quickelems";
import { TypeAheadModal } from "@/app/modals/typeaheadmodal";
import { ContextMenuModel } from "@/app/store/contextmenu";
Expand All @@ -9,7 +10,6 @@ import { RpcApi } from "@/app/store/wshclientapi";
import { TabRpcClient } from "@/app/store/wshrpcutil";
import { CodeEditor } from "@/app/view/codeeditor/codeeditor";
import { Markdown } from "@/element/markdown";
import { NodeModel } from "@/layout/index";
import { atoms, createBlock, getConnStatusAtom, getSettingsKeyAtom, globalStore, refocusNode } from "@/store/global";
import * as services from "@/store/services";
import * as WOS from "@/store/wos";
Expand Down Expand Up @@ -98,7 +98,7 @@ function isStreamingType(mimeType: string): boolean {
export class PreviewModel implements ViewModel {
viewType: string;
blockId: string;
nodeModel: NodeModel;
nodeModel: BlockNodeModel;
blockAtom: Atom<Block>;
viewIcon: Atom<string | IconButtonDecl>;
viewName: Atom<string>;
Expand Down Expand Up @@ -141,7 +141,7 @@ export class PreviewModel implements ViewModel {
directoryKeyDownHandler: (waveEvent: WaveKeyboardEvent) => boolean;
codeEditKeyDownHandler: (waveEvent: WaveKeyboardEvent) => boolean;

constructor(blockId: string, nodeModel: NodeModel) {
constructor(blockId: string, nodeModel: BlockNodeModel) {
this.viewType = "preview";
this.blockId = blockId;
this.nodeModel = nodeModel;
Expand Down Expand Up @@ -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);
return previewModel;
}
Expand Down
15 changes: 9 additions & 6 deletions frontend/app/view/term/term.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
// Copyright 2024, Command Line Inc.
// 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 { waveEventSubscribe } from "@/app/store/wps";
import { RpcApi } from "@/app/store/wshclientapi";
import { makeFeBlockRouteId } from "@/app/store/wshrouter";
import { DefaultRouter, TabRpcClient } from "@/app/store/wshrpcutil";
import { TermWshClient } from "@/app/view/term/term-wsh";
import { VDomModel } from "@/app/view/vdom/vdom-model";
import { NodeModel } from "@/layout/index";
import {
WOS,
atoms,
Expand Down Expand Up @@ -41,7 +41,7 @@ type InitialLoadDataType = {

class TermViewModel {
viewType: string;
nodeModel: NodeModel;
nodeModel: BlockNodeModel;
connected: boolean;
termRef: React.RefObject<TermWrap>;
blockAtom: jotai.Atom<Block>;
Expand All @@ -59,7 +59,7 @@ class TermViewModel {
fontSizeAtom: jotai.Atom<number>;
termThemeNameAtom: jotai.Atom<string>;

constructor(blockId: string, nodeModel: NodeModel) {
constructor(blockId: string, nodeModel: BlockNodeModel) {
this.viewType = "term";
this.blockId = blockId;
this.termWshClient = new TermWshClient(blockId, this);
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -407,6 +407,9 @@ const TermVDomNodeSingleId = ({ vdomBlockId, blockId, model }: TerminalViewProps
let vdomNodeModel = {
blockId: vdomBlockId,
isFocused: isFocusedAtom,
focusNode: () => {
model.nodeModel.focusNode();
},
onClose: () => {
if (vdomBlockId != null) {
RpcApi.DeleteSubBlockCommand(TabRpcClient, { blockid: vdomBlockId });
Expand All @@ -415,7 +418,7 @@ const TermVDomNodeSingleId = ({ vdomBlockId, blockId, model }: TerminalViewProps
};
return (
<div key="htmlElem" className="term-htmlelem">
<Block key="vdom" isSubBlock={true} preview={false} nodeModel={vdomNodeModel} />
<SubBlock key="vdom" nodeModel={vdomNodeModel} />
</div>
);
};
Expand Down
6 changes: 3 additions & 3 deletions frontend/app/view/vdom/vdom-model.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0

import { BlockNodeModel } from "@/app/block/blocktypes";
import { getBlockMetaKeyAtom, globalStore, WOS } from "@/app/store/global";
import { makeORef } from "@/app/store/wos";
import { waveEventSubscribe } from "@/app/store/wps";
import { RpcResponseHelper, WshClient } from "@/app/store/wshclient";
import { RpcApi } from "@/app/store/wshclientapi";
import { makeFeBlockRouteId } from "@/app/store/wshrouter";
import { DefaultRouter, TabRpcClient } from "@/app/store/wshrpcutil";
import { NodeModel } from "@/layout/index";
import { adaptFromReactOrNativeKeyEvent, checkKeyPressed } from "@/util/keyutil";
import debug from "debug";
import * as jotai from "jotai";
Expand Down Expand Up @@ -79,7 +79,7 @@ class VDomWshClient extends WshClient {

export class VDomModel {
blockId: string;
nodeModel: NodeModel;
nodeModel: BlockNodeModel;
viewType: string;
viewIcon: jotai.Atom<string>;
viewName: jotai.Atom<string>;
Expand Down Expand Up @@ -109,7 +109,7 @@ export class VDomModel {
routeGoneUnsub: () => void;
routeConfirmed: boolean = false;

constructor(blockId: string, nodeModel: NodeModel) {
constructor(blockId: string, nodeModel: BlockNodeModel) {
this.viewType = "vdom";
this.blockId = blockId;
this.nodeModel = nodeModel;
Expand Down
4 changes: 2 additions & 2 deletions frontend/app/view/vdom/vdom.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import debug from "debug";
import * as jotai from "jotai";
import * as React from "react";

import { BlockNodeModel } from "@/app/block/blocktypes";
import { convertVDomId, getTextChildren, validateAndWrapCss } from "@/app/view/vdom/vdom-utils";
import { NodeModel } from "@/layout/index";
import "./vdom.less";

const TextTag = "#text";
Expand Down Expand Up @@ -331,7 +331,7 @@ function VDomRoot({ model }: { model: VDomModel }) {
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);
}

Expand Down
8 changes: 4 additions & 4 deletions frontend/app/view/webview/webview.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0

import { BlockNodeModel } from "@/app/block/blocktypes";
import { getApi, getSettingsKeyAtom, openLink } from "@/app/store/global";
import { getSimpleControlShiftAtom } from "@/app/store/keymodel";
import { ObjectService } from "@/app/store/services";
import { RpcApi } from "@/app/store/wshclientapi";
import { TabRpcClient } from "@/app/store/wshrpcutil";
import { NodeModel } from "@/layout/index";
import { WOS, globalStore } from "@/store/global";
import { adaptFromReactOrNativeKeyEvent, checkKeyPressed } from "@/util/keyutil";
import { fireAndForget } from "@/util/util";
Expand Down Expand Up @@ -44,12 +44,12 @@ export class WebViewModel implements ViewModel {
refreshIcon: PrimitiveAtom<string>;
webviewRef: React.RefObject<WebviewTag>;
urlInputRef: React.RefObject<HTMLInputElement>;
nodeModel: NodeModel;
nodeModel: BlockNodeModel;
endIconButtons?: Atom<IconButtonDecl[]>;
mediaPlaying: PrimitiveAtom<boolean>;
mediaMuted: PrimitiveAtom<boolean>;

constructor(blockId: string, nodeModel: NodeModel) {
constructor(blockId: string, nodeModel: BlockNodeModel) {
this.nodeModel = nodeModel;
this.viewType = "web";
this.blockId = blockId;
Expand Down Expand Up @@ -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);
return webviewModel;
}
Expand Down

0 comments on commit a782d83

Please sign in to comment.