mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-21 16:38:23 +01:00
vdom 6 (#1145)
This commit is contained in:
parent
da57427e8c
commit
a782d83628
@ -1,7 +1,14 @@
|
||||
// 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";
|
||||
@ -9,7 +16,7 @@ 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,
|
||||
@ -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);
|
||||
}
|
||||
@ -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);
|
||||
@ -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 };
|
||||
|
@ -2,10 +2,33 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { NodeModel } from "@/layout/index";
|
||||
export interface BlockProps {
|
||||
isSubBlock?: boolean;
|
||||
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 {
|
||||
preview: boolean;
|
||||
nodeModel: NodeModel;
|
||||
}
|
||||
|
||||
export type FullSubBlockProps = {
|
||||
nodeModel: BlockNodeModel;
|
||||
viewModel: ViewModel;
|
||||
};
|
||||
|
||||
export interface SubBlockProps {
|
||||
nodeModel: BlockNodeModel;
|
||||
}
|
||||
|
||||
export interface BlockComponentModel2 {
|
||||
|
@ -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;
|
||||
|
@ -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) => {
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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";
|
||||
@ -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";
|
||||
@ -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>;
|
||||
@ -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;
|
||||
@ -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;
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
// 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";
|
||||
@ -9,7 +10,6 @@ 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,
|
||||
@ -41,7 +41,7 @@ type InitialLoadDataType = {
|
||||
|
||||
class TermViewModel {
|
||||
viewType: string;
|
||||
nodeModel: NodeModel;
|
||||
nodeModel: BlockNodeModel;
|
||||
connected: boolean;
|
||||
termRef: React.RefObject<TermWrap>;
|
||||
blockAtom: jotai.Atom<Block>;
|
||||
@ -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);
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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 });
|
||||
@ -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>
|
||||
);
|
||||
};
|
||||
|
@ -1,6 +1,7 @@
|
||||
// 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";
|
||||
@ -8,7 +9,6 @@ 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";
|
||||
@ -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>;
|
||||
@ -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;
|
||||
|
@ -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";
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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";
|
||||
@ -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;
|
||||
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user