mirror of
https://github.com/wavetermdev/backup.git
synced 2026-04-22 15:26:58 -07:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c06d846efe | |||
| 2a4d85430a | |||
| d319e72609 | |||
| 7a5afccab3 | |||
| efe567398a | |||
| 187509504d | |||
| 903b26bfca |
@@ -1,13 +1,13 @@
|
||||
import * as React from "react";
|
||||
import { GlobalModel } from "../../../models";
|
||||
import { Choose, When, If } from "tsx-control-statements";
|
||||
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(null);
|
||||
const [responseText, setResponseText] = React.useState("");
|
||||
const [countdown, setCountdown] = React.useState(Math.floor(userInputRequest.timeoutms / 1000));
|
||||
|
||||
const closeModal = React.useCallback(() => {
|
||||
|
||||
@@ -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>
|
||||
|
||||
+21
-14
@@ -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 * as T from "../types/types";
|
||||
|
||||
const WaveAppPathVarName = "WAVETERM_APP_PATH";
|
||||
const WaveDevVarName = "WAVETERM_DEV";
|
||||
@@ -37,21 +38,25 @@ ensureDir(waveHome);
|
||||
// normalize darwin/x64 to darwin/amd64 for GOARCH compatibility
|
||||
let unamePlatform = process.platform;
|
||||
let unameArch: string = process.arch;
|
||||
``;
|
||||
if (unameArch == "x64") {
|
||||
unameArch = "amd64";
|
||||
}
|
||||
let logger;
|
||||
let loggerConfig = {
|
||||
let logger: winston.Logger;
|
||||
let transports: winston.transport[] = [
|
||||
new winston.transports.File({ filename: path.join(waveHome, "waveterm-app.log"), level: "info" }),
|
||||
];
|
||||
if (isDev) {
|
||||
transports.push(new winston.transports.Console());
|
||||
}
|
||||
let loggerConfig: winston.LoggerOptions = {
|
||||
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: transports,
|
||||
};
|
||||
if (isDev) {
|
||||
loggerConfig.transports.push(new winston.transports.Console());
|
||||
}
|
||||
logger = winston.createLogger(loggerConfig);
|
||||
function log(...msg) {
|
||||
try {
|
||||
@@ -75,7 +80,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 +106,8 @@ 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");
|
||||
let homeDir: string = process.env.HOME as string;
|
||||
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 +175,7 @@ function readAuthKey() {
|
||||
return authKeyStr.trim();
|
||||
}
|
||||
|
||||
let menuTemplate = [
|
||||
let menuTemplate: (Electron.MenuItem | Electron.MenuItemConstructorOptions)[] = [
|
||||
{
|
||||
role: "appMenu",
|
||||
submenu: [
|
||||
@@ -250,7 +255,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({
|
||||
@@ -609,7 +614,9 @@ function runWaveSrv() {
|
||||
pReject(new Error(sprintf("failed to start local server (%s)", waveSrvCmd)));
|
||||
if (waveSrvShouldRestart) {
|
||||
waveSrvShouldRestart = false;
|
||||
this.runWaveSrv();
|
||||
// small timeout here so we can reuse the listen socket
|
||||
// this is normally only used in dev mode for debugging
|
||||
setTimeout(runWaveSrv, 500);
|
||||
}
|
||||
});
|
||||
proc.on("spawn", (e) => {
|
||||
@@ -644,7 +651,7 @@ electron.ipcMain.on("context-editmenu", (event, { x, y }, opts) => {
|
||||
}
|
||||
console.log("context-editmenu");
|
||||
let menu = new electron.Menu();
|
||||
let menuItem = null;
|
||||
let menuItem: Electron.MenuItem;
|
||||
if (opts.showCut) {
|
||||
menuItem = new electron.MenuItem({ label: "Cut", role: "cut" });
|
||||
menu.append(menuItem);
|
||||
@@ -657,7 +664,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) {
|
||||
|
||||
+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;
|
||||
}
|
||||
|
||||
+293
-246
File diff suppressed because it is too large
Load Diff
@@ -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) {
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
|
||||
.terminal-wrapper {
|
||||
.xterm-viewport {
|
||||
overflow-y: hidden;
|
||||
overflow: hidden;
|
||||
}
|
||||
&:hover .xterm-viewport,
|
||||
&:focus-within .xterm-viewport {
|
||||
overflow-y: auto;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
|
||||
+45
-15
@@ -29,7 +29,6 @@ type SessionDataType = {
|
||||
|
||||
// for updates
|
||||
remove?: boolean;
|
||||
full?: boolean;
|
||||
};
|
||||
|
||||
type LineStateType = { [k: string]: any };
|
||||
@@ -92,7 +91,6 @@ type ScreenDataType = {
|
||||
anchor: { anchorline: number; anchoroffset: number };
|
||||
|
||||
// for updates
|
||||
full?: boolean;
|
||||
remove?: boolean;
|
||||
};
|
||||
|
||||
@@ -260,6 +258,11 @@ type CmdDataType = {
|
||||
restarted?: boolean;
|
||||
};
|
||||
|
||||
type LineUpdateType = {
|
||||
line: LineType;
|
||||
cmd: CmdDataType;
|
||||
};
|
||||
|
||||
type PtyDataUpdateType = {
|
||||
screenid: string;
|
||||
lineid: string;
|
||||
@@ -309,30 +312,47 @@ type ScreenNumRunningCommandsUpdateType = {
|
||||
num: number;
|
||||
};
|
||||
|
||||
type ConnectUpdateType = {
|
||||
sessions: SessionDataType[];
|
||||
screens: ScreenDataType[];
|
||||
remotes: RemoteType[];
|
||||
screenstatusindicators: ScreenStatusIndicatorUpdateType[];
|
||||
screennumrunningcommands: ScreenNumRunningCommandsUpdateType[];
|
||||
activesessionid: string;
|
||||
};
|
||||
|
||||
type BookmarksUpdateType = {
|
||||
bookmarks: BookmarkType[];
|
||||
selectedbookmark: string;
|
||||
};
|
||||
|
||||
type MainViewUpdateType = {
|
||||
mainview: string;
|
||||
historyview?: HistoryViewDataType;
|
||||
bookmarksview?: BookmarksUpdateType;
|
||||
};
|
||||
|
||||
type ModelUpdateType = {
|
||||
interactive: boolean;
|
||||
sessions?: SessionDataType[];
|
||||
session?: SessionDataType;
|
||||
activesessionid?: string;
|
||||
screens?: ScreenDataType[];
|
||||
screen?: ScreenDataType;
|
||||
screenlines?: ScreenLinesType;
|
||||
line?: LineType;
|
||||
lines?: LineType[];
|
||||
line?: LineUpdateType;
|
||||
cmd?: CmdDataType;
|
||||
info?: InfoType;
|
||||
cmdline?: StrWithPos;
|
||||
remotes?: RemoteType[];
|
||||
remote?: RemoteType;
|
||||
history?: HistoryInfoType;
|
||||
connect?: boolean;
|
||||
mainview?: string;
|
||||
bookmarks?: BookmarkType[];
|
||||
selectedbookmark?: string;
|
||||
connect?: ConnectUpdateType;
|
||||
mainview?: MainViewUpdateType;
|
||||
bookmarks?: BookmarksUpdateType;
|
||||
clientdata?: ClientDataType;
|
||||
historyviewdata?: HistoryViewDataType;
|
||||
remoteview?: RemoteViewType;
|
||||
openaicmdinfochat?: OpenAICmdInfoChatMessageType[];
|
||||
alertmessage?: AlertMessageType;
|
||||
screenstatusindicators?: ScreenStatusIndicatorUpdateType[];
|
||||
screennumrunningcommands?: ScreenNumRunningCommandsUpdateType[];
|
||||
screenstatusindicator?: ScreenStatusIndicatorUpdateType;
|
||||
screennumrunningcommands?: ScreenNumRunningCommandsUpdateType;
|
||||
userinputrequest?: UserInputRequest;
|
||||
};
|
||||
|
||||
@@ -415,7 +435,7 @@ type ContextMenuOpts = {
|
||||
showCut?: boolean;
|
||||
};
|
||||
|
||||
type UpdateMessage = PtyDataUpdateType | ModelUpdateType;
|
||||
type UpdateMessage = PtyDataUpdateType | ModelUpdateType[];
|
||||
|
||||
type RendererContext = {
|
||||
screenId: string;
|
||||
@@ -540,6 +560,14 @@ type ReleaseInfoType = {
|
||||
latestversion: string;
|
||||
};
|
||||
|
||||
type ClientWinSizeType = {
|
||||
width: number;
|
||||
height: number;
|
||||
top: number;
|
||||
left: number;
|
||||
fullscreen: boolean;
|
||||
};
|
||||
|
||||
type ClientDataType = {
|
||||
clientid: string;
|
||||
userid: string;
|
||||
@@ -549,6 +577,7 @@ type ClientDataType = {
|
||||
dbversion: number;
|
||||
openaiopts?: OpenAIOptsType;
|
||||
releaseinfo?: ReleaseInfoType;
|
||||
winsize: ClientWinSizeType;
|
||||
};
|
||||
|
||||
type OpenAIOptsType = {
|
||||
@@ -866,6 +895,7 @@ export type {
|
||||
CmdInputTextPacketType,
|
||||
OpenAICmdInfoChatMessageType,
|
||||
ScreenStatusIndicatorUpdateType,
|
||||
ScreenNumRunningCommandsUpdateType,
|
||||
OV,
|
||||
OArr,
|
||||
OMap,
|
||||
|
||||
+53
-69
@@ -1,4 +1,4 @@
|
||||
// Copyright 2023, Command Line Inc.
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import * as mobx from "mobx";
|
||||
@@ -17,7 +17,7 @@ function isBlank(s: string): boolean {
|
||||
}
|
||||
|
||||
function handleNotOkResp(resp: any, url: URL): Promise<any> {
|
||||
let errMsg = sprintf(
|
||||
const errMsg = sprintf(
|
||||
"Bad status code response from fetch '%s': code=%d %s",
|
||||
url.toString(),
|
||||
resp.status,
|
||||
@@ -41,18 +41,18 @@ function handleNotOkResp(resp: any, url: URL): Promise<any> {
|
||||
}
|
||||
|
||||
function fetchJsonData(resp: any, ctErr: boolean): Promise<any> {
|
||||
let contentType = resp.headers.get("Content-Type");
|
||||
if (contentType != null && contentType.startsWith("application/json")) {
|
||||
const contentType = resp.headers.get("Content-Type");
|
||||
if (contentType?.startsWith("application/json")) {
|
||||
return resp.text().then((textData) => {
|
||||
let rtnData: any = null;
|
||||
try {
|
||||
rtnData = JSON.parse(textData);
|
||||
} catch (err) {
|
||||
let errMsg = sprintf("Unparseable JSON: " + err.message);
|
||||
let rtnErr = new Error(errMsg);
|
||||
const errMsg = sprintf("Unparseable JSON: " + err.message);
|
||||
const rtnErr = new Error(errMsg);
|
||||
throw rtnErr;
|
||||
}
|
||||
if (rtnData != null && rtnData.error) {
|
||||
if (rtnData?.error) {
|
||||
throw new Error(rtnData.error);
|
||||
}
|
||||
return rtnData;
|
||||
@@ -67,23 +67,23 @@ function handleJsonFetchResponse(url: URL, resp: any): Promise<any> {
|
||||
if (!resp.ok) {
|
||||
return handleNotOkResp(resp, url);
|
||||
}
|
||||
let rtnData = fetchJsonData(resp, true);
|
||||
const rtnData = fetchJsonData(resp, true);
|
||||
return rtnData;
|
||||
}
|
||||
|
||||
function base64ToString(b64: string): string {
|
||||
let stringBytes = base64.toByteArray(b64);
|
||||
const stringBytes = base64.toByteArray(b64);
|
||||
return new TextDecoder().decode(stringBytes);
|
||||
}
|
||||
|
||||
function stringToBase64(input: string): string {
|
||||
let stringBytes = new TextEncoder().encode(input);
|
||||
const stringBytes = new TextEncoder().encode(input);
|
||||
return base64.fromByteArray(stringBytes);
|
||||
}
|
||||
|
||||
function base64ToArray(b64: string): Uint8Array {
|
||||
let rawStr = atob(b64);
|
||||
let rtnArr = new Uint8Array(new ArrayBuffer(rawStr.length));
|
||||
const rawStr = atob(b64);
|
||||
const rtnArr = new Uint8Array(new ArrayBuffer(rawStr.length));
|
||||
for (let i = 0; i < rawStr.length; i++) {
|
||||
rtnArr[i] = rawStr.charCodeAt(i);
|
||||
}
|
||||
@@ -92,7 +92,6 @@ function base64ToArray(b64: string): Uint8Array {
|
||||
|
||||
interface IDataType {
|
||||
remove?: boolean;
|
||||
full?: boolean;
|
||||
}
|
||||
|
||||
interface IObjType<DataType> {
|
||||
@@ -113,31 +112,28 @@ function genMergeSimpleData<T extends ISimpleDataType>(
|
||||
if (dataArr == null || dataArr.length == 0) {
|
||||
return;
|
||||
}
|
||||
let objMap: Record<string, T> = {};
|
||||
for (let i = 0; i < objs.length; i++) {
|
||||
let obj = objs[i];
|
||||
let id = idFn(obj);
|
||||
const objMap: Record<string, T> = {};
|
||||
for (const obj of objs) {
|
||||
const id = idFn(obj);
|
||||
objMap[id] = obj;
|
||||
}
|
||||
for (let i = 0; i < dataArr.length; i++) {
|
||||
let dataItem = dataArr[i];
|
||||
for (const dataItem of dataArr) {
|
||||
if (dataItem == null) {
|
||||
console.log("genMergeSimpleData, null item");
|
||||
console.trace();
|
||||
}
|
||||
let id = idFn(dataItem);
|
||||
const id = idFn(dataItem);
|
||||
if (dataItem.remove) {
|
||||
delete objMap[id];
|
||||
continue;
|
||||
} else {
|
||||
objMap[id] = dataItem;
|
||||
}
|
||||
}
|
||||
let newObjs = Object.values(objMap);
|
||||
const newObjs = Object.values(objMap);
|
||||
if (sortIdxFn) {
|
||||
newObjs.sort((a, b) => {
|
||||
let astr = sortIdxFn(a);
|
||||
let bstr = sortIdxFn(b);
|
||||
const astr = sortIdxFn(a);
|
||||
const bstr = sortIdxFn(b);
|
||||
return astr.localeCompare(bstr);
|
||||
});
|
||||
}
|
||||
@@ -155,20 +151,18 @@ function genMergeData<ObjType extends IObjType<DataType>, DataType extends IData
|
||||
if (dataArr == null || dataArr.length == 0) {
|
||||
return;
|
||||
}
|
||||
let objMap: Record<string, ObjType> = {};
|
||||
for (let i = 0; i < objs.length; i++) {
|
||||
let obj = objs[i];
|
||||
let id = objIdFn(obj);
|
||||
const objMap: Record<string, ObjType> = {};
|
||||
for (const obj of objs) {
|
||||
const id = objIdFn(obj);
|
||||
objMap[id] = obj;
|
||||
}
|
||||
for (let i = 0; i < dataArr.length; i++) {
|
||||
let dataItem = dataArr[i];
|
||||
for (const dataItem of dataArr) {
|
||||
if (dataItem == null) {
|
||||
console.log("genMergeData, null item");
|
||||
console.trace();
|
||||
continue;
|
||||
}
|
||||
let id = dataIdFn(dataItem);
|
||||
const id = dataIdFn(dataItem);
|
||||
let obj = objMap[id];
|
||||
if (dataItem.remove) {
|
||||
if (obj != null) {
|
||||
@@ -178,17 +172,13 @@ function genMergeData<ObjType extends IObjType<DataType>, DataType extends IData
|
||||
continue;
|
||||
}
|
||||
if (obj == null) {
|
||||
if (!dataItem.full) {
|
||||
console.log("cannot create object, dataitem is not full", objs, dataItem);
|
||||
continue;
|
||||
}
|
||||
obj = ctorFn(dataItem);
|
||||
objMap[id] = obj;
|
||||
continue;
|
||||
}
|
||||
obj.mergeData(dataItem);
|
||||
}
|
||||
let newObjs = Object.values(objMap);
|
||||
const newObjs = Object.values(objMap);
|
||||
if (sortIdxFn) {
|
||||
newObjs.sort((a, b) => {
|
||||
return sortIdxFn(a) - sortIdxFn(b);
|
||||
@@ -204,18 +194,17 @@ function genMergeDataMap<ObjType extends IObjType<DataType>, DataType extends ID
|
||||
dataIdFn: (data: DataType) => string,
|
||||
ctorFn: (data: DataType) => ObjType
|
||||
): { added: string[]; removed: string[] } {
|
||||
let rtn: { added: string[]; removed: string[] } = { added: [], removed: [] };
|
||||
const rtn: { added: string[]; removed: string[] } = { added: [], removed: [] };
|
||||
if (dataArr == null || dataArr.length == 0) {
|
||||
return rtn;
|
||||
}
|
||||
for (let i = 0; i < dataArr.length; i++) {
|
||||
let dataItem = dataArr[i];
|
||||
for (const dataItem of dataArr) {
|
||||
if (dataItem == null) {
|
||||
console.log("genMergeDataMap, null item");
|
||||
console.trace();
|
||||
continue;
|
||||
}
|
||||
let id = dataIdFn(dataItem);
|
||||
const id = dataIdFn(dataItem);
|
||||
let obj = objMap.get(id);
|
||||
if (dataItem.remove) {
|
||||
if (obj != null) {
|
||||
@@ -226,10 +215,6 @@ function genMergeDataMap<ObjType extends IObjType<DataType>, DataType extends ID
|
||||
continue;
|
||||
}
|
||||
if (obj == null) {
|
||||
if (!dataItem.full) {
|
||||
console.log("cannot create object, dataitem is not full", dataItem);
|
||||
continue;
|
||||
}
|
||||
obj = ctorFn(dataItem);
|
||||
objMap.set(id, obj);
|
||||
rtn.added.push(id);
|
||||
@@ -262,23 +247,23 @@ function incObs(inum: mobx.IObservableValue<number>) {
|
||||
|
||||
// @check:font
|
||||
function loadFonts() {
|
||||
let jbmFontNormal = new FontFace("JetBrains Mono", "url('public/fonts/jetbrains-mono-v13-latin-regular.woff2')", {
|
||||
const jbmFontNormal = new FontFace("JetBrains Mono", "url('public/fonts/jetbrains-mono-v13-latin-regular.woff2')", {
|
||||
style: "normal",
|
||||
weight: "400",
|
||||
});
|
||||
let jbmFont200 = new FontFace("JetBrains Mono", "url('public/fonts/jetbrains-mono-v13-latin-200.woff2')", {
|
||||
const jbmFont200 = new FontFace("JetBrains Mono", "url('public/fonts/jetbrains-mono-v13-latin-200.woff2')", {
|
||||
style: "normal",
|
||||
weight: "200",
|
||||
});
|
||||
let jbmFont700 = new FontFace("JetBrains Mono", "url('public/fonts/jetbrains-mono-v13-latin-700.woff2')", {
|
||||
const jbmFont700 = new FontFace("JetBrains Mono", "url('public/fonts/jetbrains-mono-v13-latin-700.woff2')", {
|
||||
style: "normal",
|
||||
weight: "700",
|
||||
});
|
||||
let faFont = new FontFace("FontAwesome", "url(public/fonts/fontawesome-webfont-4.7.woff2)", {
|
||||
const faFont = new FontFace("FontAwesome", "url(public/fonts/fontawesome-webfont-4.7.woff2)", {
|
||||
style: "normal",
|
||||
weight: "normal",
|
||||
});
|
||||
let docFonts: any = document.fonts; // work around ts typing issue
|
||||
const docFonts: any = document.fonts; // work around ts typing issue
|
||||
docFonts.add(jbmFontNormal);
|
||||
docFonts.add(jbmFont200);
|
||||
docFonts.add(jbmFont700);
|
||||
@@ -296,13 +281,13 @@ function getTodayStr(): string {
|
||||
}
|
||||
|
||||
function getYesterdayStr(): string {
|
||||
let d = new Date();
|
||||
const d = new Date();
|
||||
d.setDate(d.getDate() - 1);
|
||||
return getDateStr(d);
|
||||
}
|
||||
|
||||
function getDateStr(d: Date): string {
|
||||
let yearStr = String(d.getFullYear());
|
||||
const yearStr = String(d.getFullYear());
|
||||
let monthStr = String(d.getMonth() + 1);
|
||||
if (monthStr.length == 1) {
|
||||
monthStr = "0" + monthStr;
|
||||
@@ -311,31 +296,30 @@ function getDateStr(d: Date): string {
|
||||
if (dayStr.length == 1) {
|
||||
dayStr = "0" + dayStr;
|
||||
}
|
||||
let dowStr = DOW_STRS[d.getDay()];
|
||||
const dowStr = DOW_STRS[d.getDay()];
|
||||
return dowStr + " " + yearStr + "-" + monthStr + "-" + dayStr;
|
||||
}
|
||||
|
||||
function getRemoteConnVal(r: RemoteType): number {
|
||||
if (r.status == "connected") {
|
||||
return 1;
|
||||
switch (r.status) {
|
||||
case "connected":
|
||||
return 1;
|
||||
case "connecting":
|
||||
return 2;
|
||||
case "disconnected":
|
||||
return 3;
|
||||
case "error":
|
||||
return 4;
|
||||
default:
|
||||
return 5;
|
||||
}
|
||||
if (r.status == "connecting") {
|
||||
return 2;
|
||||
}
|
||||
if (r.status == "disconnected") {
|
||||
return 3;
|
||||
}
|
||||
if (r.status == "error") {
|
||||
return 4;
|
||||
}
|
||||
return 5;
|
||||
}
|
||||
|
||||
function sortAndFilterRemotes(origRemotes: RemoteType[]): RemoteType[] {
|
||||
let remotes = origRemotes.filter((r) => !r.archived);
|
||||
const remotes = origRemotes.filter((r) => !r.archived);
|
||||
remotes.sort((a, b) => {
|
||||
let connValA = getRemoteConnVal(a);
|
||||
let connValB = getRemoteConnVal(b);
|
||||
const connValA = getRemoteConnVal(a);
|
||||
const connValB = getRemoteConnVal(b);
|
||||
if (connValA != connValB) {
|
||||
return connValA - connValB;
|
||||
}
|
||||
@@ -372,7 +356,7 @@ function openLink(url: string): void {
|
||||
window.open(url, "_blank");
|
||||
}
|
||||
|
||||
function getColorRGB(colorInput) {
|
||||
function getColorRGB(colorInput: string) {
|
||||
const tempElement = document.createElement("div");
|
||||
tempElement.style.color = colorInput;
|
||||
document.body.appendChild(tempElement);
|
||||
@@ -399,7 +383,7 @@ function getRemoteName(remote: RemoteType): string {
|
||||
if (remote == null) {
|
||||
return "";
|
||||
}
|
||||
let { remotealias, remotecanonicalname } = remote;
|
||||
const { remotealias, remotecanonicalname } = remote;
|
||||
return remotealias ? `${remotealias} [${remotecanonicalname}]` : remotecanonicalname;
|
||||
}
|
||||
|
||||
|
||||
@@ -257,10 +257,7 @@ func (z zshShellApi) MakeRcFileStr(pk *packet.RunPacketType) string {
|
||||
}
|
||||
rcBuf.WriteString("\n")
|
||||
}
|
||||
if shellenv.FindVarDecl(varDecls, "ZDOTDIR") == nil {
|
||||
rcBuf.WriteString("unset ZDOTDIR\n")
|
||||
rcBuf.WriteString("\n")
|
||||
}
|
||||
// do NOT unset ZDOTDIR, otherwise initialization will start to read initialization files from ~/ again
|
||||
for _, varName := range ZshUnsetVars {
|
||||
rcBuf.WriteString("unset " + shellescape.Quote(varName) + "\n")
|
||||
}
|
||||
|
||||
+245
-286
File diff suppressed because it is too large
Load Diff
@@ -66,9 +66,8 @@ func CheckNewRelease(ctx context.Context, force bool) (ReleaseCheckResult, error
|
||||
return Failure, fmt.Errorf("error getting updated client data: %w", err)
|
||||
}
|
||||
|
||||
update := &sstore.ModelUpdate{
|
||||
ClientData: clientData,
|
||||
}
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, *clientData)
|
||||
sstore.MainBus.SendUpdate(update)
|
||||
|
||||
return Success, nil
|
||||
|
||||
@@ -678,18 +678,19 @@ func (msh *MShellProc) GetRemoteRuntimeState() RemoteRuntimeState {
|
||||
|
||||
func (msh *MShellProc) NotifyRemoteUpdate() {
|
||||
rstate := msh.GetRemoteRuntimeState()
|
||||
update := &sstore.ModelUpdate{Remotes: []RemoteRuntimeState{rstate}}
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, rstate)
|
||||
sstore.MainBus.SendUpdate(update)
|
||||
}
|
||||
|
||||
func GetAllRemoteRuntimeState() []RemoteRuntimeState {
|
||||
func GetAllRemoteRuntimeState() []*RemoteRuntimeState {
|
||||
GlobalStore.Lock.Lock()
|
||||
defer GlobalStore.Lock.Unlock()
|
||||
|
||||
var rtn []RemoteRuntimeState
|
||||
var rtn []*RemoteRuntimeState
|
||||
for _, proc := range GlobalStore.Map {
|
||||
state := proc.GetRemoteRuntimeState()
|
||||
rtn = append(rtn, state)
|
||||
rtn = append(rtn, &state)
|
||||
}
|
||||
return rtn
|
||||
}
|
||||
@@ -1997,7 +1998,8 @@ func (msh *MShellProc) notifyHangups_nolock() {
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
update := &sstore.ModelUpdate{Cmd: cmd}
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, *cmd)
|
||||
sstore.MainBus.SendScreenUpdate(ck.GetGroupId(), update)
|
||||
go pushNumRunningCmdsUpdate(&ck, -1)
|
||||
}
|
||||
@@ -2027,7 +2029,7 @@ func (msh *MShellProc) handleCmdDonePacket(donePk *packet.CmdDonePacketType) {
|
||||
// fall-through (nothing to do)
|
||||
}
|
||||
if screen != nil {
|
||||
update.Screens = []*sstore.ScreenType{screen}
|
||||
sstore.AddUpdate(update, *screen)
|
||||
}
|
||||
rct := msh.GetRunningCmd(donePk.CK)
|
||||
var statePtr *sstore.ShellStatePtr
|
||||
@@ -2039,7 +2041,7 @@ func (msh *MShellProc) handleCmdDonePacket(donePk *packet.CmdDonePacketType) {
|
||||
// fall-through (nothing to do)
|
||||
}
|
||||
if remoteInst != nil {
|
||||
update.Sessions = sstore.MakeSessionsUpdateForRemote(rct.SessionId, remoteInst)
|
||||
sstore.AddUpdate(update, sstore.MakeSessionUpdateForRemote(rct.SessionId, remoteInst))
|
||||
}
|
||||
statePtr = &sstore.ShellStatePtr{BaseHash: donePk.FinalState.GetHashVal(false)}
|
||||
} else if donePk.FinalStateDiff != nil && rct != nil {
|
||||
@@ -2059,7 +2061,7 @@ func (msh *MShellProc) handleCmdDonePacket(donePk *packet.CmdDonePacketType) {
|
||||
// fall-through (nothing to do)
|
||||
}
|
||||
if remoteInst != nil {
|
||||
update.Sessions = sstore.MakeSessionsUpdateForRemote(rct.SessionId, remoteInst)
|
||||
sstore.AddUpdate(update, sstore.MakeSessionUpdateForRemote(rct.SessionId, remoteInst))
|
||||
}
|
||||
diffHashArr := append(([]string)(nil), donePk.FinalStateDiff.DiffHashArr...)
|
||||
diffHashArr = append(diffHashArr, donePk.FinalStateDiff.GetHashVal(false))
|
||||
@@ -2102,9 +2104,10 @@ func (msh *MShellProc) handleCmdFinalPacket(finalPk *packet.CmdFinalPacketType)
|
||||
log.Printf("error getting cmd(2) in handleCmdFinalPacket (not found)\n")
|
||||
return
|
||||
}
|
||||
update := &sstore.ModelUpdate{Cmd: rtnCmd}
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, *rtnCmd)
|
||||
if screen != nil {
|
||||
update.Screens = []*sstore.ScreenType{screen}
|
||||
sstore.AddUpdate(update, *screen)
|
||||
}
|
||||
go pushNumRunningCmdsUpdate(&finalPk.CK, -1)
|
||||
sstore.MainBus.SendUpdate(update)
|
||||
@@ -2172,7 +2175,9 @@ func (msh *MShellProc) makeHandleCmdFinalPacketClosure(finalPk *packet.CmdFinalP
|
||||
|
||||
func sendScreenUpdates(screens []*sstore.ScreenType) {
|
||||
for _, screen := range screens {
|
||||
sstore.MainBus.SendUpdate(&sstore.ModelUpdate{Screens: []*sstore.ScreenType{screen}})
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, *screen)
|
||||
sstore.MainBus.SendUpdate(update)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -388,11 +388,12 @@ func createHostKeyCallback(opts *sstore.SSHOpts) (ssh.HostKeyCallback, error) {
|
||||
"%s\n\n"+
|
||||
"**Offending Keys** \n"+
|
||||
"%s", key.Type(), correctKeyFingerprint, strings.Join(bulletListKnownHosts, " \n"), strings.Join(offendingKeysFmt, " \n"))
|
||||
update := &sstore.ModelUpdate{AlertMessage: &sstore.AlertMessageType{
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, sstore.AlertMessageType{
|
||||
Markdown: true,
|
||||
Title: "Known Hosts Key Changed",
|
||||
Message: alertText,
|
||||
}}
|
||||
})
|
||||
sstore.MainBus.SendUpdate(update)
|
||||
return fmt.Errorf("remote host identification has changed")
|
||||
}
|
||||
|
||||
@@ -162,16 +162,17 @@ func (ws *WSState) ReplaceShell(shell *wsshell.WSShell) {
|
||||
func (ws *WSState) handleConnection() error {
|
||||
ctx, cancelFn := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancelFn()
|
||||
update, err := sstore.GetAllSessions(ctx)
|
||||
connectUpdate, err := sstore.GetConnectUpdate(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting sessions: %w", err)
|
||||
}
|
||||
remotes := remote.GetAllRemoteRuntimeState()
|
||||
update.Remotes = remotes
|
||||
connectUpdate.Remotes = remotes
|
||||
// restore status indicators
|
||||
update.ScreenStatusIndicators, update.ScreenNumRunningCommands = sstore.GetCurrentIndicatorState()
|
||||
update.Connect = true
|
||||
err = ws.Shell.WriteJson(update)
|
||||
connectUpdate.ScreenStatusIndicators, connectUpdate.ScreenNumRunningCommands = sstore.GetCurrentIndicatorState()
|
||||
mu := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(mu, *connectUpdate)
|
||||
err = ws.Shell.WriteJson(mu)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+79
-58
@@ -453,20 +453,32 @@ func GetBareSessionById(ctx context.Context, sessionId string) (*SessionType, er
|
||||
return &rtn, nil
|
||||
}
|
||||
|
||||
func GetAllSessions(ctx context.Context) (*ModelUpdate, error) {
|
||||
return WithTxRtn(ctx, func(tx *TxWrap) (*ModelUpdate, error) {
|
||||
update := &ModelUpdate{}
|
||||
query := `SELECT * FROM session ORDER BY archived, sessionidx, archivedts`
|
||||
tx.Select(&update.Sessions, query)
|
||||
const getAllSessionsQuery = `SELECT * FROM session ORDER BY archived, sessionidx, archivedts`
|
||||
|
||||
// Gets all sessions, including archived
|
||||
func GetAllSessions(ctx context.Context) ([]*SessionType, error) {
|
||||
return WithTxRtn(ctx, func(tx *TxWrap) ([]*SessionType, error) {
|
||||
rtn := []*SessionType{}
|
||||
tx.Select(&rtn, getAllSessionsQuery)
|
||||
return rtn, nil
|
||||
})
|
||||
}
|
||||
|
||||
// Get all sessions and screens, including remotes
|
||||
func GetConnectUpdate(ctx context.Context) (*ConnectUpdate, error) {
|
||||
return WithTxRtn(ctx, func(tx *TxWrap) (*ConnectUpdate, error) {
|
||||
update := &ConnectUpdate{}
|
||||
sessions := []*SessionType{}
|
||||
tx.Select(&sessions, getAllSessionsQuery)
|
||||
sessionMap := make(map[string]*SessionType)
|
||||
for _, session := range update.Sessions {
|
||||
for _, session := range sessions {
|
||||
sessionMap[session.SessionId] = session
|
||||
session.Full = true
|
||||
update.Sessions = append(update.Sessions, session)
|
||||
}
|
||||
query = `SELECT * FROM screen ORDER BY archived, screenidx, archivedts`
|
||||
update.Screens = dbutil.SelectMapsGen[*ScreenType](tx, query)
|
||||
for _, screen := range update.Screens {
|
||||
screen.Full = true
|
||||
query := `SELECT * FROM screen ORDER BY archived, screenidx, archivedts`
|
||||
screens := dbutil.SelectMapsGen[*ScreenType](tx, query)
|
||||
for _, screen := range screens {
|
||||
update.Screens = append(update.Screens, screen)
|
||||
}
|
||||
query = `SELECT * FROM remote_instance`
|
||||
riArr := dbutil.SelectMapsGen[*RemoteInstance](tx, query)
|
||||
@@ -502,19 +514,15 @@ func GetSessionScreens(ctx context.Context, sessionId string) ([]*ScreenType, er
|
||||
return WithTxRtn(ctx, func(tx *TxWrap) ([]*ScreenType, error) {
|
||||
query := `SELECT * FROM screen WHERE sessionid = ? ORDER BY archived, screenidx, archivedts`
|
||||
rtn := dbutil.SelectMapsGen[*ScreenType](tx, query, sessionId)
|
||||
for _, screen := range rtn {
|
||||
screen.Full = true
|
||||
}
|
||||
return rtn, nil
|
||||
})
|
||||
}
|
||||
|
||||
func GetSessionById(ctx context.Context, id string) (*SessionType, error) {
|
||||
allSessionsUpdate, err := GetAllSessions(ctx)
|
||||
allSessions, err := GetAllSessions(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
allSessions := allSessionsUpdate.Sessions
|
||||
for _, session := range allSessions {
|
||||
if session.SessionId == id {
|
||||
return session, nil
|
||||
@@ -569,7 +577,11 @@ func InsertSessionWithName(ctx context.Context, sessionName string, activate boo
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newScreen = screenUpdate.Screens[0]
|
||||
screenUpdateItems := GetUpdateItems[ScreenType](screenUpdate)
|
||||
if len(screenUpdateItems) < 1 {
|
||||
return fmt.Errorf("no screen update items")
|
||||
}
|
||||
newScreen = screenUpdateItems[0]
|
||||
if activate {
|
||||
query = `UPDATE client SET activesessionid = ?`
|
||||
tx.Exec(query, newSessionId)
|
||||
@@ -583,12 +595,11 @@ func InsertSessionWithName(ctx context.Context, sessionName string, activate boo
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
update := &ModelUpdate{
|
||||
Sessions: []*SessionType{session},
|
||||
Screens: []*ScreenType{newScreen},
|
||||
}
|
||||
update := &ModelUpdate{}
|
||||
AddUpdate(update, *session)
|
||||
AddUpdate(update, *newScreen)
|
||||
if activate {
|
||||
update.ActiveSessionId = newSessionId
|
||||
AddUpdate(update, ActiveSessionIdUpdate(newSessionId))
|
||||
}
|
||||
return update, nil
|
||||
}
|
||||
@@ -742,14 +753,15 @@ func InsertScreen(ctx context.Context, sessionId string, origScreenName string,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
update := &ModelUpdate{Screens: []*ScreenType{newScreen}}
|
||||
update := &ModelUpdate{}
|
||||
AddUpdate(update, *newScreen)
|
||||
if activate {
|
||||
bareSession, err := GetBareSessionById(ctx, sessionId)
|
||||
if err != nil {
|
||||
return nil, txErr
|
||||
}
|
||||
update.Sessions = []*SessionType{bareSession}
|
||||
update.OpenAICmdInfoChat = ScreenMemGetCmdInfoChat(newScreenId).Messages
|
||||
AddUpdate(update, *bareSession)
|
||||
UpdateWithCurrentOpenAICmdInfoChat(newScreenId, update)
|
||||
}
|
||||
return update, nil
|
||||
}
|
||||
@@ -758,7 +770,6 @@ func GetScreenById(ctx context.Context, screenId string) (*ScreenType, error) {
|
||||
return WithTxRtn(ctx, func(tx *TxWrap) (*ScreenType, error) {
|
||||
query := `SELECT * FROM screen WHERE screenid = ?`
|
||||
screen := dbutil.GetMapGen[*ScreenType](tx, query, screenId)
|
||||
screen.Full = true
|
||||
return screen, nil
|
||||
})
|
||||
}
|
||||
@@ -866,17 +877,18 @@ func GetCmdByScreenId(ctx context.Context, screenId string, lineId string) (*Cmd
|
||||
|
||||
func UpdateWithClearOpenAICmdInfo(screenId string) (*ModelUpdate, error) {
|
||||
ScreenMemClearCmdInfoChat(screenId)
|
||||
return UpdateWithCurrentOpenAICmdInfoChat(screenId)
|
||||
return UpdateWithCurrentOpenAICmdInfoChat(screenId, nil)
|
||||
}
|
||||
|
||||
func UpdateWithAddNewOpenAICmdInfoPacket(ctx context.Context, screenId string, pk *packet.OpenAICmdInfoChatMessage) (*ModelUpdate, error) {
|
||||
ScreenMemAddCmdInfoChatMessage(screenId, pk)
|
||||
return UpdateWithCurrentOpenAICmdInfoChat(screenId)
|
||||
return UpdateWithCurrentOpenAICmdInfoChat(screenId, nil)
|
||||
}
|
||||
|
||||
func UpdateWithCurrentOpenAICmdInfoChat(screenId string) (*ModelUpdate, error) {
|
||||
cmdInfoUpdate := ScreenMemGetCmdInfoChat(screenId).Messages
|
||||
return &ModelUpdate{OpenAICmdInfoChat: cmdInfoUpdate}, nil
|
||||
func UpdateWithCurrentOpenAICmdInfoChat(screenId string, update *ModelUpdate) (*ModelUpdate, error) {
|
||||
ret := &ModelUpdate{}
|
||||
AddOpenAICmdInfoChatUpdate(ret, ScreenMemGetCmdInfoChat(screenId).Messages)
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func UpdateWithUpdateOpenAICmdInfoPacket(ctx context.Context, screenId string, messageID int, pk *packet.OpenAICmdInfoChatMessage) (*ModelUpdate, error) {
|
||||
@@ -884,7 +896,7 @@ func UpdateWithUpdateOpenAICmdInfoPacket(ctx context.Context, screenId string, m
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return UpdateWithCurrentOpenAICmdInfoChat(screenId)
|
||||
return UpdateWithCurrentOpenAICmdInfoChat(screenId, nil)
|
||||
}
|
||||
|
||||
func UpdateCmdForRestart(ctx context.Context, ck base.CommandKey, ts int64, cmdPid int, remotePid int, termOpts *TermOpts) error {
|
||||
@@ -935,7 +947,8 @@ func UpdateCmdDoneInfo(ctx context.Context, ck base.CommandKey, donePk *packet.C
|
||||
return nil, fmt.Errorf("cmd data not found for ck[%s]", ck)
|
||||
}
|
||||
|
||||
update := &ModelUpdate{Cmd: rtnCmd}
|
||||
update := &ModelUpdate{}
|
||||
AddUpdate(update, *rtnCmd)
|
||||
|
||||
// Update in-memory screen indicator status
|
||||
var indicator StatusIndicatorLevel
|
||||
@@ -1101,11 +1114,13 @@ func SwitchScreenById(ctx context.Context, sessionId string, screenId string) (*
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
update := &ModelUpdate{ActiveSessionId: sessionId, Sessions: []*SessionType{bareSession}}
|
||||
update := &ModelUpdate{}
|
||||
AddUpdate(update, (ActiveSessionIdUpdate)(sessionId))
|
||||
AddUpdate(update, *bareSession)
|
||||
memState := GetScreenMemState(screenId)
|
||||
if memState != nil {
|
||||
update.CmdLine = &memState.CmdInputText
|
||||
update.OpenAICmdInfoChat = ScreenMemGetCmdInfoChat(screenId).Messages
|
||||
AddCmdLineUpdate(update, memState.CmdInputText)
|
||||
UpdateWithCurrentOpenAICmdInfoChat(screenId, update)
|
||||
|
||||
// Clear any previous status indicator for this screen
|
||||
err := ResetStatusIndicator_Update(update, screenId)
|
||||
@@ -1173,13 +1188,14 @@ func ArchiveScreen(ctx context.Context, sessionId string, screenId string) (Upda
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot retrive archived screen: %w", err)
|
||||
}
|
||||
update := &ModelUpdate{Screens: []*ScreenType{newScreen}}
|
||||
update := &ModelUpdate{}
|
||||
AddUpdate(update, *newScreen)
|
||||
if isActive {
|
||||
bareSession, err := GetBareSessionById(ctx, sessionId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
update.Sessions = []*SessionType{bareSession}
|
||||
AddUpdate(update, *bareSession)
|
||||
}
|
||||
return update, nil
|
||||
}
|
||||
@@ -1199,7 +1215,7 @@ func UnArchiveScreen(ctx context.Context, sessionId string, screenId string) err
|
||||
}
|
||||
|
||||
// if sessionDel is passed, we do *not* delete the screen directory (session delete will handle that)
|
||||
func DeleteScreen(ctx context.Context, screenId string, sessionDel bool) (*ModelUpdate, error) {
|
||||
func DeleteScreen(ctx context.Context, screenId string, sessionDel bool, update *ModelUpdate) (*ModelUpdate, error) {
|
||||
var sessionId string
|
||||
var isActive bool
|
||||
var screenTombstone *ScreenTombstoneType
|
||||
@@ -1259,14 +1275,17 @@ func DeleteScreen(ctx context.Context, screenId string, sessionDel bool) (*Model
|
||||
if !sessionDel {
|
||||
GoDeleteScreenDirs(screenId)
|
||||
}
|
||||
update := &ModelUpdate{ScreenTombstones: []*ScreenTombstoneType{screenTombstone}}
|
||||
update.Screens = []*ScreenType{{SessionId: sessionId, ScreenId: screenId, Remove: true}}
|
||||
if update == nil {
|
||||
update = &ModelUpdate{}
|
||||
}
|
||||
AddUpdate(update, *screenTombstone)
|
||||
AddUpdate(update, ScreenType{SessionId: sessionId, ScreenId: screenId, Remove: true})
|
||||
if isActive {
|
||||
bareSession, err := GetBareSessionById(ctx, sessionId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
update.Sessions = []*SessionType{bareSession}
|
||||
AddUpdate(update, *bareSession)
|
||||
}
|
||||
return update, nil
|
||||
}
|
||||
@@ -1516,7 +1535,9 @@ func ArchiveScreenLines(ctx context.Context, screenId string) (*ModelUpdate, err
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ModelUpdate{ScreenLines: screenLines}, nil
|
||||
ret := &ModelUpdate{}
|
||||
AddUpdate(ret, *screenLines)
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func DeleteScreenLines(ctx context.Context, screenId string) (*ModelUpdate, error) {
|
||||
@@ -1558,7 +1579,10 @@ func DeleteScreenLines(ctx context.Context, screenId string) (*ModelUpdate, erro
|
||||
}
|
||||
screenLines.Lines = append(screenLines.Lines, line)
|
||||
}
|
||||
return &ModelUpdate{Screens: []*ScreenType{screen}, ScreenLines: screenLines}, nil
|
||||
ret := &ModelUpdate{}
|
||||
AddUpdate(ret, *screen)
|
||||
AddUpdate(ret, *screenLines)
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func GetRunningScreenCmds(ctx context.Context, screenId string) ([]*CmdType, error) {
|
||||
@@ -1621,16 +1645,10 @@ func DeleteSession(ctx context.Context, sessionId string) (UpdatePacket, error)
|
||||
query := `SELECT screenid FROM screen WHERE sessionid = ?`
|
||||
screenIds = tx.SelectStrings(query, sessionId)
|
||||
for _, screenId := range screenIds {
|
||||
screenUpdate, err := DeleteScreen(tx.Context(), screenId, true)
|
||||
_, err := DeleteScreen(tx.Context(), screenId, true, update)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error deleting screen[%s]: %v", screenId, err)
|
||||
}
|
||||
if len(screenUpdate.Screens) > 0 {
|
||||
update.Screens = append(update.Screens, screenUpdate.Screens...)
|
||||
}
|
||||
if len(screenUpdate.ScreenTombstones) > 0 {
|
||||
update.ScreenTombstones = append(update.ScreenTombstones, screenUpdate.ScreenTombstones...)
|
||||
}
|
||||
}
|
||||
query = `DELETE FROM session WHERE sessionid = ?`
|
||||
tx.Exec(query, sessionId)
|
||||
@@ -1650,10 +1668,12 @@ func DeleteSession(ctx context.Context, sessionId string) (UpdatePacket, error)
|
||||
}
|
||||
GoDeleteScreenDirs(screenIds...)
|
||||
if newActiveSessionId != "" {
|
||||
update.ActiveSessionId = newActiveSessionId
|
||||
AddUpdate(update, (ActiveSessionIdUpdate)(newActiveSessionId))
|
||||
}
|
||||
AddUpdate(update, SessionType{SessionId: sessionId, Remove: true})
|
||||
if sessionTombstone != nil {
|
||||
AddUpdate(update, *sessionTombstone)
|
||||
}
|
||||
update.Sessions = append(update.Sessions, &SessionType{SessionId: sessionId, Remove: true})
|
||||
update.SessionTombstones = []*SessionTombstoneType{sessionTombstone}
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@@ -1705,10 +1725,10 @@ func ArchiveSession(ctx context.Context, sessionId string) (*ModelUpdate, error)
|
||||
bareSession, _ := GetBareSessionById(ctx, sessionId)
|
||||
update := &ModelUpdate{}
|
||||
if bareSession != nil {
|
||||
update.Sessions = append(update.Sessions, bareSession)
|
||||
AddUpdate(update, *bareSession)
|
||||
}
|
||||
if newActiveSessionId != "" {
|
||||
update.ActiveSessionId = newActiveSessionId
|
||||
AddUpdate(update, (ActiveSessionIdUpdate)(newActiveSessionId))
|
||||
}
|
||||
return update, nil
|
||||
}
|
||||
@@ -1740,11 +1760,12 @@ func UnArchiveSession(ctx context.Context, sessionId string, activate bool) (*Mo
|
||||
}
|
||||
bareSession, _ := GetBareSessionById(ctx, sessionId)
|
||||
update := &ModelUpdate{}
|
||||
|
||||
if bareSession != nil {
|
||||
update.Sessions = append(update.Sessions, bareSession)
|
||||
AddUpdate(update, *bareSession)
|
||||
}
|
||||
if activate {
|
||||
update.ActiveSessionId = sessionId
|
||||
AddUpdate(update, (ActiveSessionIdUpdate)(sessionId))
|
||||
}
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@@ -336,6 +336,10 @@ func (cdata *ClientData) Clean() *ClientData {
|
||||
return &rtn
|
||||
}
|
||||
|
||||
func (ClientData) UpdateType() string {
|
||||
return "clientdata"
|
||||
}
|
||||
|
||||
type SessionType struct {
|
||||
SessionId string `json:"sessionid"`
|
||||
Name string `json:"name"`
|
||||
@@ -349,7 +353,17 @@ type SessionType struct {
|
||||
|
||||
// only for updates
|
||||
Remove bool `json:"remove,omitempty"`
|
||||
Full bool `json:"full,omitempty"`
|
||||
}
|
||||
|
||||
func (SessionType) UpdateType() string {
|
||||
return "session"
|
||||
}
|
||||
|
||||
func MakeSessionUpdateForRemote(sessionId string, ri *RemoteInstance) SessionType {
|
||||
return SessionType{
|
||||
SessionId: sessionId,
|
||||
Remotes: []*RemoteInstance{ri},
|
||||
}
|
||||
}
|
||||
|
||||
type SessionTombstoneType struct {
|
||||
@@ -360,6 +374,10 @@ type SessionTombstoneType struct {
|
||||
|
||||
func (SessionTombstoneType) UseDBMap() {}
|
||||
|
||||
func (SessionTombstoneType) UpdateType() string {
|
||||
return "sessiontombstone"
|
||||
}
|
||||
|
||||
type SessionStatsType struct {
|
||||
SessionId string `json:"sessionid"`
|
||||
NumScreens int `json:"numscreens"`
|
||||
@@ -429,6 +447,10 @@ type ScreenLinesType struct {
|
||||
|
||||
func (ScreenLinesType) UseDBMap() {}
|
||||
|
||||
func (ScreenLinesType) UpdateType() string {
|
||||
return "screenlines"
|
||||
}
|
||||
|
||||
type ScreenWebShareOpts struct {
|
||||
ShareName string `json:"sharename"`
|
||||
ViewKey string `json:"viewkey"`
|
||||
@@ -476,9 +498,7 @@ type ScreenType struct {
|
||||
ArchivedTs int64 `json:"archivedts,omitempty"`
|
||||
|
||||
// only for updates
|
||||
Full bool `json:"full,omitempty"`
|
||||
Remove bool `json:"remove,omitempty"`
|
||||
StatusIndicator string `json:"statusindicator,omitempty"`
|
||||
Remove bool `json:"remove,omitempty"`
|
||||
}
|
||||
|
||||
func (s *ScreenType) ToMap() map[string]interface{} {
|
||||
@@ -526,6 +546,24 @@ func (s *ScreenType) FromMap(m map[string]interface{}) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (ScreenType) UpdateType() string {
|
||||
return "screen"
|
||||
}
|
||||
|
||||
func AddScreenUpdate(update *ModelUpdate, newScreen *ScreenType) {
|
||||
if newScreen == nil {
|
||||
return
|
||||
}
|
||||
screenUpdates := GetUpdateItems[ScreenType](update)
|
||||
for _, screenUpdate := range screenUpdates {
|
||||
if screenUpdate.ScreenId == newScreen.ScreenId {
|
||||
screenUpdate = newScreen
|
||||
return
|
||||
}
|
||||
}
|
||||
AddUpdate(update, newScreen)
|
||||
}
|
||||
|
||||
type ScreenTombstoneType struct {
|
||||
ScreenId string `json:"screenid"`
|
||||
SessionId string `json:"sessionid"`
|
||||
@@ -536,6 +574,10 @@ type ScreenTombstoneType struct {
|
||||
|
||||
func (ScreenTombstoneType) UseDBMap() {}
|
||||
|
||||
func (ScreenTombstoneType) UpdateType() string {
|
||||
return "screentombstone"
|
||||
}
|
||||
|
||||
const (
|
||||
LayoutFull = "full"
|
||||
)
|
||||
@@ -1015,6 +1057,10 @@ func (state RemoteRuntimeState) ExpandHomeDir(pathStr string) (string, error) {
|
||||
return path.Join(homeDir, pathStr[2:]), nil
|
||||
}
|
||||
|
||||
func (RemoteRuntimeState) UpdateType() string {
|
||||
return "remote"
|
||||
}
|
||||
|
||||
type RemoteType struct {
|
||||
RemoteId string `json:"remoteid"`
|
||||
RemoteType string `json:"remotetype"`
|
||||
@@ -1079,6 +1125,10 @@ type CmdType struct {
|
||||
Restarted bool `json:"restarted,omitempty"` // not persisted to DB
|
||||
}
|
||||
|
||||
func (CmdType) UpdateType() string {
|
||||
return "cmd"
|
||||
}
|
||||
|
||||
func (r *RemoteType) ToMap() map[string]interface{} {
|
||||
rtn := make(map[string]interface{})
|
||||
rtn["remoteid"] = r.RemoteId
|
||||
@@ -1456,10 +1506,10 @@ func SetStatusIndicatorLevel_Update(ctx context.Context, update *ModelUpdate, sc
|
||||
}
|
||||
}
|
||||
|
||||
update.ScreenStatusIndicators = []*ScreenStatusIndicatorType{{
|
||||
AddUpdate(update, ScreenStatusIndicatorType{
|
||||
ScreenId: screenId,
|
||||
Status: newStatus,
|
||||
}}
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1489,10 +1539,11 @@ func ResetStatusIndicator(screenId string) error {
|
||||
func IncrementNumRunningCmds_Update(update *ModelUpdate, screenId string, delta int) {
|
||||
newNum := ScreenMemIncrementNumRunningCommands(screenId, delta)
|
||||
log.Printf("IncrementNumRunningCmds_Update: screenId=%s, newNum=%d\n", screenId, newNum)
|
||||
update.ScreenNumRunningCommands = []*ScreenNumRunningCommandsType{{
|
||||
AddUpdate(update, ScreenNumRunningCommandsType{
|
||||
ScreenId: screenId,
|
||||
Num: newNum,
|
||||
}}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func IncrementNumRunningCmds(screenId string, delta int) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user