mirror of
https://github.com/wavetermdev/backup.git
synced 2026-08-05 13:57:07 -07:00
move connection switching to blockheader (#276)
This commit is contained in:
@@ -148,7 +148,7 @@
|
||||
font-weight: 400;
|
||||
color: var(--main-text-color);
|
||||
border-radius: 2px;
|
||||
padding-right: 6px;
|
||||
padding-right: 2px;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--highlight-bg-color);
|
||||
@@ -162,6 +162,7 @@
|
||||
.connection-name {
|
||||
flex: 1 100 auto;
|
||||
overflow: hidden;
|
||||
padding-right: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -116,6 +116,7 @@ const BlockFull = React.memo(({ nodeModel, viewModel }: FullBlockProps) => {
|
||||
counterInc("render-BlockFull");
|
||||
const focusElemRef = React.useRef<HTMLInputElement>(null);
|
||||
const blockRef = React.useRef<HTMLDivElement>(null);
|
||||
const contentRef = React.useRef<HTMLDivElement>(null);
|
||||
const [blockClicked, setBlockClicked] = React.useState(false);
|
||||
const [blockData] = WOS.useWaveObjectValue<Block>(WOS.makeORef("block", nodeModel.blockId));
|
||||
const [focusedChild, setFocusedChild] = React.useState(null);
|
||||
@@ -202,6 +203,7 @@ const BlockFull = React.memo(({ nodeModel, viewModel }: FullBlockProps) => {
|
||||
width: addlProps?.transform?.width,
|
||||
height: addlProps?.transform?.height,
|
||||
}}
|
||||
ref={contentRef}
|
||||
>
|
||||
<ErrorBoundary>
|
||||
<React.Suspense fallback={<CenteredDiv>Loading...</CenteredDiv>}>{viewElem}</React.Suspense>
|
||||
|
||||
@@ -10,11 +10,14 @@ import {
|
||||
Input,
|
||||
} from "@/app/block/blockutil";
|
||||
import { Button } from "@/app/element/button";
|
||||
import { TypeAheadModal } from "@/app/modals/typeaheadmodal";
|
||||
import { ContextMenuModel } from "@/app/store/contextmenu";
|
||||
import { atoms, globalStore, WOS } from "@/app/store/global";
|
||||
import * as services from "@/app/store/services";
|
||||
import { WshServer } from "@/app/store/wshserver";
|
||||
import { MagnifyIcon } from "@/element/magnify";
|
||||
import { NodeModel } from "@/layout/index";
|
||||
import * as keyutil from "@/util/keyutil";
|
||||
import { checkKeyPressed, keydownWrapper } from "@/util/keyutil";
|
||||
import * as util from "@/util/util";
|
||||
import clsx from "clsx";
|
||||
@@ -129,6 +132,7 @@ const BlockFrame_Header = ({ nodeModel, viewModel, preview }: BlockFrameProps) =
|
||||
const preIconButton = util.useAtomValueSafe(viewModel.preIconButton);
|
||||
const headerTextUnion = util.useAtomValueSafe(viewModel.viewText);
|
||||
const magnified = jotai.useAtomValue(nodeModel.isMagnified);
|
||||
const manageConnection = jotai.useAtomValue(viewModel.manageConnection);
|
||||
const dragHandleRef = preview ? null : nodeModel.dragHandleRef;
|
||||
|
||||
const onContextMenu = React.useCallback(
|
||||
@@ -163,6 +167,16 @@ const BlockFrame_Header = ({ nodeModel, viewModel, preview }: BlockFrameProps) =
|
||||
} else if (Array.isArray(headerTextUnion)) {
|
||||
headerTextElems.push(...renderHeaderElements(headerTextUnion, preview));
|
||||
}
|
||||
if (manageConnection) {
|
||||
const connButtonElem = (
|
||||
<ConnectionButton
|
||||
key={nodeModel.blockId}
|
||||
blockId={nodeModel.blockId}
|
||||
connection={blockData?.meta?.connection}
|
||||
/>
|
||||
);
|
||||
headerTextElems.unshift(connButtonElem);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="block-frame-default-header" ref={dragHandleRef} onContextMenu={onContextMenu}>
|
||||
@@ -174,6 +188,7 @@ const BlockFrame_Header = ({ nodeModel, viewModel, preview }: BlockFrameProps) =
|
||||
<div className="block-frame-blockid">[{nodeModel.blockId.substring(0, 8)}]</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="block-frame-textelems-wrapper">{headerTextElems}</div>
|
||||
<div className="block-frame-end-icons">{endIconsElem}</div>
|
||||
</div>
|
||||
@@ -193,8 +208,6 @@ const HeaderTextElem = React.memo(({ elem, preview }: { elem: HeaderElem; previe
|
||||
{elem.text}
|
||||
</Button>
|
||||
);
|
||||
} else if (elem.elemtype == "connectionbutton") {
|
||||
return <ConnectionButton decl={elem} />;
|
||||
} else if (elem.elemtype == "div") {
|
||||
return (
|
||||
<div
|
||||
@@ -294,6 +307,13 @@ const BlockFrame_Default_Component = (props: BlockFrameProps) => {
|
||||
onKeyDown={keydownWrapper(handleKeyDown)}
|
||||
>
|
||||
<BlockMask nodeModel={nodeModel} />
|
||||
{preview ? null : (
|
||||
<ChangeConnectionBlockModal
|
||||
blockId={nodeModel.blockId}
|
||||
viewModel={viewModel}
|
||||
blockRef={blockModel?.blockRef}
|
||||
/>
|
||||
)}
|
||||
<div className="block-frame-default-inner" style={innerStyle}>
|
||||
<BlockFrame_Header {...props} />
|
||||
{preview ? previewElem : children}
|
||||
@@ -302,6 +322,70 @@ const BlockFrame_Default_Component = (props: BlockFrameProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
const ChangeConnectionBlockModal = React.memo(
|
||||
({
|
||||
blockId,
|
||||
viewModel,
|
||||
blockRef,
|
||||
}: {
|
||||
blockId: string;
|
||||
viewModel: ViewModel;
|
||||
blockRef: React.RefObject<HTMLDivElement>;
|
||||
}) => {
|
||||
const typeAhead = jotai.useAtomValue(atoms.typeAheadModalAtom);
|
||||
const [connSelected, setConnSelected] = React.useState("");
|
||||
const changeConnection = React.useCallback(
|
||||
async (connName: string) => {
|
||||
await WshServer.SetMetaCommand({
|
||||
oref: WOS.makeORef("block", blockId),
|
||||
meta: { connection: connName },
|
||||
});
|
||||
await WshServer.ControllerRestartCommand({ blockid: blockId });
|
||||
},
|
||||
[blockId]
|
||||
);
|
||||
const handleTypeAheadKeyDown = React.useCallback(
|
||||
(waveEvent: WaveKeyboardEvent): boolean => {
|
||||
if (keyutil.checkKeyPressed(waveEvent, "Enter")) {
|
||||
changeConnection(connSelected);
|
||||
globalStore.set(atoms.typeAheadModalAtom, {
|
||||
...(typeAhead as TypeAheadModalType),
|
||||
[blockId]: false,
|
||||
});
|
||||
setConnSelected("");
|
||||
return true;
|
||||
}
|
||||
if (keyutil.checkKeyPressed(waveEvent, "Escape")) {
|
||||
globalStore.set(atoms.typeAheadModalAtom, {
|
||||
...(typeAhead as TypeAheadModalType),
|
||||
[blockId]: false,
|
||||
});
|
||||
setConnSelected("");
|
||||
viewModel.giveFocus();
|
||||
return true;
|
||||
}
|
||||
},
|
||||
[typeAhead, viewModel, blockId, connSelected]
|
||||
);
|
||||
if (!typeAhead[blockId]) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<TypeAheadModal
|
||||
anchor={blockRef}
|
||||
suggestions={[]}
|
||||
onSelect={(selected: string) => {
|
||||
changeConnection(selected);
|
||||
}}
|
||||
onKeyDown={(e) => keyutil.keydownWrapper(handleTypeAheadKeyDown)(e)}
|
||||
onChange={(current: string) => setConnSelected(current)}
|
||||
value={connSelected}
|
||||
label="Switch Connection"
|
||||
/>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
const BlockFrame_Default = React.memo(BlockFrame_Default_Component) as typeof BlockFrame_Default_Component;
|
||||
|
||||
const BlockFrame = React.memo((props: BlockFrameProps) => {
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { useLongClick } from "@/app/hook/useLongClick";
|
||||
import { atoms, getConnStatusAtom } from "@/app/store/global";
|
||||
import * as util from "@/util/util";
|
||||
import clsx from "clsx";
|
||||
import * as jotai from "jotai";
|
||||
import * as React from "react";
|
||||
|
||||
export const colorRegex = /^((#[0-9a-f]{6,8})|([a-z]+))$/;
|
||||
@@ -168,30 +170,60 @@ export const IconButton = React.memo(({ decl, className }: { decl: HeaderIconBut
|
||||
);
|
||||
});
|
||||
|
||||
export const ConnectionButton = React.memo(({ decl }: { decl: ConnectionButton }) => {
|
||||
export const ConnectionButton = React.memo(({ blockId, connection }: { blockId: string; connection: string }) => {
|
||||
const [typeAhead, setTypeAhead] = jotai.useAtom(atoms.typeAheadModalAtom);
|
||||
const buttonRef = React.useRef<HTMLDivElement>(null);
|
||||
const isLocal = connection == "" || connection == "local";
|
||||
const connStatusAtom = getConnStatusAtom(connection);
|
||||
const connStatus = jotai.useAtomValue(connStatusAtom);
|
||||
const showDisconnectedSlash = !isLocal && !connStatus?.connected;
|
||||
let connIconElem: React.ReactNode = null;
|
||||
let color = "#53b4ea";
|
||||
const clickHandler = function () {
|
||||
setTypeAhead({
|
||||
...typeAhead,
|
||||
[blockId]: true,
|
||||
});
|
||||
};
|
||||
let titleText = null;
|
||||
if (isLocal) {
|
||||
color = "var(--grey-text-color)";
|
||||
titleText = "Connected to Local Machine";
|
||||
connIconElem = (
|
||||
<i
|
||||
className={clsx(util.makeIconClass("laptop", false), "fa-stack-1x")}
|
||||
style={{ color: color, marginRight: 2 }}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
titleText = "Connected to " + connection;
|
||||
if (!connStatus?.connected) {
|
||||
color = "var(--grey-text-color)";
|
||||
titleText = "Disconnected from " + connection;
|
||||
}
|
||||
connIconElem = (
|
||||
<i
|
||||
className={clsx(util.makeIconClass("arrow-right-arrow-left", false), "fa-stack-1x")}
|
||||
style={{ color: color, marginRight: 2 }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div ref={buttonRef} className={clsx("connection-button")} onClick={decl.onClick}>
|
||||
<div ref={buttonRef} className={clsx("connection-button")} onClick={clickHandler} title={titleText}>
|
||||
<span className="fa-stack connection-icon-box">
|
||||
{typeof decl.icon === "string" ? (
|
||||
<i
|
||||
className={clsx(util.makeIconClass(decl.icon, true), "fa-stack-1x")}
|
||||
style={{ color: decl.iconColor, marginRight: "2px" }}
|
||||
/>
|
||||
) : (
|
||||
decl.icon
|
||||
)}
|
||||
{connIconElem}
|
||||
<i
|
||||
className="fa-slash fa-solid fa-stack-1x"
|
||||
style={{
|
||||
color: decl.iconColor,
|
||||
color: color,
|
||||
marginRight: "2px",
|
||||
textShadow: "0 1px black, 0 1.5px black",
|
||||
opacity: decl.connected ? 0 : 1,
|
||||
opacity: showDisconnectedSlash ? 1 : 0,
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
<div className="connection-name">{decl.text}</div>
|
||||
{isLocal ? null : <div className="connection-name">{connection}</div>}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user