mirror of
https://github.com/wavetermdev/backup.git
synced 2026-08-05 13:57:07 -07:00
New layout model (#210)
This PR is a large refactoring of the layout code to move as much of the layout state logic as possible into a unified model class, with atoms and derived atoms to notify the display logic of changes. It also fixes some latent bugs in the node resize code, significantly speeds up response times for resizing and dragging, and sets us up to fully replace the React-DnD library in the future.
This commit is contained in:
+25
-32
@@ -1,33 +1,31 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { useWaveObjectValue } from "@/app/store/wos";
|
||||
import { Workspace } from "@/app/workspace/workspace";
|
||||
import {
|
||||
LayoutTreeActionType,
|
||||
LayoutTreeDeleteNodeAction,
|
||||
deleteLayoutModelForTab,
|
||||
getLayoutModelForTab,
|
||||
} from "@/layout/index";
|
||||
import { ContextMenuModel } from "@/store/contextmenu";
|
||||
import { PLATFORM, WOS, atoms, globalStore, setBlockFocus } from "@/store/global";
|
||||
import * as services from "@/store/services";
|
||||
import { getWebServerEndpoint } from "@/util/endpoints";
|
||||
import * as keyutil from "@/util/keyutil";
|
||||
import * as layoututil from "@/util/layoututil";
|
||||
import * as util from "@/util/util";
|
||||
import clsx from "clsx";
|
||||
import Color from "color";
|
||||
import * as csstree from "css-tree";
|
||||
import {
|
||||
deleteLayoutStateAtomForTab,
|
||||
getLayoutStateAtomForTab,
|
||||
globalLayoutTransformsMap,
|
||||
} from "frontend/layout/lib/layoutAtom";
|
||||
import * as jotai from "jotai";
|
||||
import "overlayscrollbars/overlayscrollbars.css";
|
||||
import * as React from "react";
|
||||
import { DndProvider } from "react-dnd";
|
||||
import { HTML5Backend } from "react-dnd-html5-backend";
|
||||
import { CenteredDiv } from "./element/quickelems";
|
||||
|
||||
import { useWaveObjectValue } from "@/app/store/wos";
|
||||
import { LayoutTreeActionType, LayoutTreeDeleteNodeAction } from "@/layout/index";
|
||||
import { layoutTreeStateReducer } from "@/layout/lib/layoutState";
|
||||
import { getWebServerEndpoint } from "@/util/endpoints";
|
||||
import clsx from "clsx";
|
||||
import Color from "color";
|
||||
import "overlayscrollbars/overlayscrollbars.css";
|
||||
import "./app.less";
|
||||
import { CenteredDiv } from "./element/quickelems";
|
||||
|
||||
const App = () => {
|
||||
let Provider = jotai.Provider;
|
||||
@@ -173,15 +171,15 @@ function findBlockAtPoint(m: Map<string, Bounds>, p: Point): string {
|
||||
function switchBlockIdx(index: number) {
|
||||
const tabId = globalStore.get(atoms.activeTabId);
|
||||
const tabAtom = WOS.getWaveObjectAtom<Tab>(WOS.makeORef("tab", tabId));
|
||||
const layoutTreeState = globalStore.get(getLayoutStateAtomForTab(tabId, tabAtom));
|
||||
if (layoutTreeState?.leafs == null) {
|
||||
const layoutModel = getLayoutModelForTab(tabAtom);
|
||||
if (layoutModel?.leafs == null) {
|
||||
return;
|
||||
}
|
||||
const newLeafIdx = index - 1;
|
||||
if (newLeafIdx < 0 || newLeafIdx >= layoutTreeState.leafs.length) {
|
||||
if (newLeafIdx < 0 || newLeafIdx >= layoutModel.leafs.length) {
|
||||
return;
|
||||
}
|
||||
const leaf = layoutTreeState.leafs[newLeafIdx];
|
||||
const leaf = layoutModel.leafs[newLeafIdx];
|
||||
if (leaf?.data?.blockId == null) {
|
||||
return;
|
||||
}
|
||||
@@ -194,26 +192,22 @@ function switchBlock(tabId: string, offsetX: number, offsetY: number) {
|
||||
return;
|
||||
}
|
||||
const tabAtom = WOS.getWaveObjectAtom<Tab>(WOS.makeORef("tab", tabId));
|
||||
const transforms = globalLayoutTransformsMap.get(tabId);
|
||||
if (transforms == null) {
|
||||
return;
|
||||
}
|
||||
const layoutTreeState = globalStore.get(getLayoutStateAtomForTab(tabId, tabAtom));
|
||||
const layoutModel = getLayoutModelForTab(tabAtom);
|
||||
const curBlockId = globalStore.get(atoms.waveWindow)?.activeblockid;
|
||||
const curBlockLeafId = layoututil.findLeafIdFromBlockId(layoutTreeState, curBlockId);
|
||||
const curBlockLeafId = layoututil.findLeafIdFromBlockId(layoutModel, curBlockId);
|
||||
if (curBlockLeafId == null) {
|
||||
return;
|
||||
}
|
||||
const blockPos = readBoundsFromTransform(transforms[curBlockLeafId]);
|
||||
const blockPos = readBoundsFromTransform(layoutModel.getNodeTransformById(curBlockLeafId));
|
||||
if (blockPos == null) {
|
||||
return;
|
||||
}
|
||||
var blockPositions: Map<string, Bounds> = new Map();
|
||||
for (let leaf of layoutTreeState.leafs) {
|
||||
for (const leaf of layoutModel.leafs) {
|
||||
if (leaf.id == curBlockLeafId) {
|
||||
continue;
|
||||
}
|
||||
const pos = readBoundsFromTransform(transforms[leaf.id]);
|
||||
const pos = readBoundsFromTransform(layoutModel.getNodeTransform(leaf));
|
||||
if (pos != null) {
|
||||
blockPositions.set(leaf.data.blockId, pos);
|
||||
}
|
||||
@@ -341,7 +335,7 @@ function genericClose(tabId: string) {
|
||||
if (tabData.blockids == null || tabData.blockids.length == 0) {
|
||||
// close tab
|
||||
services.WindowService.CloseTab(tabId);
|
||||
deleteLayoutStateAtomForTab(tabId);
|
||||
deleteLayoutModelForTab(tabId);
|
||||
return;
|
||||
}
|
||||
// close block
|
||||
@@ -349,14 +343,13 @@ function genericClose(tabId: string) {
|
||||
if (activeBlockId == null) {
|
||||
return;
|
||||
}
|
||||
const layoutStateAtom = getLayoutStateAtomForTab(tabId, tabAtom);
|
||||
const layoutTreeState = globalStore.get(layoutStateAtom);
|
||||
const curBlockLeafId = layoututil.findLeafIdFromBlockId(layoutTreeState, activeBlockId);
|
||||
const layoutModel = getLayoutModelForTab(tabAtom);
|
||||
const curBlockLeafId = layoututil.findLeafIdFromBlockId(layoutModel, activeBlockId);
|
||||
const deleteAction: LayoutTreeDeleteNodeAction = {
|
||||
type: LayoutTreeActionType.DeleteNode,
|
||||
nodeId: curBlockLeafId,
|
||||
};
|
||||
globalStore.set(layoutStateAtom, layoutTreeStateReducer(layoutTreeState, deleteAction));
|
||||
layoutModel.treeReducer(deleteAction);
|
||||
services.ObjectService.DeleteBlock(activeBlockId);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,10 +7,8 @@ import { ContextMenuModel } from "@/app/store/contextmenu";
|
||||
import { atoms, globalStore, useBlockAtom, WOS } from "@/app/store/global";
|
||||
import * as services from "@/app/store/services";
|
||||
import { MagnifyIcon } from "@/element/magnify";
|
||||
import { LayoutTreeState } from "@/layout/index";
|
||||
import { getLayoutStateAtomForTab } from "@/layout/lib/layoutAtom";
|
||||
import { useLayoutModel } from "@/layout/index";
|
||||
import { adaptFromReactOrNativeKeyEvent, checkKeyPressed } from "@/util/keyutil";
|
||||
import { isBlockMagnified } from "@/util/layoututil";
|
||||
import * as util from "@/util/util";
|
||||
import clsx from "clsx";
|
||||
import * as jotai from "jotai";
|
||||
@@ -73,21 +71,15 @@ function getViewIconElem(viewIconUnion: string | HeaderIconButton, blockData: Bl
|
||||
}
|
||||
}
|
||||
|
||||
const OptMagnifyButton = React.memo(
|
||||
({ blockData, layoutModel }: { blockData: Block; layoutModel: LayoutComponentModel }) => {
|
||||
const tabId = globalStore.get(atoms.activeTabId);
|
||||
const tabAtom = WOS.getWaveObjectAtom<Tab>(WOS.makeORef("tab", tabId));
|
||||
const layoutTreeState = util.useAtomValueSafe(getLayoutStateAtomForTab(tabId, tabAtom));
|
||||
const isMagnified = isBlockMagnified(layoutTreeState, blockData.oid);
|
||||
const magnifyDecl: HeaderIconButton = {
|
||||
elemtype: "iconbutton",
|
||||
icon: <MagnifyIcon enabled={isMagnified} />,
|
||||
title: isMagnified ? "Minimize" : "Magnify",
|
||||
click: layoutModel?.onMagnifyToggle,
|
||||
};
|
||||
return <IconButton key="magnify" decl={magnifyDecl} className="block-frame-magnify" />;
|
||||
}
|
||||
);
|
||||
const OptMagnifyButton = React.memo(({ layoutCompModel }: { layoutCompModel: LayoutComponentModel }) => {
|
||||
const magnifyDecl: HeaderIconButton = {
|
||||
elemtype: "iconbutton",
|
||||
icon: <MagnifyIcon enabled={layoutCompModel?.isMagnified} />,
|
||||
title: layoutCompModel?.isMagnified ? "Minimize" : "Magnify",
|
||||
click: layoutCompModel?.onMagnifyToggle,
|
||||
};
|
||||
return <IconButton key="magnify" decl={magnifyDecl} className="block-frame-magnify" />;
|
||||
});
|
||||
|
||||
function computeEndIcons(blockData: Block, viewModel: ViewModel, layoutModel: LayoutComponentModel): JSX.Element[] {
|
||||
const endIconsElem: JSX.Element[] = [];
|
||||
@@ -104,7 +96,7 @@ function computeEndIcons(blockData: Block, viewModel: ViewModel, layoutModel: La
|
||||
handleHeaderContextMenu(e, blockData, viewModel, layoutModel?.onMagnifyToggle, layoutModel?.onClose),
|
||||
};
|
||||
endIconsElem.push(<IconButton key="settings" decl={settingsDecl} className="block-frame-settings" />);
|
||||
endIconsElem.push(<OptMagnifyButton key="unmagnify" blockData={blockData} layoutModel={layoutModel} />);
|
||||
endIconsElem.push(<OptMagnifyButton key="unmagnify" layoutCompModel={layoutModel} />);
|
||||
const closeDecl: HeaderIconButton = {
|
||||
elemtype: "iconbutton",
|
||||
icon: "xmark-large",
|
||||
@@ -214,12 +206,9 @@ function renderHeaderElements(headerTextUnion: HeaderElem[]): JSX.Element[] {
|
||||
function BlockNum({ blockId }: { blockId: string }) {
|
||||
const tabId = jotai.useAtomValue(atoms.activeTabId);
|
||||
const tabAtom = WOS.getWaveObjectAtom<Tab>(WOS.makeORef("tab", tabId));
|
||||
const layoutTreeState: LayoutTreeState<TabLayoutData> = globalStore.get(getLayoutStateAtomForTab(tabId, tabAtom));
|
||||
if (!layoutTreeState || !layoutTreeState.leafs) {
|
||||
return null;
|
||||
}
|
||||
for (let idx = 0; idx < layoutTreeState.leafs.length; idx++) {
|
||||
const leaf = layoutTreeState.leafs[idx];
|
||||
const layoutModel = useLayoutModel(tabAtom);
|
||||
for (let idx = 0; idx < layoutModel.leafs.length; idx++) {
|
||||
const leaf = layoutModel.leafs[idx];
|
||||
if (leaf?.data?.blockId == blockId) {
|
||||
return String(idx + 1);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ export interface LayoutComponentModel {
|
||||
disablePointerEvents: boolean;
|
||||
onClose?: () => void;
|
||||
onMagnifyToggle?: () => void;
|
||||
isMagnified: boolean;
|
||||
dragHandleRef?: React.RefObject<HTMLDivElement>;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { handleIncomingRpcMessage } from "@/app/store/wshrpc";
|
||||
import {
|
||||
LayoutTreeAction,
|
||||
getLayoutModelForTabById,
|
||||
LayoutTreeActionType,
|
||||
LayoutTreeInsertNodeAction,
|
||||
LayoutTreeInsertNodeAtIndexAction,
|
||||
newLayoutNode,
|
||||
} from "frontend/layout/index";
|
||||
import { getLayoutStateAtomForTab } from "frontend/layout/lib/layoutAtom";
|
||||
import { layoutTreeStateReducer } from "frontend/layout/lib/layoutState";
|
||||
|
||||
import { handleIncomingRpcMessage } from "@/app/store/wshrpc";
|
||||
import { LayoutTreeInsertNodeAtIndexAction } from "@/layout/lib/model";
|
||||
import { getWSServerEndpoint, getWebServerEndpoint } from "@/util/endpoints";
|
||||
} from "@/layout/index";
|
||||
import { getWebServerEndpoint, getWSServerEndpoint } from "@/util/endpoints";
|
||||
import * as layoututil from "@/util/layoututil";
|
||||
import { produce } from "immer";
|
||||
import * as jotai from "jotai";
|
||||
@@ -261,29 +258,26 @@ function handleWSEventMessage(msg: WSEventType) {
|
||||
}
|
||||
if (msg.eventtype == "layoutaction") {
|
||||
const layoutAction: WSLayoutActionData = msg.data;
|
||||
const tabId = layoutAction.tabid;
|
||||
const layoutModel = getLayoutModelForTabById(tabId);
|
||||
switch (layoutAction.actiontype) {
|
||||
case LayoutTreeActionType.InsertNode: {
|
||||
const insertNodeAction: LayoutTreeInsertNodeAction<TabLayoutData> = {
|
||||
const insertNodeAction: LayoutTreeInsertNodeAction = {
|
||||
type: LayoutTreeActionType.InsertNode,
|
||||
node: newLayoutNode<TabLayoutData>(undefined, undefined, undefined, {
|
||||
node: newLayoutNode(undefined, undefined, undefined, {
|
||||
blockId: layoutAction.blockid,
|
||||
}),
|
||||
};
|
||||
runLayoutAction(layoutAction.tabid, insertNodeAction);
|
||||
layoutModel.treeReducer(insertNodeAction);
|
||||
break;
|
||||
}
|
||||
case LayoutTreeActionType.DeleteNode: {
|
||||
const layoutStateAtom = getLayoutStateAtomForTab(
|
||||
layoutAction.tabid,
|
||||
WOS.getWaveObjectAtom<Tab>(WOS.makeORef("tab", layoutAction.tabid))
|
||||
);
|
||||
const curState = globalStore.get(layoutStateAtom);
|
||||
const leafId = layoututil.findLeafIdFromBlockId(curState, layoutAction.blockid);
|
||||
const leafId = layoututil.findLeafIdFromBlockId(layoutModel, layoutAction.blockid);
|
||||
const deleteNodeAction = {
|
||||
type: LayoutTreeActionType.DeleteNode,
|
||||
nodeId: leafId,
|
||||
};
|
||||
runLayoutAction(layoutAction.tabid, deleteNodeAction);
|
||||
layoutModel.treeReducer(deleteNodeAction);
|
||||
break;
|
||||
}
|
||||
case LayoutTreeActionType.InsertNodeAtIndex: {
|
||||
@@ -291,14 +285,14 @@ function handleWSEventMessage(msg: WSEventType) {
|
||||
console.error("Cannot apply eventbus layout action InsertNodeAtIndex, indexarr field is missing.");
|
||||
break;
|
||||
}
|
||||
const insertAction: LayoutTreeInsertNodeAtIndexAction<TabLayoutData> = {
|
||||
const insertAction: LayoutTreeInsertNodeAtIndexAction = {
|
||||
type: LayoutTreeActionType.InsertNodeAtIndex,
|
||||
node: newLayoutNode<TabLayoutData>(undefined, layoutAction.nodesize, undefined, {
|
||||
node: newLayoutNode(undefined, layoutAction.nodesize, undefined, {
|
||||
blockId: layoutAction.blockid,
|
||||
}),
|
||||
indexArr: layoutAction.indexarr,
|
||||
};
|
||||
runLayoutAction(layoutAction.tabid, insertAction);
|
||||
layoutModel.treeReducer(insertAction);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -355,21 +349,16 @@ function getApi(): ElectronApi {
|
||||
return (window as any).api;
|
||||
}
|
||||
|
||||
function runLayoutAction(tabId: string, action: LayoutTreeAction) {
|
||||
const layoutStateAtom = getLayoutStateAtomForTab(tabId, WOS.getWaveObjectAtom<Tab>(WOS.makeORef("tab", tabId)));
|
||||
const curState = globalStore.get(layoutStateAtom);
|
||||
globalStore.set(layoutStateAtom, layoutTreeStateReducer(curState, action));
|
||||
}
|
||||
|
||||
async function createBlock(blockDef: BlockDef) {
|
||||
const rtOpts: RuntimeOpts = { termsize: { rows: 25, cols: 80 } };
|
||||
const blockId = await services.ObjectService.CreateBlock(blockDef, rtOpts);
|
||||
const insertNodeAction: LayoutTreeInsertNodeAction<TabLayoutData> = {
|
||||
const insertNodeAction: LayoutTreeInsertNodeAction = {
|
||||
type: LayoutTreeActionType.InsertNode,
|
||||
node: newLayoutNode<TabLayoutData>(undefined, undefined, undefined, { blockId }),
|
||||
node: newLayoutNode(undefined, undefined, undefined, { blockId }),
|
||||
};
|
||||
const activeTabId = globalStore.get(atoms.uiContext).activetabid;
|
||||
runLayoutAction(activeTabId, insertNodeAction);
|
||||
const layoutModel = getLayoutModelForTabById(activeTabId);
|
||||
layoutModel.treeReducer(insertNodeAction);
|
||||
}
|
||||
|
||||
// when file is not found, returns {data: null, fileInfo: null}
|
||||
@@ -450,8 +439,6 @@ async function openLink(uri: string) {
|
||||
}
|
||||
|
||||
export {
|
||||
PLATFORM,
|
||||
WOS,
|
||||
atoms,
|
||||
createBlock,
|
||||
fetchWaveFile,
|
||||
@@ -466,10 +453,12 @@ export {
|
||||
initWS,
|
||||
isDev,
|
||||
openLink,
|
||||
PLATFORM,
|
||||
sendWSCommand,
|
||||
setBlockFocus,
|
||||
setPlatform,
|
||||
useBlockAtom,
|
||||
useBlockCache,
|
||||
useSettingsAtom,
|
||||
WOS,
|
||||
};
|
||||
|
||||
@@ -24,8 +24,6 @@ type WaveObjectValue<T extends WaveObj> = {
|
||||
holdTime: number;
|
||||
};
|
||||
|
||||
type WritableWaveObjectAtom<T extends WaveObj> = jotai.WritableAtom<T, [value: T], void>;
|
||||
|
||||
function splitORef(oref: string): [string, string] {
|
||||
const parts = oref.split(":");
|
||||
if (parts.length != 2) {
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { WindowDrag } from "@/element/windowdrag";
|
||||
import { deleteLayoutModelForTab } from "@/layout/index";
|
||||
import { atoms, getApi, isDev } from "@/store/global";
|
||||
import * as services from "@/store/services";
|
||||
import { deleteLayoutStateAtomForTab } from "frontend/layout/lib/layoutAtom";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { OverlayScrollbars } from "overlayscrollbars";
|
||||
import React, { createRef, useCallback, useEffect, useRef, useState } from "react";
|
||||
@@ -140,8 +140,6 @@ const TabBar = React.memo(({ workspace }: TabBarProps) => {
|
||||
let newTabWidth = tabWidth;
|
||||
let newScrollable = scrollable;
|
||||
|
||||
console.log("spaceForTabs", spaceForTabs, minTotalTabWidth);
|
||||
|
||||
if (spaceForTabs < totalDefaultTabWidth && spaceForTabs > minTotalTabWidth) {
|
||||
newTabWidth = TAB_MIN_WIDTH;
|
||||
} else if (minTotalTabWidth > spaceForTabs) {
|
||||
@@ -467,7 +465,7 @@ const TabBar = React.memo(({ workspace }: TabBarProps) => {
|
||||
event?.stopPropagation();
|
||||
services.WindowService.CloseTab(tabId);
|
||||
tabsWrapperRef.current.style.setProperty("--tabs-wrapper-transition", "width 0.3s ease");
|
||||
deleteLayoutStateAtomForTab(tabId);
|
||||
deleteLayoutModelForTab(tabId);
|
||||
};
|
||||
|
||||
const handleTabLoaded = useCallback((tabId) => {
|
||||
|
||||
@@ -3,16 +3,13 @@
|
||||
|
||||
import { Block } from "@/app/block/block";
|
||||
import { LayoutComponentModel } from "@/app/block/blocktypes";
|
||||
import { CenteredDiv } from "@/element/quickelems";
|
||||
import { ContentRenderer, TileLayout } from "@/layout/index";
|
||||
import { getApi } from "@/store/global";
|
||||
import * as services from "@/store/services";
|
||||
import * as WOS from "@/store/wos";
|
||||
import * as React from "react";
|
||||
|
||||
import { CenteredDiv } from "@/element/quickelems";
|
||||
import { ContentRenderer } from "@/layout/lib/model";
|
||||
import { TileLayout } from "frontend/layout/index";
|
||||
import { getLayoutStateAtomForTab } from "frontend/layout/lib/layoutAtom";
|
||||
import { useAtomValue } from "jotai";
|
||||
import * as React from "react";
|
||||
import { useMemo } from "react";
|
||||
import "./tabcontent.less";
|
||||
|
||||
@@ -21,19 +18,19 @@ const TabContent = React.memo(({ tabId }: { tabId: string }) => {
|
||||
const loadingAtom = useMemo(() => WOS.getWaveObjectLoadingAtom(oref), [oref]);
|
||||
const tabLoading = useAtomValue(loadingAtom);
|
||||
const tabAtom = useMemo(() => WOS.getWaveObjectAtom<Tab>(oref), [oref]);
|
||||
const layoutStateAtom = useMemo(() => getLayoutStateAtomForTab(tabId, tabAtom), [tabAtom, tabId]);
|
||||
const tabData = useAtomValue(tabAtom);
|
||||
|
||||
const tileLayoutContents = useMemo(() => {
|
||||
const renderBlock: ContentRenderer<TabLayoutData> = (
|
||||
tabData: TabLayoutData,
|
||||
const renderBlock: ContentRenderer = (
|
||||
blockData: TabLayoutData,
|
||||
ready: boolean,
|
||||
isMagnified: boolean,
|
||||
disablePointerEvents: boolean,
|
||||
onMagnifyToggle: () => void,
|
||||
onClose: () => void,
|
||||
dragHandleRef: React.RefObject<HTMLDivElement>
|
||||
) => {
|
||||
if (!tabData.blockId || !ready) {
|
||||
if (!blockData.blockId || !ready) {
|
||||
return null;
|
||||
}
|
||||
const layoutModel: LayoutComponentModel = {
|
||||
@@ -41,11 +38,15 @@ const TabContent = React.memo(({ tabId }: { tabId: string }) => {
|
||||
onClose,
|
||||
onMagnifyToggle,
|
||||
dragHandleRef,
|
||||
isMagnified,
|
||||
};
|
||||
return <Block key={tabData.blockId} blockId={tabData.blockId} layoutModel={layoutModel} preview={false} />;
|
||||
return (
|
||||
<Block key={blockData.blockId} blockId={blockData.blockId} layoutModel={layoutModel} preview={false} />
|
||||
);
|
||||
};
|
||||
|
||||
function renderPreview(tabData: TabLayoutData) {
|
||||
if (!tabData) return;
|
||||
return <Block key={tabData.blockId} blockId={tabData.blockId} layoutModel={null} preview={true} />;
|
||||
}
|
||||
|
||||
@@ -59,7 +60,7 @@ const TabContent = React.memo(({ tabId }: { tabId: string }) => {
|
||||
tabId: tabId,
|
||||
onNodeDelete: onNodeDelete,
|
||||
};
|
||||
}, []);
|
||||
}, [tabId]);
|
||||
|
||||
if (tabLoading) {
|
||||
return (
|
||||
@@ -86,7 +87,7 @@ const TabContent = React.memo(({ tabId }: { tabId: string }) => {
|
||||
<TileLayout
|
||||
key={tabId}
|
||||
contents={tileLayoutContents}
|
||||
layoutTreeStateAtom={layoutStateAtom}
|
||||
tabAtom={tabAtom}
|
||||
getCursorPoint={getApi().getCursorPoint}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -45,8 +45,10 @@
|
||||
--zindex-elem-modal: 100;
|
||||
--zindex-window-drag: 100;
|
||||
--zindex-tab-name: 3;
|
||||
--zindex-layout-placeholder-container: 1;
|
||||
--zindex-layout-overlay-container: 2;
|
||||
--zindex-layout-display-container: 0;
|
||||
--zindex-layout-resize-handle: 1;
|
||||
--zindex-layout-placeholder-container: 2;
|
||||
--zindex-layout-overlay-container: 3;
|
||||
--zindex-block-mask-inner: 10;
|
||||
|
||||
// z-indexes in xterm.css
|
||||
|
||||
Reference in New Issue
Block a user