mirror of
https://github.com/wavetermdev/backup.git
synced 2026-04-22 15:26:58 -07:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e2ff745f55 | |||
| eab8e3be02 | |||
| e589d9c4fa | |||
| 94de0460b4 | |||
| 71b09cb44e | |||
| 07abaa92fa | |||
| 2a4d85430a | |||
| d319e72609 | |||
| 7a5afccab3 | |||
| efe567398a | |||
| 187509504d | |||
| 903b26bfca |
@@ -8,6 +8,7 @@ export const SESSION_SETTINGS = "sessionSettings";
|
||||
export const LINE_SETTINGS = "lineSettings";
|
||||
export const CLIENT_SETTINGS = "clientSettings";
|
||||
export const TAB_SWITCHER = "tabSwitcher";
|
||||
export const USER_INPUT = "userInput";
|
||||
|
||||
export const LineContainer_Main = "main";
|
||||
export const LineContainer_History = "history";
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
margin-bottom: 10px;
|
||||
font-family: @markdown-font;
|
||||
font-size: 14px;
|
||||
overflow-wrap: break-word;
|
||||
|
||||
code {
|
||||
background-color: @markdown-highlight;
|
||||
|
||||
@@ -60,7 +60,13 @@ class PasswordField extends TextField {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={cn(`wave-textfield wave-password ${className || ""}`, { focused: focused, error: error })}>
|
||||
<div
|
||||
className={cn(`wave-textfield wave-password ${className || ""}`, {
|
||||
focused: focused,
|
||||
error: error,
|
||||
"no-label": !label,
|
||||
})}
|
||||
>
|
||||
{decoration?.startDecoration && <>{decoration.startDecoration}</>}
|
||||
<div className="wave-textfield-inner">
|
||||
<label
|
||||
|
||||
@@ -9,3 +9,4 @@ export { TabSwitcherModal } from "./tabswitcher";
|
||||
export { SessionSettingsModal } from "./sessionsettings";
|
||||
export { ScreenSettingsModal } from "./screensettings";
|
||||
export { LineSettingsModal } from "./linesettings";
|
||||
export { UserInputModal } from "./userinput";
|
||||
|
||||
@@ -17,7 +17,7 @@ class ModalsProvider extends React.Component {
|
||||
for (let i = 0; i < store.length; i++) {
|
||||
let entry = store[i];
|
||||
let Comp = entry.component;
|
||||
rtn.push(<Comp key={entry.uniqueKey} />);
|
||||
rtn.push(<Comp key={entry.uniqueKey} {...entry.props} />);
|
||||
}
|
||||
return <>{rtn}</>;
|
||||
}
|
||||
|
||||
@@ -12,19 +12,21 @@ import {
|
||||
SessionSettingsModal,
|
||||
ScreenSettingsModal,
|
||||
LineSettingsModal,
|
||||
UserInputModal,
|
||||
} from "../modals";
|
||||
import * as constants from "../../appconst";
|
||||
|
||||
const modalsRegistry: { [key: string]: () => React.ReactElement } = {
|
||||
[constants.ABOUT]: () => <AboutModal />,
|
||||
[constants.CREATE_REMOTE]: () => <CreateRemoteConnModal />,
|
||||
[constants.VIEW_REMOTE]: () => <ViewRemoteConnDetailModal />,
|
||||
[constants.EDIT_REMOTE]: () => <EditRemoteConnModal />,
|
||||
[constants.ALERT]: () => <AlertModal />,
|
||||
[constants.SCREEN_SETTINGS]: () => <ScreenSettingsModal />,
|
||||
[constants.SESSION_SETTINGS]: () => <SessionSettingsModal />,
|
||||
[constants.LINE_SETTINGS]: () => <LineSettingsModal />,
|
||||
[constants.TAB_SWITCHER]: () => <TabSwitcherModal />,
|
||||
const modalsRegistry: { [key: string]: React.ComponentType } = {
|
||||
[constants.ABOUT]: AboutModal,
|
||||
[constants.CREATE_REMOTE]: CreateRemoteConnModal,
|
||||
[constants.VIEW_REMOTE]: ViewRemoteConnDetailModal,
|
||||
[constants.EDIT_REMOTE]: EditRemoteConnModal,
|
||||
[constants.ALERT]: AlertModal,
|
||||
[constants.SCREEN_SETTINGS]: ScreenSettingsModal,
|
||||
[constants.SESSION_SETTINGS]: SessionSettingsModal,
|
||||
[constants.LINE_SETTINGS]: LineSettingsModal,
|
||||
[constants.TAB_SWITCHER]: TabSwitcherModal,
|
||||
[constants.USER_INPUT]: UserInputModal,
|
||||
};
|
||||
|
||||
export { modalsRegistry };
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
@import "../../../app/common/themes/themes.less";
|
||||
|
||||
.userinput-modal {
|
||||
width: 500px;
|
||||
|
||||
.wave-modal-content {
|
||||
.wave-modal-body {
|
||||
padding: 20px 20px;
|
||||
|
||||
.userinput-query {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
import * as React from "react";
|
||||
import { GlobalModel } from "../../../models";
|
||||
import { Choose, When, If } from "tsx-control-statements/components";
|
||||
import { Modal, PasswordField, Markdown } from "../elements";
|
||||
import { UserInputRequest } from "../../../types/types";
|
||||
|
||||
import "./userinput.less";
|
||||
|
||||
export const UserInputModal = (userInputRequest: UserInputRequest) => {
|
||||
const [responseText, setResponseText] = React.useState("");
|
||||
const [countdown, setCountdown] = React.useState(Math.floor(userInputRequest.timeoutms / 1000));
|
||||
|
||||
const closeModal = React.useCallback(() => {
|
||||
GlobalModel.sendUserInput({
|
||||
type: "userinputresp",
|
||||
requestid: userInputRequest.requestid,
|
||||
errormsg: "Canceled by the user",
|
||||
});
|
||||
GlobalModel.remotesModel.closeModal();
|
||||
}, [responseText, userInputRequest]);
|
||||
|
||||
const handleSendText = React.useCallback(() => {
|
||||
GlobalModel.sendUserInput({
|
||||
type: "userinputresp",
|
||||
requestid: userInputRequest.requestid,
|
||||
text: responseText,
|
||||
});
|
||||
GlobalModel.remotesModel.closeModal();
|
||||
}, [responseText, userInputRequest]);
|
||||
|
||||
const handleSendConfirm = React.useCallback(
|
||||
(response: boolean) => {
|
||||
GlobalModel.sendUserInput({
|
||||
type: "userinputresp",
|
||||
requestid: userInputRequest.requestid,
|
||||
confirm: response,
|
||||
});
|
||||
GlobalModel.remotesModel.closeModal();
|
||||
},
|
||||
[userInputRequest]
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
let timeout: ReturnType<typeof setTimeout>;
|
||||
if (countdown == 0) {
|
||||
timeout = setTimeout(() => {
|
||||
GlobalModel.remotesModel.closeModal();
|
||||
}, 300);
|
||||
} else {
|
||||
timeout = setTimeout(() => {
|
||||
setCountdown(countdown - 1);
|
||||
}, 1000);
|
||||
}
|
||||
return () => clearTimeout(timeout);
|
||||
}, [countdown]);
|
||||
|
||||
return (
|
||||
<Modal className="userinput-modal">
|
||||
<Modal.Header onClose={closeModal} title={userInputRequest.title + ` (${countdown})`} />
|
||||
<div className="wave-modal-body">
|
||||
<div className="userinput-query">
|
||||
<If condition={userInputRequest.markdown}>
|
||||
<Markdown text={userInputRequest.querytext} />
|
||||
</If>
|
||||
<If condition={!userInputRequest.markdown}>{userInputRequest.querytext}</If>
|
||||
</div>
|
||||
<Choose>
|
||||
<When condition={userInputRequest.responsetype == "text"}>
|
||||
<PasswordField onChange={setResponseText} value={responseText} maxLength={400} />
|
||||
</When>
|
||||
</Choose>
|
||||
</div>
|
||||
<Choose>
|
||||
<When condition={userInputRequest.responsetype == "text"}>
|
||||
<Modal.Footer onCancel={closeModal} onOk={handleSendText} okLabel="Continue" />
|
||||
</When>
|
||||
<When condition={userInputRequest.responsetype == "confirm"}>
|
||||
<Modal.Footer
|
||||
onCancel={() => handleSendConfirm(false)}
|
||||
onOk={() => handleSendConfirm(true)}
|
||||
okLabel="Yes"
|
||||
cancelLabel="No"
|
||||
/>
|
||||
</When>
|
||||
</Choose>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
@@ -54,6 +54,8 @@
|
||||
}
|
||||
|
||||
.remote-detail {
|
||||
width: 100%;
|
||||
|
||||
.settings-field {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@@ -91,8 +93,9 @@
|
||||
}
|
||||
|
||||
.terminal-wrapper {
|
||||
width: 100%;
|
||||
margin-top: 5px;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
|
||||
.terminal-connectelem {
|
||||
height: 163px !important; // Needed to override plugin height
|
||||
@@ -111,7 +114,6 @@
|
||||
|
||||
.xterm-screen {
|
||||
padding: 10px;
|
||||
width: 541px !important; // Needed to override plugin width
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,12 +12,10 @@ import * as T from "../../../types/types";
|
||||
import { Modal, Tooltip, Button, Status } from "../elements";
|
||||
import * as util from "../../../util/util";
|
||||
import * as textmeasure from "../../../util/textmeasure";
|
||||
import * as appconst from "../../appconst";
|
||||
|
||||
import "./viewremoteconndetail.less";
|
||||
|
||||
const RemotePtyRows = 9;
|
||||
const RemotePtyCols = 80;
|
||||
|
||||
@mobxReact.observer
|
||||
class ViewRemoteConnDetailModal extends React.Component<{}, {}> {
|
||||
termRef: React.RefObject<any> = React.createRef();
|
||||
@@ -293,7 +291,7 @@ class ViewRemoteConnDetailModal extends React.Component<{}, {}> {
|
||||
let model = this.model;
|
||||
let isTermFocused = this.model.remoteTermWrapFocus.get();
|
||||
let termFontSize = GlobalModel.termFontSize.get();
|
||||
let termWidth = textmeasure.termWidthFromCols(RemotePtyCols, termFontSize);
|
||||
let termWidth = textmeasure.termWidthFromCols(appconst.RemotePtyCols, termFontSize);
|
||||
let remoteAliasText = util.isBlank(remote.remotealias) ? "(none)" : remote.remotealias;
|
||||
let selectedRemoteStatus = this.getSelectedRemote().status;
|
||||
|
||||
@@ -371,7 +369,7 @@ class ViewRemoteConnDetailModal extends React.Component<{}, {}> {
|
||||
ref={this.termRef}
|
||||
data-remoteid={remote.remoteid}
|
||||
style={{
|
||||
height: textmeasure.termHeightFromRows(RemotePtyRows, termFontSize),
|
||||
height: textmeasure.termHeightFromRows(appconst.RemotePtyRows, termFontSize),
|
||||
width: termWidth,
|
||||
}}
|
||||
></div>
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #3B3F3A;
|
||||
border: 1px solid #3b3f3a;
|
||||
background: rgba(213, 254, 175, 0.03);
|
||||
}
|
||||
|
||||
|
||||
&.checkbox-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
@@ -30,7 +30,7 @@
|
||||
height: 16px;
|
||||
fill: rgba(213, 254, 175, 0.03);
|
||||
stroke-width: 1px;
|
||||
stroke: #3B3F3A;
|
||||
stroke: #3b3f3a;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,6 +264,7 @@
|
||||
margin: 0px 10px 10px 10px;
|
||||
table-layout: fixed;
|
||||
border-top: 2px solid #ccc;
|
||||
width: calc(100% - 20px);
|
||||
|
||||
tr.active-history-item {
|
||||
td {
|
||||
@@ -309,9 +310,8 @@
|
||||
tr.history-item {
|
||||
padding: 0 10px 0 10px;
|
||||
display: flex;
|
||||
border-bottom: 1px solid rgba(250, 250, 250, 0.10);
|
||||
border-bottom: 1px solid rgba(250, 250, 250, 0.1);
|
||||
align-items: center;
|
||||
height: 40px;
|
||||
color: @text-secondary;
|
||||
|
||||
&.is-selected {
|
||||
|
||||
+23
-17
@@ -14,6 +14,7 @@ import { sprintf } from "sprintf-js";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { checkKeyPressed, adaptFromElectronKeyEvent, setKeyUtilPlatform } from "../util/keyutil";
|
||||
import { platform } from "os";
|
||||
import type * as T from "../types/types";
|
||||
|
||||
const WaveAppPathVarName = "WAVETERM_APP_PATH";
|
||||
const WaveDevVarName = "WAVETERM_DEV";
|
||||
@@ -40,19 +41,21 @@ let unameArch: string = process.arch;
|
||||
if (unameArch == "x64") {
|
||||
unameArch = "amd64";
|
||||
}
|
||||
let logger;
|
||||
let loggerTransports: winston.transport[] = [
|
||||
new winston.transports.File({ filename: path.join(waveHome, "waveterm-app.log"), level: "info" }),
|
||||
];
|
||||
if (isDev) {
|
||||
loggerTransports.push(new winston.transports.Console());
|
||||
}
|
||||
let loggerConfig = {
|
||||
level: "info",
|
||||
format: winston.format.combine(
|
||||
winston.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }),
|
||||
winston.format.printf((info) => `${info.timestamp} ${info.message}`)
|
||||
),
|
||||
transports: [new winston.transports.File({ filename: path.join(waveHome, "waveterm-app.log"), level: "info" })],
|
||||
transports: loggerTransports,
|
||||
};
|
||||
if (isDev) {
|
||||
loggerConfig.transports.push(new winston.transports.Console());
|
||||
}
|
||||
logger = winston.createLogger(loggerConfig);
|
||||
let logger = winston.createLogger(loggerConfig);
|
||||
function log(...msg) {
|
||||
try {
|
||||
logger.info(util.format(...msg));
|
||||
@@ -75,7 +78,7 @@ if (isDev) {
|
||||
}
|
||||
let app = electron.app;
|
||||
app.setName(isDev ? "Wave (Dev)" : "Wave");
|
||||
let waveSrvProc = null;
|
||||
let waveSrvProc: child_process.ChildProcessWithoutNullStreams | null = null;
|
||||
let waveSrvShouldRestart = false;
|
||||
|
||||
electron.dialog.showErrorBox = (title, content) => {
|
||||
@@ -101,8 +104,11 @@ function checkPromptMigrate() {
|
||||
// don't migrate if we're running dev version or if wave home directory already exists
|
||||
return;
|
||||
}
|
||||
let homeDir = process.env.HOME;
|
||||
let promptHome = path.join(homeDir, "prompt");
|
||||
if (process.env.HOME == null) {
|
||||
return;
|
||||
}
|
||||
let homeDir: string = process.env.HOME;
|
||||
let promptHome: string = path.join(homeDir, "prompt");
|
||||
if (!fs.existsSync(promptHome) || !fs.existsSync(path.join(promptHome, "prompt.db"))) {
|
||||
// make sure we have a valid prompt home directory (prompt.db must exist inside)
|
||||
return;
|
||||
@@ -170,7 +176,7 @@ function readAuthKey() {
|
||||
return authKeyStr.trim();
|
||||
}
|
||||
|
||||
let menuTemplate = [
|
||||
let menuTemplate: Electron.MenuItemConstructorOptions[] = [
|
||||
{
|
||||
role: "appMenu",
|
||||
submenu: [
|
||||
@@ -222,7 +228,7 @@ function getMods(input: any) {
|
||||
return { meta: input.meta, shift: input.shift, ctrl: input.control, alt: input.alt };
|
||||
}
|
||||
|
||||
function shNavHandler(event: any, url: any) {
|
||||
function shNavHandler(event: Electron.Event<Electron.WebContentsWillNavigateEventParams>, url: string) {
|
||||
event.preventDefault();
|
||||
if (url.startsWith("https://") || url.startsWith("http://") || url.startsWith("file://")) {
|
||||
console.log("open external, shNav", url);
|
||||
@@ -232,12 +238,13 @@ function shNavHandler(event: any, url: any) {
|
||||
}
|
||||
}
|
||||
|
||||
function shFrameNavHandler(event: any, url: any) {
|
||||
function shFrameNavHandler(event: Electron.Event<Electron.WebContentsWillFrameNavigateEventParams>) {
|
||||
if (!event.frame || event.frame.parent == null) {
|
||||
// only use this handler to process iframe events (non-iframe events go to shNavHandler)
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
let url = event.url;
|
||||
console.log(`frame-navigation url=${url} frame=${event.frame.name}`);
|
||||
if (event.frame.name == "webview") {
|
||||
// "webview" links always open in new window
|
||||
@@ -250,7 +257,7 @@ function shFrameNavHandler(event: any, url: any) {
|
||||
return;
|
||||
}
|
||||
|
||||
function createMainWindow(clientData) {
|
||||
function createMainWindow(clientData: T.ClientDataType | null) {
|
||||
let bounds = calcBounds(clientData);
|
||||
setKeyUtilPlatform(platform());
|
||||
let win = new electron.BrowserWindow({
|
||||
@@ -644,12 +651,11 @@ electron.ipcMain.on("context-editmenu", (event, { x, y }, opts) => {
|
||||
}
|
||||
console.log("context-editmenu");
|
||||
let menu = new electron.Menu();
|
||||
let menuItem = null;
|
||||
if (opts.showCut) {
|
||||
menuItem = new electron.MenuItem({ label: "Cut", role: "cut" });
|
||||
let menuItem = new electron.MenuItem({ label: "Cut", role: "cut" });
|
||||
menu.append(menuItem);
|
||||
}
|
||||
menuItem = new electron.MenuItem({ label: "Copy", role: "copy" });
|
||||
let menuItem = new electron.MenuItem({ label: "Copy", role: "copy" });
|
||||
menu.append(menuItem);
|
||||
menuItem = new electron.MenuItem({ label: "Paste", role: "paste" });
|
||||
menu.append(menuItem);
|
||||
@@ -657,7 +663,7 @@ electron.ipcMain.on("context-editmenu", (event, { x, y }, opts) => {
|
||||
});
|
||||
|
||||
async function createMainWindowWrap() {
|
||||
let clientData = null;
|
||||
let clientData: T.ClientDataType | null = null;
|
||||
try {
|
||||
clientData = await getClientDataPoll(1);
|
||||
} catch (e) {
|
||||
|
||||
@@ -8,7 +8,7 @@ import { GlobalModel } from "./global";
|
||||
class CommandRunner {
|
||||
private constructor() {}
|
||||
|
||||
static getInstance() {
|
||||
static getInstance(): CommandRunner {
|
||||
if (!(window as any).GlobalCommandRunner) {
|
||||
(window as any).GlobalCommandRunner = new CommandRunner();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Model } from "./model";
|
||||
import { CommandRunner } from "./commandrunner";
|
||||
|
||||
const GlobalModel = Model.getInstance();
|
||||
const GlobalCommandRunner = CommandRunner.getInstance();
|
||||
const GlobalModel: Model = Model.getInstance();
|
||||
const GlobalCommandRunner: CommandRunner = CommandRunner.getInstance();
|
||||
export { GlobalModel, GlobalCommandRunner };
|
||||
|
||||
+10
-15
@@ -13,10 +13,10 @@ import {
|
||||
HistoryQueryOpts,
|
||||
HistoryTypeStrs,
|
||||
OpenAICmdInfoChatMessageType,
|
||||
OV,
|
||||
StrWithPos,
|
||||
} from "../types/types";
|
||||
import { StrWithPos } from "../types/types";
|
||||
import * as appconst from "../app/appconst";
|
||||
import { OV } from "../types/types";
|
||||
import { Model } from "./model";
|
||||
import { GlobalCommandRunner } from "./global";
|
||||
|
||||
@@ -207,7 +207,6 @@ class InputModel {
|
||||
this.historyQueryOpts.set(opts);
|
||||
let bestIndex = this.findBestNewIndex(oldItem);
|
||||
setTimeout(() => this.setHistoryIndex(bestIndex, true), 10);
|
||||
return;
|
||||
})();
|
||||
}
|
||||
|
||||
@@ -624,13 +623,17 @@ class InputModel {
|
||||
}
|
||||
|
||||
openAIAssistantChat(): void {
|
||||
this.aIChatShow.set(true);
|
||||
this.setAIChatFocus();
|
||||
mobx.action(() => {
|
||||
this.aIChatShow.set(true);
|
||||
this.setAIChatFocus();
|
||||
})();
|
||||
}
|
||||
|
||||
closeAIAssistantChat(): void {
|
||||
this.aIChatShow.set(false);
|
||||
this.giveFocus();
|
||||
mobx.action(() => {
|
||||
this.aIChatShow.set(false);
|
||||
this.giveFocus();
|
||||
})();
|
||||
}
|
||||
|
||||
clearAIAssistantChat(): void {
|
||||
@@ -721,14 +724,6 @@ class InputModel {
|
||||
setCurLine(val: string): void {
|
||||
let hidx = this.historyIndex.get();
|
||||
mobx.action(() => {
|
||||
// if (val == "\" ") {
|
||||
// this.setInputMode("comment");
|
||||
// val = "";
|
||||
// }
|
||||
// if (val == "//") {
|
||||
// this.setInputMode("global");
|
||||
// val = "";
|
||||
// }
|
||||
if (this.modHistory.length <= hidx) {
|
||||
this.modHistory.length = hidx + 1;
|
||||
}
|
||||
|
||||
@@ -8,14 +8,14 @@ import { modalsRegistry } from "../app/common/modals/registry";
|
||||
import { OArr } from "../types/types";
|
||||
|
||||
class ModalsModel {
|
||||
store: OArr<ModalStoreEntry> = mobx.observable.array([], { name: "ModalsModel-store" });
|
||||
store: OArr<ModalStoreEntry> = mobx.observable.array([], { name: "ModalsModel-store", deep: false });
|
||||
|
||||
pushModal(modalId: string) {
|
||||
pushModal(modalId: string, props?: any) {
|
||||
const modalFactory = modalsRegistry[modalId];
|
||||
|
||||
if (modalFactory && !this.store.some((modal) => modal.id === modalId)) {
|
||||
mobx.action(() => {
|
||||
this.store.push({ id: modalId, component: modalFactory, uniqueKey: uuidv4() });
|
||||
this.store.push({ id: modalId, component: modalFactory, uniqueKey: uuidv4(), props });
|
||||
})();
|
||||
}
|
||||
}
|
||||
|
||||
+300
-243
File diff suppressed because it is too large
Load Diff
@@ -51,6 +51,8 @@ import {
|
||||
HistoryViewDataType,
|
||||
AlertMessageType,
|
||||
HistorySearchParams,
|
||||
UserInputRequest,
|
||||
UserInputResponsePacket,
|
||||
FocusTypeStrs,
|
||||
ScreenLinesType,
|
||||
HistoryTypeStrs,
|
||||
@@ -3376,14 +3378,14 @@ class RemotesModel {
|
||||
}
|
||||
|
||||
class ModalsModel {
|
||||
store: OArr<T.ModalStoreEntry> = mobx.observable.array([], { name: "ModalsModel-store" });
|
||||
store: OArr<T.ModalStoreEntry> = mobx.observable.array([], { name: "ModalsModel-store", deep: false });
|
||||
|
||||
pushModal(modalId: string) {
|
||||
pushModal(modalId: string, props?: any) {
|
||||
const modalFactory = modalsRegistry[modalId];
|
||||
|
||||
if (modalFactory && !this.store.some((modal) => modal.id === modalId)) {
|
||||
mobx.action(() => {
|
||||
this.store.push({ id: modalId, component: modalFactory, uniqueKey: uuidv4() });
|
||||
this.store.push({ id: modalId, component: modalFactory, uniqueKey: uuidv4(), props: props });
|
||||
})();
|
||||
}
|
||||
}
|
||||
@@ -4184,6 +4186,10 @@ class Model {
|
||||
this.getScreenById_single(snc.screenid)?.setNumRunningCmds(snc.num);
|
||||
}
|
||||
}
|
||||
if ("userinputrequest" in update) {
|
||||
let userInputRequest: UserInputRequest = update.userinputrequest;
|
||||
this.modalsModel.pushModal(appconst.USER_INPUT, userInputRequest);
|
||||
}
|
||||
}
|
||||
|
||||
updateRemotes(remotes: RemoteType[]): void {
|
||||
@@ -4591,6 +4597,10 @@ class Model {
|
||||
this.ws.pushMessage(inputPacket);
|
||||
}
|
||||
|
||||
sendUserInput(userInputResponsePacket: UserInputResponsePacket) {
|
||||
this.ws.pushMessage(userInputResponsePacket);
|
||||
}
|
||||
|
||||
sendCmdInputText(screenId: string, sp: T.StrWithPos) {
|
||||
let pk: T.CmdInputTextPacketType = {
|
||||
type: "cmdinputtext",
|
||||
@@ -12,9 +12,6 @@ import { GlobalCommandRunner } from "./global";
|
||||
import { Model } from "./model";
|
||||
import { getTermPtyData } from "../util/modelutil";
|
||||
|
||||
const RemotePtyRows = 8; // also in main.tsx
|
||||
const RemotePtyCols = 80;
|
||||
|
||||
class RemotesModel {
|
||||
globalModel: Model;
|
||||
selectedRemoteId: OV<string> = mobx.observable.box(null, {
|
||||
@@ -180,14 +177,14 @@ class RemotesModel {
|
||||
return;
|
||||
}
|
||||
let termOpts = {
|
||||
rows: RemotePtyRows,
|
||||
cols: RemotePtyCols,
|
||||
rows: appconst.RemotePtyRows,
|
||||
cols: appconst.RemotePtyCols,
|
||||
flexrows: false,
|
||||
maxptysize: 64 * 1024,
|
||||
};
|
||||
let termWrap = new TermWrap(elem, {
|
||||
termContext: { remoteId: remoteId },
|
||||
usedRows: RemotePtyRows,
|
||||
usedRows: appconst.RemotePtyRows,
|
||||
termOpts: termOpts,
|
||||
winSize: null,
|
||||
keyHandler: (e, termWrap) => {
|
||||
|
||||
@@ -139,7 +139,7 @@ class ScreenLines {
|
||||
return;
|
||||
}
|
||||
let lineIdx = 0;
|
||||
for (lineIdx = 0; lineIdx < lines.length; lineIdx++) {
|
||||
for (lineIdx; lineIdx < lines.length; lineIdx++) {
|
||||
let lineId = lines[lineIdx].lineid;
|
||||
let curTs = lines[lineIdx].ts;
|
||||
if (lineId == line.lineid) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user