Compare commits

..

1 Commits

Author SHA1 Message Date
Evan Simkowitz 406afe4a4f save work 2024-03-21 18:01:55 -04:00
47 changed files with 2581 additions and 3214 deletions
+2 -64
View File
@@ -1,8 +1,7 @@
[
{
"command": "system:toggleDeveloperTools",
"keys": ["Cmd:Option:i"],
"info": "Opens the chrome developer tool menu"
"keys": ["Cmd:Option:i"]
},
{
"command": "system:hideWindow",
@@ -16,62 +15,10 @@
"command": "generic:confirm",
"keys": ["Enter"]
},
{
"command": "generic:expandTextInput",
"keys": ["Shift:Enter", "Ctrl:Enter"]
},
{
"command": "generic:deleteItem",
"keys": ["Backspace", "Delete"]
},
{
"command": "generic:space",
"keys": ["Space"]
},
{
"command": "generic:tab",
"keys": ["Tab"]
},
{
"command": "generic:numpad-0",
"keys": ["0"]
},
{
"command": "generic:numpad-1",
"keys": ["1"]
},
{
"command": "generic:numpad-2",
"keys": ["2"]
},
{
"command": "generic:numpad-3",
"keys": ["3"]
},
{
"command": "generic:numpad-4",
"keys": ["4"]
},
{
"command": "generic:numpad-5",
"keys": ["5"]
},
{
"command": "generic:numpad-6",
"keys": ["6"]
},
{
"command": "generic:numpad-7",
"keys": ["7"]
},
{
"command": "generic:numpad-8",
"keys": ["8"]
},
{
"command": "generic:numpad-9",
"keys": ["9"]
},
{
"command": "generic:selectAbove",
"keys": ["ArrowUp"]
@@ -80,14 +27,6 @@
"command": "generic:selectBelow",
"keys": ["ArrowDown"]
},
{
"command": "generic:selectLeft",
"keys": ["ArrowLeft"]
},
{
"command": "generic:selectRight",
"keys": ["ArrowRight"]
},
{
"command": "generic:selectPageAbove",
"keys": ["PageUp"]
@@ -128,8 +67,7 @@
},
{
"command": "app:restartCommand",
"keys": ["Cmd:r"],
"info": "Restarts the command running in the current selected line"
"keys": ["Cmd:r"]
},
{
"command": "app:restartLastCommand",
+6 -6
View File
@@ -5,14 +5,14 @@
<base href="../" />
<script charset="UTF-8" src="dist-dev/waveterm.js"></script>
<link rel="stylesheet" href="public/bulma-0.9.4.min.css" />
<link rel="stylesheet" href="public/fontawesome/css/fontawesome.min.css">
<link rel="stylesheet" href="public/fontawesome/css/brands.min.css">
<link rel="stylesheet" href="public/fontawesome/css/solid.min.css">
<link rel="stylesheet" href="public/fontawesome/css/sharp-solid.min.css">
<link rel="stylesheet" href="public/fontawesome/css/sharp-regular.min.css">
<link rel="stylesheet" href="public/fontawesome/css/fontawesome.min.css" />
<link rel="stylesheet" href="public/fontawesome/css/brands.min.css" />
<link rel="stylesheet" href="public/fontawesome/css/solid.min.css" />
<link rel="stylesheet" href="public/fontawesome/css/sharp-solid.min.css" />
<link rel="stylesheet" href="public/fontawesome/css/sharp-regular.min.css" />
<link rel="stylesheet" href="dist-dev/waveterm.css" />
<link rel="stylesheet" id="theme-stylesheet" href="public/themes/default.css">
<link rel="stylesheet" id="theme-stylesheet" href="public/themes/default.css" />
</head>
<body>
<div id="measure"></div>
+37 -90
View File
@@ -1,12 +1,9 @@
import React, { useState, useEffect, useRef, createRef } from "react";
import * as mobx from "mobx";
import ReactDOM from "react-dom";
import dayjs from "dayjs";
import cs from "classnames";
import { Button } from "@/elements";
import { If } from "tsx-control-statements/components";
import { GlobalModel } from "@/models";
import { v4 as uuidv4 } from "uuid";
import "./datepicker.less";
@@ -39,10 +36,6 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
MM: selDate.format("MM"),
DD: selDate.format("DD"),
});
let curUuid = uuidv4();
let keybindsRegistered = mobx.observable.box(false, {
name: "datepicker-keybinds-registered",
});
useEffect(() => {
inputRefs.current = {
@@ -280,11 +273,6 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
setShowYearAccordion(false);
};
const closeModal = () => {
setIsOpen(false);
setShowYearAccordion(false);
};
const dayPickerModal = isOpen
? ReactDOM.createPortal(
<div ref={modalRef} className="day-picker-modal" style={calculatePosition()}>
@@ -312,13 +300,13 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
}
};
const handleArrowNavigation = (key, currentPart) => {
const handleArrowNavigation = (event, currentPart) => {
const currentIndex = formatParts.indexOf(currentPart);
let targetInput;
if (key == "ArrowLeft" && currentIndex > 0) {
if (event.key === "ArrowLeft" && currentIndex > 0) {
targetInput = inputRefs.current[formatParts[currentIndex - 1]].current;
} else if (key == "ArrowRight" && currentIndex < formatParts.length - 1) {
} else if (event.key === "ArrowRight" && currentIndex < formatParts.length - 1) {
targetInput = inputRefs.current[formatParts[currentIndex + 1]].current;
}
@@ -327,91 +315,51 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
}
};
const handleKeyDown = (event, currentPart) => {};
const handleKeyDown = (event, currentPart) => {
const key = event.key;
const handleFocus = (event, part) => {
event.target.select();
registerKeybindings(event, part);
};
const registerKeybindings = (event: any, part: string) => {
if (keybindsRegistered.get() == true) {
if (key === "ArrowLeft" || key === "ArrowRight") {
// Handle arrow navigation without selecting text
handleArrowNavigation(event, currentPart);
return;
}
mobx.action(() => {
keybindsRegistered.set(true);
})();
let keybindManager = GlobalModel.keybindManager;
let domain = "datepicker-" + curUuid + "-" + part;
keybindManager.registerKeybinding("control", domain, "generic:selectLeft", (waveEvent) => {
handleArrowNavigation("ArrowLeft", part);
return true;
});
keybindManager.registerKeybinding("control", domain, "generic:selectRight", (waveEvent) => {
handleArrowNavigation("ArrowRight", part);
return true;
});
keybindManager.registerKeybinding("control", domain, "generic:space", (waveEvent) => {
toggleModal();
return true;
});
keybindManager.registerKeybinding("control", domain, "generic:confirm", (waveEvent) => {
toggleModal();
return true;
});
keybindManager.registerKeybinding("control", domain, "generic:cancel", (waveEvent) => {
closeModal();
return true;
});
keybindManager.registerKeybinding("control", domain, "generic:tab", (waveEvent) => {
handleArrowNavigation("ArrowRight", part);
return true;
});
for (let numpadKey = 0; numpadKey <= 9; numpadKey++) {
keybindManager.registerKeybinding(
"control",
domain,
"generic:numpad-" + numpadKey.toString(),
(waveEvent) => {
let currentPart = part;
const maxLength = currentPart === "YYYY" ? 4 : 2;
const newValue = event.target.value.length < maxLength ? event.target.value + numpadKey : numpadKey;
let selectionTimeoutId = null;
handleDatePartChange(currentPart, newValue);
// Clear any existing timeout
if (selectionTimeoutId !== null) {
clearTimeout(selectionTimeoutId);
}
if (key === " ") {
// Handle spacebar press to toggle the modal
toggleModal();
return;
}
// Re-focus and select the input after state update
selectionTimeoutId = setTimeout(() => {
event.target.focus();
event.target.select();
}, 0);
return true;
}
);
if (key.match(/[0-9]/)) {
// Handle numeric keys
event.preventDefault();
const maxLength = currentPart === "YYYY" ? 4 : 2;
const newValue = event.target.value.length < maxLength ? event.target.value + key : key;
let selectionTimeoutId = null;
handleDatePartChange(currentPart, newValue);
// Clear any existing timeout
if (selectionTimeoutId !== null) {
clearTimeout(selectionTimeoutId);
}
// Re-focus and select the input after state update
selectionTimeoutId = setTimeout(() => {
event.target.focus();
event.target.select();
}, 0);
}
};
const handleBlur = (event, part) => {
unregisterKeybindings(part);
};
const unregisterKeybindings = (part) => {
mobx.action(() => {
keybindsRegistered.set(false);
})();
let domain = "datepicker-" + curUuid + "-" + part;
GlobalModel.keybindManager.unregisterDomain(domain);
const handleFocus = (event) => {
event.target.select();
};
// Prevent use from selecting text in the input
const handleMouseDown = (event, part) => {
const handleMouseDown = (event) => {
event.preventDefault();
handleFocus(event, part);
handleFocus(event);
};
const handleIconKeyDown = (event) => {
@@ -465,9 +413,8 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
value={dateParts[part]}
onChange={(e) => handleDatePartChange(part, e.target.value)}
onKeyDown={(e) => handleKeyDown(e, part)}
onMouseDown={(e) => handleMouseDown(e, part)}
onFocus={(e) => handleFocus(e, part)}
onBlur={(e) => handleBlur(e, part)}
onMouseDown={handleMouseDown}
onFocus={handleFocus}
maxLength={part === "YYYY" ? 4 : 2}
className="date-input"
placeholder={part}
+41 -73
View File
@@ -7,8 +7,6 @@ import { boundMethod } from "autobind-decorator";
import cn from "classnames";
import { If } from "tsx-control-statements/components";
import ReactDOM from "react-dom";
import { v4 as uuidv4 } from "uuid";
import { GlobalModel } from "@/models";
import "./dropdown.less";
@@ -41,7 +39,6 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
wrapperRef: React.RefObject<HTMLDivElement>;
menuRef: React.RefObject<HTMLDivElement>;
timeoutId: any;
curUuid: string;
constructor(props: DropdownProps) {
super(props);
@@ -53,7 +50,6 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
};
this.wrapperRef = React.createRef();
this.menuRef = React.createRef();
this.curUuid == uuidv4();
}
componentDidMount() {
@@ -106,76 +102,49 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
@boundMethod
handleFocus() {
this.setState({ isTouched: true });
this.registerKeybindings();
}
registerKeybindings() {
let keybindManager = GlobalModel.keybindManager;
let domain = "dropdown-" + this.curUuid;
keybindManager.registerKeybinding("control", domain, "generic:confirm", (waveEvent) => {
this.handleConfirm();
return true;
});
keybindManager.registerKeybinding("control", domain, "generic:space", (waveEvent) => {
this.handleConfirm();
return true;
});
keybindManager.registerKeybinding("control", domain, "generic:cancel", (waveEvent) => {
this.setState({ isOpen: false });
return true;
});
keybindManager.registerKeybinding("control", domain, "generic:selectAbove", (waveEvent) => {
const { isOpen } = this.state;
const { options } = this.props;
if (isOpen) {
this.setState((prevState) => ({
highlightedIndex:
prevState.highlightedIndex > 0 ? prevState.highlightedIndex - 1 : options.length - 1,
}));
}
return true;
});
keybindManager.registerKeybinding("control", domain, "generic:selectBelow", (waveEvent) => {
const { isOpen } = this.state;
const { options } = this.props;
if (isOpen) {
this.setState((prevState) => ({
highlightedIndex:
prevState.highlightedIndex < options.length - 1 ? prevState.highlightedIndex + 1 : 0,
}));
}
return true;
});
keybindManager.registerKeybinding("control", domain, "generic:tab", (waveEvent) => {
this.setState({ isOpen: false });
return true;
});
}
handleConfirm() {
const { options } = this.props;
const { isOpen, highlightedIndex } = this.state;
if (isOpen) {
const option = options[highlightedIndex];
if (option) {
this.handleSelect(option.value, undefined);
}
} else {
this.toggleDropdown();
}
}
handleBlur() {
this.unregisterKeybindings();
}
unregisterKeybindings() {
let domain = "dropdown-" + this.curUuid;
GlobalModel.keybindManager.unregisterDomain(domain);
}
@boundMethod
handleKeyDown(event: React.KeyboardEvent) {}
handleKeyDown(event: React.KeyboardEvent) {
const { options } = this.props;
const { isOpen, highlightedIndex } = this.state;
switch (event.key) {
case "Enter":
case " ":
if (isOpen) {
const option = options[highlightedIndex];
if (option) {
this.handleSelect(option.value, undefined);
}
} else {
this.toggleDropdown();
}
break;
case "Escape":
this.setState({ isOpen: false });
break;
case "ArrowUp":
if (isOpen) {
this.setState((prevState) => ({
highlightedIndex:
prevState.highlightedIndex > 0 ? prevState.highlightedIndex - 1 : options.length - 1,
}));
}
break;
case "ArrowDown":
if (isOpen) {
this.setState((prevState) => ({
highlightedIndex:
prevState.highlightedIndex < options.length - 1 ? prevState.highlightedIndex + 1 : 0,
}));
}
break;
case "Tab":
this.setState({ isOpen: false });
break;
}
}
@boundMethod
handleSelect(value: string, event?: React.MouseEvent | React.KeyboardEvent) {
@@ -259,8 +228,7 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
tabIndex={0}
onKeyDown={this.handleKeyDown}
onClick={this.handleClick}
onFocus={this.handleFocus.bind(this)}
onBlur={this.handleBlur.bind(this)}
onFocus={this.handleFocus}
>
{decoration?.startDecoration && <>{decoration.startDecoration}</>}
<If condition={label}>
@@ -8,8 +8,6 @@ import { boundMethod } from "autobind-decorator";
import cn from "classnames";
import { If } from "tsx-control-statements/components";
import { checkKeyPressed, adaptFromReactOrNativeKeyEvent } from "@/util/keyutil";
import { GlobalModel } from "@/models";
import { v4 as uuidv4 } from "uuid";
import "./inlinesettingstextedit.less";
@@ -29,11 +27,6 @@ class InlineSettingsTextEdit extends React.Component<
tempText: OV<string>;
shouldFocus: boolean = false;
inputRef: React.RefObject<any> = React.createRef();
curId: string;
componentDidMount(): void {
this.curId = uuidv4();
}
componentDidUpdate(): void {
if (this.shouldFocus) {
@@ -59,7 +52,6 @@ class InlineSettingsTextEdit extends React.Component<
this.tempText = null;
this.props.onChange(newText);
})();
this.unregisterKeybindings();
}
@boundMethod
@@ -68,38 +60,24 @@ class InlineSettingsTextEdit extends React.Component<
this.isEditing.set(false);
this.tempText = null;
})();
this.unregisterKeybindings();
}
handleFocus() {
this.registerKeybindings();
}
registerKeybindings() {
let keybindManager = GlobalModel.keybindManager;
let domain = "inline-settings" + this.curId;
keybindManager.registerKeybinding("control", domain, "generic:confirm", (waveEvent) => {
@boundMethod
handleKeyDown(e: any): void {
let waveEvent = adaptFromReactOrNativeKeyEvent(e);
if (checkKeyPressed(waveEvent, "Enter")) {
e.preventDefault();
e.stopPropagation();
this.confirmChange();
return true;
});
keybindManager.registerKeybinding("control", domain, "generic:cancel", (waveEvent) => {
return;
}
if (checkKeyPressed(waveEvent, "Escape")) {
e.preventDefault();
e.stopPropagation();
this.cancelChange();
return true;
});
}
unregisterKeybindings() {
let domain = "inline-settings" + this.curId;
GlobalModel.keybindManager.unregisterDomain(domain);
}
handleBlur() {
this.unregisterKeybindings();
this.cancelChange();
}
componentWillUnmount(): void {
this.unregisterKeybindings();
return;
}
return;
}
@boundMethod
@@ -121,8 +99,7 @@ class InlineSettingsTextEdit extends React.Component<
ref={this.inputRef}
className="input"
type="text"
onFocus={this.handleFocus.bind(this)}
onBlur={this.handleBlur.bind(this)}
onKeyDown={this.handleKeyDown}
placeholder={this.props.placeholder}
onChange={this.handleChangeText}
value={this.tempText.get()}
+2 -47
View File
@@ -6,11 +6,8 @@ import * as mobx from "mobx";
import { If } from "tsx-control-statements/components";
import ReactDOM from "react-dom";
import { Button } from "./button";
import { v4 as uuidv4 } from "uuid";
import { GlobalModel } from "@/models";
import "./modal.less";
import { boundMethod } from "autobind-decorator";
interface ModalHeaderProps {
onClose?: () => void;
@@ -33,52 +30,10 @@ interface ModalFooterProps {
onOk?: () => void;
cancelLabel?: string;
okLabel?: string;
keybindings?: boolean;
}
class ModalKeybindings extends React.Component<{ onOk; onCancel }, {}> {
curId: string;
@boundMethod
componentDidMount(): void {
this.curId = uuidv4();
let domain = "modal-" + this.curId;
let keybindManager = GlobalModel.keybindManager;
if (this.props.onOk) {
keybindManager.registerKeybinding("modal", domain, "generic:confirm", (waveEvent) => {
this.props.onOk();
return true;
});
}
if (this.props.onCancel) {
keybindManager.registerKeybinding("modal", domain, "generic:cancel", (waveEvent) => {
this.props.onCancel();
return true;
});
}
}
@boundMethod
componentWillUnmount(): void {
GlobalModel.keybindManager.unregisterDomain("modal-" + this.curId);
}
render(): React.ReactNode {
return null;
}
}
const ModalFooter: React.FC<ModalFooterProps> = ({
onCancel,
onOk,
cancelLabel = "Cancel",
okLabel = "Ok",
keybindings = true,
}) => (
const ModalFooter: React.FC<ModalFooterProps> = ({ onCancel, onOk, cancelLabel = "Cancel", okLabel = "Ok" }) => (
<div className="wave-modal-footer">
<If condition={keybindings}>
<ModalKeybindings onOk={onOk} onCancel={onCancel}></ModalKeybindings>
</If>
{onCancel && (
<Button className="secondary" onClick={onCancel}>
{cancelLabel}
@@ -124,4 +79,4 @@ class Modal extends React.Component<ModalProps> {
}
}
export { Modal, ModalKeybindings };
export { Modal };
-8
View File
@@ -18,8 +18,6 @@ interface TextFieldProps {
className?: string;
onChange?: (value: string) => void;
onKeyDown?: (event: React.KeyboardEvent<HTMLInputElement>) => void;
onFocus?: () => void;
onBlur?: () => void;
placeholder?: string;
defaultValue?: string;
decoration?: TextFieldDecorationProps;
@@ -80,9 +78,6 @@ class TextField extends React.Component<TextFieldProps, TextFieldState> {
@boundMethod
handleFocus() {
this.setState({ focused: true });
if (this.props.onFocus) {
this.props.onFocus();
}
}
@boundMethod
@@ -96,9 +91,6 @@ class TextField extends React.Component<TextFieldProps, TextFieldState> {
this.setState({ error: false, focused: false });
}
}
if (this.props.onBlur) {
this.props.onBlur();
}
}
@boundMethod
-3
View File
@@ -9,7 +9,6 @@ import { Markdown, Modal, Button, Checkbox } from "@/elements";
import { GlobalModel, GlobalCommandRunner } from "@/models";
import "./alert.less";
import { ModalKeybindings } from "../elements/modal";
@mobxReact.observer
class AlertModal extends React.Component<{}, {}> {
@@ -55,7 +54,6 @@ class AlertModal extends React.Component<{}, {}> {
</div>
<div className="wave-modal-footer">
<If condition={isConfirm}>
<ModalKeybindings onOk={this.handleOK} onCancel={this.closeModal}></ModalKeybindings>
<Button className="secondary" onClick={this.closeModal}>
Cancel
</Button>
@@ -64,7 +62,6 @@ class AlertModal extends React.Component<{}, {}> {
</Button>
</If>
<If condition={!isConfirm}>
<ModalKeybindings onOk={this.handleOK} onCancel={null}></ModalKeybindings>
<Button autoFocus={true} onClick={this.handleOK}>
Ok
</Button>
+12 -17
View File
@@ -2,7 +2,7 @@ import * as React from "react";
import { GlobalModel } from "@/models";
import { Choose, When, If } from "tsx-control-statements/components";
import { Modal, PasswordField, TextField, Markdown, Checkbox } from "@/elements";
import { checkKeyPressed, adaptFromReactOrNativeKeyEvent, KeybindManager } from "@/util/keyutil";
import { checkKeyPressed, adaptFromReactOrNativeKeyEvent } from "@/util/keyutil";
import "./userinput.less";
@@ -44,20 +44,17 @@ export const UserInputModal = (userInputRequest: UserInputRequest) => {
[userInputRequest]
);
function handleTextFocus() {
let keybindManager = GlobalModel.keybindManager;
keybindManager.registerKeybinding("modal", "userinput", "generic:confirm", (waveEvent) => {
function handleTextKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {
let waveEvent = adaptFromReactOrNativeKeyEvent(e);
if (checkKeyPressed(waveEvent, "Enter")) {
e.preventDefault();
e.stopPropagation();
handleSendText();
return true;
});
keybindManager.registerKeybinding("modal", "userinput", "generic:cancel", (waveEvent) => {
} else if (checkKeyPressed(waveEvent, "Escape")) {
e.preventDefault();
e.stopPropagation();
handleSendCancel();
return true;
});
}
function handleTextBlur() {
GlobalModel.keybindManager.unregisterDomain("userinput");
}
}
React.useEffect(() => {
@@ -92,8 +89,7 @@ export const UserInputModal = (userInputRequest: UserInputRequest) => {
value={responseText}
maxLength={400}
autoFocus={true}
onFocus={() => handleTextFocus()}
onBlur={() => handleTextBlur()}
onKeyDown={(e) => handleTextKeyDown(e)}
/>
</If>
<If condition={!userInputRequest.publictext}>
@@ -102,8 +98,7 @@ export const UserInputModal = (userInputRequest: UserInputRequest) => {
value={responseText}
maxLength={400}
autoFocus={true}
onFocus={() => handleTextFocus()}
onBlur={() => handleTextBlur()}
onKeyDown={(e) => handleTextKeyDown(e)}
/>
</If>
</If>
@@ -14,7 +14,6 @@ import * as textmeasure from "@/util/textmeasure";
import * as appconst from "@/app/appconst";
import "./viewremoteconndetail.less";
import { ModalKeybindings } from "../elements/modal";
@mobxReact.observer
class ViewRemoteConnDetailModal extends React.Component<{}, {}> {
@@ -383,20 +382,6 @@ class ViewRemoteConnDetailModal extends React.Component<{}, {}> {
</div>
</div>
<div className="wave-modal-footer">
<ModalKeybindings
onOk={() => {
if (selectedRemoteStatus == "connecting") {
return;
}
this.handleClose();
}}
onCancel={() => {
if (selectedRemoteStatus == "connecting") {
return;
}
this.handleClose();
}}
></ModalKeybindings>
<Button
className="secondary"
disabled={selectedRemoteStatus == "connecting"}
+59 -124
View File
@@ -8,64 +8,21 @@ import { GlobalModel } from "@/models";
import { isBlank } from "@/util/util";
import { boundMethod } from "autobind-decorator";
import cn from "classnames";
import { If, For } from "tsx-control-statements/components";
import { For } from "tsx-control-statements/components";
import { Markdown } from "@/elements";
import { checkKeyPressed, adaptFromReactOrNativeKeyEvent } from "@/util/keyutil";
class AIChatKeybindings extends React.Component<{ AIChatObject: AIChat }, {}> {
componentDidMount(): void {
let AIChatObject = this.props.AIChatObject;
let keybindManager = GlobalModel.keybindManager;
let inputModel = GlobalModel.inputModel;
keybindManager.registerKeybinding("pane", "aichat", "generic:confirm", (waveEvent) => {
AIChatObject.onEnterKeyPressed();
return true;
});
keybindManager.registerKeybinding("pane", "aichat", "generic:expandTextInput", (waveEvent) => {
AIChatObject.onExpandInputPressed();
return true;
});
keybindManager.registerKeybinding("pane", "aichat", "generic:cancel", (waveEvent) => {
inputModel.closeAIAssistantChat(true);
return true;
});
keybindManager.registerKeybinding("pane", "aichat", "aichat:clearHistory", (waveEvent) => {
inputModel.clearAIAssistantChat();
return true;
});
keybindManager.registerKeybinding("pane", "aichat", "generic:selectAbove", (waveEvent) => {
return AIChatObject.onArrowUpPressed();
});
keybindManager.registerKeybinding("pane", "aichat", "generic:selectBelow", (waveEvent) => {
return AIChatObject.onArrowDownPressed();
});
}
componentWillUnmount(): void {
GlobalModel.keybindManager.unregisterDomain("aichat");
}
render() {
return null;
}
}
@mobxReact.observer
class AIChat extends React.Component<{}, {}> {
chatListKeyCount: number = 0;
textAreaNumLines: mobx.IObservableValue<number> = mobx.observable.box(1, { name: "textAreaNumLines" });
chatWindowScrollRef: React.RefObject<HTMLDivElement>;
textAreaRef: React.RefObject<HTMLTextAreaElement>;
isFocused: OV<boolean>;
constructor(props: any) {
super(props);
this.chatWindowScrollRef = React.createRef();
this.textAreaRef = React.createRef();
this.isFocused = mobx.observable.box(false, {
name: "aichat-isfocused",
});
}
componentDidMount() {
@@ -109,81 +66,66 @@ class AIChat extends React.Component<{}, {}> {
return { numLines, linePos };
}
onTextAreaFocused(e: any) {
mobx.action(() => {
this.isFocused.set(true);
})();
}
onTextAreaBlur(e: any) {
mobx.action(() => {
this.isFocused.set(false);
})();
}
onTextAreaChange(e: any) {
// set height of textarea based on number of newlines
mobx.action(() => {
this.textAreaNumLines.set(e.target.value.split(/\n/).length);
GlobalModel.inputModel.codeSelectDeselectAll();
})();
}
onEnterKeyPressed() {
let inputModel = GlobalModel.inputModel;
let currentRef = this.textAreaRef.current;
if (currentRef == null) {
return;
}
if (inputModel.getCodeSelectSelectedIndex() == -1) {
let messageStr = currentRef.value;
this.submitChatMessage(messageStr);
currentRef.value = "";
} else {
inputModel.grabCodeSelectSelection();
}
}
onExpandInputPressed() {
let currentRef = this.textAreaRef.current;
if (currentRef == null) {
return;
}
currentRef.setRangeText("\n", currentRef.selectionStart, currentRef.selectionEnd, "end");
GlobalModel.inputModel.codeSelectDeselectAll();
}
onArrowUpPressed(): boolean {
let currentRef = this.textAreaRef.current;
if (currentRef == null) {
return false;
}
if (this.getLinePos(currentRef).linePos > 1) {
// normal up arrow
GlobalModel.inputModel.codeSelectDeselectAll();
return false;
}
GlobalModel.inputModel.codeSelectSelectNextOldestCodeBlock();
return true;
}
onArrowDownPressed(): boolean {
let currentRef = this.textAreaRef.current;
let inputModel = GlobalModel.inputModel;
if (currentRef == null) {
return false;
}
if (inputModel.getCodeSelectSelectedIndex() == inputModel.codeSelectBottom) {
GlobalModel.inputModel.codeSelectDeselectAll();
return false;
}
inputModel.codeSelectSelectNextNewestCodeBlock();
return true;
}
@mobx.action
@boundMethod
onKeyDown(e: any) {}
onKeyDown(e: any) {
mobx.action(() => {
let model = GlobalModel;
let inputModel = model.inputModel;
let ctrlMod = e.getModifierState("Control") || e.getModifierState("Meta") || e.getModifierState("Shift");
let resetCodeSelect = !ctrlMod;
let waveEvent = adaptFromReactOrNativeKeyEvent(e);
if (checkKeyPressed(waveEvent, "Enter")) {
e.preventDefault();
if (!ctrlMod) {
if (inputModel.getCodeSelectSelectedIndex() == -1) {
let messageStr = e.target.value;
this.submitChatMessage(messageStr);
e.target.value = "";
} else {
inputModel.grabCodeSelectSelection();
}
} else {
e.target.setRangeText("\n", e.target.selectionStart, e.target.selectionEnd, "end");
}
}
if (checkKeyPressed(waveEvent, "Escape")) {
e.preventDefault();
e.stopPropagation();
inputModel.closeAIAssistantChat(true);
}
if (checkKeyPressed(waveEvent, "Ctrl:l")) {
e.preventDefault();
e.stopPropagation();
inputModel.clearAIAssistantChat();
}
if (checkKeyPressed(waveEvent, "ArrowUp")) {
if (this.getLinePos(e.target).linePos > 1) {
// normal up arrow
return;
}
e.preventDefault();
inputModel.codeSelectSelectNextOldestCodeBlock();
resetCodeSelect = false;
}
if (checkKeyPressed(waveEvent, "ArrowDown")) {
if (inputModel.getCodeSelectSelectedIndex() == inputModel.codeSelectBottom) {
return;
}
e.preventDefault();
inputModel.codeSelectSelectNextNewestCodeBlock();
resetCodeSelect = false;
}
if (resetCodeSelect) {
inputModel.codeSelectDeselectAll();
}
// set height of textarea based on number of newlines
this.textAreaNumLines.set(e.target.value.split(/\n/).length);
})();
}
renderError(err: string): any {
return <div className="chat-msg-error">{err}</div>;
@@ -250,13 +192,9 @@ class AIChat extends React.Component<{}, {}> {
const textAreaPadding = 2 * 0.5 * termFontSize;
let textAreaMaxHeight = textAreaLineHeight * textAreaMaxLines + textAreaPadding;
let textAreaInnerHeight = this.textAreaNumLines.get() * textAreaLineHeight + textAreaPadding;
let isFocused = this.isFocused.get();
return (
<div className="cmd-aichat">
<If condition={isFocused}>
<AIChatKeybindings AIChatObject={this}></AIChatKeybindings>
</If>
<div className="cmdinput-titlebar">
<div className="title-icon">
<i className="fa-sharp fa-solid fa-sparkles" />
@@ -279,9 +217,6 @@ class AIChat extends React.Component<{}, {}> {
autoComplete="off"
autoCorrect="off"
id="chat-cmd-input"
onFocus={this.onTextAreaFocused.bind(this)}
onBlur={this.onTextAreaBlur.bind(this)}
onChange={this.onTextAreaChange.bind(this)}
onKeyDown={this.onKeyDown}
style={{ height: textAreaInnerHeight, maxHeight: textAreaMaxHeight, fontSize: termFontSize }}
className={cn("chat-textarea")}
File diff suppressed because it is too large Load Diff
+14 -2
View File
@@ -352,7 +352,6 @@ function createMainWindow(clientData: ClientDataType | null): Electron.BrowserWi
const indexHtml = isDev ? "index-dev.html" : "index.html";
win.loadFile(path.join(getElectronAppBasePath(), "public", indexHtml));
win.webContents.on("before-input-event", (e, input) => {
const waveEvent = adaptFromElectronKeyEvent(input);
if (win.isFocused()) {
wasActive = true;
}
@@ -380,7 +379,7 @@ function createMainWindow(clientData: ClientDataType | null): Electron.BrowserWi
win.webContents.on("zoom-changed", (e) => {
win.webContents.send("zoom-changed");
});
win.webContents.setWindowOpenHandler(({ url, frameName }) => {
win.webContents.setWindowOpenHandler(({ url }) => {
if (url.startsWith("https://docs.waveterm.dev/")) {
console.log("openExternal docs", url);
electron.shell.openExternal(url);
@@ -401,6 +400,19 @@ function createMainWindow(clientData: ClientDataType | null): Electron.BrowserWi
return { action: "deny" };
});
electron.session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
callback({
responseHeaders: {
...details.responseHeaders,
"Content-Security-Policy": [
`default-src 'file://${getElectronAppBasePath()}/dist${isDev ? "-dev" : ""}/'`,
`script-src 'file://${getElectronAppBasePath()}/dist${isDev ? "-dev" : ""}/'`,
`style-src 'file://${getElectronAppBasePath()}/dist${isDev ? "-dev" : ""}/'`,
],
},
});
});
return win;
}
-3
View File
@@ -630,9 +630,6 @@ class InputModel {
}
codeSelectDeselectAll(direction: number = this.codeSelectBottom) {
if (this.codeSelectSelectedIndex.get() == direction) {
return;
}
mobx.action(() => {
this.codeSelectSelectedIndex.set(direction);
this.codeSelectBlockRefArray = [];
+17
View File
@@ -476,6 +476,23 @@ class Model {
if (isModKeyPress(e)) {
return;
}
if (this.alertMessage.get() != null) {
if (checkKeyPressed(waveEvent, "Escape")) {
e.preventDefault();
this.modalsModel.popModal(() => this.cancelAlert());
return;
}
if (checkKeyPressed(waveEvent, "Enter")) {
e.preventDefault();
this.confirmAlert();
return;
}
return;
}
if (checkKeyPressed(waveEvent, "Escape") && this.modalsModel.store.length > 0) {
this.modalsModel.popModal();
return;
}
if (this.keybindManager.processKeyEvent(e, waveEvent)) {
return;
}
+67 -4
View File
@@ -12,7 +12,7 @@ import { MagicLayout } from "@/app/magiclayout";
import * as appconst from "@/app/appconst";
import { checkKeyPressed, adaptFromReactOrNativeKeyEvent } from "@/util/keyutil";
import { Model } from "./model";
import { GlobalCommandRunner, GlobalModel } from "./global";
import { GlobalCommandRunner } from "./global";
import { Cmd } from "./cmd";
import { ScreenLines } from "./screenlines";
import { getTermPtyData } from "@/util/modelutil";
@@ -469,7 +469,7 @@ class Screen {
this.renderers[lineId] = renderer;
}
setLineFocus(lineNum: number, lineid: string, focus: boolean): void {
setLineFocus(lineNum: number, focus: boolean): void {
mobx.action(() => this.termLineNumFocus.set(focus ? lineNum : 0))();
if (focus && this.selectedLine.get() != lineNum) {
GlobalCommandRunner.screenSelectLine(String(lineNum), "cmd");
@@ -498,8 +498,71 @@ class Screen {
})();
}
termCustomKeyHandlerInternal(e: any, termWrap: TermWrap): void {
let waveEvent = adaptFromReactOrNativeKeyEvent(e);
if (checkKeyPressed(waveEvent, "ArrowUp")) {
termWrap.terminal.scrollLines(-1);
return;
}
if (checkKeyPressed(waveEvent, "ArrowDown")) {
termWrap.terminal.scrollLines(1);
return;
}
if (checkKeyPressed(waveEvent, "PageUp")) {
termWrap.terminal.scrollPages(-1);
return;
}
if (checkKeyPressed(waveEvent, "PageDown")) {
termWrap.terminal.scrollPages(1);
return;
}
}
isTermCapturedKey(e: any): boolean {
let waveEvent = adaptFromReactOrNativeKeyEvent(e);
if (
checkKeyPressed(waveEvent, "ArrowUp") ||
checkKeyPressed(waveEvent, "ArrowDown") ||
checkKeyPressed(waveEvent, "PageUp") ||
checkKeyPressed(waveEvent, "PageDown")
) {
return true;
}
return false;
}
termCustomKeyHandler(e: any, termWrap: TermWrap): boolean {
return true;
let waveEvent = adaptFromReactOrNativeKeyEvent(e);
if (e.type == "keypress" && checkKeyPressed(waveEvent, "Ctrl:Shift:c")) {
e.stopPropagation();
e.preventDefault();
let sel = termWrap.terminal.getSelection();
navigator.clipboard.writeText(sel);
return false;
}
if (e.type == "keypress" && checkKeyPressed(waveEvent, "Ctrl:Shift:v")) {
e.stopPropagation();
e.preventDefault();
let p = navigator.clipboard.readText();
p.then((text) => {
termWrap.dataHandler?.(text, termWrap);
});
return false;
}
if (termWrap.isRunning) {
return true;
}
let isCaptured = this.isTermCapturedKey(e);
if (!isCaptured) {
return true;
}
if (e.type != "keydown" || isModKeyPress(e)) {
return false;
}
e.stopPropagation();
e.preventDefault();
this.termCustomKeyHandlerInternal(e, termWrap);
return false;
}
loadTerminalRenderer(elem: Element, line: LineType, cmd: Cmd, width: number) {
@@ -525,7 +588,7 @@ class Screen {
termOpts: cmd.getTermOpts(),
winSize: { height: 0, width: width },
dataHandler: cmd.handleData.bind(cmd),
focusHandler: (focus: boolean) => this.setLineFocus(line.linenum, line.lineid, focus),
focusHandler: (focus: boolean) => this.setLineFocus(line.linenum, focus),
isRunning: cmd.isRunning(),
customKeyHandler: this.termCustomKeyHandler.bind(this),
fontSize: this.globalModel.getTermFontSize(),
+15 -68
View File
@@ -2,7 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
import * as React from "react";
import * as mobx from "mobx";
import Editor, { Monaco } from "@monaco-editor/react";
import type * as MonacoTypes from "monaco-editor/esm/vs/editor/editor.api";
import cn from "classnames";
@@ -11,12 +10,7 @@ import { Markdown } from "@/elements";
import { GlobalModel, GlobalCommandRunner } from "@/models";
import Split from "react-split-it";
import loader from "@monaco-editor/loader";
import {
checkKeyPressed,
adaptFromReactOrNativeKeyEvent,
KeybindManager,
adaptFromElectronKeyEvent,
} from "@/util/keyutil";
import { checkKeyPressed, adaptFromReactOrNativeKeyEvent } from "@/util/keyutil";
import { Button, Dropdown } from "@/elements";
import "./code.less";
@@ -52,18 +46,6 @@ function renderCmdText(text: string): any {
// there is a global monaco variable (TODO get the correct TS type)
declare var monaco: any;
class CodeKeybindings extends React.Component<{ codeObject: SourceCodeRenderer }, {}> {
componentDidMount(): void {
this.props.codeObject.registerKeybindings();
}
componentWillUnmount(): void {
this.props.codeObject.unregisterKeybindings();
}
render() {
return null;
}
}
class SourceCodeRenderer extends React.Component<
{
data: ExtBlob;
@@ -149,10 +131,6 @@ class SourceCodeRenderer extends React.Component<
}
}
componentWillUnmount() {
this.unregisterKeybindings();
}
componentDidUpdate(prevProps: any): void {
if (!prevProps.shouldFocus && this.props.shouldFocus) {
if (this.monacoEditor) {
@@ -196,30 +174,6 @@ class SourceCodeRenderer extends React.Component<
}
};
registerKeybindings() {
const { lineId } = this.props.context;
let domain = "code-" + lineId;
let keybindManager = GlobalModel.keybindManager;
keybindManager.registerKeybinding("plugin", domain, "codeedit:save", (waveEvent) => {
this.doSave();
return true;
});
keybindManager.registerKeybinding("plugin", domain, "codeedit:close", (waveEvent) => {
this.doClose();
return true;
});
keybindManager.registerKeybinding("plugin", domain, "codeedit:togglePreview", (waveEvent) => {
this.togglePreview();
return true;
});
}
unregisterKeybindings() {
const { lineId } = this.props.context;
let domain = "code-" + lineId;
GlobalModel.keybindManager.unregisterDomain(domain);
}
handleEditorDidMount = (editor: MonacoTypes.editor.IStandaloneCodeEditor, monaco: Monaco) => {
this.monacoEditor = editor;
this.setInitialLanguage(editor);
@@ -230,15 +184,20 @@ class SourceCodeRenderer extends React.Component<
}, 2000);
editor.onKeyDown((e: MonacoTypes.IKeyboardEvent) => {
let waveEvent = adaptFromReactOrNativeKeyEvent(e.browserEvent);
console.log("keydown?", waveEvent);
if (
GlobalModel.keybindManager.checkKeysPressed(waveEvent, [
"codeedit:save",
"codeedit:close",
"codeedit:togglePreview",
])
) {
GlobalModel.keybindManager.processKeyEvent(e.browserEvent, waveEvent);
if (checkKeyPressed(waveEvent, "Cmd:s") && this.state.isSave) {
e.preventDefault();
e.stopPropagation();
this.doSave();
}
if (checkKeyPressed(waveEvent, "Cmd:d")) {
e.preventDefault();
e.stopPropagation();
this.doClose();
}
if (checkKeyPressed(waveEvent, "Cmd:p")) {
e.preventDefault();
e.stopPropagation();
this.togglePreview();
}
});
editor.onDidScrollChange((e) => {
@@ -544,20 +503,8 @@ class SourceCodeRenderer extends React.Component<
</div>
);
}
let { lineNum } = this.props.context;
let screen = GlobalModel.getActiveScreen();
let lineIsSelected = mobx.computed(
() => screen.getSelectedLine() == lineNum && screen.getFocusType() == "cmd",
{
name: "code-lineisselected",
}
);
console.log("lineis selected:", lineIsSelected.get());
return (
<div className="code-renderer">
<If condition={lineIsSelected.get()}>
<CodeKeybindings codeObject={this}></CodeKeybindings>
</If>
<Split sizes={[editorFraction, 1 - editorFraction]} onSetSizes={this.setSizes}>
{this.getCodeEditor()}
{isPreviewerAvailable && showPreview && this.getPreviewer()}
+1 -1
View File
@@ -148,7 +148,7 @@ class TermWrap {
});
this.terminal.open(elem);
if (opts.keyHandler != null) {
//this.terminal.onKey((e) => opts.keyHandler(e, this));
this.terminal.onKey((e) => opts.keyHandler(e, this));
}
if (opts.dataHandler != null) {
this.dataHandler = opts.dataHandler;
-59
View File
@@ -17,60 +17,6 @@ import "./terminal.less";
dayjs.extend(localizedFormat);
class TerminalKeybindings extends React.Component<{ termWrap: any; lineid: string }, {}> {
componentDidMount(): void {
this.registerKeybindings();
}
registerKeybindings() {
let keybindManager = GlobalModel.keybindManager;
let domain = "line-" + this.props.lineid;
let termWrap = this.props.termWrap;
keybindManager.registerKeybinding("plugin", domain, "terminal:copy", (waveEvent) => {
let termWrap = this.props.termWrap;
let sel = termWrap.terminal.getSelection();
navigator.clipboard.writeText(sel);
return true;
});
keybindManager.registerKeybinding("plugin", domain, "terminal:paste", (waveEvent) => {
let p = navigator.clipboard.readText();
p.then((text) => {
termWrap.dataHandler?.(text, termWrap);
});
return true;
});
keybindManager.registerKeybinding("plugin", domain, "generic:selectAbove", (waveEvent) => {
termWrap.terminal.scrollLines(-1);
return true;
});
keybindManager.registerKeybinding("plugin", domain, "generic:selectBelow", (waveEvent) => {
termWrap.terminal.scrollLines(1);
return true;
});
keybindManager.registerKeybinding("plugin", domain, "generic:selectPageAbove", (waveEvent) => {
termWrap.terminal.scrollLines(-10);
return true;
});
keybindManager.registerKeybinding("plugin", domain, "generic:selectPageBelow", (waveEvent) => {
termWrap.terminal.scrollLines(10);
return true;
});
}
unregisterKeybindings() {
let domain = "line-" + this.props.lineid;
GlobalModel.keybindManager.unregisterDomain(domain);
}
componentWillUnmount(): void {
this.unregisterKeybindings();
}
render(): React.ReactNode {
return null;
}
}
@mobxReact.observer
class TerminalRenderer extends React.Component<
{
@@ -207,8 +153,6 @@ class TerminalRenderer extends React.Component<
termHeight = 0;
}
let termLoaded = this.termLoaded.get();
let lineid = line.lineid;
let termWrap = screen.getTermWrap(lineid);
return (
<div
ref={this.elemRef}
@@ -225,9 +169,6 @@ class TerminalRenderer extends React.Component<
<If condition={!isFocused}>
<div key="term-block" className="term-block" onClick={this.clickTermBlock}></div>
</If>
<If condition={isFocused}>
<TerminalKeybindings termWrap={termWrap} lineid={lineid}></TerminalKeybindings>
</If>
<div
key="term-connectelem"
className="terminal-connectelem"
+8 -104
View File
@@ -25,11 +25,10 @@ const KeyTypeCode = "code";
type KeybindCallback = (event: WaveKeyboardEvent) => boolean;
type KeybindConfigArray = Array<KeybindConfig>;
type KeybindConfig = { command: string; keys: Array<string>; commandStr?: string; info?: string };
type KeybindConfig = { command: string; keys: Array<string>; commandStr?: string };
const Callback = "callback";
const Command = "command";
const DumpLogs = false;
type Keybind = {
domain: string;
@@ -39,7 +38,7 @@ type Keybind = {
commandStr: string;
};
const KeybindLevels = ["system", "modal", "app", "mainview", "pane", "plugin", "control"];
const KeybindLevels = ["system", "modal", "app", "mainview", "pane", "plugin"];
class KeybindManager {
domainCallbacks: Map<string, KeybindCallback>;
@@ -94,7 +93,6 @@ class KeybindManager {
throw new Error("invalid keybind key");
}
}
// if user doesn't specify a command string or a description, we will revert to the old one
let defaultCmd = this.keyDescriptionsMap.get(curKeybind.command);
if (
defaultCmd != null &&
@@ -103,13 +101,6 @@ class KeybindManager {
) {
curKeybind.commandStr = this.keyDescriptionsMap.get(curKeybind.command).commandStr;
}
if (
defaultCmd != null &&
defaultCmd.info != null &&
(curKeybind.info == null || curKeybind.info == "")
) {
curKeybind.info = this.keyDescriptionsMap.get(curKeybind.command).info;
}
newKeyDescriptions.set(curKeybind.command, curKeybind);
}
} catch (e) {
@@ -123,83 +114,6 @@ class KeybindManager {
this.keyDescriptionsMap = newKeyDescriptions;
}
prettyPrintKeybind(keyDescription: string): string {
let keyPress = parseKeyDescription(keyDescription);
let returnString = "";
if (keyPress.mods.Cmd) {
returnString += "⌘";
}
if (keyPress.mods.Ctrl) {
returnString += "⌃";
}
if (keyPress.mods.Option) {
returnString += "⌥";
}
if (keyPress.mods.Shift) {
returnString += "⇧";
}
if (keyPress.mods.Meta) {
returnString += "M";
}
if (keyPress.mods.Alt) {
returnString += "⌥";
}
returnString += keyPress.key;
return returnString;
}
getUIDescription(keyDescription: string, prettyPrint: boolean = true): KeybindConfig {
let keybinds = this.getKeybindsFromDescription(keyDescription, prettyPrint);
if (!this.keyDescriptionsMap.has(keyDescription)) {
return { keys: keybinds, info: "", command: keyDescription, commandStr: "" };
}
let curKeybindConfig = this.keyDescriptionsMap.get(keyDescription);
let curInfo = "";
if (curKeybindConfig.info) {
curInfo = curKeybindConfig.info;
}
let curCommandStr = "";
if (curKeybindConfig.commandStr) {
curCommandStr = curKeybindConfig.commandStr;
}
return { keys: keybinds, info: curInfo, commandStr: curCommandStr, command: keyDescription };
}
getKeybindsFromDescription(keyDescription: string, prettyPrint: boolean = true): Array<string> {
if (!this.keyDescriptionsMap.has(keyDescription)) {
return [];
}
let keyBinds = this.keyDescriptionsMap.get(keyDescription).keys;
if (!prettyPrint) {
return keyBinds;
}
let keybindsArray = [];
for (let index = 0; index < keyBinds.length; index++) {
let curKeybind = keyBinds[index];
let curPrettyPrintString = this.prettyPrintKeybind(curKeybind);
keybindsArray.push(curPrettyPrintString);
}
return keybindsArray;
}
getAllKeybindUIDescriptions(prettyPrint: boolean = true): KeybindConfigArray {
let keybindsList = [];
let keybindDescriptions = this.keyDescriptionsMap.keys();
for (let keyDesc of keybindDescriptions) {
keybindsList.push(this.getUIDescription(keyDesc, prettyPrint));
}
return keybindsList;
}
getAllKeybinds(prettyPrint: boolean = true): Array<Array<string>> {
let keybindsList = [];
let keybindDescriptions = this.keyDescriptionsMap.keys();
for (let keyDesc of keybindDescriptions) {
keybindsList.push(this.getKeybindsFromDescription(keyDesc, prettyPrint));
}
return keybindsList;
}
runSlashCommand(curKeybind: Keybind): boolean {
let curConfigKeybind = this.keyDescriptionsMap.get(curKeybind.keybinding);
if (curConfigKeybind == null || curConfigKeybind.commandStr == null || curKeybind.commandStr == "") {
@@ -233,9 +147,6 @@ class KeybindManager {
for (let index = keybindsArray.length - 1; index >= 0; index--) {
let curKeybind = keybindsArray[index];
if (this.checkKeyPressed(event, curKeybind.keybinding)) {
if (DumpLogs) {
console.log("keybind found", curKeybind);
}
let shouldReturn = false;
let shouldRunCommand = true;
if (curKeybind.callback != null) {
@@ -267,21 +178,13 @@ class KeybindManager {
if (modalLevel.length != 0) {
// console.log("processing modal");
// special case when modal keybindings are present
let controlLevel = this.levelMap.get("control");
let shouldReturn = this.processLevel(nativeEvent, event, controlLevel);
if (shouldReturn) {
return true;
}
shouldReturn = this.processLevel(nativeEvent, event, modalLevel);
let shouldReturn = this.processLevel(nativeEvent, event, modalLevel);
if (shouldReturn) {
return true;
}
let systemLevel = this.levelMap.get("system");
return this.processLevel(nativeEvent, event, systemLevel);
}
if (DumpLogs) {
console.log("levels:", this.levelMap, "event:", event);
}
for (let index = this.levelArray.length - 1; index >= 0; index--) {
let curLevel = this.levelArray[index];
let curKeybindsArray;
@@ -454,6 +357,7 @@ function parseKeyDescription(keyDescription: string): KeyPressDecl {
for (let key of keys) {
if (key == "Cmd") {
rtn.mods.Cmd = true;
rtn.mods.Meta = true;
} else if (key == "Shift") {
rtn.mods.Shift = true;
} else if (key == "Ctrl") {
@@ -503,10 +407,10 @@ function notMod(keyPressMod, eventMod) {
function checkKeyPressed(event: WaveKeyboardEvent, keyDescription: string): boolean {
let keyPress = parseKeyDescription(keyDescription);
if (!keyPress.mods.Alt && notMod(keyPress.mods.Option, event.option)) {
if (notMod(keyPress.mods.Option, event.option)) {
return false;
}
if (!keyPress.mods.Meta && notMod(keyPress.mods.Cmd, event.cmd)) {
if (notMod(keyPress.mods.Cmd, event.cmd)) {
return false;
}
if (notMod(keyPress.mods.Shift, event.shift)) {
@@ -515,10 +419,10 @@ function checkKeyPressed(event: WaveKeyboardEvent, keyDescription: string): bool
if (notMod(keyPress.mods.Ctrl, event.control)) {
return false;
}
if (keyPress.mods.Alt && !event.alt) {
if (notMod(keyPress.mods.Alt, event.alt)) {
return false;
}
if (keyPress.mods.Meta && !event.meta) {
if (notMod(keyPress.mods.Meta, event.meta)) {
return false;
}
let eventKey = "";

Some files were not shown because too many files have changed in this diff Show More