mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-03-11 13:23:06 +01:00
trap Shift:Cmd, and enable special blockmask action to show block indexes
This commit is contained in:
parent
6ebc2e44c3
commit
4f74b232e2
@ -332,20 +332,31 @@ function genericClose(tabId: string) {
|
||||
services.ObjectService.DeleteBlock(activeBlockId);
|
||||
}
|
||||
|
||||
const AppInner = () => {
|
||||
const client = jotai.useAtomValue(atoms.client);
|
||||
const windowData = jotai.useAtomValue(atoms.waveWindow);
|
||||
const simpleCmdShiftAtom = jotai.atom(false);
|
||||
|
||||
const AppKeyHandlers = () => {
|
||||
const tabId = jotai.useAtomValue(atoms.activeTabId);
|
||||
if (client == null || windowData == null) {
|
||||
return (
|
||||
<div className="mainapp">
|
||||
<AppBackground />
|
||||
<CenteredDiv>invalid configuration, client or window was not loaded</CenteredDiv>
|
||||
</div>
|
||||
);
|
||||
|
||||
function handleKeyUp(event: KeyboardEvent) {
|
||||
const waveEvent = keyutil.adaptFromReactOrNativeKeyEvent(event);
|
||||
if (waveEvent.key == "Meta" || waveEvent.key == "Shift") {
|
||||
globalStore.set(simpleCmdShiftAtom, false);
|
||||
globalStore.set(atoms.cmdShiftDelayAtom, false);
|
||||
}
|
||||
}
|
||||
|
||||
function handleKeyDown(waveEvent: WaveKeyboardEvent): boolean {
|
||||
if ((waveEvent.key == "Meta" || waveEvent.key == "Shift") && waveEvent.cmd && waveEvent.shift) {
|
||||
globalStore.set(simpleCmdShiftAtom, true);
|
||||
setTimeout(() => {
|
||||
const simpleState = globalStore.get(simpleCmdShiftAtom);
|
||||
if (simpleState) {
|
||||
globalStore.set(atoms.cmdShiftDelayAtom, true);
|
||||
}
|
||||
}, 400);
|
||||
return false;
|
||||
}
|
||||
|
||||
// global key handler for now (refactor later)
|
||||
if (keyutil.checkKeyPressed(waveEvent, "Cmd:]") || keyutil.checkKeyPressed(waveEvent, "Shift:Cmd:]")) {
|
||||
switchTab(1);
|
||||
@ -381,15 +392,34 @@ const AppInner = () => {
|
||||
React.useEffect(() => {
|
||||
const staticKeyDownHandler = keyutil.keydownWrapper(handleKeyDown);
|
||||
document.addEventListener("keydown", staticKeyDownHandler);
|
||||
const savedKeyUpHandler = handleKeyUp;
|
||||
document.addEventListener("keyup", savedKeyUpHandler);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener("keydown", staticKeyDownHandler);
|
||||
document.removeEventListener("keyup", savedKeyUpHandler);
|
||||
};
|
||||
}, []);
|
||||
return null;
|
||||
};
|
||||
|
||||
const AppInner = () => {
|
||||
const client = jotai.useAtomValue(atoms.client);
|
||||
const windowData = jotai.useAtomValue(atoms.waveWindow);
|
||||
if (client == null || windowData == null) {
|
||||
return (
|
||||
<div className="mainapp">
|
||||
<AppBackground />
|
||||
<CenteredDiv>invalid configuration, client or window was not loaded</CenteredDiv>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const isFullScreen = jotai.useAtomValue(atoms.isFullScreen);
|
||||
return (
|
||||
<div className={clsx("mainapp", PLATFORM, { fullscreen: isFullScreen })} onContextMenu={handleContextMenu}>
|
||||
<AppBackground />
|
||||
<AppKeyHandlers />
|
||||
<AppSettingsUpdater />
|
||||
<DndProvider backend={HTML5Backend}>
|
||||
<Workspace />
|
||||
|
@ -271,7 +271,26 @@
|
||||
pointer-events: none;
|
||||
padding: 2px;
|
||||
border-radius: calc(var(--block-border-radius) + 2px);
|
||||
z-index: var(--zindex-block-mask-inner);
|
||||
|
||||
&.is-layoutmode .block-mask-inner {
|
||||
margin-top: 35px; // TODO fix this magic
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.bignum {
|
||||
margin-top: -15%;
|
||||
font-size: 60px;
|
||||
font-weight: bold;
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.block-focused {
|
||||
.block-mask {
|
||||
border: 2px solid var(--accent-color);
|
||||
|
@ -6,6 +6,7 @@ import { Button } from "@/app/element/button";
|
||||
import { ContextMenuModel } from "@/app/store/contextmenu";
|
||||
import { atoms, globalStore, useBlockAtom, WOS } from "@/app/store/global";
|
||||
import * as services from "@/app/store/services";
|
||||
import { LayoutTreeState } from "@/layout/index";
|
||||
import { getLayoutStateAtomForTab } from "@/layout/lib/layoutAtom";
|
||||
import { adaptFromReactOrNativeKeyEvent, checkKeyPressed } from "@/util/keyutil";
|
||||
import { isBlockMagnified } from "@/util/layoututil";
|
||||
@ -221,6 +222,50 @@ function renderHeaderElements(headerTextUnion: HeaderElem[]): JSX.Element[] {
|
||||
return headerTextElems;
|
||||
}
|
||||
|
||||
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];
|
||||
if (leaf?.data?.blockId == blockId) {
|
||||
return String(idx + 1);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
const BlockMask = ({ blockId, preview, isFocused }: { blockId: string; preview: boolean; isFocused: boolean }) => {
|
||||
const isLayoutMode = jotai.useAtomValue(atoms.cmdShiftDelayAtom);
|
||||
const [blockData] = WOS.useWaveObjectValue<Block>(WOS.makeORef("block", blockId));
|
||||
|
||||
const style: React.CSSProperties = {};
|
||||
if (!isFocused && blockData?.meta?.["frame:bordercolor"]) {
|
||||
style.borderColor = blockData.meta["frame:bordercolor"];
|
||||
}
|
||||
if (isFocused && blockData?.meta?.["frame:bordercolor:focused"]) {
|
||||
style.borderColor = blockData.meta["frame:bordercolor:focused"];
|
||||
}
|
||||
let innerElem = null;
|
||||
if (isLayoutMode) {
|
||||
innerElem = (
|
||||
<div className="block-mask-inner">
|
||||
<div className="bignum">
|
||||
<BlockNum blockId={blockId} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className={clsx("block-mask", { "is-layoutmode": isLayoutMode })} style={style}>
|
||||
{innerElem}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const BlockFrame_Default_Component = (props: BlockFrameProps) => {
|
||||
const { blockId, layoutModel, viewModel, blockModel, preview, numBlocksInTab, children } = props;
|
||||
const [blockData] = WOS.useWaveObjectValue<Block>(WOS.makeORef("block", blockId));
|
||||
@ -230,19 +275,14 @@ const BlockFrame_Default_Component = (props: BlockFrameProps) => {
|
||||
return winData?.activeblockid === blockId;
|
||||
});
|
||||
});
|
||||
let isFocused = jotai.useAtomValue(isFocusedAtom);
|
||||
const viewIconUnion = util.useAtomValueSafe(viewModel.viewIcon) ?? blockViewToIcon(blockData?.meta?.view);
|
||||
const customBg = util.useAtomValueSafe(viewModel.blockBg);
|
||||
|
||||
let isFocused = jotai.useAtomValue(isFocusedAtom);
|
||||
if (preview) {
|
||||
isFocused = true;
|
||||
}
|
||||
const style: React.CSSProperties = {};
|
||||
if (!isFocused && blockData?.meta?.["frame:bordercolor"]) {
|
||||
style.borderColor = blockData.meta["frame:bordercolor"];
|
||||
}
|
||||
if (isFocused && blockData?.meta?.["frame:bordercolor:focused"]) {
|
||||
style.borderColor = blockData.meta["frame:bordercolor:focused"];
|
||||
}
|
||||
|
||||
const viewIconElem = getViewIconElem(viewIconUnion, blockData);
|
||||
|
||||
function handleKeyDown(e: React.KeyboardEvent<HTMLDivElement>) {
|
||||
@ -253,7 +293,6 @@ const BlockFrame_Default_Component = (props: BlockFrameProps) => {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const innerStyle: React.CSSProperties = {};
|
||||
if (!preview && customBg?.bg != null) {
|
||||
innerStyle.background = customBg.bg;
|
||||
@ -278,10 +317,9 @@ const BlockFrame_Default_Component = (props: BlockFrameProps) => {
|
||||
onClick={blockModel?.onClick}
|
||||
onFocusCapture={blockModel?.onFocusCapture}
|
||||
ref={blockModel?.blockRef}
|
||||
style={style}
|
||||
onKeyDown={handleKeyDown}
|
||||
>
|
||||
<div className="block-mask"></div>
|
||||
<BlockMask blockId={blockId} preview={preview} isFocused={isFocused} />
|
||||
<div className="block-frame-default-inner" style={innerStyle}>
|
||||
<BlockFrame_Header {...props} />
|
||||
{preview ? previewElem : children}
|
||||
|
@ -103,6 +103,7 @@ function initGlobalAtoms(initOpts: GlobalInitOptions) {
|
||||
}
|
||||
return windowData.activetabid;
|
||||
});
|
||||
const cmdShiftDelayAtom = jotai.atom(false);
|
||||
atoms = {
|
||||
// initialized in wave.ts (will not be null inside of application)
|
||||
windowId: windowIdAtom,
|
||||
@ -115,6 +116,7 @@ function initGlobalAtoms(initOpts: GlobalInitOptions) {
|
||||
tabAtom: tabAtom,
|
||||
activeTabId: activeTabIdAtom,
|
||||
isFullScreen: isFullScreenAtom,
|
||||
cmdShiftDelayAtom: cmdShiftDelayAtom,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,7 @@
|
||||
--zindex-tab-name: 3;
|
||||
--zindex-layout-placeholder-container: 1;
|
||||
--zindex-layout-overlay-container: 2;
|
||||
--zindex-block-mask-inner: 10;
|
||||
|
||||
// z-indexes in xterm.css
|
||||
// xterm-helpers: 5
|
||||
|
1
frontend/types/custom.d.ts
vendored
1
frontend/types/custom.d.ts
vendored
@ -16,6 +16,7 @@ declare global {
|
||||
tabAtom: jotai.Atom<Tab>; // driven from WOS
|
||||
activeTabId: jotai.Atom<string>; // derrived from windowDataAtom
|
||||
isFullScreen: jotai.PrimitiveAtom<boolean>;
|
||||
cmdShiftDelayAtom: jotai.PrimitiveAtom<boolean>;
|
||||
};
|
||||
|
||||
type TabLayoutData = {
|
||||
|
Loading…
Reference in New Issue
Block a user