mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-01-02 18:39:05 +01:00
vdom terminal toolbar (#1263)
This commit is contained in:
parent
83f671c7a9
commit
3fc45c63f3
@ -26,6 +26,10 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
|
|
||||||
|
&.block-no-padding {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.block-focuselem {
|
.block-focuselem {
|
||||||
|
@ -25,12 +25,13 @@ import {
|
|||||||
} from "@/store/global";
|
} from "@/store/global";
|
||||||
import { getWaveObjectAtom, makeORef, useWaveObjectValue } from "@/store/wos";
|
import { getWaveObjectAtom, makeORef, useWaveObjectValue } from "@/store/wos";
|
||||||
import { focusedBlockId, getElemAsStr } from "@/util/focusutil";
|
import { focusedBlockId, getElemAsStr } from "@/util/focusutil";
|
||||||
import { isBlank } from "@/util/util";
|
import { isBlank, useAtomValueSafe } from "@/util/util";
|
||||||
import { HelpView, HelpViewModel, makeHelpViewModel } from "@/view/helpview/helpview";
|
import { HelpView, HelpViewModel, makeHelpViewModel } from "@/view/helpview/helpview";
|
||||||
import { QuickTipsView, QuickTipsViewModel } from "@/view/quicktipsview/quicktipsview";
|
import { QuickTipsView, QuickTipsViewModel } from "@/view/quicktipsview/quicktipsview";
|
||||||
import { TermViewModel, TerminalView, makeTerminalModel } from "@/view/term/term";
|
import { TermViewModel, TerminalView, makeTerminalModel } from "@/view/term/term";
|
||||||
import { WaveAi, WaveAiModel, makeWaveAiViewModel } from "@/view/waveai/waveai";
|
import { WaveAi, WaveAiModel, makeWaveAiViewModel } from "@/view/waveai/waveai";
|
||||||
import { WebView, WebViewModel, makeWebViewModel } from "@/view/webview/webview";
|
import { WebView, WebViewModel, makeWebViewModel } from "@/view/webview/webview";
|
||||||
|
import clsx from "clsx";
|
||||||
import { atom, useAtomValue } from "jotai";
|
import { atom, useAtomValue } from "jotai";
|
||||||
import { Suspense, memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
import { Suspense, memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
||||||
import "./block.less";
|
import "./block.less";
|
||||||
@ -154,11 +155,12 @@ const BlockSubBlock = memo(({ nodeModel, viewModel }: FullSubBlockProps) => {
|
|||||||
() => getViewElem(nodeModel.blockId, blockRef, contentRef, blockData?.meta?.view, viewModel),
|
() => getViewElem(nodeModel.blockId, blockRef, contentRef, blockData?.meta?.view, viewModel),
|
||||||
[nodeModel.blockId, blockData?.meta?.view, viewModel]
|
[nodeModel.blockId, blockData?.meta?.view, viewModel]
|
||||||
);
|
);
|
||||||
|
const noPadding = useAtomValueSafe(viewModel.noPadding);
|
||||||
if (!blockData) {
|
if (!blockData) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div key="content" className="block-content" ref={contentRef}>
|
<div key="content" className={clsx("block-content", { "block-no-padding": noPadding })} ref={contentRef}>
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
<Suspense fallback={<CenteredDiv>Loading...</CenteredDiv>}>{viewElem}</Suspense>
|
<Suspense fallback={<CenteredDiv>Loading...</CenteredDiv>}>{viewElem}</Suspense>
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
@ -176,6 +178,7 @@ const BlockFull = memo(({ nodeModel, viewModel }: FullBlockProps) => {
|
|||||||
const isFocused = useAtomValue(nodeModel.isFocused);
|
const isFocused = useAtomValue(nodeModel.isFocused);
|
||||||
const disablePointerEvents = useAtomValue(nodeModel.disablePointerEvents);
|
const disablePointerEvents = useAtomValue(nodeModel.disablePointerEvents);
|
||||||
const innerRect = useDebouncedNodeInnerRect(nodeModel);
|
const innerRect = useDebouncedNodeInnerRect(nodeModel);
|
||||||
|
const noPadding = useAtomValueSafe(viewModel.noPadding);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
setBlockClicked(isFocused);
|
setBlockClicked(isFocused);
|
||||||
@ -273,7 +276,12 @@ const BlockFull = memo(({ nodeModel, viewModel }: FullBlockProps) => {
|
|||||||
onChange={() => {}}
|
onChange={() => {}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div key="content" className="block-content" ref={contentRef} style={blockContentStyle}>
|
<div
|
||||||
|
key="content"
|
||||||
|
className={clsx("block-content", { "block-no-padding": noPadding })}
|
||||||
|
ref={contentRef}
|
||||||
|
style={blockContentStyle}
|
||||||
|
>
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
<Suspense fallback={<CenteredDiv>Loading...</CenteredDiv>}>{viewElem}</Suspense>
|
<Suspense fallback={<CenteredDiv>Loading...</CenteredDiv>}>{viewElem}</Suspense>
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
|
@ -41,6 +41,35 @@ export class TermWshClient extends WshClient {
|
|||||||
magnified: data.target?.magnified,
|
magnified: data.target?.magnified,
|
||||||
});
|
});
|
||||||
return oref;
|
return oref;
|
||||||
|
} else if (data.target?.toolbar?.toolbar) {
|
||||||
|
const oldVDomBlockId = globalStore.get(this.model.vdomToolbarBlockId);
|
||||||
|
console.log("vdom:toolbar", data.target.toolbar);
|
||||||
|
globalStore.set(this.model.vdomToolbarTarget, data.target.toolbar);
|
||||||
|
const oref = await RpcApi.CreateSubBlockCommand(this, {
|
||||||
|
parentblockid: this.blockId,
|
||||||
|
blockdef: {
|
||||||
|
meta: {
|
||||||
|
view: "vdom",
|
||||||
|
"vdom:route": rh.getSource(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const [_, newVDomBlockId] = splitORef(oref);
|
||||||
|
if (!isBlank(oldVDomBlockId)) {
|
||||||
|
// dispose of the old vdom block
|
||||||
|
setTimeout(() => {
|
||||||
|
RpcApi.DeleteSubBlockCommand(this, { blockid: oldVDomBlockId });
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
RpcApi.SetMetaCommand(this, {
|
||||||
|
oref: makeORef("block", this.model.blockId),
|
||||||
|
meta: {
|
||||||
|
"term:vdomtoolbarblockid": newVDomBlockId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}, 50);
|
||||||
|
return oref;
|
||||||
} else {
|
} else {
|
||||||
// in the terminal
|
// in the terminal
|
||||||
// check if there is a current active vdom block
|
// check if there is a current active vdom block
|
||||||
|
@ -13,11 +13,10 @@
|
|||||||
|
|
||||||
.view-term {
|
.view-term {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: column;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding-left: 4px;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
.term-header {
|
.term-header {
|
||||||
@ -31,11 +30,19 @@
|
|||||||
border-bottom: 1px solid var(--border-color);
|
border-bottom: 1px solid var(--border-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.term-toolbar {
|
||||||
|
height: 20px;
|
||||||
|
border-bottom: 1px solid var(--border-color);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
.term-connectelem {
|
.term-connectelem {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
|
margin: 5px;
|
||||||
|
margin-left: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.term-htmlelem {
|
.term-htmlelem {
|
||||||
|
@ -56,8 +56,11 @@ class TermViewModel {
|
|||||||
termWshClient: TermWshClient;
|
termWshClient: TermWshClient;
|
||||||
shellProcStatusRef: React.MutableRefObject<string>;
|
shellProcStatusRef: React.MutableRefObject<string>;
|
||||||
vdomBlockId: jotai.Atom<string>;
|
vdomBlockId: jotai.Atom<string>;
|
||||||
|
vdomToolbarBlockId: jotai.Atom<string>;
|
||||||
|
vdomToolbarTarget: jotai.PrimitiveAtom<VDomTargetToolbar>;
|
||||||
fontSizeAtom: jotai.Atom<number>;
|
fontSizeAtom: jotai.Atom<number>;
|
||||||
termThemeNameAtom: jotai.Atom<string>;
|
termThemeNameAtom: jotai.Atom<string>;
|
||||||
|
noPadding: jotai.PrimitiveAtom<boolean>;
|
||||||
|
|
||||||
constructor(blockId: string, nodeModel: BlockNodeModel) {
|
constructor(blockId: string, nodeModel: BlockNodeModel) {
|
||||||
this.viewType = "term";
|
this.viewType = "term";
|
||||||
@ -70,6 +73,11 @@ class TermViewModel {
|
|||||||
const blockData = get(this.blockAtom);
|
const blockData = get(this.blockAtom);
|
||||||
return blockData?.meta?.["term:vdomblockid"];
|
return blockData?.meta?.["term:vdomblockid"];
|
||||||
});
|
});
|
||||||
|
this.vdomToolbarBlockId = jotai.atom((get) => {
|
||||||
|
const blockData = get(this.blockAtom);
|
||||||
|
return blockData?.meta?.["term:vdomtoolbarblockid"];
|
||||||
|
});
|
||||||
|
this.vdomToolbarTarget = jotai.atom<VDomTargetToolbar>(null) as jotai.PrimitiveAtom<VDomTargetToolbar>;
|
||||||
this.termMode = jotai.atom((get) => {
|
this.termMode = jotai.atom((get) => {
|
||||||
const blockData = get(this.blockAtom);
|
const blockData = get(this.blockAtom);
|
||||||
return blockData?.meta?.["term:mode"] ?? "term";
|
return blockData?.meta?.["term:mode"] ?? "term";
|
||||||
@ -167,6 +175,7 @@ class TermViewModel {
|
|||||||
return blockData?.meta?.["term:theme"] ?? get(settingsKeyAtom) ?? "default-dark";
|
return blockData?.meta?.["term:theme"] ?? get(settingsKeyAtom) ?? "default-dark";
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
this.noPadding = jotai.atom(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
setTermMode(mode: "term" | "vdom") {
|
setTermMode(mode: "term" | "vdom") {
|
||||||
@ -191,6 +200,18 @@ class TermViewModel {
|
|||||||
return bcm.viewModel as VDomModel;
|
return bcm.viewModel as VDomModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getVDomToolbarModel(): VDomModel {
|
||||||
|
const vdomToolbarBlockId = globalStore.get(this.vdomToolbarBlockId);
|
||||||
|
if (!vdomToolbarBlockId) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const bcm = getBlockComponentModel(vdomToolbarBlockId);
|
||||||
|
if (!bcm) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return bcm.viewModel as VDomModel;
|
||||||
|
}
|
||||||
|
|
||||||
dispose() {
|
dispose() {
|
||||||
DefaultRouter.unregisterRoute(makeFeBlockRouteId(this.blockId));
|
DefaultRouter.unregisterRoute(makeFeBlockRouteId(this.blockId));
|
||||||
}
|
}
|
||||||
@ -347,6 +368,15 @@ class TermViewModel {
|
|||||||
prtn.catch((e) => console.log("error controller resync (force restart)", e));
|
prtn.catch((e) => console.log("error controller resync (force restart)", e));
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
if (blockData?.meta?.["term:vdomtoolbarblockid"]) {
|
||||||
|
fullMenu.push({ type: "separator" });
|
||||||
|
fullMenu.push({
|
||||||
|
label: "Close Toolbar",
|
||||||
|
click: () => {
|
||||||
|
RpcApi.DeleteSubBlockCommand(TabRpcClient, { blockid: blockData.meta["term:vdomtoolbarblockid"] });
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
return fullMenu;
|
return fullMenu;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -382,6 +412,44 @@ const TermResyncHandler = React.memo(({ blockId, model }: TerminalViewProps) =>
|
|||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const TermVDomToolbarNode = ({ vdomBlockId, blockId, model }: TerminalViewProps & { vdomBlockId: string }) => {
|
||||||
|
React.useEffect(() => {
|
||||||
|
const unsub = waveEventSubscribe({
|
||||||
|
eventType: "blockclose",
|
||||||
|
scope: WOS.makeORef("block", vdomBlockId),
|
||||||
|
handler: (event) => {
|
||||||
|
RpcApi.SetMetaCommand(TabRpcClient, {
|
||||||
|
oref: WOS.makeORef("block", blockId),
|
||||||
|
meta: {
|
||||||
|
"term:mode": null,
|
||||||
|
"term:vdomtoolbarblockid": null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return () => {
|
||||||
|
unsub();
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
let vdomNodeModel = {
|
||||||
|
blockId: vdomBlockId,
|
||||||
|
isFocused: jotai.atom(false),
|
||||||
|
focusNode: () => {},
|
||||||
|
onClose: () => {
|
||||||
|
if (vdomBlockId != null) {
|
||||||
|
RpcApi.DeleteSubBlockCommand(TabRpcClient, { blockid: vdomBlockId });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const toolbarTarget = jotai.useAtomValue(model.vdomToolbarTarget);
|
||||||
|
const heightStr = toolbarTarget?.height ?? "1.5em";
|
||||||
|
return (
|
||||||
|
<div key="vdomToolbar" className="term-toolbar" style={{ height: heightStr }}>
|
||||||
|
<SubBlock key="vdom" nodeModel={vdomNodeModel} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const TermVDomNodeSingleId = ({ vdomBlockId, blockId, model }: TerminalViewProps & { vdomBlockId: string }) => {
|
const TermVDomNodeSingleId = ({ vdomBlockId, blockId, model }: TerminalViewProps & { vdomBlockId: string }) => {
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const unsub = waveEventSubscribe({
|
const unsub = waveEventSubscribe({
|
||||||
@ -431,6 +499,21 @@ const TermVDomNode = ({ blockId, model }: TerminalViewProps) => {
|
|||||||
return <TermVDomNodeSingleId key={vdomBlockId} vdomBlockId={vdomBlockId} blockId={blockId} model={model} />;
|
return <TermVDomNodeSingleId key={vdomBlockId} vdomBlockId={vdomBlockId} blockId={blockId} model={model} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const TermToolbarVDomNode = ({ blockId, model }: TerminalViewProps) => {
|
||||||
|
const vdomToolbarBlockId = jotai.useAtomValue(model.vdomToolbarBlockId);
|
||||||
|
if (vdomToolbarBlockId == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<TermVDomToolbarNode
|
||||||
|
key={vdomToolbarBlockId}
|
||||||
|
vdomBlockId={vdomToolbarBlockId}
|
||||||
|
blockId={blockId}
|
||||||
|
model={model}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const TerminalView = ({ blockId, model }: TerminalViewProps) => {
|
const TerminalView = ({ blockId, model }: TerminalViewProps) => {
|
||||||
const viewRef = React.useRef<HTMLDivElement>(null);
|
const viewRef = React.useRef<HTMLDivElement>(null);
|
||||||
const connectElemRef = React.useRef<HTMLDivElement>(null);
|
const connectElemRef = React.useRef<HTMLDivElement>(null);
|
||||||
@ -547,14 +630,14 @@ const TerminalView = ({ blockId, model }: TerminalViewProps) => {
|
|||||||
cols: termRef.current?.terminal.cols ?? 80,
|
cols: termRef.current?.terminal.cols ?? 80,
|
||||||
blockId: blockId,
|
blockId: blockId,
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={clsx("view-term", "term-mode-" + termMode)} ref={viewRef}>
|
<div className={clsx("view-term", "term-mode-" + termMode)} ref={viewRef}>
|
||||||
<TermResyncHandler blockId={blockId} model={model} />
|
<TermResyncHandler blockId={blockId} model={model} />
|
||||||
<TermThemeUpdater blockId={blockId} termRef={termRef} />
|
<TermThemeUpdater blockId={blockId} termRef={termRef} />
|
||||||
<TermStickers config={stickerConfig} />
|
<TermStickers config={stickerConfig} />
|
||||||
<div key="conntectElem" className="term-connectelem" ref={connectElemRef}></div>
|
<TermToolbarVDomNode key="vdom-toolbar" blockId={blockId} model={model} />
|
||||||
<TermVDomNode key="vdom" blockId={blockId} model={model} />
|
<TermVDomNode key="vdom" blockId={blockId} model={model} />
|
||||||
|
<div key="conntectElem" className="term-connectelem" ref={connectElemRef}></div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -134,6 +134,7 @@ export class VDomModel {
|
|||||||
refOutputStore: Map<string, any> = new Map();
|
refOutputStore: Map<string, any> = new Map();
|
||||||
globalVersion: jotai.PrimitiveAtom<number> = jotai.atom(0);
|
globalVersion: jotai.PrimitiveAtom<number> = jotai.atom(0);
|
||||||
hasBackendWork: boolean = false;
|
hasBackendWork: boolean = false;
|
||||||
|
noPadding: jotai.PrimitiveAtom<boolean>;
|
||||||
|
|
||||||
constructor(blockId: string, nodeModel: BlockNodeModel) {
|
constructor(blockId: string, nodeModel: BlockNodeModel) {
|
||||||
this.viewType = "vdom";
|
this.viewType = "vdom";
|
||||||
@ -147,6 +148,7 @@ export class VDomModel {
|
|||||||
const blockData = get(WOS.getWaveObjectAtom<Block>(makeORef("block", this.blockId)));
|
const blockData = get(WOS.getWaveObjectAtom<Block>(makeORef("block", this.blockId)));
|
||||||
return blockData?.meta?.["vdom:route"];
|
return blockData?.meta?.["vdom:route"];
|
||||||
});
|
});
|
||||||
|
this.noPadding = jotai.atom(true);
|
||||||
this.persist = getBlockMetaKeyAtom(this.blockId, "vdom:persist");
|
this.persist = getBlockMetaKeyAtom(this.blockId, "vdom:persist");
|
||||||
this.wshClient = new VDomWshClient(this);
|
this.wshClient = new VDomWshClient(this);
|
||||||
DefaultRouter.registerRoute(this.wshClient.routeId, this.wshClient);
|
DefaultRouter.registerRoute(this.wshClient.routeId, this.wshClient);
|
||||||
|
1
frontend/types/custom.d.ts
vendored
1
frontend/types/custom.d.ts
vendored
@ -229,6 +229,7 @@ declare global {
|
|||||||
endIconButtons?: jotai.Atom<IconButtonDecl[]>;
|
endIconButtons?: jotai.Atom<IconButtonDecl[]>;
|
||||||
blockBg?: jotai.Atom<MetaType>;
|
blockBg?: jotai.Atom<MetaType>;
|
||||||
manageConnection?: jotai.Atom<boolean>;
|
manageConnection?: jotai.Atom<boolean>;
|
||||||
|
noPadding?: jotai.Atom<boolean>;
|
||||||
|
|
||||||
onBack?: () => void;
|
onBack?: () => void;
|
||||||
onForward?: () => void;
|
onForward?: () => void;
|
||||||
|
8
frontend/types/gotypes.d.ts
vendored
8
frontend/types/gotypes.d.ts
vendored
@ -365,6 +365,7 @@ declare global {
|
|||||||
"term:localshellopts"?: string[];
|
"term:localshellopts"?: string[];
|
||||||
"term:scrollback"?: number;
|
"term:scrollback"?: number;
|
||||||
"term:vdomblockid"?: string;
|
"term:vdomblockid"?: string;
|
||||||
|
"term:vdomtoolbarblockid"?: string;
|
||||||
"vdom:*"?: boolean;
|
"vdom:*"?: boolean;
|
||||||
"vdom:initialized"?: boolean;
|
"vdom:initialized"?: boolean;
|
||||||
"vdom:correlationid"?: string;
|
"vdom:correlationid"?: string;
|
||||||
@ -795,6 +796,13 @@ declare global {
|
|||||||
type VDomTarget = {
|
type VDomTarget = {
|
||||||
newblock?: boolean;
|
newblock?: boolean;
|
||||||
magnified?: boolean;
|
magnified?: boolean;
|
||||||
|
toolbar?: VDomTargetToolbar;
|
||||||
|
};
|
||||||
|
|
||||||
|
// vdom.VDomTargetToolbar
|
||||||
|
type VDomTargetToolbar = {
|
||||||
|
toolbar: boolean;
|
||||||
|
height?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
// vdom.VDomTransferElem
|
// vdom.VDomTransferElem
|
||||||
|
@ -207,6 +207,12 @@ type VDomMessage struct {
|
|||||||
type VDomTarget struct {
|
type VDomTarget struct {
|
||||||
NewBlock bool `json:"newblock,omitempty"`
|
NewBlock bool `json:"newblock,omitempty"`
|
||||||
Magnified bool `json:"magnified,omitempty"`
|
Magnified bool `json:"magnified,omitempty"`
|
||||||
|
Toolbar *VDomTargetToolbar `json:"toolbar,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type VDomTargetToolbar struct {
|
||||||
|
Toolbar bool `json:"toolbar"`
|
||||||
|
Height string `json:"height,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// matches WaveKeyboardEvent
|
// matches WaveKeyboardEvent
|
||||||
|
@ -33,6 +33,8 @@ type AppOpts struct {
|
|||||||
GlobalStyles []byte
|
GlobalStyles []byte
|
||||||
RootComponentName string // defaults to "App"
|
RootComponentName string // defaults to "App"
|
||||||
NewBlockFlag string // defaults to "n" (set to "-" to disable)
|
NewBlockFlag string // defaults to "n" (set to "-" to disable)
|
||||||
|
TargetNewBlock bool
|
||||||
|
TargetToolbar *vdom.VDomTargetToolbar
|
||||||
}
|
}
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
@ -116,7 +118,17 @@ func (client *Client) runMainE() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = client.CreateVDomContext(&vdom.VDomTarget{NewBlock: client.NewBlockFlag})
|
target := &vdom.VDomTarget{}
|
||||||
|
if client.AppOpts.TargetNewBlock || client.NewBlockFlag {
|
||||||
|
target.NewBlock = client.NewBlockFlag
|
||||||
|
}
|
||||||
|
if client.AppOpts.TargetToolbar != nil {
|
||||||
|
target.Toolbar = client.AppOpts.TargetToolbar
|
||||||
|
}
|
||||||
|
if target.NewBlock && target.Toolbar != nil {
|
||||||
|
return fmt.Errorf("cannot specify both new block and toolbar target")
|
||||||
|
}
|
||||||
|
err = client.CreateVDomContext(target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -85,6 +85,7 @@ const (
|
|||||||
MetaKey_TermLocalShellOpts = "term:localshellopts"
|
MetaKey_TermLocalShellOpts = "term:localshellopts"
|
||||||
MetaKey_TermScrollback = "term:scrollback"
|
MetaKey_TermScrollback = "term:scrollback"
|
||||||
MetaKey_TermVDomSubBlockId = "term:vdomblockid"
|
MetaKey_TermVDomSubBlockId = "term:vdomblockid"
|
||||||
|
MetaKey_TermVDomToolbarBlockId = "term:vdomtoolbarblockid"
|
||||||
|
|
||||||
MetaKey_VDomClear = "vdom:*"
|
MetaKey_VDomClear = "vdom:*"
|
||||||
MetaKey_VDomInitialized = "vdom:initialized"
|
MetaKey_VDomInitialized = "vdom:initialized"
|
||||||
|
@ -86,6 +86,7 @@ type MetaTSType struct {
|
|||||||
TermLocalShellOpts []string `json:"term:localshellopts,omitempty"` // matches settings
|
TermLocalShellOpts []string `json:"term:localshellopts,omitempty"` // matches settings
|
||||||
TermScrollback *int `json:"term:scrollback,omitempty"`
|
TermScrollback *int `json:"term:scrollback,omitempty"`
|
||||||
TermVDomSubBlockId string `json:"term:vdomblockid,omitempty"`
|
TermVDomSubBlockId string `json:"term:vdomblockid,omitempty"`
|
||||||
|
TermVDomToolbarBlockId string `json:"term:vdomtoolbarblockid,omitempty"`
|
||||||
|
|
||||||
VDomClear bool `json:"vdom:*,omitempty"`
|
VDomClear bool `json:"vdom:*,omitempty"`
|
||||||
VDomInitialized bool `json:"vdom:initialized,omitempty"`
|
VDomInitialized bool `json:"vdom:initialized,omitempty"`
|
||||||
|
Loading…
Reference in New Issue
Block a user