Compare commits

..

51 Commits

Author SHA1 Message Date
Red Adaya 1d0b7bd770 split models/model 2024-02-08 16:40:15 +08:00
Red Adaya a9b9ff3362 fix conflicts 2024-02-08 14:48:29 +08:00
Red Adaya d2829c466d fix ptyDataSource errors 2024-02-08 14:26:49 +08:00
Red Adaya f65e632c35 move model_old to models 2024-02-08 13:37:42 +08:00
Red Adaya acb3bd303b rename model to models 2024-02-08 13:37:02 +08:00
Red Adaya 3ad7feedad replace /model_old imports with /model 2024-02-08 13:34:46 +08:00
Red Adaya 24690ff931 add index.ts inside model dir 2024-02-08 09:35:52 +08:00
Red Adaya f510e1c904 cleanup connectionsview model 2024-02-08 09:23:44 +08:00
Red Adaya 35fa59aadd cleanup screenlinecontainer model 2024-02-08 09:20:30 +08:00
Red Adaya d414657252 cleanup session model 2024-02-08 09:16:02 +08:00
Red Adaya b59dd6960f cleanup screenlines model 2024-02-08 09:14:30 +08:00
Red Adaya 1ae74b767d cleanup screen model 2024-02-08 09:13:04 +08:00
Red Adaya 7fa862b402 cleanup remote model 2024-02-08 09:09:16 +08:00
Red Adaya 970c5c30fd cleanup plugins model 2024-02-08 09:07:26 +08:00
Red Adaya 2bcc8756e7 cleanup main model 2024-02-08 09:06:09 +08:00
Red Adaya 5ad26b10cd cleanup mainsidebar model 2024-02-08 09:02:31 +08:00
Red Adaya ef7acda1bb cleanup linecontainer model 2024-02-08 09:01:08 +08:00
Red Adaya 29cd754358 cleanup input model 2024-02-08 08:59:40 +08:00
Red Adaya 648d98f065 cleanup historyview model 2024-02-08 08:55:56 +08:00
Red Adaya 5770e482a1 cleanup commandrunner model 2024-02-08 08:44:01 +08:00
Red Adaya 23b3250f18 remove dayjs import from bookmarks model 2024-02-08 08:41:22 +08:00
Red Adaya b62977470b cleanup cmd model 2024-02-08 08:40:33 +08:00
Red Adaya 07f2794b1b cleanup clientsettingsview model 2024-02-08 08:37:56 +08:00
Red Adaya cf27a8baff cleanup bookmarks model 2024-02-08 08:37:17 +08:00
Red Adaya aace48d42a init 2024-02-08 08:35:30 +08:00
Red Adaya 15d02f3357 remove styles not related to Tooltip 2024-02-06 13:42:09 +08:00
Red Adaya 39d371681c remove styles not related to Toggle 2024-02-06 13:41:23 +08:00
Red Adaya 412c3ac5a2 remove styles not related to TextField 2024-02-06 13:37:15 +08:00
Red Adaya 36484621ec remove styles not related to Status 2024-02-06 13:35:15 +08:00
Red Adaya 72231ead1d SettingsError doesn't need styles cos it uses classnames in app.less 2024-02-06 13:33:42 +08:00
Red Adaya 81c1fd43f7 remove styles not related to ResizableSidebar 2024-02-06 13:31:20 +08:00
Red Adaya c9a73c2204 RemoteStatusLight no longer used. It's replaced by Status component. 2024-02-06 13:27:58 +08:00
Red Adaya 434f980b49 remove styles not related to PasswordField 2024-02-06 13:26:22 +08:00
Red Adaya 75d462764d NumberField doesn't need styles cos it extends TextField 2024-02-06 13:24:50 +08:00
Red Adaya c58c88af4e remove styles not related to modal 2024-02-06 13:23:32 +08:00
Red Adaya 05be301ea2 remove styles not related to markdown 2024-02-06 13:22:04 +08:00
Red Adaya 27e5a9154d LinkButton doesn't need styles cos it's extends Button component 2024-02-06 13:19:31 +08:00
Red Adaya a7d2148bc0 remove styles not related to InputDecoration 2024-02-06 10:28:39 +08:00
Red Adaya ead75880e1 remove styles not related to InlineSettingsTextEdit 2024-02-06 10:17:18 +08:00
Red Adaya 0bdb50cf91 fix import error 2024-02-06 10:12:32 +08:00
Red Adaya abf3448f07 InfoMessage conmponent no longer needed 2024-02-06 10:09:01 +08:00
Red Adaya 8988d26867 remove old connections 2024-02-06 09:50:57 +08:00
Red Adaya a084ca4801 IconButton doesn't need styles because it extends Button 2024-02-06 09:30:10 +08:00
Red Adaya 36e2578a03 remove styles not related to dropdown 2024-02-06 09:26:46 +08:00
Red Adaya a49487c035 renderCmdText doesn't need styles 2024-02-06 09:15:51 +08:00
Red Adaya 03296043fb remove styles not related to CmdStrCode 2024-02-06 09:10:35 +08:00
Red Adaya ec797f55ff remove styles not related to checkbox 2024-02-06 09:05:18 +08:00
Red Adaya 550461167b init 2024-02-05 23:08:59 +08:00
Red Adaya cf5d2ecddf Merge branch 'main' of github.com:wavetermdev/waveterm into split-components-in-common 2024-02-05 23:07:48 +08:00
Red Adaya c4128cd266 init 2024-02-02 23:26:33 +08:00
Red Adaya 17bb07a47d split settings modals 2024-02-02 16:50:44 +08:00
32 changed files with 988 additions and 2386 deletions
-1
View File
@@ -8,7 +8,6 @@ export const SESSION_SETTINGS = "sessionSettings";
export const LINE_SETTINGS = "lineSettings";
export const CLIENT_SETTINGS = "clientSettings";
export const TAB_SWITCHER = "tabSwitcher";
export const USER_INPUT = "userInput";
export const LineContainer_Main = "main";
export const LineContainer_History = "history";
-1
View File
@@ -5,7 +5,6 @@
margin-bottom: 10px;
font-family: @markdown-font;
font-size: 14px;
overflow-wrap: break-word;
code {
background-color: @markdown-highlight;
+1 -7
View File
@@ -60,13 +60,7 @@ class PasswordField extends TextField {
};
return (
<div
className={cn(`wave-textfield wave-password ${className || ""}`, {
focused: focused,
error: error,
"no-label": !label,
})}
>
<div className={cn(`wave-textfield wave-password ${className || ""}`, { focused: focused, error: error })}>
{decoration?.startDecoration && <>{decoration.startDecoration}</>}
<div className="wave-textfield-inner">
<label
-1
View File
@@ -9,4 +9,3 @@ export { TabSwitcherModal } from "./tabswitcher";
export { SessionSettingsModal } from "./sessionsettings";
export { ScreenSettingsModal } from "./screensettings";
export { LineSettingsModal } from "./linesettings";
export { UserInputModal } from "./userinput";
+1 -1
View File
@@ -17,7 +17,7 @@ class ModalsProvider extends React.Component {
for (let i = 0; i < store.length; i++) {
let entry = store[i];
let Comp = entry.component;
rtn.push(<Comp key={entry.uniqueKey} {...entry.props} />);
rtn.push(<Comp key={entry.uniqueKey} />);
}
return <>{rtn}</>;
}
+10 -12
View File
@@ -12,21 +12,19 @@ import {
SessionSettingsModal,
ScreenSettingsModal,
LineSettingsModal,
UserInputModal,
} from "../modals";
import * as constants from "../../appconst";
const modalsRegistry: { [key: string]: React.ComponentType } = {
[constants.ABOUT]: AboutModal,
[constants.CREATE_REMOTE]: CreateRemoteConnModal,
[constants.VIEW_REMOTE]: ViewRemoteConnDetailModal,
[constants.EDIT_REMOTE]: EditRemoteConnModal,
[constants.ALERT]: AlertModal,
[constants.SCREEN_SETTINGS]: ScreenSettingsModal,
[constants.SESSION_SETTINGS]: SessionSettingsModal,
[constants.LINE_SETTINGS]: LineSettingsModal,
[constants.TAB_SWITCHER]: TabSwitcherModal,
[constants.USER_INPUT]: UserInputModal,
const modalsRegistry: { [key: string]: () => React.ReactElement } = {
[constants.ABOUT]: () => <AboutModal />,
[constants.CREATE_REMOTE]: () => <CreateRemoteConnModal />,
[constants.VIEW_REMOTE]: () => <ViewRemoteConnDetailModal />,
[constants.EDIT_REMOTE]: () => <EditRemoteConnModal />,
[constants.ALERT]: () => <AlertModal />,
[constants.SCREEN_SETTINGS]: () => <ScreenSettingsModal />,
[constants.SESSION_SETTINGS]: () => <SessionSettingsModal />,
[constants.LINE_SETTINGS]: () => <LineSettingsModal />,
[constants.TAB_SWITCHER]: () => <TabSwitcherModal />,
};
export { modalsRegistry };
-15
View File
@@ -1,15 +0,0 @@
@import "../../../app/common/themes/themes.less";
.userinput-modal {
width: 500px;
.wave-modal-content {
.wave-modal-body {
padding: 20px 20px;
.userinput-query {
margin-bottom: 10px;
}
}
}
}
-88
View File
@@ -1,88 +0,0 @@
import * as React from "react";
import { GlobalModel } from "../../../models";
import { Choose, When, If } from "tsx-control-statements/components";
import { Modal, PasswordField, Markdown } from "../elements";
import { UserInputRequest } from "../../../types/types";
import "./userinput.less";
export const UserInputModal = (userInputRequest: UserInputRequest) => {
const [responseText, setResponseText] = React.useState("");
const [countdown, setCountdown] = React.useState(Math.floor(userInputRequest.timeoutms / 1000));
const closeModal = React.useCallback(() => {
GlobalModel.sendUserInput({
type: "userinputresp",
requestid: userInputRequest.requestid,
errormsg: "Canceled by the user",
});
GlobalModel.remotesModel.closeModal();
}, [responseText, userInputRequest]);
const handleSendText = React.useCallback(() => {
GlobalModel.sendUserInput({
type: "userinputresp",
requestid: userInputRequest.requestid,
text: responseText,
});
GlobalModel.remotesModel.closeModal();
}, [responseText, userInputRequest]);
const handleSendConfirm = React.useCallback(
(response: boolean) => {
GlobalModel.sendUserInput({
type: "userinputresp",
requestid: userInputRequest.requestid,
confirm: response,
});
GlobalModel.remotesModel.closeModal();
},
[userInputRequest]
);
React.useEffect(() => {
let timeout: ReturnType<typeof setTimeout>;
if (countdown == 0) {
timeout = setTimeout(() => {
GlobalModel.remotesModel.closeModal();
}, 300);
} else {
timeout = setTimeout(() => {
setCountdown(countdown - 1);
}, 1000);
}
return () => clearTimeout(timeout);
}, [countdown]);
return (
<Modal className="userinput-modal">
<Modal.Header onClose={closeModal} title={userInputRequest.title + ` (${countdown})`} />
<div className="wave-modal-body">
<div className="userinput-query">
<If condition={userInputRequest.markdown}>
<Markdown text={userInputRequest.querytext} />
</If>
<If condition={!userInputRequest.markdown}>{userInputRequest.querytext}</If>
</div>
<Choose>
<When condition={userInputRequest.responsetype == "text"}>
<PasswordField onChange={setResponseText} value={responseText} maxLength={400} />
</When>
</Choose>
</div>
<Choose>
<When condition={userInputRequest.responsetype == "text"}>
<Modal.Footer onCancel={closeModal} onOk={handleSendText} okLabel="Continue" />
</When>
<When condition={userInputRequest.responsetype == "confirm"}>
<Modal.Footer
onCancel={() => handleSendConfirm(false)}
onOk={() => handleSendConfirm(true)}
okLabel="Yes"
cancelLabel="No"
/>
</When>
</Choose>
</Modal>
);
};
@@ -54,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>
+15 -10
View File
@@ -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;
}
+3 -3
View File
@@ -8,14 +8,14 @@ import { modalsRegistry } from "../app/common/modals/registry";
import { OArr } from "../types/types";
class ModalsModel {
store: OArr<ModalStoreEntry> = mobx.observable.array([], { name: "ModalsModel-store", deep: false });
store: OArr<ModalStoreEntry> = mobx.observable.array([], { name: "ModalsModel-store" });
pushModal(modalId: string, props?: any) {
pushModal(modalId: string) {
const modalFactory = modalsRegistry[modalId];
if (modalFactory && !this.store.some((modal) => modal.id === modalId)) {
mobx.action(() => {
this.store.push({ id: modalId, component: modalFactory, uniqueKey: uuidv4(), props });
this.store.push({ id: modalId, component: modalFactory, uniqueKey: uuidv4() });
})();
}
}
+243 -300
View File
File diff suppressed because it is too large Load Diff
@@ -51,8 +51,6 @@ import {
HistoryViewDataType,
AlertMessageType,
HistorySearchParams,
UserInputRequest,
UserInputResponsePacket,
FocusTypeStrs,
ScreenLinesType,
HistoryTypeStrs,
@@ -3378,14 +3376,14 @@ class RemotesModel {
}
class ModalsModel {
store: OArr<T.ModalStoreEntry> = mobx.observable.array([], { name: "ModalsModel-store", deep: false });
store: OArr<T.ModalStoreEntry> = mobx.observable.array([], { name: "ModalsModel-store" });
pushModal(modalId: string, props?: any) {
pushModal(modalId: string) {
const modalFactory = modalsRegistry[modalId];
if (modalFactory && !this.store.some((modal) => modal.id === modalId)) {
mobx.action(() => {
this.store.push({ id: modalId, component: modalFactory, uniqueKey: uuidv4(), props: props });
this.store.push({ id: modalId, component: modalFactory, uniqueKey: uuidv4() });
})();
}
}
@@ -4186,10 +4184,6 @@ class Model {
this.getScreenById_single(snc.screenid)?.setNumRunningCmds(snc.num);
}
}
if ("userinputrequest" in update) {
let userInputRequest: UserInputRequest = update.userinputrequest;
this.modalsModel.pushModal(appconst.USER_INPUT, userInputRequest);
}
}
updateRemotes(remotes: RemoteType[]): void {
@@ -4597,10 +4591,6 @@ class Model {
this.ws.pushMessage(inputPacket);
}
sendUserInput(userInputResponsePacket: UserInputResponsePacket) {
this.ws.pushMessage(userInputResponsePacket);
}
sendCmdInputText(screenId: string, sp: T.StrWithPos) {
let pk: T.CmdInputTextPacketType = {
type: "cmdinputtext",
+6 -3
View File
@@ -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) => {
+1 -1
View File
@@ -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) {
+2 -2
View File
@@ -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 -57
View File
@@ -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,48 +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;
userinputrequest?: UserInputRequest;
screenstatusindicators?: ScreenStatusIndicatorUpdateType[];
screennumrunningcommands?: ScreenNumRunningCommandsUpdateType[];
};
type HistoryViewDataType = {
@@ -435,7 +414,7 @@ type ContextMenuOpts = {
showCut?: boolean;
};
type UpdateMessage = PtyDataUpdateType | ModelUpdateType[];
type UpdateMessage = PtyDataUpdateType | ModelUpdateType;
type RendererContext = {
screenId: string;
@@ -616,23 +595,6 @@ type HistorySearchParams = {
filterCmds?: boolean;
};
type UserInputRequest = {
requestid: string;
querytext: string;
responsetype: string;
title: string;
markdown: boolean;
timeoutms: number;
};
type UserInputResponsePacket = {
type: string;
requestid: string;
text?: string;
confirm?: boolean;
errormsg?: string;
};
type RenderModeType = "normal" | "collapsed" | "expanded";
type WebScreen = {
@@ -768,7 +730,6 @@ type ModalStoreEntry = {
id: string;
component: React.ComponentType;
uniqueKey: string;
props?: any;
};
type StrWithPos = {
@@ -848,8 +809,6 @@ export type {
RenderModeType,
AlertMessageType,
HistorySearchParams,
UserInputRequest,
UserInputResponsePacket,
ScreenLinesType,
FocusTypeStrs,
HistoryTypeStrs,
@@ -886,7 +845,6 @@ export type {
CmdInputTextPacketType,
OpenAICmdInfoChatMessageType,
ScreenStatusIndicatorUpdateType,
ScreenNumRunningCommandsUpdateType,
OV,
OArr,
OMap,
+69 -53
View File
@@ -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;
}
+6 -2
View File
@@ -156,12 +156,16 @@ func (p *PacketParser) trySendRpcResponse(pk PacketType) bool {
return false
}
p.Lock.Lock()
defer p.Lock.Unlock()
entry := p.RpcMap[respId]
p.Lock.Unlock()
if entry == nil {
return false
}
entry.RespCh <- respPk
// nonblocking send
select {
case entry.RespCh <- respPk:
default:
}
return true
}

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