mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-03-11 13:23:06 +01:00
Refactor ModelUpdate to set up for decoupling sstore (#280)
This PR changes ModelUpdate mechanism from a statically-typed struct to an interface, allowing us to define the update mechanism and the update types separately. This sets us up to move app logic and update mechanisms into separate packages. Ultimately, sstore will only define low-level persistence logic.
This commit is contained in:
parent
7a5afccab3
commit
d319e72609
@ -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 {
|
||||
mobx.action(() => {
|
||||
this.aIChatShow.set(true);
|
||||
this.setAIChatFocus();
|
||||
})();
|
||||
}
|
||||
|
||||
closeAIAssistantChat(): void {
|
||||
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;
|
||||
}
|
||||
|
@ -22,7 +22,6 @@ import {
|
||||
FeCmdPacketType,
|
||||
ScreenDataType,
|
||||
PtyDataUpdateType,
|
||||
ModelUpdateType,
|
||||
UpdateMessage,
|
||||
InfoType,
|
||||
StrWithPos,
|
||||
@ -40,15 +39,18 @@ import {
|
||||
CmdInputTextPacketType,
|
||||
FileInfoType,
|
||||
ExtFile,
|
||||
HistorySearchParams,
|
||||
LineStateType,
|
||||
OV,
|
||||
OArr,
|
||||
OMap,
|
||||
CV,
|
||||
ScreenNumRunningCommandsUpdateType,
|
||||
ScreenStatusIndicatorUpdateType,
|
||||
} from "../types/types";
|
||||
import { WSControl } from "./ws";
|
||||
import { cmdStatusIsRunning } from "../app/line/lineutil";
|
||||
import * as appconst from "../app/appconst";
|
||||
import { remotePtrToString, cmdPacketString } from "../util/modelutil";
|
||||
import { checkKeyPressed, adaptFromReactOrNativeKeyEvent, setKeyUtilPlatform } from "../util/keyutil";
|
||||
import { OV, OArr, OMap, CV } from "../types/types";
|
||||
import { Session } from "./session";
|
||||
import { ScreenLines } from "./screenlines";
|
||||
import { InputModel } from "./input";
|
||||
@ -187,7 +189,7 @@ class Model {
|
||||
this.isDev = getApi().getIsDev();
|
||||
this.authKey = getApi().getAuthKey();
|
||||
this.ws = new WSControl(this.getBaseWsHostPort(), this.clientId, this.authKey, (message: any) => {
|
||||
let interactive = message?.interactive ?? false;
|
||||
const interactive = message?.interactive ?? false;
|
||||
this.runUpdate(message, interactive);
|
||||
});
|
||||
this.ws.reconnect();
|
||||
@ -200,17 +202,17 @@ class Model {
|
||||
this.remotesModel = new RemotesModel(this);
|
||||
this.modalsModel = new ModalsModel();
|
||||
this.mainSidebarModel = new MainSidebarModel(this);
|
||||
let isWaveSrvRunning = getApi().getWaveSrvStatus();
|
||||
const isWaveSrvRunning = getApi().getWaveSrvStatus();
|
||||
this.waveSrvRunning = mobx.observable.box(isWaveSrvRunning, {
|
||||
name: "model-wavesrv-running",
|
||||
});
|
||||
this.platform = this.getPlatform();
|
||||
this.termFontSize = mobx.computed(() => {
|
||||
let cdata = this.clientData.get();
|
||||
if (cdata == null || cdata.feopts == null || cdata.feopts.termfontsize == null) {
|
||||
const cdata = this.clientData.get();
|
||||
if (cdata?.feopts?.termfontsize == null) {
|
||||
return appconst.DefaultTermFontSize;
|
||||
}
|
||||
let fontSize = Math.ceil(cdata.feopts.termfontsize);
|
||||
const fontSize = Math.ceil(cdata.feopts.termfontsize);
|
||||
if (fontSize < appconst.MinFontSize) {
|
||||
return appconst.MinFontSize;
|
||||
}
|
||||
@ -265,11 +267,11 @@ class Model {
|
||||
}
|
||||
|
||||
needsTos(): boolean {
|
||||
let cdata = this.clientData.get();
|
||||
const cdata = this.clientData.get();
|
||||
if (cdata == null) {
|
||||
return false;
|
||||
}
|
||||
return cdata.clientopts == null || !cdata.clientopts.acceptedtos;
|
||||
return !cdata.clientopts?.acceptedtos;
|
||||
}
|
||||
|
||||
refreshClient(): void {
|
||||
@ -288,7 +290,7 @@ class Model {
|
||||
|
||||
refocus() {
|
||||
// givefocus() give back focus to cmd or input
|
||||
let activeScreen = this.getActiveScreen();
|
||||
const activeScreen = this.getActiveScreen();
|
||||
if (screen == null) {
|
||||
return;
|
||||
}
|
||||
@ -296,8 +298,8 @@ class Model {
|
||||
}
|
||||
|
||||
getWebSharedScreens(): Screen[] {
|
||||
let rtn: Screen[] = [];
|
||||
for (let screen of this.screenMap.values()) {
|
||||
const rtn: Screen[] = [];
|
||||
for (const screen of this.screenMap.values()) {
|
||||
if (screen.shareMode.get() == "web") {
|
||||
rtn.push(screen);
|
||||
}
|
||||
@ -309,7 +311,7 @@ class Model {
|
||||
if (this.clientData.get() == null) {
|
||||
return true;
|
||||
}
|
||||
let cdata = this.clientData.get();
|
||||
const cdata = this.clientData.get();
|
||||
if (cdata.cmdstoretype == "session") {
|
||||
return true;
|
||||
}
|
||||
@ -318,8 +320,8 @@ class Model {
|
||||
|
||||
showAlert(alertMessage: AlertMessageType): Promise<boolean> {
|
||||
if (alertMessage.confirmflag != null) {
|
||||
let cdata = this.clientData.get();
|
||||
let noConfirm = cdata.clientopts?.confirmflags?.[alertMessage.confirmflag];
|
||||
const cdata = this.clientData.get();
|
||||
const noConfirm = cdata.clientopts?.confirmflags?.[alertMessage.confirmflag];
|
||||
if (noConfirm) {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
@ -328,7 +330,7 @@ class Model {
|
||||
this.alertMessage.set(alertMessage);
|
||||
this.modalsModel.pushModal(appconst.ALERT);
|
||||
})();
|
||||
let prtn = new Promise<boolean>((resolve, reject) => {
|
||||
const prtn = new Promise<boolean>((resolve, reject) => {
|
||||
this.alertPromiseResolver = resolve;
|
||||
});
|
||||
return prtn;
|
||||
@ -405,7 +407,7 @@ class Model {
|
||||
}
|
||||
|
||||
docKeyDownHandler(e: KeyboardEvent) {
|
||||
let waveEvent = adaptFromReactOrNativeKeyEvent(e);
|
||||
const waveEvent = adaptFromReactOrNativeKeyEvent(e);
|
||||
if (isModKeyPress(e)) {
|
||||
return;
|
||||
}
|
||||
@ -447,7 +449,7 @@ class Model {
|
||||
if (this.clearModals()) {
|
||||
return;
|
||||
}
|
||||
let inputModel = this.inputModel;
|
||||
const inputModel = this.inputModel;
|
||||
inputModel.toggleInfoMsg();
|
||||
if (inputModel.inputMode.get() != null) {
|
||||
inputModel.resetInputMode();
|
||||
@ -460,9 +462,9 @@ class Model {
|
||||
}
|
||||
if (this.activeMainView.get() == "session" && checkKeyPressed(waveEvent, "Cmd:Ctrl:s")) {
|
||||
e.preventDefault();
|
||||
let activeScreen = this.getActiveScreen();
|
||||
const activeScreen = this.getActiveScreen();
|
||||
if (activeScreen != null) {
|
||||
let isSidebarOpen = activeScreen.isSidebarOpen();
|
||||
const isSidebarOpen = activeScreen.isSidebarOpen();
|
||||
if (isSidebarOpen) {
|
||||
GlobalCommandRunner.screenSidebarClose();
|
||||
} else {
|
||||
@ -471,7 +473,7 @@ class Model {
|
||||
}
|
||||
}
|
||||
if (checkKeyPressed(waveEvent, "Cmd:d")) {
|
||||
let ranDelete = this.deleteActiveLine();
|
||||
const ranDelete = this.deleteActiveLine();
|
||||
if (ranDelete) {
|
||||
e.preventDefault();
|
||||
}
|
||||
@ -479,22 +481,22 @@ class Model {
|
||||
}
|
||||
|
||||
deleteActiveLine(): boolean {
|
||||
let activeScreen = this.getActiveScreen();
|
||||
const activeScreen = this.getActiveScreen();
|
||||
if (activeScreen == null || activeScreen.getFocusType() != "cmd") {
|
||||
return false;
|
||||
}
|
||||
let selectedLine = activeScreen.selectedLine.get();
|
||||
const selectedLine = activeScreen.selectedLine.get();
|
||||
if (selectedLine == null || selectedLine <= 0) {
|
||||
return false;
|
||||
}
|
||||
let line = activeScreen.getLineByNum(selectedLine);
|
||||
const line = activeScreen.getLineByNum(selectedLine);
|
||||
if (line == null) {
|
||||
return false;
|
||||
}
|
||||
let cmd = activeScreen.getCmd(line);
|
||||
const cmd = activeScreen.getCmd(line);
|
||||
if (cmd != null) {
|
||||
if (cmd.isRunning()) {
|
||||
let info: InfoType = { infomsg: "Cannot delete a running command" };
|
||||
const info: InfoType = { infomsg: "Cannot delete a running command" };
|
||||
this.inputModel.flashInfoMsg(info, 2000);
|
||||
return false;
|
||||
}
|
||||
@ -507,11 +509,11 @@ class Model {
|
||||
if (this.activeMainView.get() != "session") {
|
||||
return;
|
||||
}
|
||||
let activeScreen = this.getActiveScreen();
|
||||
const activeScreen = this.getActiveScreen();
|
||||
if (activeScreen == null) {
|
||||
return;
|
||||
}
|
||||
let rtnp = this.showAlert({
|
||||
const rtnp = this.showAlert({
|
||||
message: "Are you sure you want to delete this screen?",
|
||||
confirm: true,
|
||||
});
|
||||
@ -527,7 +529,7 @@ class Model {
|
||||
if (this.activeMainView.get() != "session") {
|
||||
return;
|
||||
}
|
||||
let activeScreen = this.getActiveScreen();
|
||||
const activeScreen = this.getActiveScreen();
|
||||
if (activeScreen == null) {
|
||||
return;
|
||||
}
|
||||
@ -536,7 +538,7 @@ class Model {
|
||||
GlobalCommandRunner.lineRestart("E", true);
|
||||
} else {
|
||||
// restart selected line
|
||||
let selectedLine = activeScreen.selectedLine.get();
|
||||
const selectedLine = activeScreen.selectedLine.get();
|
||||
if (selectedLine == null || selectedLine == 0) {
|
||||
return;
|
||||
}
|
||||
@ -585,7 +587,7 @@ class Model {
|
||||
}
|
||||
|
||||
getCurRemoteInstance(): RemoteInstanceType {
|
||||
let screen = this.getActiveScreen();
|
||||
const screen = this.getActiveScreen();
|
||||
if (screen == null) {
|
||||
return null;
|
||||
}
|
||||
@ -603,12 +605,12 @@ class Model {
|
||||
}
|
||||
|
||||
getContentHeight(context: RendererContext): number {
|
||||
let key = context.screenId + "/" + context.lineId;
|
||||
const key = context.screenId + "/" + context.lineId;
|
||||
return this.termUsedRowsCache[key];
|
||||
}
|
||||
|
||||
setContentHeight(context: RendererContext, height: number): void {
|
||||
let key = context.screenId + "/" + context.lineId;
|
||||
const key = context.screenId + "/" + context.lineId;
|
||||
this.termUsedRowsCache[key] = height;
|
||||
GlobalCommandRunner.setTermUsedRows(context, height);
|
||||
}
|
||||
@ -622,7 +624,7 @@ class Model {
|
||||
}
|
||||
|
||||
getUIContext(): UIContextType {
|
||||
let rtn: UIContextType = {
|
||||
const rtn: UIContextType = {
|
||||
sessionid: null,
|
||||
screenid: null,
|
||||
remote: null,
|
||||
@ -630,10 +632,10 @@ class Model {
|
||||
linenum: null,
|
||||
build: appconst.VERSION + " " + appconst.BUILD,
|
||||
};
|
||||
let session = this.getActiveSession();
|
||||
const session = this.getActiveSession();
|
||||
if (session != null) {
|
||||
rtn.sessionid = session.sessionId;
|
||||
let screen = session.getActiveScreen();
|
||||
const screen = session.getActiveScreen();
|
||||
if (screen != null) {
|
||||
rtn.screenid = screen.screenId;
|
||||
rtn.remote = screen.curRemote.get();
|
||||
@ -653,7 +655,7 @@ class Model {
|
||||
}
|
||||
|
||||
onLCmd(e: any, mods: KeyModsType) {
|
||||
let screen = this.getActiveScreen();
|
||||
const screen = this.getActiveScreen();
|
||||
if (screen != null) {
|
||||
GlobalCommandRunner.screenSetFocus("cmd");
|
||||
}
|
||||
@ -671,11 +673,11 @@ class Model {
|
||||
if (this.inputModel.hasFocus()) {
|
||||
return { cmdInputFocus: true };
|
||||
}
|
||||
let lineElem: any = document.activeElement.closest(".line[data-lineid]");
|
||||
const lineElem: any = document.activeElement.closest(".line[data-lineid]");
|
||||
if (lineElem == null) {
|
||||
return { cmdInputFocus: false };
|
||||
}
|
||||
let lineNum = parseInt(lineElem.dataset.linenum);
|
||||
const lineNum = parseInt(lineElem.dataset.linenum);
|
||||
return {
|
||||
cmdInputFocus: false,
|
||||
lineid: lineElem.dataset.lineid,
|
||||
@ -685,17 +687,17 @@ class Model {
|
||||
}
|
||||
|
||||
cmdStatusUpdate(screenId: string, lineId: string, origStatus: string, newStatus: string) {
|
||||
let wasRunning = cmdStatusIsRunning(origStatus);
|
||||
let isRunning = cmdStatusIsRunning(newStatus);
|
||||
const wasRunning = cmdStatusIsRunning(origStatus);
|
||||
const isRunning = cmdStatusIsRunning(newStatus);
|
||||
if (wasRunning && !isRunning) {
|
||||
let ptr = this.getActiveLine(screenId, lineId);
|
||||
const ptr = this.getActiveLine(screenId, lineId);
|
||||
if (ptr != null) {
|
||||
let screen = ptr.screen;
|
||||
let renderer = screen.getRenderer(lineId);
|
||||
const screen = ptr.screen;
|
||||
const renderer = screen.getRenderer(lineId);
|
||||
if (renderer != null) {
|
||||
renderer.setIsDone();
|
||||
}
|
||||
let term = screen.getTermWrap(lineId);
|
||||
const term = screen.getTermWrap(lineId);
|
||||
if (term != null) {
|
||||
term.cmdDone();
|
||||
}
|
||||
@ -747,21 +749,25 @@ class Model {
|
||||
|
||||
runUpdate(genUpdate: UpdateMessage, interactive: boolean) {
|
||||
mobx.action(() => {
|
||||
let oldContext = this.getUIContext();
|
||||
const oldContext = this.getUIContext();
|
||||
try {
|
||||
this.runUpdate_internal(genUpdate, oldContext, interactive);
|
||||
} catch (e) {
|
||||
console.log("error running update", e, genUpdate);
|
||||
console.warn("error running update", e, genUpdate);
|
||||
throw e;
|
||||
}
|
||||
let newContext = this.getUIContext();
|
||||
const newContext = this.getUIContext();
|
||||
if (oldContext.sessionid != newContext.sessionid || oldContext.screenid != newContext.screenid) {
|
||||
this.inputModel.resetInput();
|
||||
if ("cmdline" in genUpdate) {
|
||||
if (!("ptydata64" in genUpdate)) {
|
||||
const reversedGenUpdate = genUpdate.slice().reverse();
|
||||
const lastCmdLine = reversedGenUpdate.find((update) => "cmdline" in update);
|
||||
if (lastCmdLine) {
|
||||
// TODO a bit of a hack since this update gets applied in runUpdate_internal.
|
||||
// we then undo that update with the resetInput, and then redo it with the line below
|
||||
// not sure how else to handle this for now though
|
||||
this.inputModel.updateCmdLine(genUpdate.cmdline);
|
||||
this.inputModel.updateCmdLine(lastCmdLine.cmdline);
|
||||
}
|
||||
}
|
||||
} else if (remotePtrToString(oldContext.remote) != remotePtrToString(newContext.remote)) {
|
||||
this.inputModel.resetHistory();
|
||||
@ -769,27 +775,10 @@ class Model {
|
||||
})();
|
||||
}
|
||||
|
||||
runUpdate_internal(genUpdate: UpdateMessage, uiContext: UIContextType, interactive: boolean) {
|
||||
if ("ptydata64" in genUpdate) {
|
||||
let ptyMsg: PtyDataUpdateType = genUpdate;
|
||||
if (isBlank(ptyMsg.remoteid)) {
|
||||
// regular update
|
||||
this.updatePtyData(ptyMsg);
|
||||
} else {
|
||||
// remote update
|
||||
let ptyData = base64ToArray(ptyMsg.ptydata64);
|
||||
this.remotesModel.receiveData(ptyMsg.remoteid, ptyMsg.ptypos, ptyData);
|
||||
}
|
||||
return;
|
||||
}
|
||||
let update: ModelUpdateType = genUpdate;
|
||||
if ("screens" in update) {
|
||||
if (update.connect) {
|
||||
this.screenMap.clear();
|
||||
}
|
||||
let mods = genMergeDataMap(
|
||||
updateScreens(screens: ScreenDataType[]): void {
|
||||
const mods = genMergeDataMap(
|
||||
this.screenMap,
|
||||
update.screens,
|
||||
screens,
|
||||
(s: Screen) => s.screenId,
|
||||
(sdata: ScreenDataType) => sdata.screenid,
|
||||
(sdata: ScreenDataType) => new Screen(sdata, this)
|
||||
@ -798,116 +787,177 @@ class Model {
|
||||
this.removeScreenLinesByScreenId(screenId);
|
||||
}
|
||||
}
|
||||
if ("sessions" in update || "activesessionid" in update) {
|
||||
if (update.connect) {
|
||||
this.sessionList.clear();
|
||||
}
|
||||
let [oldActiveSessionId, oldActiveScreenId] = this.getActiveIds();
|
||||
|
||||
updateSessions(sessions: SessionDataType[]): void {
|
||||
genMergeData(
|
||||
this.sessionList,
|
||||
update.sessions,
|
||||
sessions,
|
||||
(s: Session) => s.sessionId,
|
||||
(sdata: SessionDataType) => sdata.sessionid,
|
||||
(sdata: SessionDataType) => new Session(sdata, this),
|
||||
(s: Session) => s.sessionIdx.get()
|
||||
);
|
||||
if ("activesessionid" in update) {
|
||||
let newSessionId = update.activesessionid;
|
||||
}
|
||||
|
||||
updateActiveSession(sessionId: string): void {
|
||||
const [oldActiveSessionId, oldActiveScreenId] = this.getActiveIds();
|
||||
|
||||
if (sessionId != null) {
|
||||
const newSessionId = sessionId;
|
||||
if (this.activeSessionId.get() != newSessionId) {
|
||||
this.activeSessionId.set(newSessionId);
|
||||
}
|
||||
}
|
||||
let [newActiveSessionId, newActiveScreenId] = this.getActiveIds();
|
||||
const [newActiveSessionId, newActiveScreenId] = this.getActiveIds();
|
||||
if (oldActiveSessionId != newActiveSessionId || oldActiveScreenId != newActiveScreenId) {
|
||||
this.activeMainView.set("session");
|
||||
this.deactivateScreenLines();
|
||||
this.ws.watchScreen(newActiveSessionId, newActiveScreenId);
|
||||
}
|
||||
}
|
||||
if ("line" in update) {
|
||||
this.addLineCmd(update.line, update.cmd, interactive);
|
||||
} else if ("cmd" in update) {
|
||||
this.updateCmd(update.cmd);
|
||||
}
|
||||
if ("lines" in update) {
|
||||
for (const line of update.lines) {
|
||||
this.addLineCmd(line, null, interactive);
|
||||
|
||||
updateScreenNumRunningCommands(numRunningCommandUpdates: ScreenNumRunningCommandsUpdateType[]) {
|
||||
for (const update of numRunningCommandUpdates) {
|
||||
this.getScreenById_single(update.screenid)?.setNumRunningCmds(update.num);
|
||||
}
|
||||
}
|
||||
if ("screenlines" in update) {
|
||||
this.updateScreenLines(update.screenlines, false);
|
||||
}
|
||||
if ("remotes" in update) {
|
||||
if (update.connect) {
|
||||
this.remotes.clear();
|
||||
}
|
||||
this.updateRemotes(update.remotes);
|
||||
// This code's purpose is to show view remote connection modal when a new connection is added
|
||||
if (update.remotes?.length && this.remotesModel.recentConnAddedState.get()) {
|
||||
this.remotesModel.openReadModal(update.remotes[0].remoteid);
|
||||
|
||||
updateScreenStatusIndicators(screenStatusIndicators: ScreenStatusIndicatorUpdateType[]) {
|
||||
for (const update of screenStatusIndicators) {
|
||||
this.getScreenById_single(update.screenid)?.setStatusIndicator(update.status);
|
||||
}
|
||||
}
|
||||
if ("mainview" in update) {
|
||||
if (update.mainview == "plugins") {
|
||||
this.pluginsModel.showPluginsView();
|
||||
} else if (update.mainview == "bookmarks") {
|
||||
this.bookmarksModel.showBookmarksView(update.bookmarks, update.selectedbookmark);
|
||||
} else if (update.mainview == "session") {
|
||||
this.activeMainView.set("session");
|
||||
} else if (update.mainview == "history") {
|
||||
this.historyViewModel.showHistoryView(update.historyviewdata);
|
||||
|
||||
runUpdate_internal(genUpdate: UpdateMessage, uiContext: UIContextType, interactive: boolean) {
|
||||
if ("ptydata64" in genUpdate) {
|
||||
const ptyMsg: PtyDataUpdateType = genUpdate;
|
||||
if (isBlank(ptyMsg.remoteid)) {
|
||||
// regular update
|
||||
this.updatePtyData(ptyMsg);
|
||||
} else {
|
||||
console.log("invalid mainview in update:", update.mainview);
|
||||
// remote update
|
||||
const ptyData = base64ToArray(ptyMsg.ptydata64);
|
||||
this.remotesModel.receiveData(ptyMsg.remoteid, ptyMsg.ptypos, ptyData);
|
||||
}
|
||||
} else if ("bookmarks" in update) {
|
||||
this.bookmarksModel.mergeBookmarks(update.bookmarks);
|
||||
return;
|
||||
}
|
||||
if ("clientdata" in update) {
|
||||
let showedRemotesModal = false;
|
||||
genUpdate.forEach((update) => {
|
||||
if (update.connect != null) {
|
||||
if (update.connect.screens != null) {
|
||||
this.screenMap.clear();
|
||||
this.updateScreens(update.connect.screens);
|
||||
}
|
||||
if (update.connect.sessions != null) {
|
||||
this.sessionList.clear();
|
||||
this.updateSessions(update.connect.sessions);
|
||||
}
|
||||
if (update.connect.remotes != null) {
|
||||
this.remotes.clear();
|
||||
this.updateRemotes(update.connect.remotes);
|
||||
}
|
||||
if (update.connect.activesessionid != null) {
|
||||
this.updateActiveSession(update.connect.activesessionid);
|
||||
}
|
||||
if (update.connect.screennumrunningcommands != null) {
|
||||
this.updateScreenNumRunningCommands(update.connect.screennumrunningcommands);
|
||||
}
|
||||
if (update.connect.screenstatusindicators != null) {
|
||||
this.updateScreenStatusIndicators(update.connect.screenstatusindicators);
|
||||
}
|
||||
|
||||
this.sessionListLoaded.set(true);
|
||||
this.remotesLoaded.set(true);
|
||||
} else if (update.screen != null) {
|
||||
this.updateScreens([update.screen]);
|
||||
} else if (update.session != null) {
|
||||
this.updateSessions([update.session]);
|
||||
} else if (update.activesessionid != null) {
|
||||
this.updateActiveSession(update.activesessionid);
|
||||
} else if (update.line != null) {
|
||||
this.addLineCmd(update.line.line, update.line.cmd, interactive);
|
||||
} else if (update.cmd != null) {
|
||||
this.updateCmd(update.cmd);
|
||||
} else if (update.screenlines != null) {
|
||||
this.updateScreenLines(update.screenlines, false);
|
||||
} else if (update.remote != null) {
|
||||
this.updateRemotes([update.remote]);
|
||||
// This code's purpose is to show view remote connection modal when a new connection is added
|
||||
if (!showedRemotesModal && this.remotesModel.recentConnAddedState.get()) {
|
||||
showedRemotesModal = true;
|
||||
this.remotesModel.openReadModal(update.remote.remoteid);
|
||||
}
|
||||
} else if (update.mainview != null) {
|
||||
switch (update.mainview.mainview) {
|
||||
case "session":
|
||||
this.activeMainView.set("session");
|
||||
break;
|
||||
case "history":
|
||||
if (update.mainview.historyview != null) {
|
||||
this.historyViewModel.showHistoryView(update.mainview.historyview);
|
||||
} else {
|
||||
console.warn("invalid historyview in update:", update.mainview);
|
||||
}
|
||||
break;
|
||||
case "bookmarks":
|
||||
if (update.mainview.bookmarksview != null) {
|
||||
this.bookmarksModel.showBookmarksView(
|
||||
update.mainview.bookmarksview?.bookmarks ?? [],
|
||||
update.mainview.bookmarksview?.selectedbookmark
|
||||
);
|
||||
} else {
|
||||
console.warn("invalid bookmarksview in update:", update.mainview);
|
||||
}
|
||||
break;
|
||||
case "plugins":
|
||||
this.pluginsModel.showPluginsView();
|
||||
break;
|
||||
default:
|
||||
console.warn("invalid mainview in update:", update.mainview);
|
||||
}
|
||||
} else if (update.bookmarks != null) {
|
||||
if (update.bookmarks.bookmarks != null) {
|
||||
this.bookmarksModel.mergeBookmarks(update.bookmarks.bookmarks);
|
||||
}
|
||||
} else if (update.clientdata != null) {
|
||||
this.clientData.set(update.clientdata);
|
||||
}
|
||||
if (interactive && "info" in update) {
|
||||
let info: InfoType = update.info;
|
||||
} else if (update.cmdline != null) {
|
||||
this.inputModel.updateCmdLine(update.cmdline);
|
||||
} else if (update.openaicmdinfochat != null) {
|
||||
this.inputModel.setOpenAICmdInfoChat(update.openaicmdinfochat);
|
||||
} else if (update.screenstatusindicator != null) {
|
||||
this.updateScreenStatusIndicators([update.screenstatusindicator]);
|
||||
} else if (update.screennumrunningcommands != null) {
|
||||
this.updateScreenNumRunningCommands([update.screennumrunningcommands]);
|
||||
} else if (update.userinputrequest != null) {
|
||||
let userInputRequest: UserInputRequest = update.userinputrequest;
|
||||
this.modalsModel.pushModal(appconst.USER_INPUT, userInputRequest);
|
||||
} else if (interactive) {
|
||||
if (update.info != null) {
|
||||
const info: InfoType = update.info;
|
||||
this.inputModel.flashInfoMsg(info, info.timeoutms);
|
||||
}
|
||||
if (interactive && "remoteview" in update) {
|
||||
let rview: RemoteViewType = update.remoteview;
|
||||
} else if (update.remoteview != null) {
|
||||
const rview: RemoteViewType = update.remoteview;
|
||||
if (rview.remoteedit != null) {
|
||||
this.remotesModel.openEditModal({ ...rview.remoteedit });
|
||||
}
|
||||
}
|
||||
if (interactive && "alertmessage" in update) {
|
||||
let alertMessage: AlertMessageType = update.alertmessage;
|
||||
} else if (update.alertmessage != null) {
|
||||
const alertMessage: AlertMessageType = update.alertmessage;
|
||||
this.showAlert(alertMessage);
|
||||
}
|
||||
if ("cmdline" in update) {
|
||||
this.inputModel.updateCmdLine(update.cmdline);
|
||||
}
|
||||
if (interactive && "history" in update) {
|
||||
if (uiContext.sessionid == update.history.sessionid && uiContext.screenid == update.history.screenid) {
|
||||
} else if (update.history != null) {
|
||||
if (
|
||||
uiContext.sessionid == update.history.sessionid &&
|
||||
uiContext.screenid == update.history.screenid
|
||||
) {
|
||||
this.inputModel.setHistoryInfo(update.history);
|
||||
}
|
||||
} else if (this.isDev) {
|
||||
console.log("did not match update", update);
|
||||
}
|
||||
if ("connect" in update) {
|
||||
this.sessionListLoaded.set(true);
|
||||
this.remotesLoaded.set(true);
|
||||
}
|
||||
if ("openaicmdinfochat" in update) {
|
||||
this.inputModel.setOpenAICmdInfoChat(update.openaicmdinfochat);
|
||||
}
|
||||
if ("screenstatusindicators" in update) {
|
||||
for (const indicator of update.screenstatusindicators) {
|
||||
this.getScreenById_single(indicator.screenid)?.setStatusIndicator(indicator.status);
|
||||
}
|
||||
}
|
||||
if ("screennumrunningcommands" in update) {
|
||||
for (const snc of update.screennumrunningcommands) {
|
||||
this.getScreenById_single(snc.screenid)?.setNumRunningCmds(snc.num);
|
||||
}
|
||||
}
|
||||
if ("userinputrequest" in update) {
|
||||
let userInputRequest: UserInputRequest = update.userinputrequest;
|
||||
this.modalsModel.pushModal(appconst.USER_INPUT, userInputRequest);
|
||||
} else if (this.isDev) {
|
||||
console.log("did not match update", update);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
updateRemotes(remotes: RemoteType[]): void {
|
||||
@ -919,7 +969,7 @@ class Model {
|
||||
}
|
||||
|
||||
getSessionNames(): Record<string, string> {
|
||||
let rtn: Record<string, string> = {};
|
||||
const rtn: Record<string, string> = {};
|
||||
for (const session of this.sessionList) {
|
||||
rtn[session.sessionId] = session.name.get();
|
||||
}
|
||||
@ -927,8 +977,8 @@ class Model {
|
||||
}
|
||||
|
||||
getScreenNames(): Record<string, string> {
|
||||
let rtn: Record<string, string> = {};
|
||||
for (let screen of this.screenMap.values()) {
|
||||
const rtn: Record<string, string> = {};
|
||||
for (const screen of this.screenMap.values()) {
|
||||
rtn[screen.screenId] = screen.name.get();
|
||||
}
|
||||
return rtn;
|
||||
@ -958,13 +1008,13 @@ class Model {
|
||||
|
||||
updateScreenLines(slines: ScreenLinesType, load: boolean) {
|
||||
mobx.action(() => {
|
||||
let existingWin = this.screenLines.get(slines.screenid);
|
||||
const existingWin = this.screenLines.get(slines.screenid);
|
||||
if (existingWin == null) {
|
||||
if (!load) {
|
||||
console.log("cannot update screen-lines that does not exist", slines.screenid);
|
||||
return;
|
||||
}
|
||||
let newWindow = new ScreenLines(slines.screenid);
|
||||
const newWindow = new ScreenLines(slines.screenid);
|
||||
this.screenLines.set(slines.screenid, newWindow);
|
||||
newWindow.updateData(slines, load);
|
||||
} else {
|
||||
@ -989,8 +1039,8 @@ class Model {
|
||||
}
|
||||
|
||||
getSessionScreens(sessionId: string): Screen[] {
|
||||
let rtn: Screen[] = [];
|
||||
for (let screen of this.screenMap.values()) {
|
||||
const rtn: Screen[] = [];
|
||||
for (const screen of this.screenMap.values()) {
|
||||
if (screen.sessionId == sessionId) {
|
||||
rtn.push(screen);
|
||||
}
|
||||
@ -999,7 +1049,7 @@ class Model {
|
||||
}
|
||||
|
||||
getScreenLinesForActiveScreen(): ScreenLines {
|
||||
let screen = this.getActiveScreen();
|
||||
const screen = this.getActiveScreen();
|
||||
if (screen == null) {
|
||||
return null;
|
||||
}
|
||||
@ -1007,7 +1057,7 @@ class Model {
|
||||
}
|
||||
|
||||
getActiveScreen(): Screen {
|
||||
let session = this.getActiveSession();
|
||||
const session = this.getActiveSession();
|
||||
if (session == null) {
|
||||
return null;
|
||||
}
|
||||
@ -1018,11 +1068,11 @@ class Model {
|
||||
if (cmd == null || !cmd.restarted) {
|
||||
return;
|
||||
}
|
||||
let screen = this.screenMap.get(cmd.screenid);
|
||||
const screen = this.screenMap.get(cmd.screenid);
|
||||
if (screen == null) {
|
||||
return;
|
||||
}
|
||||
let termWrap = screen.getTermWrap(cmd.lineid);
|
||||
const termWrap = screen.getTermWrap(cmd.lineid);
|
||||
if (termWrap == null) {
|
||||
return;
|
||||
}
|
||||
@ -1030,7 +1080,7 @@ class Model {
|
||||
}
|
||||
|
||||
addLineCmd(line: LineType, cmd: CmdDataType, interactive: boolean) {
|
||||
let slines = this.getScreenLinesById(line.screenid);
|
||||
const slines = this.getScreenLinesById(line.screenid);
|
||||
if (slines == null) {
|
||||
return;
|
||||
}
|
||||
@ -1039,7 +1089,7 @@ class Model {
|
||||
}
|
||||
|
||||
updateCmd(cmd: CmdDataType) {
|
||||
let slines = this.screenLines.get(cmd.screenid);
|
||||
const slines = this.screenLines.get(cmd.screenid);
|
||||
if (slines != null) {
|
||||
slines.updateCmd(cmd);
|
||||
}
|
||||
@ -1050,12 +1100,12 @@ class Model {
|
||||
if (update == null || "ptydata64" in update) {
|
||||
return false;
|
||||
}
|
||||
return update.info != null || update.history != null;
|
||||
return update.some((u) => u.info != null || u.history != null);
|
||||
}
|
||||
|
||||
getClientDataLoop(loopNum: number): void {
|
||||
this.getClientData();
|
||||
let clientStop = this.getHasClientStop();
|
||||
const clientStop = this.getHasClientStop();
|
||||
if (this.clientData.get() != null && !clientStop) {
|
||||
return;
|
||||
}
|
||||
@ -1073,13 +1123,13 @@ class Model {
|
||||
}
|
||||
|
||||
getClientData(): void {
|
||||
let url = new URL(this.getBaseHostPort() + "/api/get-client-data");
|
||||
let fetchHeaders = this.getFetchHeaders();
|
||||
const url = new URL(this.getBaseHostPort() + "/api/get-client-data");
|
||||
const fetchHeaders = this.getFetchHeaders();
|
||||
fetch(url, { method: "post", body: null, headers: fetchHeaders })
|
||||
.then((resp) => handleJsonFetchResponse(url, resp))
|
||||
.then((data) => {
|
||||
mobx.action(() => {
|
||||
let clientData: ClientDataType = data.data;
|
||||
const clientData: ClientDataType = data.data;
|
||||
this.clientData.set(clientData);
|
||||
})();
|
||||
})
|
||||
@ -1096,10 +1146,10 @@ class Model {
|
||||
}
|
||||
}
|
||||
// adding cmdStr for debugging only (easily filter run-command calls in the network tab of debugger)
|
||||
let cmdStr = cmdPk.metacmd + (cmdPk.metasubcmd ? ":" + cmdPk.metasubcmd : "");
|
||||
let url = new URL(this.getBaseHostPort() + "/api/run-command?cmd=" + cmdStr);
|
||||
let fetchHeaders = this.getFetchHeaders();
|
||||
let prtn = fetch(url, {
|
||||
const cmdStr = cmdPk.metacmd + (cmdPk.metasubcmd ? ":" + cmdPk.metasubcmd : "");
|
||||
const url = new URL(this.getBaseHostPort() + "/api/run-command?cmd=" + cmdStr);
|
||||
const fetchHeaders = this.getFetchHeaders();
|
||||
const prtn = fetch(url, {
|
||||
method: "post",
|
||||
body: JSON.stringify(cmdPk),
|
||||
headers: fetchHeaders,
|
||||
@ -1107,7 +1157,7 @@ class Model {
|
||||
.then((resp) => handleJsonFetchResponse(url, resp))
|
||||
.then((data) => {
|
||||
mobx.action(() => {
|
||||
let update = data.data;
|
||||
const update = data.data;
|
||||
if (update != null) {
|
||||
this.runUpdate(update, interactive);
|
||||
}
|
||||
@ -1135,7 +1185,7 @@ class Model {
|
||||
kwargs: Record<string, string>,
|
||||
interactive: boolean
|
||||
): Promise<CommandRtnType> {
|
||||
let pk: FeCmdPacketType = {
|
||||
const pk: FeCmdPacketType = {
|
||||
type: "fecmd",
|
||||
metacmd: metaCmd,
|
||||
metasubcmd: metaSubCmd,
|
||||
@ -1157,9 +1207,9 @@ class Model {
|
||||
}
|
||||
|
||||
submitChatInfoCommand(chatMsg: string, curLineStr: string, clear: boolean): Promise<CommandRtnType> {
|
||||
let commandStr = "/chat " + chatMsg;
|
||||
let interactive = false;
|
||||
let pk: FeCmdPacketType = {
|
||||
const commandStr = "/chat " + chatMsg;
|
||||
const interactive = false;
|
||||
const pk: FeCmdPacketType = {
|
||||
type: "fecmd",
|
||||
metacmd: "eval",
|
||||
args: [commandStr],
|
||||
@ -1179,7 +1229,7 @@ class Model {
|
||||
}
|
||||
|
||||
submitRawCommand(cmdStr: string, addToHistory: boolean, interactive: boolean): Promise<CommandRtnType> {
|
||||
let pk: FeCmdPacketType = {
|
||||
const pk: FeCmdPacketType = {
|
||||
type: "fecmd",
|
||||
metacmd: "eval",
|
||||
args: [cmdStr],
|
||||
@ -1196,16 +1246,16 @@ class Model {
|
||||
|
||||
// returns [sessionId, screenId]
|
||||
getActiveIds(): [string, string] {
|
||||
let activeSession = this.getActiveSession();
|
||||
let activeScreen = this.getActiveScreen();
|
||||
const activeSession = this.getActiveSession();
|
||||
const activeScreen = this.getActiveScreen();
|
||||
return [activeSession?.sessionId, activeScreen?.screenId];
|
||||
}
|
||||
|
||||
_loadScreenLinesAsync(newWin: ScreenLines) {
|
||||
this.screenLines.set(newWin.screenId, newWin);
|
||||
let usp = new URLSearchParams({ screenid: newWin.screenId });
|
||||
let url = new URL(this.getBaseHostPort() + "/api/get-screen-lines?" + usp.toString());
|
||||
let fetchHeaders = this.getFetchHeaders();
|
||||
const usp = new URLSearchParams({ screenid: newWin.screenId });
|
||||
const url = new URL(this.getBaseHostPort() + "/api/get-screen-lines?" + usp.toString());
|
||||
const fetchHeaders = this.getFetchHeaders();
|
||||
fetch(url, { headers: fetchHeaders })
|
||||
.then((resp) => handleJsonFetchResponse(url, resp))
|
||||
.then((data) => {
|
||||
@ -1213,7 +1263,7 @@ class Model {
|
||||
console.log("null screen-lines returned from get-screen-lines");
|
||||
return;
|
||||
}
|
||||
let slines: ScreenLinesType = data.data;
|
||||
const slines: ScreenLinesType = data.data;
|
||||
this.updateScreenLines(slines, true);
|
||||
})
|
||||
.catch((err) => {
|
||||
@ -1222,7 +1272,7 @@ class Model {
|
||||
}
|
||||
|
||||
loadScreenLines(screenId: string): ScreenLines {
|
||||
let newWin = new ScreenLines(screenId);
|
||||
const newWin = new ScreenLines(screenId);
|
||||
setTimeout(() => this._loadScreenLinesAsync(newWin), 0);
|
||||
return newWin;
|
||||
}
|
||||
@ -1235,7 +1285,7 @@ class Model {
|
||||
}
|
||||
|
||||
getRemoteNames(): Record<string, string> {
|
||||
let rtn: Record<string, string> = {};
|
||||
const rtn: Record<string, string> = {};
|
||||
for (const remote of this.remotes) {
|
||||
if (!isBlank(remote.remotealias)) {
|
||||
rtn[remote.remoteid] = remote.remotealias;
|
||||
@ -1260,7 +1310,7 @@ class Model {
|
||||
}
|
||||
|
||||
getCmdByScreenLine(screenId: string, lineId: string): Cmd {
|
||||
let slines = this.getScreenLinesById(screenId);
|
||||
const slines = this.getScreenLinesById(screenId);
|
||||
if (slines == null) {
|
||||
return null;
|
||||
}
|
||||
@ -1268,14 +1318,14 @@ class Model {
|
||||
}
|
||||
|
||||
getActiveLine(screenId: string, lineid: string): SWLinePtr {
|
||||
let slines = this.screenLines.get(screenId);
|
||||
const slines = this.screenLines.get(screenId);
|
||||
if (slines == null) {
|
||||
return null;
|
||||
}
|
||||
if (!slines.loaded.get()) {
|
||||
return null;
|
||||
}
|
||||
let cmd = slines.getCmd(lineid);
|
||||
const cmd = slines.getCmd(lineid);
|
||||
if (cmd == null) {
|
||||
return null;
|
||||
}
|
||||
@ -1289,12 +1339,12 @@ class Model {
|
||||
if (line == null) {
|
||||
return null;
|
||||
}
|
||||
let screen = this.getScreenById_single(slines.screenId);
|
||||
const screen = this.getScreenById_single(slines.screenId);
|
||||
return { line: line, slines: slines, screen: screen };
|
||||
}
|
||||
|
||||
updatePtyData(ptyMsg: PtyDataUpdateType): void {
|
||||
let linePtr = this.getActiveLine(ptyMsg.screenid, ptyMsg.lineid);
|
||||
const linePtr = this.getActiveLine(ptyMsg.screenid, ptyMsg.lineid);
|
||||
if (linePtr != null) {
|
||||
linePtr.screen.updatePtyData(ptyMsg);
|
||||
}
|
||||
@ -1320,7 +1370,7 @@ class Model {
|
||||
}
|
||||
|
||||
sendCmdInputText(screenId: string, sp: StrWithPos) {
|
||||
let pk: CmdInputTextPacketType = {
|
||||
const pk: CmdInputTextPacketType = {
|
||||
type: "cmdinputtext",
|
||||
seqnum: this.getNextPacketSeqNum(),
|
||||
screenid: screenId,
|
||||
@ -1334,7 +1384,7 @@ class Model {
|
||||
}
|
||||
|
||||
resolveRemoteIdToRef(remoteId: string) {
|
||||
let remote = this.getRemote(remoteId);
|
||||
const remote = this.getRemote(remoteId);
|
||||
if (remote == null) {
|
||||
return "[unknown]";
|
||||
}
|
||||
@ -1345,7 +1395,7 @@ class Model {
|
||||
}
|
||||
|
||||
resolveRemoteIdToFullRef(remoteId: string) {
|
||||
let remote = this.getRemote(remoteId);
|
||||
const remote = this.getRemote(remoteId);
|
||||
if (remote == null) {
|
||||
return "[unknown]";
|
||||
}
|
||||
@ -1356,17 +1406,17 @@ class Model {
|
||||
}
|
||||
|
||||
readRemoteFile(screenId: string, lineId: string, path: string): Promise<ExtFile> {
|
||||
let urlParams = {
|
||||
const urlParams = {
|
||||
screenid: screenId,
|
||||
lineid: lineId,
|
||||
path: path,
|
||||
};
|
||||
let usp = new URLSearchParams(urlParams);
|
||||
let url = new URL(this.getBaseHostPort() + "/api/read-file?" + usp.toString());
|
||||
let fetchHeaders = this.getFetchHeaders();
|
||||
const usp = new URLSearchParams(urlParams);
|
||||
const url = new URL(this.getBaseHostPort() + "/api/read-file?" + usp.toString());
|
||||
const fetchHeaders = this.getFetchHeaders();
|
||||
let fileInfo: FileInfoType = null;
|
||||
let badResponseStr: string = null;
|
||||
let prtn = fetch(url, { method: "get", headers: fetchHeaders })
|
||||
const prtn = fetch(url, { method: "get", headers: fetchHeaders })
|
||||
.then((resp) => {
|
||||
if (!resp.ok) {
|
||||
badResponseStr = sprintf(
|
||||
@ -1381,14 +1431,14 @@ class Model {
|
||||
})
|
||||
.then((blobOrText: any) => {
|
||||
if (blobOrText instanceof Blob) {
|
||||
let blob: Blob = blobOrText;
|
||||
let file = new File([blob], fileInfo.name, { type: blob.type, lastModified: fileInfo.modts });
|
||||
let isWriteable = (fileInfo.perm & 0o222) > 0; // checks for unix permission "w" bits
|
||||
const blob: Blob = blobOrText;
|
||||
const file = new File([blob], fileInfo.name, { type: blob.type, lastModified: fileInfo.modts });
|
||||
const isWriteable = (fileInfo.perm & 0o222) > 0; // checks for unix permission "w" bits
|
||||
(file as any).readOnly = !isWriteable;
|
||||
(file as any).notFound = !!fileInfo.notfound;
|
||||
return file as ExtFile;
|
||||
} else {
|
||||
let textError: string = blobOrText;
|
||||
const textError: string = blobOrText;
|
||||
if (textError == null || textError.length == 0) {
|
||||
throw new Error(badResponseStr);
|
||||
}
|
||||
@ -1398,7 +1448,7 @@ class Model {
|
||||
return prtn;
|
||||
}
|
||||
|
||||
writeRemoteFile(
|
||||
async writeRemoteFile(
|
||||
screenId: string,
|
||||
lineId: string,
|
||||
path: string,
|
||||
@ -1406,24 +1456,21 @@ class Model {
|
||||
opts?: { useTemp?: boolean }
|
||||
): Promise<void> {
|
||||
opts = opts || {};
|
||||
let params = {
|
||||
const params = {
|
||||
screenid: screenId,
|
||||
lineid: lineId,
|
||||
path: path,
|
||||
usetemp: !!opts.useTemp,
|
||||
};
|
||||
let formData = new FormData();
|
||||
const formData = new FormData();
|
||||
formData.append("params", JSON.stringify(params));
|
||||
let blob = new Blob([data], { type: "application/octet-stream" });
|
||||
const blob = new Blob([data], { type: "application/octet-stream" });
|
||||
formData.append("data", blob);
|
||||
let url = new URL(this.getBaseHostPort() + "/api/write-file");
|
||||
let fetchHeaders = this.getFetchHeaders();
|
||||
let prtn = fetch(url, { method: "post", headers: fetchHeaders, body: formData });
|
||||
return prtn
|
||||
.then((resp) => handleJsonFetchResponse(url, resp))
|
||||
.then((_) => {
|
||||
return;
|
||||
});
|
||||
const url = new URL(this.getBaseHostPort() + "/api/write-file");
|
||||
const fetchHeaders = this.getFetchHeaders();
|
||||
const prtn = fetch(url, { method: "post", headers: fetchHeaders, body: formData });
|
||||
const resp = await prtn;
|
||||
const _ = await handleJsonFetchResponse(url, resp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
@ -866,6 +886,7 @@ export type {
|
||||
CmdInputTextPacketType,
|
||||
OpenAICmdInfoChatMessageType,
|
||||
ScreenStatusIndicatorUpdateType,
|
||||
ScreenNumRunningCommandsUpdateType,
|
||||
OV,
|
||||
OArr,
|
||||
OMap,
|
||||
|
114
src/util/util.ts
114
src/util/util.ts
@ -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") {
|
||||
switch (r.status) {
|
||||
case "connected":
|
||||
return 1;
|
||||
}
|
||||
if (r.status == "connecting") {
|
||||
case "connecting":
|
||||
return 2;
|
||||
}
|
||||
if (r.status == "disconnected") {
|
||||
case "disconnected":
|
||||
return 3;
|
||||
}
|
||||
if (r.status == "error") {
|
||||
case "error":
|
||||
return 4;
|
||||
}
|
||||
default:
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -515,7 +515,7 @@ func SyncCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
update.Interactive = pk.Interactive
|
||||
sstore.AddInteractiveUpdate(update, pk.Interactive)
|
||||
sstore.MainBus.SendScreenUpdate(ids.ScreenId, update)
|
||||
return nil, nil
|
||||
}
|
||||
@ -623,7 +623,7 @@ func RunCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.U
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
update.Interactive = pk.Interactive
|
||||
sstore.AddInteractiveUpdate(update, pk.Interactive)
|
||||
// this update is sent asynchronously for timing issues. the cmd update comes async as well
|
||||
// so if we return this directly it sometimes gets evaluated first. by pushing it on the MainBus
|
||||
// it ensures it happens after the command creation event.
|
||||
@ -729,9 +729,9 @@ func EvalCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.
|
||||
if resolveErr == nil {
|
||||
screen, sidebarErr := implementRunInSidebar(ctx, ids.ScreenId, historyContext.LineId)
|
||||
if sidebarErr == nil {
|
||||
modelUpdate.UpdateScreen(screen)
|
||||
sstore.AddScreenUpdate(modelUpdate, screen)
|
||||
} else {
|
||||
modelUpdate.AddInfoError(fmt.Sprintf("cannot move command to sidebar: %v", sidebarErr))
|
||||
sstore.AddInfoMsgUpdateError(modelUpdate, fmt.Sprintf("cannot move command to sidebar: %v", sidebarErr))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -775,9 +775,8 @@ func ScreenArchiveCommand(ctx context.Context, pk *scpacket.FeCommandPacketType)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("/screen:archive cannot get updated screen obj: %v", err)
|
||||
}
|
||||
update := &sstore.ModelUpdate{
|
||||
Screens: []*sstore.ScreenType{screen},
|
||||
}
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, *screen)
|
||||
return update, nil
|
||||
}
|
||||
}
|
||||
@ -798,7 +797,7 @@ func ScreenDeleteCommand(ctx context.Context, pk *scpacket.FeCommandPacketType)
|
||||
if screenId == "" {
|
||||
return nil, fmt.Errorf("/screen:delete no active screen or screen arg passed")
|
||||
}
|
||||
update, err := sstore.DeleteScreen(ctx, screenId, false)
|
||||
update, err := sstore.DeleteScreen(ctx, screenId, false, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -853,13 +852,14 @@ func ScreenReorderCommand(ctx context.Context, pk *scpacket.FeCommandPacketType)
|
||||
}
|
||||
|
||||
// Prepare the update packet to send back to the client
|
||||
update := &sstore.ModelUpdate{
|
||||
Screens: screens,
|
||||
Info: &sstore.InfoMsgType{
|
||||
update := &sstore.ModelUpdate{}
|
||||
for _, screen := range screens {
|
||||
sstore.AddUpdate(update, *screen)
|
||||
}
|
||||
sstore.AddUpdate(update, sstore.InfoMsgType{
|
||||
InfoMsg: "screen indices updated successfully",
|
||||
TimeoutMs: 2000,
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
return update, nil
|
||||
}
|
||||
@ -968,13 +968,13 @@ func ScreenSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ss
|
||||
if !setNonAnchor {
|
||||
return nil, nil
|
||||
}
|
||||
update := &sstore.ModelUpdate{
|
||||
Screens: []*sstore.ScreenType{screen},
|
||||
Info: &sstore.InfoMsgType{
|
||||
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, *screen)
|
||||
sstore.AddUpdate(update, sstore.InfoMsgType{
|
||||
InfoMsg: fmt.Sprintf("screen updated %s", formatStrs(varsUpdated, "and", false)),
|
||||
TimeoutMs: 2000,
|
||||
},
|
||||
}
|
||||
})
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -1043,7 +1043,9 @@ func SidebarOpenCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &sstore.ModelUpdate{Screens: []*sstore.ScreenType{screen}}, nil
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, *screen)
|
||||
return update, nil
|
||||
}
|
||||
|
||||
func SidebarCloseCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||
@ -1055,7 +1057,9 @@ func SidebarCloseCommand(ctx context.Context, pk *scpacket.FeCommandPacketType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &sstore.ModelUpdate{Screens: []*sstore.ScreenType{screen}}, nil
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, *screen)
|
||||
return update, nil
|
||||
}
|
||||
|
||||
func SidebarAddCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||
@ -1083,7 +1087,9 @@ func SidebarAddCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (s
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("/%s error updating screenviewopts: %v", GetCmdStr(pk), err)
|
||||
}
|
||||
return &sstore.ModelUpdate{Screens: []*sstore.ScreenType{screen}}, nil
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, *screen)
|
||||
return update, nil
|
||||
}
|
||||
|
||||
func SidebarRemoveCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||
@ -1105,7 +1111,25 @@ func SidebarRemoveCommand(ctx context.Context, pk *scpacket.FeCommandPacketType)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("/%s error updating screenviewopts: %v", GetCmdStr(pk), err)
|
||||
}
|
||||
return &sstore.ModelUpdate{Screens: []*sstore.ScreenType{screen}}, nil
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, *screen)
|
||||
return update, nil
|
||||
}
|
||||
|
||||
func createRemoteViewRemoteIdUpdate(remoteId string) sstore.UpdatePacket {
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, sstore.RemoteViewType{
|
||||
PtyRemoteId: remoteId,
|
||||
})
|
||||
return update
|
||||
}
|
||||
|
||||
func createRemoteViewRemoteEditUpdate(redit *sstore.RemoteEditType) sstore.UpdatePacket {
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, sstore.RemoteViewType{
|
||||
RemoteEdit: redit,
|
||||
})
|
||||
return update
|
||||
}
|
||||
|
||||
func prettyPrintByteSize(size int64) string {
|
||||
@ -1622,7 +1646,7 @@ func CopyFileCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sst
|
||||
// TODO tricky error since the command was a success, but we can't show the output
|
||||
return nil, err
|
||||
}
|
||||
update.Interactive = pk.Interactive
|
||||
sstore.AddInteractiveUpdate(update, pk.Interactive)
|
||||
if destRemote != ConnectedRemote && destRemoteId != nil && !destRemoteId.RState.IsConnected() {
|
||||
writeStringToPty(ctx, cmd, fmt.Sprintf("Attempting to autoconnect to remote %v\r\n", destRemote), &outputPos)
|
||||
err = destRemoteId.MShell.TryAutoConnect()
|
||||
@ -1662,11 +1686,7 @@ func RemoteInstallCommand(ctx context.Context, pk *scpacket.FeCommandPacketType)
|
||||
}
|
||||
mshell := ids.Remote.MShell
|
||||
go mshell.RunInstall()
|
||||
return &sstore.ModelUpdate{
|
||||
RemoteView: &sstore.RemoteViewType{
|
||||
PtyRemoteId: ids.Remote.RemotePtr.RemoteId,
|
||||
},
|
||||
}, nil
|
||||
return createRemoteViewRemoteIdUpdate(ids.Remote.RemotePtr.RemoteId), nil
|
||||
}
|
||||
|
||||
func RemoteInstallCancelCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||
@ -1676,11 +1696,7 @@ func RemoteInstallCancelCommand(ctx context.Context, pk *scpacket.FeCommandPacke
|
||||
}
|
||||
mshell := ids.Remote.MShell
|
||||
go mshell.CancelInstall()
|
||||
return &sstore.ModelUpdate{
|
||||
RemoteView: &sstore.RemoteViewType{
|
||||
PtyRemoteId: ids.Remote.RemotePtr.RemoteId,
|
||||
},
|
||||
}, nil
|
||||
return createRemoteViewRemoteIdUpdate(ids.Remote.RemotePtr.RemoteId), nil
|
||||
}
|
||||
|
||||
func RemoteConnectCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||
@ -1689,11 +1705,7 @@ func RemoteConnectCommand(ctx context.Context, pk *scpacket.FeCommandPacketType)
|
||||
return nil, err
|
||||
}
|
||||
go ids.Remote.MShell.Launch(true)
|
||||
return &sstore.ModelUpdate{
|
||||
RemoteView: &sstore.RemoteViewType{
|
||||
PtyRemoteId: ids.Remote.RemotePtr.RemoteId,
|
||||
},
|
||||
}, nil
|
||||
return createRemoteViewRemoteIdUpdate(ids.Remote.RemotePtr.RemoteId), nil
|
||||
}
|
||||
|
||||
func RemoteDisconnectCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||
@ -1703,11 +1715,7 @@ func RemoteDisconnectCommand(ctx context.Context, pk *scpacket.FeCommandPacketTy
|
||||
}
|
||||
force := resolveBool(pk.Kwargs["force"], false)
|
||||
go ids.Remote.MShell.Disconnect(force)
|
||||
return &sstore.ModelUpdate{
|
||||
RemoteView: &sstore.RemoteViewType{
|
||||
PtyRemoteId: ids.Remote.RemotePtr.RemoteId,
|
||||
},
|
||||
}, nil
|
||||
return createRemoteViewRemoteIdUpdate(ids.Remote.RemotePtr.RemoteId), nil
|
||||
}
|
||||
|
||||
func makeRemoteEditUpdate_new(err error) sstore.UpdatePacket {
|
||||
@ -1717,12 +1725,7 @@ func makeRemoteEditUpdate_new(err error) sstore.UpdatePacket {
|
||||
if err != nil {
|
||||
redit.ErrorStr = err.Error()
|
||||
}
|
||||
update := &sstore.ModelUpdate{
|
||||
RemoteView: &sstore.RemoteViewType{
|
||||
RemoteEdit: redit,
|
||||
},
|
||||
}
|
||||
return update
|
||||
return createRemoteViewRemoteEditUpdate(redit)
|
||||
}
|
||||
|
||||
func makeRemoteEditErrorReturn_new(visual bool, err error) (sstore.UpdatePacket, error) {
|
||||
@ -1744,12 +1747,7 @@ func makeRemoteEditUpdate_edit(ids resolvedIds, err error) sstore.UpdatePacket {
|
||||
if err != nil {
|
||||
redit.ErrorStr = err.Error()
|
||||
}
|
||||
update := &sstore.ModelUpdate{
|
||||
RemoteView: &sstore.RemoteViewType{
|
||||
RemoteEdit: redit,
|
||||
},
|
||||
}
|
||||
return update
|
||||
return createRemoteViewRemoteEditUpdate(redit)
|
||||
}
|
||||
|
||||
func makeRemoteEditErrorReturn_edit(ids resolvedIds, visual bool, err error) (sstore.UpdatePacket, error) {
|
||||
@ -1961,11 +1959,7 @@ func RemoteNewCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ss
|
||||
return nil, fmt.Errorf("cannot create remote %q: %v", r.RemoteCanonicalName, err)
|
||||
}
|
||||
// SUCCESS
|
||||
return &sstore.ModelUpdate{
|
||||
RemoteView: &sstore.RemoteViewType{
|
||||
PtyRemoteId: r.RemoteId,
|
||||
},
|
||||
}, nil
|
||||
return createRemoteViewRemoteIdUpdate(r.RemoteId), nil
|
||||
}
|
||||
|
||||
func RemoteSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||
@ -1990,18 +1984,13 @@ func RemoteSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ss
|
||||
return makeRemoteEditErrorReturn_edit(ids, visualEdit, fmt.Errorf("/remote:new error updating remote: %v", err))
|
||||
}
|
||||
if visualEdit {
|
||||
return &sstore.ModelUpdate{
|
||||
RemoteView: &sstore.RemoteViewType{
|
||||
PtyRemoteId: ids.Remote.RemoteCopy.RemoteId,
|
||||
},
|
||||
}, nil
|
||||
return createRemoteViewRemoteIdUpdate(ids.Remote.RemoteCopy.RemoteId), nil
|
||||
}
|
||||
update := &sstore.ModelUpdate{
|
||||
Info: &sstore.InfoMsgType{
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, sstore.InfoMsgType{
|
||||
InfoMsg: fmt.Sprintf("remote %q updated", ids.Remote.DisplayName),
|
||||
TimeoutMs: 2000,
|
||||
},
|
||||
}
|
||||
})
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -2011,11 +2000,7 @@ func RemoteShowCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (s
|
||||
return nil, err
|
||||
}
|
||||
state := ids.Remote.RState
|
||||
return &sstore.ModelUpdate{
|
||||
RemoteView: &sstore.RemoteViewType{
|
||||
PtyRemoteId: state.RemoteId,
|
||||
},
|
||||
}, nil
|
||||
return createRemoteViewRemoteIdUpdate(state.RemoteId), nil
|
||||
}
|
||||
|
||||
func RemoteShowAllCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||
@ -2030,11 +2015,11 @@ func RemoteShowAllCommand(ctx context.Context, pk *scpacket.FeCommandPacketType)
|
||||
}
|
||||
buf.WriteString(fmt.Sprintf("%-12s %-5s %8s %s\n", rstate.Status, rstate.RemoteType, rstate.RemoteId[0:8], name))
|
||||
}
|
||||
return &sstore.ModelUpdate{
|
||||
RemoteView: &sstore.RemoteViewType{
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, sstore.RemoteViewType{
|
||||
RemoteShowAll: true,
|
||||
},
|
||||
}, nil
|
||||
})
|
||||
return update, nil
|
||||
}
|
||||
|
||||
func resolveSshConfigPatterns(configFiles []string) ([]string, error) {
|
||||
@ -2330,16 +2315,17 @@ func RemoteConfigParseCommand(ctx context.Context, pk *scpacket.FeCommandPacketT
|
||||
visualEdit := resolveBool(pk.Kwargs["visual"], false)
|
||||
if visualEdit {
|
||||
update := &sstore.ModelUpdate{}
|
||||
update.AlertMessage = &sstore.AlertMessageType{
|
||||
sstore.AddUpdate(update, sstore.AlertMessageType{
|
||||
Title: "SSH Config Import",
|
||||
Message: outMsg,
|
||||
Markdown: true,
|
||||
}
|
||||
})
|
||||
return update, nil
|
||||
} else {
|
||||
update := &sstore.ModelUpdate{}
|
||||
update.Info = &sstore.InfoMsgType{}
|
||||
update.Info.InfoMsg = outMsg
|
||||
sstore.AddUpdate(update, sstore.InfoMsgType{
|
||||
InfoMsg: outMsg,
|
||||
})
|
||||
return update, nil
|
||||
}
|
||||
}
|
||||
@ -2363,12 +2349,12 @@ func ScreenShowAllCommand(ctx context.Context, pk *scpacket.FeCommandPacketType)
|
||||
outStr := fmt.Sprintf("%-30s %s %s\n", screen.Name+archivedStr, screen.ScreenId, screenIdxStr)
|
||||
buf.WriteString(outStr)
|
||||
}
|
||||
return &sstore.ModelUpdate{
|
||||
Info: &sstore.InfoMsgType{
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, sstore.InfoMsgType{
|
||||
InfoTitle: fmt.Sprintf("all screens for session"),
|
||||
InfoLines: splitLinesForInfo(buf.String()),
|
||||
},
|
||||
}, nil
|
||||
})
|
||||
return update, nil
|
||||
}
|
||||
|
||||
func ScreenResetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||
@ -2402,8 +2388,8 @@ func ScreenResetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (
|
||||
// TODO tricky error since the command was a success, but we can't show the output
|
||||
return nil, err
|
||||
}
|
||||
update.Interactive = pk.Interactive
|
||||
update.Sessions = []*sstore.SessionType{sessionUpdate}
|
||||
sstore.AddInteractiveUpdate(update, pk.Interactive)
|
||||
sstore.AddUpdate(update, sessionUpdate)
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -2427,7 +2413,7 @@ func RemoteArchiveCommand(ctx context.Context, pk *scpacket.FeCommandPacketType)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot get updated screen: %w", err)
|
||||
}
|
||||
update.Screens = []*sstore.ScreenType{screen}
|
||||
sstore.AddUpdate(update, *screen)
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -2476,11 +2462,10 @@ func crShowCommand(ctx context.Context, pk *scpacket.FeCommandPacketType, ids re
|
||||
}
|
||||
buf.WriteString(fmt.Sprintf("%-30s %-50s (default)\n", msh.GetDisplayName(), cwdStr))
|
||||
}
|
||||
update := &sstore.ModelUpdate{
|
||||
Info: &sstore.InfoMsgType{
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, sstore.InfoMsgType{
|
||||
InfoLines: splitLinesForInfo(buf.String()),
|
||||
},
|
||||
}
|
||||
})
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -2834,7 +2819,7 @@ func OpenAICommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstor
|
||||
if resolveBool(pk.Kwargs["cmdinfo"], false) {
|
||||
if promptStr == "" {
|
||||
// this is requesting an update without wanting an openai query
|
||||
update, err := sstore.UpdateWithCurrentOpenAICmdInfoChat(cmd.ScreenId)
|
||||
update, err := sstore.UpdateWithCurrentOpenAICmdInfoChat(cmd.ScreenId, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error getting update for CmdInfoChat %v", err)
|
||||
}
|
||||
@ -2879,7 +2864,9 @@ func OpenAICommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstor
|
||||
// ignore error again (nothing to do)
|
||||
log.Printf("openai error updating screen selected line: %v\n", err)
|
||||
}
|
||||
update := &sstore.ModelUpdate{Line: line, Cmd: cmd, Screens: []*sstore.ScreenType{screen}}
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddLineUpdate(update, line, cmd)
|
||||
sstore.AddUpdate(update, *screen)
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -2912,10 +2899,9 @@ func CrCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.Up
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("/%s error: cannot resolve screen for update: %w", GetCmdStr(pk), err)
|
||||
}
|
||||
update := &sstore.ModelUpdate{
|
||||
Screens: []*sstore.ScreenType{screen},
|
||||
Interactive: pk.Interactive,
|
||||
}
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, *screen)
|
||||
sstore.AddInteractiveUpdate(update, pk.Interactive)
|
||||
return update, nil
|
||||
}
|
||||
outputStr := fmt.Sprintf("connected to %s", GetFullRemoteDisplayName(rptr, rstate))
|
||||
@ -2929,7 +2915,7 @@ func CrCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.Up
|
||||
// TODO tricky error since the command was a success, but we can't show the output
|
||||
return nil, err
|
||||
}
|
||||
update.Interactive = pk.Interactive
|
||||
sstore.AddInteractiveUpdate(update, pk.Interactive)
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -3011,11 +2997,9 @@ func addLineForCmd(ctx context.Context, metaCmd string, shouldFocus bool, ids re
|
||||
log.Printf("%s error updating screen selected line: %v\n", metaCmd, err)
|
||||
}
|
||||
}
|
||||
update := &sstore.ModelUpdate{
|
||||
Line: rtnLine,
|
||||
Cmd: cmd,
|
||||
Screens: []*sstore.ScreenType{screen},
|
||||
}
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddLineUpdate(update, rtnLine, cmd)
|
||||
sstore.AddUpdate(update, *screen)
|
||||
sstore.IncrementNumRunningCmds_Update(update, cmd.ScreenId, 1)
|
||||
updateHistoryContext(ctx, rtnLine, cmd, cmd.FeState)
|
||||
return update, nil
|
||||
@ -3057,13 +3041,12 @@ func makeInfoFromComps(compType string, comps []string, hasMore bool) sstore.Upd
|
||||
if len(comps) == 0 {
|
||||
comps = []string{"(no completions)"}
|
||||
}
|
||||
update := &sstore.ModelUpdate{
|
||||
Info: &sstore.InfoMsgType{
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, sstore.InfoMsgType{
|
||||
InfoTitle: fmt.Sprintf("%s completions", compType),
|
||||
InfoComps: comps,
|
||||
InfoCompsMore: hasMore,
|
||||
},
|
||||
}
|
||||
})
|
||||
return update
|
||||
}
|
||||
|
||||
@ -3199,9 +3182,8 @@ func CompGenCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ssto
|
||||
if newSP == nil || cmdSP == *newSP {
|
||||
return nil, nil
|
||||
}
|
||||
update := &sstore.ModelUpdate{
|
||||
CmdLine: &utilfn.StrWithPos{Str: newSP.Str, Pos: newSP.Pos},
|
||||
}
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddCmdLineUpdate(update, utilfn.StrWithPos{Str: newSP.Str, Pos: newSP.Pos})
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -3227,7 +3209,9 @@ func CommentCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ssto
|
||||
// ignore error again (nothing to do)
|
||||
log.Printf("/comment error updating screen selected line: %v\n", err)
|
||||
}
|
||||
update := &sstore.ModelUpdate{Line: rtnLine, Screens: []*sstore.ScreenType{screen}}
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddLineUpdate(update, rtnLine, nil)
|
||||
sstore.AddUpdate(update, *screen)
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -3410,9 +3394,9 @@ func SessionArchiveCommand(ctx context.Context, pk *scpacket.FeCommandPacketType
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot archive session: %v", err)
|
||||
}
|
||||
update.Info = &sstore.InfoMsgType{
|
||||
sstore.AddUpdate(update, sstore.InfoMsgType{
|
||||
InfoMsg: "session archived",
|
||||
}
|
||||
})
|
||||
return update, nil
|
||||
} else {
|
||||
activate := resolveBool(pk.Kwargs["activate"], false)
|
||||
@ -3420,9 +3404,9 @@ func SessionArchiveCommand(ctx context.Context, pk *scpacket.FeCommandPacketType
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot un-archive session: %v", err)
|
||||
}
|
||||
update.Info = &sstore.InfoMsgType{
|
||||
sstore.AddUpdate(update, sstore.InfoMsgType{
|
||||
InfoMsg: "session un-archived",
|
||||
}
|
||||
})
|
||||
return update, nil
|
||||
}
|
||||
}
|
||||
@ -3463,12 +3447,12 @@ func SessionShowCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %d\n", "cmds", stats.NumCmds))
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %0.2fM\n", "disksize", float64(stats.DiskStats.TotalSize)/1000000))
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %s\n", "disk-location", stats.DiskStats.Location))
|
||||
return &sstore.ModelUpdate{
|
||||
Info: &sstore.InfoMsgType{
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, sstore.InfoMsgType{
|
||||
InfoTitle: "session info",
|
||||
InfoLines: splitLinesForInfo(buf.String()),
|
||||
},
|
||||
}, nil
|
||||
})
|
||||
return update, nil
|
||||
}
|
||||
|
||||
func SessionShowAllCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||
@ -3489,12 +3473,12 @@ func SessionShowAllCommand(ctx context.Context, pk *scpacket.FeCommandPacketType
|
||||
outStr := fmt.Sprintf("%-30s %s %s\n", session.Name+archivedStr, session.SessionId, sessionIdxStr)
|
||||
buf.WriteString(outStr)
|
||||
}
|
||||
return &sstore.ModelUpdate{
|
||||
Info: &sstore.InfoMsgType{
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, sstore.InfoMsgType{
|
||||
InfoTitle: "all sessions",
|
||||
InfoLines: splitLinesForInfo(buf.String()),
|
||||
},
|
||||
}, nil
|
||||
})
|
||||
return update, nil
|
||||
}
|
||||
|
||||
func SessionSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||
@ -3514,21 +3498,17 @@ func SessionSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (s
|
||||
return nil, fmt.Errorf("setting session name: %v", err)
|
||||
}
|
||||
varsUpdated = append(varsUpdated, "name")
|
||||
}
|
||||
if pk.Kwargs["pos"] != "" {
|
||||
|
||||
}
|
||||
if len(varsUpdated) == 0 {
|
||||
return nil, fmt.Errorf("/session:set no updates, can set %s", formatStrs([]string{"name", "pos"}, "or", false))
|
||||
}
|
||||
bareSession, err := sstore.GetBareSessionById(ctx, ids.SessionId)
|
||||
update := &sstore.ModelUpdate{
|
||||
Sessions: []*sstore.SessionType{bareSession},
|
||||
Info: &sstore.InfoMsgType{
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, *bareSession)
|
||||
sstore.AddUpdate(update, sstore.InfoMsgType{
|
||||
InfoMsg: fmt.Sprintf("session updated %s", formatStrs(varsUpdated, "and", false)),
|
||||
TimeoutMs: 2000,
|
||||
},
|
||||
}
|
||||
})
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -3549,14 +3529,12 @@ func SessionCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ssto
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
update := &sstore.ModelUpdate{
|
||||
ActiveSessionId: ritem.Id,
|
||||
Info: &sstore.InfoMsgType{
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, (sstore.ActiveSessionIdUpdate)(ritem.Id))
|
||||
sstore.AddUpdate(update, sstore.InfoMsgType{
|
||||
InfoMsg: fmt.Sprintf("switched to session %q", ritem.Name),
|
||||
TimeoutMs: 2000,
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
// Reset the status indicator for the new active screen
|
||||
session, err := sstore.GetSessionById(ctx, ritem.Id)
|
||||
@ -3611,8 +3589,8 @@ func RemoteResetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (
|
||||
// TODO tricky error since the command was a success, but we can't show the output
|
||||
return nil, err
|
||||
}
|
||||
update.Interactive = pk.Interactive
|
||||
update.Sessions = sstore.MakeSessionsUpdateForRemote(ids.SessionId, remoteInst)
|
||||
sstore.AddInteractiveUpdate(update, pk.Interactive)
|
||||
sstore.AddUpdate(update, sstore.MakeSessionUpdateForRemote(ids.SessionId, remoteInst))
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -3626,20 +3604,20 @@ func ClearCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("clearing screen (archiving): %v", err)
|
||||
}
|
||||
update.Info = &sstore.InfoMsgType{
|
||||
sstore.AddUpdate(update, sstore.InfoMsgType{
|
||||
InfoMsg: fmt.Sprintf("screen cleared (all lines archived)"),
|
||||
TimeoutMs: 2000,
|
||||
}
|
||||
})
|
||||
return update, nil
|
||||
} else {
|
||||
update, err := sstore.DeleteScreenLines(ctx, ids.ScreenId)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("clearing screen: %v", err)
|
||||
}
|
||||
update.Info = &sstore.InfoMsgType{
|
||||
sstore.AddUpdate(update, sstore.InfoMsgType{
|
||||
InfoMsg: fmt.Sprintf("screen cleared"),
|
||||
TimeoutMs: 2000,
|
||||
}
|
||||
})
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -3751,10 +3729,8 @@ func HistoryViewAllCommand(ctx context.Context, pk *scpacket.FeCommandPacketType
|
||||
}
|
||||
hvdata.Lines = lines
|
||||
hvdata.Cmds = cmds
|
||||
update := &sstore.ModelUpdate{
|
||||
HistoryViewData: hvdata,
|
||||
MainView: sstore.MainViewHistory,
|
||||
}
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, &sstore.MainViewUpdate{MainView: sstore.MainViewHistory, HistoryView: hvdata})
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -3800,13 +3776,13 @@ func HistoryCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ssto
|
||||
sstore.UpdateActivityWrap(ctx, sstore.ActivityUpdate{HistoryView: 1}, "history")
|
||||
}
|
||||
update := &sstore.ModelUpdate{}
|
||||
update.History = &sstore.HistoryInfoType{
|
||||
sstore.AddUpdate(update, sstore.HistoryInfoType{
|
||||
HistoryType: htype,
|
||||
SessionId: ids.SessionId,
|
||||
ScreenId: ids.ScreenId,
|
||||
Items: hresult.Items,
|
||||
Show: show,
|
||||
}
|
||||
})
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -3993,18 +3969,16 @@ func LineRestartCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (
|
||||
return nil, fmt.Errorf("error getting updated line/cmd: %w", err)
|
||||
}
|
||||
cmd.Restarted = true
|
||||
update := &sstore.ModelUpdate{
|
||||
Line: line,
|
||||
Cmd: cmd,
|
||||
Interactive: pk.Interactive,
|
||||
}
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddLineUpdate(update, line, cmd)
|
||||
sstore.AddInteractiveUpdate(update, pk.Interactive)
|
||||
screen, focusErr := focusScreenLine(ctx, ids.ScreenId, line.LineNum)
|
||||
if focusErr != nil {
|
||||
// not a fatal error, so just log
|
||||
log.Printf("error focusing screen line: %v\n", focusErr)
|
||||
}
|
||||
if screen != nil {
|
||||
update.Screens = []*sstore.ScreenType{screen}
|
||||
sstore.AddUpdate(update, *screen)
|
||||
}
|
||||
return update, nil
|
||||
}
|
||||
@ -4083,13 +4057,12 @@ func LineSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ssto
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("/line:set cannot retrieve updated line: %v", err)
|
||||
}
|
||||
update := &sstore.ModelUpdate{
|
||||
Line: updatedLine,
|
||||
Info: &sstore.InfoMsgType{
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddLineUpdate(update, updatedLine, nil)
|
||||
sstore.AddUpdate(update, sstore.InfoMsgType{
|
||||
InfoMsg: fmt.Sprintf("line updated %s", formatStrs(varsUpdated, "and", false)),
|
||||
TimeoutMs: 2000,
|
||||
},
|
||||
}
|
||||
})
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -4135,7 +4108,7 @@ func LineViewCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sst
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
update.Screens = []*sstore.ScreenType{screen}
|
||||
sstore.AddUpdate(update, *screen)
|
||||
}
|
||||
return update, nil
|
||||
}
|
||||
@ -4151,10 +4124,12 @@ func BookmarksShowCommand(ctx context.Context, pk *scpacket.FeCommandPacketType)
|
||||
return nil, fmt.Errorf("cannot retrieve bookmarks: %v", err)
|
||||
}
|
||||
sstore.UpdateActivityWrap(ctx, sstore.ActivityUpdate{BookmarksView: 1}, "bookmarks")
|
||||
update := &sstore.ModelUpdate{
|
||||
update := &sstore.ModelUpdate{}
|
||||
|
||||
sstore.AddUpdate(update, &sstore.MainViewUpdate{
|
||||
MainView: sstore.MainViewBookmarks,
|
||||
Bookmarks: bms,
|
||||
}
|
||||
BookmarksView: &sstore.BookmarksUpdate{Bookmarks: bms},
|
||||
})
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -4188,12 +4163,11 @@ func BookmarkSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error retrieving edited bookmark: %v", err)
|
||||
}
|
||||
return &sstore.ModelUpdate{
|
||||
Info: &sstore.InfoMsgType{
|
||||
InfoMsg: "bookmark edited",
|
||||
},
|
||||
Bookmarks: []*sstore.BookmarkType{bm},
|
||||
}, nil
|
||||
bms := []*sstore.BookmarkType{bm}
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddBookmarksUpdate(update, bms, nil)
|
||||
sstore.AddUpdate(update, sstore.InfoMsgUpdate("bookmark edited"))
|
||||
return update, nil
|
||||
}
|
||||
|
||||
func BookmarkDeleteCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||
@ -4212,13 +4186,11 @@ func BookmarkDeleteCommand(ctx context.Context, pk *scpacket.FeCommandPacketType
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error deleting bookmark: %v", err)
|
||||
}
|
||||
bm := &sstore.BookmarkType{BookmarkId: bookmarkId, Remove: true}
|
||||
return &sstore.ModelUpdate{
|
||||
Info: &sstore.InfoMsgType{
|
||||
InfoMsg: "bookmark deleted",
|
||||
},
|
||||
Bookmarks: []*sstore.BookmarkType{bm},
|
||||
}, nil
|
||||
update := &sstore.ModelUpdate{}
|
||||
bms := []*sstore.BookmarkType{{BookmarkId: bookmarkId, Remove: true}}
|
||||
sstore.AddBookmarksUpdate(update, bms, nil)
|
||||
sstore.AddUpdate(update, sstore.InfoMsgUpdate("bookmark deleted"))
|
||||
return update, nil
|
||||
}
|
||||
|
||||
func LineBookmarkCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||
@ -4267,11 +4239,11 @@ func LineBookmarkCommand(ctx context.Context, pk *scpacket.FeCommandPacketType)
|
||||
newBmId = newBm.BookmarkId
|
||||
}
|
||||
bms, err := sstore.GetBookmarks(ctx, "")
|
||||
update := &sstore.ModelUpdate{
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, &sstore.MainViewUpdate{
|
||||
MainView: sstore.MainViewBookmarks,
|
||||
Bookmarks: bms,
|
||||
SelectedBookmark: newBmId,
|
||||
}
|
||||
BookmarksView: &sstore.BookmarksUpdate{Bookmarks: bms, SelectedBookmark: newBmId},
|
||||
})
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -4317,7 +4289,9 @@ func LineStarCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sst
|
||||
// no line (which is strange given we checked for it above). just return a nop.
|
||||
return nil, nil
|
||||
}
|
||||
return &sstore.ModelUpdate{Line: lineObj}, nil
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddLineUpdate(update, lineObj, nil)
|
||||
return update, nil
|
||||
}
|
||||
|
||||
func LineArchiveCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||
@ -4352,7 +4326,9 @@ func LineArchiveCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (
|
||||
// no line (which is strange given we checked for it above). just return a nop.
|
||||
return nil, nil
|
||||
}
|
||||
return &sstore.ModelUpdate{Line: lineObj}, nil
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddLineUpdate(update, lineObj, nil)
|
||||
return update, nil
|
||||
}
|
||||
|
||||
func LineDeleteCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||
@ -4380,18 +4356,16 @@ func LineDeleteCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (s
|
||||
}
|
||||
update := &sstore.ModelUpdate{}
|
||||
for _, lineId := range lineIds {
|
||||
lineObj := &sstore.LineType{
|
||||
ScreenId: ids.ScreenId,
|
||||
LineId: lineId,
|
||||
Remove: true,
|
||||
}
|
||||
update.Lines = append(update.Lines, lineObj)
|
||||
line := &sstore.LineType{ScreenId: ids.ScreenId, LineId: lineId, Remove: true}
|
||||
sstore.AddLineUpdate(update, line, nil)
|
||||
}
|
||||
screen, err := sstore.FixupScreenSelectedLine(ctx, ids.ScreenId)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("/line:delete error fixing up screen: %v", err)
|
||||
}
|
||||
update.Screens = []*sstore.ScreenType{screen}
|
||||
if screen != nil {
|
||||
sstore.AddUpdate(update, *screen)
|
||||
}
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -4474,12 +4448,11 @@ func LineShowCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sst
|
||||
stateStr = stateStr[0:77] + "..."
|
||||
}
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %s\n", "state", stateStr))
|
||||
update := &sstore.ModelUpdate{
|
||||
Info: &sstore.InfoMsgType{
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, sstore.InfoMsgType{
|
||||
InfoTitle: fmt.Sprintf("line %d info", line.LineNum),
|
||||
InfoLines: splitLinesForInfo(buf.String()),
|
||||
},
|
||||
}
|
||||
})
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -4569,12 +4542,11 @@ func ViewStatCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sst
|
||||
modeStr = modeStr[len(modeStr)-9:]
|
||||
}
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %s\n", "perms", modeStr))
|
||||
update := &sstore.ModelUpdate{
|
||||
Info: &sstore.InfoMsgType{
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, sstore.InfoMsgType{
|
||||
InfoTitle: fmt.Sprintf("view stat %q", streamPk.Path),
|
||||
InfoLines: splitLinesForInfo(buf.String()),
|
||||
},
|
||||
}
|
||||
})
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -4631,12 +4603,11 @@ func ViewTestCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sst
|
||||
buf.Write(dataPk.Data)
|
||||
}
|
||||
buf.WriteString(fmt.Sprintf("\n\ntotal packets: %d\n", numPackets))
|
||||
update := &sstore.ModelUpdate{
|
||||
Info: &sstore.InfoMsgType{
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, sstore.InfoMsgType{
|
||||
InfoTitle: fmt.Sprintf("view file %q", streamPk.Path),
|
||||
InfoLines: splitLinesForInfo(buf.String()),
|
||||
},
|
||||
}
|
||||
})
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -4679,7 +4650,7 @@ func CodeEditCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sst
|
||||
// TODO tricky error since the command was a success, but we can't show the output
|
||||
return nil, err
|
||||
}
|
||||
update.Interactive = pk.Interactive
|
||||
sstore.AddInteractiveUpdate(update, pk.Interactive)
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -4710,7 +4681,7 @@ func CSVViewCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ssto
|
||||
// TODO tricky error since the command was a success, but we can't show the output
|
||||
return nil, err
|
||||
}
|
||||
update.Interactive = pk.Interactive
|
||||
sstore.AddInteractiveUpdate(update, pk.Interactive)
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -4741,7 +4712,7 @@ func ImageViewCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ss
|
||||
// TODO tricky error since the command was a success, but we can't show the output
|
||||
return nil, err
|
||||
}
|
||||
update.Interactive = pk.Interactive
|
||||
sstore.AddInteractiveUpdate(update, pk.Interactive)
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -4772,7 +4743,7 @@ func MarkdownViewCommand(ctx context.Context, pk *scpacket.FeCommandPacketType)
|
||||
// TODO tricky error since the command was a success, but we can't show the output
|
||||
return nil, err
|
||||
}
|
||||
update.Interactive = pk.Interactive
|
||||
sstore.AddInteractiveUpdate(update, pk.Interactive)
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -4836,11 +4807,10 @@ func EditTestCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sst
|
||||
if donePk.Error != "" {
|
||||
return nil, fmt.Errorf("/edit:test %s", donePk.Error)
|
||||
}
|
||||
update := &sstore.ModelUpdate{
|
||||
Info: &sstore.InfoMsgType{
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, sstore.InfoMsgType{
|
||||
InfoTitle: fmt.Sprintf("edit test, wrote %q", writePk.Path),
|
||||
},
|
||||
}
|
||||
})
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -4903,11 +4873,8 @@ func SignalCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstor
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot send signal: %v", err)
|
||||
}
|
||||
update := &sstore.ModelUpdate{
|
||||
Info: &sstore.InfoMsgType{
|
||||
InfoMsg: fmt.Sprintf("sent line %s signal %s", lineArg, sigArg),
|
||||
},
|
||||
}
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, sstore.InfoMsgUpdate("sent line %s signal %s", lineArg, sigArg))
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -4941,11 +4908,8 @@ func ClientCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstor
|
||||
func ClientNotifyUpdateWriterCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||
pcloud.ResetUpdateWriterNumFailures()
|
||||
sstore.NotifyUpdateWriter()
|
||||
update := &sstore.ModelUpdate{
|
||||
Info: &sstore.InfoMsgType{
|
||||
InfoMsg: fmt.Sprintf("notified update writer"),
|
||||
},
|
||||
}
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, sstore.InfoMsgUpdate("notified update writer"))
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -4971,9 +4935,8 @@ func ClientAcceptTosCommand(ctx context.Context, pk *scpacket.FeCommandPacketTyp
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot retrieve updated client data: %v", err)
|
||||
}
|
||||
update := &sstore.ModelUpdate{
|
||||
ClientData: clientData,
|
||||
}
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, *clientData)
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -5021,9 +4984,8 @@ func ClientConfirmFlagCommand(ctx context.Context, pk *scpacket.FeCommandPacketT
|
||||
return nil, fmt.Errorf("cannot retrieve updated client data: %v", err)
|
||||
}
|
||||
|
||||
update := &sstore.ModelUpdate{
|
||||
ClientData: clientData,
|
||||
}
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, *clientData)
|
||||
|
||||
return update, nil
|
||||
}
|
||||
@ -5077,9 +5039,8 @@ func ClientSetSidebarCommand(ctx context.Context, pk *scpacket.FeCommandPacketTy
|
||||
return nil, fmt.Errorf("cannot retrieve updated client data: %v", err)
|
||||
}
|
||||
|
||||
update := &sstore.ModelUpdate{
|
||||
ClientData: clientData,
|
||||
}
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, *clientData)
|
||||
|
||||
return update, nil
|
||||
}
|
||||
@ -5227,13 +5188,12 @@ func ClientSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ss
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot retrieve updated client data: %v", err)
|
||||
}
|
||||
update := &sstore.ModelUpdate{
|
||||
Info: &sstore.InfoMsgType{
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, *clientData)
|
||||
sstore.AddUpdate(update, sstore.InfoMsgType{
|
||||
InfoMsg: fmt.Sprintf("client updated %s", formatStrs(varsUpdated, "and", false)),
|
||||
TimeoutMs: 2000,
|
||||
},
|
||||
ClientData: clientData,
|
||||
}
|
||||
})
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -5259,12 +5219,12 @@ func ClientShowCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (s
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %s\n", "client-version", clientVersion))
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %s %s\n", "server-version", scbase.WaveVersion, scbase.BuildTime))
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %s (%s)\n", "arch", scbase.ClientArch(), scbase.UnameKernelRelease()))
|
||||
update := &sstore.ModelUpdate{
|
||||
Info: &sstore.InfoMsgType{
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, sstore.InfoMsgType{
|
||||
InfoTitle: fmt.Sprintf("client info"),
|
||||
InfoLines: splitLinesForInfo(buf.String()),
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -5318,7 +5278,7 @@ func TelemetryOnCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (
|
||||
return nil, fmt.Errorf("cannot retrieve updated client data: %v", err)
|
||||
}
|
||||
update := sstore.InfoMsgUpdate("telemetry is now on")
|
||||
update.ClientData = clientData
|
||||
sstore.AddUpdate(update, *clientData)
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -5339,7 +5299,7 @@ func TelemetryOffCommand(ctx context.Context, pk *scpacket.FeCommandPacketType)
|
||||
return nil, fmt.Errorf("cannot retrieve updated client data: %v", err)
|
||||
}
|
||||
update := sstore.InfoMsgUpdate("telemetry is now off")
|
||||
update.ClientData = clientData
|
||||
sstore.AddUpdate(update, *clientData)
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -5350,12 +5310,11 @@ func TelemetryShowCommand(ctx context.Context, pk *scpacket.FeCommandPacketType)
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %s\n", "telemetry", boolToStr(clientData.ClientOpts.NoTelemetry, "off", "on")))
|
||||
update := &sstore.ModelUpdate{
|
||||
Info: &sstore.InfoMsgType{
|
||||
update := &sstore.ModelUpdate{}
|
||||
sstore.AddUpdate(update, sstore.InfoMsgType{
|
||||
InfoTitle: fmt.Sprintf("telemetry info"),
|
||||
InfoLines: splitLinesForInfo(buf.String()),
|
||||
},
|
||||
}
|
||||
})
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -5427,7 +5386,7 @@ func ReleaseCheckOnCommand(ctx context.Context, pk *scpacket.FeCommandPacketType
|
||||
return nil, fmt.Errorf("cannot retrieve updated client data: %v", err)
|
||||
}
|
||||
update := sstore.InfoMsgUpdate("automatic release checking is now on")
|
||||
update.ClientData = clientData
|
||||
sstore.AddUpdate(update, *clientData)
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -5448,7 +5407,7 @@ func ReleaseCheckOffCommand(ctx context.Context, pk *scpacket.FeCommandPacketTyp
|
||||
return nil, fmt.Errorf("cannot retrieve updated client data: %v", err)
|
||||
}
|
||||
update := sstore.InfoMsgUpdate("automatic release checking is now off")
|
||||
update.ClientData = clientData
|
||||
sstore.AddUpdate(update, *clientData)
|
||||
return update, nil
|
||||
}
|
||||
|
||||
@ -5471,7 +5430,7 @@ func ReleaseCheckCommand(ctx context.Context, pk *scpacket.FeCommandPacketType)
|
||||
}
|
||||
|
||||
update := sstore.InfoMsgUpdate(rsp)
|
||||
update.ClientData = clientData
|
||||
sstore.AddUpdate(update, *clientData)
|
||||
return update, nil
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
sessionMap := make(map[string]*SessionType)
|
||||
for _, session := range update.Sessions {
|
||||
sessionMap[session.SessionId] = session
|
||||
session.Full = true
|
||||
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
|
||||
})
|
||||
}
|
||||
query = `SELECT * FROM screen ORDER BY archived, screenidx, archivedts`
|
||||
update.Screens = dbutil.SelectMapsGen[*ScreenType](tx, query)
|
||||
for _, screen := range update.Screens {
|
||||
screen.Full = true
|
||||
|
||||
// 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 sessions {
|
||||
sessionMap[session.SessionId] = session
|
||||
update.Sessions = append(update.Sessions, session)
|
||||
}
|
||||
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"`
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -5,14 +5,13 @@ package sstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/wavetermdev/waveterm/waveshell/pkg/packet"
|
||||
"github.com/wavetermdev/waveterm/waveshell/pkg/utilfn"
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/scpacket"
|
||||
)
|
||||
|
||||
@ -23,6 +22,7 @@ const ModelUpdateStr = "model"
|
||||
const UpdateChSize = 100
|
||||
|
||||
type UpdatePacket interface {
|
||||
// The key to use when marshalling to JSON and interpreting in the client
|
||||
UpdateType() string
|
||||
Clean()
|
||||
}
|
||||
@ -42,136 +42,61 @@ func (*PtyDataUpdate) UpdateType() string {
|
||||
|
||||
func (pdu *PtyDataUpdate) Clean() {}
|
||||
|
||||
type ModelUpdate struct {
|
||||
Sessions []*SessionType `json:"sessions,omitempty"`
|
||||
ActiveSessionId string `json:"activesessionid,omitempty"`
|
||||
Screens []*ScreenType `json:"screens,omitempty"`
|
||||
ScreenLines *ScreenLinesType `json:"screenlines,omitempty"`
|
||||
Line *LineType `json:"line,omitempty"`
|
||||
Lines []*LineType `json:"lines,omitempty"`
|
||||
Cmd *CmdType `json:"cmd,omitempty"`
|
||||
CmdLine *utilfn.StrWithPos `json:"cmdline,omitempty"`
|
||||
Info *InfoMsgType `json:"info,omitempty"`
|
||||
ClearInfo bool `json:"clearinfo,omitempty"`
|
||||
Remotes []RemoteRuntimeState `json:"remotes,omitempty"`
|
||||
History *HistoryInfoType `json:"history,omitempty"`
|
||||
Interactive bool `json:"interactive"`
|
||||
Connect bool `json:"connect,omitempty"`
|
||||
MainView string `json:"mainview,omitempty"`
|
||||
Bookmarks []*BookmarkType `json:"bookmarks,omitempty"`
|
||||
SelectedBookmark string `json:"selectedbookmark,omitempty"`
|
||||
HistoryViewData *HistoryViewData `json:"historyviewdata,omitempty"`
|
||||
ClientData *ClientData `json:"clientdata,omitempty"`
|
||||
RemoteView *RemoteViewType `json:"remoteview,omitempty"`
|
||||
ScreenTombstones []*ScreenTombstoneType `json:"screentombstones,omitempty"`
|
||||
SessionTombstones []*SessionTombstoneType `json:"sessiontombstones,omitempty"`
|
||||
OpenAICmdInfoChat []*packet.OpenAICmdInfoChatMessage `json:"openaicmdinfochat,omitempty"`
|
||||
AlertMessage *AlertMessageType `json:"alertmessage,omitempty"`
|
||||
ScreenStatusIndicators []*ScreenStatusIndicatorType `json:"screenstatusindicators,omitempty"`
|
||||
ScreenNumRunningCommands []*ScreenNumRunningCommandsType `json:"screennumrunningcommands,omitempty"`
|
||||
UserInputRequest *UserInputRequestType `json:"userinputrequest,omitempty"`
|
||||
}
|
||||
// A collection of independent model updates to be sent to the client. Will be evaluated in order on the client.
|
||||
type ModelUpdate []*ModelUpdateItem
|
||||
|
||||
func (*ModelUpdate) UpdateType() string {
|
||||
return ModelUpdateStr
|
||||
}
|
||||
|
||||
func (mu *ModelUpdate) MarshalJSON() ([]byte, error) {
|
||||
rtn := make([]map[string]any, 0)
|
||||
for _, u := range *mu {
|
||||
m := make(map[string]any)
|
||||
m[(*u).UpdateType()] = u
|
||||
rtn = append(rtn, m)
|
||||
}
|
||||
return json.Marshal(rtn)
|
||||
}
|
||||
|
||||
// An interface for all model updates
|
||||
type ModelUpdateItem interface {
|
||||
// The key to use when marshalling to JSON and interpreting in the client
|
||||
UpdateType() string
|
||||
}
|
||||
|
||||
// Clean the ClientData in an update, if present
|
||||
func (update *ModelUpdate) Clean() {
|
||||
if update == nil {
|
||||
return
|
||||
}
|
||||
update.ClientData = update.ClientData.Clean()
|
||||
}
|
||||
|
||||
func (update *ModelUpdate) UpdateScreen(newScreen *ScreenType) {
|
||||
if newScreen == nil {
|
||||
return
|
||||
}
|
||||
for idx, screen := range update.Screens {
|
||||
if screen.ScreenId == newScreen.ScreenId {
|
||||
update.Screens[idx] = newScreen
|
||||
return
|
||||
}
|
||||
}
|
||||
update.Screens = append(update.Screens, newScreen)
|
||||
}
|
||||
|
||||
// only sets InfoError if InfoError is not already set
|
||||
func (update *ModelUpdate) AddInfoError(errStr string) {
|
||||
if update.Info == nil {
|
||||
update.Info = &InfoMsgType{}
|
||||
}
|
||||
if update.Info.InfoError == "" {
|
||||
update.Info.InfoError = errStr
|
||||
clientDataUpdates := GetUpdateItems[ClientData](update)
|
||||
if len(clientDataUpdates) > 0 {
|
||||
lastUpdate := clientDataUpdates[len(clientDataUpdates)-1]
|
||||
lastUpdate.Clean()
|
||||
}
|
||||
}
|
||||
|
||||
type RemoteViewType struct {
|
||||
RemoteShowAll bool `json:"remoteshowall,omitempty"`
|
||||
PtyRemoteId string `json:"ptyremoteid,omitempty"`
|
||||
RemoteEdit *RemoteEditType `json:"remoteedit,omitempty"`
|
||||
func (update *ModelUpdate) append(item *ModelUpdateItem) {
|
||||
*update = append(*update, item)
|
||||
}
|
||||
|
||||
func InfoMsgUpdate(infoMsgFmt string, args ...interface{}) *ModelUpdate {
|
||||
msg := fmt.Sprintf(infoMsgFmt, args...)
|
||||
return &ModelUpdate{
|
||||
Info: &InfoMsgType{InfoMsg: msg},
|
||||
// Add a collection of model updates to the update
|
||||
func AddUpdate(update *ModelUpdate, item ...ModelUpdateItem) {
|
||||
for _, i := range item {
|
||||
update.append(&i)
|
||||
}
|
||||
}
|
||||
|
||||
type HistoryViewData struct {
|
||||
Items []*HistoryItemType `json:"items"`
|
||||
Offset int `json:"offset"`
|
||||
RawOffset int `json:"rawoffset"`
|
||||
NextRawOffset int `json:"nextrawoffset"`
|
||||
HasMore bool `json:"hasmore"`
|
||||
Lines []*LineType `json:"lines"`
|
||||
Cmds []*CmdType `json:"cmds"`
|
||||
// Returns the items in the update that are of type I
|
||||
func GetUpdateItems[I ModelUpdateItem](update *ModelUpdate) []*I {
|
||||
ret := make([]*I, 0)
|
||||
for _, item := range *update {
|
||||
if i, ok := (*item).(I); ok {
|
||||
ret = append(ret, &i)
|
||||
}
|
||||
|
||||
type RemoteEditType struct {
|
||||
RemoteEdit bool `json:"remoteedit"`
|
||||
RemoteId string `json:"remoteid,omitempty"`
|
||||
ErrorStr string `json:"errorstr,omitempty"`
|
||||
InfoStr string `json:"infostr,omitempty"`
|
||||
KeyStr string `json:"keystr,omitempty"`
|
||||
HasPassword bool `json:"haspassword,omitempty"`
|
||||
}
|
||||
|
||||
type AlertMessageType struct {
|
||||
Title string `json:"title,omitempty"`
|
||||
Message string `json:"message"`
|
||||
Confirm bool `json:"confirm,omitempty"`
|
||||
Markdown bool `json:"markdown,omitempty"`
|
||||
}
|
||||
|
||||
type InfoMsgType struct {
|
||||
InfoTitle string `json:"infotitle"`
|
||||
InfoError string `json:"infoerror,omitempty"`
|
||||
InfoMsg string `json:"infomsg,omitempty"`
|
||||
InfoMsgHtml bool `json:"infomsghtml,omitempty"`
|
||||
WebShareLink bool `json:"websharelink,omitempty"`
|
||||
InfoComps []string `json:"infocomps,omitempty"`
|
||||
InfoCompsMore bool `json:"infocompssmore,omitempty"`
|
||||
InfoLines []string `json:"infolines,omitempty"`
|
||||
TimeoutMs int64 `json:"timeoutms,omitempty"`
|
||||
}
|
||||
|
||||
type HistoryInfoType struct {
|
||||
HistoryType string `json:"historytype"`
|
||||
SessionId string `json:"sessionid,omitempty"`
|
||||
ScreenId string `json:"screenid,omitempty"`
|
||||
Items []*HistoryItemType `json:"items"`
|
||||
Show bool `json:"show"`
|
||||
}
|
||||
|
||||
type UserInputRequestType struct {
|
||||
RequestId string `json:"requestid"`
|
||||
QueryText string `json:"querytext"`
|
||||
ResponseType string `json:"responsetype"`
|
||||
Title string `json:"title"`
|
||||
Markdown bool `json:"markdown"`
|
||||
TimeoutMs int `json:"timeoutms"`
|
||||
return ret
|
||||
}
|
||||
|
||||
type UpdateChannel struct {
|
||||
@ -267,29 +192,6 @@ func (bus *UpdateBus) SendScreenUpdate(screenId string, update UpdatePacket) {
|
||||
}
|
||||
}
|
||||
|
||||
func MakeSessionsUpdateForRemote(sessionId string, ri *RemoteInstance) []*SessionType {
|
||||
return []*SessionType{
|
||||
{
|
||||
SessionId: sessionId,
|
||||
Remotes: []*RemoteInstance{ri},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type BookmarksViewType struct {
|
||||
Bookmarks []*BookmarkType `json:"bookmarks"`
|
||||
}
|
||||
|
||||
type ScreenStatusIndicatorType struct {
|
||||
ScreenId string `json:"screenid"`
|
||||
Status StatusIndicatorLevel `json:"status"`
|
||||
}
|
||||
|
||||
type ScreenNumRunningCommandsType struct {
|
||||
ScreenId string `json:"screenid"`
|
||||
Num int `json:"num"`
|
||||
}
|
||||
|
||||
func (bus *UpdateBus) registerUserInputChannel() (string, chan *scpacket.UserInputResponsePacketType) {
|
||||
bus.Lock.Lock()
|
||||
defer bus.Lock.Unlock()
|
||||
@ -323,7 +225,8 @@ func (bus *UpdateBus) GetUserInput(ctx context.Context, userInputRequest *UserIn
|
||||
userInputRequest.RequestId = id
|
||||
deadline, _ := ctx.Deadline()
|
||||
userInputRequest.TimeoutMs = int(time.Until(deadline).Milliseconds()) - 500
|
||||
update := &ModelUpdate{UserInputRequest: userInputRequest}
|
||||
update := &ModelUpdate{}
|
||||
AddUpdate(update, *userInputRequest)
|
||||
bus.SendUpdate(update)
|
||||
log.Printf("test: %+v", userInputRequest)
|
||||
|
||||
|
234
wavesrv/pkg/sstore/updatetypes.go
Normal file
234
wavesrv/pkg/sstore/updatetypes.go
Normal file
@ -0,0 +1,234 @@
|
||||
package sstore
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/wavetermdev/waveterm/waveshell/pkg/packet"
|
||||
"github.com/wavetermdev/waveterm/waveshell/pkg/utilfn"
|
||||
)
|
||||
|
||||
type ActiveSessionIdUpdate string
|
||||
|
||||
func (ActiveSessionIdUpdate) UpdateType() string {
|
||||
return "activesessionid"
|
||||
}
|
||||
|
||||
type LineUpdate struct {
|
||||
Line LineType `json:"line"`
|
||||
Cmd CmdType `json:"cmd,omitempty"`
|
||||
}
|
||||
|
||||
func (LineUpdate) UpdateType() string {
|
||||
return "line"
|
||||
}
|
||||
|
||||
func AddLineUpdate(update *ModelUpdate, newLine *LineType, newCmd *CmdType) {
|
||||
if newLine == nil {
|
||||
return
|
||||
}
|
||||
newLineUpdate := LineUpdate{
|
||||
Line: *newLine,
|
||||
}
|
||||
if newCmd != nil {
|
||||
newLineUpdate.Cmd = *newCmd
|
||||
}
|
||||
AddUpdate(update, newLineUpdate)
|
||||
}
|
||||
|
||||
type CmdLineUpdate utilfn.StrWithPos
|
||||
|
||||
func (CmdLineUpdate) UpdateType() string {
|
||||
return "cmdline"
|
||||
}
|
||||
|
||||
func AddCmdLineUpdate(update *ModelUpdate, cmdLine utilfn.StrWithPos) {
|
||||
AddUpdate(update, CmdLineUpdate(cmdLine))
|
||||
}
|
||||
|
||||
type InfoMsgType struct {
|
||||
InfoTitle string `json:"infotitle"`
|
||||
InfoError string `json:"infoerror,omitempty"`
|
||||
InfoMsg string `json:"infomsg,omitempty"`
|
||||
InfoMsgHtml bool `json:"infomsghtml,omitempty"`
|
||||
WebShareLink bool `json:"websharelink,omitempty"`
|
||||
InfoComps []string `json:"infocomps,omitempty"`
|
||||
InfoCompsMore bool `json:"infocompssmore,omitempty"`
|
||||
InfoLines []string `json:"infolines,omitempty"`
|
||||
TimeoutMs int64 `json:"timeoutms,omitempty"`
|
||||
}
|
||||
|
||||
func (InfoMsgType) UpdateType() string {
|
||||
return "info"
|
||||
}
|
||||
|
||||
func InfoMsgUpdate(infoMsgFmt string, args ...interface{}) *ModelUpdate {
|
||||
msg := fmt.Sprintf(infoMsgFmt, args...)
|
||||
ret := &ModelUpdate{}
|
||||
newInfoUpdate := InfoMsgType{InfoMsg: msg}
|
||||
AddUpdate(ret, newInfoUpdate)
|
||||
return ret
|
||||
}
|
||||
|
||||
// only sets InfoError if InfoError is not already set
|
||||
func AddInfoMsgUpdateError(update *ModelUpdate, errStr string) {
|
||||
infoUpdates := GetUpdateItems[InfoMsgType](update)
|
||||
|
||||
if len(infoUpdates) > 0 {
|
||||
lastUpdate := infoUpdates[len(infoUpdates)-1]
|
||||
if lastUpdate.InfoError == "" {
|
||||
lastUpdate.InfoError = errStr
|
||||
return
|
||||
}
|
||||
} else {
|
||||
AddUpdate(update, InfoMsgType{InfoError: errStr})
|
||||
}
|
||||
}
|
||||
|
||||
type ClearInfoUpdate bool
|
||||
|
||||
func (ClearInfoUpdate) UpdateType() string {
|
||||
return "clearinfo"
|
||||
}
|
||||
|
||||
type HistoryInfoType struct {
|
||||
HistoryType string `json:"historytype"`
|
||||
SessionId string `json:"sessionid,omitempty"`
|
||||
ScreenId string `json:"screenid,omitempty"`
|
||||
Items []*HistoryItemType `json:"items"`
|
||||
Show bool `json:"show"`
|
||||
}
|
||||
|
||||
func (HistoryInfoType) UpdateType() string {
|
||||
return "history"
|
||||
}
|
||||
|
||||
type InteractiveUpdate bool
|
||||
|
||||
func (InteractiveUpdate) UpdateType() string {
|
||||
return "interactive"
|
||||
}
|
||||
|
||||
func AddInteractiveUpdate(update *ModelUpdate, interactive bool) {
|
||||
AddUpdate(update, InteractiveUpdate(interactive))
|
||||
}
|
||||
|
||||
type ConnectUpdate struct {
|
||||
Sessions []*SessionType `json:"sessions,omitempty"`
|
||||
Screens []*ScreenType `json:"screens,omitempty"`
|
||||
Remotes []*RemoteRuntimeState `json:"remotes,omitempty"`
|
||||
ScreenStatusIndicators []*ScreenStatusIndicatorType `json:"screenstatusindicators,omitempty"`
|
||||
ScreenNumRunningCommands []*ScreenNumRunningCommandsType `json:"screennumrunningcommands,omitempty"`
|
||||
ActiveSessionId string `json:"activesessionid,omitempty"`
|
||||
}
|
||||
|
||||
func (ConnectUpdate) UpdateType() string {
|
||||
return "connect"
|
||||
}
|
||||
|
||||
type MainViewUpdate struct {
|
||||
MainView string `json:"mainview"`
|
||||
HistoryView *HistoryViewData `json:"historyview,omitempty"`
|
||||
BookmarksView *BookmarksUpdate `json:"bookmarksview,omitempty"`
|
||||
}
|
||||
|
||||
func (MainViewUpdate) UpdateType() string {
|
||||
return "mainview"
|
||||
}
|
||||
|
||||
type BookmarksUpdate struct {
|
||||
Bookmarks []*BookmarkType `json:"bookmarks"`
|
||||
SelectedBookmark string `json:"selectedbookmark,omitempty"`
|
||||
}
|
||||
|
||||
func (BookmarksUpdate) UpdateType() string {
|
||||
return "bookmarks"
|
||||
}
|
||||
|
||||
func AddBookmarksUpdate(update *ModelUpdate, bookmarks []*BookmarkType, selectedBookmark *string) {
|
||||
if selectedBookmark == nil {
|
||||
AddUpdate(update, BookmarksUpdate{Bookmarks: bookmarks})
|
||||
} else {
|
||||
AddUpdate(update, BookmarksUpdate{Bookmarks: bookmarks, SelectedBookmark: *selectedBookmark})
|
||||
}
|
||||
}
|
||||
|
||||
type HistoryViewData struct {
|
||||
Items []*HistoryItemType `json:"items"`
|
||||
Offset int `json:"offset"`
|
||||
RawOffset int `json:"rawoffset"`
|
||||
NextRawOffset int `json:"nextrawoffset"`
|
||||
HasMore bool `json:"hasmore"`
|
||||
Lines []*LineType `json:"lines"`
|
||||
Cmds []*CmdType `json:"cmds"`
|
||||
}
|
||||
|
||||
type RemoteEditType struct {
|
||||
RemoteEdit bool `json:"remoteedit"`
|
||||
RemoteId string `json:"remoteid,omitempty"`
|
||||
ErrorStr string `json:"errorstr,omitempty"`
|
||||
InfoStr string `json:"infostr,omitempty"`
|
||||
KeyStr string `json:"keystr,omitempty"`
|
||||
HasPassword bool `json:"haspassword,omitempty"`
|
||||
}
|
||||
|
||||
type RemoteViewType struct {
|
||||
RemoteShowAll bool `json:"remoteshowall,omitempty"`
|
||||
PtyRemoteId string `json:"ptyremoteid,omitempty"`
|
||||
RemoteEdit *RemoteEditType `json:"remoteedit,omitempty"`
|
||||
}
|
||||
|
||||
func (RemoteViewType) UpdateType() string {
|
||||
return "remoteview"
|
||||
}
|
||||
|
||||
type OpenAICmdInfoChatUpdate []*packet.OpenAICmdInfoChatMessage
|
||||
|
||||
func (OpenAICmdInfoChatUpdate) UpdateType() string {
|
||||
return "openaicmdinfochat"
|
||||
}
|
||||
|
||||
func AddOpenAICmdInfoChatUpdate(update *ModelUpdate, chatMessages []*packet.OpenAICmdInfoChatMessage) {
|
||||
AddUpdate(update, OpenAICmdInfoChatUpdate(chatMessages))
|
||||
}
|
||||
|
||||
type AlertMessageType struct {
|
||||
Title string `json:"title,omitempty"`
|
||||
Message string `json:"message"`
|
||||
Confirm bool `json:"confirm,omitempty"`
|
||||
Markdown bool `json:"markdown,omitempty"`
|
||||
}
|
||||
|
||||
func (AlertMessageType) UpdateType() string {
|
||||
return "alertmessage"
|
||||
}
|
||||
|
||||
type ScreenStatusIndicatorType struct {
|
||||
ScreenId string `json:"screenid"`
|
||||
Status StatusIndicatorLevel `json:"status"`
|
||||
}
|
||||
|
||||
func (ScreenStatusIndicatorType) UpdateType() string {
|
||||
return "screenstatusindicator"
|
||||
}
|
||||
|
||||
type ScreenNumRunningCommandsType struct {
|
||||
ScreenId string `json:"screenid"`
|
||||
Num int `json:"num"`
|
||||
}
|
||||
|
||||
func (ScreenNumRunningCommandsType) UpdateType() string {
|
||||
return "screennumrunningcommands"
|
||||
}
|
||||
|
||||
type UserInputRequestType struct {
|
||||
RequestId string `json:"requestid"`
|
||||
QueryText string `json:"querytext"`
|
||||
ResponseType string `json:"responsetype"`
|
||||
Title string `json:"title"`
|
||||
Markdown bool `json:"markdown"`
|
||||
TimeoutMs int `json:"timeoutms"`
|
||||
}
|
||||
|
||||
func (UserInputRequestType) UpdateType() string {
|
||||
return "userinputrequest"
|
||||
}
|
Loading…
Reference in New Issue
Block a user