From 452836bffc41bb80b2500e78552e224b83791ff6 Mon Sep 17 00:00:00 2001 From: Red J Adaya Date: Sun, 31 Dec 2023 14:34:05 +0800 Subject: [PATCH 01/25] Cmd-P feature -- Quick Tab Selector (#200) * register cmd+p shortcut * tab switcher modal * initial implementation * tab switcher modal content * fix styles * fix scroll bugs * set selected index when clicking option * hover effect for options * switch when Enter key is pressed * remove fuse.js * only use switchscreen for switching sessions and tabs * var naming changes * fix multiple focused options on mouse hover * fix duplicate focused options and scrollbar * clean imports * fix wrong function name * merge color styles in app.less * remove debugging code * use For component when iterating thru options * minor style fix * remove mouse interaction, keep focusedIdx in bounds, increase max number of tabs shown, small layout adjustment for big tab names (and more space for icon) --- src/app/app.less | 51 +++- src/app/app.tsx | 6 - src/app/appconst.ts | 1 + src/app/common/common.less | 8 + src/app/common/common.tsx | 29 ++- src/app/common/modals/modals.less | 83 ++++++ src/app/common/modals/modals.tsx | 315 ++++++++++++++++++++++- src/app/common/modals/modalsRegistry.tsx | 2 + src/electron/emain.ts | 13 +- src/electron/preload.js | 1 + src/model/model.ts | 14 +- src/util/util.ts | 9 + 12 files changed, 494 insertions(+), 38 deletions(-) diff --git a/src/app/app.less b/src/app/app.less index aab2875f7..52aca9d76 100644 --- a/src/app/app.less +++ b/src/app/app.less @@ -476,17 +476,26 @@ a.a-block { } } +.icon.color-default, +.icon.color-green { + path, + circle { + fill: @tab-green; + } + + i { + color: @tab-green; + } +} + .icon.color-red { path, circle { fill: @tab-red; } -} -.icon.color-green { - path, - circle { - fill: @tab-green; + i { + color: @tab-red; } } @@ -495,6 +504,10 @@ a.a-block { circle { fill: @tab-orange; } + + i { + color: @tab-orange; + } } .icon.color-blue { @@ -502,6 +515,10 @@ a.a-block { circle { fill: @tab-blue; } + + i { + color: @tab-blue; + } } .icon.color-yellow { @@ -509,6 +526,10 @@ a.a-block { circle { fill: @tab-yellow; } + + i { + color: @tab-yellow; + } } .icon.color-pink { @@ -516,6 +537,10 @@ a.a-block { circle { fill: @tab-pink; } + + i { + color: @tab-pink; + } } .icon.color-mint { @@ -523,6 +548,10 @@ a.a-block { circle { fill: @tab-mint; } + + i { + color: @tab-mint; + } } .icon.color-cyan { @@ -530,6 +559,10 @@ a.a-block { circle { fill: @tab-cyan; } + + i { + color: @tab-cyan; + } } .icon.color-violet { @@ -537,6 +570,10 @@ a.a-block { circle { fill: @tab-violet; } + + i { + color: @tab-violet; + } } .icon.color-white { @@ -544,6 +581,10 @@ a.a-block { circle { fill: @tab-white; } + + i { + color: @tab-white; + } } .status-icon.status-connected { diff --git a/src/app/app.tsx b/src/app/app.tsx index 7b67a4cda..690b6f088 100644 --- a/src/app/app.tsx +++ b/src/app/app.tsx @@ -16,12 +16,6 @@ import { PluginsView } from "./pluginsview/pluginsview"; import { BookmarksView } from "./bookmarks/bookmarks"; import { HistoryView } from "./history/history"; import { ConnectionsView } from "./connections/connections"; -import { - ScreenSettingsModal, - SessionSettingsModal, - LineSettingsModal, - ClientSettingsModal, -} from "./common/modals/settings"; import { MainSideBar } from "./sidebar/sidebar"; import { DisconnectedModal, ClientStopModal, ModalsProvider } from "./common/modals/modals"; import { ErrorBoundary } from "./common/error/errorboundary"; diff --git a/src/app/appconst.ts b/src/app/appconst.ts index 172bbf984..aa4c29a08 100644 --- a/src/app/appconst.ts +++ b/src/app/appconst.ts @@ -7,6 +7,7 @@ export const SCREEN_SETTINGS = "screenSettings"; export const SESSION_SETTINGS = "sessionSettings"; export const LINE_SETTINGS = "lineSettings"; export const CLIENT_SETTINGS = "clientSettings"; +export const TAB_SWITCHER = "tabSwitcher"; export const LineContainer_Main = "main"; export const LineContainer_History = "history"; diff --git a/src/app/common/common.less b/src/app/common/common.less index e4a46ae0a..8b4b832a5 100644 --- a/src/app/common/common.less +++ b/src/app/common/common.less @@ -837,6 +837,14 @@ } } } + + &.no-label { + height: 34px; + + input { + height: 32px; + } + } } .wave-input-decoration { diff --git a/src/app/common/common.tsx b/src/app/common/common.tsx index 87dbcccea..c6042382e 100644 --- a/src/app/common/common.tsx +++ b/src/app/common/common.tsx @@ -332,7 +332,7 @@ interface TextFieldDecorationProps { endDecoration?: React.ReactNode; } interface TextFieldProps { - label: string; + label?: string; value?: string; className?: string; onChange?: (value: string) => void; @@ -445,10 +445,11 @@ class TextField extends React.Component { return (
{ > {decoration?.startDecoration && <>{decoration.startDecoration}}
- + + + + {props.children} ); @@ -1141,7 +1144,7 @@ class Modal extends React.Component { } render() { - return ReactDOM.createPortal(this.renderModal(), document.getElementById("app") ); + return ReactDOM.createPortal(this.renderModal(), document.getElementById("app")); } } diff --git a/src/app/common/modals/modals.less b/src/app/common/modals/modals.less index 3bdd24c47..f40745397 100644 --- a/src/app/common/modals/modals.less +++ b/src/app/common/modals/modals.less @@ -453,6 +453,89 @@ } } +.tabswitcher-modal { + width: 452px; + min-height: 384px; + + .wave-modal-content { + .wave-modal-body { + display: flex; + padding: 0px; + flex-direction: column; + align-items: flex-start; + align-self: stretch; + width: 100%; + + .textfield-wrapper { + padding: 20px 20px 0px; + + .wave-input-decoration.start-position { + height: 100%; + + .tabswitcher-search-prefix { + opacity: 0.5; + font-size: 13px; + } + } + } + + .list-container { + overflow: hidden; + padding: 10px 0 20px; + width: 100%; + } + + .list-container-inner { + width: 100%; + max-height: 300px; + overflow-y: scroll; + padding: 0 16px 0 20px; + + &::-webkit-scrollbar-thumb { + display: none; + } + + &:hover::-webkit-scrollbar-thumb { + display: block; + } + + .options-list { + width: 100%; + + .search-option { + padding: 5px 5px 5px 8px; + display: flex; + align-items: center; + border: 1px solid transparent; + width: 100%; + overflow: hidden; + + div.tabname { + flex-grow: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + padding-right: 5px; + } + + div.icon { + flex-shrink: 0; + width: 20px; + margin-right: 6px; + } + } + + .focused-option { + border: 1px solid rgba(241, 246, 243, 0.15); + border-radius: 4px; + background: rgba(255, 255, 255, 0.06); + } + } + } + } + } +} + .screen-settings-tooltip .wave-tooltip-icon { i { font-size: 13px; diff --git a/src/app/common/modals/modals.tsx b/src/app/common/modals/modals.tsx index 19f273768..bbf1df332 100644 --- a/src/app/common/modals/modals.tsx +++ b/src/app/common/modals/modals.tsx @@ -27,6 +27,8 @@ import { import * as util from "../../../util/util"; import * as textmeasure from "../../../util/textmeasure"; import { ClientDataType } from "../../../types/types"; +import { Session, Screen } from "../../../model/model"; +import { ReactComponent as SquareIcon } from "../../assets/icons/tab/square.svg"; import { ReactComponent as WarningIcon } from "../../assets/icons/line/triangle-exclamation.svg"; import shield from "../../assets/icons/shield_check.svg"; @@ -42,6 +44,7 @@ const VERSION = __WAVETERM_VERSION__; let BUILD = __WAVETERM_BUILD__; type OV = mobx.IObservableValue; +type OArr = mobx.IObservableArray; const RemotePtyRows = 9; const RemotePtyCols = 80; @@ -1090,7 +1093,7 @@ class ViewRemoteConnDetailModal extends React.Component<{}, {}> {
- {getName(remote)}  {getImportTooltip(remote)} + {util.getRemoteName(remote)}  {getImportTooltip(remote)}
{this.renderHeaderBtns(remote)}
@@ -1343,7 +1346,7 @@ class EditRemoteConnModal extends React.Component<{}, {}> {
-
{getName(this.selectedRemote)}
+
{util.getRemoteName(this.selectedRemote)}
{ } } -const getName = (remote: T.RemoteType): string => { - if (remote == null) { - return ""; - } - const { remotealias, remotecanonicalname } = remote; - return remotealias ? `${remotealias} [${remotecanonicalname}]` : remotecanonicalname; +type SwitcherDataType = { + sessionId: string; + sessionName: string; + sessionIdx: number; + screenId: string; + screenIdx: number; + screenName: string; + icon: string; + color: string; }; +const MaxOptionsToDisplay = 100; + +@mobxReact.observer +class TabSwitcherModal extends React.Component<{}, {}> { + screens: Map>[]; + sessions: Map>[]; + options: SwitcherDataType[] = []; + sOptions: OArr = mobx.observable.array(null, { + name: "TabSwitcherModal-sOptions", + }); + focusedIdx: OV = mobx.observable.box(0, { name: "TabSwitcherModal-selectedIdx" }); + activeSessionIdx: number; + optionRefs = []; + listWrapperRef = React.createRef(); + prevFocusedIdx = 0; + + componentDidMount() { + this.activeSessionIdx = GlobalModel.getActiveSession().sessionIdx.get(); + let oSessions = GlobalModel.sessionList; + let oScreens = GlobalModel.screenMap; + oScreens.forEach((oScreen) => { + // Find the matching session in the observable array + let foundSession = oSessions.find((s) => { + if (s.sessionId === oScreen.sessionId && s.archived.get() == false) { + return true; + } + return false; + }); + + if (foundSession) { + let data: SwitcherDataType = { + sessionName: foundSession.name.get(), + sessionId: foundSession.sessionId, + sessionIdx: foundSession.sessionIdx.get(), + screenName: oScreen.name.get(), + screenId: oScreen.screenId, + screenIdx: oScreen.screenIdx.get(), + icon: this.getTabIcon(oScreen), + color: this.getTabColor(oScreen), + }; + this.options.push(data); + } + }); + + mobx.action(() => { + this.sOptions.replace(this.sortOptions(this.options).slice(0, MaxOptionsToDisplay)); + })(); + + document.addEventListener("keydown", this.handleKeyDown); + } + + componentWillUnmount() { + document.removeEventListener("keydown", this.handleKeyDown); + } + + componentDidUpdate() { + let currFocusedIdx = this.focusedIdx.get(); + + // Check if selectedIdx has changed + if (currFocusedIdx !== this.prevFocusedIdx) { + let optionElement = this.optionRefs[currFocusedIdx]?.current; + + if (optionElement) { + optionElement.scrollIntoView({ block: "nearest" }); + } + + // Update prevFocusedIdx for the next update cycle + this.prevFocusedIdx = currFocusedIdx; + } + if (currFocusedIdx >= this.sOptions.length && this.sOptions.length > 0) { + this.setFocusedIndex(this.sOptions.length - 1); + } + } + + @boundMethod + getTabIcon(screen: Screen): string { + let tabIcon = "default"; + let screenOpts = screen.opts.get(); + if (screenOpts != null && !util.isBlank(screenOpts.tabicon)) { + tabIcon = screenOpts.tabicon; + } + return tabIcon; + } + + @boundMethod + getTabColor(screen: Screen): string { + let tabColor = "default"; + let screenOpts = screen.opts.get(); + if (screenOpts != null && !util.isBlank(screenOpts.tabcolor)) { + tabColor = screenOpts.tabcolor; + } + return tabColor; + } + + @boundMethod + handleKeyDown(e) { + if (e.key === "Escape") { + this.closeModal(); + } else if (e.key === "ArrowUp" || e.key === "ArrowDown") { + e.preventDefault(); + let newIndex = this.calculateNewIndex(e.key === "ArrowUp"); + this.setFocusedIndex(newIndex); + } else if (e.key === "Enter") { + e.preventDefault(); + this.handleSelect(this.focusedIdx.get()); + } + } + + @boundMethod + calculateNewIndex(isUpKey) { + let currentIndex = this.focusedIdx.get(); + if (isUpKey) { + return Math.max(currentIndex - 1, 0); + } else { + return Math.min(currentIndex + 1, this.sOptions.length - 1); + } + } + + @boundMethod + setFocusedIndex(index) { + mobx.action(() => { + this.focusedIdx.set(index); + })(); + } + + @boundMethod + closeModal(): void { + GlobalModel.modalsModel.popModal(); + } + + @boundMethod + handleSelect(index: number): void { + const selectedOption = this.sOptions[index]; + if (selectedOption) { + GlobalCommandRunner.switchScreen(selectedOption.screenId, selectedOption.sessionId); + this.closeModal(); + } + } + + @boundMethod + handleSearch(val: string): void { + let sOptions: SwitcherDataType[]; + if (val == "") { + sOptions = this.sortOptions(this.options).slice(0, MaxOptionsToDisplay); + } else { + sOptions = this.filterOptions(val); + sOptions = this.sortOptions(sOptions); + if (sOptions.length > MaxOptionsToDisplay) { + sOptions = sOptions.slice(0, MaxOptionsToDisplay); + } + } + mobx.action(() => { + this.sOptions.replace(sOptions); + this.focusedIdx.set(0); + })(); + } + + @mobx.computed + @boundMethod + filterOptions(searchInput: string): SwitcherDataType[] { + let filteredScreens = []; + + for (let i = 0; i < this.options.length; i++) { + let tab = this.options[i]; + let match = false; + + if (searchInput.includes("/")) { + let [sessionFilter, screenFilter] = searchInput.split("/").map((s) => s.trim().toLowerCase()); + match = + tab.sessionName.toLowerCase().includes(sessionFilter) && + tab.screenName.toLowerCase().includes(screenFilter); + } else { + match = + tab.sessionName.toLowerCase().includes(searchInput) || + tab.screenName.toLowerCase().includes(searchInput); + } + + // Add tab to filtered list if it matches the criteria + if (match) { + filteredScreens.push(tab); + } + } + + return filteredScreens; + } + + @mobx.computed + @boundMethod + sortOptions(options: SwitcherDataType[]): SwitcherDataType[] { + return options.sort((a, b) => { + let aInCurrentSession = a.sessionIdx === this.activeSessionIdx; + let bInCurrentSession = b.sessionIdx === this.activeSessionIdx; + + // Tabs in the current session are sorted by screenIdx + if (aInCurrentSession && bInCurrentSession) { + return a.screenIdx - b.screenIdx; + } + // a is in the current session and b is not, so a comes first + else if (aInCurrentSession) { + return -1; + } + // b is in the current session and a is not, so b comes first + else if (bInCurrentSession) { + return 1; + } + // Both are in different, non-current sessions - sort by sessionIdx and then by screenIdx + else { + if (a.sessionIdx === b.sessionIdx) { + return a.screenIdx - b.screenIdx; + } else { + return a.sessionIdx - b.sessionIdx; + } + } + }); + } + + @boundMethod + renderIcon(option: SwitcherDataType): React.ReactNode { + let tabIcon = option.icon; + if (tabIcon === "default" || tabIcon === "square") { + return ; + } + return ; + } + + @boundMethod + renderOption(option: SwitcherDataType, index: number): JSX.Element { + if (!this.optionRefs[index]) { + this.optionRefs[index] = React.createRef(); + } + return ( +
this.handleSelect(index)} + > +
{this.renderIcon(option)}
+
+ #{option.sessionName} / {option.screenName} +
+
+ ); + } + + render() { + let option: SwitcherDataType; + let index: number; + return ( + +
+
+ +
Switch to Tab:
+ + ), + endDecoration: ( + + } + > + + + + ), + }} + /> +
+
+
+
+ + {this.renderOption(option, index)} + +
+
+
+
+
+ ); + } +} + const getImportTooltip = (remote: T.RemoteType): React.ReactElement => { if (remote.sshconfigsrc == "sshconfig-import") { return ( @@ -1493,4 +1791,5 @@ export { ViewRemoteConnDetailModal, EditRemoteConnModal, ModalsProvider, + TabSwitcherModal, }; diff --git a/src/app/common/modals/modalsRegistry.tsx b/src/app/common/modals/modalsRegistry.tsx index 833d99d40..36cedf7e5 100644 --- a/src/app/common/modals/modalsRegistry.tsx +++ b/src/app/common/modals/modalsRegistry.tsx @@ -8,6 +8,7 @@ import { ViewRemoteConnDetailModal, EditRemoteConnModal, AlertModal, + TabSwitcherModal, } from "./modals"; import { ScreenSettingsModal, SessionSettingsModal, LineSettingsModal, ClientSettingsModal } from "./settings"; import * as constants from "../../appconst"; @@ -22,6 +23,7 @@ const modalsRegistry: { [key: string]: () => React.ReactElement } = { [constants.SESSION_SETTINGS]: () => , [constants.LINE_SETTINGS]: () => , [constants.CLIENT_SETTINGS]: () => , + [constants.TAB_SWITCHER]: () => , }; export { modalsRegistry }; diff --git a/src/electron/emain.ts b/src/electron/emain.ts index d3066d488..d4819add6 100644 --- a/src/electron/emain.ts +++ b/src/electron/emain.ts @@ -173,10 +173,10 @@ let menuTemplate = [ role: "appMenu", submenu: [ { - label: 'About Wave Terminal', + label: "About Wave Terminal", click: () => { - MainWindow?.webContents.send('menu-item-about'); - } + MainWindow?.webContents.send("menu-item-about"); + }, }, { type: "separator" }, { role: "services" }, @@ -250,7 +250,7 @@ function createMainWindow(clientData) { minWidth: 800, minHeight: 600, transparent: true, - icon: (unamePlatform == "linux") ? "public/logos/wave-logo-dark.png" : undefined, + icon: unamePlatform == "linux" ? "public/logos/wave-logo-dark.png" : undefined, webPreferences: { preload: path.join(getAppBasePath(), DistDir, "preload.js"), }, @@ -302,6 +302,11 @@ function createMainWindow(clientData) { e.preventDefault(); return; } + if (input.code == "KeyP" && input.meta) { + win.webContents.send("p-cmd", mods); + e.preventDefault(); + return; + } if (input.meta && (input.code == "ArrowUp" || input.code == "ArrowDown")) { if (input.code == "ArrowUp") { win.webContents.send("meta-arrowup"); diff --git a/src/electron/preload.js b/src/electron/preload.js index 2b07a1e97..6dc8f108c 100644 --- a/src/electron/preload.js +++ b/src/electron/preload.js @@ -13,6 +13,7 @@ contextBridge.exposeInMainWorld("api", { onLCmd: (callback) => ipcRenderer.on("l-cmd", callback), onHCmd: (callback) => ipcRenderer.on("h-cmd", callback), onWCmd: (callback) => ipcRenderer.on("w-cmd", callback), + onPCmd: (callback) => ipcRenderer.on("p-cmd", callback), onMetaArrowUp: (callback) => ipcRenderer.on("meta-arrowup", callback), onMetaArrowDown: (callback) => ipcRenderer.on("meta-arrowdown", callback), onMetaPageUp: (callback) => ipcRenderer.on("meta-pageup", callback), diff --git a/src/model/model.ts b/src/model/model.ts index aeebc4240..a4cec535a 100644 --- a/src/model/model.ts +++ b/src/model/model.ts @@ -197,6 +197,7 @@ type ElectronApi = { onICmd: (callback: (mods: KeyModsType) => void) => void; onLCmd: (callback: (mods: KeyModsType) => void) => void; onHCmd: (callback: (mods: KeyModsType) => void) => void; + onPCmd: (callback: (mods: KeyModsType) => void) => void; onMenuItemAbout: (callback: () => void) => void; onMetaArrowUp: (callback: () => void) => void; onMetaArrowDown: (callback: () => void) => void; @@ -3207,6 +3208,7 @@ class Model { getApi().onICmd(this.onICmd.bind(this)); getApi().onLCmd(this.onLCmd.bind(this)); getApi().onHCmd(this.onHCmd.bind(this)); + getApi().onPCmd(this.onPCmd.bind(this)); getApi().onMenuItemAbout(this.onMenuItemAbout.bind(this)); getApi().onMetaArrowUp(this.onMetaArrowUp.bind(this)); getApi().onMetaArrowDown(this.onMetaArrowDown.bind(this)); @@ -3535,6 +3537,10 @@ class Model { GlobalModel.historyViewModel.reSearch(); } + onPCmd(e: any, mods: KeyModsType) { + GlobalModel.modalsModel.pushModal(appconst.TAB_SWITCHER); + } + getFocusedLine(): LineFocusType { if (this.inputModel.hasFocus()) { return { cmdInputFocus: true }; @@ -4268,11 +4274,15 @@ class CommandRunner { GlobalModel.submitCommand("session", null, [session], { nohist: "1" }, false); } - switchScreen(screen: string) { + switchScreen(screen: string, session?: string) { mobx.action(() => { GlobalModel.activeMainView.set("session"); })(); - GlobalModel.submitCommand("screen", null, [screen], { nohist: "1" }, false); + let kwargs = { nohist: "1" }; + if (session != null) { + kwargs["session"] = session; + } + GlobalModel.submitCommand("screen", null, [screen], kwargs, false); } lineView(sessionId: string, screenId: string, lineNum?: number) { diff --git a/src/util/util.ts b/src/util/util.ts index 252ba3c63..b5d9ee62f 100644 --- a/src/util/util.ts +++ b/src/util/util.ts @@ -404,6 +404,14 @@ function commandRtnHandler(prtn: Promise, errorMessage: OV Date: Sun, 31 Dec 2023 14:42:46 +0800 Subject: [PATCH 02/25] fix tabs scrollbar jump (#203) --- src/app/workspace/screen/tabs.less | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/app/workspace/screen/tabs.less b/src/app/workspace/screen/tabs.less index 20dfb0630..c22bad162 100644 --- a/src/app/workspace/screen/tabs.less +++ b/src/app/workspace/screen/tabs.less @@ -244,11 +244,15 @@ display: flex; flex-direction: row; align-items: center; - overflow-x: hidden; + overflow-x: scroll; - &:hover, - &:focus { - overflow-x: overlay; + &::-webkit-scrollbar-thumb, + &::-webkit-scrollbar-track { + display: none; + } + + &:hover::-webkit-scrollbar-thumb { + display: block; } .screen-tab { @@ -321,6 +325,7 @@ cursor: pointer; display: flex; align-items: center; + height: 37px; .icon { height: 2rem; From d1319c0a2c40ba868481830f298cebb48f7432cc Mon Sep 17 00:00:00 2001 From: Sylvie Crowe <107814465+oneirocosm@users.noreply.github.com> Date: Sat, 30 Dec 2023 22:52:30 -0800 Subject: [PATCH 03/25] Fix Commands that Require Quoted Paths (#198) * fix commands that require quoted paths Several commands did not wrap the path in quotes which caused problems when attempting to store the waveterm installation in a place that had a space in the path. This corrects this in the particular case where the username does not have spaces but the path to the executable does. Note: the case of a user name having spaces has not been tested but likely does not work. * fix logging problem for wavesrv A previous fix replaced the getWaveSrvCmd with getWaveSrvPath. This needs to be getWaveSrvCmd to enable logging. * fix variable name --- src/electron/emain.ts | 13 +++++++------ wavesrv/pkg/remote/remote.go | 5 +++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/electron/emain.ts b/src/electron/emain.ts index d4819add6..c31d3912c 100644 --- a/src/electron/emain.ts +++ b/src/electron/emain.ts @@ -140,7 +140,7 @@ function getWaveSrvCmd() { let waveSrvPath = getWaveSrvPath(); let waveHome = getWaveHomeDir(); let logFile = path.join(waveHome, "wavesrv.log"); - return `${waveSrvPath} >> "${logFile}" 2>&1`; + return `"${waveSrvPath}" >> "${logFile}" 2>&1`; } function getWaveSrvCwd() { @@ -540,8 +540,8 @@ function sendWSSC() { } function runWaveSrv() { - let pResolve = null; - let pReject = null; + let pResolve: (value: unknown) => void; + let pReject: (reason?: any) => void; let rtnPromise = new Promise((argResolve, argReject) => { pResolve = argResolve; pReject = argReject; @@ -551,8 +551,9 @@ function runWaveSrv() { if (isDev) { envCopy[WaveDevVarName] = "1"; } - console.log("trying to run local server", getWaveSrvPath()); - let proc = child_process.spawn("bash", ["-c", getWaveSrvCmd()], { + let waveSrvCmd = getWaveSrvCmd(); + console.log("trying to run local server", waveSrvCmd); + let proc = child_process.spawn("bash", ["-c", waveSrvCmd], { cwd: getWaveSrvCwd(), env: envCopy, }); @@ -560,7 +561,7 @@ function runWaveSrv() { console.log("wavesrv exit", e); waveSrvProc = null; sendWSSC(); - pReject(new Error(sprintf("failed to start local server (%s)", getWaveSrvPath()))); + pReject(new Error(sprintf("failed to start local server (%s)", waveSrvCmd))); if (waveSrvShouldRestart) { waveSrvShouldRestart = false; this.runWaveSrv(); diff --git a/wavesrv/pkg/remote/remote.go b/wavesrv/pkg/remote/remote.go index 7b6b5cbf7..145920962 100644 --- a/wavesrv/pkg/remote/remote.go +++ b/wavesrv/pkg/remote/remote.go @@ -21,6 +21,7 @@ import ( "syscall" "time" + "github.com/alessio/shellescape" "github.com/armon/circbuf" "github.com/creack/pty" "github.com/google/uuid" @@ -66,9 +67,9 @@ func MakeLocalMShellCommandStr(isSudo bool) (string, error) { return "", err } if isSudo { - return fmt.Sprintf(`%s; sudo %s --server`, PrintPingPacket, mshellPath), nil + return fmt.Sprintf(`%s; sudo %s --server`, PrintPingPacket, shellescape.Quote(mshellPath)), nil } else { - return fmt.Sprintf(`%s; %s --server`, PrintPingPacket, mshellPath), nil + return fmt.Sprintf(`%s; %s --server`, PrintPingPacket, shellescape.Quote(mshellPath)), nil } } From b2a1bb3818f0ddc2cacc23ecac38954e867e0928 Mon Sep 17 00:00:00 2001 From: Red J Adaya Date: Fri, 5 Jan 2024 02:13:40 +0800 Subject: [PATCH 04/25] When client is disconnected change log to show last 50 lines of wavesrv.log (#210) * improved disconnected modal * wrap pre with div * make number of a lines param a constant * revert app.tsx * use tail command and capture the output instead * reset TabSwitcherModal --- src/app/app.tsx | 1 - src/app/common/common.tsx | 10 ++-- src/app/common/modals/modals.less | 52 ++++++++++++----- src/app/common/modals/modals.tsx | 95 ++++++++++++++++--------------- src/electron/emain.ts | 27 +++++++++ src/electron/preload.js | 4 ++ src/model/model.ts | 5 ++ 7 files changed, 128 insertions(+), 66 deletions(-) diff --git a/src/app/app.tsx b/src/app/app.tsx index 690b6f088..374cf232a 100644 --- a/src/app/app.tsx +++ b/src/app/app.tsx @@ -68,7 +68,6 @@ class App extends React.Component<{}, {}> { } render() { - let clientSettingsModal = GlobalModel.clientSettingsModal.get(); let remotesModel = GlobalModel.remotesModel; let disconnected = !GlobalModel.ws.open.get() || !GlobalModel.waveSrvRunning.get(); let hasClientStop = GlobalModel.getHasClientStop(); diff --git a/src/app/common/common.tsx b/src/app/common/common.tsx index c6042382e..0f263a8ad 100644 --- a/src/app/common/common.tsx +++ b/src/app/common/common.tsx @@ -1085,16 +1085,18 @@ class Dropdown extends React.Component { } interface ModalHeaderProps { - onClose: () => void; + onClose?: () => void; title: string; } const ModalHeader: React.FC = ({ onClose, title }) => (
{
{title}
} - - - + + + + +
); diff --git a/src/app/common/modals/modals.less b/src/app/common/modals/modals.less index f40745397..7a8744183 100644 --- a/src/app/common/modals/modals.less +++ b/src/app/common/modals/modals.less @@ -17,24 +17,46 @@ } .disconnected-modal { - .modal-content { - footer { - .footer-text-link { - color: @term-white; - cursor: pointer; + .wave-modal-content { + .wave-modal-body { + padding: 0; + + .modal-content { + footer { + .footer-text-link { + color: @term-white; + cursor: pointer; + } + } + } + + .inner-content { + .log { + height: 335px; + margin-bottom: 20px; + overflow: auto; + + &::-webkit-scrollbar-track, + &::-webkit-scrollbar-thumb, + &::-webkit-scrollbar-corner { + display: none; + } + + &:hover::-webkit-scrollbar-thumb { + display: block; + } + + pre { + color: @term-white; + background-color: @term-black; + } + } } } - } - .inner-content { - .ws-log { - padding: 5px; - background-color: @term-black; - height: 250px; - overflow: auto; - - .ws-logline { - color: @term-white; + .wave-modal-footer { + button:first-child { + color: @term-green; } } } diff --git a/src/app/common/modals/modals.tsx b/src/app/common/modals/modals.tsx index bbf1df332..f19c4cb0a 100644 --- a/src/app/common/modals/modals.tsx +++ b/src/app/common/modals/modals.tsx @@ -27,10 +27,9 @@ import { import * as util from "../../../util/util"; import * as textmeasure from "../../../util/textmeasure"; import { ClientDataType } from "../../../types/types"; -import { Session, Screen } from "../../../model/model"; +import { Screen } from "../../../model/model"; import { ReactComponent as SquareIcon } from "../../assets/icons/tab/square.svg"; -import { ReactComponent as WarningIcon } from "../../assets/icons/line/triangle-exclamation.svg"; import shield from "../../assets/icons/shield_check.svg"; import help from "../../assets/icons/help_filled.svg"; import github from "../../assets/icons/github.svg"; @@ -48,6 +47,7 @@ type OArr = mobx.IObservableArray; const RemotePtyRows = 9; const RemotePtyCols = 80; +const NumOfLines = 50; const PasswordUnchangedSentinel = "--unchanged--"; @mobxReact.observer @@ -70,7 +70,8 @@ class ModalsProvider extends React.Component { @mobxReact.observer class DisconnectedModal extends React.Component<{}, {}> { logRef: any = React.createRef(); - showLog: mobx.IObservableValue = mobx.observable.box(false); + logs: mobx.IObservableValue = mobx.observable.box(""); + logInterval: NodeJS.Timeout = null; @boundMethod restartServer() { @@ -83,8 +84,16 @@ class DisconnectedModal extends React.Component<{}, {}> { } componentDidMount() { - if (this.logRef.current != null) { - this.logRef.current.scrollTop = this.logRef.current.scrollHeight; + this.fetchLogs(); + + this.logInterval = setInterval(() => { + this.fetchLogs(); + }, 5000); + } + + componentWillUnmount() { + if (this.logInterval) { + clearInterval(this.logInterval); } } @@ -94,58 +103,52 @@ class DisconnectedModal extends React.Component<{}, {}> { } } - @boundMethod - handleShowLog(): void { - mobx.action(() => { - this.showLog.set(!this.showLog.get()); - })(); + fetchLogs() { + GlobalModel.getLastLogs( + NumOfLines, + mobx.action((logs) => { + this.logs.set(logs); + if (this.logRef.current != null) { + this.logRef.current.scrollTop = this.logRef.current.scrollHeight; + } + }) + ); } render() { - let model = GlobalModel; - let logLine: string = null; - let idx: number = 0; return ( -
-
-
-
-
Wave Client Disconnected
-
- + + +
+
-
- -
- {logLine} -
-
+
+
{this.logs.get()}
- -
-
- - Show Log - - - Hide Log - -
-
-
+
+
+ - - + } + > + Try Reconnect + +
-
+ ); } } diff --git a/src/electron/emain.ts b/src/electron/emain.ts index c31d3912c..4f4602fa6 100644 --- a/src/electron/emain.ts +++ b/src/electron/emain.ts @@ -485,6 +485,33 @@ electron.ipcMain.on("reload-window", (event) => { return; }); +electron.ipcMain.on("get-last-logs", async (event, numberOfLines) => { + try { + const logPath = path.join(getWaveHomeDir(), "wavesrv.log"); + const lastLines = await readLastLinesOfFile(logPath, numberOfLines); + event.reply("last-logs", lastLines); + } catch (err) { + console.error("Error reading log file:", err); + event.reply("last-logs", "Error reading log file."); + } +}); + +function readLastLinesOfFile(filePath, lineCount) { + return new Promise((resolve, reject) => { + child_process.exec(`tail -n ${lineCount} "${filePath}"`, (err, stdout, stderr) => { + if (err) { + reject(err.message); + return; + } + if (stderr) { + reject(stderr); + return; + } + resolve(stdout); + }); + }); +} + function getContextMenu(): any { let menu = new electron.Menu(); let menuItem = new electron.MenuItem({ label: "Testing", click: () => console.log("click testing!") }); diff --git a/src/electron/preload.js b/src/electron/preload.js index 6dc8f108c..1abe03611 100644 --- a/src/electron/preload.js +++ b/src/electron/preload.js @@ -6,6 +6,10 @@ contextBridge.exposeInMainWorld("api", { getIsDev: () => ipcRenderer.sendSync("get-isdev"), getAuthKey: () => ipcRenderer.sendSync("get-authkey"), getWaveSrvStatus: () => ipcRenderer.sendSync("wavesrv-status"), + getLastLogs: (numberOfLines, callback) => { + ipcRenderer.send("get-last-logs", numberOfLines); + ipcRenderer.once("last-logs", (event, data) => callback(data)); + }, restartWaveSrv: () => ipcRenderer.sendSync("restart-server"), reloadWindow: () => ipcRenderer.sendSync("reload-window"), onTCmd: (callback) => ipcRenderer.on("t-cmd", callback), diff --git a/src/model/model.ts b/src/model/model.ts index a4cec535a..4ba81bd19 100644 --- a/src/model/model.ts +++ b/src/model/model.ts @@ -208,6 +208,7 @@ type ElectronApi = { contextScreen: (screenOpts: { screenId: string }, position: { x: number; y: number }) => void; contextEditMenu: (position: { x: number; y: number }, opts: ContextMenuOpts) => void; onWaveSrvStatusChange: (callback: (status: boolean, pid: number) => void) => void; + getLastLogs: (numOfLines: number, callback: (logs: any) => void) => void; }; function getApi(): ElectronApi { @@ -3476,6 +3477,10 @@ class Model { })(); } + getLastLogs(numbOfLines: number, cb: (logs: any) => void): void { + getApi().getLastLogs(numbOfLines, cb); + } + getContentHeight(context: RendererContext): number { let key = context.screenId + "/" + context.lineId; return this.termUsedRowsCache[key]; From 8cbee1e1c3ab7f667193033064cf2480b912a809 Mon Sep 17 00:00:00 2001 From: Sylvie Crowe <107814465+oneirocosm@users.noreply.github.com> Date: Thu, 4 Jan 2024 10:16:26 -0800 Subject: [PATCH 05/25] Allow dots in alias and add port to canonical name (#209) * allow numerical start and allow dots in ssh alias We previously restricted the ssh alias to start with an alphabetic character and did not allow dots within it. This caused problems with users wanting to use an ip address as an alias. This lifts that restriction so both can freely be used. Note that while it is common to use the hostname as the alias, hostnames are not allowed to use the underscore character. However, we do allow the alias to contain an underscore. I do not think we can remove this from aliases now but it is something to watch out for in the future. * allow backslash in username This involved converting the regexp string into a raw string to able to use the backslash character. this is important. * Revert "allow backslash in username" This reverts commit cafe2812411cfba15b7ece1250a6def29d092366. Upon reflection, more time is needed to evaluate that this actually corrects the issue. It will be performed with proper diligence at a later time. * add port to end of canoncial names when not 22 The canonical name is the identifying key in the database, so it causes problems if another remote entry has the same canonical name. By adding the port number to the end of this, it is possible to differentiate the two. * add db migrations for adding port to canonicalname The up migration adds the port to the existing canonical id if it exists and is not 22. The down migration strips the port off the canonical name and deletes extra remotes with the same canonical name. If all remotes with that canonical name have been archived, it keeps the first one added to the database. If any have not been archived, it keeps the first added to the database from the non-archived group. * remove ability to edit port number via ssh import Previously, ssh imports could edit the port number since it was possible to change them in the config file without changin the canonical name. Now that the canonical name contains the port, a change in the port will simply create a new database entry. For this reason, the ability to modify the ssh port is dead code and has been removed. * allow backslash in username This involved converting the regexp string into a raw string to able to use the backslash character. this is important. * simplify up migration logic The previous up migration was suboptimal because it was accounting for a corner case not found in production. That case no longer needs to be considered, so the procedure was simplified. --- .../db/migrations/000029_canonicalport.down.sql | 12 ++++++++++++ wavesrv/db/migrations/000029_canonicalport.up.sql | 3 +++ wavesrv/pkg/cmdrunner/cmdrunner.go | 15 +++++++-------- wavesrv/pkg/sstore/dbops.go | 5 ----- wavesrv/pkg/sstore/migrate.go | 2 +- 5 files changed, 23 insertions(+), 14 deletions(-) create mode 100644 wavesrv/db/migrations/000029_canonicalport.down.sql create mode 100644 wavesrv/db/migrations/000029_canonicalport.up.sql diff --git a/wavesrv/db/migrations/000029_canonicalport.down.sql b/wavesrv/db/migrations/000029_canonicalport.down.sql new file mode 100644 index 000000000..35cf4fcd2 --- /dev/null +++ b/wavesrv/db/migrations/000029_canonicalport.down.sql @@ -0,0 +1,12 @@ +UPDATE remote +SET remotecanonicalname = SUBSTR(remotecanonicalname, 1, INSTR(remotecanonicalname, ':') - 1) +WHERE INSTR(remotecanonicalname, ':'); + +DELETE FROM remote +WHERE remoteid NOT IN ( + SELECT remoteid FROM ( + SELECT MIN(archived), remoteid, remotecanonicalname + FROM remote + GROUP BY remotecanonicalname + ) +); \ No newline at end of file diff --git a/wavesrv/db/migrations/000029_canonicalport.up.sql b/wavesrv/db/migrations/000029_canonicalport.up.sql new file mode 100644 index 000000000..085e1640a --- /dev/null +++ b/wavesrv/db/migrations/000029_canonicalport.up.sql @@ -0,0 +1,3 @@ +UPDATE remote +SET remotecanonicalname = remotecanonicalname || COALESCE( ":" || json_extract(sshopts, '$.sshport'), "") +WHERE json_extract(sshopts, '$.sshport') != 22; \ No newline at end of file diff --git a/wavesrv/pkg/cmdrunner/cmdrunner.go b/wavesrv/pkg/cmdrunner/cmdrunner.go index b7d94d201..d0af9581b 100644 --- a/wavesrv/pkg/cmdrunner/cmdrunner.go +++ b/wavesrv/pkg/cmdrunner/cmdrunner.go @@ -115,8 +115,8 @@ var SetVarScopes = []SetVarScope{ {ScopeName: "remote", VarNames: []string{}}, } -var userHostRe = regexp.MustCompile("^(sudo@)?([a-z][a-z0-9._@-]*)@([a-z0-9][a-z0-9.-]*)(?::([0-9]+))?$") -var remoteAliasRe = regexp.MustCompile("^[a-zA-Z][a-zA-Z0-9_-]*$") +var userHostRe = regexp.MustCompile(`^(sudo@)?([a-z][a-z0-9._@\\-]*)@([a-z0-9][a-z0-9.-]*)(?::([0-9]+))?$`) +var remoteAliasRe = regexp.MustCompile("^[a-zA-Z0-9][a-zA-Z0-9._-]*$") var genericNameRe = regexp.MustCompile("^[a-zA-Z][a-zA-Z0-9_ .()<>,/\"'\\[\\]{}=+$@!*-]*$") var rendererRe = regexp.MustCompile("^[a-zA-Z][a-zA-Z0-9_.:-]*$") var positionRe = regexp.MustCompile("^((S?\\+|E?-)?[0-9]+|(\\+|-|S|E))$") @@ -1257,6 +1257,9 @@ func parseRemoteEditArgs(isNew bool, pk *scpacket.FeCommandPacketType, isLocal b } sshOpts.SSHPort = portVal canonicalName = remoteUser + "@" + remoteHost + if portVal != 0 && portVal != 22 { + canonicalName = canonicalName + ":" + strconv.Itoa(portVal) + } if isSudo { canonicalName = "sudo@" + canonicalName } @@ -1528,7 +1531,8 @@ func NewHostInfo(hostName string) (*HostInfoType, error) { portStr, _ := ssh_config.GetStrict(hostName, "Port") var portVal int - if portStr != "" { + if portStr != "" && portStr != "22" { + canonicalName = canonicalName + ":" + portStr var err error portVal, err = strconv.Atoi(portStr) if err != nil { @@ -1539,7 +1543,6 @@ func NewHostInfo(hostName string) (*HostInfoType, error) { return nil, fmt.Errorf("could not parse port \"%d\": number is not valid for a port\n", portVal) } } - identityFile, _ := ssh_config.GetStrict(hostName, "IdentityFile") passwordAuth, _ := ssh_config.GetStrict(hostName, "PasswordAuthentication") @@ -1626,13 +1629,9 @@ func RemoteConfigParseCommand(ctx context.Context, pk *scpacket.FeCommandPacketT if previouslyImportedRemote != nil && !previouslyImportedRemote.Archived { // this already existed and was created via import // it needs to be updated instead of created - editMap := make(map[string]interface{}) editMap[sstore.RemoteField_Alias] = hostInfo.Host editMap[sstore.RemoteField_ConnectMode] = hostInfo.ConnectMode - // changing port is unique to imports because it lets us avoid conflicts - // if the port is changed in the ssh config - editMap[sstore.RemoteField_SSHPort] = hostInfo.Port if hostInfo.SshKeyFile != "" { editMap[sstore.RemoteField_SSHKey] = hostInfo.SshKeyFile } diff --git a/wavesrv/pkg/sstore/dbops.go b/wavesrv/pkg/sstore/dbops.go index 2ccb0d66e..1f0dbd421 100644 --- a/wavesrv/pkg/sstore/dbops.go +++ b/wavesrv/pkg/sstore/dbops.go @@ -1704,7 +1704,6 @@ const ( RemoteField_ConnectMode = "connectmode" // string RemoteField_SSHKey = "sshkey" // string RemoteField_SSHPassword = "sshpassword" // string - RemoteField_SSHPort = "sshport" // string RemoteField_Color = "color" // string ) @@ -1736,10 +1735,6 @@ func UpdateRemote(ctx context.Context, remoteId string, editMap map[string]inter query = `UPDATE remote SET sshopts = json_set(sshopts, '$.sshpassword', ?) WHERE remoteid = ?` tx.Exec(query, sshPassword, remoteId) } - if sshPort, found := editMap[RemoteField_SSHPort]; found { - query = `UPDATE remote SET sshopts = json_set(sshopts, '$.sshport', ?) WHERE remoteid = ?` - tx.Exec(query, sshPort, remoteId) - } if color, found := editMap[RemoteField_Color]; found { query = `UPDATE remote SET remoteopts = json_set(remoteopts, '$.color', ?) WHERE remoteid = ?` tx.Exec(query, color, remoteId) diff --git a/wavesrv/pkg/sstore/migrate.go b/wavesrv/pkg/sstore/migrate.go index 91253a01f..8e46cdcba 100644 --- a/wavesrv/pkg/sstore/migrate.go +++ b/wavesrv/pkg/sstore/migrate.go @@ -22,7 +22,7 @@ import ( "github.com/golang-migrate/migrate/v4" ) -const MaxMigration = 28 +const MaxMigration = 29 const MigratePrimaryScreenVersion = 9 const CmdScreenSpecialMigration = 13 const CmdLineSpecialMigration = 20 From f737c2af864cc711ccfe7578cd2306e39382461b Mon Sep 17 00:00:00 2001 From: sawka Date: Sun, 7 Jan 2024 00:30:25 -0800 Subject: [PATCH 06/25] add autofocus prop to button --- src/app/common/common.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/app/common/common.tsx b/src/app/common/common.tsx index 0f263a8ad..3e271b577 100644 --- a/src/app/common/common.tsx +++ b/src/app/common/common.tsx @@ -231,6 +231,7 @@ interface ButtonProps { rightIcon?: React.ReactNode; color?: string; style?: React.CSSProperties; + autoFocus?: boolean; } class Button extends React.Component { @@ -257,6 +258,7 @@ class Button extends React.Component { onClick={this.handleClick} disabled={disabled} style={style} + autoFocus={this.props.autoFocus} > {leftIcon && {leftIcon}} {children} From 7f91efc3141c857f49d986f78152c591cc95e131 Mon Sep 17 00:00:00 2001 From: Mike Sawka Date: Sun, 7 Jan 2024 23:48:10 -0800 Subject: [PATCH 07/25] working on a macos x86 build workflow (#216) must check in to main to test --- .github/workflows/build-macos-x86.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .github/workflows/build-macos-x86.yml diff --git a/.github/workflows/build-macos-x86.yml b/.github/workflows/build-macos-x86.yml new file mode 100644 index 000000000..bb766733e --- /dev/null +++ b/.github/workflows/build-macos-x86.yml @@ -0,0 +1,17 @@ +name: "Build MacOS x86" +on: workflow_dispatch +jobs: + runbuild: + name: "Build MacOS x86" + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v4 + with: + go-version: '1.21.5' + - run: brew tap scripthaus-dev/scripthaus + - run: brew install scripthaus + - run: yarn --frozen-lockfile + - run: scripthaus run build-package + + From ed1dff320d8bd2683bd4789b9f945827078c78ec Mon Sep 17 00:00:00 2001 From: sawka Date: Sun, 7 Jan 2024 23:58:46 -0800 Subject: [PATCH 08/25] upload build artifact --- .github/workflows/build-macos-x86.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/build-macos-x86.yml b/.github/workflows/build-macos-x86.yml index bb766733e..f8d0cbaa7 100644 --- a/.github/workflows/build-macos-x86.yml +++ b/.github/workflows/build-macos-x86.yml @@ -1,5 +1,7 @@ name: "Build MacOS x86" on: workflow_dispatch +env: + WAVETERM_VERSION: 0.5.3 jobs: runbuild: name: "Build MacOS x86" @@ -13,5 +15,10 @@ jobs: - run: brew install scripthaus - run: yarn --frozen-lockfile - run: scripthaus run build-package + - uses: actions/upload-artifact@v3 + with: + name: waveterm-build-darwin-x86 + path: out/make/zip/darwin/x86/*.zip + retention_days: 2 From 5bd7f737468bb2171e39f5185d787ea3112cc9dd Mon Sep 17 00:00:00 2001 From: sawka Date: Mon, 8 Jan 2024 00:12:07 -0800 Subject: [PATCH 09/25] updates to build workflow --- .../{build-macos-x86.yml => build-macos-x64.yml} | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) rename .github/workflows/{build-macos-x86.yml => build-macos-x64.yml} (61%) diff --git a/.github/workflows/build-macos-x86.yml b/.github/workflows/build-macos-x64.yml similarity index 61% rename from .github/workflows/build-macos-x86.yml rename to .github/workflows/build-macos-x64.yml index f8d0cbaa7..b081579c9 100644 --- a/.github/workflows/build-macos-x86.yml +++ b/.github/workflows/build-macos-x64.yml @@ -1,10 +1,10 @@ -name: "Build MacOS x86" +name: "Build MacOS x64" on: workflow_dispatch env: WAVETERM_VERSION: 0.5.3 jobs: runbuild: - name: "Build MacOS x86" + name: "Build MacOS x64" runs-on: macos-latest steps: - uses: actions/checkout@v4 @@ -13,12 +13,16 @@ jobs: go-version: '1.21.5' - run: brew tap scripthaus-dev/scripthaus - run: brew install scripthaus + - uses: actions/setup-node@v4 + with: + node-version: '21.5.0' + cache: 'yarn' - run: yarn --frozen-lockfile - run: scripthaus run build-package - uses: actions/upload-artifact@v3 with: - name: waveterm-build-darwin-x86 - path: out/make/zip/darwin/x86/*.zip - retention_days: 2 + name: waveterm-build-darwin-x64 + path: out/make/zip/darwin/x64/*.zip + retention-days: 2 From 631a0867aa2fda6e8633bc5402fc2f3c222dab5d Mon Sep 17 00:00:00 2001 From: sawka Date: Mon, 8 Jan 2024 00:28:54 -0800 Subject: [PATCH 10/25] fix go cache dependency --- .github/workflows/build-macos-x64.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/build-macos-x64.yml b/.github/workflows/build-macos-x64.yml index b081579c9..76f5ef0ac 100644 --- a/.github/workflows/build-macos-x64.yml +++ b/.github/workflows/build-macos-x64.yml @@ -11,6 +11,9 @@ jobs: - uses: actions/setup-go@v4 with: go-version: '1.21.5' + cache-dependency-path: | + wavesrv/go.sum + waveshell/go.sum - run: brew tap scripthaus-dev/scripthaus - run: brew install scripthaus - uses: actions/setup-node@v4 From 0bb80b6a74e1d48343195791969561760ac24e86 Mon Sep 17 00:00:00 2001 From: sawka Date: Mon, 8 Jan 2024 00:35:38 -0800 Subject: [PATCH 11/25] run both mac builds --- .github/workflows/build-macos-x64.yml | 32 ++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-macos-x64.yml b/.github/workflows/build-macos-x64.yml index 76f5ef0ac..948413ee9 100644 --- a/.github/workflows/build-macos-x64.yml +++ b/.github/workflows/build-macos-x64.yml @@ -2,15 +2,17 @@ name: "Build MacOS x64" on: workflow_dispatch env: WAVETERM_VERSION: 0.5.3 + GO_VERSION: '1.21.5' + NODE_VERSION: '21.5.0' jobs: - runbuild: + runbuild-x64: name: "Build MacOS x64" runs-on: macos-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v4 with: - go-version: '1.21.5' + go-version: ${{env.GO_VERSION}} cache-dependency-path: | wavesrv/go.sum waveshell/go.sum @@ -18,7 +20,7 @@ jobs: - run: brew install scripthaus - uses: actions/setup-node@v4 with: - node-version: '21.5.0' + node-version: ${{env.NODE_VERSION}} cache: 'yarn' - run: yarn --frozen-lockfile - run: scripthaus run build-package @@ -27,5 +29,29 @@ jobs: name: waveterm-build-darwin-x64 path: out/make/zip/darwin/x64/*.zip retention-days: 2 + runbuild-arm64: + name: "Build MacOS arm64" + runs-on: macos-latest-xlarge + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v4 + with: + go-version: ${{env.GO_VERSION}} + cache-dependency-path: | + wavesrv/go.sum + waveshell/go.sum + - run: brew tap scripthaus-dev/scripthaus + - run: brew install scripthaus + - uses: actions/setup-node@v4 + with: + node-version: ${{env.NODE_VERSION}} + cache: 'yarn' + - run: yarn --frozen-lockfile + - run: scripthaus run build-package + - uses: actions/upload-artifact@v3 + with: + name: waveterm-build-darwin-arm64 + path: out/make/zip/darwin/arm64/*.zip + retention-days: 2 From e1e5b67ff613d713bca596769a7b34429b73e39e Mon Sep 17 00:00:00 2001 From: Sylvie Crowe <107814465+oneirocosm@users.noreply.github.com> Date: Mon, 8 Jan 2024 18:31:17 -0800 Subject: [PATCH 12/25] I18n fixes (#211) * remove byte sanitization for user commands When serializing jsonBytes in packet.go::MarshalPacket, a step existed that attempted to manually sanitize the bytes before sending them. This was initially done to avoid invalid characters in json; however, go should handle this for us. But this sanitization broke internationalization because it excluded characters required for unicode in other languages. Because of that, it has been removed. * properly decode non-ascii on frontend The functions atob and btoa do not convert base 64 to strings in the expected way. The base64ToArray function handles it properly but other cases do not. These other cases have been replaced with a helper function that makes use of the base64-js package. This package has already been included as a dependency of another package we use, but it was added to the package.json file to make the inclusion explicit. * automatically set/share LANG var with waveshell Waveterm previously did not set the LANG environment variable which caused problems for international users. On Linux, this is done automatically, but it needs to be done manually on macos. Even on linux, the wavesrv LANG variable is shared with waveshell to ensure the same one is used on remotes. * only set the lang var if not previously set In order to prevent waveterm from overriding the lang var entirely, this ensures that it is only manually determined if it hasn't previously been set. * use envMap instead of os to determine var This is slightly more performant and relies more directly on our code instead of external code. --- package.json | 1 + src/model/model.ts | 10 ++++++---- src/util/util.ts | 34 +++++++++++++--------------------- waveshell/pkg/packet/packet.go | 9 --------- wavesrv/pkg/remote/remote.go | 3 +++ wavesrv/pkg/scbase/scbase.go | 27 +++++++++++++++++++++++++++ 6 files changed, 50 insertions(+), 34 deletions(-) diff --git a/package.json b/package.json index 7253204e9..66db33ea3 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "@tanstack/react-table": "^8.10.3", "@types/semver": "^7.5.6", "autobind-decorator": "^2.4.0", + "base64-js": "^1.5.1", "classnames": "^2.3.1", "dayjs": "^1.11.3", "dompurify": "^3.0.2", diff --git a/src/model/model.ts b/src/model/model.ts index 4ba81bd19..ce2d49a88 100644 --- a/src/model/model.ts +++ b/src/model/model.ts @@ -9,6 +9,8 @@ import { boundMethod } from "autobind-decorator"; import { debounce } from "throttle-debounce"; import { handleJsonFetchResponse, + base64ToString, + stringToBase64, base64ToArray, genMergeData, genMergeDataMap, @@ -336,7 +338,7 @@ class Cmd { type: "feinput", ck: this.screenId + "/" + this.lineId, remote: this.remote, - inputdata64: btoa(data), + inputdata64: stringToBase64(data), }; GlobalModel.sendInputPacket(inputPacket); } @@ -2866,7 +2868,7 @@ class RemotesModalModel { let inputPacket: RemoteInputPacketType = { type: "remoteinput", remoteid: remoteId, - inputdata64: btoa(event.key), + inputdata64: stringToBase64(event.key), }; GlobalModel.sendInputPacket(inputPacket); } @@ -3045,7 +3047,7 @@ class RemotesModel { let inputPacket: RemoteInputPacketType = { type: "remoteinput", remoteid: remoteId, - inputdata64: btoa(event.key), + inputdata64: stringToBase64(event.key), }; GlobalModel.sendInputPacket(inputPacket); } @@ -4201,7 +4203,7 @@ class Model { return resp.text() as any; } contentType = resp.headers.get("Content-Type"); - fileInfo = JSON.parse(atob(resp.headers.get("X-FileInfo"))); + fileInfo = JSON.parse(base64ToString(resp.headers.get("X-FileInfo"))); return resp.blob(); }) .then((blobOrText: any) => { diff --git a/src/util/util.ts b/src/util/util.ts index b5d9ee62f..b4b80ef19 100644 --- a/src/util/util.ts +++ b/src/util/util.ts @@ -6,6 +6,7 @@ import { sprintf } from "sprintf-js"; import dayjs from "dayjs"; import localizedFormat from "dayjs/plugin/localizedFormat"; import type { RemoteType, CommandRtnType } from "../types/types"; +import base64 from "base64-js"; type OV = mobx.IObservableValue; @@ -70,6 +71,16 @@ function handleJsonFetchResponse(url: URL, resp: any): Promise { return rtnData; } +function base64ToString(b64: string): string { + let stringBytes = base64.toByteArray(b64) + return new TextDecoder().decode(stringBytes) +} + +function stringToBase64(input: string): string { + let 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)); @@ -229,26 +240,6 @@ function genMergeDataMap, DataType extends ID return rtn; } -function parseEnv0(envStr64: string): Map { - let envStr = atob(envStr64); - let parts = envStr.split("\x00"); - let rtn: Map = new Map(); - for (let i = 0; i < parts.length; i++) { - let part = parts[i]; - if (part == "") { - continue; - } - let eqIdx = part.indexOf("="); - if (eqIdx == -1) { - continue; - } - let varName = part.substr(0, eqIdx); - let varVal = part.substr(eqIdx + 1); - rtn.set(varName, varVal); - } - return rtn; -} - function boundInt(ival: number, minVal: number, maxVal: number): number { if (ival < minVal) { return minVal; @@ -414,11 +405,12 @@ function getRemoteName(remote: RemoteType): string { export { handleJsonFetchResponse, + base64ToString, + stringToBase64, base64ToArray, genMergeData, genMergeDataMap, genMergeSimpleData, - parseEnv0, boundInt, isModKeyPress, incObs, diff --git a/waveshell/pkg/packet/packet.go b/waveshell/pkg/packet/packet.go index c2dec0500..f75030558 100644 --- a/waveshell/pkg/packet/packet.go +++ b/waveshell/pkg/packet/packet.go @@ -927,14 +927,6 @@ func ParseJsonPacket(jsonBuf []byte) (PacketType, error) { return pk, nil } -func sanitizeBytes(buf []byte) { - for idx, b := range buf { - if b >= 127 || (b < 32 && b != 10 && b != 13) { - buf[idx] = '?' - } - } -} - type SendError struct { IsWriteError bool // fatal IsMarshalError bool // not fatal @@ -970,7 +962,6 @@ func MarshalPacket(packet PacketType) ([]byte, error) { outBuf.Write(jsonBytes) outBuf.WriteByte('\n') outBytes := outBuf.Bytes() - sanitizeBytes(outBytes) return outBytes, nil } diff --git a/wavesrv/pkg/remote/remote.go b/wavesrv/pkg/remote/remote.go index 145920962..786597db0 100644 --- a/wavesrv/pkg/remote/remote.go +++ b/wavesrv/pkg/remote/remote.go @@ -1126,6 +1126,9 @@ func addScVarsToState(state *packet.ShellState) *packet.ShellState { envMap := shexec.DeclMapFromState(&rtn) envMap["PROMPT"] = &shexec.DeclareDeclType{Name: "PROMPT", Value: "1", Args: "x"} envMap["PROMPT_VERSION"] = &shexec.DeclareDeclType{Name: "PROMPT_VERSION", Value: scbase.WaveVersion, Args: "x"} + if _, exists := envMap["LANG"]; !exists { + envMap["LANG"] = &shexec.DeclareDeclType{Name: "LANG", Value: scbase.DetermineLang(), Args: "x"} + } rtn.ShellVars = shexec.SerializeDeclMap(envMap) return &rtn } diff --git a/wavesrv/pkg/scbase/scbase.go b/wavesrv/pkg/scbase/scbase.go index 2b064cdff..84643ef72 100644 --- a/wavesrv/pkg/scbase/scbase.go +++ b/wavesrv/pkg/scbase/scbase.go @@ -377,3 +377,30 @@ func MacOSRelease() string { }) return osRelease } + +var osLangOnce = &sync.Once{} +var osLang string + +func determineLang() string { + ctx, cancelFn := context.WithTimeout(context.Background(), 2*time.Second) + defer cancelFn() + if runtime.GOOS == "darwin" { + out, err := exec.CommandContext(ctx, "defaults", "read", "-g", "AppleLocale").CombinedOutput() + if err != nil { + log.Printf("error executing 'defaults read -g AppleLocale': %v\n", err) + return "" + } + return strings.TrimSpace(string(out)) + ".UTF-8" + } else { + // this is specifically to get the wavesrv LANG so waveshell + // on a remote uses the same LANG + return os.Getenv("LANG") + } +} + +func DetermineLang() string { + osLangOnce.Do(func() { + osLang = determineLang() + }) + return osLang +} From f6a60686747d35354691d8ec09543500113d61eb Mon Sep 17 00:00:00 2001 From: Red J Adaya Date: Tue, 9 Jan 2024 14:56:49 +0800 Subject: [PATCH 13/25] Connection Screen Terminal "Flash" Making it Impossible to Enter Manual Passwords (#217) * fix flashing view modal * cleanup * fix name typo, also unset setRecentConnAdded once the modal is open --- src/app/common/modals/modals.tsx | 38 +++++++++++++++++++------------- src/model/model.ts | 10 ++++++--- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/src/app/common/modals/modals.tsx b/src/app/common/modals/modals.tsx index f19c4cb0a..7b15fda7c 100644 --- a/src/app/common/modals/modals.tsx +++ b/src/app/common/modals/modals.tsx @@ -558,26 +558,33 @@ class CreateRemoteConnModal extends React.Component<{}, {}> { kwargs["connectmode"] = this.tempConnectMode.get(); kwargs["visual"] = "1"; kwargs["submit"] = "1"; - let model = this.model; let prtn = GlobalCommandRunner.createRemote(cname, kwargs, false); prtn.then((crtn) => { if (crtn.success) { + this.model.setRecentConnAdded(true); + this.model.closeModal(); + let crRtn = GlobalCommandRunner.screenSetRemote(cname, true, false); crRtn.then((crcrtn) => { if (crcrtn.success) { return; } mobx.action(() => { - this.errorStr.set(crcrtn.error ?? null); + this.errorStr.set(crcrtn.error); })(); }); return; } mobx.action(() => { - this.errorStr.set(crtn.error ?? null); + this.errorStr.set(crtn.error); })(); }); - model.seRecentConnAdded(true); + } + + @boundMethod + handleClose(): void { + this.model.closeModal(); + this.model.setRecentConnAdded(false); } @boundMethod @@ -795,7 +802,7 @@ class CreateRemoteConnModal extends React.Component<{}, {}> {
Error: {this.getErrorStr()}
- +
); } @@ -812,7 +819,7 @@ class ViewRemoteConnDetailModal extends React.Component<{}, {}> { } @mobx.computed - get selectedRemote(): T.RemoteType { + getSelectedRemote(): T.RemoteType { const selectedRemoteId = this.model.selectedRemoteId.get(); return GlobalModel.getRemote(selectedRemoteId); } @@ -827,7 +834,7 @@ class ViewRemoteConnDetailModal extends React.Component<{}, {}> { } componentDidUpdate() { - if (this.selectedRemote == null || this.selectedRemote.archived) { + if (this.getSelectedRemote() == null || this.getSelectedRemote().archived) { this.model.deSelectRemote(); } } @@ -891,7 +898,7 @@ class ViewRemoteConnDetailModal extends React.Component<{}, {}> { @boundMethod clickArchive(): void { - if (this.selectedRemote && this.selectedRemote.status == "connected") { + if (this.getSelectedRemote() && this.getSelectedRemote().status == "connected") { GlobalModel.showAlert({ message: "Cannot delete when connected. Disconnect and try again." }); return; } @@ -903,21 +910,22 @@ class ViewRemoteConnDetailModal extends React.Component<{}, {}> { if (!confirm) { return; } - if (this.selectedRemote) { - GlobalCommandRunner.archiveRemote(this.selectedRemote.remoteid); + if (this.getSelectedRemote()) { + GlobalCommandRunner.archiveRemote(this.getSelectedRemote().remoteid); } + GlobalModel.modalsModel.popModal(); }); } @boundMethod clickReinstall(): void { - GlobalCommandRunner.installRemote(this.selectedRemote?.remoteid); + GlobalCommandRunner.installRemote(this.getSelectedRemote().remoteid); } @boundMethod handleClose(): void { this.model.closeModal(); - this.model.seRecentConnAdded(false); + this.model.setRecentConnAdded(false); } renderInstallStatus(remote: T.RemoteType): any { @@ -1078,7 +1086,7 @@ class ViewRemoteConnDetailModal extends React.Component<{}, {}> { } render() { - let remote = this.selectedRemote; + let remote = this.getSelectedRemote(); if (remote == null) { return null; @@ -1092,7 +1100,7 @@ class ViewRemoteConnDetailModal extends React.Component<{}, {}> { return ( - +
@@ -1167,7 +1175,7 @@ class ViewRemoteConnDetailModal extends React.Component<{}, {}> {
- +
); } diff --git a/src/model/model.ts b/src/model/model.ts index ce2d49a88..323f6db84 100644 --- a/src/model/model.ts +++ b/src/model/model.ts @@ -2926,8 +2926,11 @@ class RemotesModel { return this.recentConnAddedState.get(); } - seRecentConnAdded(value: boolean) { - this.recentConnAddedState.set(value); + @boundMethod + setRecentConnAdded(value: boolean) { + mobx.action(() => { + this.recentConnAddedState.set(value); + })(); } deSelectRemote(): void { @@ -2939,6 +2942,7 @@ class RemotesModel { openReadModal(remoteId: string): void { mobx.action(() => { + this.setRecentConnAdded(false); this.selectedRemoteId.set(remoteId); this.remoteEdit.set(null); GlobalModel.modalsModel.pushModal(appconst.VIEW_REMOTE); @@ -3724,8 +3728,8 @@ class Model { 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 && update.remotes.length && this.remotesModel.recentConnAddedState.get()) { - GlobalModel.remotesModel.closeModal(); GlobalModel.remotesModel.openReadModal(update.remotes![0].remoteid); } } From 8ac1943d5625dba4802809b8871f29b605c78061 Mon Sep 17 00:00:00 2001 From: Mike Sawka Date: Mon, 8 Jan 2024 22:58:32 -0800 Subject: [PATCH 14/25] Add Icon / HotKey to Delete Line (Cmd-D) (#214) * work on cmd-d to delete a selected line * call stoppropagation when code.tsx captures keyboard input * finish up with line delete. add a trash icon to line. prevent delete when cmd is running (show error msg) --- src/app/common/modals/modals.less | 4 ++++ src/app/common/modals/settings.tsx | 17 ++++++++------ src/app/line/linecomps.tsx | 9 ++++++++ src/model/model.ts | 37 +++++++++++++++++++++++++++++- src/plugins/code/code.tsx | 16 ++++++++----- wavesrv/pkg/cmdrunner/cmdrunner.go | 7 +++++- wavesrv/pkg/sstore/dbops.go | 27 +++++++++++++++++++--- 7 files changed, 99 insertions(+), 18 deletions(-) diff --git a/src/app/common/modals/modals.less b/src/app/common/modals/modals.less index 7a8744183..3dcf8e4ad 100644 --- a/src/app/common/modals/modals.less +++ b/src/app/common/modals/modals.less @@ -596,6 +596,10 @@ gap: 4px; align-self: stretch; width: 100%; + + .settings-input .hotkey { + color: @text-secondary; + } } } } diff --git a/src/app/common/modals/settings.tsx b/src/app/common/modals/settings.tsx index bceca6cd8..e02117eb3 100644 --- a/src/app/common/modals/settings.tsx +++ b/src/app/common/modals/settings.tsx @@ -17,7 +17,16 @@ import { Screen, Session, } from "../../../model/model"; -import { Toggle, InlineSettingsTextEdit, SettingsError, InfoMessage, Modal, Dropdown, Tooltip } from "../common"; +import { + Toggle, + InlineSettingsTextEdit, + SettingsError, + InfoMessage, + Modal, + Dropdown, + Tooltip, + Button, +} from "../common"; import { LineType, RendererPluginType, ClientDataType, CommandRtnType, RemoteType } from "../../../types/types"; import { PluginModel } from "../../../plugins/plugins"; import * as util from "../../../util/util"; @@ -632,12 +641,6 @@ class LineSettingsModal extends React.Component<{}, {}> { />
-
-
Archived
-
- -
-
diff --git a/src/app/line/linecomps.tsx b/src/app/line/linecomps.tsx index e0732f17d..5cd1b618a 100644 --- a/src/app/line/linecomps.tsx +++ b/src/app/line/linecomps.tsx @@ -354,6 +354,12 @@ class LineCmd extends React.Component< GlobalCommandRunner.lineBookmark(line.lineid); } + @boundMethod + clickDelete() { + let { line } = this.props; + GlobalCommandRunner.lineDelete(line.lineid, true); + } + @boundMethod clickMinimize() { mobx.action(() => { @@ -659,6 +665,9 @@ class LineCmd extends React.Component< {this.renderMeta1(cmd)} {this.renderCmdText(cmd)}
+
+ +
{ + return GlobalModel.submitCommand("line", "delete", [lineArg], { nohist: "1" }, interactive); + } + lineSet(lineArg: string, opts: { renderer?: string }): Promise { let kwargs = { nohist: "1" }; if ("renderer" in opts) { diff --git a/src/plugins/code/code.tsx b/src/plugins/code/code.tsx index 24fc305c1..172bb45df 100644 --- a/src/plugins/code/code.tsx +++ b/src/plugins/code/code.tsx @@ -3,7 +3,8 @@ import * as React from "react"; import * as T from "../../types/types"; -import Editor from "@monaco-editor/react"; +import Editor, { Monaco } from "@monaco-editor/react"; +import type * as MonacoTypes from "monaco-editor/esm/vs/editor/editor.api"; import { Markdown } from "../../app/common/common"; import { GlobalModel, GlobalCommandRunner } from "../../model/model"; import Split from "react-split-it"; @@ -146,21 +147,24 @@ class SourceCodeRenderer extends React.Component< } }; - handleEditorDidMount = (editor, monaco) => { + handleEditorDidMount = (editor: MonacoTypes.editor.IStandaloneCodeEditor, monaco: Monaco) => { this.monacoEditor = editor; this.setInitialLanguage(editor); this.setEditorHeight(); - editor.onKeyDown((e) => { - if (e.code === "KeyS" && (e.ctrlKey || e.metaKey) && this.state.isSave) { + editor.onKeyDown((e: MonacoTypes.IKeyboardEvent) => { + if (e.code === "KeyS" && e.metaKey && this.state.isSave) { e.preventDefault(); + e.stopPropagation(); this.doSave(); } - if (e.code === "KeyD" && (e.ctrlKey || e.metaKey)) { + if (e.code === "KeyD" && e.metaKey) { e.preventDefault(); + e.stopPropagation(); this.doClose(); } - if (e.code === "KeyP" && (e.ctrlKey || e.metaKey)) { + if (e.code === "KeyP" && e.metaKey) { e.preventDefault(); + e.stopPropagation(); this.togglePreview(); } }); diff --git a/wavesrv/pkg/cmdrunner/cmdrunner.go b/wavesrv/pkg/cmdrunner/cmdrunner.go index d0af9581b..7ce5f5432 100644 --- a/wavesrv/pkg/cmdrunner/cmdrunner.go +++ b/wavesrv/pkg/cmdrunner/cmdrunner.go @@ -3440,7 +3440,7 @@ func LineDeleteCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (s } err = sstore.DeleteLinesByIds(ctx, ids.ScreenId, lineIds) if err != nil { - return nil, fmt.Errorf("/line:delete error purging lines: %v", err) + return nil, fmt.Errorf("/line:delete error deleting lines: %v", err) } update := &sstore.ModelUpdate{} for _, lineId := range lineIds { @@ -3451,6 +3451,11 @@ func LineDeleteCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (s } update.Lines = append(update.Lines, lineObj) } + 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} return update, nil } diff --git a/wavesrv/pkg/sstore/dbops.go b/wavesrv/pkg/sstore/dbops.go index 1f0dbd421..d2653cca5 100644 --- a/wavesrv/pkg/sstore/dbops.go +++ b/wavesrv/pkg/sstore/dbops.go @@ -2039,6 +2039,29 @@ func SetLineArchivedById(ctx context.Context, screenId string, lineId string, ar return txErr } +// returns updated screen (only if updated) +func FixupScreenSelectedLine(ctx context.Context, screenId string) (*ScreenType, error) { + return WithTxRtn(ctx, func(tx *TxWrap) (*ScreenType, error) { + query := `SELECT selectedline FROM screen WHERE screenid = ?` + sline := tx.GetInt(query, screenId) + query = `SELECT linenum FROM line WHERE screenid = ? AND linenum = ?` + if tx.Exists(query, screenId, sline) { + // selected line is valid + return nil, nil + } + query = `SELECT min(linenum) FROM line WHERE screenid = ? AND linenum > ?` + newSLine := tx.GetInt(query, screenId, sline) + if newSLine == 0 { + query = `SELECT max(linenum) FROM line WHERE screenid = ? AND linenum < ?` + newSLine = tx.GetInt(query, screenId, sline) + } + // newSLine might be 0, but that's ok (because that means there are no lines) + query = `UPDATE screen SET selectedline = ? WHERE screenid = ?` + tx.Exec(query, newSLine, screenId) + return GetScreenById(tx.Context(), screenId) + }) +} + func DeleteLinesByIds(ctx context.Context, screenId string, lineIds []string) error { txErr := WithTx(ctx, func(tx *TxWrap) error { isWS := isWebShare(tx, screenId) @@ -2046,9 +2069,8 @@ func DeleteLinesByIds(ctx context.Context, screenId string, lineIds []string) er query := `SELECT status FROM cmd WHERE screenid = ? AND lineid = ?` cmdStatus := tx.GetString(query, screenId, lineId) if cmdStatus == CmdStatusRunning { - return fmt.Errorf("cannot delete line[%s:%s], cmd is running", screenId, lineId) + return fmt.Errorf("cannot delete line[%s], cmd is running", lineId) } - query = `DELETE FROM line WHERE screenid = ? AND lineid = ?` tx.Exec(query, screenId, lineId) query = `DELETE FROM cmd WHERE screenid = ? AND lineid = ?` @@ -2056,7 +2078,6 @@ func DeleteLinesByIds(ctx context.Context, screenId string, lineIds []string) er // don't delete history anymore, just remove lineid reference query = `UPDATE history SET lineid = '', linenum = 0 WHERE screenid = ? AND lineid = ?` tx.Exec(query, screenId, lineId) - if isWS { insertScreenLineUpdate(tx, screenId, lineId, UpdateType_LineDel) } From fad48b0d0980576c2621472c27f05f8e09366918 Mon Sep 17 00:00:00 2001 From: Mike Sawka Date: Mon, 8 Jan 2024 22:59:17 -0800 Subject: [PATCH 15/25] bind cmd-w to delete a screen (with a confirm message). also fix 'esc' so it closes the alert modal with a 'cancel' (#215) --- src/app/common/modals/modals.tsx | 4 ++-- src/app/common/modals/settings.tsx | 4 ++-- src/model/model.ts | 23 +++++++++++++++++++++-- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/app/common/modals/modals.tsx b/src/app/common/modals/modals.tsx index 7b15fda7c..7d995d736 100644 --- a/src/app/common/modals/modals.tsx +++ b/src/app/common/modals/modals.tsx @@ -235,10 +235,10 @@ class AlertModal extends React.Component<{}, {}> { - + - +
diff --git a/src/app/common/modals/settings.tsx b/src/app/common/modals/settings.tsx index e02117eb3..3718a8389 100644 --- a/src/app/common/modals/settings.tsx +++ b/src/app/common/modals/settings.tsx @@ -228,7 +228,7 @@ class ScreenSettingsModal extends React.Component<{}, {}> { return; } if (this.screen.getScreenLines().lines.length == 0) { - GlobalCommandRunner.screenDelete(this.screenId); + GlobalCommandRunner.screenDelete(this.screenId, false); GlobalModel.modalsModel.popModal(); return; } @@ -238,7 +238,7 @@ class ScreenSettingsModal extends React.Component<{}, {}> { if (!result) { return; } - let prtn = GlobalCommandRunner.screenDelete(this.screenId); + let prtn = GlobalCommandRunner.screenDelete(this.screenId, false); commandRtnHandler(prtn, this.errorMessage); GlobalModel.modalsModel.popModal(); }); diff --git a/src/model/model.ts b/src/model/model.ts index a85f9724e..8a8cb7fa7 100644 --- a/src/model/model.ts +++ b/src/model/model.ts @@ -200,6 +200,7 @@ type ElectronApi = { onLCmd: (callback: (mods: KeyModsType) => void) => void; onHCmd: (callback: (mods: KeyModsType) => void) => void; onPCmd: (callback: (mods: KeyModsType) => void) => void; + onWCmd: (callback: (mods: KeyModsType) => void) => void; onMenuItemAbout: (callback: () => void) => void; onMetaArrowUp: (callback: () => void) => void; onMetaArrowDown: (callback: () => void) => void; @@ -3216,6 +3217,7 @@ class Model { getApi().onLCmd(this.onLCmd.bind(this)); getApi().onHCmd(this.onHCmd.bind(this)); getApi().onPCmd(this.onPCmd.bind(this)); + getApi().onWCmd(this.onWCmd.bind(this)); getApi().onMenuItemAbout(this.onMenuItemAbout.bind(this)); getApi().onMetaArrowUp(this.onMetaArrowUp.bind(this)); getApi().onMetaArrowDown(this.onMetaArrowDown.bind(this)); @@ -3460,6 +3462,23 @@ class Model { return true; } + onWCmd(e: any, mods: KeyModsType) { + let activeScreen = this.getActiveScreen(); + if (activeScreen == null) { + return; + } + let rtnp = this.showAlert({ + message: "Are you sure you want to delete this screen?", + confirm: true, + }); + rtnp.then((result) => { + if (!result) { + return; + } + GlobalCommandRunner.screenDelete(activeScreen.screenId, true); + }); + } + clearModals(): boolean { let didSomething = false; mobx.action(() => { @@ -4395,8 +4414,8 @@ class CommandRunner { ); } - screenDelete(screenId: string): Promise { - return GlobalModel.submitCommand("screen", "delete", [screenId], { nohist: "1" }, false); + screenDelete(screenId: string, interactive: boolean): Promise { + return GlobalModel.submitCommand("screen", "delete", [screenId], { nohist: "1" }, interactive); } screenWebShare(screenId: string, shouldShare: boolean): Promise { From c2a894b28021235fea46359783eedbf4287847bb Mon Sep 17 00:00:00 2001 From: Sylvie Crowe <107814465+oneirocosm@users.noreply.github.com> Date: Tue, 9 Jan 2024 16:13:23 -0800 Subject: [PATCH 16/25] SSH Configuration Import Alert Modal (#218) * add an alert modal for the sshconfig import button When the sshconfig import button is pressed, there currently is no visual indicator of what changed. This adds an alert modal to pop up only in the case where the gui button is used. * improve alert modal for sshconfig imports The previous message for SSH configuration imports was vague and did not provide detailed information as what happened during the import. This clarifies that by specifying which remotes were deleted, created, and updated. Updates are only ran and recorded if they would actually change something. * fix port value limiting The SSH config import port limiting was correct but set off a warning in linters. It has been updated to do the same behavior in a different way. Also, port limiting was never added to manually adding a new remote. This change adds it there as well. * change user-facing term to connection Previously, the ssh configuration alert modal used to use the word "remote" to describe connections. "Remote" is the internal name but it isn't consistent with what is being displayed to users. So it has been replaced with "Connection" instead to match. * change remote to connection for ssh import buttons Like the previous change, the word "remote" was used instead of "connection." This was for the tooltips added to connections that had been imported in the connections menu. * update one more remote -> connection --- src/app/common/modals/modals.tsx | 4 +- src/model/model.ts | 6 +- src/types/types.ts | 1 + wavesrv/pkg/cmdrunner/cmdrunner.go | 95 +++++++++++++++++++++++++----- wavesrv/pkg/sstore/updatebus.go | 8 +++ 5 files changed, 96 insertions(+), 18 deletions(-) diff --git a/src/app/common/modals/modals.tsx b/src/app/common/modals/modals.tsx index 7d995d736..f70e0a61d 100644 --- a/src/app/common/modals/modals.tsx +++ b/src/app/common/modals/modals.tsx @@ -1004,7 +1004,7 @@ class ViewRemoteConnDetailModal extends React.Component<{}, {}> { - + - +
@@ -503,6 +525,10 @@ class CreateRemoteConnModal extends React.Component<{}, {}> { this.errorStr = mobx.observable.box(this.remoteEdit?.errorstr ?? null, { name: "CreateRemote-errorStr" }); } + componentDidMount(): void { + GlobalModel.getClientData(); + } + remoteCName(): string { let hostName = this.tempHostName.get(); if (hostName == "") { @@ -521,6 +547,27 @@ class CreateRemoteConnModal extends React.Component<{}, {}> { return this.remoteEdit?.errorstr ?? null; } + @boundMethod + handleOk(): void { + this.showShellPrompt(this.submitRemote); + } + + @boundMethod + showShellPrompt(cb: () => void): void { + let prtn = GlobalModel.showAlert({ + message: + "You are about to install WaveShell on a remote machine. Please be aware that WaveShell will be executed on the remote system.", + confirm: true, + confirmflag: appconst.ConfirmKey_HideShellPrompt, + }); + prtn.then((confirm) => { + if (!confirm) { + return; + } + cb(); + }); + } + @boundMethod submitRemote(): void { mobx.action(() => { @@ -581,12 +628,6 @@ class CreateRemoteConnModal extends React.Component<{}, {}> { }); } - @boundMethod - handleClose(): void { - this.model.closeModal(); - this.model.setRecentConnAdded(false); - } - @boundMethod handleChangeKeyFile(value: string): void { mobx.action(() => { @@ -802,7 +843,7 @@ class CreateRemoteConnModal extends React.Component<{}, {}> {
Error: {this.getErrorStr()}
- + ); } @@ -1097,6 +1138,7 @@ class ViewRemoteConnDetailModal extends React.Component<{}, {}> { let termFontSize = GlobalModel.termFontSize.get(); let termWidth = textmeasure.termWidthFromCols(RemotePtyCols, termFontSize); let remoteAliasText = util.isBlank(remote.remotealias) ? "(none)" : remote.remotealias; + let selectedRemoteStatus = this.getSelectedRemote().status; return ( @@ -1175,7 +1217,18 @@ class ViewRemoteConnDetailModal extends React.Component<{}, {}> {
- +
+ + +
); } diff --git a/src/app/connections/connections.tsx b/src/app/connections/connections.tsx index e9b1e03e0..56017b757 100644 --- a/src/app/connections/connections.tsx +++ b/src/app/connections/connections.tsx @@ -11,6 +11,7 @@ import { GlobalModel, RemotesModel, GlobalCommandRunner } from "../../model/mode import { Button, IconButton, Status } from "../common/common"; import * as T from "../../types/types"; import * as util from "../../util/util"; +import * as appconst from "../appconst"; import "./connections.less"; @@ -74,10 +75,31 @@ class ConnectionsView extends React.Component<{ model: RemotesModel }, { hovered } @boundMethod - handleImportSshConfig(): void { + importSshConfig(): void { GlobalCommandRunner.importSshConfig(); } + @boundMethod + handleImportSshConfig(): void { + this.showShellPrompt(this.importSshConfig); + } + + @boundMethod + showShellPrompt(cb: () => void): void { + let prtn = GlobalModel.showAlert({ + message: + "You are about to install WaveShell on a remote machine. Please be aware that WaveShell will be executed on the remote system.", + confirm: true, + confirmflag: appconst.ConfirmKey_HideShellPrompt, + }); + prtn.then((confirm) => { + if (!confirm) { + return; + } + cb(); + }); + } + @boundMethod handleRead(remoteId: string): void { GlobalModel.remotesModel.openReadModal(remoteId); @@ -163,8 +185,8 @@ class ConnectionsView extends React.Component<{ model: RemotesModel }, { hovered onClick={() => this.handleRead(item.remoteid)} // Moved onClick here > - - {this.getName(item)} {this.getImportSymbol(item)} + + {this.getName(item)} {this.getImportSymbol(item)}
{item.remotetype}
diff --git a/src/model/model.ts b/src/model/model.ts index 9ba1051dd..7934fbe75 100644 --- a/src/model/model.ts +++ b/src/model/model.ts @@ -3287,6 +3287,13 @@ class Model { } showAlert(alertMessage: AlertMessageType): Promise { + if (alertMessage.confirmflag != null) { + let cdata = GlobalModel.clientData.get(); + let noConfirm = cdata.clientopts?.confirmflags?.[alertMessage.confirmflag]; + if (noConfirm) { + return Promise.resolve(true); + } + } mobx.action(() => { this.alertMessage.set(alertMessage); GlobalModel.modalsModel.pushModal(appconst.ALERT); @@ -4652,6 +4659,12 @@ class CommandRunner { GlobalModel.submitCommand("client", "accepttos", null, { nohist: "1" }, true); } + clientSetConfirmFlag(flag: string, value: boolean): Promise { + let kwargs = { nohist: "1" }; + let valueStr = value ? "1" : "0"; + return GlobalModel.submitCommand("client", "setconfirmflag", [flag, valueStr], kwargs, false); + } + editBookmark(bookmarkId: string, desc: string, cmdstr: string) { let kwargs = { nohist: "1", diff --git a/src/types/types.ts b/src/types/types.ts index 758392ffb..29b6fb070 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -473,10 +473,15 @@ type FeOptsType = { termfontsize: number; }; +type ConfirmFlagsType = { + [k: string]: boolean; +}; + type ClientOptsType = { notelemetry: boolean; noreleasecheck: boolean; acceptedtos: number; + confirmflags: ConfirmFlagsType; }; type ReleaseInfoType = { @@ -525,6 +530,7 @@ type AlertMessageType = { message: string; confirm?: boolean; markdown?: boolean; + confirmflag?: string; }; type HistorySearchParams = { diff --git a/wavesrv/pkg/cmdrunner/cmdrunner.go b/wavesrv/pkg/cmdrunner/cmdrunner.go index 96472a812..810771a58 100644 --- a/wavesrv/pkg/cmdrunner/cmdrunner.go +++ b/wavesrv/pkg/cmdrunner/cmdrunner.go @@ -89,6 +89,7 @@ var ColorNames = []string{"yellow", "blue", "pink", "mint", "cyan", "violet", "o var TabIcons = []string{"square", "sparkle", "fire", "ghost", "cloud", "compass", "crown", "droplet", "graduation-cap", "heart", "file"} var RemoteColorNames = []string{"red", "green", "yellow", "blue", "magenta", "cyan", "white", "orange"} var RemoteSetArgs = []string{"alias", "connectmode", "key", "password", "autoinstall", "color"} +var ConfirmFlags = []string{"hideshellprompt"} var ScreenCmds = []string{"run", "comment", "cd", "cr", "clear", "sw", "reset", "signal", "chat"} var NoHistCmds = []string{"_compgen", "line", "history", "_killserver"} @@ -213,6 +214,7 @@ func init() { registerCmdFn("client:set", ClientSetCommand) registerCmdFn("client:notifyupdatewriter", ClientNotifyUpdateWriterCommand) registerCmdFn("client:accepttos", ClientAcceptTosCommand) + registerCmdFn("client:setconfirmflag", ClientConfirmFlagCommand) registerCmdFn("sidebar:open", SidebarOpenCommand) registerCmdFn("sidebar:close", SidebarCloseCommand) @@ -4089,6 +4091,57 @@ func ClientAcceptTosCommand(ctx context.Context, pk *scpacket.FeCommandPacketTyp return update, nil } +var confirmKeyRe = regexp.MustCompile(`^[a-z][a-z0-9_]*$`) + +// confirm flags must be all lowercase and only contain letters, numbers, and underscores (and start with letter) +func ClientConfirmFlagCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) { + // Check for valid arguments length + if len(pk.Args) < 2 { + return nil, fmt.Errorf("invalid arguments: expected at least 2, got %d", len(pk.Args)) + } + + // Extract confirmKey and value from pk.Args + confirmKey := pk.Args[0] + if !confirmKeyRe.MatchString(confirmKey) { + return nil, fmt.Errorf("invalid confirm flag key: %s", confirmKey) + } + value := resolveBool(pk.Args[1], true) + validKey := utilfn.ContainsStr(ConfirmFlags, confirmKey) + if !validKey { + return nil, fmt.Errorf("invalid confirm flag key: %s", confirmKey) + } + + clientData, err := sstore.EnsureClientData(ctx) + if err != nil { + return nil, fmt.Errorf("cannot retrieve client data: %v", err) + } + + // Initialize ConfirmFlags if it's nil + if clientData.ClientOpts.ConfirmFlags == nil { + clientData.ClientOpts.ConfirmFlags = make(map[string]bool) + } + + // Set the confirm flag + clientData.ClientOpts.ConfirmFlags[confirmKey] = value + + err = sstore.SetClientOpts(ctx, clientData.ClientOpts) + if err != nil { + return nil, fmt.Errorf("error updating client data: %v", err) + } + + // Retrieve updated client data + clientData, err = sstore.EnsureClientData(ctx) + if err != nil { + return nil, fmt.Errorf("cannot retrieve updated client data: %v", err) + } + + update := &sstore.ModelUpdate{ + ClientData: clientData, + } + + return update, nil +} + func validateOpenAIAPIToken(key string) error { if len(key) > MaxOpenAIAPITokenLen { return fmt.Errorf("invalid openai token, too long") diff --git a/wavesrv/pkg/cmdrunner/resolver.go b/wavesrv/pkg/cmdrunner/resolver.go index 43ed6c43d..d429cc9ca 100644 --- a/wavesrv/pkg/cmdrunner/resolver.go +++ b/wavesrv/pkg/cmdrunner/resolver.go @@ -11,10 +11,10 @@ import ( "strconv" "strings" + "github.com/google/uuid" "github.com/wavetermdev/waveterm/wavesrv/pkg/remote" "github.com/wavetermdev/waveterm/wavesrv/pkg/scpacket" "github.com/wavetermdev/waveterm/wavesrv/pkg/sstore" - "github.com/google/uuid" ) const ( diff --git a/wavesrv/pkg/shparse/tokenize.go b/wavesrv/pkg/shparse/tokenize.go index 32ae75b00..7d0cc1b07 100644 --- a/wavesrv/pkg/shparse/tokenize.go +++ b/wavesrv/pkg/shparse/tokenize.go @@ -240,7 +240,8 @@ func (c *parseContext) tokenizeDQ() ([]*WordType, bool) { // returns (words, eofexit) // backticks (WordTypeBQ) handle backslash in a special way, but that seems to mainly effect execution (not completion) -// de_backslash => removes initial backslash in \`, \\, and \$ before execution +// +// de_backslash => removes initial backslash in \`, \\, and \$ before execution func (c *parseContext) tokenizeRaw() ([]*WordType, bool) { state := &tokenizeOutputState{} isExpSubShell := c.QC.cur() == WordTypeDP diff --git a/wavesrv/pkg/sstore/sstore.go b/wavesrv/pkg/sstore/sstore.go index 4f25dbdc9..9e4f646d3 100644 --- a/wavesrv/pkg/sstore/sstore.go +++ b/wavesrv/pkg/sstore/sstore.go @@ -267,9 +267,10 @@ func (tdata *TelemetryData) Scan(val interface{}) error { } type ClientOptsType struct { - NoTelemetry bool `json:"notelemetry,omitempty"` - NoReleaseCheck bool `json:"noreleasecheck,omitempty"` - AcceptedTos int64 `json:"acceptedtos,omitempty"` + NoTelemetry bool `json:"notelemetry,omitempty"` + NoReleaseCheck bool `json:"noreleasecheck,omitempty"` + AcceptedTos int64 `json:"acceptedtos,omitempty"` + ConfirmFlags map[string]bool `json:"confirmflags,omitempty"` } type FeOptsType struct { From 077cb2be03d69d0496e84863590ed269f9ed2c90 Mon Sep 17 00:00:00 2001 From: Red J Adaya Date: Fri, 12 Jan 2024 01:42:03 +0800 Subject: [PATCH 19/25] Split up modals.tsx file (#220) * init * diconnected and clientstop modals * alert and createremoteconn modals * tabswitcher, view and edit remoteconn modals * migrate clientstop modal to Modal * LinkButton * import styles for createremoteconn modal * import tabswitcher modal styles * disable buttons while status is 'connecting' * minor refactor * apply changes to viewremoteconn modal from main --- src/app/app.tsx | 3 +- src/app/common/common.tsx | 18 +- src/app/common/modals/about.less | 114 +++++ src/app/common/modals/about.tsx | 136 ++++++ src/app/common/modals/alert.less | 11 + src/app/common/modals/alert.tsx | 75 ++++ src/app/common/modals/clientstop.less | 11 + src/app/common/modals/clientstop.tsx | 49 ++ src/app/common/modals/createremoteconn.less | 24 + src/app/common/modals/createremoteconn.tsx | 370 +++++++++++++++ src/app/common/modals/disconnected.less | 47 ++ src/app/common/modals/disconnected.tsx | 101 +++++ src/app/common/modals/editremoteconn.less | 51 +++ src/app/common/modals/editremoteconn.tsx | 312 +++++++++++++ src/app/common/modals/index.tsx | 8 + src/app/common/modals/provider.tsx | 26 ++ .../{modalsRegistry.tsx => registry.tsx} | 4 +- src/app/common/modals/tabswitcher.less | 84 ++++ src/app/common/modals/tabswitcher.tsx | 324 ++++++++++++++ src/app/common/modals/tos.less | 102 +++++ src/app/common/modals/tos.tsx | 130 ++++++ .../common/modals/viewremoteconndetail.less | 121 +++++ .../common/modals/viewremoteconndetail.tsx | 421 ++++++++++++++++++ src/model/model.ts | 2 +- 24 files changed, 2531 insertions(+), 13 deletions(-) create mode 100644 src/app/common/modals/about.less create mode 100644 src/app/common/modals/about.tsx create mode 100644 src/app/common/modals/alert.less create mode 100644 src/app/common/modals/alert.tsx create mode 100644 src/app/common/modals/clientstop.less create mode 100644 src/app/common/modals/clientstop.tsx create mode 100644 src/app/common/modals/createremoteconn.less create mode 100644 src/app/common/modals/createremoteconn.tsx create mode 100644 src/app/common/modals/disconnected.less create mode 100644 src/app/common/modals/disconnected.tsx create mode 100644 src/app/common/modals/editremoteconn.less create mode 100644 src/app/common/modals/editremoteconn.tsx create mode 100644 src/app/common/modals/index.tsx create mode 100644 src/app/common/modals/provider.tsx rename src/app/common/modals/{modalsRegistry.tsx => registry.tsx} (98%) create mode 100644 src/app/common/modals/tabswitcher.less create mode 100644 src/app/common/modals/tabswitcher.tsx create mode 100644 src/app/common/modals/tos.less create mode 100644 src/app/common/modals/tos.tsx create mode 100644 src/app/common/modals/viewremoteconndetail.less create mode 100644 src/app/common/modals/viewremoteconndetail.tsx diff --git a/src/app/app.tsx b/src/app/app.tsx index 374cf232a..42dba4207 100644 --- a/src/app/app.tsx +++ b/src/app/app.tsx @@ -17,7 +17,8 @@ import { BookmarksView } from "./bookmarks/bookmarks"; import { HistoryView } from "./history/history"; import { ConnectionsView } from "./connections/connections"; import { MainSideBar } from "./sidebar/sidebar"; -import { DisconnectedModal, ClientStopModal, ModalsProvider } from "./common/modals/modals"; +import { DisconnectedModal, ClientStopModal } from "./common/modals"; +import { ModalsProvider } from "./common/modals/provider"; import { ErrorBoundary } from "./common/error/errorboundary"; import "./app.less"; diff --git a/src/app/common/common.tsx b/src/app/common/common.tsx index 69b8b52be..2a2b2c3fe 100644 --- a/src/app/common/common.tsx +++ b/src/app/common/common.tsx @@ -266,6 +266,7 @@ interface ButtonProps { color?: string; style?: React.CSSProperties; autoFocus?: boolean; + className?: string; } class Button extends React.Component { @@ -319,25 +320,24 @@ export default IconButton; interface LinkButtonProps extends ButtonProps { href: string; + rel?: string; target?: string; } -class LinkButton extends IconButton { +class LinkButton extends React.Component { render() { - // @ts-ignore - const { href, target, leftIcon, rightIcon, children, theme, variant }: LinkButtonProps = this.props; + const { leftIcon, rightIcon, children, className, ...rest } = this.props; return ( - - + + {leftIcon && {leftIcon}} + {children} + {rightIcon && {rightIcon}} ); } } + interface StatusProps { status: "green" | "red" | "gray" | "yellow"; text: string; diff --git a/src/app/common/modals/about.less b/src/app/common/modals/about.less new file mode 100644 index 000000000..025246493 --- /dev/null +++ b/src/app/common/modals/about.less @@ -0,0 +1,114 @@ +@import "../../../app/common/themes/themes.less"; + +.about-modal { + .wave-modal-content { + gap: 24px; + + .wave-modal-body { + margin-bottom: 0; + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 24px; + + .about-section { + display: flex; + align-items: center; + gap: 16px; + align-self: stretch; + width: 100%; + + .logo-wrapper { + width: 72px; + height: 72px; + flex-shrink: 0; + + img { + border-radius: 10px; + } + } + + .text-wrapper { + display: flex; + align-items: flex-start; + flex-direction: column; + gap: 4px; + align-self: stretch; + font-style: normal; + line-height: 20px; + + div:first-child { + color: @term-bright-white; + font-size: 14.5px; + } + + div:last-child { + color: @term-white; + text-align: left; + } + } + + .status { + div { + display: flex; + align-items: center; + margin-bottom: 5px; + + i { + font-size: 16px; + margin-right: 10px; + } + } + + div:first-child + div { + color: @term-white; + } + } + + .status.updated { + div { + display: flex; + align-items: center; + margin-bottom: 5px; + + i { + color: @term-green; + } + } + } + + .status.outdated { + div { + i { + color: @term-yellow; + } + } + + button { + margin-top: 5px; + } + } + } + + .about-section:nth-child(3) { + display: flex; + align-items: flex-start; + gap: 10px; + + .wave-button-link { + display: flex; + align-items: center; + + i { + font-size: 16px; + } + } + } + + .about-section:last-child { + margin-bottom: 24px; + color: @term-white; + } + } + } +} diff --git a/src/app/common/modals/about.tsx b/src/app/common/modals/about.tsx new file mode 100644 index 000000000..7d46cccba --- /dev/null +++ b/src/app/common/modals/about.tsx @@ -0,0 +1,136 @@ +// Copyright 2023, Command Line Inc. +// SPDX-License-Identifier: Apache-2.0 + +import * as React from "react"; +import * as mobxReact from "mobx-react"; +import * as mobx from "mobx"; +import { boundMethod } from "autobind-decorator"; +import { GlobalModel } from "../../../model/model"; +import { Modal, LinkButton } from "../common"; +import * as util from "../../../util/util"; + +import logo from "../../assets/waveterm-logo-with-bg.svg"; +import "./about.less"; + +// @ts-ignore +const VERSION = __WAVETERM_VERSION__; +// @ts-ignore +let BUILD = __WAVETERM_BUILD__; + +@mobxReact.observer +class AboutModal extends React.Component<{}, {}> { + @boundMethod + closeModal(): void { + mobx.action(() => { + GlobalModel.modalsModel.popModal(); + })(); + } + + @boundMethod + isUpToDate(): boolean { + return true; + } + + @boundMethod + updateApp(): void { + // GlobalCommandRunner.updateApp(); + } + + @boundMethod + getStatus(isUpToDate: boolean): JSX.Element { + // TODO no up-to-date status reporting + return ( +
+
+ Client Version {VERSION} ({BUILD}) +
+
+ ); + + if (isUpToDate) { + return ( +
+
+ + Up to Date +
+
+ Client Version {VERSION} ({BUILD}) +
+
+ ); + } + return ( +
+
+ + Outdated Version +
+
+ Client Version {VERSION} ({BUILD}) +
+
+ +
+
+ ); + } + + render() { + return ( + + +
+
+
+ logo +
+
+
Wave Terminal
+
+ Modern Terminal for +
+ Seamless Workflow +
+
+
+
{this.getStatus(this.isUpToDate())}
+
+ } + > + Github + + } + > + Website + + } + > + Acknowledgements + +
+
© 2023 Command Line Inc.
+
+ + ); + } +} + +export { AboutModal }; diff --git a/src/app/common/modals/alert.less b/src/app/common/modals/alert.less new file mode 100644 index 000000000..ddec18c57 --- /dev/null +++ b/src/app/common/modals/alert.less @@ -0,0 +1,11 @@ +@import "../../../app/common/themes/themes.less"; + +.alert-modal { + width: 500px; + + .wave-modal-content { + .wave-modal-body { + padding: 40px 20px; + } + } +} diff --git a/src/app/common/modals/alert.tsx b/src/app/common/modals/alert.tsx new file mode 100644 index 000000000..4ce56fc12 --- /dev/null +++ b/src/app/common/modals/alert.tsx @@ -0,0 +1,75 @@ +// Copyright 2023, Command Line Inc. +// SPDX-License-Identifier: Apache-2.0 + +import * as React from "react"; +import * as mobxReact from "mobx-react"; +import { boundMethod } from "autobind-decorator"; +import { If } from "tsx-control-statements/components"; +import { Markdown, Modal, Button, Checkbox } from "../common"; +import { GlobalModel, GlobalCommandRunner } from "../../../model/model"; + +import "./alert.less"; + +@mobxReact.observer +class AlertModal extends React.Component<{}, {}> { + @boundMethod + closeModal(): void { + GlobalModel.cancelAlert(); + } + + @boundMethod + handleOK(): void { + GlobalModel.confirmAlert(); + } + + @boundMethod + handleDontShowAgain(checked: boolean) { + let message = GlobalModel.alertMessage.get(); + if (message.confirmflag == null) { + return; + } + GlobalCommandRunner.clientSetConfirmFlag(message.confirmflag, checked); + } + + render() { + let message = GlobalModel.alertMessage.get(); + let title = message?.title ?? (message?.confirm ? "Confirm" : "Alert"); + let isConfirm = message?.confirm ?? false; + + return ( + + +
+ + + + {message?.message} + + + +
+
+ + + + + + + +
+
+ ); + } +} + +export { AlertModal }; diff --git a/src/app/common/modals/clientstop.less b/src/app/common/modals/clientstop.less new file mode 100644 index 000000000..4ce7d7594 --- /dev/null +++ b/src/app/common/modals/clientstop.less @@ -0,0 +1,11 @@ +@import "../../../app/common/themes/themes.less"; + +.clientstop-modal { + .inner-content { + display: flex; + flex-direction: column; + padding: 30px; + gap: 20px; + align-items: center; + } +} diff --git a/src/app/common/modals/clientstop.tsx b/src/app/common/modals/clientstop.tsx new file mode 100644 index 000000000..b4d4f91e0 --- /dev/null +++ b/src/app/common/modals/clientstop.tsx @@ -0,0 +1,49 @@ +// Copyright 2023, Command Line Inc. +// SPDX-License-Identifier: Apache-2.0 + +import * as React from "react"; +import * as mobxReact from "mobx-react"; +import { boundMethod } from "autobind-decorator"; +import { If } from "tsx-control-statements/components"; +import { GlobalModel } from "../../../model/model"; +import { Modal, Button } from "../common"; + +import "./clientstop.less"; + +@mobxReact.observer +class ClientStopModal extends React.Component<{}, {}> { + @boundMethod + refreshClient() { + GlobalModel.refreshClient(); + } + + render() { + let model = GlobalModel; + let cdata = model.clientData.get(); + return ( + + +
+
+
+ +
Cannot get client data.
+
+
+ +
+
+
+
+ + ); + } +} + +export { ClientStopModal }; diff --git a/src/app/common/modals/createremoteconn.less b/src/app/common/modals/createremoteconn.less new file mode 100644 index 000000000..f6e3a1f00 --- /dev/null +++ b/src/app/common/modals/createremoteconn.less @@ -0,0 +1,24 @@ +@import "../../../app/common/themes/themes.less"; + +.crconn-modal { + width: 452px; + min-height: 411px; + + .wave-modal-content { + gap: 24px; + + .wave-modal-body { + display: flex; + padding: 0px 20px; + flex-direction: column; + align-items: flex-start; + gap: 12px; + align-self: stretch; + width: 100%; + + > div { + width: 100%; + } + } + } +} diff --git a/src/app/common/modals/createremoteconn.tsx b/src/app/common/modals/createremoteconn.tsx new file mode 100644 index 000000000..78ddd4985 --- /dev/null +++ b/src/app/common/modals/createremoteconn.tsx @@ -0,0 +1,370 @@ +// Copyright 2023, Command Line Inc. +// SPDX-License-Identifier: Apache-2.0 + +import * as React from "react"; +import * as mobxReact from "mobx-react"; +import * as mobx from "mobx"; +import { boundMethod } from "autobind-decorator"; +import { If } from "tsx-control-statements/components"; +import { GlobalModel, GlobalCommandRunner, RemotesModel } from "../../../model/model"; +import * as T from "../../../types/types"; +import { Modal, TextField, NumberField, InputDecoration, Dropdown, PasswordField, Tooltip } from "../common"; +import * as util from "../../../util/util"; +import * as appconst from "../../appconst"; + +import "./createremoteconn.less"; + +type OV = mobx.IObservableValue; + +@mobxReact.observer +class CreateRemoteConnModal extends React.Component<{}, {}> { + tempAlias: OV; + tempHostName: OV; + tempPort: OV; + tempAuthMode: OV; + tempConnectMode: OV; + tempPassword: OV; + tempKeyFile: OV; + errorStr: OV; + remoteEdit: T.RemoteEditType; + model: RemotesModel; + + constructor(props: { remotesModel?: RemotesModel }) { + super(props); + this.model = GlobalModel.remotesModel; + this.remoteEdit = this.model.remoteEdit.get(); + this.tempAlias = mobx.observable.box("", { name: "CreateRemote-alias" }); + this.tempHostName = mobx.observable.box("", { name: "CreateRemote-hostName" }); + this.tempPort = mobx.observable.box("", { name: "CreateRemote-port" }); + this.tempAuthMode = mobx.observable.box("none", { name: "CreateRemote-authMode" }); + this.tempConnectMode = mobx.observable.box("auto", { name: "CreateRemote-connectMode" }); + this.tempKeyFile = mobx.observable.box("", { name: "CreateRemote-keystr" }); + this.tempPassword = mobx.observable.box("", { name: "CreateRemote-password" }); + this.errorStr = mobx.observable.box(this.remoteEdit?.errorstr ?? null, { name: "CreateRemote-errorStr" }); + } + + componentDidMount(): void { + GlobalModel.getClientData(); + } + + remoteCName(): string { + let hostName = this.tempHostName.get(); + if (hostName == "") { + return "[no host]"; + } + if (hostName.indexOf("@") == -1) { + hostName = "[no user]@" + hostName; + } + return hostName; + } + + getErrorStr(): string { + if (this.errorStr.get() != null) { + return this.errorStr.get(); + } + return this.remoteEdit?.errorstr ?? null; + } + + @boundMethod + handleOk(): void { + this.showShellPrompt(this.submitRemote); + } + + @boundMethod + showShellPrompt(cb: () => void): void { + let prtn = GlobalModel.showAlert({ + message: + "You are about to install WaveShell on a remote machine. Please be aware that WaveShell will be executed on the remote system.", + confirm: true, + confirmflag: appconst.ConfirmKey_HideShellPrompt, + }); + prtn.then((confirm) => { + if (!confirm) { + return; + } + cb(); + }); + } + + @boundMethod + submitRemote(): void { + mobx.action(() => { + this.errorStr.set(null); + })(); + let authMode = this.tempAuthMode.get(); + let cname = this.tempHostName.get(); + if (cname == "") { + this.errorStr.set("You must specify a 'user@host' value to create a new connection"); + return; + } + let kwargs: Record = {}; + kwargs["alias"] = this.tempAlias.get(); + if (this.tempPort.get() != "" && this.tempPort.get() != "22") { + kwargs["port"] = this.tempPort.get(); + } + if (authMode == "key" || authMode == "key+password") { + if (this.tempKeyFile.get() == "") { + this.errorStr.set("When AuthMode is set to 'key', you must supply a valid key file name."); + return; + } + kwargs["key"] = this.tempKeyFile.get(); + } else { + kwargs["key"] = ""; + } + if (authMode == "password" || authMode == "key+password") { + if (this.tempPassword.get() == "") { + this.errorStr.set("When AuthMode is set to 'password', you must supply a password."); + return; + } + kwargs["password"] = this.tempPassword.get(); + } else { + kwargs["password"] = ""; + } + kwargs["connectmode"] = this.tempConnectMode.get(); + kwargs["visual"] = "1"; + kwargs["submit"] = "1"; + let prtn = GlobalCommandRunner.createRemote(cname, kwargs, false); + prtn.then((crtn) => { + if (crtn.success) { + this.model.setRecentConnAdded(true); + this.model.closeModal(); + + let crRtn = GlobalCommandRunner.screenSetRemote(cname, true, false); + crRtn.then((crcrtn) => { + if (crcrtn.success) { + return; + } + mobx.action(() => { + this.errorStr.set(crcrtn.error); + })(); + }); + return; + } + mobx.action(() => { + this.errorStr.set(crtn.error); + })(); + }); + } + + @boundMethod + handleChangeKeyFile(value: string): void { + mobx.action(() => { + this.tempKeyFile.set(value); + })(); + } + + @boundMethod + handleChangePassword(value: string): void { + mobx.action(() => { + this.tempPassword.set(value); + })(); + } + + @boundMethod + handleChangeAlias(value: string): void { + mobx.action(() => { + this.tempAlias.set(value); + })(); + } + + @boundMethod + handleChangeAuthMode(value: string): void { + mobx.action(() => { + this.tempAuthMode.set(value); + })(); + } + + @boundMethod + handleChangePort(value: string): void { + mobx.action(() => { + this.tempPort.set(value); + })(); + } + + @boundMethod + handleChangeHostName(value: string): void { + mobx.action(() => { + this.tempHostName.set(value); + })(); + } + + @boundMethod + handleChangeConnectMode(value: string): void { + mobx.action(() => { + this.tempConnectMode.set(value); + })(); + } + + render() { + let authMode = this.tempAuthMode.get(); + + if (this.remoteEdit == null) { + return null; + } + + return ( + + +
+
+ + } + > + + + + ), + }} + /> +
+
+ + } + > + + + + ), + }} + /> +
+
+ + } + > + + + + ), + }} + /> +
+
+ { + this.tempAuthMode.set(val); + }} + decoration={{ + endDecoration: ( + + +
  • + none - no authentication, or authentication is already + configured in your ssh config. +
  • +
  • + key - use a private key. +
  • +
  • + password - use a password. +
  • +
  • + key+password - use a key with a passphrase. +
  • + + } + icon={} + > + +
    +
    + ), + }} + /> +
    + + + } + > + + + + ), + }} + /> + + + + +
    + { + this.tempConnectMode.set(val); + }} + /> +
    + +
    Error: {this.getErrorStr()}
    +
    +
    + +
    + ); + } +} + +export { CreateRemoteConnModal }; diff --git a/src/app/common/modals/disconnected.less b/src/app/common/modals/disconnected.less new file mode 100644 index 000000000..1439c9298 --- /dev/null +++ b/src/app/common/modals/disconnected.less @@ -0,0 +1,47 @@ +@import "../../../app/common/themes/themes.less"; + +.disconnected-modal { + .wave-modal-content { + .wave-modal-body { + padding: 0; + + .modal-content { + footer { + .footer-text-link { + color: @term-white; + cursor: pointer; + } + } + } + + .inner-content { + .log { + height: 335px; + margin-bottom: 20px; + overflow: auto; + + &::-webkit-scrollbar-track, + &::-webkit-scrollbar-thumb, + &::-webkit-scrollbar-corner { + display: none; + } + + &:hover::-webkit-scrollbar-thumb { + display: block; + } + + pre { + color: @term-white; + background-color: @term-black; + } + } + } + } + + .wave-modal-footer { + button:first-child { + color: @term-green; + } + } + } +} diff --git a/src/app/common/modals/disconnected.tsx b/src/app/common/modals/disconnected.tsx new file mode 100644 index 000000000..96dd92517 --- /dev/null +++ b/src/app/common/modals/disconnected.tsx @@ -0,0 +1,101 @@ +// Copyright 2023, Command Line Inc. +// SPDX-License-Identifier: Apache-2.0 + +import * as React from "react"; +import * as mobxReact from "mobx-react"; +import * as mobx from "mobx"; +import { boundMethod } from "autobind-decorator"; +import { GlobalModel } from "../../../model/model"; +import { Modal, Button } from "../common"; + +import "./disconnected.less"; + +const NumOfLines = 50; + +@mobxReact.observer +class DisconnectedModal extends React.Component<{}, {}> { + logRef: any = React.createRef(); + logs: mobx.IObservableValue = mobx.observable.box(""); + logInterval: NodeJS.Timeout = null; + + @boundMethod + restartServer() { + GlobalModel.restartWaveSrv(); + } + + @boundMethod + tryReconnect() { + GlobalModel.ws.connectNow("manual"); + } + + componentDidMount() { + this.fetchLogs(); + + this.logInterval = setInterval(() => { + this.fetchLogs(); + }, 5000); + } + + componentWillUnmount() { + if (this.logInterval) { + clearInterval(this.logInterval); + } + } + + componentDidUpdate() { + if (this.logRef.current != null) { + this.logRef.current.scrollTop = this.logRef.current.scrollHeight; + } + } + + fetchLogs() { + GlobalModel.getLastLogs( + NumOfLines, + mobx.action((logs) => { + this.logs.set(logs); + if (this.logRef.current != null) { + this.logRef.current.scrollTop = this.logRef.current.scrollHeight; + } + }) + ); + } + + render() { + return ( + + +
    +
    +
    +
    +
    {this.logs.get()}
    +
    +
    +
    +
    +
    + + +
    +
    + ); + } +} + +export { DisconnectedModal }; diff --git a/src/app/common/modals/editremoteconn.less b/src/app/common/modals/editremoteconn.less new file mode 100644 index 000000000..ad954ff39 --- /dev/null +++ b/src/app/common/modals/editremoteconn.less @@ -0,0 +1,51 @@ +@import "../../../app/common/themes/themes.less"; + +.erconn-modal { + width: 502px; + min-height: 411px; + + .wave-modal-content { + gap: 20px; + + .wave-modal-body { + display: flex; + padding: 0px 20px; + flex-direction: column; + align-items: flex-start; + gap: 12px; + align-self: stretch; + width: 100%; + + > div { + width: 100%; + } + + .name-actions-section { + margin-bottom: 10px; + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 12px; + + .name { + color: @term-bright-white; + font-size: 15px; + font-weight: 500; + line-height: 20px; + } + + .header-actions { + display: flex; + justify-content: flex-end; + align-items: flex-start; + + .wave-button { + padding: 4px 15px; + font-size: 11px; + margin-right: 8px; + } + } + } + } + } +} diff --git a/src/app/common/modals/editremoteconn.tsx b/src/app/common/modals/editremoteconn.tsx new file mode 100644 index 000000000..f08efc807 --- /dev/null +++ b/src/app/common/modals/editremoteconn.tsx @@ -0,0 +1,312 @@ +// Copyright 2023, Command Line Inc. +// SPDX-License-Identifier: Apache-2.0 + +import * as React from "react"; +import * as mobxReact from "mobx-react"; +import * as mobx from "mobx"; +import { If } from "tsx-control-statements/components"; +import { boundMethod } from "autobind-decorator"; +import { GlobalModel, GlobalCommandRunner, RemotesModel } from "../../../model/model"; +import * as T from "../../../types/types"; +import { Modal, TextField, InputDecoration, Dropdown, PasswordField, Tooltip } from "../common"; +import * as util from "../../../util/util"; + +import "./editremoteconn.less"; + +type OV = mobx.IObservableValue; + +const PasswordUnchangedSentinel = "--unchanged--"; + +@mobxReact.observer +class EditRemoteConnModal extends React.Component<{}, {}> { + tempAlias: OV; + tempKeyFile: OV; + tempPassword: OV; + tempConnectMode: OV; + tempAuthMode: OV; + model: RemotesModel; + + constructor(props: { remotesModel?: RemotesModel }) { + super(props); + this.model = GlobalModel.remotesModel; + this.tempAlias = mobx.observable.box(null, { name: "EditRemoteSettings-tempAlias" }); + this.tempAuthMode = mobx.observable.box(null, { name: "EditRemoteSettings-tempAuthMode" }); + this.tempKeyFile = mobx.observable.box(null, { name: "EditRemoteSettings-tempKeyFile" }); + this.tempPassword = mobx.observable.box(null, { name: "EditRemoteSettings-tempPassword" }); + this.tempConnectMode = mobx.observable.box(null, { name: "EditRemoteSettings-tempConnectMode" }); + } + + get selectedRemoteId() { + return this.model.selectedRemoteId.get(); + } + + get selectedRemote(): T.RemoteType { + return GlobalModel.getRemote(this.selectedRemoteId); + } + + get remoteEdit(): T.RemoteEditType { + return this.model.remoteEdit.get(); + } + + get isAuthEditMode(): boolean { + return this.model.isAuthEditMode(); + } + + componentDidMount(): void { + mobx.action(() => { + this.tempAlias.set(this.selectedRemote?.remotealias); + this.tempKeyFile.set(this.remoteEdit?.keystr); + this.tempPassword.set(this.remoteEdit?.haspassword ? PasswordUnchangedSentinel : ""); + this.tempConnectMode.set(this.selectedRemote?.connectmode); + this.tempAuthMode.set(this.selectedRemote?.authtype); + })(); + } + + componentDidUpdate() { + if (this.selectedRemote == null || this.selectedRemote.archived) { + this.model.deSelectRemote(); + } + } + + @boundMethod + handleChangeKeyFile(value: string): void { + mobx.action(() => { + this.tempKeyFile.set(value); + })(); + } + + @boundMethod + handleChangePassword(value: string): void { + mobx.action(() => { + this.tempPassword.set(value); + })(); + } + + @boundMethod + handleChangeAlias(value: string): void { + mobx.action(() => { + this.tempAlias.set(value); + })(); + } + + @boundMethod + handleChangeAuthMode(value: string): void { + mobx.action(() => { + this.tempAuthMode.set(value); + })(); + } + + @boundMethod + handleChangeConnectMode(value: string): void { + mobx.action(() => { + this.tempConnectMode.set(value); + })(); + } + + @boundMethod + canResetPw(): boolean { + if (this.remoteEdit == null) { + return false; + } + return Boolean(this.remoteEdit.haspassword) && this.tempPassword.get() != PasswordUnchangedSentinel; + } + + @boundMethod + resetPw(): void { + mobx.action(() => { + this.tempPassword.set(PasswordUnchangedSentinel); + })(); + } + + @boundMethod + onFocusPassword(e: any) { + if (this.tempPassword.get() == PasswordUnchangedSentinel) { + e.target.select(); + } + } + + @boundMethod + submitRemote(): void { + let authMode = this.tempAuthMode.get(); + let kwargs: Record = {}; + if (authMode == "key" || authMode == "key+password") { + let keyStrEq = util.isStrEq(this.tempKeyFile.get(), this.remoteEdit?.keystr); + if (!keyStrEq) { + kwargs["key"] = this.tempKeyFile.get(); + } + } else { + if (!util.isBlank(this.tempKeyFile.get())) { + kwargs["key"] = ""; + } + } + if (authMode == "password" || authMode == "key+password") { + if (this.tempPassword.get() != PasswordUnchangedSentinel) { + kwargs["password"] = this.tempPassword.get(); + } + } else { + if (this.remoteEdit?.haspassword) { + kwargs["password"] = ""; + } + } + if (!util.isStrEq(this.tempAlias.get(), this.selectedRemote?.remotealias)) { + kwargs["alias"] = this.tempAlias.get(); + } + if (!util.isStrEq(this.tempConnectMode.get(), this.selectedRemote?.connectmode)) { + kwargs["connectmode"] = this.tempConnectMode.get(); + } + kwargs["visual"] = "1"; + kwargs["submit"] = "1"; + GlobalCommandRunner.editRemote(this.selectedRemote?.remoteid, kwargs); + this.model.closeModal(); + } + + renderAuthModeMessage(): any { + let authMode = this.tempAuthMode.get(); + if (authMode == "none") { + return ( + + This connection requires no authentication. +
    + Or authentication is already configured in ssh_config. +
    + ); + } + if (authMode == "key") { + return Use a public/private keypair.; + } + if (authMode == "password") { + return Use a password.; + } + if (authMode == "key+password") { + return Use a public/private keypair with a passphrase.; + } + return null; + } + + render() { + let authMode = this.tempAuthMode.get(); + if (this.remoteEdit === null || !this.isAuthEditMode) { + return null; + } + return ( + + +
    +
    +
    {util.getRemoteName(this.selectedRemote)}
    +
    +
    + + } + > + + + + ), + }} + /> +
    +
    + + +
  • + none - no authentication, or authentication is already + configured in your ssh config. +
  • +
  • + key - use a private key. +
  • +
  • + password - use a password. +
  • +
  • + key+password - use a key with a passphrase. +
  • + + } + icon={} + > + +
    + + ), + }} + /> +
    + + + } + > + + + + ), + }} + /> + + + + +
    + +
    + +
    Error: {this.remoteEdit?.errorstr}
    +
    +
    + +
    + ); + } +} + +export { EditRemoteConnModal }; diff --git a/src/app/common/modals/index.tsx b/src/app/common/modals/index.tsx new file mode 100644 index 000000000..50da27888 --- /dev/null +++ b/src/app/common/modals/index.tsx @@ -0,0 +1,8 @@ +export { AboutModal } from "./about"; +export { DisconnectedModal } from "./disconnected"; +export { ClientStopModal } from "./clientstop"; +export { AlertModal } from "./alert"; +export { CreateRemoteConnModal } from "./createremoteconn"; +export { ViewRemoteConnDetailModal } from "./viewremoteconndetail"; +export { EditRemoteConnModal } from "./editremoteconn"; +export { TabSwitcherModal } from "./tabswitcher"; diff --git a/src/app/common/modals/provider.tsx b/src/app/common/modals/provider.tsx new file mode 100644 index 000000000..0d10f11d2 --- /dev/null +++ b/src/app/common/modals/provider.tsx @@ -0,0 +1,26 @@ +// Copyright 2023, Command Line Inc. +// SPDX-License-Identifier: Apache-2.0 + +import * as React from "react"; +import * as mobxReact from "mobx-react"; +import { GlobalModel } from "../../../model/model"; +import { TosModal } from "./tos"; + +@mobxReact.observer +class ModalsProvider extends React.Component { + render() { + let store = GlobalModel.modalsModel.store.slice(); + if (GlobalModel.needsTos()) { + return ; + } + let rtn: JSX.Element[] = []; + for (let i = 0; i < store.length; i++) { + let entry = store[i]; + let Comp = entry.component; + rtn.push(); + } + return <>{rtn}; + } +} + +export { ModalsProvider }; diff --git a/src/app/common/modals/modalsRegistry.tsx b/src/app/common/modals/registry.tsx similarity index 98% rename from src/app/common/modals/modalsRegistry.tsx rename to src/app/common/modals/registry.tsx index 36cedf7e5..ebdc8382b 100644 --- a/src/app/common/modals/modalsRegistry.tsx +++ b/src/app/common/modals/registry.tsx @@ -4,12 +4,12 @@ import * as React from "react"; import { AboutModal, + AlertModal, CreateRemoteConnModal, ViewRemoteConnDetailModal, EditRemoteConnModal, - AlertModal, TabSwitcherModal, -} from "./modals"; +} from "../modals"; import { ScreenSettingsModal, SessionSettingsModal, LineSettingsModal, ClientSettingsModal } from "./settings"; import * as constants from "../../appconst"; diff --git a/src/app/common/modals/tabswitcher.less b/src/app/common/modals/tabswitcher.less new file mode 100644 index 000000000..1bbfee5af --- /dev/null +++ b/src/app/common/modals/tabswitcher.less @@ -0,0 +1,84 @@ +@import "../../../app/common/themes/themes.less"; + +.tabswitcher-modal { + width: 452px; + min-height: 384px; + + .wave-modal-content { + .wave-modal-body { + display: flex; + padding: 0px; + flex-direction: column; + align-items: flex-start; + align-self: stretch; + width: 100%; + + .textfield-wrapper { + padding: 20px 20px 0px; + + .wave-input-decoration.start-position { + height: 100%; + + .tabswitcher-search-prefix { + opacity: 0.5; + font-size: 13px; + } + } + } + + .list-container { + overflow: hidden; + padding: 10px 0 20px; + width: 100%; + } + + .list-container-inner { + width: 100%; + max-height: 300px; + overflow-y: scroll; + padding: 0 16px 0 20px; + + &::-webkit-scrollbar-thumb { + display: none; + } + + &:hover::-webkit-scrollbar-thumb { + display: block; + } + + .options-list { + width: 100%; + + .search-option { + padding: 5px 5px 5px 8px; + display: flex; + align-items: center; + border: 1px solid transparent; + width: 100%; + overflow: hidden; + + div.tabname { + flex-grow: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + padding-right: 5px; + } + + div.icon { + flex-shrink: 0; + width: 20px; + margin-right: 6px; + } + } + + .focused-option { + border: 1px solid rgba(241, 246, 243, 0.15); + border-radius: 4px; + background: rgba(255, 255, 255, 0.06); + } + } + } + } + } +} diff --git a/src/app/common/modals/tabswitcher.tsx b/src/app/common/modals/tabswitcher.tsx new file mode 100644 index 000000000..c75a35cea --- /dev/null +++ b/src/app/common/modals/tabswitcher.tsx @@ -0,0 +1,324 @@ +// Copyright 2023, Command Line Inc. +// SPDX-License-Identifier: Apache-2.0 + +import * as React from "react"; +import * as mobxReact from "mobx-react"; +import * as mobx from "mobx"; +import { boundMethod } from "autobind-decorator"; +import { For } from "tsx-control-statements/components"; +import cn from "classnames"; +import { GlobalModel, GlobalCommandRunner } from "../../../model/model"; +import { Modal, TextField, InputDecoration, Tooltip } from "../common"; +import * as util from "../../../util/util"; +import { Screen } from "../../../model/model"; +import { ReactComponent as SquareIcon } from "../../assets/icons/tab/square.svg"; + +import "./tabswitcher.less"; + +type OV = mobx.IObservableValue; +type OArr = mobx.IObservableArray; + +type SwitcherDataType = { + sessionId: string; + sessionName: string; + sessionIdx: number; + screenId: string; + screenIdx: number; + screenName: string; + icon: string; + color: string; +}; + +const MaxOptionsToDisplay = 100; + +@mobxReact.observer +class TabSwitcherModal extends React.Component<{}, {}> { + screens: Map>[]; + sessions: Map>[]; + options: SwitcherDataType[] = []; + sOptions: OArr = mobx.observable.array(null, { + name: "TabSwitcherModal-sOptions", + }); + focusedIdx: OV = mobx.observable.box(0, { name: "TabSwitcherModal-selectedIdx" }); + activeSessionIdx: number; + optionRefs = []; + listWrapperRef = React.createRef(); + prevFocusedIdx = 0; + + componentDidMount() { + this.activeSessionIdx = GlobalModel.getActiveSession().sessionIdx.get(); + let oSessions = GlobalModel.sessionList; + let oScreens = GlobalModel.screenMap; + oScreens.forEach((oScreen) => { + // Find the matching session in the observable array + let foundSession = oSessions.find((s) => { + if (s.sessionId === oScreen.sessionId && s.archived.get() == false) { + return true; + } + return false; + }); + + if (foundSession) { + let data: SwitcherDataType = { + sessionName: foundSession.name.get(), + sessionId: foundSession.sessionId, + sessionIdx: foundSession.sessionIdx.get(), + screenName: oScreen.name.get(), + screenId: oScreen.screenId, + screenIdx: oScreen.screenIdx.get(), + icon: this.getTabIcon(oScreen), + color: this.getTabColor(oScreen), + }; + this.options.push(data); + } + }); + + mobx.action(() => { + this.sOptions.replace(this.sortOptions(this.options).slice(0, MaxOptionsToDisplay)); + })(); + + document.addEventListener("keydown", this.handleKeyDown); + } + + componentWillUnmount() { + document.removeEventListener("keydown", this.handleKeyDown); + } + + componentDidUpdate() { + let currFocusedIdx = this.focusedIdx.get(); + + // Check if selectedIdx has changed + if (currFocusedIdx !== this.prevFocusedIdx) { + let optionElement = this.optionRefs[currFocusedIdx]?.current; + + if (optionElement) { + optionElement.scrollIntoView({ block: "nearest" }); + } + + // Update prevFocusedIdx for the next update cycle + this.prevFocusedIdx = currFocusedIdx; + } + if (currFocusedIdx >= this.sOptions.length && this.sOptions.length > 0) { + this.setFocusedIndex(this.sOptions.length - 1); + } + } + + @boundMethod + getTabIcon(screen: Screen): string { + let tabIcon = "default"; + let screenOpts = screen.opts.get(); + if (screenOpts != null && !util.isBlank(screenOpts.tabicon)) { + tabIcon = screenOpts.tabicon; + } + return tabIcon; + } + + @boundMethod + getTabColor(screen: Screen): string { + let tabColor = "default"; + let screenOpts = screen.opts.get(); + if (screenOpts != null && !util.isBlank(screenOpts.tabcolor)) { + tabColor = screenOpts.tabcolor; + } + return tabColor; + } + + @boundMethod + handleKeyDown(e) { + if (e.key === "Escape") { + this.closeModal(); + } else if (e.key === "ArrowUp" || e.key === "ArrowDown") { + e.preventDefault(); + let newIndex = this.calculateNewIndex(e.key === "ArrowUp"); + this.setFocusedIndex(newIndex); + } else if (e.key === "Enter") { + e.preventDefault(); + this.handleSelect(this.focusedIdx.get()); + } + } + + @boundMethod + calculateNewIndex(isUpKey) { + let currentIndex = this.focusedIdx.get(); + if (isUpKey) { + return Math.max(currentIndex - 1, 0); + } else { + return Math.min(currentIndex + 1, this.sOptions.length - 1); + } + } + + @boundMethod + setFocusedIndex(index) { + mobx.action(() => { + this.focusedIdx.set(index); + })(); + } + + @boundMethod + closeModal(): void { + GlobalModel.modalsModel.popModal(); + } + + @boundMethod + handleSelect(index: number): void { + const selectedOption = this.sOptions[index]; + if (selectedOption) { + GlobalCommandRunner.switchScreen(selectedOption.screenId, selectedOption.sessionId); + this.closeModal(); + } + } + + @boundMethod + handleSearch(val: string): void { + let sOptions: SwitcherDataType[]; + if (val == "") { + sOptions = this.sortOptions(this.options).slice(0, MaxOptionsToDisplay); + } else { + sOptions = this.filterOptions(val); + sOptions = this.sortOptions(sOptions); + if (sOptions.length > MaxOptionsToDisplay) { + sOptions = sOptions.slice(0, MaxOptionsToDisplay); + } + } + mobx.action(() => { + this.sOptions.replace(sOptions); + this.focusedIdx.set(0); + })(); + } + + @mobx.computed + @boundMethod + filterOptions(searchInput: string): SwitcherDataType[] { + let filteredScreens = []; + + for (let i = 0; i < this.options.length; i++) { + let tab = this.options[i]; + let match = false; + + if (searchInput.includes("/")) { + let [sessionFilter, screenFilter] = searchInput.split("/").map((s) => s.trim().toLowerCase()); + match = + tab.sessionName.toLowerCase().includes(sessionFilter) && + tab.screenName.toLowerCase().includes(screenFilter); + } else { + match = + tab.sessionName.toLowerCase().includes(searchInput) || + tab.screenName.toLowerCase().includes(searchInput); + } + + // Add tab to filtered list if it matches the criteria + if (match) { + filteredScreens.push(tab); + } + } + + return filteredScreens; + } + + @mobx.computed + @boundMethod + sortOptions(options: SwitcherDataType[]): SwitcherDataType[] { + return options.sort((a, b) => { + let aInCurrentSession = a.sessionIdx === this.activeSessionIdx; + let bInCurrentSession = b.sessionIdx === this.activeSessionIdx; + + // Tabs in the current session are sorted by screenIdx + if (aInCurrentSession && bInCurrentSession) { + return a.screenIdx - b.screenIdx; + } + // a is in the current session and b is not, so a comes first + else if (aInCurrentSession) { + return -1; + } + // b is in the current session and a is not, so b comes first + else if (bInCurrentSession) { + return 1; + } + // Both are in different, non-current sessions - sort by sessionIdx and then by screenIdx + else { + if (a.sessionIdx === b.sessionIdx) { + return a.screenIdx - b.screenIdx; + } else { + return a.sessionIdx - b.sessionIdx; + } + } + }); + } + + @boundMethod + renderIcon(option: SwitcherDataType): React.ReactNode { + let tabIcon = option.icon; + if (tabIcon === "default" || tabIcon === "square") { + return ; + } + return ; + } + + @boundMethod + renderOption(option: SwitcherDataType, index: number): JSX.Element { + if (!this.optionRefs[index]) { + this.optionRefs[index] = React.createRef(); + } + return ( +
    this.handleSelect(index)} + > +
    {this.renderIcon(option)}
    +
    + #{option.sessionName} / {option.screenName} +
    +
    + ); + } + + render() { + let option: SwitcherDataType; + let index: number; + return ( + +
    +
    + +
    Switch to Tab:
    + + ), + endDecoration: ( + + } + > + + + + ), + }} + /> +
    +
    +
    +
    + + {this.renderOption(option, index)} + +
    +
    +
    +
    +
    + ); + } +} + +export { TabSwitcherModal }; diff --git a/src/app/common/modals/tos.less b/src/app/common/modals/tos.less new file mode 100644 index 000000000..fddb8efc7 --- /dev/null +++ b/src/app/common/modals/tos.less @@ -0,0 +1,102 @@ +@import "../../../app/common/themes/themes.less"; + +.tos-modal { + width: 640px; + + .wave-modal-content .wave-modal-body { + padding: 32px 48px; + gap: 8px; + + .wave-modal-body-inner { + gap: 24px; + display: flex; + flex-direction: column; + + header.tos-header { + flex-direction: column; + gap: var(--sizing-sm, 12px); + border-bottom: none; + padding: 0; + + .modal-title { + text-align: center; + font-size: 20px; + font-weight: 300; + } + + .modal-subtitle { + color: @term-white; + text-align: center; + + font-style: normal; + font-weight: 300; + line-height: 20px; + } + } + + .content.tos-content { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 32px; + width: 100%; + margin-bottom: 0; + + .item { + display: flex; + width: 100%; + align-items: center; + gap: 16px; + + .item-inner { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 4px; + flex: 1 0 0; + + .item-title { + color: @term-bright-white; + font-style: normal; + line-height: 20px; + } + + .item-text { + color: @term-white; + font-style: normal; + line-height: 20px; + } + + .item-field { + display: flex; + align-items: center; + gap: 8px; + } + } + } + } + + footer { + .item-text { + text-align: center; + } + + .button-wrapper { + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + + button { + font-size: 12.5px !important; + margin-top: 16px; + } + + button.disabled-button { + cursor: default; + } + } + } + } + } +} diff --git a/src/app/common/modals/tos.tsx b/src/app/common/modals/tos.tsx new file mode 100644 index 000000000..b4ca7ec1c --- /dev/null +++ b/src/app/common/modals/tos.tsx @@ -0,0 +1,130 @@ +// Copyright 2023, Command Line Inc. +// SPDX-License-Identifier: Apache-2.0 + +import * as React from "react"; +import * as mobxReact from "mobx-react"; +import { boundMethod } from "autobind-decorator"; +import { GlobalModel, GlobalCommandRunner } from "../../../model/model"; +import { Toggle, Modal, Button } from "../common"; +import * as util from "../../../util/util"; +import { ClientDataType } from "../../../types/types"; + +import shield from "../../assets/icons/shield_check.svg"; +import help from "../../assets/icons/help_filled.svg"; +import github from "../../assets/icons/github.svg"; + +import "./tos.less"; + +@mobxReact.observer +class TosModal extends React.Component<{}, {}> { + @boundMethod + acceptTos(): void { + GlobalCommandRunner.clientAcceptTos(); + GlobalModel.modalsModel.popModal(); + } + + @boundMethod + handleChangeTelemetry(val: boolean): void { + if (val) { + GlobalCommandRunner.telemetryOn(false); + } else { + GlobalCommandRunner.telemetryOff(false); + } + } + + render() { + let cdata: ClientDataType = GlobalModel.clientData.get(); + + return ( + +
    +
    +
    +
    Welcome to Wave Terminal!
    +
    Lets set everything for you
    +
    +
    +
    + Privacy +
    +
    Telemetry
    +
    + We only collect minimal anonymous telemetry data to help us understand + how many people are using Wave. +
    +
    + +
    + Telemetry {cdata.clientopts.notelemetry ? "Disabled" : "Enabled"} +
    +
    +
    +
    +
    + + Help + +
    +
    Join our Community
    +
    + Get help, submit feature requests, report bugs, or just chat with fellow + terminal enthusiasts. +
    + + Join the Wave Discord Channel + +
    +
    +
    +
    + + Github + +
    +
    Support us on GitHub
    +
    + We're open source and committed to providing a free terminal for + individual users. Please show your support us by giving us a star on{" "} + + Github (wavetermdev/waveterm) + +
    +
    +
    +
    + +
    +
    +
    + ); + } +} + +export { TosModal }; diff --git a/src/app/common/modals/viewremoteconndetail.less b/src/app/common/modals/viewremoteconndetail.less new file mode 100644 index 000000000..2789c8779 --- /dev/null +++ b/src/app/common/modals/viewremoteconndetail.less @@ -0,0 +1,121 @@ +@import "../../../app/common/themes/themes.less"; + +.rconndetail-modal { + width: 631px; + min-height: 565px; + + .wave-modal-content { + display: flex; + padding-bottom: 0px; + flex-direction: column; + align-items: center; + gap: 20px; + flex-shrink: 0; + + .wave-modal-body { + display: flex; + padding: 0px 20px; + align-items: flex-start; + width: 100%; + display: flex; + flex-direction: column; + gap: 16px; + align-self: stretch; + + .name-header-actions-wrapper { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 12px; + + .name-wrapper { + display: flex; + flex-direction: row; + } + + .rconndetail-name { + color: @term-bright-white; + font-size: 15px; + font-weight: 500; + line-height: 20px; + } + + .header-actions { + display: flex; + justify-content: flex-end; + align-items: flex-start; + + .wave-button { + padding: 4px 15px; + font-size: 11px; + margin-right: 8px; + } + } + } + + .remote-detail { + .settings-field { + display: flex; + flex-direction: row; + align-items: center; + + .settings-label { + font-weight: bold; + width: 12em; + display: flex; + flex-direction: row; + align-items: center; + } + + .settings-input { + display: flex; + flex-direction: row; + align-items: center; + color: @term-white; + } + } + + .settings-field:not(:first-child) { + margin-top: 4px; + } + + .status { + display: flex; + height: 30px; + padding: 3px 8px; + align-items: center; + gap: 8px; + align-self: stretch; + border-radius: 6px; + background: rgba(241, 246, 243, 0.08); + } + + .terminal-wrapper { + width: 100%; + margin-top: 5px; + + .terminal-connectelem { + height: 163px !important; // Needed to override plugin height + + .xterm-viewport { + display: flex; + padding: 6px 10px; + gap: 8px; + align-items: flex-start; + align-self: stretch; + border-radius: 6px; + border: 1px solid var(--element-separator, rgba(241, 246, 243, 0.15)); + background: #080a08; + height: 163px !important; // Needed to override plugin height + } + + .xterm-screen { + padding: 10px; + width: 541px !important; // Needed to override plugin width + } + } + } + } + } + } +} diff --git a/src/app/common/modals/viewremoteconndetail.tsx b/src/app/common/modals/viewremoteconndetail.tsx new file mode 100644 index 000000000..c0518d07a --- /dev/null +++ b/src/app/common/modals/viewremoteconndetail.tsx @@ -0,0 +1,421 @@ +// Copyright 2023, Command Line Inc. +// SPDX-License-Identifier: Apache-2.0 + +import * as React from "react"; +import * as mobxReact from "mobx-react"; +import * as mobx from "mobx"; +import { boundMethod } from "autobind-decorator"; +import { If, For } from "tsx-control-statements/components"; +import cn from "classnames"; +import { GlobalModel, GlobalCommandRunner, RemotesModel } from "../../../model/model"; +import * as T from "../../../types/types"; +import { Modal, Tooltip, Button, Status } from "../common"; +import * as util from "../../../util/util"; +import * as textmeasure from "../../../util/textmeasure"; + +import "./viewremoteconndetail.less"; + +const RemotePtyRows = 9; +const RemotePtyCols = 80; + +@mobxReact.observer +class ViewRemoteConnDetailModal extends React.Component<{}, {}> { + termRef: React.RefObject = React.createRef(); + model: RemotesModel; + + constructor(props: { remotesModel?: RemotesModel }) { + super(props); + this.model = GlobalModel.remotesModel; + } + + @mobx.computed + getSelectedRemote(): T.RemoteType { + const selectedRemoteId = this.model.selectedRemoteId.get(); + return GlobalModel.getRemote(selectedRemoteId); + } + + componentDidMount() { + let elem = this.termRef.current; + if (elem == null) { + console.log("ERROR null term-remote element"); + return; + } + this.model.createTermWrap(elem); + } + + componentDidUpdate() { + if (this.getSelectedRemote() == null || this.getSelectedRemote().archived) { + this.model.deSelectRemote(); + } + } + + componentWillUnmount() { + this.model.disposeTerm(); + } + + @boundMethod + clickTermBlock(): void { + if (this.model.remoteTermWrap != null) { + this.model.remoteTermWrap.giveFocus(); + } + } + + getRemoteTypeStr(remote: T.RemoteType): string { + if (!util.isBlank(remote.uname)) { + let unameStr = remote.uname; + unameStr = unameStr.replace("|", ", "); + return remote.remotetype + " (" + unameStr + ")"; + } + return remote.remotetype; + } + + @boundMethod + connectRemote(remoteId: string) { + GlobalCommandRunner.connectRemote(remoteId); + } + + @boundMethod + disconnectRemote(remoteId: string) { + GlobalCommandRunner.disconnectRemote(remoteId); + } + + @boundMethod + installRemote(remoteId: string) { + GlobalCommandRunner.installRemote(remoteId); + } + + @boundMethod + cancelInstall(remoteId: string) { + GlobalCommandRunner.installCancelRemote(remoteId); + } + + @boundMethod + openEditModal(): void { + GlobalModel.remotesModel.startEditAuth(); + } + + @boundMethod + getStatus(status: string) { + switch (status) { + case "connected": + return "green"; + case "disconnected": + return "gray"; + default: + return "red"; + } + } + + @boundMethod + clickArchive(): void { + if (this.getSelectedRemote() && this.getSelectedRemote().status == "connected") { + GlobalModel.showAlert({ message: "Cannot delete when connected. Disconnect and try again." }); + return; + } + let prtn = GlobalModel.showAlert({ + message: "Are you sure you want to delete this connection?", + confirm: true, + }); + prtn.then((confirm) => { + if (!confirm) { + return; + } + if (this.getSelectedRemote()) { + GlobalCommandRunner.archiveRemote(this.getSelectedRemote().remoteid); + } + GlobalModel.modalsModel.popModal(); + }); + } + + @boundMethod + clickReinstall(): void { + GlobalCommandRunner.installRemote(this.getSelectedRemote().remoteid); + } + + @boundMethod + handleClose(): void { + this.model.closeModal(); + this.model.setRecentConnAdded(false); + } + + renderInstallStatus(remote: T.RemoteType): any { + let statusStr: string = null; + if (remote.installstatus == "disconnected") { + if (remote.needsmshellupgrade) { + statusStr = "mshell " + remote.mshellversion + " - needs upgrade"; + } else if (util.isBlank(remote.mshellversion)) { + statusStr = "mshell unknown"; + } else { + statusStr = "mshell " + remote.mshellversion + " - current"; + } + } else { + statusStr = remote.installstatus; + } + if (statusStr == null) { + return null; + } + return ( +
    +
    Install Status
    +
    {statusStr}
    +
    + ); + } + + renderHeaderBtns(remote: T.RemoteType): React.ReactNode { + let buttons: React.ReactNode[] = []; + const disconnectButton = ( + + ); + const connectButton = ( + + ); + const tryReconnectButton = ( + + ); + let updateAuthButton = ( + + ); + let cancelInstallButton = ( + + ); + let installNowButton = ( + + ); + let archiveButton = ( + + ); + const reinstallButton = ( + + ); + if (remote.local) { + installNowButton = <>; + updateAuthButton = <>; + cancelInstallButton = <>; + } + if (remote.sshconfigsrc == "sshconfig-import") { + updateAuthButton = ( + + ); + archiveButton = ( + + ); + } + if (remote.status == "connected" || remote.status == "connecting") { + buttons.push(disconnectButton); + } else if (remote.status == "disconnected") { + buttons.push(connectButton); + } else if (remote.status == "error") { + if (remote.needsmshellupgrade) { + if (remote.installstatus == "connecting") { + buttons.push(cancelInstallButton); + } else { + buttons.push(installNowButton); + } + } else { + buttons.push(tryReconnectButton); + } + } + buttons.push(reinstallButton); + buttons.push(updateAuthButton); + buttons.push(archiveButton); + + let i = 0; + let button: React.ReactNode = null; + + return ( + +
    {button}
    +
    + ); + } + + getMessage(remote: T.RemoteType): string { + let message = ""; + if (remote.status == "connected") { + message = "Connected and ready to run commands."; + } else if (remote.status == "connecting") { + message = remote.waitingforpassword ? "Connecting, waiting for user-input..." : "Connecting..."; + let connectTimeout = remote.connecttimeout ?? 0; + message = message + " (" + connectTimeout + "s)"; + } else if (remote.status == "disconnected") { + message = "Disconnected"; + } else if (remote.status == "error") { + if (remote.noinitpk) { + message = "Error, could not connect."; + } else if (remote.needsmshellupgrade) { + if (remote.installstatus == "connecting") { + message = "Installing..."; + } else { + message = "Error, needs install."; + } + } else { + message = "Error"; + } + } + + return message; + } + + render() { + let remote = this.getSelectedRemote(); + + if (remote == null) { + return null; + } + + let model = this.model; + let isTermFocused = this.model.remoteTermWrapFocus.get(); + let termFontSize = GlobalModel.termFontSize.get(); + let termWidth = textmeasure.termWidthFromCols(RemotePtyCols, termFontSize); + let remoteAliasText = util.isBlank(remote.remotealias) ? "(none)" : remote.remotealias; + let selectedRemoteStatus = this.getSelectedRemote().status; + + return ( + + +
    +
    +
    + {util.getRemoteName(remote)}  {getImportTooltip(remote)} +
    +
    {this.renderHeaderBtns(remote)}
    +
    +
    +
    +
    Conn Id
    +
    {remote.remoteid}
    +
    +
    +
    Type
    +
    {this.getRemoteTypeStr(remote)}
    +
    +
    +
    Canonical Name
    +
    + {remote.remotecanonicalname} + + (port {remote.remotevars.port}) + +
    +
    +
    +
    Alias
    +
    {remoteAliasText}
    +
    +
    +
    Auth Type
    +
    + {remote.authtype} + local +
    +
    +
    +
    Connect Mode
    +
    {remote.connectmode}
    +
    + {this.renderInstallStatus(remote)} +
    +
    + +
    +
    + +
    +
    + +
    + input is only allowed while status is 'connecting' +
    +
    +
    +
    +
    +
    +
    + + +
    + + ); + } +} + +function getImportTooltip(remote: T.RemoteType): React.ReactElement { + if (remote.sshconfigsrc == "sshconfig-import") { + return ( + } + > + + + ); + } else { + return <>; + } +} + +export { ViewRemoteConnDetailModal }; diff --git a/src/model/model.ts b/src/model/model.ts index 7934fbe75..6b867636f 100644 --- a/src/model/model.ts +++ b/src/model/model.ts @@ -80,7 +80,7 @@ import localizedFormat from "dayjs/plugin/localizedFormat"; import customParseFormat from "dayjs/plugin/customParseFormat"; import { getRendererContext, cmdStatusIsRunning } from "../app/line/lineutil"; import { MagicLayout } from "../app/magiclayout"; -import { modalsRegistry } from "../app/common/modals/modalsRegistry"; +import { modalsRegistry } from "../app/common/modals/registry"; import * as appconst from "../app/appconst"; dayjs.extend(customParseFormat); From ea3be8115a7b133d552e9807c6cc439725e4741b Mon Sep 17 00:00:00 2001 From: Cole Lashley Date: Thu, 11 Jan 2024 17:34:23 -0800 Subject: [PATCH 20/25] Chat GPT Command Info Chat (#207) * first draft at ui * first draft connecting openai to cmd info ui * added more updates and added prompt engineering * focus textarea on mount * fix aichat layout issue * added focus back to input after closing cmd info chat * added ability to clear chat history, closes on command enter, better initial greeting message, and small things like user can refocus the help textarea by pressing ctrl + space again * added a bunch of small upgrades * added context for chatgpt info command * added context to chatgpt cmd info command * added ability to use arrow keys to grab code markdown * added error handling as well as fixed the text area outline bug * slightly changed the ui for selecting * revamped ui and added correct scroll behavior * changed ui, fixed up code block selection, some other small changes * deep copied cmd info chat when we return * added error checking and removed logs * made deep copy code more clear * prettier with the right version * more prettier changes * removed extraneous comment --- src/app/common/common.less | 9 +- src/app/common/common.tsx | 64 +++++- src/app/workspace/cmdinput/aichat.tsx | 219 +++++++++++++++++++ src/app/workspace/cmdinput/cmdinput.less | 70 ++++++ src/app/workspace/cmdinput/cmdinput.tsx | 16 +- src/app/workspace/cmdinput/textareainput.tsx | 5 + src/model/model.ts | 193 ++++++++++++++++ src/types/types.ts | 16 ++ waveshell/pkg/packet/packet.go | 18 ++ wavesrv/pkg/cmdrunner/cmdrunner.go | 159 +++++++++++++- wavesrv/pkg/sstore/dbops.go | 25 +++ wavesrv/pkg/sstore/memops.go | 108 ++++++++- wavesrv/pkg/sstore/updatebus.go | 48 ++-- 13 files changed, 915 insertions(+), 35 deletions(-) create mode 100644 src/app/workspace/cmdinput/aichat.tsx diff --git a/src/app/common/common.less b/src/app/common/common.less index 8552e15f3..ddfd827c2 100644 --- a/src/app/common/common.less +++ b/src/app/common/common.less @@ -352,7 +352,7 @@ background-color: @markdown-highlight; color: @term-white; font-family: @terminal-font; - display: inline-block; + border-radius: 4px; } code.inline { @@ -403,6 +403,13 @@ background-color: @markdown-highlight; margin: 4px 10px 4px 10px; padding: 6px 6px 6px 10px; + border-radius: 4px; + } + + pre.selected { + border-style: solid; + outline-width: 2px; + border-color: @term-green; } .title.is-1 { diff --git a/src/app/common/common.tsx b/src/app/common/common.tsx index 2a2b2c3fe..90183571f 100644 --- a/src/app/common/common.tsx +++ b/src/app/common/common.tsx @@ -11,6 +11,7 @@ import cn from "classnames"; import { If } from "tsx-control-statements/components"; import type { RemoteType } from "../../types/types"; import ReactDOM from "react-dom"; +import { GlobalModel } from "../../model/model"; import { ReactComponent as CheckIcon } from "../assets/icons/line/check.svg"; import { ReactComponent as CopyIcon } from "../assets/icons/history/copy.svg"; @@ -828,9 +829,67 @@ function CodeRenderer(props: any): any { } @mobxReact.observer -class Markdown extends React.Component<{ text: string; style?: any; extraClassName?: string }, {}> { +class CodeBlockMarkdown extends React.Component< + { children: React.ReactNode; blockText: string; codeSelectSelectedIndex?: number }, + {} +> { + blockIndex: number; + blockRef: React.RefObject; + + constructor(props) { + super(props); + this.blockRef = React.createRef(); + this.blockIndex = GlobalModel.inputModel.addCodeBlockToCodeSelect(this.blockRef); + } + + render() { + let codeText = this.props.blockText; + let clickHandler: (e: React.MouseEvent, blockIndex: number) => void; + let inputModel = GlobalModel.inputModel; + clickHandler = (e: React.MouseEvent, blockIndex: number) => { + inputModel.setCodeSelectSelectedCodeBlock(blockIndex); + }; + let selected = this.blockIndex == this.props.codeSelectSelectedIndex; + return ( +
     clickHandler(event, this.blockIndex)}
    +            >
    +                {this.props.children}
    +            
    + ); + } +} + +@mobxReact.observer +class Markdown extends React.Component< + { text: string; style?: any; extraClassName?: string; codeSelect?: boolean }, + {} +> { + CodeBlockRenderer(props: any, codeSelect: boolean, codeSelectIndex: number): any { + let codeText = codeSelect ? props.node.children[0].children[0].value : props.children; + if (codeText) { + codeText = codeText.replace(/\n$/, ""); // remove trailing newline + } + if (codeSelect) { + return ( + + {props.children} + + ); + } else { + let clickHandler = (e: React.MouseEvent) => { + navigator.clipboard.writeText(codeText); + }; + return
     clickHandler(event)}>{props.children}
    ; + } + } + render() { let text = this.props.text; + let codeSelect = this.props.codeSelect; + let curCodeSelectIndex = GlobalModel.inputModel.getCodeSelectSelectedIndex(); let markdownComponents = { a: LinkRenderer, h1: (props) => HeaderRenderer(props, 1), @@ -839,7 +898,8 @@ class Markdown extends React.Component<{ text: string; style?: any; extraClassNa h4: (props) => HeaderRenderer(props, 4), h5: (props) => HeaderRenderer(props, 5), h6: (props) => HeaderRenderer(props, 6), - code: CodeRenderer, + code: (props) => CodeRenderer(props), + pre: (props) => this.CodeBlockRenderer(props, codeSelect, curCodeSelectIndex), }; return (
    diff --git a/src/app/workspace/cmdinput/aichat.tsx b/src/app/workspace/cmdinput/aichat.tsx new file mode 100644 index 000000000..008fe8eba --- /dev/null +++ b/src/app/workspace/cmdinput/aichat.tsx @@ -0,0 +1,219 @@ +// Copyright 2023, Command Line Inc. +// SPDX-License-Identifier: Apache-2.0 + +import * as React from "react"; +import * as mobxReact from "mobx-react"; +import * as mobx from "mobx"; +import { GlobalModel } from "../../../model/model"; +import { isBlank } from "../../../util/util"; +import { boundMethod } from "autobind-decorator"; +import cn from "classnames"; +import { Prompt } from "../../common/prompt/prompt"; +import { TextAreaInput } from "./textareainput"; +import { If, For } from "tsx-control-statements/components"; +import type { OpenAICmdInfoChatMessageType } from "../../../types/types"; +import { Markdown } from "../../common/common"; + +@mobxReact.observer +class AIChat extends React.Component<{}, {}> { + chatListKeyCount: number = 0; + textAreaNumLines: mobx.IObservableValue = mobx.observable.box(1, { name: "textAreaNumLines" }); + chatWindowScrollRef: React.RefObject; + textAreaRef: React.RefObject; + + constructor(props: any) { + super(props); + this.chatWindowScrollRef = React.createRef(); + this.textAreaRef = React.createRef(); + } + + componentDidMount() { + let model = GlobalModel; + let inputModel = model.inputModel; + if (this.chatWindowScrollRef != null && this.chatWindowScrollRef.current != null) { + this.chatWindowScrollRef.current.scrollTop = this.chatWindowScrollRef.current.scrollHeight; + } + if (this.textAreaRef.current != null) { + this.textAreaRef.current.focus(); + inputModel.setCmdInfoChatRefs(this.textAreaRef, this.chatWindowScrollRef); + } + this.requestChatUpdate(); + } + + componentDidUpdate() { + if (this.chatWindowScrollRef != null && this.chatWindowScrollRef.current != null) { + this.chatWindowScrollRef.current.scrollTop = this.chatWindowScrollRef.current.scrollHeight; + } + } + + requestChatUpdate() { + this.submitChatMessage(""); + } + + submitChatMessage(messageStr: string) { + let model = GlobalModel; + let inputModel = model.inputModel; + let curLine = inputModel.getCurLine(); + let prtn = GlobalModel.submitChatInfoCommand(messageStr, curLine, false); + prtn.then((rtn) => { + if (!rtn.success) { + console.log("submit chat command error: " + rtn.error); + } + }).catch((error) => {}); + } + + getLinePos(elem: any): { numLines: number; linePos: number } { + let numLines = elem.value.split("\n").length; + let linePos = elem.value.substr(0, elem.selectionStart).split("\n").length; + return { numLines, linePos }; + } + + @mobx.action + @boundMethod + onKeyDown(e: any) { + mobx.action(() => { + let model = GlobalModel; + let inputModel = model.inputModel; + let ctrlMod = e.getModifierState("Control") || e.getModifierState("Meta") || e.getModifierState("Shift"); + let resetCodeSelect = !ctrlMod; + + if (e.code == "Enter") { + e.preventDefault(); + if (!ctrlMod) { + if (inputModel.getCodeSelectSelectedIndex() == -1) { + let messageStr = e.target.value; + this.submitChatMessage(messageStr); + e.target.value = ""; + } else { + inputModel.grabCodeSelectSelection(); + } + } else { + e.target.setRangeText("\n", e.target.selectionStart, e.target.selectionEnd, "end"); + } + } + if (e.code == "Escape") { + e.preventDefault(); + e.stopPropagation(); + inputModel.closeAIAssistantChat(); + } + if (e.code == "KeyL" && e.getModifierState("Control")) { + e.preventDefault(); + e.stopPropagation(); + inputModel.clearAIAssistantChat(); + } + if (e.code == "ArrowUp") { + if (this.getLinePos(e.target).linePos > 1) { + // normal up arrow + return; + } + e.preventDefault(); + inputModel.codeSelectSelectNextOldestCodeBlock(); + resetCodeSelect = false; + } + if (e.code == "ArrowDown") { + if (inputModel.getCodeSelectSelectedIndex() == inputModel.codeSelectBottom) { + return; + } + e.preventDefault(); + inputModel.codeSelectSelectNextNewestCodeBlock(); + resetCodeSelect = false; + } + + if (resetCodeSelect) { + inputModel.codeSelectDeselectAll(); + } + + // set height of textarea based on number of newlines + this.textAreaNumLines.set(e.target.value.split(/\n/).length); + })(); + } + + renderError(err: string): any { + return
    {err}
    ; + } + + renderChatMessage(chatItem: OpenAICmdInfoChatMessageType): any { + let curKey = "chatmsg-" + this.chatListKeyCount; + this.chatListKeyCount++; + let senderClassName = chatItem.isassistantresponse ? "chat-msg-assistant" : "chat-msg-user"; + let msgClassName = "chat-msg " + senderClassName; + let innerHTML: React.JSX.Element = ( + + + +

    You

    +
    +

    {chatItem.userquery}

    +
    + ); + if (chatItem.isassistantresponse) { + if (chatItem.assistantresponse.error != null && chatItem.assistantresponse.error != "") { + innerHTML = this.renderError(chatItem.assistantresponse.error); + } else { + innerHTML = ( + + + +

    ChatGPT

    +
    + +
    + ); + } + } + + return ( +
    + {innerHTML} +
    + ); + } + + renderChatWindow(): any { + let model = GlobalModel; + let inputModel = model.inputModel; + let chatMessageItems = inputModel.AICmdInfoChatItems.slice(); + let chitem: OpenAICmdInfoChatMessageType = null; + return ( +
    + + {this.renderChatMessage(chitem)} + +
    + ); + } + + render() { + let model = GlobalModel; + let inputModel = model.inputModel; + + const termFontSize = 14; + const textAreaMaxLines = 4; + const textAreaLineHeight = termFontSize * 1.5; + const textAreaPadding = 2 * 0.5 * termFontSize; + let textAreaMaxHeight = textAreaLineHeight * textAreaMaxLines + textAreaPadding; + let textAreaInnerHeight = this.textAreaNumLines.get() * textAreaLineHeight + textAreaPadding; + + return ( +
    + {this.renderChatWindow()} + +
    + ); + } +} + +export { AIChat }; diff --git a/src/app/workspace/cmdinput/cmdinput.less b/src/app/workspace/cmdinput/cmdinput.less index 7324b86ea..69efc8521 100644 --- a/src/app/workspace/cmdinput/cmdinput.less +++ b/src/app/workspace/cmdinput/cmdinput.less @@ -42,6 +42,10 @@ max-height: max(300px, 70%); } + &.has-aichat { + max-height: max(300px, 70%); + } + .remote-status-warning { display: flex; flex-direction: row; @@ -196,6 +200,72 @@ } } } + + .cmd-aichat { + display: flex; + justify-content: flex-end; + flex-flow: column nowrap; + margin-bottom: 10px; + flex-shrink: 1; + overflow-y: auto; + + .chat-window { + overflow-y: auto; + margin-bottom: 5px; + flex-shrink: 1; + flex-direction: column-reverse; + } + + .chat-textarea { + color: @term-bright-white; + background-color: @textarea-background; + padding: 0.5em; + resize: none; + overflow: auto; + overflow-wrap: anywhere; + border-color: transparent; + border: none; + font-family: @terminal-font; + flex-shrink: 0; + flex-grow: 1; + border-radius: 4px; + + &:focus { + box-shadow: none; + border: none; + outline: none; + } + } + + .chat-msg { + margin-top:5px; + margin-bottom:5px; + } + + .chat-msg-assistant { + color: @term-white; + } + + .chat-msg-user { + + .msg-text { + font-family: @markdown-font; + font-size: 14px; + white-space: pre-wrap; + } + } + + .chat-msg-error { + color: @term-bright-red; + font-family: @markdown-font; + font-size: 14px; + } + + + .grow-spacer { + flex: 1 0 10px; + } + } .cmd-history { color: @term-white; diff --git a/src/app/workspace/cmdinput/cmdinput.tsx b/src/app/workspace/cmdinput/cmdinput.tsx index fd157b776..a13e961d0 100644 --- a/src/app/workspace/cmdinput/cmdinput.tsx +++ b/src/app/workspace/cmdinput/cmdinput.tsx @@ -19,6 +19,7 @@ import { Prompt } from "../../common/prompt/prompt"; import { ReactComponent as ExecIcon } from "../../assets/icons/exec.svg"; import { ReactComponent as RotateIcon } from "../../assets/icons/line/rotate.svg"; import "./cmdinput.less"; +import { AIChat } from "./aichat"; dayjs.extend(localizedFormat); @@ -116,6 +117,7 @@ class CmdInput extends React.Component<{}, {}> { } let infoShow = inputModel.infoShow.get(); let historyShow = !infoShow && inputModel.historyShow.get(); + let aiChatShow = inputModel.aIChatShow.get(); let infoMsg = inputModel.infoMsg.get(); let hasInfo = infoMsg != null; let focusVal = inputModel.physicalInputFocused.get(); @@ -127,11 +129,23 @@ class CmdInput extends React.Component<{}, {}> { numRunningLines = mobx.computed(() => win.getRunningCmdLines().length).get(); } return ( -
    +
    + +
    + +
    diff --git a/src/app/workspace/cmdinput/textareainput.tsx b/src/app/workspace/cmdinput/textareainput.tsx index 04e0c6b93..8cca3b89d 100644 --- a/src/app/workspace/cmdinput/textareainput.tsx +++ b/src/app/workspace/cmdinput/textareainput.tsx @@ -230,6 +230,7 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: () if (inputModel.inputMode.get() != null) { inputModel.resetInputMode(); } + inputModel.closeAIAssistantChat(); return; } if (e.code == "KeyE" && e.getModifierState("Meta")) { @@ -313,6 +314,10 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: () scrollDiv(div, e.code == "PageUp" ? -amt : amt); } } + if (e.code == "Space" && e.getModifierState("Control")) { + e.preventDefault(); + inputModel.openAIAssistantChat(); + } // console.log(e.code, e.keyCode, e.key, event.which, ctrlMod, e); })(); } diff --git a/src/model/model.ts b/src/model/model.ts index 6b867636f..f7cc0d56b 100644 --- a/src/model/model.ts +++ b/src/model/model.ts @@ -65,6 +65,7 @@ import type { CommandRtnType, WebCmd, WebRemote, + OpenAICmdInfoChatMessageType, } from "../types/types"; import * as T from "../types/types"; import { WSControl } from "./ws"; @@ -1233,7 +1234,18 @@ function getDefaultHistoryQueryOpts(): HistoryQueryOpts { class InputModel { historyShow: OV = mobx.observable.box(false); infoShow: OV = mobx.observable.box(false); + aIChatShow: OV = mobx.observable.box(false); cmdInputHeight: OV = mobx.observable.box(0); + aiChatTextAreaRef: React.RefObject; + aiChatWindowRef: React.RefObject; + codeSelectBlockRefArray: Array>; + codeSelectSelectedIndex: OV = mobx.observable.box(-1); + + AICmdInfoChatItems: mobx.IObservableArray = mobx.observable.array([], { + name: "aicmdinfo-chat", + }); + readonly codeSelectTop: number = -2; + readonly codeSelectBottom: number = -1; historyType: mobx.IObservableValue = mobx.observable.box("screen"); historyLoading: mobx.IObservableValue = mobx.observable.box(false); @@ -1271,6 +1283,10 @@ class InputModel { this.filteredHistoryItems = mobx.computed(() => { return this._getFilteredHistoryItems(); }); + mobx.action(() => { + this.codeSelectSelectedIndex.set(-1); + this.codeSelectBlockRefArray = []; + })(); } setInputMode(inputMode: null | "comment" | "global"): void { @@ -1395,6 +1411,11 @@ class InputModel { })(); } + setOpenAICmdInfoChat(chat: OpenAICmdInfoChatMessageType[]): void { + this.AICmdInfoChatItems.replace(chat); + this.codeSelectBlockRefArray = []; + } + setHistoryShow(show: boolean): void { if (this.historyShow.get() == show) { return; @@ -1683,6 +1704,152 @@ class InputModel { } } + setCmdInfoChatRefs( + textAreaRef: React.RefObject, + chatWindowRef: React.RefObject + ) { + this.aiChatTextAreaRef = textAreaRef; + this.aiChatWindowRef = chatWindowRef; + } + + setAIChatFocus() { + if (this.aiChatTextAreaRef != null && this.aiChatTextAreaRef.current != null) { + this.aiChatTextAreaRef.current.focus(); + } + } + + grabCodeSelectSelection() { + if ( + this.codeSelectSelectedIndex.get() >= 0 && + this.codeSelectSelectedIndex.get() < this.codeSelectBlockRefArray.length + ) { + let curBlockRef = this.codeSelectBlockRefArray[this.codeSelectSelectedIndex.get()]; + let codeText = curBlockRef.current.innerText; + codeText = codeText.replace(/\n$/, ""); // remove trailing newline + let newLineValue = this.getCurLine() + " " + codeText; + this.setCurLine(newLineValue); + this.giveFocus(); + } + } + + addCodeBlockToCodeSelect(blockRef: React.RefObject): number { + let rtn = -1; + rtn = this.codeSelectBlockRefArray.length; + this.codeSelectBlockRefArray.push(blockRef); + return rtn; + } + + setCodeSelectSelectedCodeBlock(blockIndex: number) { + mobx.action(() => { + if (blockIndex >= 0 && blockIndex < this.codeSelectBlockRefArray.length) { + this.codeSelectSelectedIndex.set(blockIndex); + let currentRef = this.codeSelectBlockRefArray[blockIndex].current; + if (currentRef != null) { + if (this.aiChatWindowRef != null && this.aiChatWindowRef.current != null) { + let chatWindowTop = this.aiChatWindowRef.current.scrollTop; + let chatWindowBottom = chatWindowTop + this.aiChatWindowRef.current.clientHeight - 100; + let elemTop = currentRef.offsetTop; + let elemBottom = elemTop - currentRef.offsetHeight; + let elementIsInView = elemBottom < chatWindowBottom && elemTop > chatWindowTop; + if (!elementIsInView) { + this.aiChatWindowRef.current.scrollTop = + elemBottom - this.aiChatWindowRef.current.clientHeight / 3; + } + } + } + this.codeSelectBlockRefArray = []; + this.setAIChatFocus(); + } + })(); + } + + codeSelectSelectNextNewestCodeBlock() { + // oldest code block = index 0 in array + // this decrements codeSelectSelected index + mobx.action(() => { + if (this.codeSelectSelectedIndex.get() == this.codeSelectTop) { + this.codeSelectSelectedIndex.set(this.codeSelectBottom); + } else if (this.codeSelectSelectedIndex.get() == this.codeSelectBottom) { + return; + } + let incBlockIndex = this.codeSelectSelectedIndex.get() + 1; + if (this.codeSelectSelectedIndex.get() == this.codeSelectBlockRefArray.length - 1) { + this.codeSelectDeselectAll(); + if (this.aiChatWindowRef != null && this.aiChatWindowRef.current != null) { + this.aiChatWindowRef.current.scrollTop = this.aiChatWindowRef.current.scrollHeight; + } + } + if (incBlockIndex >= 0 && incBlockIndex < this.codeSelectBlockRefArray.length) { + this.setCodeSelectSelectedCodeBlock(incBlockIndex); + } + })(); + } + + codeSelectSelectNextOldestCodeBlock() { + mobx.action(() => { + if (this.codeSelectSelectedIndex.get() == this.codeSelectBottom) { + if (this.codeSelectBlockRefArray.length > 0) { + this.codeSelectSelectedIndex.set(this.codeSelectBlockRefArray.length); + } else { + return; + } + } else if (this.codeSelectSelectedIndex.get() == this.codeSelectTop) { + return; + } + let decBlockIndex = this.codeSelectSelectedIndex.get() - 1; + if (decBlockIndex < 0) { + this.codeSelectDeselectAll(this.codeSelectTop); + if (this.aiChatWindowRef != null && this.aiChatWindowRef.current != null) { + this.aiChatWindowRef.current.scrollTop = 0; + } + } + if (decBlockIndex >= 0 && decBlockIndex < this.codeSelectBlockRefArray.length) { + this.setCodeSelectSelectedCodeBlock(decBlockIndex); + } + })(); + } + + getCodeSelectSelectedIndex() { + return this.codeSelectSelectedIndex.get(); + } + + getCodeSelectRefArrayLength() { + return this.codeSelectBlockRefArray.length; + } + + codeBlockIsSelected(blockIndex: number): boolean { + return blockIndex == this.codeSelectSelectedIndex.get(); + } + + codeSelectDeselectAll(direction: number = this.codeSelectBottom) { + mobx.action(() => { + this.codeSelectSelectedIndex.set(direction); + this.codeSelectBlockRefArray = []; + })(); + } + + openAIAssistantChat(): void { + this.aIChatShow.set(true); + this.setAIChatFocus(); + } + + closeAIAssistantChat(): void { + this.aIChatShow.set(false); + this.giveFocus(); + } + + clearAIAssistantChat(): void { + let prtn = GlobalModel.submitChatInfoCommand("", "", true); + prtn.then((rtn) => { + if (rtn.success) { + } else { + console.log("submit chat command error: " + rtn.error); + } + }).catch((error) => { + console.log("submit chat command error: ", error); + }); + } + hasScrollingInfoMsg(): boolean { if (!this.infoShow.get()) { return false; @@ -1778,6 +1945,7 @@ class InputModel { resetInput(): void { mobx.action(() => { this.setHistoryShow(false); + this.closeAIAssistantChat(); this.infoShow.set(false); this.inputMode.set(null); this.resetHistory(); @@ -3834,6 +4002,9 @@ class Model { this.sessionListLoaded.set(true); this.remotesLoaded.set(true); } + if ("openaicmdinfochat" in update) { + this.inputModel.setOpenAICmdInfoChat(update.openaicmdinfochat); + } // console.log("run-update>", Date.now(), interactive, update); } @@ -4068,6 +4239,28 @@ class Model { return this.submitCommandPacket(pk, interactive); } + submitChatInfoCommand(chatMsg: string, curLineStr: string, clear: boolean): Promise { + let commandStr = "/chat " + chatMsg; + let interactive = false; + let pk: FeCmdPacketType = { + type: "fecmd", + metacmd: "eval", + args: [commandStr], + kwargs: {}, + uicontext: this.getUIContext(), + interactive: interactive, + rawstr: chatMsg, + }; + pk.kwargs["nohist"] = "1"; + if (clear) { + pk.kwargs["cmdinfoclear"] = "1"; + } else { + pk.kwargs["cmdinfo"] = "1"; + } + pk.kwargs["curline"] = curLineStr; + return this.submitCommandPacket(pk, interactive); + } + submitRawCommand(cmdStr: string, addToHistory: boolean, interactive: boolean): Promise { let pk: FeCmdPacketType = { type: "fecmd", diff --git a/src/types/types.ts b/src/types/types.ts index 29b6fb070..c69bbd709 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -265,6 +265,20 @@ type ScreenLinesType = { cmds: CmdDataType[]; }; +type OpenAIPacketOutputType = { + model: string; + created: number; + finish_reason: string; + message: string; + error?: string; +}; + +type OpenAICmdInfoChatMessageType = { + isassistantresponse?: boolean; + assistantresponse?: OpenAIPacketOutputType; + userquery?: string; +}; + type ModelUpdateType = { interactive: boolean; sessions?: SessionDataType[]; @@ -285,6 +299,7 @@ type ModelUpdateType = { clientdata?: ClientDataType; historyviewdata?: HistoryViewDataType; remoteview?: RemoteViewType; + openaicmdinfochat?: OpenAICmdInfoChatMessageType[]; alertmessage?: AlertMessageType; }; @@ -763,4 +778,5 @@ export type { ModalStoreEntry, StrWithPos, CmdInputTextPacketType, + OpenAICmdInfoChatMessageType, }; diff --git a/waveshell/pkg/packet/packet.go b/waveshell/pkg/packet/packet.go index f75030558..b485b6919 100644 --- a/waveshell/pkg/packet/packet.go +++ b/waveshell/pkg/packet/packet.go @@ -70,6 +70,8 @@ const PacketEOFStr = "EOF" var TypeStrToFactory map[string]reflect.Type +const OpenAICmdInfoChatGreetingMessage = "Hello, may I help you with this command? \n(Press ESC to close and Ctrl+L to clear chat buffer)" + func init() { TypeStrToFactory = make(map[string]reflect.Type) TypeStrToFactory[RunPacketStr] = reflect.TypeOf(RunPacketType{}) @@ -729,6 +731,14 @@ type OpenAIUsageType struct { TotalTokens int `json:"total_tokens,omitempty"` } +type OpenAICmdInfoPacketOutputType struct { + Model string `json:"model,omitempty"` + Created int64 `json:"created,omitempty"` + FinishReason string `json:"finish_reason,omitempty"` + Message string `json:"message,omitempty"` + Error string `json:"error,omitempty"` +} + type OpenAIPacketType struct { Type string `json:"type"` Model string `json:"model,omitempty"` @@ -843,6 +853,14 @@ func MakeWriteFileDonePacket(reqId string) *WriteFileDonePacketType { } } +type OpenAICmdInfoChatMessage struct { + MessageID int `json:"messageid"` + IsAssistantResponse bool `json:"isassistantresponse,omitempty"` + AssistantResponse *OpenAICmdInfoPacketOutputType `json:"assistantresponse,omitempty"` + UserQuery string `json:"userquery,omitempty"` + UserEngineeredQuery string `json:"userengineeredquery,omitempty"` +} + type OpenAIPromptMessageType struct { Role string `json:"role"` Content string `json:"content"` diff --git a/wavesrv/pkg/cmdrunner/cmdrunner.go b/wavesrv/pkg/cmdrunner/cmdrunner.go index 810771a58..36ff58d63 100644 --- a/wavesrv/pkg/cmdrunner/cmdrunner.go +++ b/wavesrv/pkg/cmdrunner/cmdrunner.go @@ -2001,6 +2001,114 @@ func doOpenAICompletion(cmd *sstore.CmdType, opts *sstore.OpenAIOptsType, prompt return } +func writePacketToUpdateBus(ctx context.Context, cmd *sstore.CmdType, pk *packet.OpenAICmdInfoChatMessage) { + update, err := sstore.UpdateWithAddNewOpenAICmdInfoPacket(ctx, cmd.ScreenId, pk) + if err != nil { + log.Printf("Open AI Update packet err: %v\n", err) + } + sstore.MainBus.SendScreenUpdate(cmd.ScreenId, update) +} + +func updateAsstResponseAndWriteToUpdateBus(ctx context.Context, cmd *sstore.CmdType, pk *packet.OpenAICmdInfoChatMessage, messageID int) { + update, err := sstore.UpdateWithUpdateOpenAICmdInfoPacket(ctx, cmd.ScreenId, messageID, pk) + if err != nil { + log.Printf("Open AI Update packet err: %v\n", err) + } + sstore.MainBus.SendScreenUpdate(cmd.ScreenId, update) +} + +func getCmdInfoEngineeredPrompt(userQuery string, curLineStr string) string { + rtn := "You are an expert on the command line terminal. Your task is to help me write a command." + if curLineStr != "" { + rtn += "My current command is: " + curLineStr + } + rtn += ". My question is: " + userQuery + "." + return rtn +} + +func doOpenAICmdInfoCompletion(cmd *sstore.CmdType, clientId string, opts *sstore.OpenAIOptsType, prompt []packet.OpenAIPromptMessageType, curLineStr string) { + var hadError bool + log.Println("had error: ", hadError) + ctx, cancelFn := context.WithTimeout(context.Background(), OpenAIStreamTimeout) + defer cancelFn() + defer func() { + r := recover() + if r != nil { + panicMsg := fmt.Sprintf("panic: %v", r) + log.Printf("panic in doOpenAICompletion: %s\n", panicMsg) + hadError = true + } + }() + var ch chan *packet.OpenAIPacketType + var err error + if opts.APIToken == "" { + var conn *websocket.Conn + ch, conn, err = openai.RunCloudCompletionStream(ctx, clientId, opts, prompt) + if conn != nil { + defer conn.Close() + } + } else { + ch, err = openai.RunCompletionStream(ctx, opts, prompt) + } + asstOutputPk := &packet.OpenAICmdInfoPacketOutputType{ + Model: "", + Created: 0, + FinishReason: "", + Message: "", + } + asstOutputMessageID := sstore.ScreenMemGetCmdInfoMessageCount(cmd.ScreenId) + asstMessagePk := &packet.OpenAICmdInfoChatMessage{IsAssistantResponse: true, AssistantResponse: asstOutputPk, MessageID: asstOutputMessageID} + if err != nil { + asstOutputPk.Error = fmt.Sprintf("Error calling OpenAI API: %v", err) + writePacketToUpdateBus(ctx, cmd, asstMessagePk) + return + } + writePacketToUpdateBus(ctx, cmd, asstMessagePk) + doneWaitingForPackets := false + for !doneWaitingForPackets { + select { + case <-time.After(OpenAIPacketTimeout): + // timeout reading from channel + hadError = true + doneWaitingForPackets = true + asstOutputPk.Error = "timeout waiting for server response" + updateAsstResponseAndWriteToUpdateBus(ctx, cmd, asstMessagePk, asstOutputMessageID) + break + case pk, ok := <-ch: + if ok { + // got a packet + if pk.Error != "" { + hadError = true + asstOutputPk.Error = pk.Error + } + if pk.Model != "" && pk.Index == 0 { + asstOutputPk.Model = pk.Model + asstOutputPk.Created = pk.Created + asstOutputPk.FinishReason = pk.FinishReason + if pk.Text != "" { + asstOutputPk.Message += pk.Text + } + } + if pk.Index == 0 { + if pk.FinishReason != "" { + asstOutputPk.FinishReason = pk.FinishReason + } + if pk.Text != "" { + asstOutputPk.Message += pk.Text + } + } + asstMessagePk.AssistantResponse = asstOutputPk + updateAsstResponseAndWriteToUpdateBus(ctx, cmd, asstMessagePk, asstOutputMessageID) + + } else { + // channel closed + doneWaitingForPackets = true + break + } + } + } +} + func doOpenAIStreamCompletion(cmd *sstore.CmdType, clientId string, opts *sstore.OpenAIOptsType, prompt []packet.OpenAIPromptMessageType) { var outputPos int64 var hadError bool @@ -2086,6 +2194,23 @@ func doOpenAIStreamCompletion(cmd *sstore.CmdType, clientId string, opts *sstore return } +func BuildOpenAIPromptArrayWithContext(messages []*packet.OpenAICmdInfoChatMessage) []packet.OpenAIPromptMessageType { + rtn := make([]packet.OpenAIPromptMessageType, 0) + for _, msg := range messages { + content := msg.UserEngineeredQuery + if msg.UserEngineeredQuery == "" { + content = msg.UserQuery + } + msgRole := sstore.OpenAIRoleUser + if msg.IsAssistantResponse { + msgRole = sstore.OpenAIRoleAssistant + content = msg.AssistantResponse.Message + } + rtn = append(rtn, packet.OpenAIPromptMessageType{Role: msgRole, Content: content}) + } + return rtn +} + func OpenAICommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) { ids, err := resolveUiIds(ctx, pk, R_Session|R_Screen) if err != nil { @@ -2111,9 +2236,6 @@ func OpenAICommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstor opts.MaxTokens = openai.DefaultMaxTokens } promptStr := firstArg(pk) - if promptStr == "" { - return nil, fmt.Errorf("openai error, prompt string is blank") - } ptermVal := defaultStr(pk.Kwargs["wterm"], DefaultPTERM) pkTermOpts, err := GetUITermOpts(pk.UIContext.WinSize, ptermVal) if err != nil { @@ -2124,11 +2246,40 @@ func OpenAICommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstor if err != nil { return nil, fmt.Errorf("openai error, cannot make dyn cmd") } + if resolveBool(pk.Kwargs["cmdinfo"], false) { + if promptStr == "" { + // this is requesting an update without wanting an openai query + update, err := sstore.UpdateWithCurrentOpenAICmdInfoChat(cmd.ScreenId) + if err != nil { + return nil, fmt.Errorf("error getting update for CmdInfoChat %v", err) + } + return update, nil + } + curLineStr := defaultStr(pk.Kwargs["curline"], "") + userQueryPk := &packet.OpenAICmdInfoChatMessage{UserQuery: promptStr, MessageID: sstore.ScreenMemGetCmdInfoMessageCount(cmd.ScreenId)} + engineeredQuery := getCmdInfoEngineeredPrompt(promptStr, curLineStr) + userQueryPk.UserEngineeredQuery = engineeredQuery + writePacketToUpdateBus(ctx, cmd, userQueryPk) + prompt := BuildOpenAIPromptArrayWithContext(sstore.ScreenMemGetCmdInfoChat(cmd.ScreenId).Messages) + go doOpenAICmdInfoCompletion(cmd, clientData.ClientId, opts, prompt, curLineStr) + update := &sstore.ModelUpdate{} + return update, nil + } + prompt := []packet.OpenAIPromptMessageType{{Role: sstore.OpenAIRoleUser, Content: promptStr}} + if resolveBool(pk.Kwargs["cmdinfoclear"], false) { + update, err := sstore.UpdateWithClearOpenAICmdInfo(cmd.ScreenId) + if err != nil { + return nil, fmt.Errorf("error clearing CmdInfoChat: %v", err) + } + return update, nil + } + if promptStr == "" { + return nil, fmt.Errorf("openai error, prompt string is blank") + } line, err := sstore.AddOpenAILine(ctx, ids.ScreenId, DefaultUserId, cmd) if err != nil { return nil, fmt.Errorf("cannot add new line: %v", err) } - prompt := []packet.OpenAIPromptMessageType{{Role: sstore.OpenAIRoleUser, Content: promptStr}} if resolveBool(pk.Kwargs["stream"], true) { go doOpenAIStreamCompletion(cmd, clientData.ClientId, opts, prompt) } else { diff --git a/wavesrv/pkg/sstore/dbops.go b/wavesrv/pkg/sstore/dbops.go index d2653cca5..e6a8b9278 100644 --- a/wavesrv/pkg/sstore/dbops.go +++ b/wavesrv/pkg/sstore/dbops.go @@ -748,6 +748,7 @@ func InsertScreen(ctx context.Context, sessionId string, origScreenName string, return nil, txErr } update.Sessions = []*SessionType{bareSession} + update.OpenAICmdInfoChat = ScreenMemGetCmdInfoChat(newScreenId).Messages } return update, nil } @@ -854,6 +855,29 @@ func GetCmdByScreenId(ctx context.Context, screenId string, lineId string) (*Cmd }) } +func UpdateWithClearOpenAICmdInfo(screenId string) (*ModelUpdate, error) { + ScreenMemClearCmdInfoChat(screenId) + return UpdateWithCurrentOpenAICmdInfoChat(screenId) +} + +func UpdateWithAddNewOpenAICmdInfoPacket(ctx context.Context, screenId string, pk *packet.OpenAICmdInfoChatMessage) (*ModelUpdate, error) { + ScreenMemAddCmdInfoChatMessage(screenId, pk) + return UpdateWithCurrentOpenAICmdInfoChat(screenId) +} + +func UpdateWithCurrentOpenAICmdInfoChat(screenId string) (*ModelUpdate, error) { + cmdInfoUpdate := ScreenMemGetCmdInfoChat(screenId).Messages + return &ModelUpdate{OpenAICmdInfoChat: cmdInfoUpdate}, nil +} + +func UpdateWithUpdateOpenAICmdInfoPacket(ctx context.Context, screenId string, messageID int, pk *packet.OpenAICmdInfoChatMessage) (*ModelUpdate, error) { + err := ScreenMemUpdateCmdInfoChatMessage(screenId, messageID, pk) + if err != nil { + return nil, err + } + return UpdateWithCurrentOpenAICmdInfoChat(screenId) +} + func UpdateCmdDoneInfo(ctx context.Context, ck base.CommandKey, donePk *packet.CmdDonePacketType, status string) (*ModelUpdate, error) { if donePk == nil { return nil, fmt.Errorf("invalid cmddone packet") @@ -1039,6 +1063,7 @@ func SwitchScreenById(ctx context.Context, sessionId string, screenId string) (* memState := GetScreenMemState(screenId) if memState != nil { update.CmdLine = &memState.CmdInputText + update.OpenAICmdInfoChat = ScreenMemGetCmdInfoChat(screenId).Messages } return update, nil } diff --git a/wavesrv/pkg/sstore/memops.go b/wavesrv/pkg/sstore/memops.go index 4571d8089..9b72a3bbf 100644 --- a/wavesrv/pkg/sstore/memops.go +++ b/wavesrv/pkg/sstore/memops.go @@ -5,9 +5,11 @@ package sstore import ( + "fmt" "log" "sync" + "github.com/wavetermdev/waveterm/waveshell/pkg/packet" "github.com/wavetermdev/waveterm/wavesrv/pkg/utilfn" ) @@ -43,11 +45,109 @@ func isIndicatorGreater(i1 string, i2 string) bool { return screenIndicatorLevels[i1] > screenIndicatorLevels[i2] } +type OpenAICmdInfoChatStore struct { + MessageCount int `json:"messagecount"` + Messages []*packet.OpenAICmdInfoChatMessage `json:"messages"` +} + type ScreenMemState struct { - NumRunningCommands int `json:"numrunningcommands,omitempty"` - IndicatorType string `json:"indicatortype,omitempty"` - CmdInputText utilfn.StrWithPos `json:"cmdinputtext,omitempty"` - CmdInputSeqNum int `json:"cmdinputseqnum,omitempty"` + NumRunningCommands int `json:"numrunningcommands,omitempty"` + IndicatorType string `json:"indicatortype,omitempty"` + CmdInputText utilfn.StrWithPos `json:"cmdinputtext,omitempty"` + CmdInputSeqNum int `json:"cmdinputseqnum,omitempty"` + AICmdInfoChat *OpenAICmdInfoChatStore `json:"aicmdinfochat,omitempty"` +} + +func ScreenMemDeepCopyCmdInfoChatStore(store *OpenAICmdInfoChatStore) *OpenAICmdInfoChatStore { + rtnMessages := []*packet.OpenAICmdInfoChatMessage{} + for index := 0; index < len(store.Messages); index++ { + messageToCopy := *store.Messages[index] + if messageToCopy.AssistantResponse != nil { + assistantResponseCopy := *messageToCopy.AssistantResponse + messageToCopy.AssistantResponse = &assistantResponseCopy + } + rtnMessages = append(rtnMessages, &messageToCopy) + } + rtn := &OpenAICmdInfoChatStore{MessageCount: store.MessageCount, Messages: rtnMessages} + return rtn +} + +func ScreenMemInitCmdInfoChat(screenId string) { + greetingMessagePk := &packet.OpenAICmdInfoChatMessage{ + MessageID: 0, + IsAssistantResponse: true, + AssistantResponse: &packet.OpenAICmdInfoPacketOutputType{ + Message: packet.OpenAICmdInfoChatGreetingMessage, + }, + } + ScreenMemStore[screenId].AICmdInfoChat = &OpenAICmdInfoChatStore{MessageCount: 1, Messages: []*packet.OpenAICmdInfoChatMessage{greetingMessagePk}} +} + +func ScreenMemClearCmdInfoChat(screenId string) { + MemLock.Lock() + defer MemLock.Unlock() + if ScreenMemStore[screenId] == nil { + ScreenMemStore[screenId] = &ScreenMemState{} + } + ScreenMemInitCmdInfoChat(screenId) +} + +func ScreenMemAddCmdInfoChatMessage(screenId string, msg *packet.OpenAICmdInfoChatMessage) { + MemLock.Lock() + defer MemLock.Unlock() + if ScreenMemStore[screenId] == nil { + ScreenMemStore[screenId] = &ScreenMemState{} + } + if ScreenMemStore[screenId].AICmdInfoChat == nil { + log.Printf("AICmdInfoChat is null, creating") + ScreenMemInitCmdInfoChat(screenId) + } + + CmdInfoChat := ScreenMemStore[screenId].AICmdInfoChat + CmdInfoChat.Messages = append(CmdInfoChat.Messages, msg) + CmdInfoChat.MessageCount++ +} + +func ScreenMemGetCmdInfoMessageCount(screenId string) int { + MemLock.Lock() + defer MemLock.Unlock() + if ScreenMemStore[screenId] == nil { + ScreenMemStore[screenId] = &ScreenMemState{} + } + if ScreenMemStore[screenId].AICmdInfoChat == nil { + ScreenMemInitCmdInfoChat(screenId) + } + return ScreenMemStore[screenId].AICmdInfoChat.MessageCount +} + +func ScreenMemGetCmdInfoChat(screenId string) *OpenAICmdInfoChatStore { + MemLock.Lock() + defer MemLock.Unlock() + if ScreenMemStore[screenId] == nil { + ScreenMemStore[screenId] = &ScreenMemState{} + } + if ScreenMemStore[screenId].AICmdInfoChat == nil { + ScreenMemInitCmdInfoChat(screenId) + } + return ScreenMemDeepCopyCmdInfoChatStore(ScreenMemStore[screenId].AICmdInfoChat) +} + +func ScreenMemUpdateCmdInfoChatMessage(screenId string, messageID int, msg *packet.OpenAICmdInfoChatMessage) error { + MemLock.Lock() + defer MemLock.Unlock() + if ScreenMemStore[screenId] == nil { + ScreenMemStore[screenId] = &ScreenMemState{} + } + if ScreenMemStore[screenId].AICmdInfoChat == nil { + ScreenMemInitCmdInfoChat(screenId) + } + CmdInfoChat := ScreenMemStore[screenId].AICmdInfoChat + if messageID >= 0 && messageID < len(CmdInfoChat.Messages) { + CmdInfoChat.Messages[messageID] = msg + } else { + return fmt.Errorf("ScreenMemUpdateCmdInfoChatMessage: error: Message Id out of range: %d", messageID) + } + return nil } func ScreenMemSetCmdInputText(screenId string, sp utilfn.StrWithPos, seqNum int) { diff --git a/wavesrv/pkg/sstore/updatebus.go b/wavesrv/pkg/sstore/updatebus.go index a3715d934..8247c4d2f 100644 --- a/wavesrv/pkg/sstore/updatebus.go +++ b/wavesrv/pkg/sstore/updatebus.go @@ -8,6 +8,7 @@ import ( "log" "sync" + "github.com/wavetermdev/waveterm/waveshell/pkg/packet" "github.com/wavetermdev/waveterm/wavesrv/pkg/utilfn" ) @@ -38,29 +39,30 @@ 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"` - AlertMessage *AlertMessageType `json:"alertmessage,omitempty"` + 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"` } func (*ModelUpdate) UpdateType() string { From ed2a3455552d5ed0fb42e3902ef24cbb1924660f Mon Sep 17 00:00:00 2001 From: Evan Simkowitz Date: Thu, 11 Jan 2024 20:49:13 -0500 Subject: [PATCH 21/25] Add support for opening web links in the default browser (#221) * Add support for opening web links in the default browser * require modifier key to click * undo emain change * remove newline --- package.json | 3 ++- src/electron/emain.ts | 8 ++++++++ src/electron/preload.js | 1 + src/model/model.ts | 11 +++++++++++ src/plugins/terminal/term.ts | 18 ++++++++++++++++++ yarn.lock | 5 +++++ 6 files changed, 45 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 66db33ea3..9779edc70 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,8 @@ "tsx-control-statements": "^4.1.1", "uuid": "^9.0.0", "winston": "^3.8.2", - "xterm": "^5.0.0" + "xterm": "^5.0.0", + "xterm-addon-web-links": "^0.9.0" }, "devDependencies": { "@babel/cli": "^7.17.10", diff --git a/src/electron/emain.ts b/src/electron/emain.ts index 4f4602fa6..70f0691c1 100644 --- a/src/electron/emain.ts +++ b/src/electron/emain.ts @@ -485,6 +485,14 @@ electron.ipcMain.on("reload-window", (event) => { return; }); +electron.ipcMain.on("open-external-link", async (_, url) => { + try { + await electron.shell.openExternal(url); + } catch (err) { + console.warn("error opening external link", err); + } +}); + electron.ipcMain.on("get-last-logs", async (event, numberOfLines) => { try { const logPath = path.join(getWaveHomeDir(), "wavesrv.log"); diff --git a/src/electron/preload.js b/src/electron/preload.js index 1abe03611..c58eafc11 100644 --- a/src/electron/preload.js +++ b/src/electron/preload.js @@ -12,6 +12,7 @@ contextBridge.exposeInMainWorld("api", { }, restartWaveSrv: () => ipcRenderer.sendSync("restart-server"), reloadWindow: () => ipcRenderer.sendSync("reload-window"), + openExternalLink: (url) => ipcRenderer.send("open-external-link", url), onTCmd: (callback) => ipcRenderer.on("t-cmd", callback), onICmd: (callback) => ipcRenderer.on("i-cmd", callback), onLCmd: (callback) => ipcRenderer.on("l-cmd", callback), diff --git a/src/model/model.ts b/src/model/model.ts index f7cc0d56b..29b6487e4 100644 --- a/src/model/model.ts +++ b/src/model/model.ts @@ -196,6 +196,7 @@ type ElectronApi = { getWaveSrvStatus: () => boolean; restartWaveSrv: () => boolean; reloadWindow: () => void; + openExternalLink: (url: string) => void; onTCmd: (callback: (mods: KeyModsType) => void) => void; onICmd: (callback: (mods: KeyModsType) => void) => void; onLCmd: (callback: (mods: KeyModsType) => void) => void; @@ -3424,6 +3425,16 @@ class Model { getApi().reloadWindow(); } + /** + * Opens a new default browser window to the given url + * @param {string} url The url to open + */ + openExternalLink(url: string): void { + console.log("opening external link: " + url); + getApi().openExternalLink(url); + console.log("finished opening external link"); + } + refocus() { // givefocus() give back focus to cmd or input let activeScreen = this.getActiveScreen(); diff --git a/src/plugins/terminal/term.ts b/src/plugins/terminal/term.ts index 446fb24f0..8c9d4ca88 100644 --- a/src/plugins/terminal/term.ts +++ b/src/plugins/terminal/term.ts @@ -3,10 +3,13 @@ import * as mobx from "mobx"; import { Terminal } from "xterm"; +//TODO: replace with `@xterm/addon-web-links` when it's available as stable +import { WebLinksAddon } from "xterm-addon-web-links"; import { sprintf } from "sprintf-js"; import { boundMethod } from "autobind-decorator"; import { windowWidthToCols, windowHeightToRows } from "../../util/textmeasure"; import { boundInt } from "../../util/util"; +import { GlobalModel } from "../../model/model" import type { TermContextUnion, TermOptsType, @@ -96,6 +99,21 @@ class TermWrap { fontFamily: "JetBrains Mono", theme: { foreground: terminal.foreground, background: terminal.background }, }); + this.terminal.loadAddon(new WebLinksAddon((e, uri) => { + e.preventDefault(); + switch (GlobalModel.platform) { + case "darwin": + if (e.metaKey) { + GlobalModel.openExternalLink(uri); + } + break; + default: + if (e.ctrlKey) { + GlobalModel.openExternalLink(uri); + } + break; + } + })); this.terminal._core._inputHandler._parser.setErrorHandler((state) => { this.numParseErrors++; return state; diff --git a/yarn.lock b/yarn.lock index 7c077f71b..0e033fd54 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8466,6 +8466,11 @@ xmlbuilder@^15.1.1: resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-15.1.1.tgz#9dcdce49eea66d8d10b42cae94a79c3c8d0c2ec5" integrity sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg== +xterm-addon-web-links@^0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.9.0.tgz#c65b18588d1f613e703eb6feb7f129e7ff1c63e7" + integrity sha512-LIzi4jBbPlrKMZF3ihoyqayWyTXAwGfu4yprz1aK2p71e9UKXN6RRzVONR0L+Zd+Ik5tPVI9bwp9e8fDTQh49Q== + xterm@^5.0.0: version "5.3.0" resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.3.0.tgz#867daf9cc826f3d45b5377320aabd996cb0fce46" From ebdf8b5aee804ed0437cb41e03f718d0b1b09205 Mon Sep 17 00:00:00 2001 From: Evan Simkowitz Date: Thu, 11 Jan 2024 21:28:21 -0500 Subject: [PATCH 22/25] Remove unused and unmaintained `react-json-view` (#223) --- package.json | 1 - yarn.lock | 146 ++------------------------------------------------- 2 files changed, 3 insertions(+), 144 deletions(-) diff --git a/package.json b/package.json index 9779edc70..1125cec6a 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,6 @@ "papaparse": "^5.4.1", "react": "^18.1.0", "react-dom": "^18.1.0", - "react-json-view": "^1.21.3", "react-markdown": "^9.0.0", "remark": "^15.0.1", "remark-gfm": "^4.0.0", diff --git a/yarn.lock b/yarn.lock index 0e033fd54..aebd7553c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1304,13 +1304,6 @@ resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== -"@babel/runtime@^7.20.13": - version "7.23.1" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.1.tgz#72741dc4d413338a91dcb044a86f3c0bc402646d" - integrity sha512-hC2v6p8ZSI/W0HUzh3V8C5g+NwSKzKPtJwSpTjwl0o297GP9+ZLQSkdvHz46CM3LqyoXxq+5G9komY+eSqSO0g== - dependencies: - regenerator-runtime "^0.14.0" - "@babel/runtime@^7.8.4": version "7.23.5" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.5.tgz#11edb98f8aeec529b82b211028177679144242db" @@ -2656,11 +2649,6 @@ array-flatten@^2.1.2: resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== -asap@~2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== - asar@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/asar/-/asar-3.2.0.tgz#e6edb5edd6f627ebef04db62f771c61bea9c1221" @@ -2754,11 +2742,6 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -base16@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/base16/-/base16-1.0.0.tgz#e297f60d7ec1014a7a971a39ebc8a98c0b681e70" - integrity sha512-pNdYkNPiJUnEhnfXV56+sQy8+AaPcG3POZAUnwr4EeqCUZFz4u2PePbo3e5Gj4ziYPCWGUZT9RHisvJKnwFuBQ== - base64-js@^1.3.1, base64-js@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" @@ -3325,13 +3308,6 @@ cosmiconfig@^8.1.3: parse-json "^5.2.0" path-type "^4.0.0" -cross-fetch@^3.1.5: - version "3.1.8" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82" - integrity sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg== - dependencies: - node-fetch "^2.6.12" - cross-spawn-windows-exe@^1.1.0, cross-spawn-windows-exe@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/cross-spawn-windows-exe/-/cross-spawn-windows-exe-1.2.0.tgz#46253b0f497676e766faf4a7061004618b5ac5ec" @@ -4073,31 +4049,6 @@ faye-websocket@^0.11.3: dependencies: websocket-driver ">=0.5.1" -fbemitter@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/fbemitter/-/fbemitter-3.0.0.tgz#00b2a1af5411254aab416cd75f9e6289bee4bff3" - integrity sha512-KWKaceCwKQU0+HPoop6gn4eOHk50bBv/VxjJtGMfwmJt3D29JpN4H4eisCtIPA+a8GVBam+ldMMpMjJUvpDyHw== - dependencies: - fbjs "^3.0.0" - -fbjs-css-vars@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz#216551136ae02fe255932c3ec8775f18e2c078b8" - integrity sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ== - -fbjs@^3.0.0, fbjs@^3.0.1: - version "3.0.5" - resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-3.0.5.tgz#aa0edb7d5caa6340011790bd9249dbef8a81128d" - integrity sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg== - dependencies: - cross-fetch "^3.1.5" - fbjs-css-vars "^1.0.0" - loose-envify "^1.0.0" - object-assign "^4.1.0" - promise "^7.1.1" - setimmediate "^1.0.5" - ua-parser-js "^1.0.35" - fd-slicer@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" @@ -4212,14 +4163,6 @@ flora-colossus@^2.0.0: debug "^4.3.4" fs-extra "^10.1.0" -flux@^4.0.1: - version "4.0.4" - resolved "https://registry.yarnpkg.com/flux/-/flux-4.0.4.tgz#9661182ea81d161ee1a6a6af10d20485ef2ac572" - integrity sha512-NCj3XlayA2UsapRpM7va6wU1+9rE5FIL7qoMcmxWHRzbp0yujihMBm9BBHZ1MDIk5h5o2Bl6eGiCe8rYELAmYw== - dependencies: - fbemitter "^3.0.0" - fbjs "^3.0.1" - fn.name@1.x.x: version "1.1.0" resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" @@ -5299,21 +5242,11 @@ lodash._reinterpolate@^3.0.0: resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" integrity sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA== -lodash.curry@^4.0.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.curry/-/lodash.curry-4.1.1.tgz#248e36072ede906501d75966200a86dab8b23170" - integrity sha512-/u14pXGviLaweY5JI0IUzgzF2J6Ne8INyzAZjImcryjgkZ+ebruBxy2/JaOOkTqScddcYtakjhSaeemV8lR0tA== - lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== -lodash.flow@^3.3.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/lodash.flow/-/lodash.flow-3.5.0.tgz#87bf40292b8cf83e4e8ce1a3ae4209e20071675a" - integrity sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw== - lodash.get@^4.0.0: version "4.4.2" resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" @@ -5374,7 +5307,7 @@ longest-streak@^3.0.0: resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-3.1.0.tgz#62fa67cd958742a1574af9f39866364102d90cd4" integrity sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g== -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: +loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== @@ -6217,7 +6150,7 @@ node-domexception@^1.0.0: resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== -node-fetch@^2.6.12, node-fetch@^2.6.7: +node-fetch@^2.6.7: version "2.7.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== @@ -6318,7 +6251,7 @@ nth-check@^2.0.1: dependencies: boolbase "^1.0.0" -object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== @@ -6753,13 +6686,6 @@ promise-retry@^2.0.1: err-code "^2.0.2" retry "^0.12.0" -promise@^7.1.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" - integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg== - dependencies: - asap "~2.0.3" - prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" @@ -6800,11 +6726,6 @@ punycode@^2.1.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== -pure-color@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/pure-color/-/pure-color-1.3.0.tgz#1fe064fb0ac851f0de61320a8bf796836422f33e" - integrity sha512-QFADYnsVoBMw1srW7OVKEYjG+MbIa49s54w1MA1EDY6r2r/sTcKKYqRX1f4GYvnXP7eN/Pe9HFcX+hwzmrXRHA== - qs@6.11.0: version "6.11.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" @@ -6866,16 +6787,6 @@ rcedit@^3.0.1: dependencies: cross-spawn-windows-exe "^1.1.0" -react-base16-styling@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/react-base16-styling/-/react-base16-styling-0.6.0.tgz#ef2156d66cf4139695c8a167886cb69ea660792c" - integrity sha512-yvh/7CArceR/jNATXOKDlvTnPKPmGZz7zsenQ3jUwLzHkNUR0CvY3yGYJbWJ/nnxsL8Sgmt5cO3/SILVuPO6TQ== - dependencies: - base16 "^1.0.0" - lodash.curry "^4.0.1" - lodash.flow "^3.3.0" - pure-color "^1.2.0" - react-dom@^18.1.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" @@ -6889,21 +6800,6 @@ react-is@^16.13.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== -react-json-view@^1.21.3: - version "1.21.3" - resolved "https://registry.yarnpkg.com/react-json-view/-/react-json-view-1.21.3.tgz#f184209ee8f1bf374fb0c41b0813cff54549c475" - integrity sha512-13p8IREj9/x/Ye4WI/JpjhoIwuzEgUAtgJZNBJckfzJt1qyh24BdTm6UQNGnyTq9dapQdrqvquZTo3dz1X6Cjw== - dependencies: - flux "^4.0.1" - react-base16-styling "^0.6.0" - react-lifecycles-compat "^3.0.4" - react-textarea-autosize "^8.3.2" - -react-lifecycles-compat@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" - integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== - react-markdown@^9.0.0: version "9.0.1" resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-9.0.1.tgz#c05ddbff67fd3b3f839f8c648e6fb35d022397d1" @@ -6927,15 +6823,6 @@ react-split-it@^2.0.0: dependencies: prop-types "^15.8.1" -react-textarea-autosize@^8.3.2: - version "8.5.3" - resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.5.3.tgz#d1e9fe760178413891484847d3378706052dd409" - integrity sha512-XT1024o2pqCuZSuBt9FwHlaDeNtVrtCXu0Rnz88t1jUGheCLa3PhjE1GH8Ctm2axEtvdCl5SUHYschyQ0L5QHQ== - dependencies: - "@babel/runtime" "^7.20.13" - use-composed-ref "^1.3.0" - use-latest "^1.2.1" - react@^18.1.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" @@ -7399,11 +7286,6 @@ set-blocking@^2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== -setimmediate@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== - setprototypeof@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" @@ -7950,11 +7832,6 @@ typescript@^4.7.3: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== -ua-parser-js@^1.0.35: - version "1.0.36" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.36.tgz#a9ab6b9bd3a8efb90bb0816674b412717b7c428c" - integrity sha512-znuyCIXzl8ciS3+y3fHJI/2OhQIXbXw9MWC/o3qwyR+RGppjZHrM27CGFSKCJXi2Kctiz537iOu2KnXs1lMQhw== - undici-types@~5.26.4: version "5.26.5" resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" @@ -8098,23 +7975,6 @@ url-join@^4.0.1: resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.1.tgz#b642e21a2646808ffa178c4c5fda39844e12cde7" integrity sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA== -use-composed-ref@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/use-composed-ref/-/use-composed-ref-1.3.0.tgz#3d8104db34b7b264030a9d916c5e94fbe280dbda" - integrity sha512-GLMG0Jc/jiKov/3Ulid1wbv3r54K9HlMW29IWcDFPEqFkSO2nS0MuefWgMJpeHQ9YJeXDL3ZUF+P3jdXlZX/cQ== - -use-isomorphic-layout-effect@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz#497cefb13d863d687b08477d9e5a164ad8c1a6fb" - integrity sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA== - -use-latest@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/use-latest/-/use-latest-1.2.1.tgz#d13dfb4b08c28e3e33991546a2cee53e14038cf2" - integrity sha512-xA+AVm/Wlg3e2P/JiItTziwS7FK92LWrDB0p+hgXloIMuVCeJJ8v6f0eeHyPZaJrM+usM1FkFfbNCrJGs8A/zw== - dependencies: - use-isomorphic-layout-effect "^1.1.1" - username@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/username/-/username-5.1.0.tgz#a7f9325adce2d0166448cdd55d4985b1360f2508" From f8024799ed62c518cc15874954c7135189b83854 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 11 Jan 2024 18:31:07 -0800 Subject: [PATCH 23/25] Bump follow-redirects from 1.15.3 to 1.15.4 (#222) Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.3 to 1.15.4. - [Release notes](https://github.com/follow-redirects/follow-redirects/releases) - [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.3...v1.15.4) --- updated-dependencies: - dependency-name: follow-redirects dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index aebd7553c..d762a0d47 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4169,9 +4169,9 @@ fn.name@1.x.x: integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== follow-redirects@^1.0.0: - version "1.15.3" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.3.tgz#fe2f3ef2690afce7e82ed0b44db08165b207123a" - integrity sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q== + version "1.15.4" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.4.tgz#cdc7d308bf6493126b17ea2191ea0ccf3e535adf" + integrity sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw== formdata-polyfill@^4.0.10: version "4.0.10" From d431ac1ecf4c253f12aca049fa65e268df272bc7 Mon Sep 17 00:00:00 2001 From: Evan Simkowitz Date: Thu, 11 Jan 2024 21:57:15 -0500 Subject: [PATCH 24/25] Upgrade to Typescript 5, along with a bunch of other minor bumps (#224) * Bump electron and dependencies * upgrade typescript and webpack * upgrade remaining outdated * bump node types --- package.json | 4 +- yarn.lock | 696 ++++++++++++++++++++++++++++----------------------- 2 files changed, 390 insertions(+), 310 deletions(-) diff --git a/package.json b/package.json index 1125cec6a..f118fe5ca 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "@svgr/webpack": "^8.1.0", "@types/classnames": "^2.3.1", "@types/electron": "^1.6.10", - "@types/node": "20.10.3", + "@types/node": "20.11.0", "@types/papaparse": "^5.3.10", "@types/react": "^18.0.12", "@types/sprintf-js": "^1.1.3", @@ -82,7 +82,7 @@ "raw-loader": "^4.0.2", "react-split-it": "^2.0.0", "style-loader": "^3.3.1", - "typescript": "^4.7.3", + "typescript": "^5.0.0", "webpack": "^5.73.0", "webpack-bundle-analyzer": "^4.10.1", "webpack-cli": "^5.1.4", diff --git a/yarn.lock b/yarn.lock index d762a0d47..dfe7e7c3b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -47,7 +47,7 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.2.tgz#6a12ced93455827037bfb5ed8492820d60fc32cc" integrity sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ== -"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.22.9", "@babel/compat-data@^7.23.3", "@babel/compat-data@^7.23.5": +"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.23.3", "@babel/compat-data@^7.23.5": version "7.23.5" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98" integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw== @@ -74,27 +74,27 @@ semver "^6.3.1" "@babel/core@^7.18.2": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.5.tgz#6e23f2acbcb77ad283c5ed141f824fd9f70101c7" - integrity sha512-Cwc2XjUrG4ilcfOw4wBAK+enbdgwAcAJCfGUItPBKR7Mjw4aEfAFYrLxeRp4jWgtNIKn3n2AlBOfwwafl+42/g== + version "7.23.7" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.7.tgz#4d8016e06a14b5f92530a13ed0561730b5c6483f" + integrity sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw== dependencies: "@ampproject/remapping" "^2.2.0" "@babel/code-frame" "^7.23.5" - "@babel/generator" "^7.23.5" - "@babel/helper-compilation-targets" "^7.22.15" + "@babel/generator" "^7.23.6" + "@babel/helper-compilation-targets" "^7.23.6" "@babel/helper-module-transforms" "^7.23.3" - "@babel/helpers" "^7.23.5" - "@babel/parser" "^7.23.5" + "@babel/helpers" "^7.23.7" + "@babel/parser" "^7.23.6" "@babel/template" "^7.22.15" - "@babel/traverse" "^7.23.5" - "@babel/types" "^7.23.5" + "@babel/traverse" "^7.23.7" + "@babel/types" "^7.23.6" convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" json5 "^2.2.3" semver "^6.3.1" -"@babel/generator@^7.23.0", "@babel/generator@^7.23.5": +"@babel/generator@^7.23.0": version "7.23.5" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.5.tgz#17d0a1ea6b62f351d281350a5f80b87a810c4755" integrity sha512-BPssCHrBD+0YrxviOa3QzpqwhNIXKEtOa2jQrm4FlmkC2apYgRnQcmPWiGZDlGxiNtltnUFolMe8497Esry+jA== @@ -104,6 +104,16 @@ "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" +"@babel/generator@^7.23.5", "@babel/generator@^7.23.6": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" + integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw== + dependencies: + "@babel/types" "^7.23.6" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + "@babel/helper-annotate-as-pure@^7.18.6", "@babel/helper-annotate-as-pure@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" @@ -118,14 +128,14 @@ dependencies: "@babel/types" "^7.22.15" -"@babel/helper-compilation-targets@^7.22.15", "@babel/helper-compilation-targets@^7.22.6": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz#0698fc44551a26cf29f18d4662d5bf545a6cfc52" - integrity sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw== +"@babel/helper-compilation-targets@^7.22.15", "@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.23.6": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" + integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ== dependencies: - "@babel/compat-data" "^7.22.9" - "@babel/helper-validator-option" "^7.22.15" - browserslist "^4.21.9" + "@babel/compat-data" "^7.23.5" + "@babel/helper-validator-option" "^7.23.5" + browserslist "^4.22.2" lru-cache "^5.1.1" semver "^6.3.1" @@ -144,10 +154,10 @@ "@babel/helper-split-export-declaration" "^7.22.6" semver "^6.3.1" -"@babel/helper-create-class-features-plugin@^7.22.15", "@babel/helper-create-class-features-plugin@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.5.tgz#2a8792357008ae9ce8c0f2b78b9f646ac96b314b" - integrity sha512-QELlRWxSpgdwdJzSJn4WAhKC+hvw/AtHbbrIoncKHkhKKR/luAlKkgBDcri1EzWAo8f8VvYVryEHN4tax/V67A== +"@babel/helper-create-class-features-plugin@^7.22.15", "@babel/helper-create-class-features-plugin@^7.23.5", "@babel/helper-create-class-features-plugin@^7.23.7": + version "7.23.7" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.7.tgz#b2e6826e0e20d337143655198b79d58fdc9bd43d" + integrity sha512-xCoqR/8+BoNnXOY7RVSgv6X+o7pmT5q1d+gGcRlXYkI+9B31glE4jeejhKVpA04O1AtzOt7OSQ6VYKP5FcRl9g== dependencies: "@babel/helper-annotate-as-pure" "^7.22.5" "@babel/helper-environment-visitor" "^7.22.20" @@ -168,10 +178,10 @@ regexpu-core "^5.3.1" semver "^6.3.1" -"@babel/helper-define-polyfill-provider@^0.4.3": - version "0.4.3" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.3.tgz#a71c10f7146d809f4a256c373f462d9bba8cf6ba" - integrity sha512-WBrLmuPP47n7PNwsZ57pqam6G/RGo1vw/87b0Blc53tZNGZ4x7YvZ6HgQe2vo1W/FR20OgjeZuGXzudPiXHFug== +"@babel/helper-define-polyfill-provider@^0.4.3", "@babel/helper-define-polyfill-provider@^0.4.4": + version "0.4.4" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.4.tgz#64df615451cb30e94b59a9696022cffac9a10088" + integrity sha512-QcJMILQCu2jm5TFPGA3lCpJJTeEP+mqeXooG/NZbg/h5FTFi6V0+99ahlRsW8/kRLyb24LZVCCiclDedhLKcBA== dependencies: "@babel/helper-compilation-targets" "^7.22.6" "@babel/helper-plugin-utils" "^7.22.5" @@ -308,14 +318,14 @@ "@babel/traverse" "^7.23.2" "@babel/types" "^7.23.0" -"@babel/helpers@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.5.tgz#52f522840df8f1a848d06ea6a79b79eefa72401e" - integrity sha512-oO7us8FzTEsG3U6ag9MfdF1iA/7Z6dz+MtFhifZk8C8o453rGJFFWUP1t+ULM9TUIAzC9uxXEiXjOiVMyd7QPg== +"@babel/helpers@^7.23.7": + version "7.23.8" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.8.tgz#fc6b2d65b16847fd50adddbd4232c76378959e34" + integrity sha512-KDqYz4PiOWvDFrdHLPhKtCThtIcKVy6avWD2oG4GEvyQ+XDZwHD4YQd+H2vNMnq2rkdxsDkU82T+Vk8U/WXHRQ== dependencies: "@babel/template" "^7.22.15" - "@babel/traverse" "^7.23.5" - "@babel/types" "^7.23.5" + "@babel/traverse" "^7.23.7" + "@babel/types" "^7.23.6" "@babel/highlight@^7.22.13", "@babel/highlight@^7.23.4": version "7.23.4" @@ -326,7 +336,12 @@ chalk "^2.4.2" js-tokens "^4.0.0" -"@babel/parser@^7.22.15", "@babel/parser@^7.23.0", "@babel/parser@^7.23.5": +"@babel/parser@^7.22.15", "@babel/parser@^7.23.5", "@babel/parser@^7.23.6": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.6.tgz#ba1c9e512bda72a47e285ae42aff9d2a635a9e3b" + integrity sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ== + +"@babel/parser@^7.23.0": version "7.23.5" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.5.tgz#37dee97c4752af148e1d38c34b856b2507660563" integrity sha512-hOOqoiNXrmGdFbhgCzu6GiURxUgM27Xwd/aPuu8RfHEZPBzL1Z54okAHAQjXfcQNwvrlkAmAp4SlRTZ45vlthQ== @@ -347,10 +362,10 @@ "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" "@babel/plugin-transform-optional-chaining" "^7.23.3" -"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.3.tgz#20c60d4639d18f7da8602548512e9d3a4c8d7098" - integrity sha512-XaJak1qcityzrX0/IU5nKHb34VaibwP3saKqG6a/tppelgllOH13LUann4ZCIBcVOeE6H18K4Vx9QKkVww3z/w== +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.23.7": + version "7.23.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.7.tgz#516462a95d10a9618f197d39ad291a9b47ae1d7b" + integrity sha512-LlRT7HgaifEpQA1ZgLVOIJZZFVPWN5iReq/7/JixwBtwcoeVGDBD53ZV28rrsLYOZs1Y/EHhA8N/Z6aazHR8cw== dependencies: "@babel/helper-environment-visitor" "^7.22.20" "@babel/helper-plugin-utils" "^7.22.5" @@ -364,14 +379,12 @@ "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-proposal-decorators@^7.18.2": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.23.5.tgz#eeaa49d0dc9229aec4d23378653738cdc5a3ea0a" - integrity sha512-6IsY8jOeWibsengGlWIezp7cuZEFzNlAghFpzh9wiZwhQ42/hRcPnY/QV9HJoKTlujupinSlnQPiEy/u2C1ZfQ== + version "7.23.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.23.7.tgz#1d827902cbd3d9054e54fb2f2056cdd1eaa0e368" + integrity sha512-b1s5JyeMvqj7d9m9KhJNHKc18gEJiSyVzVX3bwbiPalQBQpuvfPh6lA9F7Kk/dWH0TIiXRpB9yicwijY6buPng== dependencies: - "@babel/helper-create-class-features-plugin" "^7.23.5" + "@babel/helper-create-class-features-plugin" "^7.23.7" "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-replace-supers" "^7.22.20" - "@babel/helper-split-export-declaration" "^7.22.6" "@babel/plugin-syntax-decorators" "^7.23.3" "@babel/plugin-proposal-private-methods@^7.18.6": @@ -562,10 +575,10 @@ "@babel/helper-remap-async-to-generator" "^7.22.20" "@babel/plugin-syntax-async-generators" "^7.8.4" -"@babel/plugin-transform-async-generator-functions@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.4.tgz#93ac8e3531f347fba519b4703f9ff2a75c6ae27a" - integrity sha512-efdkfPhHYTtn0G6n2ddrESE91fgXxjlqLsnUtPWnJs4a4mZIbUaK7ffqKIIUKXSHwcDvaCVX6GXkaJJFqtX7jw== +"@babel/plugin-transform-async-generator-functions@^7.23.7": + version "7.23.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.7.tgz#3aa0b4f2fa3788b5226ef9346cf6d16ec61f99cd" + integrity sha512-PdxEpL71bJp1byMG0va5gwQcXHxuEYC/BgI/e88mGTtohbZN28O5Yit0Plkkm/dBzCF/BxmbNcses1RH1T+urA== dependencies: "@babel/helper-environment-visitor" "^7.22.20" "@babel/helper-plugin-utils" "^7.22.5" @@ -619,7 +632,7 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-class-static-block" "^7.14.5" -"@babel/plugin-transform-classes@^7.22.15", "@babel/plugin-transform-classes@^7.23.5": +"@babel/plugin-transform-classes@^7.22.15": version "7.23.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.5.tgz#e7a75f815e0c534cc4c9a39c56636c84fc0d64f2" integrity sha512-jvOTR4nicqYC9yzOHIhXG5emiFEOpappSJAl73SDSEDcybD+Puuze8Tnpb9p9qEyYup24tq891gkaygIFvWDqg== @@ -634,6 +647,20 @@ "@babel/helper-split-export-declaration" "^7.22.6" globals "^11.1.0" +"@babel/plugin-transform-classes@^7.23.8": + version "7.23.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.8.tgz#d08ae096c240347badd68cdf1b6d1624a6435d92" + integrity sha512-yAYslGsY1bX6Knmg46RjiCiNSwJKv2IUC8qOdYKqMMr0491SXFhcHqOdRDeCRohOOIzwN/90C6mQ9qAKgrP7dg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-compilation-targets" "^7.23.6" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.20" + "@babel/helper-split-export-declaration" "^7.22.6" + globals "^11.1.0" + "@babel/plugin-transform-computed-properties@^7.22.5", "@babel/plugin-transform-computed-properties@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz#652e69561fcc9d2b50ba4f7ac7f60dcf65e86474" @@ -695,13 +722,21 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" -"@babel/plugin-transform-for-of@^7.22.15", "@babel/plugin-transform-for-of@^7.23.3": +"@babel/plugin-transform-for-of@^7.22.15": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.3.tgz#afe115ff0fbce735e02868d41489093c63e15559" integrity sha512-X8jSm8X1CMwxmK878qsUGJRmbysKNbdpTv/O1/v0LuY/ZkZrng5WYiekYSdg9m09OTmDDUWeEDsTE+17WYbAZw== dependencies: "@babel/helper-plugin-utils" "^7.22.5" +"@babel/plugin-transform-for-of@^7.23.6": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz#81c37e24171b37b370ba6aaffa7ac86bcb46f94e" + integrity sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/plugin-transform-function-name@^7.22.5", "@babel/plugin-transform-function-name@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz#8f424fcd862bf84cb9a1a6b42bc2f47ed630f8dc" @@ -984,15 +1019,15 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-runtime@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.23.4.tgz#5132b388580002fc5cb7c84eccfb968acdc231cb" - integrity sha512-ITwqpb6V4btwUG0YJR82o2QvmWrLgDnx/p2A3CTPYGaRgULkDiC0DRA2C4jlRB9uXGUEfaSS/IGHfVW+ohzYDw== + version "7.23.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.23.7.tgz#52bbd20054855beb9deae3bee9ceb05289c343e6" + integrity sha512-fa0hnfmiXc9fq/weK34MUV0drz2pOL/vfKWvN7Qw127hiUPabFCUMgAbYWcchRzMJit4o5ARsK/s+5h0249pLw== dependencies: "@babel/helper-module-imports" "^7.22.15" "@babel/helper-plugin-utils" "^7.22.5" - babel-plugin-polyfill-corejs2 "^0.4.6" - babel-plugin-polyfill-corejs3 "^0.8.5" - babel-plugin-polyfill-regenerator "^0.5.3" + babel-plugin-polyfill-corejs2 "^0.4.7" + babel-plugin-polyfill-corejs3 "^0.8.7" + babel-plugin-polyfill-regenerator "^0.5.4" semver "^6.3.1" "@babel/plugin-transform-shorthand-properties@^7.22.5", "@babel/plugin-transform-shorthand-properties@^7.23.3": @@ -1073,17 +1108,17 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/preset-env@^7.18.2": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.23.5.tgz#350a3aedfa9f119ad045b068886457e895ba0ca1" - integrity sha512-0d/uxVD6tFGWXGDSfyMD1p2otoaKmu6+GD+NfAx0tMaH+dxORnp7T9TaVQ6mKyya7iBtCIVxHjWT7MuzzM9z+A== + version "7.23.8" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.23.8.tgz#7d6f8171ea7c221ecd28059e65ad37c20e441e3e" + integrity sha512-lFlpmkApLkEP6woIKprO6DO60RImpatTQKtz4sUcDjVcK8M8mQ4sZsuxaTMNOZf0sqAq/ReYW1ZBHnOQwKpLWA== dependencies: "@babel/compat-data" "^7.23.5" - "@babel/helper-compilation-targets" "^7.22.15" + "@babel/helper-compilation-targets" "^7.23.6" "@babel/helper-plugin-utils" "^7.22.5" "@babel/helper-validator-option" "^7.23.5" "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.23.3" "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.23.3" - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.23.3" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.23.7" "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-class-properties" "^7.12.13" @@ -1104,13 +1139,13 @@ "@babel/plugin-syntax-top-level-await" "^7.14.5" "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" "@babel/plugin-transform-arrow-functions" "^7.23.3" - "@babel/plugin-transform-async-generator-functions" "^7.23.4" + "@babel/plugin-transform-async-generator-functions" "^7.23.7" "@babel/plugin-transform-async-to-generator" "^7.23.3" "@babel/plugin-transform-block-scoped-functions" "^7.23.3" "@babel/plugin-transform-block-scoping" "^7.23.4" "@babel/plugin-transform-class-properties" "^7.23.3" "@babel/plugin-transform-class-static-block" "^7.23.4" - "@babel/plugin-transform-classes" "^7.23.5" + "@babel/plugin-transform-classes" "^7.23.8" "@babel/plugin-transform-computed-properties" "^7.23.3" "@babel/plugin-transform-destructuring" "^7.23.3" "@babel/plugin-transform-dotall-regex" "^7.23.3" @@ -1118,7 +1153,7 @@ "@babel/plugin-transform-dynamic-import" "^7.23.4" "@babel/plugin-transform-exponentiation-operator" "^7.23.3" "@babel/plugin-transform-export-namespace-from" "^7.23.4" - "@babel/plugin-transform-for-of" "^7.23.3" + "@babel/plugin-transform-for-of" "^7.23.6" "@babel/plugin-transform-function-name" "^7.23.3" "@babel/plugin-transform-json-strings" "^7.23.4" "@babel/plugin-transform-literals" "^7.23.3" @@ -1152,9 +1187,9 @@ "@babel/plugin-transform-unicode-regex" "^7.23.3" "@babel/plugin-transform-unicode-sets-regex" "^7.23.3" "@babel/preset-modules" "0.1.6-no-external-plugins" - babel-plugin-polyfill-corejs2 "^0.4.6" - babel-plugin-polyfill-corejs3 "^0.8.5" - babel-plugin-polyfill-regenerator "^0.5.3" + babel-plugin-polyfill-corejs2 "^0.4.7" + babel-plugin-polyfill-corejs3 "^0.8.7" + babel-plugin-polyfill-regenerator "^0.5.4" core-js-compat "^3.31.0" semver "^6.3.1" @@ -1305,9 +1340,9 @@ integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== "@babel/runtime@^7.8.4": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.5.tgz#11edb98f8aeec529b82b211028177679144242db" - integrity sha512-NdUTHcPe4C99WxPub+K9l9tK5/lV4UXIoaHSYgzco9BCyjKAAwzdBI+wWtYqHt7LJdbo74ZjRPJgzVweq1sz0w== + version "7.23.8" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.8.tgz#8ee6fe1ac47add7122902f257b8ddf55c898f650" + integrity sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw== dependencies: regenerator-runtime "^0.14.0" @@ -1336,7 +1371,7 @@ debug "^4.1.0" globals "^11.1.0" -"@babel/traverse@^7.23.2", "@babel/traverse@^7.23.5": +"@babel/traverse@^7.23.2": version "7.23.5" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.5.tgz#f546bf9aba9ef2b042c0e00d245990c15508e7ec" integrity sha512-czx7Xy5a6sapWWRx61m1Ke1Ra4vczu1mCTtJam5zRTBOonfdJ+S/B6HYmGYu3fJtr8GGET3si6IhgWVBhJ/m8w== @@ -1352,6 +1387,22 @@ debug "^4.1.0" globals "^11.1.0" +"@babel/traverse@^7.23.7": + version "7.23.7" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.7.tgz#9a7bf285c928cb99b5ead19c3b1ce5b310c9c305" + integrity sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg== + dependencies: + "@babel/code-frame" "^7.23.5" + "@babel/generator" "^7.23.6" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/parser" "^7.23.6" + "@babel/types" "^7.23.6" + debug "^4.3.1" + globals "^11.1.0" + "@babel/types@^7.21.3": version "7.23.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.0.tgz#8c1f020c9df0e737e4e247c0619f58c68458aaeb" @@ -1361,7 +1412,16 @@ "@babel/helper-validator-identifier" "^7.22.20" to-fast-properties "^2.0.0" -"@babel/types@^7.22.15", "@babel/types@^7.22.19", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.4", "@babel/types@^7.23.5", "@babel/types@^7.4.4": +"@babel/types@^7.22.15", "@babel/types@^7.22.19", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.5", "@babel/types@^7.23.6", "@babel/types@^7.4.4": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.6.tgz#be33fdb151e1f5a56877d704492c240fc71c7ccd" + integrity sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg== + dependencies: + "@babel/helper-string-parser" "^7.23.4" + "@babel/helper-validator-identifier" "^7.22.20" + to-fast-properties "^2.0.0" + +"@babel/types@^7.23.4": version "7.23.5" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.5.tgz#48d730a00c95109fa4393352705954d74fb5b602" integrity sha512-ON5kSOJwVO6xXVRTvOI0eOnWe7VdUcIpsovGo9U/Br4Ie4UVFQTboO2cYnDhAGU6Fp+UxSiT+pMft0SMHfuq6w== @@ -1660,9 +1720,9 @@ yargs "^17.0.1" "@electron/rebuild@^3.4.0": - version "3.4.1" - resolved "https://registry.yarnpkg.com/@electron/rebuild/-/rebuild-3.4.1.tgz#a547af63068f1e62ff18631beb7704190ceab895" - integrity sha512-iMKb6KJgKcdURbejs0j2GLEmrY8uY4rg1ESThXx9sFTgdWb8UOfJuTqW6LIEtcoY8FrbFqDmJrkWc4tBpdStXw== + version "3.5.0" + resolved "https://registry.yarnpkg.com/@electron/rebuild/-/rebuild-3.5.0.tgz#4483a2577c516d9c7698edf51cf25496bcfe42d8" + integrity sha512-pWRza7F+JxzTNATkEgI5iW7lAQTVBtU5r6ZjUSbrD04kbuQWUIHBcuvqosaHvKLmTpdRlsZQkPxTYciIoOWf3A== dependencies: "@malept/cross-spawn-promise" "^2.0.0" chalk "^4.0.0" @@ -1671,7 +1731,7 @@ fs-extra "^10.0.0" got "^11.7.0" node-abi "^3.45.0" - node-api-version "^0.1.4" + node-api-version "^0.2.0" node-gyp "^9.0.0" ora "^5.1.0" read-binary-file-arch "^1.0.6" @@ -1741,7 +1801,7 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== -"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": +"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.9": version "0.3.20" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f" integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q== @@ -1958,23 +2018,23 @@ integrity sha512-S+DsD/qDqp50Z4dqt5tZFMWA3sRu0OOT/grMQuq/z/52jPEKJB+b9t+YSH8Ms55vCJOJ0DxuYldJpYrJLMG5ew== "@tanstack/match-sorter-utils@^8.8.4": - version "8.8.4" - resolved "https://registry.yarnpkg.com/@tanstack/match-sorter-utils/-/match-sorter-utils-8.8.4.tgz#0b2864d8b7bac06a9f84cb903d405852cc40a457" - integrity sha512-rKH8LjZiszWEvmi01NR72QWZ8m4xmXre0OOwlRGnjU01Eqz/QnN+cqpty2PJ0efHblq09+KilvyR7lsbzmXVEw== + version "8.11.3" + resolved "https://registry.yarnpkg.com/@tanstack/match-sorter-utils/-/match-sorter-utils-8.11.3.tgz#904bf4916bac1338751491de0685151126e5c29b" + integrity sha512-2XVYTN6fLFyeIPywDL/HGKIQce3V6oUch1FHweGwxruPKEXip6Z9qg+zWZwNE26WG6CktqJh6NqTq90a42jeEw== dependencies: remove-accents "0.4.2" "@tanstack/react-table@^8.10.3": - version "8.10.7" - resolved "https://registry.yarnpkg.com/@tanstack/react-table/-/react-table-8.10.7.tgz#733f4bee8cf5aa19582f944dd0fd3224b21e8c94" - integrity sha512-bXhjA7xsTcsW8JPTTYlUg/FuBpn8MNjiEPhkNhIGCUR6iRQM2+WEco4OBpvDeVcR9SE+bmWLzdfiY7bCbCSVuA== + version "8.11.6" + resolved "https://registry.yarnpkg.com/@tanstack/react-table/-/react-table-8.11.6.tgz#ae234355eaae230ede95ebcbadb3251482eb6087" + integrity sha512-i0heTVZtuHF9VPMwcYoZ21hbzGDmLjxHYemDMvbGpjk5fUZ8nLF3S8qjVRU79XfPW8KK9o7iTU2fGFVQQmxMSQ== dependencies: - "@tanstack/table-core" "8.10.7" + "@tanstack/table-core" "8.11.6" -"@tanstack/table-core@8.10.7": - version "8.10.7" - resolved "https://registry.yarnpkg.com/@tanstack/table-core/-/table-core-8.10.7.tgz#577e8a635048875de4c9d6d6a3c21d26ff9f9d08" - integrity sha512-KQk5OMg5OH6rmbHZxuNROvdI+hKDIUxANaHlV+dPlNN7ED3qYQ/WkpY2qlXww1SIdeMlkIhpN/2L00rof0fXFw== +"@tanstack/table-core@8.11.6": + version "8.11.6" + resolved "https://registry.yarnpkg.com/@tanstack/table-core/-/table-core-8.11.6.tgz#ab753617b64d72f868f6ea4666059912f0c98441" + integrity sha512-69WEY1PaZROaGYUrseng4/4sMYnRGhDe1vM6888CnWekGz/wuCnvqwOoOuKGYivnaiI4BVmZq4WKWhvahyj3/g== "@tootallnate/once@2": version "2.0.0" @@ -1987,17 +2047,17 @@ integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== "@types/body-parser@*": - version "1.19.3" - resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.3.tgz#fb558014374f7d9e56c8f34bab2042a3a07d25cd" - integrity sha512-oyl4jvAfTGX9Bt6Or4H9ni1Z447/tQuxnZsytsCaExKlmJiU8sFgnIBRzJUpKwB5eWn9HuBYlUlVA74q/yN0eQ== + version "1.19.5" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.5.tgz#04ce9a3b677dc8bd681a17da1ab9835dc9d3ede4" + integrity sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg== dependencies: "@types/connect" "*" "@types/node" "*" "@types/bonjour@^3.5.9": - version "3.5.11" - resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.11.tgz#fbaa46a1529ea5c5e46cde36e4be6a880db55b84" - integrity sha512-isGhjmBtLIxdHBDl2xGwUzEM8AOyOvWsADWq7rqirdi/ZQoHnLWErHvsThcEzTX8juDRiZtzp2Qkv5bgNh6mAg== + version "3.5.13" + resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.13.tgz#adf90ce1a105e81dd1f9c61fdc5afda1bfb92956" + integrity sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ== dependencies: "@types/node" "*" @@ -2019,17 +2079,17 @@ classnames "*" "@types/connect-history-api-fallback@^1.3.5": - version "1.5.1" - resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.1.tgz#6e5e3602d93bda975cebc3449e1a318340af9e20" - integrity sha512-iaQslNbARe8fctL5Lk+DsmgWOM83lM+7FzP0eQUJs1jd3kBE8NWqBTIT2S8SqQOJjxvt2eyIjpOuYeRXq2AdMw== + version "1.5.4" + resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz#7de71645a103056b48ac3ce07b3520b819c1d5b3" + integrity sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw== dependencies: "@types/express-serve-static-core" "*" "@types/node" "*" "@types/connect@*": - version "3.4.36" - resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.36.tgz#e511558c15a39cb29bd5357eebb57bd1459cd1ab" - integrity sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w== + version "3.4.38" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858" + integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug== dependencies: "@types/node" "*" @@ -2048,17 +2108,17 @@ electron "*" "@types/eslint-scope@^3.7.3": - version "3.7.6" - resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.6.tgz#585578b368ed170e67de8aae7b93f54a1b2fdc26" - integrity sha512-zfM4ipmxVKWdxtDaJ3MP3pBurDXOCoyjvlpE3u6Qzrmw4BPbfm4/ambIeTk/r/J0iq/+2/xp0Fmt+gFvXJY2PQ== + version "3.7.7" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" + integrity sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg== dependencies: "@types/eslint" "*" "@types/estree" "*" "@types/eslint@*": - version "8.44.6" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.44.6.tgz#60e564551966dd255f4c01c459f0b4fb87068603" - integrity sha512-P6bY56TVmX8y9J87jHNgQh43h6VVU+6H7oN7hgvivV81K2XY8qJZ5vqPy/HdUoVIelii2kChYVzQanlswPWVFw== + version "8.56.2" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.56.2.tgz#1c72a9b794aa26a8b94ad26d5b9aa51c8a6384bb" + integrity sha512-uQDwm1wFHmbBbCZCqAlq6Do9LYwByNZHWzXppSnay9SuwJ+VRbjkbLABer54kcPnMSlG6Fdiy2yaFXm/z9Z5gw== dependencies: "@types/estree" "*" "@types/json-schema" "*" @@ -2071,14 +2131,14 @@ "@types/estree" "*" "@types/estree@*", "@types/estree@^1.0.0": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.4.tgz#d9748f5742171b26218516cf1828b8eafaf8a9fa" - integrity sha512-2JwWnHK9H+wUZNorf2Zr6ves96WHoWDJIftkcxPKsS7Djta6Zu519LarhRNljPXkpsZR2ZMwNCPeW7omW07BJw== + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" + integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== "@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.33": - version "4.17.37" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.37.tgz#7e4b7b59da9142138a2aaa7621f5abedce8c7320" - integrity sha512-ZohaCYTgGFcOP7u6aJOhY9uIZQgZ2vxC2yWoArY+FeDXlqeH66ZVBjgvg+RLVAS/DWNq4Ap9ZXu1+SUQiiWYMg== + version "4.17.41" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.41.tgz#5077defa630c2e8d28aa9ffc2c01c157c305bef6" + integrity sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA== dependencies: "@types/node" "*" "@types/qs" "*" @@ -2086,9 +2146,9 @@ "@types/send" "*" "@types/express@*", "@types/express@^4.17.13": - version "4.17.18" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.18.tgz#efabf5c4495c1880df1bdffee604b143b29c4a95" - integrity sha512-Sxv8BSLLgsBYmcnGdGjjEjqET2U+AKAdCRODmMiq02FgjwuV75Ut85DRpvFjyw/Mk0vgUOliGRU0UUmuuZHByQ== + version "4.17.21" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d" + integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== dependencies: "@types/body-parser" "*" "@types/express-serve-static-core" "^4.17.33" @@ -2123,26 +2183,21 @@ integrity sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA== "@types/http-errors@*": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.2.tgz#a86e00bbde8950364f8e7846687259ffcd96e8c2" - integrity sha512-lPG6KlZs88gef6aD85z3HNkztpj7w2R7HmR3gygjfXCQmsLloWNARFkMuzKiiY8FGdh1XDpgBdrSf4aKDiA7Kg== + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f" + integrity sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA== "@types/http-proxy@^1.17.8": - version "1.17.12" - resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.12.tgz#86e849e9eeae0362548803c37a0a1afc616bd96b" - integrity sha512-kQtujO08dVtQ2wXAuSFfk9ASy3sug4+ogFR8Kd8UgP8PEuc1/G/8yjYRmp//PcDNJEUKOza/MrQu15bouEUCiw== + version "1.17.14" + resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.14.tgz#57f8ccaa1c1c3780644f8a94f9c6b5000b5e2eec" + integrity sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w== dependencies: "@types/node" "*" -"@types/json-schema@*", "@types/json-schema@^7.0.8": - version "7.0.14" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.14.tgz#74a97a5573980802f32c8e47b663530ab3b6b7d1" - integrity sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw== - -"@types/json-schema@^7.0.9": - version "7.0.13" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.13.tgz#02c24f4363176d2d18fc8b70b9f3c54aba178a85" - integrity sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ== +"@types/json-schema@*", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== "@types/keyv@^3.1.4": version "3.1.4" @@ -2159,14 +2214,14 @@ "@types/unist" "*" "@types/mime@*": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.2.tgz#c1ae807f13d308ee7511a5b81c74f327028e66e8" - integrity sha512-Wj+fqpTLtTbG7c0tH47dkahefpLKEbB+xAZuLq7b4/IDHPl/n6VoXcyUQ2bypFlbSwvCr0y+bD4euTTqTJsPxQ== + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.4.tgz#2198ac274de6017b44d941e00261d5bc6a0e0a45" + integrity sha512-iJt33IQnVRkqeqC7PzBHPTC6fDlRNRW8vjrgqtScAhrmMwe8c4Eo7+fUGTa+XdWrpEgpyKWMYmi2dIwMAYRzPw== "@types/mime@^1": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.3.tgz#bbe64987e0eb05de150c305005055c7ad784a9ce" - integrity sha512-Ys+/St+2VF4+xuY6+kDIXGxbNRO0mesVg0bbxEfB97Od1Vjpjx9KD1qxs64Gcb3CWPirk9Xe+PT4YiiHQ9T+eg== + version "1.3.5" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690" + integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w== "@types/minimatch@*": version "5.1.2" @@ -2178,17 +2233,24 @@ resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.34.tgz#10964ba0dee6ac4cd462e2795b6bebd407303433" integrity sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g== -"@types/node@*", "@types/node@20.10.3": - version "20.10.3" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.10.3.tgz#4900adcc7fc189d5af5bb41da8f543cea6962030" - integrity sha512-XJavIpZqiXID5Yxnxv3RUDKTN5b81ddNC3ecsA0SoFXz/QU8OGBwZGMomiq0zw+uuqbL/krztv/DINAQ/EV4gg== +"@types/node-forge@^1.3.0": + version "1.3.11" + resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-1.3.11.tgz#0972ea538ddb0f4d9c2fa0ec5db5724773a604da" + integrity sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ== + dependencies: + "@types/node" "*" + +"@types/node@*", "@types/node@20.11.0": + version "20.11.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.0.tgz#8e0b99e70c0c1ade1a86c4a282f7b7ef87c9552f" + integrity sha512-o9bjXmDNcF7GbM4CNQpmi+TutCgap/K3w1JyKgxAjqx41zp9qlIAVFi0IhCNsJcXolEqLWhbFbEeL0PvYm4pcQ== dependencies: undici-types "~5.26.4" "@types/node@^18.11.18": - version "18.19.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.2.tgz#865107157bda220eef9fa8c2173152d6559a41ae" - integrity sha512-6wzfBdbWpe8QykUkXBjtmO3zITA0A3FIjoy+in0Y2K4KrCiRhNYJIdwAPDffZ3G6GnaKaSLSEa9ZuORLfEoiwg== + version "18.19.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.6.tgz#537beece2c8ad4d9abdaa3b0f428e601eb57dac8" + integrity sha512-X36s5CXMrrJOs2lQCdDF68apW4Rfx9ixYMawlepwmE4Anezv/AV2LSpKD1Ub8DAc+urp5bk0BGZ6NtmBitfnsg== dependencies: undici-types "~5.26.4" @@ -2205,19 +2267,19 @@ integrity sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng== "@types/qs@*": - version "6.9.8" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.8.tgz#f2a7de3c107b89b441e071d5472e6b726b4adf45" - integrity sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg== + version "6.9.11" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.11.tgz#208d8a30bc507bd82e03ada29e4732ea46a6bbda" + integrity sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ== "@types/range-parser@*": - version "1.2.5" - resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.5.tgz#38bd1733ae299620771bd414837ade2e57757498" - integrity sha512-xrO9OoVPqFuYyR/loIHjnbvvyRZREYKLjxV4+dY6v3FQR3stQ9ZxIGkaclF7YhI9hfjpuTbu14hZEy94qKLtOA== + version "1.2.7" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb" + integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ== "@types/react@^18.0.12": - version "18.2.42" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.42.tgz#6f6b11a904f6d96dda3c2920328a97011a00aba7" - integrity sha512-c1zEr96MjakLYus/wPnuWDo1/zErfdU9rNsIGmE+NV71nx88FG9Ttgo5dqorXTu/LImX2f63WBP986gJkMPNbA== + version "18.2.47" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.47.tgz#85074b27ab563df01fbc3f68dc64bf7050b0af40" + integrity sha512-xquNkkOirwyCgoClNk85BjP+aqnIS+ckAJ8i37gAbDs14jfW/J23f2GItAf33oiUPQnqNMALiFeoM9Y5mbjpVQ== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" @@ -2246,33 +2308,33 @@ integrity sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A== "@types/send@*": - version "0.17.2" - resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.2.tgz#af78a4495e3c2b79bfbdac3955fdd50e03cc98f2" - integrity sha512-aAG6yRf6r0wQ29bkS+x97BIs64ZLxeE/ARwyS6wrldMm3C1MdKwCcnnEwMC1slI8wuxJOpiUH9MioC0A0i+GJw== + version "0.17.4" + resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.4.tgz#6619cd24e7270793702e4e6a4b958a9010cfc57a" + integrity sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA== dependencies: "@types/mime" "^1" "@types/node" "*" "@types/serve-index@^1.9.1": - version "1.9.2" - resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.2.tgz#cb26e775678a8526b73a5d980a147518740aaecd" - integrity sha512-asaEIoc6J+DbBKXtO7p2shWUpKacZOoMBEGBgPG91P8xhO53ohzHWGCs4ScZo5pQMf5ukQzVT9fhX1WzpHihig== + version "1.9.4" + resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.4.tgz#e6ae13d5053cb06ed36392110b4f9a49ac4ec898" + integrity sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug== dependencies: "@types/express" "*" "@types/serve-static@*", "@types/serve-static@^1.13.10": - version "1.15.3" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.3.tgz#2cfacfd1fd4520bbc3e292cca432d5e8e2e3ee61" - integrity sha512-yVRvFsEMrv7s0lGhzrggJjNOSmZCdgCjw9xWrPr/kNNLp6FaDfMC1KaYl3TSJ0c58bECwNBMoQrZJ8hA8E1eFg== + version "1.15.5" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.5.tgz#15e67500ec40789a1e8c9defc2d32a896f05b033" + integrity sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ== dependencies: "@types/http-errors" "*" "@types/mime" "*" "@types/node" "*" "@types/sockjs@^0.3.33": - version "0.3.34" - resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.34.tgz#43e10e549b36d2ba2589278f00f81b5d7ccda167" - integrity sha512-R+n7qBFnm/6jinlteC9DBL5dGiDGjWAvjo4viUanpnc/dG1y7uDoacXPIQ/PQEg1fI912SMHIa014ZjRpvDw4g== + version "0.3.36" + resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.36.tgz#ce322cf07bcc119d4cbf7f88954f3a3bd0f67535" + integrity sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q== dependencies: "@types/node" "*" @@ -2312,9 +2374,9 @@ integrity sha512-I6e+9+HtWADAWeeJWDFQtdk4EVSAbj6Rtz4q8fJ7mSr1M0jzlFcs8/HZ+Xb5SHzVm1dxH7aUiI+A8kA8Gcrm0A== "@types/ws@^8.5.5": - version "8.5.6" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.6.tgz#e9ad51f0ab79b9110c50916c9fcbddc36d373065" - integrity sha512-8B5EO9jLVCy+B58PLHvLDuOD8DRVMgQzq8d55SjLCOn9kqGyqOvy27exVaTio1q1nX5zLu8/6N0n2ThSxOM6tg== + version "8.5.10" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.10.tgz#4acfb517970853fa6574a3a6886791d04a396787" + integrity sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A== dependencies: "@types/node" "*" @@ -2510,9 +2572,9 @@ acorn@^8.0.4: integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== acorn@^8.7.1, acorn@^8.8.2: - version "8.11.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.2.tgz#ca0d78b51895be5390a5903c5b3bdcdaf78ae40b" - integrity sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w== + version "8.11.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" + integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== agent-base@6, agent-base@^6.0.2: version "6.0.2" @@ -2644,11 +2706,6 @@ array-flatten@1.1.1: resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== -array-flatten@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" - integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== - asar@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/asar/-/asar-3.2.0.tgz#e6edb5edd6f627ebef04db62f771c61bea9c1221" @@ -2708,7 +2765,7 @@ babel-plugin-jsx-control-statements@^4.1.2: dependencies: "@babel/core" "^7.1.2" -babel-plugin-polyfill-corejs2@^0.4.5, babel-plugin-polyfill-corejs2@^0.4.6: +babel-plugin-polyfill-corejs2@^0.4.5: version "0.4.6" resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.6.tgz#b2df0251d8e99f229a8e60fc4efa9a68b41c8313" integrity sha512-jhHiWVZIlnPbEUKSSNb9YoWcQGdlTLq7z1GHL4AjFxaoOUMuuEVJ+Y4pAaQUGOGk93YsVCKPbqbfw3m0SM6H8Q== @@ -2717,7 +2774,16 @@ babel-plugin-polyfill-corejs2@^0.4.5, babel-plugin-polyfill-corejs2@^0.4.6: "@babel/helper-define-polyfill-provider" "^0.4.3" semver "^6.3.1" -babel-plugin-polyfill-corejs3@^0.8.3, babel-plugin-polyfill-corejs3@^0.8.5: +babel-plugin-polyfill-corejs2@^0.4.7: + version "0.4.7" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.7.tgz#679d1b94bf3360f7682e11f2cb2708828a24fe8c" + integrity sha512-LidDk/tEGDfuHW2DWh/Hgo4rmnw3cduK6ZkOI1NPFceSK3n/yAGeOsNT7FLnSGHkXj3RHGSEVkN3FsCTY6w2CQ== + dependencies: + "@babel/compat-data" "^7.22.6" + "@babel/helper-define-polyfill-provider" "^0.4.4" + semver "^6.3.1" + +babel-plugin-polyfill-corejs3@^0.8.3: version "0.8.6" resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.6.tgz#25c2d20002da91fe328ff89095c85a391d6856cf" integrity sha512-leDIc4l4tUgU7str5BWLS2h8q2N4Nf6lGZP6UrNDxdtfF2g69eJ5L0H7S8A5Ln/arfFAfHor5InAdZuIOwZdgQ== @@ -2725,13 +2791,28 @@ babel-plugin-polyfill-corejs3@^0.8.3, babel-plugin-polyfill-corejs3@^0.8.5: "@babel/helper-define-polyfill-provider" "^0.4.3" core-js-compat "^3.33.1" -babel-plugin-polyfill-regenerator@^0.5.2, babel-plugin-polyfill-regenerator@^0.5.3: +babel-plugin-polyfill-corejs3@^0.8.7: + version "0.8.7" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.7.tgz#941855aa7fdaac06ed24c730a93450d2b2b76d04" + integrity sha512-KyDvZYxAzkC0Aj2dAPyDzi2Ym15e5JKZSK+maI7NAwSqofvuFglbSsxE7wUOvTg9oFVnHMzVzBKcqEb4PJgtOA== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.4.4" + core-js-compat "^3.33.1" + +babel-plugin-polyfill-regenerator@^0.5.2: version "0.5.3" resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.3.tgz#d4c49e4b44614607c13fb769bcd85c72bb26a4a5" integrity sha512-8sHeDOmXC8csczMrYEOf0UTNa4yE2SxV5JGeT/LP1n0OYVDUUFPxG9vdk2AlDlIit4t+Kf0xCtpgXPBwnn/9pw== dependencies: "@babel/helper-define-polyfill-provider" "^0.4.3" +babel-plugin-polyfill-regenerator@^0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.4.tgz#c6fc8eab610d3a11eb475391e52584bacfc020f4" + integrity sha512-S/x2iOCvDaCASLYsOOgWOq4bCfKYVqvO/uxjkaYyZ3rVsVE3CeAI/c84NpyuBBymEgNvHgjEot3a9/Z/kXvqsg== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.4.4" + bail@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/bail/-/bail-2.0.2.tgz#d26f5cd8fe5d6f832a31517b9f7c356040ba6d5d" @@ -2802,12 +2883,10 @@ body-parser@1.20.1: unpipe "1.0.0" bonjour-service@^1.0.11: - version "1.1.1" - resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.1.1.tgz#960948fa0e0153f5d26743ab15baf8e33752c135" - integrity sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg== + version "1.2.1" + resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.2.1.tgz#eb41b3085183df3321da1264719fbada12478d02" + integrity sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw== dependencies: - array-flatten "^2.1.2" - dns-equal "^1.0.0" fast-deep-equal "^3.1.3" multicast-dns "^7.2.5" @@ -2843,17 +2922,7 @@ braces@^3.0.2, braces@~3.0.2: dependencies: fill-range "^7.0.1" -browserslist@^4.14.5: - version "4.22.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.1.tgz#ba91958d1a59b87dab6fed8dfbcb3da5e2e9c619" - integrity sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ== - dependencies: - caniuse-lite "^1.0.30001541" - electron-to-chromium "^1.4.535" - node-releases "^2.0.13" - update-browserslist-db "^1.0.13" - -browserslist@^4.21.9, browserslist@^4.22.1: +browserslist@^4.14.5, browserslist@^4.22.2: version "4.22.2" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.2.tgz#704c4943072bd81ea18997f3bd2180e89c77874b" integrity sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A== @@ -2939,12 +3008,13 @@ cacheable-request@^7.0.2: responselike "^2.0.0" call-bind@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + version "1.0.5" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.5.tgz#6fa2b7845ce0ea49bf4d8b9ef64727a2c2e2e513" + integrity sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ== dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" + function-bind "^1.1.2" + get-intrinsic "^1.2.1" + set-function-length "^1.1.1" callsites@^3.0.0: version "3.1.0" @@ -2956,10 +3026,10 @@ camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001541, caniuse-lite@^1.0.30001565: - version "1.0.30001566" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001566.tgz#61a8e17caf3752e3e426d4239c549ebbb37fef0d" - integrity sha512-ggIhCsTxmITBAMmK8yZjEhCO5/47jKXPu6Dha/wuCS4JePVL+3uiDEBuhu2aIoT+bqTOR8L76Ip1ARL9xYsEJA== +caniuse-lite@^1.0.30001565: + version "1.0.30001576" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001576.tgz#893be772cf8ee6056d6c1e2d07df365b9ec0a5c4" + integrity sha512-ff5BdakGe2P3SQsMsiqmt1Lc8221NR1VzHj5jXN5vBny9A6fpze94HiVV/n7XRosOlsShJcvMv5mdnpjOGCEgg== ccount@^2.0.0: version "2.0.1" @@ -3033,11 +3103,16 @@ chromium-pickle-js@^0.2.0: resolved "https://registry.yarnpkg.com/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz#04a106672c18b085ab774d983dfa3ea138f22205" integrity sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw== -classnames@*, classnames@^2.3.1: +classnames@*: version "2.3.2" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924" integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw== +classnames@^2.3.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b" + integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow== + clean-stack@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" @@ -3282,11 +3357,11 @@ copy-webpack-plugin@^11.0.0: serialize-javascript "^6.0.0" core-js-compat@^3.31.0, core-js-compat@^3.33.1: - version "3.33.3" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.33.3.tgz#ec678b772c5a2d8a7c60a91c3a81869aa704ae01" - integrity sha512-cNzGqFsh3Ot+529GIXacjTJ7kegdt5fPXxCBVS1G0iaZpuo/tBz399ymceLJveQhFFZ8qThHiP3fzuoQjKN2ow== + version "3.35.0" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.35.0.tgz#c149a3d1ab51e743bc1da61e39cb51f461a41873" + integrity sha512-5blwFAddknKeNgsjBzilkdQ0+YK8L1PfqPYq40NOYMYFSS38qj+hpTcLLWwpIwA2A5bje/x5jmVn2tzUMg9IVw== dependencies: - browserslist "^4.22.1" + browserslist "^4.22.2" core-util-is@~1.0.0: version "1.0.3" @@ -3343,18 +3418,18 @@ cross-zip@^4.0.0: integrity sha512-MEzGfZo0rqE10O/B+AEcCSJLZsrWuRUvmqJTqHNqBtALhaJc3E3ixLGLJNTRzEA2K34wbmOHC4fwYs9sVsdcCA== css-loader@^6.7.1: - version "6.8.1" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.8.1.tgz#0f8f52699f60f5e679eab4ec0fcd68b8e8a50a88" - integrity sha512-xDAXtEVGlD0gJ07iclwWVkLoZOpEvAWaSyf6W18S2pOC//K8+qUDIx8IIT3D+HjnmkJPQeesOPv5aiUaJsCM2g== + version "6.9.0" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.9.0.tgz#0cc2f14df94ed97c526c5ae42b6b13916d1d8d0e" + integrity sha512-3I5Nu4ytWlHvOP6zItjiHlefBNtrH+oehq8tnQa2kO305qpVyx9XNIT1CXIj5bgCJs7qICBCkgCYxQLKPANoLA== dependencies: icss-utils "^5.1.0" - postcss "^8.4.21" + postcss "^8.4.31" postcss-modules-extract-imports "^3.0.0" postcss-modules-local-by-default "^4.0.3" - postcss-modules-scope "^3.0.0" + postcss-modules-scope "^3.1.0" postcss-modules-values "^4.0.0" postcss-value-parser "^4.2.0" - semver "^7.3.8" + semver "^7.5.4" css-select@^5.1.0: version "5.1.0" @@ -3401,9 +3476,9 @@ csso@^5.0.5: css-tree "~2.2.0" csstype@^3.0.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b" - integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ== + version "3.1.3" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" + integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== data-uri-to-buffer@^4.0.0: version "4.0.1" @@ -3479,7 +3554,7 @@ defer-to-connect@^2.0.0: resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== -define-data-property@^1.0.1: +define-data-property@^1.0.1, define-data-property@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" integrity sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ== @@ -3559,11 +3634,6 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" -dns-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" - integrity sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg== - dns-packet@^5.2.2: version "5.6.1" resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.6.1.tgz#ae888ad425a9d1478a0674256ab866de1012cf2f" @@ -3593,9 +3663,9 @@ domhandler@^5.0.2, domhandler@^5.0.3: domelementtype "^2.3.0" dompurify@^3.0.2: - version "3.0.6" - resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.0.6.tgz#925ebd576d54a9531b5d76f0a5bef32548351dae" - integrity sha512-ilkD8YEnnGh1zJ240uJsW7AzE+2qpbOUYjacomn3AvJ6J4JhKGSZ2nh4wUIXPZrEPppaCLx5jFe8T89Rk8tQ7w== + version "3.0.8" + resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.0.8.tgz#e0021ab1b09184bc8af7e35c7dd9063f43a8a437" + integrity sha512-b7uwreMYL2eZhrSCRC4ahLTeZcPZxSmYfmcQGXGkXiZSNW1X85v+SDM5KsWcpivIiUBH47Ji7NtyUdpLeF5JZQ== domutils@^3.0.1: version "3.1.0" @@ -3716,10 +3786,10 @@ electron-squirrel-startup@^1.0.0: dependencies: debug "^2.2.0" -electron-to-chromium@^1.4.535, electron-to-chromium@^1.4.601: - version "1.4.601" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.601.tgz#cac69868548aee89961ffe63ff5a7716f0685b75" - integrity sha512-SpwUMDWe9tQu8JX5QCO1+p/hChAi9AE9UpoC3rcHVc+gdCGlbT3SGb5I1klgb952HRIyvt9wZhSz9bNBYz9swA== +electron-to-chromium@^1.4.601: + version "1.4.628" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.628.tgz#97cefa4b2356d981875f19639885e4fc50ce6e82" + integrity sha512-2k7t5PHvLsufpP6Zwk0nof62yLOsCf032wZx7/q0mv8gwlXjhcxI3lz6f0jBr0GrnWKcm3burXzI3t5IrcdUxw== electron-winstaller@^5.0.0: version "5.1.0" @@ -3827,9 +3897,9 @@ error-ex@^1.2.0, error-ex@^1.3.1: is-arrayish "^0.2.1" es-module-lexer@^1.2.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.3.1.tgz#c1b0dd5ada807a3b3155315911f364dc4e909db1" - integrity sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q== + version "1.4.1" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.4.1.tgz#41ea21b43908fe6a287ffcbe4300f790555331f5" + integrity sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w== es6-error@^4.1.1: version "4.1.1" @@ -4186,9 +4256,9 @@ forwarded@0.2.0: integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== framer-motion@^10.16.16: - version "10.16.16" - resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-10.16.16.tgz#a10a03e1190a717109163cfff212a84c8ad11b0c" - integrity sha512-je6j91rd7NmUX7L1XHouwJ4v3R+SO4umso2LUcgOct3rHZ0PajZ80ETYZTajzEXEl9DlKyzjyt4AvGQ+lrebOw== + version "10.18.0" + resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-10.18.0.tgz#1f4fc51403996ea7170af885bd44a7079d255950" + integrity sha512-oGlDh1Q1XqYPksuTD/usb0I70hq95OUzmL9+6Zd+Hs4XV0oaISBa/UUMSjYiq6m8EUF32132mOJ8xVZS+I0S6w== dependencies: tslib "^2.4.0" optionalDependencies: @@ -4272,7 +4342,7 @@ fsevents@~2.3.2: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== -function-bind@^1.1.1, function-bind@^1.1.2: +function-bind@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== @@ -4330,17 +4400,7 @@ get-installed-path@^2.0.3: dependencies: global-modules "1.0.0" -get-intrinsic@^1.0.2: - version "1.2.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82" - integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-proto "^1.0.1" - has-symbols "^1.0.3" - -get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2: +get-intrinsic@^1.0.2, get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz#281b7622971123e1ef4b3c90fd7539306da93f3b" integrity sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA== @@ -4549,11 +4609,6 @@ has-unicode@^2.0.1: resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== -has@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.4.tgz#2eb2860e000011dae4f1406a86fe80e530fb2ec6" - integrity sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ== - hasown@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" @@ -5137,9 +5192,9 @@ launch-editor@^2.6.0: shell-quote "^1.8.1" less-loader@^11.0.0: - version "11.1.3" - resolved "https://registry.yarnpkg.com/less-loader/-/less-loader-11.1.3.tgz#1bb62d6ca9bf00a177c02793b54baac40f9be694" - integrity sha512-A5b7O8dH9xpxvkosNrP0dFp2i/dISOJa9WwGF3WJflfqIERE2ybxh1BFDj5CovC2+jCE4M354mk90hN6ziXlVw== + version "11.1.4" + resolved "https://registry.yarnpkg.com/less-loader/-/less-loader-11.1.4.tgz#e8a070844efaefbe59b978acaf57b9d3e868cf08" + integrity sha512-6/GrYaB6QcW6Vj+/9ZPgKKs6G10YZai/l/eJ4SLwbzqNTBsAqt5hSLVF47TgsiBxV1P6eAU0GYRH3YRuQU9V3A== less@^4.1.2: version "4.2.0" @@ -5938,9 +5993,9 @@ mimic-response@^3.1.0: integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== mini-css-extract-plugin@^2.6.0: - version "2.7.6" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.6.tgz#282a3d38863fddcd2e0c220aaed5b90bc156564d" - integrity sha512-Qk7HcgaPkGG6eD77mLvZS1nmxlao3j+9PkrT9Uc7HAE1id3F41+DdBRYRYkbyfNRGzm8/YWtzhw7nVPmwhqTQw== + version "2.7.7" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.7.tgz#4acf02f362c641c38fb913bfcb7ca2fc4a7cf339" + integrity sha512-+0n11YGyRavUR3IlaOzJ0/4Il1avMvJ1VJfhWfCn24ITQXhRr1gghbhhrda6tgtNcpZaWKdSuwKq20Jb7fnlyw== dependencies: schema-utils "^4.0.0" @@ -6094,10 +6149,10 @@ mustache@^4.2.0: resolved "https://registry.yarnpkg.com/mustache/-/mustache-4.2.0.tgz#e5892324d60a12ec9c2a73359edca52972bf6f64" integrity sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ== -nanoid@^3.3.6: - version "3.3.6" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" - integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== +nanoid@^3.3.7: + version "3.3.7" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" + integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== needle@^3.1.0: version "3.2.0" @@ -6132,9 +6187,9 @@ no-case@^3.0.4: tslib "^2.0.3" node-abi@^3.45.0: - version "3.52.0" - resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.52.0.tgz#ffba0a85f54e552547e5849015f40f9514d5ba7c" - integrity sha512-JJ98b02z16ILv7859irtXn4oUaFWADtvkzy2c0IAatNVX2Mc9Yoh8z6hZInn3QwvMEYhHuQloYi+TTQy67SIdQ== + version "3.54.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.54.0.tgz#f6386f7548817acac6434c6cba02999c9aebcc69" + integrity sha512-p7eGEiQil0YUV3ItH4/tBb781L5impVmmx2E9FRKF7d18XXzp4PGT2tdYMFY6wQqgxD0IwNZOiSJ0/K0fSi/OA== dependencies: semver "^7.3.5" @@ -6145,6 +6200,13 @@ node-api-version@^0.1.4: dependencies: semver "^7.3.5" +node-api-version@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/node-api-version/-/node-api-version-0.2.0.tgz#5177441da2b1046a4d4547ab9e0972eed7b1ac1d" + integrity sha512-fthTTsi8CxaBXMaBAD7ST2uylwvsnYxh2PfaScwpMhos6KlSFajXQPcM4ogNE1q2s3Lbz9GCGqeIHC+C6OZnKg== + dependencies: + semver "^7.3.5" + node-domexception@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" @@ -6188,7 +6250,7 @@ node-gyp@^9.0.0: tar "^6.1.2" which "^2.0.2" -node-releases@^2.0.13, node-releases@^2.0.14: +node-releases@^2.0.14: version "2.0.14" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== @@ -6257,9 +6319,9 @@ object-assign@^4.1.1: integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== object-inspect@^1.9.0: - version "1.12.3" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" - integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== + version "1.13.1" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" + integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== object-keys@^1.1.1: version "1.1.1" @@ -6622,10 +6684,10 @@ postcss-modules-local-by-default@^4.0.3: postcss-selector-parser "^6.0.2" postcss-value-parser "^4.1.0" -postcss-modules-scope@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06" - integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg== +postcss-modules-scope@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.1.0.tgz#fbfddfda93a31f310f1d152c2bb4d3f3c5592ee0" + integrity sha512-SaIbK8XW+MZbd0xHPf7kdfA/3eOt7vxJ72IRecn3EzuZVLr1r0orzf0MX/pN8m+NMDoo6X/SQd8oeKqGZd8PXg== dependencies: postcss-selector-parser "^6.0.4" @@ -6637,9 +6699,9 @@ postcss-modules-values@^4.0.0: icss-utils "^5.0.0" postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: - version "6.0.13" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz#d05d8d76b1e8e173257ef9d60b706a8e5e99bf1b" - integrity sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ== + version "6.0.15" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz#11cc2b21eebc0b99ea374ffb9887174855a01535" + integrity sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw== dependencies: cssesc "^3.0.0" util-deprecate "^1.0.2" @@ -6649,12 +6711,12 @@ postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss@^8.4.21: - version "8.4.31" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d" - integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ== +postcss@^8.4.31: + version "8.4.33" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.33.tgz#1378e859c9f69bf6f638b990a0212f43e2aaa742" + integrity sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg== dependencies: - nanoid "^3.3.6" + nanoid "^3.3.7" picocolors "^1.0.0" source-map-js "^1.0.2" @@ -6903,9 +6965,9 @@ regenerate@^1.4.2: integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== regenerator-runtime@^0.14.0: - version "0.14.0" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz#5e19d68eb12d486f797e15a3c6a918f7cec5eb45" - integrity sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA== + version "0.14.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" + integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== regenerator-transform@^0.15.2: version "0.15.2" @@ -7197,10 +7259,11 @@ select-hose@^2.0.0: integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg== selfsigned@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.1.1.tgz#18a7613d714c0cd3385c48af0075abf3f266af61" - integrity sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ== + version "2.4.1" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.4.1.tgz#560d90565442a3ed35b674034cec4e95dceb4ae0" + integrity sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q== dependencies: + "@types/node-forge" "^1.3.0" node-forge "^1" semver-compare@^1.0.0: @@ -7218,7 +7281,7 @@ semver@^6.2.0, semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.1.1, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.5, semver@^7.3.8: +semver@^7.1.1, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.5, semver@^7.5.4: version "7.5.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== @@ -7251,13 +7314,20 @@ serialize-error@^7.0.1: dependencies: type-fest "^0.13.1" -serialize-javascript@^6.0.0, serialize-javascript@^6.0.1: +serialize-javascript@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.1.tgz#b206efb27c3da0b0ab6b52f48d170b7996458e5c" integrity sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w== dependencies: randombytes "^2.1.0" +serialize-javascript@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" + integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== + dependencies: + randombytes "^2.1.0" + serve-index@^1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" @@ -7286,6 +7356,16 @@ set-blocking@^2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== +set-function-length@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.1.1.tgz#4bc39fafb0307224a33e106a7d35ca1218d659ed" + integrity sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ== + dependencies: + define-data-property "^1.1.1" + get-intrinsic "^1.2.1" + gopd "^1.0.1" + has-property-descriptors "^1.0.0" + setprototypeof@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" @@ -7599,9 +7679,9 @@ strip-outer@^1.0.1: escape-string-regexp "^1.0.2" style-loader@^3.3.1: - version "3.3.3" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.3.tgz#bba8daac19930169c0c9c96706749a597ae3acff" - integrity sha512-53BiGLXAcll9maCYtZi2RCQZKa8NQQai5C4horqKyRmHj9H7QmcUyucrH+4KW/gBQbXM2AsB0axoEcFZPlfPcw== + version "3.3.4" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.4.tgz#f30f786c36db03a45cbd55b6a70d930c479090e7" + integrity sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w== style-to-object@^1.0.0: version "1.0.5" @@ -7691,20 +7771,20 @@ temp@^0.9.0: rimraf "~2.6.2" terser-webpack-plugin@^5.3.7: - version "5.3.9" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz#832536999c51b46d468067f9e37662a3b96adfe1" - integrity sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA== + version "5.3.10" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" + integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w== dependencies: - "@jridgewell/trace-mapping" "^0.3.17" + "@jridgewell/trace-mapping" "^0.3.20" jest-worker "^27.4.5" schema-utils "^3.1.1" serialize-javascript "^6.0.1" - terser "^5.16.8" + terser "^5.26.0" -terser@^5.16.8: - version "5.24.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.24.0.tgz#4ae50302977bca4831ccc7b4fef63a3c04228364" - integrity sha512-ZpGR4Hy3+wBEzVEnHvstMvqpD/nABNelQn/z2r0fjVWGQsN3bpOLzQlqDxmb4CDZnXq5lpjnQ+mHQLAOpfM5iw== +terser@^5.26.0: + version "5.26.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.26.0.tgz#ee9f05d929f4189a9c28a0feb889d96d50126fe1" + integrity sha512-dytTGoE2oHgbNV9nTzgBEPaqAWvcJNl66VZ0BkJqlvp71IjO8CxdBx/ykCNb47cLnCmCvRZ6ZR0tLkqvZCdVBQ== dependencies: "@jridgewell/source-map" "^0.3.3" acorn "^8.8.2" @@ -7827,10 +7907,10 @@ type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" -typescript@^4.7.3: - version "4.9.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" - integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== +typescript@^5.0.0: + version "5.3.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" + integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== undici-types@~5.26.4: version "5.26.5" @@ -8317,9 +8397,9 @@ ws@^7.3.1: integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== ws@^8.13.0: - version "8.14.2" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.14.2.tgz#6c249a806eb2db7a20d26d51e7709eab7b2e6c7f" - integrity sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g== + version "8.16.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.16.0.tgz#d1cd774f36fbc07165066a60e40323eab6446fd4" + integrity sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ== xmlbuilder@^15.1.1: version "15.1.1" From ff65a3f042667e5d86a796ae6fd71b58fee4551e Mon Sep 17 00:00:00 2001 From: Evan Simkowitz Date: Thu, 11 Jan 2024 22:08:17 -0500 Subject: [PATCH 25/25] Bump electron to version 28 (#225) * Bump electron to version 28 * update electron-forge --- package.json | 14 +- yarn.lock | 395 +++++++++++++++++++++++++++++---------------------- 2 files changed, 232 insertions(+), 177 deletions(-) diff --git a/package.json b/package.json index f118fe5ca..472eabd0b 100644 --- a/package.json +++ b/package.json @@ -50,12 +50,12 @@ "@babel/preset-env": "^7.18.2", "@babel/preset-react": "^7.23.3", "@babel/preset-typescript": "^7.17.12", - "@electron-forge/cli": "^6.0.0-beta.70", - "@electron-forge/maker-deb": "^6.0.0-beta.70", - "@electron-forge/maker-rpm": "^6.0.0-beta.70", - "@electron-forge/maker-snap": "^6.4.2", - "@electron-forge/maker-squirrel": "^6.0.0-beta.70", - "@electron-forge/maker-zip": "^6.0.0-beta.70", + "@electron-forge/cli": "^7.2.0", + "@electron-forge/maker-deb": "^7.2.0", + "@electron-forge/maker-rpm": "^7.2.0", + "@electron-forge/maker-snap": "^7.2.0", + "@electron-forge/maker-squirrel": "^7.2.0", + "@electron-forge/maker-zip": "^7.2.0", "@electron/rebuild": "^3.4.0", "@svgr/webpack": "^8.1.0", "@types/classnames": "^2.3.1", @@ -71,7 +71,7 @@ "babel-plugin-jsx-control-statements": "^4.1.2", "copy-webpack-plugin": "^11.0.0", "css-loader": "^6.7.1", - "electron": "27.1.3", + "electron": "28.1.3", "file-loader": "^6.2.0", "http-server": "^14.1.1", "less": "^4.1.2", diff --git a/yarn.lock b/yarn.lock index dfe7e7c3b..48e8dd4c6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1454,14 +1454,14 @@ resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== -"@electron-forge/cli@^6.0.0-beta.70": - version "6.4.2" - resolved "https://registry.yarnpkg.com/@electron-forge/cli/-/cli-6.4.2.tgz#a4d8dc5d3ed6f5ca358f7b92e756e14390d04b0f" - integrity sha512-bM6YVTV0uUEpIL1jkpARlSm4Li26XZn+avC/lyTdpPqnd65T/oXZNkrAD+2Jb0RlgplOaM21qWm7ybtvKDGDyA== +"@electron-forge/cli@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@electron-forge/cli/-/cli-7.2.0.tgz#54349ed2b1cb0e09dd8cff51cf3699b62163ab46" + integrity sha512-FJ8XzT4w6bTC3trvHHWL67W1zp7g2xmCC5riNa1rjk8Gd2C1j8wf0ul4ch9kbcaEAFaXuXwv98QKXxhCn4aLtQ== dependencies: - "@electron-forge/core" "6.4.2" - "@electron-forge/shared-types" "6.4.2" - "@electron/get" "^2.0.0" + "@electron-forge/core" "7.2.0" + "@electron-forge/shared-types" "7.2.0" + "@electron/get" "^3.0.0" chalk "^4.0.0" commander "^4.1.1" debug "^4.3.1" @@ -1469,12 +1469,12 @@ listr2 "^5.0.3" semver "^7.2.1" -"@electron-forge/core-utils@6.4.2": - version "6.4.2" - resolved "https://registry.yarnpkg.com/@electron-forge/core-utils/-/core-utils-6.4.2.tgz#99c2b459e07ec504b3e0ee0af090e180e78aefa1" - integrity sha512-CjB3aakmRsXAMMDYc8PxNTMf4FdI29y4PErfv7eCXlL5oo3JW0VSKZIV7R8/Po0S0got85q2kmhZgCKuxL1BNA== +"@electron-forge/core-utils@7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@electron-forge/core-utils/-/core-utils-7.2.0.tgz#4634a264fa9a20c6957879d5d6dcd6bde88b62c2" + integrity sha512-PI1wETlF/+Cxm1m/IgURQ9S3LzHU70/S4CHmkw4xJg4wYVRTfiKpH2XRE9VqEJU854hEnsCGynAIn7/Z2h6SIA== dependencies: - "@electron-forge/shared-types" "6.4.2" + "@electron-forge/shared-types" "7.2.0" "@electron/rebuild" "^3.2.10" "@malept/cross-spawn-promise" "^2.0.0" chalk "^4.0.0" @@ -1485,27 +1485,28 @@ semver "^7.2.1" yarn-or-npm "^3.0.1" -"@electron-forge/core@6.4.2": - version "6.4.2" - resolved "https://registry.yarnpkg.com/@electron-forge/core/-/core-6.4.2.tgz#0ba39730e7e27cdbc6565a00c58c5a37a2489050" - integrity sha512-VtrFZ1Q7NG1ov0jJO/tUvUiYdWZ0Y31xw762is/jfpRPD6V/soOpwJJAoWoPK9TZVkTm2pkS8S5LikCMbNCLxw== +"@electron-forge/core@7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@electron-forge/core/-/core-7.2.0.tgz#467d0aadf449b8404dae6894037d6e707d93b34d" + integrity sha512-7Sh0KW79Z/y9MStU3sWTBbTkM4SvV6rL557/ndlfAbZrxcGMnmWHrzn/odAZW1eyfhKguBb7C1Ijw0YTpsdVsw== dependencies: - "@electron-forge/core-utils" "6.4.2" - "@electron-forge/maker-base" "6.4.2" - "@electron-forge/plugin-base" "6.4.2" - "@electron-forge/publisher-base" "6.4.2" - "@electron-forge/shared-types" "6.4.2" - "@electron-forge/template-base" "6.4.2" - "@electron-forge/template-vite" "6.4.2" - "@electron-forge/template-vite-typescript" "6.4.2" - "@electron-forge/template-webpack" "6.4.2" - "@electron-forge/template-webpack-typescript" "6.4.2" - "@electron/get" "^2.0.0" + "@electron-forge/core-utils" "7.2.0" + "@electron-forge/maker-base" "7.2.0" + "@electron-forge/plugin-base" "7.2.0" + "@electron-forge/publisher-base" "7.2.0" + "@electron-forge/shared-types" "7.2.0" + "@electron-forge/template-base" "7.2.0" + "@electron-forge/template-vite" "7.2.0" + "@electron-forge/template-vite-typescript" "7.2.0" + "@electron-forge/template-webpack" "7.2.0" + "@electron-forge/template-webpack-typescript" "7.2.0" + "@electron-forge/tracer" "7.2.0" + "@electron/get" "^3.0.0" + "@electron/packager" "^18.0.0" "@electron/rebuild" "^3.2.10" "@malept/cross-spawn-promise" "^2.0.0" chalk "^4.0.0" debug "^4.3.1" - electron-packager "^17.1.2" fast-glob "^3.2.7" filenamify "^4.1.0" find-up "^5.0.0" @@ -1525,137 +1526,145 @@ username "^5.1.0" yarn-or-npm "^3.0.1" -"@electron-forge/maker-base@6.4.2": - version "6.4.2" - resolved "https://registry.yarnpkg.com/@electron-forge/maker-base/-/maker-base-6.4.2.tgz#0403f12773f816089f37c42792025162e067defe" - integrity sha512-zW3GH+LqDK9nxQmQEFkJPR8RqiX0lVk6a4mXll3ngujN1fPevO4ivUAWmaEVeC1dH/hXbN7s9m0S6a37MigftQ== +"@electron-forge/maker-base@7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@electron-forge/maker-base/-/maker-base-7.2.0.tgz#2086b1ffc110316d8336e96e72c81aefd0c62c54" + integrity sha512-5dCFiVo4WhSlLf/T9MP+jnMqP3qfmwvjCSiTRE08USeotNWhycztcFox94NbxMJkRt329tNeG2RRs7RzdCz21w== dependencies: - "@electron-forge/shared-types" "6.4.2" + "@electron-forge/shared-types" "7.2.0" fs-extra "^10.0.0" which "^2.0.2" -"@electron-forge/maker-deb@^6.0.0-beta.70": - version "6.4.2" - resolved "https://registry.yarnpkg.com/@electron-forge/maker-deb/-/maker-deb-6.4.2.tgz#8b2c1a85641d8c7f46a22d5c747ed1da393c51b5" - integrity sha512-tlV8ffivgBP94vtYXgAeXgzeKCaRyLuWH9LT8PQW1QrYbAFpCMmuwk/zFaJkyMklImCWmDFTPYMEqdEJGd7Npg== +"@electron-forge/maker-deb@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@electron-forge/maker-deb/-/maker-deb-7.2.0.tgz#31f3340cdc95eedf2229eadf52340c4b5613455a" + integrity sha512-UYulMZpof+PIcapUFxQ5pVoSqa2FsS8crY8WGbVm1ALuknJUn4C2I37S8AujQH0l7oJRGnH95Y7Bcryyhe08yw== dependencies: - "@electron-forge/maker-base" "6.4.2" - "@electron-forge/shared-types" "6.4.2" + "@electron-forge/maker-base" "7.2.0" + "@electron-forge/shared-types" "7.2.0" optionalDependencies: electron-installer-debian "^3.2.0" -"@electron-forge/maker-rpm@^6.0.0-beta.70": - version "6.4.2" - resolved "https://registry.yarnpkg.com/@electron-forge/maker-rpm/-/maker-rpm-6.4.2.tgz#a687b07382a1b4dec76e2f19588bc599648a3d69" - integrity sha512-+hfbY5pYbAer0y07OtOzVgVBHoTRmemqqZ//T0mKJpyK2ThHKGTvyW8FFlr5jlQs5LoDCM2WHKE8oGtRhivsMg== +"@electron-forge/maker-rpm@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@electron-forge/maker-rpm/-/maker-rpm-7.2.0.tgz#2b627c058922b6ed31e7394652ba1c6bb25a9f6c" + integrity sha512-XKWK8Db44O9L7Njx0jEYLPfkf5eJ/i+XqT1Tejke+t0b74uCqFMKcbWLFp1LZj0hVM3kACy1LqtTCuOlti3INA== dependencies: - "@electron-forge/maker-base" "6.4.2" - "@electron-forge/shared-types" "6.4.2" + "@electron-forge/maker-base" "7.2.0" + "@electron-forge/shared-types" "7.2.0" optionalDependencies: electron-installer-redhat "^3.2.0" -"@electron-forge/maker-snap@^6.4.2": - version "6.4.2" - resolved "https://registry.yarnpkg.com/@electron-forge/maker-snap/-/maker-snap-6.4.2.tgz#6a87e92ee07d460e91697064e0d8369c55114aba" - integrity sha512-07ge28xLdcUpLQFu9POuNuaR8rWjU3c9r2PX8dMrvgAi00DooVaLuZFF7DIOPRDxFO5JfX1BwgzjO7KZhMA3og== +"@electron-forge/maker-snap@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@electron-forge/maker-snap/-/maker-snap-7.2.0.tgz#a82f6027c3fb8234f59a683fc6ac75e9816681ce" + integrity sha512-qOq/iUJcsE+8SmaBpnhF7SPMhUsRVoRPvmz16+OG2RDvt5XIwS6S/yHiZjGlFUyz5XDp2OM3Yb85vNF+27O5zg== dependencies: - "@electron-forge/maker-base" "6.4.2" - "@electron-forge/shared-types" "6.4.2" + "@electron-forge/maker-base" "7.2.0" + "@electron-forge/shared-types" "7.2.0" optionalDependencies: electron-installer-snap "^5.2.0" -"@electron-forge/maker-squirrel@^6.0.0-beta.70": - version "6.4.2" - resolved "https://registry.yarnpkg.com/@electron-forge/maker-squirrel/-/maker-squirrel-6.4.2.tgz#92d44fc6cadf6ff23c65dc901c8044d7c8b53f95" - integrity sha512-ukK3RcFaBrQXUzR52PsHxfwDq5XKSnj6A1kkXiyHWqgj+HIU97prBScBb5JRtasPvYN+nDdQO2vlInsLaqcx9Q== +"@electron-forge/maker-squirrel@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@electron-forge/maker-squirrel/-/maker-squirrel-7.2.0.tgz#eb573369919678468207b22a842da0c802ffdac6" + integrity sha512-SyPeFgJoMUcOPDM8+1AUPuseOqnl5YqnnjgKX9+YUIrsGKIsSz1cTtSOEu5R/l2yWNWFTmLnOlcuqIe7NayHBg== dependencies: - "@electron-forge/maker-base" "6.4.2" - "@electron-forge/shared-types" "6.4.2" + "@electron-forge/maker-base" "7.2.0" + "@electron-forge/shared-types" "7.2.0" fs-extra "^10.0.0" optionalDependencies: electron-winstaller "^5.0.0" -"@electron-forge/maker-zip@^6.0.0-beta.70": - version "6.4.2" - resolved "https://registry.yarnpkg.com/@electron-forge/maker-zip/-/maker-zip-6.4.2.tgz#f8a064bde04bfc73756716ed4d7d62bdd455de28" - integrity sha512-k2nfhhnxcYbUS7rCKCisuqEalxtH9l73+lrtfL0aQZiE/BLbDXyNckDIDOPvX0tBEg62nVzUdJonZwOhZVvAMw== +"@electron-forge/maker-zip@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@electron-forge/maker-zip/-/maker-zip-7.2.0.tgz#59926d108dc2af52a80bc1ad673c33eb7290ae09" + integrity sha512-U6FSSMcHogHDv+7SmF037lJ9m0stwwqyerw7Q6mD3jKQHX9GBxFApEzA5HSURGPAEBhPgPppYOSMGRB6LV5F2g== dependencies: - "@electron-forge/maker-base" "6.4.2" - "@electron-forge/shared-types" "6.4.2" + "@electron-forge/maker-base" "7.2.0" + "@electron-forge/shared-types" "7.2.0" cross-zip "^4.0.0" fs-extra "^10.0.0" got "^11.8.5" -"@electron-forge/plugin-base@6.4.2": - version "6.4.2" - resolved "https://registry.yarnpkg.com/@electron-forge/plugin-base/-/plugin-base-6.4.2.tgz#65054f841728688cc31edeb94479e6bd4bc07782" - integrity sha512-g6AAtQ7fZ94djBmwcnWasQ8xgaNVNjgaQ00GLK0NkmQ7n0PNbsnlMDuw9vdfTiL6WaLg5nxNSYc9bFJP/rtyeA== +"@electron-forge/plugin-base@7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@electron-forge/plugin-base/-/plugin-base-7.2.0.tgz#1d7f3cb6ededc68139b3556ccae5bbce6cbac7ff" + integrity sha512-c/pQK36BMBMKiemO68g1ZQOCXBA93x/aeX3lIXwK5bKVuaGt16Unfmby5Q7iIvY+/KsBuLYGkAder8HDN+4Nbw== dependencies: - "@electron-forge/shared-types" "6.4.2" + "@electron-forge/shared-types" "7.2.0" -"@electron-forge/publisher-base@6.4.2": - version "6.4.2" - resolved "https://registry.yarnpkg.com/@electron-forge/publisher-base/-/publisher-base-6.4.2.tgz#89a5a85a889bfc96ae760b801a91da39f212f6b5" - integrity sha512-Tnf9O8MFzdT1gsb5EDDaQUoslt7gUuUywtsr+lT/fpBlBQbei2fvioTwvZ1Q1cmsKnld7XhRh6unfgdWLTZzgw== +"@electron-forge/publisher-base@7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@electron-forge/publisher-base/-/publisher-base-7.2.0.tgz#dce47a7e4b3caaf36e87dce4d0fa21c7e11504e2" + integrity sha512-c0pwcQeMZi0S4iLlgA3pqm6ZdW2u7Ea4Ynat04Gw7su5GLtbrKRgYSL36ZRhzz7sgm4372niI0k91KaH5KToHg== dependencies: - "@electron-forge/shared-types" "6.4.2" + "@electron-forge/shared-types" "7.2.0" -"@electron-forge/shared-types@6.4.2": - version "6.4.2" - resolved "https://registry.yarnpkg.com/@electron-forge/shared-types/-/shared-types-6.4.2.tgz#ffc25a21d1bc7e6cb8fcf8dc1e1767c6a8c52d02" - integrity sha512-DKOUMsdTXZIq8XiqY0Hi3C+dam/JKUnvfBjwcUeyZqPdgEE1qry8xZmmjorXuLrRf1Jq8rhxYGQInSK4af0QYw== +"@electron-forge/shared-types@7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@electron-forge/shared-types/-/shared-types-7.2.0.tgz#8642910693e957e9da18fa9fff2d8da2d14a0415" + integrity sha512-d8i+pwPwBnlmFTRkq7QfaoRS9LywfyjDdHqQZuArFbL6NLAEbZ52irFiAE3NSLf4STew/BA6IK9sTPz3KRmvQw== dependencies: + "@electron-forge/tracer" "7.2.0" + "@electron/packager" "^18.0.0" "@electron/rebuild" "^3.2.10" - electron-packager "^17.1.2" listr2 "^5.0.3" -"@electron-forge/template-base@6.4.2": - version "6.4.2" - resolved "https://registry.yarnpkg.com/@electron-forge/template-base/-/template-base-6.4.2.tgz#9351dac21d46a86e3826feaf4d8ea6286d627e42" - integrity sha512-vsQh+64Fr2Vxg6k8DAahWq4MAdB2F2qTig+LgIJENv8ksbzC1YIq05SBAS/g2674cdr7WdwyukMy2rgxe3rhnQ== +"@electron-forge/template-base@7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@electron-forge/template-base/-/template-base-7.2.0.tgz#dec1f1279520ff3dadc490ee69a4f8165c3a546a" + integrity sha512-X7JrgQctgN0saFih/kKWVJ3KxiI1BpzdrkW58vs5H0kXXmA6UObE16/dWuKYfB06j0yIsfMbZ32Md1yAkgdCfg== dependencies: - "@electron-forge/shared-types" "6.4.2" + "@electron-forge/shared-types" "7.2.0" "@malept/cross-spawn-promise" "^2.0.0" debug "^4.3.1" fs-extra "^10.0.0" username "^5.1.0" -"@electron-forge/template-vite-typescript@6.4.2": - version "6.4.2" - resolved "https://registry.yarnpkg.com/@electron-forge/template-vite-typescript/-/template-vite-typescript-6.4.2.tgz#197a321745b946bd1170d67ed70321193f62e1d8" - integrity sha512-h3pn6onvC/nLglmJuelYU82Qzrh0l6MqvbBGoT39bbDoRLIqmlhWTWppHgDJVXAGrSoH+9BEpptipeBQWirFwg== +"@electron-forge/template-vite-typescript@7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@electron-forge/template-vite-typescript/-/template-vite-typescript-7.2.0.tgz#7453583d7671fca9deb33038a14eef960c5225a8" + integrity sha512-knN3lxJY6UyXa2u5957K4ZyItCoCw22wrUhQARvdHOcgXvMFAcwvfEDT8zOQy6ki6A9W3cMHhSTys7dC8/ChVw== dependencies: - "@electron-forge/shared-types" "6.4.2" - "@electron-forge/template-base" "6.4.2" + "@electron-forge/shared-types" "7.2.0" + "@electron-forge/template-base" "7.2.0" fs-extra "^10.0.0" -"@electron-forge/template-vite@6.4.2": - version "6.4.2" - resolved "https://registry.yarnpkg.com/@electron-forge/template-vite/-/template-vite-6.4.2.tgz#c8b49e3517ffca32818446916abf6871afc6f3be" - integrity sha512-NX7jHRblBmIqufMbqWgpI/VnpgF/qMSTq9ZPmDSXamBhid336MC6+DoWzDpXceQZEp0m/jpMLR04ynr8O4jGlg== +"@electron-forge/template-vite@7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@electron-forge/template-vite/-/template-vite-7.2.0.tgz#0b37eada1094ee16fd7fc9f229cafa3b8cb475d4" + integrity sha512-Q5FSD+NVNMJKuAo/htQXpk3Q/eo116Xhx0zTzhSldAqpsgfxdAIJhl8TFmdVvCJIig1vEcLG2n/PgudxnuDuEQ== dependencies: - "@electron-forge/shared-types" "6.4.2" - "@electron-forge/template-base" "6.4.2" + "@electron-forge/shared-types" "7.2.0" + "@electron-forge/template-base" "7.2.0" fs-extra "^10.0.0" -"@electron-forge/template-webpack-typescript@6.4.2": - version "6.4.2" - resolved "https://registry.yarnpkg.com/@electron-forge/template-webpack-typescript/-/template-webpack-typescript-6.4.2.tgz#06dbd326878ffd1ec47b5f3cdea0a7260c8e5568" - integrity sha512-MPAZQ4v6piCED7NT1LTVQf61o6Eg/laNoKbhbrFBSH1i20OUwbtV2MLj6Op292ynI9+1qdHKmFgctr6qPTCAQw== +"@electron-forge/template-webpack-typescript@7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@electron-forge/template-webpack-typescript/-/template-webpack-typescript-7.2.0.tgz#2a77e5a11026b29e6f74ef476ce7e8c23ba80b08" + integrity sha512-eshvPcYXUgmpB+ts9/xRPvQexY46unfe0mGmLDaj8s/5fqCANgyUO5jusvMXlJdf3qwJ/rfi3jS0NuqnjsqskQ== dependencies: - "@electron-forge/shared-types" "6.4.2" - "@electron-forge/template-base" "6.4.2" + "@electron-forge/shared-types" "7.2.0" + "@electron-forge/template-base" "7.2.0" fs-extra "^10.0.0" -"@electron-forge/template-webpack@6.4.2": - version "6.4.2" - resolved "https://registry.yarnpkg.com/@electron-forge/template-webpack/-/template-webpack-6.4.2.tgz#b8b4cd664d9d2593588bcbb6e0ac1e4c27814ffc" - integrity sha512-9QYr/td4cmnGOj8UF25W6An/eI+JXj9T/b+KFybL3cQ87H1yrQOn2T84Bm5/JaB4SPdIu4FdKRjqwR7C7R0g2w== +"@electron-forge/template-webpack@7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@electron-forge/template-webpack/-/template-webpack-7.2.0.tgz#91c77fb27b1405569ff52536e659283b5282909e" + integrity sha512-h2LQ3vAzIraRqLUM5fKOLXknp7n5hrQXudRjO/vEEbm1a0jbl4yjp6liKk3yx8MFFO4eAHVDrXwRSsLR3a2Wew== dependencies: - "@electron-forge/shared-types" "6.4.2" - "@electron-forge/template-base" "6.4.2" + "@electron-forge/shared-types" "7.2.0" + "@electron-forge/template-base" "7.2.0" fs-extra "^10.0.0" +"@electron-forge/tracer@7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@electron-forge/tracer/-/tracer-7.2.0.tgz#e70fb373946cce4c40409a3d9152d3bbfcec2057" + integrity sha512-EoJ07nptEuuY2fcs/bUWzIf11RQRx6Ch/dZ6A9WIRcFYe9cFrslQwvyUf0siY3jcqVvxETCz69JGuBxKGwak7A== + dependencies: + chrome-trace-event "^1.0.3" + "@electron/asar@^3.2.1": version "3.2.7" resolved "https://registry.yarnpkg.com/@electron/asar/-/asar-3.2.7.tgz#bb8117dc6fd0c06a922ae7fb1c0e2d433e35a6e5" @@ -1665,6 +1674,15 @@ glob "^7.1.6" minimatch "^3.0.4" +"@electron/asar@^3.2.7": + version "3.2.8" + resolved "https://registry.yarnpkg.com/@electron/asar/-/asar-3.2.8.tgz#2ea722f3452583dbd4ffdcc4b4f5dc903f1d8178" + integrity sha512-cmskk5M06ewHMZAplSiF4AlME3IrnnZhKnWbtwKVLRkdJkKyUVjMLhDIiPIx/+6zQWVlKX/LtmK9xDme7540Sg== + dependencies: + commander "^5.0.0" + glob "^7.1.6" + minimatch "^3.0.4" + "@electron/get@^2.0.0": version "2.0.3" resolved "https://registry.yarnpkg.com/@electron/get/-/get-2.0.3.tgz#fba552683d387aebd9f3fcadbcafc8e12ee4f960" @@ -1680,13 +1698,29 @@ optionalDependencies: global-agent "^3.0.0" -"@electron/notarize@^1.2.3": - version "1.2.4" - resolved "https://registry.yarnpkg.com/@electron/notarize/-/notarize-1.2.4.tgz#a7d38773f4cad40df111a5edc64037e5d768ea1e" - integrity sha512-W5GQhJEosFNafewnS28d3bpQ37/s91CDWqxVchHfmv2dQSTWpOzNlUVQwYzC1ay5bChRV/A9BTL68yj0Pa+TSg== +"@electron/get@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@electron/get/-/get-3.0.0.tgz#2b0c794b98902d0bc5218546872c1379bef68aa2" + integrity sha512-hLv4BYFiyrNRI+U0Mm2X7RxCCdJLkDUn8GCEp9QJzbLpZRko+UaLlCjOMkj6TEtirNLPyBA7y1SeGfnpOB21aQ== + dependencies: + debug "^4.1.1" + env-paths "^2.2.0" + fs-extra "^8.1.0" + got "^11.8.5" + progress "^2.0.3" + semver "^6.2.0" + sumchecker "^3.0.1" + optionalDependencies: + global-agent "^3.0.0" + +"@electron/notarize@^2.1.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@electron/notarize/-/notarize-2.2.0.tgz#40455f9d8ca8098a74567aa4613b709089d82657" + integrity sha512-Sf7RG47rafeGuUm+kLEbTXMN8XZeYXN70dMBstrcgiykxCq3SLl1uqxFWndxSI1LfMqv4Eq9PTDHLPwiya31Kg== dependencies: debug "^4.1.1" fs-extra "^9.0.1" + promise-retry "^2.0.1" "@electron/osx-sign@^1.0.5": version "1.0.5" @@ -1700,6 +1734,32 @@ minimist "^1.2.6" plist "^3.0.5" +"@electron/packager@^18.0.0": + version "18.1.3" + resolved "https://registry.yarnpkg.com/@electron/packager/-/packager-18.1.3.tgz#53eba507e5dccaa4cbfae56bf6e2f58a7bc257a5" + integrity sha512-21T5MxUf7DwV07IIes3jO/571mXCjOGVPdmYJFPCVDTimFiHQSW0Oy+OIGQaKBiNIXfnP29KylsCQbmds6O6Iw== + dependencies: + "@electron/asar" "^3.2.1" + "@electron/get" "^3.0.0" + "@electron/notarize" "^2.1.0" + "@electron/osx-sign" "^1.0.5" + "@electron/universal" "^2.0.1" + "@electron/windows-sign" "^1.0.0" + cross-spawn-windows-exe "^1.2.0" + debug "^4.0.1" + extract-zip "^2.0.0" + filenamify "^4.1.0" + fs-extra "^11.1.0" + galactus "^1.0.0" + get-package-info "^1.0.0" + junk "^3.1.0" + parse-author "^2.0.0" + plist "^3.0.0" + rcedit "^4.0.0" + resolve "^1.1.6" + semver "^7.1.3" + yargs-parser "^21.1.1" + "@electron/rebuild@^3.2.10": version "3.3.0" resolved "https://registry.yarnpkg.com/@electron/rebuild/-/rebuild-3.3.0.tgz#6ba0ae1cb545b2e314901d2ac175ca9c03a2e3da" @@ -1739,18 +1799,27 @@ tar "^6.0.5" yargs "^17.0.1" -"@electron/universal@^1.3.2": - version "1.4.2" - resolved "https://registry.yarnpkg.com/@electron/universal/-/universal-1.4.2.tgz#66668ece1c772054846a42bf649daac9c3ee23b7" - integrity sha512-ymGwXYBUGFS1DuTqYJwZ0p1gIlELKOf21zPJefij/amzV66vTXRNJ2mAtW0uRsaHfV+pzYTJVrt5oco44DFOMg== +"@electron/universal@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@electron/universal/-/universal-2.0.1.tgz#7b070ab355e02957388f3dbd68e2c3cd08c448ae" + integrity sha512-fKpv9kg4SPmt+hY7SVBnIYULE9QJl8L3sCfcBsnqbJwwBwAeTLokJ9TRt9y7bK0JAzIW2y78TVVjvnQEms/yyA== dependencies: - "@electron/asar" "^3.2.1" - "@malept/cross-spawn-promise" "^1.1.0" + "@electron/asar" "^3.2.7" + "@malept/cross-spawn-promise" "^2.0.0" debug "^4.3.1" - dir-compare "^3.0.0" - fs-extra "^9.0.1" - minimatch "^3.0.4" - plist "^3.0.4" + dir-compare "^4.2.0" + fs-extra "^11.1.1" + minimatch "^9.0.3" + plist "^3.1.0" + +"@electron/windows-sign@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@electron/windows-sign/-/windows-sign-1.0.0.tgz#f08a0a5d4b96840ab637ce11228a59ee8b665287" + integrity sha512-sdkQYAR/TQCEyYgz2jMbusL/ljdj6qA7vyIm/S9HICMAitXhXROFHUOLLgiORj1uiaf2EOB2U33DatGubUuZaQ== + dependencies: + debug "^4.3.4" + fs-extra "^11.1.1" + minimist "^1.2.8" "@emotion/is-prop-valid@^0.8.2": version "0.8.8" @@ -2937,11 +3006,6 @@ buffer-crc32@~0.2.3: resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ== -buffer-equal@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.1.tgz#2f7651be5b1b3f057fcd6e7ee16cf34767077d90" - integrity sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg== - buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" @@ -3093,7 +3157,7 @@ chownr@^2.0.0: resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== -chrome-trace-event@^1.0.2: +chrome-trace-event@^1.0.2, chrome-trace-event@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== @@ -3619,13 +3683,13 @@ devlop@^1.0.0, devlop@^1.1.0: dependencies: dequal "^2.0.0" -dir-compare@^3.0.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/dir-compare/-/dir-compare-3.3.0.tgz#2c749f973b5c4b5d087f11edaae730db31788416" - integrity sha512-J7/et3WlGUCxjdnD3HAAzQ6nsnc0WL6DD7WcwJb7c39iH1+AWfg+9OqzJNaI6PkBwBvm1mhZNL9iY/nRiZXlPg== +dir-compare@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/dir-compare/-/dir-compare-4.2.0.tgz#d1d4999c14fbf55281071fdae4293b3b9ce86f19" + integrity sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ== dependencies: - buffer-equal "^1.0.0" - minimatch "^3.0.4" + minimatch "^3.0.5" + p-limit "^3.1.0 " dir-glob@^3.0.1: version "3.0.1" @@ -3754,31 +3818,6 @@ electron-installer-snap@^5.2.0: which "^2.0.1" yargs "^16.0.2" -electron-packager@^17.1.2: - version "17.1.2" - resolved "https://registry.yarnpkg.com/electron-packager/-/electron-packager-17.1.2.tgz#18030b28024d242b706d0a8a67ed4cd1a57311aa" - integrity sha512-XofXdikjYI7MVBcnXeoOvRR+yFFFHOLs3J7PF5KYQweigtgLshcH4W660PsvHr4lYZ03JBpLyEcUB8DzHZ+BNw== - dependencies: - "@electron/asar" "^3.2.1" - "@electron/get" "^2.0.0" - "@electron/notarize" "^1.2.3" - "@electron/osx-sign" "^1.0.5" - "@electron/universal" "^1.3.2" - cross-spawn-windows-exe "^1.2.0" - debug "^4.0.1" - extract-zip "^2.0.0" - filenamify "^4.1.0" - fs-extra "^11.1.0" - galactus "^1.0.0" - get-package-info "^1.0.0" - junk "^3.1.0" - parse-author "^2.0.0" - plist "^3.0.0" - rcedit "^3.0.1" - resolve "^1.1.6" - semver "^7.1.3" - yargs-parser "^21.1.1" - electron-squirrel-startup@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/electron-squirrel-startup/-/electron-squirrel-startup-1.0.0.tgz#19b4e55933fa0ef8f556784b9c660f772546a0b8" @@ -3811,10 +3850,10 @@ electron@*: "@types/node" "^18.11.18" extract-zip "^2.0.1" -electron@27.1.3: - version "27.1.3" - resolved "https://registry.yarnpkg.com/electron/-/electron-27.1.3.tgz#3fd6decda95c1dd0a7e51a9ac77ee0ba37b7c5c6" - integrity sha512-7eD8VMhhlL5J531OOawn00eMthUkX1e3qN5Nqd7eMK8bg5HxQBrn8bdPlvUEnCano9KhrVwaDnGeuzWoDOGpjQ== +electron@28.1.3: + version "28.1.3" + resolved "https://registry.yarnpkg.com/electron/-/electron-28.1.3.tgz#38382a177af2fa6026b02eb4e4ebde067fb30154" + integrity sha512-NSFyTo6SndTPXzU18XRePv4LnjmuM9rF5GMKta1/kPmi02ISoSRonnD7wUlWXD2x53XyJ6d/TbSVesMW6sXkEQ== dependencies: "@electron/get" "^2.0.0" "@types/node" "^18.11.18" @@ -4287,6 +4326,15 @@ fs-extra@^11.1.0: jsonfile "^6.0.1" universalify "^2.0.0" +fs-extra@^11.1.1: + version "11.2.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b" + integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs-extra@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" @@ -6004,7 +6052,7 @@ minimalistic-assert@^1.0.0: resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== -minimatch@^3.0.4, minimatch@^3.1.1: +minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -6018,7 +6066,14 @@ minimatch@^5.0.1: dependencies: brace-expansion "^2.0.1" -minimist@^1.2.6: +minimatch@^9.0.3: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + +minimist@^1.2.6, minimist@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== @@ -6429,7 +6484,7 @@ p-limit@^2.2.0: dependencies: p-try "^2.0.0" -p-limit@^3.0.2: +p-limit@^3.0.2, "p-limit@^3.1.0 ": version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== @@ -6652,7 +6707,7 @@ pkg-dir@^7.0.0: dependencies: find-up "^6.3.0" -plist@^3.0.0, plist@^3.0.4, plist@^3.0.5: +plist@^3.0.0, plist@^3.0.5, plist@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/plist/-/plist-3.1.0.tgz#797a516a93e62f5bde55e0b9cc9c967f860893c9" integrity sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ== @@ -6842,10 +6897,10 @@ raw-loader@^4.0.2: loader-utils "^2.0.0" schema-utils "^3.0.0" -rcedit@^3.0.1: - version "3.1.0" - resolved "https://registry.yarnpkg.com/rcedit/-/rcedit-3.1.0.tgz#1563ec7a5663de639f94c5dc85429db1da364b3e" - integrity sha512-WRlRdY1qZbu1L11DklT07KuHfRk42l0NFFJdaExELEu4fEQ982bP5Z6OWGPj/wLLIuKRQDCxZJGAwoFsxhZhNA== +rcedit@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/rcedit/-/rcedit-4.0.1.tgz#892ac47a19204a380f49e00ea38ce070443343c2" + integrity sha512-bZdaQi34krFWhrDn+O53ccBDw0MkAT2Vhu75SqhtvhQu4OPyFM4RoVheyYiVQYdjhUi6EJMVWQ0tR6bCIYVkUg== dependencies: cross-spawn-windows-exe "^1.1.0"