mirror of
https://github.com/wavetermdev/backup.git
synced 2026-04-22 15:26:58 -07:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ea253c33ae | |||
| 53de138832 | |||
| 75778963c5 | |||
| 89906d21d4 | |||
| 747a2b784a | |||
| 84e7605e36 | |||
| 839e338dad | |||
| 771046637d | |||
| 8dc3b3b0c1 | |||
| 0a8c8221fd | |||
| 38c6e8f5f8 | |||
| def90a0493 | |||
| e2d10cd807 | |||
| 26240bea97 | |||
| fa9a0bd228 | |||
| fa2c684c0e | |||
| 750e8bc9f7 | |||
| f781e358e5 | |||
| 98f6b84d3e |
@@ -1,13 +1,13 @@
|
||||
import * as React from "react";
|
||||
import { GlobalModel } from "../../../models";
|
||||
import { Choose, When, If } from "tsx-control-statements/components";
|
||||
import { Choose, When, If } from "tsx-control-statements";
|
||||
import { Modal, PasswordField, Markdown } from "../elements";
|
||||
import { UserInputRequest } from "../../../types/types";
|
||||
|
||||
import "./userinput.less";
|
||||
|
||||
export const UserInputModal = (userInputRequest: UserInputRequest) => {
|
||||
const [responseText, setResponseText] = React.useState("");
|
||||
const [responseText, setResponseText] = React.useState(null);
|
||||
const [countdown, setCountdown] = React.useState(Math.floor(userInputRequest.timeoutms / 1000));
|
||||
|
||||
const closeModal = React.useCallback(() => {
|
||||
|
||||
@@ -54,8 +54,6 @@
|
||||
}
|
||||
|
||||
.remote-detail {
|
||||
width: 100%;
|
||||
|
||||
.settings-field {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@@ -93,9 +91,8 @@
|
||||
}
|
||||
|
||||
.terminal-wrapper {
|
||||
width: 100%;
|
||||
margin-top: 5px;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
|
||||
.terminal-connectelem {
|
||||
height: 163px !important; // Needed to override plugin height
|
||||
@@ -114,6 +111,7 @@
|
||||
|
||||
.xterm-screen {
|
||||
padding: 10px;
|
||||
width: 541px !important; // Needed to override plugin width
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,10 +12,12 @@ import * as T from "../../../types/types";
|
||||
import { Modal, Tooltip, Button, Status } from "../elements";
|
||||
import * as util from "../../../util/util";
|
||||
import * as textmeasure from "../../../util/textmeasure";
|
||||
import * as appconst from "../../appconst";
|
||||
|
||||
import "./viewremoteconndetail.less";
|
||||
|
||||
const RemotePtyRows = 9;
|
||||
const RemotePtyCols = 80;
|
||||
|
||||
@mobxReact.observer
|
||||
class ViewRemoteConnDetailModal extends React.Component<{}, {}> {
|
||||
termRef: React.RefObject<any> = React.createRef();
|
||||
@@ -291,7 +293,7 @@ class ViewRemoteConnDetailModal extends React.Component<{}, {}> {
|
||||
let model = this.model;
|
||||
let isTermFocused = this.model.remoteTermWrapFocus.get();
|
||||
let termFontSize = GlobalModel.termFontSize.get();
|
||||
let termWidth = textmeasure.termWidthFromCols(appconst.RemotePtyCols, termFontSize);
|
||||
let termWidth = textmeasure.termWidthFromCols(RemotePtyCols, termFontSize);
|
||||
let remoteAliasText = util.isBlank(remote.remotealias) ? "(none)" : remote.remotealias;
|
||||
let selectedRemoteStatus = this.getSelectedRemote().status;
|
||||
|
||||
@@ -369,7 +371,7 @@ class ViewRemoteConnDetailModal extends React.Component<{}, {}> {
|
||||
ref={this.termRef}
|
||||
data-remoteid={remote.remoteid}
|
||||
style={{
|
||||
height: textmeasure.termHeightFromRows(appconst.RemotePtyRows, termFontSize),
|
||||
height: textmeasure.termHeightFromRows(RemotePtyRows, termFontSize),
|
||||
width: termWidth,
|
||||
}}
|
||||
></div>
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #3b3f3a;
|
||||
border: 1px solid #3B3F3A;
|
||||
background: rgba(213, 254, 175, 0.03);
|
||||
}
|
||||
|
||||
|
||||
&.checkbox-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
@@ -30,7 +30,7 @@
|
||||
height: 16px;
|
||||
fill: rgba(213, 254, 175, 0.03);
|
||||
stroke-width: 1px;
|
||||
stroke: #3b3f3a;
|
||||
stroke: #3B3F3A;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,7 +264,6 @@
|
||||
margin: 0px 10px 10px 10px;
|
||||
table-layout: fixed;
|
||||
border-top: 2px solid #ccc;
|
||||
width: calc(100% - 20px);
|
||||
|
||||
tr.active-history-item {
|
||||
td {
|
||||
@@ -310,8 +309,9 @@
|
||||
tr.history-item {
|
||||
padding: 0 10px 0 10px;
|
||||
display: flex;
|
||||
border-bottom: 1px solid rgba(250, 250, 250, 0.1);
|
||||
border-bottom: 1px solid rgba(250, 250, 250, 0.10);
|
||||
align-items: center;
|
||||
height: 40px;
|
||||
color: @text-secondary;
|
||||
|
||||
&.is-selected {
|
||||
|
||||
+17
-23
@@ -14,7 +14,6 @@ import { sprintf } from "sprintf-js";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { checkKeyPressed, adaptFromElectronKeyEvent, setKeyUtilPlatform } from "../util/keyutil";
|
||||
import { platform } from "os";
|
||||
import type * as T from "../types/types";
|
||||
|
||||
const WaveAppPathVarName = "WAVETERM_APP_PATH";
|
||||
const WaveDevVarName = "WAVETERM_DEV";
|
||||
@@ -41,21 +40,19 @@ let unameArch: string = process.arch;
|
||||
if (unameArch == "x64") {
|
||||
unameArch = "amd64";
|
||||
}
|
||||
let loggerTransports: winston.transport[] = [
|
||||
new winston.transports.File({ filename: path.join(waveHome, "waveterm-app.log"), level: "info" }),
|
||||
];
|
||||
if (isDev) {
|
||||
loggerTransports.push(new winston.transports.Console());
|
||||
}
|
||||
let logger;
|
||||
let loggerConfig = {
|
||||
level: "info",
|
||||
format: winston.format.combine(
|
||||
winston.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }),
|
||||
winston.format.printf((info) => `${info.timestamp} ${info.message}`)
|
||||
),
|
||||
transports: loggerTransports,
|
||||
transports: [new winston.transports.File({ filename: path.join(waveHome, "waveterm-app.log"), level: "info" })],
|
||||
};
|
||||
let logger = winston.createLogger(loggerConfig);
|
||||
if (isDev) {
|
||||
loggerConfig.transports.push(new winston.transports.Console());
|
||||
}
|
||||
logger = winston.createLogger(loggerConfig);
|
||||
function log(...msg) {
|
||||
try {
|
||||
logger.info(util.format(...msg));
|
||||
@@ -78,7 +75,7 @@ if (isDev) {
|
||||
}
|
||||
let app = electron.app;
|
||||
app.setName(isDev ? "Wave (Dev)" : "Wave");
|
||||
let waveSrvProc: child_process.ChildProcessWithoutNullStreams | null = null;
|
||||
let waveSrvProc = null;
|
||||
let waveSrvShouldRestart = false;
|
||||
|
||||
electron.dialog.showErrorBox = (title, content) => {
|
||||
@@ -104,11 +101,8 @@ function checkPromptMigrate() {
|
||||
// don't migrate if we're running dev version or if wave home directory already exists
|
||||
return;
|
||||
}
|
||||
if (process.env.HOME == null) {
|
||||
return;
|
||||
}
|
||||
let homeDir: string = process.env.HOME;
|
||||
let promptHome: string = path.join(homeDir, "prompt");
|
||||
let homeDir = process.env.HOME;
|
||||
let promptHome = path.join(homeDir, "prompt");
|
||||
if (!fs.existsSync(promptHome) || !fs.existsSync(path.join(promptHome, "prompt.db"))) {
|
||||
// make sure we have a valid prompt home directory (prompt.db must exist inside)
|
||||
return;
|
||||
@@ -176,7 +170,7 @@ function readAuthKey() {
|
||||
return authKeyStr.trim();
|
||||
}
|
||||
|
||||
let menuTemplate: Electron.MenuItemConstructorOptions[] = [
|
||||
let menuTemplate = [
|
||||
{
|
||||
role: "appMenu",
|
||||
submenu: [
|
||||
@@ -228,7 +222,7 @@ function getMods(input: any) {
|
||||
return { meta: input.meta, shift: input.shift, ctrl: input.control, alt: input.alt };
|
||||
}
|
||||
|
||||
function shNavHandler(event: Electron.Event<Electron.WebContentsWillNavigateEventParams>, url: string) {
|
||||
function shNavHandler(event: any, url: any) {
|
||||
event.preventDefault();
|
||||
if (url.startsWith("https://") || url.startsWith("http://") || url.startsWith("file://")) {
|
||||
console.log("open external, shNav", url);
|
||||
@@ -238,13 +232,12 @@ function shNavHandler(event: Electron.Event<Electron.WebContentsWillNavigateEven
|
||||
}
|
||||
}
|
||||
|
||||
function shFrameNavHandler(event: Electron.Event<Electron.WebContentsWillFrameNavigateEventParams>) {
|
||||
function shFrameNavHandler(event: any, url: any) {
|
||||
if (!event.frame || event.frame.parent == null) {
|
||||
// only use this handler to process iframe events (non-iframe events go to shNavHandler)
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
let url = event.url;
|
||||
console.log(`frame-navigation url=${url} frame=${event.frame.name}`);
|
||||
if (event.frame.name == "webview") {
|
||||
// "webview" links always open in new window
|
||||
@@ -257,7 +250,7 @@ function shFrameNavHandler(event: Electron.Event<Electron.WebContentsWillFrameNa
|
||||
return;
|
||||
}
|
||||
|
||||
function createMainWindow(clientData: T.ClientDataType | null) {
|
||||
function createMainWindow(clientData) {
|
||||
let bounds = calcBounds(clientData);
|
||||
setKeyUtilPlatform(platform());
|
||||
let win = new electron.BrowserWindow({
|
||||
@@ -651,11 +644,12 @@ electron.ipcMain.on("context-editmenu", (event, { x, y }, opts) => {
|
||||
}
|
||||
console.log("context-editmenu");
|
||||
let menu = new electron.Menu();
|
||||
let menuItem = null;
|
||||
if (opts.showCut) {
|
||||
let menuItem = new electron.MenuItem({ label: "Cut", role: "cut" });
|
||||
menuItem = new electron.MenuItem({ label: "Cut", role: "cut" });
|
||||
menu.append(menuItem);
|
||||
}
|
||||
let menuItem = new electron.MenuItem({ label: "Copy", role: "copy" });
|
||||
menuItem = new electron.MenuItem({ label: "Copy", role: "copy" });
|
||||
menu.append(menuItem);
|
||||
menuItem = new electron.MenuItem({ label: "Paste", role: "paste" });
|
||||
menu.append(menuItem);
|
||||
@@ -663,7 +657,7 @@ electron.ipcMain.on("context-editmenu", (event, { x, y }, opts) => {
|
||||
});
|
||||
|
||||
async function createMainWindowWrap() {
|
||||
let clientData: T.ClientDataType | null = null;
|
||||
let clientData = null;
|
||||
try {
|
||||
clientData = await getClientDataPoll(1);
|
||||
} catch (e) {
|
||||
|
||||
@@ -8,7 +8,7 @@ import { GlobalModel } from "./global";
|
||||
class CommandRunner {
|
||||
private constructor() {}
|
||||
|
||||
static getInstance(): CommandRunner {
|
||||
static getInstance() {
|
||||
if (!(window as any).GlobalCommandRunner) {
|
||||
(window as any).GlobalCommandRunner = new CommandRunner();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Model } from "./model";
|
||||
import { CommandRunner } from "./commandrunner";
|
||||
|
||||
const GlobalModel: Model = Model.getInstance();
|
||||
const GlobalCommandRunner: CommandRunner = CommandRunner.getInstance();
|
||||
const GlobalModel = Model.getInstance();
|
||||
const GlobalCommandRunner = CommandRunner.getInstance();
|
||||
export { GlobalModel, GlobalCommandRunner };
|
||||
|
||||
+15
-10
@@ -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,6 +207,7 @@ class InputModel {
|
||||
this.historyQueryOpts.set(opts);
|
||||
let bestIndex = this.findBestNewIndex(oldItem);
|
||||
setTimeout(() => this.setHistoryIndex(bestIndex, true), 10);
|
||||
return;
|
||||
})();
|
||||
}
|
||||
|
||||
@@ -623,17 +624,13 @@ class InputModel {
|
||||
}
|
||||
|
||||
openAIAssistantChat(): void {
|
||||
mobx.action(() => {
|
||||
this.aIChatShow.set(true);
|
||||
this.setAIChatFocus();
|
||||
})();
|
||||
this.aIChatShow.set(true);
|
||||
this.setAIChatFocus();
|
||||
}
|
||||
|
||||
closeAIAssistantChat(): void {
|
||||
mobx.action(() => {
|
||||
this.aIChatShow.set(false);
|
||||
this.giveFocus();
|
||||
})();
|
||||
this.aIChatShow.set(false);
|
||||
this.giveFocus();
|
||||
}
|
||||
|
||||
clearAIAssistantChat(): void {
|
||||
@@ -724,6 +721,14 @@ 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;
|
||||
}
|
||||
|
||||
+248
-295
File diff suppressed because it is too large
Load Diff
@@ -12,6 +12,9 @@ import { GlobalCommandRunner } from "./global";
|
||||
import { Model } from "./model";
|
||||
import { getTermPtyData } from "../util/modelutil";
|
||||
|
||||
const RemotePtyRows = 8; // also in main.tsx
|
||||
const RemotePtyCols = 80;
|
||||
|
||||
class RemotesModel {
|
||||
globalModel: Model;
|
||||
selectedRemoteId: OV<string> = mobx.observable.box(null, {
|
||||
@@ -177,14 +180,14 @@ class RemotesModel {
|
||||
return;
|
||||
}
|
||||
let termOpts = {
|
||||
rows: appconst.RemotePtyRows,
|
||||
cols: appconst.RemotePtyCols,
|
||||
rows: RemotePtyRows,
|
||||
cols: RemotePtyCols,
|
||||
flexrows: false,
|
||||
maxptysize: 64 * 1024,
|
||||
};
|
||||
let termWrap = new TermWrap(elem, {
|
||||
termContext: { remoteId: remoteId },
|
||||
usedRows: appconst.RemotePtyRows,
|
||||
usedRows: RemotePtyRows,
|
||||
termOpts: termOpts,
|
||||
winSize: null,
|
||||
keyHandler: (e, termWrap) => {
|
||||
|
||||
@@ -139,7 +139,7 @@ class ScreenLines {
|
||||
return;
|
||||
}
|
||||
let lineIdx = 0;
|
||||
for (lineIdx; lineIdx < lines.length; lineIdx++) {
|
||||
for (lineIdx = 0; lineIdx < lines.length; lineIdx++) {
|
||||
let lineId = lines[lineIdx].lineid;
|
||||
let curTs = lines[lineIdx].ts;
|
||||
if (lineId == line.lineid) {
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
|
||||
.terminal-wrapper {
|
||||
.xterm-viewport {
|
||||
overflow: hidden;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
&:hover .xterm-viewport,
|
||||
&:focus-within .xterm-viewport {
|
||||
overflow: auto;
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
|
||||
+15
-45
@@ -29,6 +29,7 @@ type SessionDataType = {
|
||||
|
||||
// for updates
|
||||
remove?: boolean;
|
||||
full?: boolean;
|
||||
};
|
||||
|
||||
type LineStateType = { [k: string]: any };
|
||||
@@ -91,6 +92,7 @@ type ScreenDataType = {
|
||||
anchor: { anchorline: number; anchoroffset: number };
|
||||
|
||||
// for updates
|
||||
full?: boolean;
|
||||
remove?: boolean;
|
||||
};
|
||||
|
||||
@@ -258,11 +260,6 @@ type CmdDataType = {
|
||||
restarted?: boolean;
|
||||
};
|
||||
|
||||
type LineUpdateType = {
|
||||
line: LineType;
|
||||
cmd: CmdDataType;
|
||||
};
|
||||
|
||||
type PtyDataUpdateType = {
|
||||
screenid: string;
|
||||
lineid: string;
|
||||
@@ -312,47 +309,30 @@ 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;
|
||||
session?: SessionDataType;
|
||||
sessions?: SessionDataType[];
|
||||
activesessionid?: string;
|
||||
screen?: ScreenDataType;
|
||||
screens?: ScreenDataType[];
|
||||
screenlines?: ScreenLinesType;
|
||||
line?: LineUpdateType;
|
||||
line?: LineType;
|
||||
lines?: LineType[];
|
||||
cmd?: CmdDataType;
|
||||
info?: InfoType;
|
||||
cmdline?: StrWithPos;
|
||||
remote?: RemoteType;
|
||||
remotes?: RemoteType[];
|
||||
history?: HistoryInfoType;
|
||||
connect?: ConnectUpdateType;
|
||||
mainview?: MainViewUpdateType;
|
||||
bookmarks?: BookmarksUpdateType;
|
||||
connect?: boolean;
|
||||
mainview?: string;
|
||||
bookmarks?: BookmarkType[];
|
||||
selectedbookmark?: string;
|
||||
clientdata?: ClientDataType;
|
||||
historyviewdata?: HistoryViewDataType;
|
||||
remoteview?: RemoteViewType;
|
||||
openaicmdinfochat?: OpenAICmdInfoChatMessageType[];
|
||||
alertmessage?: AlertMessageType;
|
||||
screenstatusindicator?: ScreenStatusIndicatorUpdateType;
|
||||
screennumrunningcommands?: ScreenNumRunningCommandsUpdateType;
|
||||
screenstatusindicators?: ScreenStatusIndicatorUpdateType[];
|
||||
screennumrunningcommands?: ScreenNumRunningCommandsUpdateType[];
|
||||
userinputrequest?: UserInputRequest;
|
||||
};
|
||||
|
||||
@@ -435,7 +415,7 @@ type ContextMenuOpts = {
|
||||
showCut?: boolean;
|
||||
};
|
||||
|
||||
type UpdateMessage = PtyDataUpdateType | ModelUpdateType[];
|
||||
type UpdateMessage = PtyDataUpdateType | ModelUpdateType;
|
||||
|
||||
type RendererContext = {
|
||||
screenId: string;
|
||||
@@ -560,14 +540,6 @@ type ReleaseInfoType = {
|
||||
latestversion: string;
|
||||
};
|
||||
|
||||
type ClientWinSize = {
|
||||
width: number;
|
||||
height: number;
|
||||
top: number;
|
||||
left: number;
|
||||
fullscreen: boolean;
|
||||
};
|
||||
|
||||
type ClientDataType = {
|
||||
clientid: string;
|
||||
userid: string;
|
||||
@@ -577,7 +549,6 @@ type ClientDataType = {
|
||||
dbversion: number;
|
||||
openaiopts?: OpenAIOptsType;
|
||||
releaseinfo?: ReleaseInfoType;
|
||||
winsize: ClientWinSize;
|
||||
};
|
||||
|
||||
type OpenAIOptsType = {
|
||||
@@ -895,7 +866,6 @@ export type {
|
||||
CmdInputTextPacketType,
|
||||
OpenAICmdInfoChatMessageType,
|
||||
ScreenStatusIndicatorUpdateType,
|
||||
ScreenNumRunningCommandsUpdateType,
|
||||
OV,
|
||||
OArr,
|
||||
OMap,
|
||||
|
||||
+69
-53
@@ -1,4 +1,4 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// Copyright 2023, 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> {
|
||||
const errMsg = sprintf(
|
||||
let 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> {
|
||||
const contentType = resp.headers.get("Content-Type");
|
||||
if (contentType?.startsWith("application/json")) {
|
||||
let contentType = resp.headers.get("Content-Type");
|
||||
if (contentType != null && contentType.startsWith("application/json")) {
|
||||
return resp.text().then((textData) => {
|
||||
let rtnData: any = null;
|
||||
try {
|
||||
rtnData = JSON.parse(textData);
|
||||
} catch (err) {
|
||||
const errMsg = sprintf("Unparseable JSON: " + err.message);
|
||||
const rtnErr = new Error(errMsg);
|
||||
let errMsg = sprintf("Unparseable JSON: " + err.message);
|
||||
let rtnErr = new Error(errMsg);
|
||||
throw rtnErr;
|
||||
}
|
||||
if (rtnData?.error) {
|
||||
if (rtnData != null && 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);
|
||||
}
|
||||
const rtnData = fetchJsonData(resp, true);
|
||||
let rtnData = fetchJsonData(resp, true);
|
||||
return rtnData;
|
||||
}
|
||||
|
||||
function base64ToString(b64: string): string {
|
||||
const stringBytes = base64.toByteArray(b64);
|
||||
let stringBytes = base64.toByteArray(b64);
|
||||
return new TextDecoder().decode(stringBytes);
|
||||
}
|
||||
|
||||
function stringToBase64(input: string): string {
|
||||
const stringBytes = new TextEncoder().encode(input);
|
||||
let stringBytes = new TextEncoder().encode(input);
|
||||
return base64.fromByteArray(stringBytes);
|
||||
}
|
||||
|
||||
function base64ToArray(b64: string): Uint8Array {
|
||||
const rawStr = atob(b64);
|
||||
const rtnArr = new Uint8Array(new ArrayBuffer(rawStr.length));
|
||||
let rawStr = atob(b64);
|
||||
let rtnArr = new Uint8Array(new ArrayBuffer(rawStr.length));
|
||||
for (let i = 0; i < rawStr.length; i++) {
|
||||
rtnArr[i] = rawStr.charCodeAt(i);
|
||||
}
|
||||
@@ -92,6 +92,7 @@ function base64ToArray(b64: string): Uint8Array {
|
||||
|
||||
interface IDataType {
|
||||
remove?: boolean;
|
||||
full?: boolean;
|
||||
}
|
||||
|
||||
interface IObjType<DataType> {
|
||||
@@ -112,28 +113,31 @@ function genMergeSimpleData<T extends ISimpleDataType>(
|
||||
if (dataArr == null || dataArr.length == 0) {
|
||||
return;
|
||||
}
|
||||
const objMap: Record<string, T> = {};
|
||||
for (const obj of objs) {
|
||||
const id = idFn(obj);
|
||||
let objMap: Record<string, T> = {};
|
||||
for (let i = 0; i < objs.length; i++) {
|
||||
let obj = objs[i];
|
||||
let id = idFn(obj);
|
||||
objMap[id] = obj;
|
||||
}
|
||||
for (const dataItem of dataArr) {
|
||||
for (let i = 0; i < dataArr.length; i++) {
|
||||
let dataItem = dataArr[i];
|
||||
if (dataItem == null) {
|
||||
console.log("genMergeSimpleData, null item");
|
||||
console.trace();
|
||||
}
|
||||
const id = idFn(dataItem);
|
||||
let id = idFn(dataItem);
|
||||
if (dataItem.remove) {
|
||||
delete objMap[id];
|
||||
continue;
|
||||
} else {
|
||||
objMap[id] = dataItem;
|
||||
}
|
||||
}
|
||||
const newObjs = Object.values(objMap);
|
||||
let newObjs = Object.values(objMap);
|
||||
if (sortIdxFn) {
|
||||
newObjs.sort((a, b) => {
|
||||
const astr = sortIdxFn(a);
|
||||
const bstr = sortIdxFn(b);
|
||||
let astr = sortIdxFn(a);
|
||||
let bstr = sortIdxFn(b);
|
||||
return astr.localeCompare(bstr);
|
||||
});
|
||||
}
|
||||
@@ -151,18 +155,20 @@ function genMergeData<ObjType extends IObjType<DataType>, DataType extends IData
|
||||
if (dataArr == null || dataArr.length == 0) {
|
||||
return;
|
||||
}
|
||||
const objMap: Record<string, ObjType> = {};
|
||||
for (const obj of objs) {
|
||||
const id = objIdFn(obj);
|
||||
let objMap: Record<string, ObjType> = {};
|
||||
for (let i = 0; i < objs.length; i++) {
|
||||
let obj = objs[i];
|
||||
let id = objIdFn(obj);
|
||||
objMap[id] = obj;
|
||||
}
|
||||
for (const dataItem of dataArr) {
|
||||
for (let i = 0; i < dataArr.length; i++) {
|
||||
let dataItem = dataArr[i];
|
||||
if (dataItem == null) {
|
||||
console.log("genMergeData, null item");
|
||||
console.trace();
|
||||
continue;
|
||||
}
|
||||
const id = dataIdFn(dataItem);
|
||||
let id = dataIdFn(dataItem);
|
||||
let obj = objMap[id];
|
||||
if (dataItem.remove) {
|
||||
if (obj != null) {
|
||||
@@ -172,13 +178,17 @@ 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);
|
||||
}
|
||||
const newObjs = Object.values(objMap);
|
||||
let newObjs = Object.values(objMap);
|
||||
if (sortIdxFn) {
|
||||
newObjs.sort((a, b) => {
|
||||
return sortIdxFn(a) - sortIdxFn(b);
|
||||
@@ -194,17 +204,18 @@ function genMergeDataMap<ObjType extends IObjType<DataType>, DataType extends ID
|
||||
dataIdFn: (data: DataType) => string,
|
||||
ctorFn: (data: DataType) => ObjType
|
||||
): { added: string[]; removed: string[] } {
|
||||
const rtn: { added: string[]; removed: string[] } = { added: [], removed: [] };
|
||||
let rtn: { added: string[]; removed: string[] } = { added: [], removed: [] };
|
||||
if (dataArr == null || dataArr.length == 0) {
|
||||
return rtn;
|
||||
}
|
||||
for (const dataItem of dataArr) {
|
||||
for (let i = 0; i < dataArr.length; i++) {
|
||||
let dataItem = dataArr[i];
|
||||
if (dataItem == null) {
|
||||
console.log("genMergeDataMap, null item");
|
||||
console.trace();
|
||||
continue;
|
||||
}
|
||||
const id = dataIdFn(dataItem);
|
||||
let id = dataIdFn(dataItem);
|
||||
let obj = objMap.get(id);
|
||||
if (dataItem.remove) {
|
||||
if (obj != null) {
|
||||
@@ -215,6 +226,10 @@ 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);
|
||||
@@ -247,23 +262,23 @@ function incObs(inum: mobx.IObservableValue<number>) {
|
||||
|
||||
// @check:font
|
||||
function loadFonts() {
|
||||
const jbmFontNormal = new FontFace("JetBrains Mono", "url('public/fonts/jetbrains-mono-v13-latin-regular.woff2')", {
|
||||
let jbmFontNormal = new FontFace("JetBrains Mono", "url('public/fonts/jetbrains-mono-v13-latin-regular.woff2')", {
|
||||
style: "normal",
|
||||
weight: "400",
|
||||
});
|
||||
const jbmFont200 = new FontFace("JetBrains Mono", "url('public/fonts/jetbrains-mono-v13-latin-200.woff2')", {
|
||||
let jbmFont200 = new FontFace("JetBrains Mono", "url('public/fonts/jetbrains-mono-v13-latin-200.woff2')", {
|
||||
style: "normal",
|
||||
weight: "200",
|
||||
});
|
||||
const jbmFont700 = new FontFace("JetBrains Mono", "url('public/fonts/jetbrains-mono-v13-latin-700.woff2')", {
|
||||
let jbmFont700 = new FontFace("JetBrains Mono", "url('public/fonts/jetbrains-mono-v13-latin-700.woff2')", {
|
||||
style: "normal",
|
||||
weight: "700",
|
||||
});
|
||||
const faFont = new FontFace("FontAwesome", "url(public/fonts/fontawesome-webfont-4.7.woff2)", {
|
||||
let faFont = new FontFace("FontAwesome", "url(public/fonts/fontawesome-webfont-4.7.woff2)", {
|
||||
style: "normal",
|
||||
weight: "normal",
|
||||
});
|
||||
const docFonts: any = document.fonts; // work around ts typing issue
|
||||
let docFonts: any = document.fonts; // work around ts typing issue
|
||||
docFonts.add(jbmFontNormal);
|
||||
docFonts.add(jbmFont200);
|
||||
docFonts.add(jbmFont700);
|
||||
@@ -281,13 +296,13 @@ function getTodayStr(): string {
|
||||
}
|
||||
|
||||
function getYesterdayStr(): string {
|
||||
const d = new Date();
|
||||
let d = new Date();
|
||||
d.setDate(d.getDate() - 1);
|
||||
return getDateStr(d);
|
||||
}
|
||||
|
||||
function getDateStr(d: Date): string {
|
||||
const yearStr = String(d.getFullYear());
|
||||
let yearStr = String(d.getFullYear());
|
||||
let monthStr = String(d.getMonth() + 1);
|
||||
if (monthStr.length == 1) {
|
||||
monthStr = "0" + monthStr;
|
||||
@@ -296,30 +311,31 @@ function getDateStr(d: Date): string {
|
||||
if (dayStr.length == 1) {
|
||||
dayStr = "0" + dayStr;
|
||||
}
|
||||
const dowStr = DOW_STRS[d.getDay()];
|
||||
let dowStr = DOW_STRS[d.getDay()];
|
||||
return dowStr + " " + yearStr + "-" + monthStr + "-" + dayStr;
|
||||
}
|
||||
|
||||
function getRemoteConnVal(r: RemoteType): number {
|
||||
switch (r.status) {
|
||||
case "connected":
|
||||
return 1;
|
||||
case "connecting":
|
||||
return 2;
|
||||
case "disconnected":
|
||||
return 3;
|
||||
case "error":
|
||||
return 4;
|
||||
default:
|
||||
return 5;
|
||||
if (r.status == "connected") {
|
||||
return 1;
|
||||
}
|
||||
if (r.status == "connecting") {
|
||||
return 2;
|
||||
}
|
||||
if (r.status == "disconnected") {
|
||||
return 3;
|
||||
}
|
||||
if (r.status == "error") {
|
||||
return 4;
|
||||
}
|
||||
return 5;
|
||||
}
|
||||
|
||||
function sortAndFilterRemotes(origRemotes: RemoteType[]): RemoteType[] {
|
||||
const remotes = origRemotes.filter((r) => !r.archived);
|
||||
let remotes = origRemotes.filter((r) => !r.archived);
|
||||
remotes.sort((a, b) => {
|
||||
const connValA = getRemoteConnVal(a);
|
||||
const connValB = getRemoteConnVal(b);
|
||||
let connValA = getRemoteConnVal(a);
|
||||
let connValB = getRemoteConnVal(b);
|
||||
if (connValA != connValB) {
|
||||
return connValA - connValB;
|
||||
}
|
||||
@@ -356,7 +372,7 @@ function openLink(url: string): void {
|
||||
window.open(url, "_blank");
|
||||
}
|
||||
|
||||
function getColorRGB(colorInput: string) {
|
||||
function getColorRGB(colorInput) {
|
||||
const tempElement = document.createElement("div");
|
||||
tempElement.style.color = colorInput;
|
||||
document.body.appendChild(tempElement);
|
||||
@@ -383,7 +399,7 @@ function getRemoteName(remote: RemoteType): string {
|
||||
if (remote == null) {
|
||||
return "";
|
||||
}
|
||||
const { remotealias, remotecanonicalname } = remote;
|
||||
let { remotealias, remotecanonicalname } = remote;
|
||||
return remotealias ? `${remotealias} [${remotecanonicalname}]` : remotecanonicalname;
|
||||
}
|
||||
|
||||
|
||||
@@ -257,7 +257,10 @@ func (z zshShellApi) MakeRcFileStr(pk *packet.RunPacketType) string {
|
||||
}
|
||||
rcBuf.WriteString("\n")
|
||||
}
|
||||
// do NOT unset ZDOTDIR, otherwise initialization will start to read initialization files from ~/ again
|
||||
if shellenv.FindVarDecl(varDecls, "ZDOTDIR") == nil {
|
||||
rcBuf.WriteString("unset ZDOTDIR\n")
|
||||
rcBuf.WriteString("\n")
|
||||
}
|
||||
for _, varName := range ZshUnsetVars {
|
||||
rcBuf.WriteString("unset " + shellescape.Quote(varName) + "\n")
|
||||
}
|
||||
|
||||
@@ -824,7 +824,7 @@ func main() {
|
||||
return
|
||||
}
|
||||
if len(os.Args) >= 2 && strings.HasPrefix(os.Args[1], "--migrate") {
|
||||
err := sstore.MainDBMigrateCommandOpts(os.Args[1:])
|
||||
err := sstore.MigrateCommandOpts(os.Args[1:])
|
||||
if err != nil {
|
||||
log.Printf("[error] migrate cmd: %v\n", err)
|
||||
}
|
||||
@@ -836,7 +836,7 @@ func main() {
|
||||
return
|
||||
}
|
||||
GlobalAuthKey = authKey
|
||||
err = sstore.MainDBTryMigrateUp()
|
||||
err = sstore.TryMigrateUp()
|
||||
if err != nil {
|
||||
log.Printf("[error] migrate up: %v\n", err)
|
||||
return
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
DROP TABLE file;
|
||||
@@ -1,9 +0,0 @@
|
||||
CREATE TABLE file (
|
||||
screenid varchar(36) NOT NULL,
|
||||
lineid varchar(36) NOT NULL,
|
||||
filename varchar(200) NOT NULL,
|
||||
filetype varchar(20) NOT NULL,
|
||||
diskfilename varchar(250) NOT NULL,
|
||||
contents blob NOT NULL,
|
||||
PRIMARY KEY (screenid, lineid, filename)
|
||||
);
|
||||
+286
-245
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user