diff --git a/package.json b/package.json index e9813da2..89c8fd68 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "@types/papaparse": "^5.3.9", "@types/react": "^18.0.12", "@types/uuid": "9.0.0", + "@types/webpack-env": "^1.18.3", "babel-loader": "^9.1.3", "babel-plugin-jsx-control-statements": "^4.1.2", "copy-webpack-plugin": "^11.0.0", diff --git a/scripthaus.md b/scripthaus.md index c2f1b88a..c3716788 100644 --- a/scripthaus.md +++ b/scripthaus.md @@ -33,7 +33,7 @@ PROMPT_DEV=1 PCLOUD_ENDPOINT="https://ot2e112zx5.execute-api.us-west-2.amazonaws ```bash # @scripthaus command typecheck # @scripthaus cd :playbook -node_modules/.bin/tsc --jsx preserve --noEmit --esModuleInterop --target ES5 --experimentalDecorators --downlevelIteration src/index.ts +node_modules/.bin/tsc --jsx preserve --noEmit --esModuleInterop --target ES5 --experimentalDecorators --downlevelIteration src/index.ts src/types/custom.d.ts ``` ```bash @@ -101,7 +101,7 @@ rm *.dmg DMG_VERSION=$(node -e 'console.log(require("./version.js"))') DMG_NAME="waveterm-macos-arm64-${DMG_VERSION}.dmg" rm *.dmg -../../create-dmg/create-dmg/create-dmg \ +/Users/sawka/work/gopath/src/github.com/create-dmg/create-dmg/create-dmg \ --volname "WaveTerm" \ --window-pos 200 120 \ --window-size 600 300 \ diff --git a/src/app/common/error/errorboundary.tsx b/src/app/common/error/errorboundary.tsx index a87998fd..d4d32a7b 100644 --- a/src/app/common/error/errorboundary.tsx +++ b/src/app/common/error/errorboundary.tsx @@ -1,5 +1,5 @@ import React, { Component, ReactNode } from "react"; -import { RendererContext } from "../../../plugins/types/types"; +import { RendererContext } from "../../../types/types"; import cn from "classnames"; interface ErrorBoundaryState { diff --git a/src/app/common/prompt/prompt.tsx b/src/app/common/prompt/prompt.tsx index 725218f4..3cdc9ebd 100644 --- a/src/app/common/prompt/prompt.tsx +++ b/src/app/common/prompt/prompt.tsx @@ -9,7 +9,7 @@ import localizedFormat from "dayjs/plugin/localizedFormat"; import { GlobalModel, LineContainerModel } from "../../../model/model"; import type { LineType, RemoteType, RemotePtrType, LineHeightChangeCallbackType } from "../../../types/types"; import cn from "classnames"; -import { isBlank, getRemoteStr } from "../../../util/util"; +import { isBlank } from "../../../util/util"; import { ReactComponent as FolderIcon } from "../../assets/icons/folder.svg"; import "./prompt.less"; @@ -33,6 +33,29 @@ type RendererComponentType = { new (props: RendererComponentProps): React.Component; }; +function makeFullRemoteRef(ownerName: string, remoteRef: string, name: string): string { + if (isBlank(ownerName) && isBlank(name)) { + return remoteRef; + } + if (!isBlank(ownerName) && isBlank(name)) { + return ownerName + ":" + remoteRef; + } + if (isBlank(ownerName) && !isBlank(name)) { + return remoteRef + ":" + name; + } + return ownerName + ":" + remoteRef + ":" + name; +} + +function getRemoteStr(rptr: RemotePtrType): string { + if (rptr == null || isBlank(rptr.remoteid)) { + return "(invalid remote)"; + } + let username = isBlank(rptr.ownerid) ? null : GlobalModel.resolveUserIdToName(rptr.ownerid); + let remoteRef = GlobalModel.resolveRemoteIdToRef(rptr.remoteid); + let fullRef = makeFullRemoteRef(username, remoteRef, rptr.name); + return fullRef; +} + function getShortVEnv(venvDir: string): string { if (isBlank(venvDir)) { return ""; @@ -133,4 +156,4 @@ class Prompt extends React.Component<{ rptr: RemotePtrType; festate: Record; renderMode: RenderModeType; noSelect?: boolean; + topBorder: boolean; }, {} > { diff --git a/src/app/magiclayout.ts b/src/app/magiclayout.ts index df8c90da..dcba4620 100644 --- a/src/app/magiclayout.ts +++ b/src/app/magiclayout.ts @@ -29,6 +29,6 @@ let m = MagicLayout; // add up all the line overhead + padding. subtract 2 so we don't see the border of neighboring line m.ScreenMaxContentHeightBuffer = m.LineHeaderHeight + m.LinePadding + m.WindowHeightOffset + m.LinesBottomPadding + m.LineMarginTop - 2; -window.MagicLayout = MagicLayout; +(window as any).MagicLayout = MagicLayout; export { MagicLayout }; diff --git a/src/app/pluginsview/pluginsview.tsx b/src/app/pluginsview/pluginsview.tsx index 94e1ceff..318b2355 100644 --- a/src/app/pluginsview/pluginsview.tsx +++ b/src/app/pluginsview/pluginsview.tsx @@ -7,7 +7,7 @@ import * as mobx from "mobx"; import { boundMethod } from "autobind-decorator"; import { GlobalModel } from "../../model/model"; import { PluginModel } from "../../plugins/plugins"; -import { ImageDisplay, Markdown } from "../common/common"; +import { Markdown } from "../common/common"; import { ReactComponent as XmarkIcon } from "../assets/icons/line/xmark.svg"; @@ -20,6 +20,11 @@ class PluginsView extends React.Component<{}, {}> { GlobalModel.pluginsModel.closeView(); } + renderPluginIcon(plugin): any { + let Comp = plugin.iconComp; + return ; + } + render() { if (GlobalModel.activeMainView.get() !== "plugins") { return <>; @@ -37,7 +42,7 @@ class PluginsView extends React.Component<{}, {}> { onClick={() => pluginsModel.setSelectedPlugin(plugin)} >
-
{plugin.getIcon()}
+
{this.renderPluginIcon(plugin)}
{plugin.title}
{plugin.vendor}
@@ -54,7 +59,7 @@ class PluginsView extends React.Component<{}, {}> { return (
-
{plugin.getIcon()}
+
{this.renderPluginIcon(plugin)}
{plugin.title}
{plugin.vendor}
diff --git a/src/app/workspace/screen/screenview.tsx b/src/app/workspace/screen/screenview.tsx index 94cf4bde..0ac81b4d 100644 --- a/src/app/workspace/screen/screenview.tsx +++ b/src/app/workspace/screen/screenview.tsx @@ -6,7 +6,7 @@ import * as mobxReact from "mobx-react"; import * as mobx from "mobx"; import { sprintf } from "sprintf-js"; import { boundMethod } from "autobind-decorator"; -import { If } from "tsx-control-statements/components"; +import { If, For } from "tsx-control-statements/components"; import cn from "classnames"; import { debounce } from "throttle-debounce"; import dayjs from "dayjs"; @@ -15,6 +15,7 @@ import type { LineType, RenderModeType, LineFactoryProps, CommandRtnType } from import * as T from "../../../types/types"; import localizedFormat from "dayjs/plugin/localizedFormat"; import { InlineSettingsTextEdit, RemoteStatusLight } from "../../common/common"; +import { getRemoteStr } from "../../common/prompt/prompt"; import { GlobalModel, ScreenLines, Screen } from "../../../model/model"; import { Line } from "../../line/linecomps"; import { LinesView } from "../../line/linesview"; @@ -61,7 +62,7 @@ class NewTabSettings extends React.Component<{ screen: Screen }, {}> { if (screen.getTabColor() == color) { return; } - let prtn = GlobalCommandRunner.screenSetSettings(this.props.screenId, { tabcolor: color }, false); + let prtn = GlobalCommandRunner.screenSetSettings(screen.screenId, { tabcolor: color }, false); util.commandRtnHandler(prtn, this.errorMessage); } @@ -71,7 +72,7 @@ class NewTabSettings extends React.Component<{ screen: Screen }, {}> { if (util.isStrEq(val, screen.name.get())) { return; } - let prtn = GlobalCommandRunner.screenSetSettings(this.props.screenId, { name: val }, false); + let prtn = GlobalCommandRunner.screenSetSettings(screen.screenId, { name: val }, false); util.commandRtnHandler(prtn, this.errorMessage); } @@ -102,7 +103,7 @@ class NewTabSettings extends React.Component<{ screen: Screen }, {}> { renderConnDropdown(): any { let { screen } = this.props; let allRemotes = util.sortAndFilterRemotes(GlobalModel.remotes.slice()); - let remote: RemoteType = null; + let remote: T.RemoteType = null; let curRemote = GlobalModel.getRemote(GlobalModel.getActiveScreen().getCurRemoteInstance().remoteid); // TODO no remote? return ( @@ -173,7 +174,7 @@ class NewTabSettings extends React.Component<{ screen: Screen }, {}> {
- You're connected to [{util.getRemoteStr(rptr)}]. Do you want to change it? + You're connected to [{getRemoteStr(rptr)}]. Do you want to change it?
{this.renderConnDropdown()} diff --git a/src/model/model.ts b/src/model/model.ts index ac614696..3fcae67b 100644 --- a/src/model/model.ts +++ b/src/model/model.ts @@ -3676,7 +3676,7 @@ class Model { return remote.remotecanonicalname; } - readRemoteFile(screenId: string, lineId: string, path: string): Promise { + readRemoteFile(screenId: string, lineId: string, path: string): Promise { let urlParams = { screenid: screenId, lineid: lineId, @@ -3711,7 +3711,7 @@ class Model { let isWriteable = (fileInfo.perm & 0o222) > 0; // checks for unix permission "w" bits (file as any).readOnly = !isWriteable; (file as any).notFound = !!fileInfo.notfound; - return file; + return file as T.ExtFile; } else { let textError: string = blobOrText; if (textError == null || textError.length == 0) { diff --git a/src/plugins/code/code.tsx b/src/plugins/code/code.tsx index 4da4df72..87da0780 100644 --- a/src/plugins/code/code.tsx +++ b/src/plugins/code/code.tsx @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import * as React from "react"; -import { RendererContext, RendererOpts, LineStateType, RendererModelContainerApi } from "../../types/types"; +import * as T from "../../types/types"; import Editor from "@monaco-editor/react"; import { Markdown } from "../../app/common/common"; import { GlobalModel, GlobalCommandRunner } from "../../model/model"; @@ -21,20 +21,20 @@ declare var monaco: any; class SourceCodeRenderer extends React.Component< { - data: Blob; + data: T.ExtBlob; cmdstr: string; cwd: string; readOnly: boolean; notFound: boolean; exitcode: number; - context: RendererContext; - opts: RendererOpts; + context: T.RendererContext; + opts: T.RendererOpts; savedHeight: number; scrollToBringIntoViewport: () => void; - lineState: LineStateType; + lineState: T.LineStateType; isSelected: boolean; shouldFocus: boolean; - rendererApi: RendererModelContainerApi; + rendererApi: T.RendererModelContainerApi; }, { code: string; diff --git a/src/plugins/core/basicrenderer.tsx b/src/plugins/core/basicrenderer.tsx index 4a6ad614..fc1caa84 100644 --- a/src/plugins/core/basicrenderer.tsx +++ b/src/plugins/core/basicrenderer.tsx @@ -17,6 +17,7 @@ import type { TermContextUnion, RendererContainerType, } from "../../types/types"; +import * as T from "../../types/types"; import { debounce, throttle } from "throttle-debounce"; import * as util from "../../util/util"; import { GlobalModel } from "../../model/model"; @@ -37,7 +38,7 @@ class SimpleBlobRendererModel { lineState: LineStateType; ptyData: PtyDataType; ptyDataSource: (termContext: TermContextUnion) => Promise; - dataBlob: Blob; + dataBlob: T.ExtBlob; readOnly: boolean; notFound: boolean; @@ -146,7 +147,9 @@ class SimpleBlobRendererModel { } rtnp.then((ptydata) => { this.ptyData = ptydata; - this.dataBlob = new Blob([this.ptyData.data]); + let blob: T.ExtBlob = new Blob([this.ptyData.data]) as T.ExtBlob; + blob.notFound = false; + this.dataBlob = blob; mobx.action(() => { this.loading.set(false); this.loadError.set(null); diff --git a/src/plugins/csv/csv.tsx b/src/plugins/csv/csv.tsx index 1a790136..62f537c9 100644 --- a/src/plugins/csv/csv.tsx +++ b/src/plugins/csv/csv.tsx @@ -3,6 +3,7 @@ import React, { FC, useEffect, useState, useRef, useMemo } from "react"; import { RendererContext, RendererOpts, LineStateType, RendererModelContainerApi } from "../../types/types"; +import * as T from "../../types/types"; import { GlobalModel } from "../../model/model"; import Papa from "papaparse"; import { @@ -27,14 +28,14 @@ type CSVRow = { }; interface Props { - data: Blob; + data: T.ExtBlob; readOnly: boolean; - context: RendererContext; - opts: RendererOpts; + context: T.RendererContext; + opts: T.RendererOpts; savedHeight: number; - lineState: LineStateType; + lineState: T.LineStateType; shouldFocus: boolean; - rendererApi: RendererModelContainerApi; + rendererApi: T.RendererModelContainerApi; scrollToBringIntoViewport: () => void; } diff --git a/src/plugins/image/image.tsx b/src/plugins/image/image.tsx index 5859577b..dbe77fb2 100644 --- a/src/plugins/image/image.tsx +++ b/src/plugins/image/image.tsx @@ -4,7 +4,7 @@ import * as React from "react"; import * as mobx from "mobx"; import * as mobxReact from "mobx-react"; -import { RendererContext, RendererOpts } from "../../types/types"; +import * as T from "../../types/types"; import "./image.less"; @@ -13,7 +13,7 @@ type CV = mobx.IComputedValue; @mobxReact.observer class SimpleImageRenderer extends React.Component< - { data: Blob; context: RendererContext; opts: RendererOpts; savedHeight: number }, + { data: T.ExtBlob; context: T.RendererContext; opts: T.RendererOpts; savedHeight: number }, {} > { objUrl: string = null; diff --git a/src/plugins/markdown/markdown.tsx b/src/plugins/markdown/markdown.tsx index ace18899..dd720f3f 100644 --- a/src/plugins/markdown/markdown.tsx +++ b/src/plugins/markdown/markdown.tsx @@ -4,7 +4,7 @@ import * as React from "react"; import * as mobx from "mobx"; import * as mobxReact from "mobx-react"; -import { RendererContext, RendererOpts } from "../../types/types"; +import * as T from "../../types/types"; import { sprintf } from "sprintf-js"; import { Markdown } from "../../app/common/common"; @@ -16,7 +16,7 @@ const MaxMarkdownSize = 200000; @mobxReact.observer class SimpleMarkdownRenderer extends React.Component< - { data: Blob; context: RendererContext; opts: RendererOpts; savedHeight: number }, + { data: T.ExtBlob; context: T.RendererContext; opts: T.RendererOpts; savedHeight: number }, {} > { markdownText: OV = mobx.observable.box(null, { name: "markdownText" }); diff --git a/src/plugins/mustache/mustache.tsx b/src/plugins/mustache/mustache.tsx index 859ddd0a..971f4f32 100644 --- a/src/plugins/mustache/mustache.tsx +++ b/src/plugins/mustache/mustache.tsx @@ -17,7 +17,7 @@ type OV = mobx.IObservableValue; @mobxReact.observer class SimpleMustacheRenderer extends React.Component< - { data: Blob; context: T.RendererContext; opts: T.RendererOpts; savedHeight: number; lineState: T.LineStateType }, + { data: T.ExtBlob; context: T.RendererContext; opts: T.RendererOpts; savedHeight: number; lineState: T.LineStateType }, {} > { templateLoading: OV = mobx.observable.box(true, { name: "templateLoading" }); diff --git a/src/plugins/plugins.ts b/src/plugins/plugins.ts index a9a8809c..34cd9caa 100644 --- a/src/plugins/plugins.ts +++ b/src/plugins/plugins.ts @@ -152,7 +152,7 @@ class PluginModelClass { const handleImportError = (error, resourceType) => console.error(`Failed to load ${resourceType} for plugin ${plugin.name}`); const iconPromise = import(`../plugins/${plugin.name}/icon.svg`) - .then((icon) => (plugin.getIcon = icon.ReactComponent)) + .then((icon) => (plugin.iconComp = icon.ReactComponent)) .catch((error) => handleImportError(error, "icon")); const readmePromise = import(`../plugins/${plugin.name}/readme.md`) .then((content) => (plugin.readme = content.default)) diff --git a/src/types/custom.d.ts b/src/types/custom.d.ts new file mode 100644 index 00000000..3b9a9c8f --- /dev/null +++ b/src/types/custom.d.ts @@ -0,0 +1,6 @@ +declare module '*.svg' { + import * as React from 'react'; + export const ReactComponent: React.FunctionComponent & { title?: string }>; + const src: string; + export default src; +} diff --git a/src/types/types.ts b/src/types/types.ts index 670c2ba4..ddd50d2f 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -381,6 +381,12 @@ type RendererPluginType = { modelCtor?: () => RendererModel; simpleComponent?: SimpleBlobRendererComponent; fullComponent?: FullRendererComponent; + readme?: string; + screenshots?: any[]; + vendor?: string; + summary?: string; + title?: string; + iconComp?: React.Component<{}, {}>; }; type RendererModelContainerApi = { @@ -412,7 +418,7 @@ type RendererModel = { }; type SimpleBlobRendererComponent = React.ComponentType<{ - data: Blob; + data: ExtBlob; readOnly?: boolean; notFound?: boolean; isSelected?: boolean; @@ -624,6 +630,14 @@ type FileInfoType = { notfound: boolean; }; +type ExtBlob = Blob & { + notFound: boolean; +}; + +type ExtFile = File & { + notFound: boolean; +}; + export type { SessionDataType, LineStateType, @@ -693,4 +707,6 @@ export type { CommandRtnType, OpenAIPacketType, FileInfoType, + ExtBlob, + ExtFile, }; diff --git a/src/util/util.ts b/src/util/util.ts index 91386e2c..477f9248 100644 --- a/src/util/util.ts +++ b/src/util/util.ts @@ -5,7 +5,9 @@ import * as mobx from "mobx"; import { sprintf } from "sprintf-js"; import dayjs from "dayjs"; import localizedFormat from "dayjs/plugin/localizedFormat"; -import type { RemoteType } from "../types/types"; +import type { RemoteType, CommandRtnType } from "../types/types"; + +type OV = mobx.IObservableValue; dayjs.extend(localizedFormat); @@ -401,29 +403,6 @@ function generateBackgroundWithGradient(colorName = "white", decay = 3) { return `linear-gradient(180deg, rgba(${r}, ${g}, ${b}, ${opacities[0]}) ${percentages[0]}%, rgba(${r}, ${g}, ${b}, ${opacities[1]}) ${percentages[1]}%, rgba(${r}, ${g}, ${b}, 0) ${percentages[2]}%)`; } -function makeFullRemoteRef(ownerName: string, remoteRef: string, name: string): string { - if (isBlank(ownerName) && isBlank(name)) { - return remoteRef; - } - if (!isBlank(ownerName) && isBlank(name)) { - return ownerName + ":" + remoteRef; - } - if (isBlank(ownerName) && !isBlank(name)) { - return remoteRef + ":" + name; - } - return ownerName + ":" + remoteRef + ":" + name; -} - -function getRemoteStr(rptr: RemotePtrType): string { - if (rptr == null || isBlank(rptr.remoteid)) { - return "(invalid remote)"; - } - let username = isBlank(rptr.ownerid) ? null : GlobalModel.resolveUserIdToName(rptr.ownerid); - let remoteRef = GlobalModel.resolveRemoteIdToRef(rptr.remoteid); - let fullRef = makeFullRemoteRef(username, remoteRef, rptr.name); - return fullRef; -} - function commandRtnHandler(prtn: Promise, errorMessage: OV) { prtn.then((crtn) => { if (crtn.success) { @@ -458,6 +437,5 @@ export { openLink, generateBackgroundWithGradient, getColorRGB, - getRemoteStr, commandRtnHandler, }; diff --git a/yarn.lock b/yarn.lock index 5c60c64c..77791bf5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1966,6 +1966,11 @@ resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.0.tgz#53ef263e5239728b56096b0a869595135b7952d2" integrity sha512-kr90f+ERiQtKWMz5rP32ltJ/BtULDI5RVO0uavn1HQUOwjx0R1h0rnDYNL0CepF1zL5bSY6FISAfd9tOdDhU5Q== +"@types/webpack-env@^1.18.3": + version "1.18.3" + resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.18.3.tgz#e81f769199a5609c751f34fcc6f6095ceac7831f" + integrity sha512-v4CH6FLBCftYGFAswDhzFLjKgucXsOkIf5Mzl8ZZhEtC6oye9whFInNPKszNB9AvX7JEZMtpXxWctih6addP+Q== + "@types/ws@^8.5.5": version "8.5.6" resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.6.tgz#e9ad51f0ab79b9110c50916c9fcbddc36d373065"