diff --git a/cmd/wsh/cmd/wshcmd-edit.go b/cmd/wsh/cmd/wshcmd-edit.go
index 4640cf9f..bdb05174 100644
--- a/cmd/wsh/cmd/wshcmd-edit.go
+++ b/cmd/wsh/cmd/wshcmd-edit.go
@@ -14,6 +14,8 @@ import (
"github.com/wavetermdev/thenextwave/pkg/wshrpc/wshclient"
)
+var editMagnified bool
+
var editCmd = &cobra.Command{
Use: "edit",
Short: "edit a file",
@@ -23,6 +25,7 @@ var editCmd = &cobra.Command{
}
func init() {
+ editCmd.Flags().BoolVarP(&editMagnified, "magnified", "m", false, "open view in magnified mode")
rootCmd.AddCommand(editCmd)
}
@@ -35,6 +38,7 @@ func editRun(cmd *cobra.Command, args []string) {
waveobj.MetaKey_File: fileArg,
},
},
+ Magnified: editMagnified,
}
if RpcContext.Conn != "" {
wshCmd.BlockDef.Meta[waveobj.MetaKey_Connection] = RpcContext.Conn
diff --git a/cmd/wsh/cmd/wshcmd-term.go b/cmd/wsh/cmd/wshcmd-term.go
index 52371167..066e0e94 100644
--- a/cmd/wsh/cmd/wshcmd-term.go
+++ b/cmd/wsh/cmd/wshcmd-term.go
@@ -14,6 +14,8 @@ import (
"github.com/wavetermdev/thenextwave/pkg/wshrpc/wshclient"
)
+var termMagnified bool
+
var termCmd = &cobra.Command{
Use: "term",
Short: "open a terminal in directory",
@@ -23,6 +25,7 @@ var termCmd = &cobra.Command{
}
func init() {
+ termCmd.Flags().BoolVarP(&termMagnified, "magnified", "m", false, "open view in magnified mode")
rootCmd.AddCommand(termCmd)
}
@@ -53,6 +56,7 @@ func termRun(cmd *cobra.Command, args []string) {
waveobj.MetaKey_Controller: "shell",
},
},
+ Magnified: termMagnified,
}
if RpcContext.Conn != "" {
createBlockData.BlockDef.Meta[waveobj.MetaKey_Connection] = RpcContext.Conn
diff --git a/cmd/wsh/cmd/wshcmd-view.go b/cmd/wsh/cmd/wshcmd-view.go
index 2e7192b7..2ac6f850 100644
--- a/cmd/wsh/cmd/wshcmd-view.go
+++ b/cmd/wsh/cmd/wshcmd-view.go
@@ -15,6 +15,7 @@ import (
)
var viewNewBlock bool
+var viewMagnified bool
var viewCmd = &cobra.Command{
Use: "view",
@@ -26,6 +27,7 @@ var viewCmd = &cobra.Command{
func init() {
viewCmd.Flags().BoolVarP(&viewNewBlock, "newblock", "n", false, "open view in a new block")
+ viewCmd.Flags().BoolVarP(&viewMagnified, "magnified", "m", false, "open view in magnified mode")
rootCmd.AddCommand(viewCmd)
}
@@ -41,6 +43,7 @@ func viewRun(cmd *cobra.Command, args []string) {
waveobj.MetaKey_Url: fileArg,
},
},
+ Magnified: viewMagnified,
}
} else {
absFile, err := filepath.Abs(fileArg)
@@ -64,6 +67,7 @@ func viewRun(cmd *cobra.Command, args []string) {
waveobj.MetaKey_File: absFile,
},
},
+ Magnified: viewMagnified,
}
if conn != "" {
wshCmd.BlockDef.Meta[waveobj.MetaKey_Connection] = conn
diff --git a/frontend/app/store/global.ts b/frontend/app/store/global.ts
index 23e4f761..697ac94d 100644
--- a/frontend/app/store/global.ts
+++ b/frontend/app/store/global.ts
@@ -277,6 +277,7 @@ function handleWSEventMessage(msg: WSEventType) {
node: newLayoutNode(undefined, undefined, undefined, {
blockId: layoutAction.blockid,
}),
+ magnified: layoutAction.magnified,
};
layoutModel.treeReducer(insertNodeAction);
break;
@@ -304,6 +305,7 @@ function handleWSEventMessage(msg: WSEventType) {
blockId: layoutAction.blockid,
}),
indexArr: layoutAction.indexarr,
+ magnified: layoutAction.magnified,
};
layoutModel.treeReducer(insertAction);
break;
diff --git a/frontend/layout/lib/TileLayout.tsx b/frontend/layout/lib/TileLayout.tsx
index d0c273af..fa27edbe 100644
--- a/frontend/layout/lib/TileLayout.tsx
+++ b/frontend/layout/lib/TileLayout.tsx
@@ -175,7 +175,6 @@ const DisplayNode = ({ layoutModel, layoutNode, contents }: DisplayNodeProps) =>
const addlProps = useLayoutNode(layoutModel, layoutNode);
const activeDrag = useAtomValue(layoutModel.activeDrag);
const globalReady = useAtomValue(layoutModel.ready);
- const layoutGeneration = useAtomValue(layoutModel.generationAtom);
const devicePixelRatio = useDevicePixelRatio();
@@ -183,12 +182,12 @@ const DisplayNode = ({ layoutModel, layoutNode, contents }: DisplayNodeProps) =>
() => ({
type: dragItemType,
item: () => layoutNode,
- canDrag: () => !layoutModel?.treeState?.magnifiedNodeId,
+ canDrag: () => !addlProps?.isMagnifiedNode,
collect: (monitor) => ({
isDragging: monitor.isDragging(),
}),
}),
- [layoutNode, layoutGeneration]
+ [layoutNode, addlProps]
);
const [previewElementGeneration, setPreviewElementGeneration] = useState(0);
@@ -249,7 +248,7 @@ const DisplayNode = ({ layoutModel, layoutNode, contents }: DisplayNodeProps) =>
{contents.renderContent(
layoutNode.data,
globalReady,
- layoutNode.id === layoutModel.treeState.magnifiedNodeId,
+ addlProps?.isMagnifiedNode ?? false,
activeDrag,
() => layoutModel.magnifyNodeToggle(layoutNode),
() => layoutModel.closeNode(layoutNode),
@@ -258,13 +257,13 @@ const DisplayNode = ({ layoutModel, layoutNode, contents }: DisplayNodeProps) =>
)
);
- }, [layoutNode, globalReady, layoutGeneration, activeDrag, addlProps]);
+ }, [layoutNode, globalReady, activeDrag, addlProps]);
return (
;
+ /**
+ * The currently magnified node.
+ */
+ magnifiedNodeId: string;
/**
* The last node to be magnified, other than the current magnified node, if set. This node should sit at a higher z-index than the others so that it floats above the other nodes as it returns to its original position.
*/
@@ -314,6 +318,10 @@ export class LayoutModel {
}
if (stateChanged) {
console.log("state changed", this.treeState);
+ if (this.magnifiedNodeId !== this.treeState.magnifiedNodeId) {
+ this.lastMagnifiedNodeId = this.magnifiedNodeId;
+ this.magnifiedNodeId = this.treeState.magnifiedNodeId;
+ }
this.updateTree();
this.treeState.generation++;
this.setter(this.treeStateAtom, this.treeState);
@@ -393,7 +401,7 @@ export class LayoutModel {
leafs.push(node);
const addlProps = additionalPropsMap[node.id];
if (addlProps) {
- if (this.treeState.magnifiedNodeId === node.id) {
+ if (this.magnifiedNodeId === node.id) {
const boundingRect = getBoundingRect();
const transform = setTransform(
{
@@ -405,6 +413,7 @@ export class LayoutModel {
true
);
addlProps.transform = transform;
+ addlProps.isMagnifiedNode = true;
}
addlProps.isLastMagnifiedNode = this.lastMagnifiedNodeId === node.id;
}
@@ -578,12 +587,6 @@ export class LayoutModel {
nodeId: node.id,
};
- // If the node is already magnified, then it is being un-magnified and should be set as the last-magnified node to ensure it has a higher z-index as it transitions back to its original position.
- if (this.treeState.magnifiedNodeId === node.id) {
- console.log("new last-magnified-node", node.id);
- this.lastMagnifiedNodeId = node.id;
- }
-
this.treeReducer(action);
}
diff --git a/frontend/layout/lib/layoutModelHooks.ts b/frontend/layout/lib/layoutModelHooks.ts
index 5cdbb01a..bd2c236f 100644
--- a/frontend/layout/lib/layoutModelHooks.ts
+++ b/frontend/layout/lib/layoutModelHooks.ts
@@ -43,6 +43,8 @@ export function useLayoutModel(tabAtom: Atom): LayoutModel {
}
export function useTileLayout(tabAtom: Atom, tileContent: TileLayoutContents): LayoutModel {
+ // Use tab data to ensure we can reload if the tab is disposed and remade (such as during Hot Module Reloading)
+ useAtomValue(tabAtom);
const layoutModel = useLayoutModel(tabAtom);
useResizeObserver(layoutModel?.displayContainerRef, layoutModel?.onContainerResize);
useEffect(() => layoutModel.registerTileLayout(tileContent), [tileContent]);
diff --git a/frontend/layout/lib/layoutTree.ts b/frontend/layout/lib/layoutTree.ts
index b7963de1..be115b4d 100644
--- a/frontend/layout/lib/layoutTree.ts
+++ b/frontend/layout/lib/layoutTree.ts
@@ -5,7 +5,6 @@ import { lazy } from "@/util/util";
import {
addChildAt,
addIntermediateNode,
- balanceNode,
findInsertLocationFromIndexArr,
findNextInsertLocation,
findNode,
@@ -256,8 +255,6 @@ export function moveNode(layoutState: LayoutTreeState, action: LayoutTreeMoveNod
if (oldParent) {
removeChild(oldParent, node, startingIndex);
}
-
- layoutState.rootNode = balanceNode(layoutState.rootNode);
}
export function insertNode(layoutState: LayoutTreeState, action: LayoutTreeInsertNodeAction) {
@@ -266,12 +263,14 @@ export function insertNode(layoutState: LayoutTreeState, action: LayoutTreeInser
return;
}
if (!layoutState.rootNode) {
- layoutState.rootNode = balanceNode(action.node);
+ layoutState.rootNode = action.node;
return;
}
const insertLoc = findNextInsertLocation(layoutState.rootNode, 5);
addChildAt(insertLoc.node, insertLoc.index, action.node);
- layoutState.rootNode = balanceNode(layoutState.rootNode);
+ if (action.magnified) {
+ layoutState.magnifiedNodeId = action.node.id;
+ }
}
export function insertNodeAtIndex(layoutState: LayoutTreeState, action: LayoutTreeInsertNodeAtIndexAction) {
@@ -280,7 +279,7 @@ export function insertNodeAtIndex(layoutState: LayoutTreeState, action: LayoutTr
return;
}
if (!layoutState.rootNode) {
- layoutState.rootNode = balanceNode(action.node);
+ layoutState.rootNode = action.node;
return;
}
const insertLoc = findInsertLocationFromIndexArr(layoutState.rootNode, action.indexArr);
@@ -289,7 +288,9 @@ export function insertNodeAtIndex(layoutState: LayoutTreeState, action: LayoutTr
return;
}
addChildAt(insertLoc.node, insertLoc.index + 1, action.node);
- layoutState.rootNode = balanceNode(layoutState.rootNode);
+ if (action.magnified) {
+ layoutState.magnifiedNodeId = action.node.id;
+ }
}
export function swapNode(layoutState: LayoutTreeState, action: LayoutTreeSwapNodeAction) {
@@ -323,8 +324,6 @@ export function swapNode(layoutState: LayoutTreeState, action: LayoutTreeSwapNod
parentNode1.children[parentNode1Index] = node2;
parentNode2.children[parentNode2Index] = node1;
-
- layoutState.rootNode = balanceNode(layoutState.rootNode);
}
export function deleteNode(layoutState: LayoutTreeState, action: LayoutTreeDeleteNodeAction) {
@@ -349,7 +348,6 @@ export function deleteNode(layoutState: LayoutTreeState, action: LayoutTreeDelet
} else {
console.error("unable to delete node, not found in tree");
}
- layoutState.rootNode = balanceNode(layoutState.rootNode);
}
export function resizeNode(layoutState: LayoutTreeState, action: LayoutTreeResizeNodeAction) {
diff --git a/frontend/layout/lib/types.ts b/frontend/layout/lib/types.ts
index 01ec0e07..e18001e2 100644
--- a/frontend/layout/lib/types.ts
+++ b/frontend/layout/lib/types.ts
@@ -93,24 +93,30 @@ export interface LayoutTreeSwapNodeAction extends LayoutTreeAction {
node2Id: string;
}
+interface InsertNodeOperation {
+ /**
+ * The node to insert.
+ */
+ node: LayoutNode;
+ /**
+ * Whether the inserted node should be magnified.
+ */
+ magnified?: boolean;
+}
+
/**
* Action for inserting a new node to the layout tree.
*
*/
-export interface LayoutTreeInsertNodeAction extends LayoutTreeAction {
+export interface LayoutTreeInsertNodeAction extends LayoutTreeAction, InsertNodeOperation {
type: LayoutTreeActionType.InsertNode;
- node: LayoutNode;
}
/**
* Action for inserting a node into the layout tree at the specified index.
*/
-export interface LayoutTreeInsertNodeAtIndexAction extends LayoutTreeAction {
+export interface LayoutTreeInsertNodeAtIndexAction extends LayoutTreeAction, InsertNodeOperation {
type: LayoutTreeActionType.InsertNodeAtIndex;
- /**
- * The node to insert.
- */
- node: LayoutNode;
/**
* The array of indices to traverse when inserting the node.
* The last index is the index within the parent node where the node should be inserted.
@@ -274,5 +280,6 @@ export interface LayoutNodeAdditionalProps {
rect?: Dimensions;
pixelToSizeRatio?: number;
resizeHandles?: ResizeHandleProps[];
+ isMagnifiedNode?: boolean;
isLastMagnifiedNode?: boolean;
}
diff --git a/frontend/types/gotypes.d.ts b/frontend/types/gotypes.d.ts
index 2fd95895..df52f787 100644
--- a/frontend/types/gotypes.d.ts
+++ b/frontend/types/gotypes.d.ts
@@ -95,7 +95,8 @@ declare global {
type CommandCreateBlockData = {
tabid: string;
blockdef: BlockDef;
- rtopts: RuntimeOpts;
+ rtopts?: RuntimeOpts;
+ magnified?: boolean;
};
// wshrpc.CommandDeleteBlockData
@@ -522,6 +523,7 @@ declare global {
blockid: string;
nodesize?: number;
indexarr?: number[];
+ magnified?: boolean;
};
// webcmd.WSRpcCommand
diff --git a/pkg/eventbus/eventbus.go b/pkg/eventbus/eventbus.go
index 7c63a31e..6353aa80 100644
--- a/pkg/eventbus/eventbus.go
+++ b/pkg/eventbus/eventbus.go
@@ -62,6 +62,7 @@ type WSLayoutActionData struct {
BlockId string `json:"blockid"`
NodeSize uint `json:"nodesize,omitempty"`
IndexArr []int `json:"indexarr,omitempty"`
+ Magnified bool `json:"magnified,omitempty"`
}
var globalLock = &sync.Mutex{}
diff --git a/pkg/wshrpc/wshrpctypes.go b/pkg/wshrpc/wshrpctypes.go
index 875fb0e2..dcd7d7cb 100644
--- a/pkg/wshrpc/wshrpctypes.go
+++ b/pkg/wshrpc/wshrpctypes.go
@@ -185,9 +185,10 @@ type CommandResolveIdsRtnData struct {
}
type CommandCreateBlockData struct {
- TabId string `json:"tabid" wshcontext:"TabId"`
- BlockDef *waveobj.BlockDef `json:"blockdef"`
- RtOpts *waveobj.RuntimeOpts `json:"rtopts"`
+ TabId string `json:"tabid" wshcontext:"TabId"`
+ BlockDef *waveobj.BlockDef `json:"blockdef"`
+ RtOpts *waveobj.RuntimeOpts `json:"rtopts,omitempty"`
+ Magnified bool `json:"magnified,omitempty"`
}
type CommandBlockSetViewData struct {
diff --git a/pkg/wshrpc/wshserver/wshserver.go b/pkg/wshrpc/wshserver/wshserver.go
index 498ea3e1..392f4134 100644
--- a/pkg/wshrpc/wshserver/wshserver.go
+++ b/pkg/wshrpc/wshserver/wshserver.go
@@ -293,6 +293,7 @@ func (ws *WshServer) CreateBlockCommand(ctx context.Context, data wshrpc.Command
ActionType: "insert",
TabId: tabId,
BlockId: blockData.OID,
+ Magnified: data.Magnified,
},
})
return &waveobj.ORef{OType: waveobj.OType_Block, OID: blockData.OID}, nil