mirror of
https://github.com/wavetermdev/backup.git
synced 2026-08-05 13:57:07 -07:00
Pe 179 refactoring UI code (#25)
* refactored main JS files * modals have been refactored * lines and renderer refactored * all refactoring done. ready for reskinning
This commit is contained in:
+1
-2
@@ -12,7 +12,6 @@ node_modules/.bin/webpack --watch --config webpack.dev.js
|
||||
node_modules/.bin/webpack --config webpack.dev.js
|
||||
```
|
||||
|
||||
|
||||
```bash
|
||||
# @scripthaus command webpack-electron-watch
|
||||
# @scripthaus cd :playbook
|
||||
@@ -64,7 +63,7 @@ node_modules/.bin/webpack --config webpack.share.prod.js
|
||||
```bash
|
||||
# @scripthaus command typecheck
|
||||
# @scripthaus cd :playbook
|
||||
node_modules/.bin/tsc --jsx preserve --noEmit --esModuleInterop --target ES5 --experimentalDecorators --downlevelIteration src/prompt.ts
|
||||
node_modules/.bin/tsc --jsx preserve --noEmit --esModuleInterop --target ES5 --experimentalDecorators --downlevelIteration src/index.ts
|
||||
```
|
||||
|
||||
```bash
|
||||
|
||||
@@ -1,3 +1,44 @@
|
||||
@import "../index.less";
|
||||
|
||||
.info-message {
|
||||
position: relative;
|
||||
font-weight: normal;
|
||||
font-size: 12px;
|
||||
color: @term-white;
|
||||
|
||||
.message-content {
|
||||
position: absolute;
|
||||
display: none;
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
top: -6px;
|
||||
left: -6px;
|
||||
padding: 5px;
|
||||
border: 1px solid #777;
|
||||
background-color: #444;
|
||||
border-radius: 5px;
|
||||
z-index: 5;
|
||||
overflow: hidden;
|
||||
|
||||
.info-icon {
|
||||
margin-right: 5px;
|
||||
width: 12px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.info-children {
|
||||
flex: 1 0 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.message-content {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cmdstr-code {
|
||||
position: relative;
|
||||
display: flex;
|
||||
@@ -1,13 +1,14 @@
|
||||
import * as React from "react";
|
||||
import * as mobxReact from "mobx-react";
|
||||
import * as mobx from "mobx";
|
||||
import { sprintf } from "sprintf-js";
|
||||
import { boundMethod } from "autobind-decorator";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import cn from "classnames";
|
||||
import { If, For, When, Otherwise, Choose } from "tsx-control-statements/components";
|
||||
import type { RemoteType } from "./types";
|
||||
import { If } from "tsx-control-statements/components";
|
||||
import type { RemoteType } from "../types";
|
||||
|
||||
import "./common.less";
|
||||
|
||||
type OV<V> = mobx.IObservableValue<V>;
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
import { sprintf } from "sprintf-js";
|
||||
import { Database } from "better-sqlite3";
|
||||
|
||||
let DB = new Database();
|
||||
+641
File diff suppressed because it is too large
Load Diff
@@ -2,10 +2,7 @@ import * as mobx from "mobx";
|
||||
import * as React from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { sprintf } from "sprintf-js";
|
||||
import { Terminal } from "xterm";
|
||||
import { Main } from "./main";
|
||||
import { GlobalModel } from "./model";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { Main } from "./main/Main";
|
||||
import { loadFonts } from "./util";
|
||||
import * as DOMPurify from "dompurify";
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
@keyframes loader-ring {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fade-in {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
80% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fade-in-out {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
-2298
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,140 @@
|
||||
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 dayjs from "dayjs";
|
||||
import type { ContextMenuOpts } from "../types";
|
||||
import localizedFormat from "dayjs/plugin/localizedFormat";
|
||||
import { GlobalModel } from "../model";
|
||||
import { isBlank } from "../util";
|
||||
import { BookmarksView } from "./bookmarks/bookmarks";
|
||||
import { WebShareView } from "../webshare/webshare-client-view";
|
||||
import { HistoryView } from "./history/history";
|
||||
import { ScreenSettingsModal, SessionSettingsModal, LineSettingsModal, ClientSettingsModal } from "./modals/settings";
|
||||
import { RemotesModal } from "../remotes/remotes";
|
||||
import { TosModal } from "./modals/Modals";
|
||||
|
||||
import { SessionView } from "./sessionview/SessionView";
|
||||
import { MainSideBar } from "./sidebar/MainSideBar";
|
||||
import { DisconnectedModal, ClientStopModal, AlertModal, WelcomeModal } from "./modals/Modals";
|
||||
|
||||
dayjs.extend(localizedFormat);
|
||||
|
||||
type OV<V> = mobx.IObservableValue<V>;
|
||||
|
||||
@mobxReact.observer
|
||||
class Main extends React.Component<{}, {}> {
|
||||
dcWait: OV<boolean> = mobx.observable.box(false, { name: "dcWait" });
|
||||
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
handleContextMenu(e: any) {
|
||||
let isInNonTermInput = false;
|
||||
let activeElem = document.activeElement;
|
||||
if (activeElem != null && activeElem.nodeName == "TEXTAREA") {
|
||||
if (!activeElem.classList.contains("xterm-helper-textarea")) {
|
||||
isInNonTermInput = true;
|
||||
}
|
||||
}
|
||||
if (activeElem != null && activeElem.nodeName == "INPUT" && activeElem.getAttribute("type") == "text") {
|
||||
isInNonTermInput = true;
|
||||
}
|
||||
let opts: ContextMenuOpts = {};
|
||||
if (isInNonTermInput) {
|
||||
opts.showCut = true;
|
||||
}
|
||||
let sel = window.getSelection();
|
||||
if (!isBlank(sel.toString())) {
|
||||
GlobalModel.contextEditMenu(e, opts);
|
||||
} else {
|
||||
if (isInNonTermInput) {
|
||||
GlobalModel.contextEditMenu(e, opts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
updateDcWait(val: boolean): void {
|
||||
mobx.action(() => {
|
||||
this.dcWait.set(val);
|
||||
})();
|
||||
}
|
||||
|
||||
render() {
|
||||
let screenSettingsModal = GlobalModel.screenSettingsModal.get();
|
||||
let sessionSettingsModal = GlobalModel.sessionSettingsModal.get();
|
||||
let lineSettingsModal = GlobalModel.lineSettingsModal.get();
|
||||
let clientSettingsModal = GlobalModel.clientSettingsModal.get();
|
||||
let remotesModal = GlobalModel.remotesModalModel.isOpen();
|
||||
let disconnected = !GlobalModel.ws.open.get() || !GlobalModel.localServerRunning.get();
|
||||
let hasClientStop = GlobalModel.getHasClientStop();
|
||||
let dcWait = this.dcWait.get();
|
||||
if (disconnected || hasClientStop) {
|
||||
if (!dcWait) {
|
||||
setTimeout(() => this.updateDcWait(true), 1500);
|
||||
}
|
||||
return (
|
||||
<div id="main" onContextMenu={this.handleContextMenu}>
|
||||
<div className="main-content">
|
||||
<MainSideBar />
|
||||
<div className="session-view" />
|
||||
</div>
|
||||
<If condition={dcWait}>
|
||||
<If condition={disconnected}>
|
||||
<DisconnectedModal />
|
||||
</If>
|
||||
<If condition={!disconnected && hasClientStop}>
|
||||
<ClientStopModal />
|
||||
</If>
|
||||
</If>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (dcWait) {
|
||||
setTimeout(() => this.updateDcWait(false), 0);
|
||||
}
|
||||
return (
|
||||
<div id="main" onContextMenu={this.handleContextMenu}>
|
||||
<div className="main-content">
|
||||
<MainSideBar />
|
||||
<SessionView />
|
||||
<HistoryView />
|
||||
<BookmarksView />
|
||||
<WebShareView />
|
||||
</div>
|
||||
<AlertModal />
|
||||
<If condition={GlobalModel.needsTos()}>
|
||||
<TosModal />
|
||||
</If>
|
||||
<If condition={GlobalModel.welcomeModalOpen.get()}>
|
||||
<WelcomeModal />
|
||||
</If>
|
||||
<If condition={screenSettingsModal != null}>
|
||||
<ScreenSettingsModal
|
||||
key={screenSettingsModal.sessionId + ":" + screenSettingsModal.screenId}
|
||||
sessionId={screenSettingsModal.sessionId}
|
||||
screenId={screenSettingsModal.screenId}
|
||||
/>
|
||||
</If>
|
||||
<If condition={sessionSettingsModal != null}>
|
||||
<SessionSettingsModal key={sessionSettingsModal} sessionId={sessionSettingsModal} />
|
||||
</If>
|
||||
<If condition={lineSettingsModal != null}>
|
||||
<LineSettingsModal key={String(lineSettingsModal)} linenum={lineSettingsModal} />
|
||||
</If>
|
||||
<If condition={clientSettingsModal}>
|
||||
<ClientSettingsModal />
|
||||
</If>
|
||||
<If condition={remotesModal}>
|
||||
<RemotesModal model={GlobalModel.remotesModalModel} />
|
||||
</If>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export { Main };
|
||||
@@ -0,0 +1,99 @@
|
||||
@import "../../index.less";
|
||||
|
||||
.bookmarks-view {
|
||||
.bookmarks-list {
|
||||
color: white;
|
||||
margin: 4px 10px 5px 5px;
|
||||
|
||||
.no-bookmarks {
|
||||
color: @term-white;
|
||||
padding: 30px 10px 35px 10px;
|
||||
border-bottom: 1px solid white;
|
||||
}
|
||||
}
|
||||
|
||||
.bookmark {
|
||||
border-bottom: 1px solid #777;
|
||||
padding: 4px 5px 8px 15px;
|
||||
margin-bottom: 4px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
max-width: 100%;
|
||||
|
||||
.focus-indicator {
|
||||
top: 0;
|
||||
height: calc(100% - 4px);
|
||||
}
|
||||
|
||||
&.is-editing {
|
||||
padding-top: 8px;
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
|
||||
&.pending-delete {
|
||||
background-color: #522;
|
||||
}
|
||||
|
||||
.bookmark-content,
|
||||
.bookmark-edit {
|
||||
flex-grow: 1;
|
||||
max-width: calc(100% - 50px);
|
||||
}
|
||||
|
||||
label {
|
||||
color: white;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 80%;
|
||||
min-width: 50%;
|
||||
color: white;
|
||||
background-color: black;
|
||||
|
||||
&.mono-font {
|
||||
.mono-font(12px);
|
||||
}
|
||||
}
|
||||
|
||||
.bookmark-id-div {
|
||||
display: none;
|
||||
position: absolute;
|
||||
color: #666;
|
||||
right: 5px;
|
||||
bottom: 2px;
|
||||
.mono-font(8px);
|
||||
}
|
||||
|
||||
&:hover .bookmark-id-div {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.bookmark-controls {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
font-size: 16px;
|
||||
visibility: hidden;
|
||||
color: @term-white;
|
||||
|
||||
.bookmark-control:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.bookmark-control {
|
||||
margin-left: 10px;
|
||||
cursor: pointer;
|
||||
padding: 2px;
|
||||
|
||||
&:hover {
|
||||
color: @term-bright-white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover .bookmark-controls {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,14 @@
|
||||
import * as React from "react";
|
||||
import * as mobxReact from "mobx-react";
|
||||
import * as mobx from "mobx";
|
||||
import { sprintf } from "sprintf-js";
|
||||
import { boundMethod } from "autobind-decorator";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import dayjs from "dayjs";
|
||||
import { If, For, When, Otherwise, Choose } from "tsx-control-statements/components";
|
||||
import { If, For } from "tsx-control-statements/components";
|
||||
import cn from "classnames";
|
||||
import type { BookmarkType } from "./types";
|
||||
import { GlobalModel, GlobalCommandRunner } from "./model";
|
||||
import { CmdStrCode, Markdown } from "./elements";
|
||||
import type { BookmarkType } from "../../types";
|
||||
import { GlobalModel } from "../../model";
|
||||
import { CmdStrCode, Markdown } from "../../common/common";
|
||||
|
||||
import "./bookmarks.less";
|
||||
|
||||
@mobxReact.observer
|
||||
class Bookmark extends React.Component<{ bookmark: BookmarkType }, {}> {
|
||||
@@ -1,57 +1,4 @@
|
||||
.alt-view {
|
||||
background-color: #111;
|
||||
overflow-y: auto;
|
||||
flex-grow: 1;
|
||||
|
||||
.alt-title {
|
||||
margin: 20px 10px 0px 5px;
|
||||
padding-left: 10px;
|
||||
padding-bottom: 12px;
|
||||
.mono-font(1.5rem);
|
||||
color: @term-bright-white;
|
||||
border-bottom: 1px solid white;
|
||||
}
|
||||
|
||||
.alt-list {
|
||||
color: white;
|
||||
margin: 4px 10px 5px 5px;
|
||||
border-bottom: 1px solid white;
|
||||
}
|
||||
|
||||
.no-content {
|
||||
color: @term-white;
|
||||
padding: 30px 10px 35px 10px;
|
||||
border-bottom: 1px solid white;
|
||||
}
|
||||
|
||||
.close-button {
|
||||
position: absolute;
|
||||
padding: 4px;
|
||||
font-size: 24px;
|
||||
color: #aaa;
|
||||
right: 15px;
|
||||
top: 18px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.alt-help {
|
||||
color: @term-white;
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
margin-bottom: 10px;
|
||||
|
||||
.help-entry {
|
||||
margin-left: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@import "../../index.less";
|
||||
|
||||
.history-view {
|
||||
color: #ccc;
|
||||
@@ -418,140 +365,3 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.webshare-view {
|
||||
.webshare-item {
|
||||
padding: 4px 5px 8px 15px;
|
||||
margin-bottom: 4px;
|
||||
border-top: 1px solid white;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
position: relative;
|
||||
min-height: 55px;
|
||||
align-items: center;
|
||||
|
||||
&:first-child {
|
||||
border-top: 0;
|
||||
}
|
||||
|
||||
.webshare-vic {
|
||||
width: 200px;
|
||||
|
||||
.webshare-vic-link {
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: #222;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bookmarks-view {
|
||||
.bookmarks-list {
|
||||
color: white;
|
||||
margin: 4px 10px 5px 5px;
|
||||
|
||||
.no-bookmarks {
|
||||
color: @term-white;
|
||||
padding: 30px 10px 35px 10px;
|
||||
border-bottom: 1px solid white;
|
||||
}
|
||||
}
|
||||
|
||||
.bookmark {
|
||||
border-bottom: 1px solid #777;
|
||||
padding: 4px 5px 8px 15px;
|
||||
margin-bottom: 4px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
max-width: 100%;
|
||||
|
||||
.focus-indicator {
|
||||
top: 0;
|
||||
height: calc(100% - 4px);
|
||||
}
|
||||
|
||||
&.is-editing {
|
||||
padding-top: 8px;
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
|
||||
&.pending-delete {
|
||||
background-color: #522;
|
||||
}
|
||||
|
||||
.bookmark-content,
|
||||
.bookmark-edit {
|
||||
flex-grow: 1;
|
||||
max-width: calc(100% - 50px);
|
||||
}
|
||||
|
||||
label {
|
||||
color: white;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 80%;
|
||||
min-width: 50%;
|
||||
color: white;
|
||||
background-color: black;
|
||||
|
||||
&.mono-font {
|
||||
.mono-font(12px);
|
||||
}
|
||||
}
|
||||
|
||||
.bookmark-id-div {
|
||||
display: none;
|
||||
position: absolute;
|
||||
color: #666;
|
||||
right: 5px;
|
||||
bottom: 2px;
|
||||
.mono-font(8px);
|
||||
}
|
||||
|
||||
&:hover .bookmark-id-div {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.bookmark-controls {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
font-size: 16px;
|
||||
visibility: hidden;
|
||||
color: @term-white;
|
||||
|
||||
.bookmark-control:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.bookmark-control {
|
||||
margin-left: 10px;
|
||||
cursor: pointer;
|
||||
padding: 2px;
|
||||
|
||||
&:hover {
|
||||
color: @term-bright-white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover .bookmark-controls {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,13 +5,15 @@ import { If, For, When, Otherwise, Choose } from "tsx-control-statements/compone
|
||||
import { sprintf } from "sprintf-js";
|
||||
import { boundMethod } from "autobind-decorator";
|
||||
import cn from "classnames";
|
||||
import { GlobalModel, GlobalCommandRunner, Cmd } from "./model";
|
||||
import { HistoryItem, RemotePtrType, LineType, CmdDataType } from "./types";
|
||||
import { GlobalModel, GlobalCommandRunner, Cmd } from "../../model";
|
||||
import { HistoryItem, RemotePtrType, LineType, CmdDataType } from "../../types";
|
||||
import dayjs from "dayjs";
|
||||
import localizedFormat from "dayjs/plugin/localizedFormat";
|
||||
import customParseFormat from "dayjs/plugin/customParseFormat";
|
||||
import { Line } from "./linecomps";
|
||||
import { CmdStrCode } from "./elements";
|
||||
import { Line } from "../line/linecomps";
|
||||
import { CmdStrCode } from "../../common/common";
|
||||
|
||||
import "./history.less";
|
||||
|
||||
dayjs.extend(customParseFormat);
|
||||
dayjs.extend(localizedFormat);
|
||||
@@ -5,9 +5,9 @@ import { sprintf } from "sprintf-js";
|
||||
import { boundMethod } from "autobind-decorator";
|
||||
import dayjs from "dayjs";
|
||||
import localizedFormat from "dayjs/plugin/localizedFormat";
|
||||
import { If, For, When, Otherwise, Choose } from "tsx-control-statements/components";
|
||||
import { GlobalModel, GlobalCommandRunner, Session, Cmd, ScreenLines, Screen, getTermPtyData } from "./model";
|
||||
import { windowWidthToCols, windowHeightToRows, termHeightFromRows, termWidthFromCols } from "./textmeasure";
|
||||
import { If } from "tsx-control-statements/components";
|
||||
import { GlobalModel, GlobalCommandRunner, Cmd, getTermPtyData } from "../../model";
|
||||
import { termHeightFromRows } from "../../textmeasure";
|
||||
import type {
|
||||
LineType,
|
||||
CmdDataType,
|
||||
@@ -21,18 +21,18 @@ import type {
|
||||
LineHeightChangeCallbackType,
|
||||
RendererModelInitializeParams,
|
||||
RendererModel,
|
||||
} from "./types";
|
||||
} from "../../types";
|
||||
import cn from "classnames";
|
||||
import { TermWrap } from "./term";
|
||||
import type { LineContainerModel } from "./model";
|
||||
import { renderCmdText } from "./elements";
|
||||
import { SimpleBlobRendererModel, SimpleBlobRenderer } from "./simplerenderer";
|
||||
import { FullRenderer } from "./fullrenderer";
|
||||
import { isBlank } from "./util";
|
||||
import { PluginModel } from "./plugins";
|
||||
import { PtyDataBuffer } from "./ptydata";
|
||||
import type { LineContainerModel } from "../../model";
|
||||
import { renderCmdText } from "../../common/common";
|
||||
import { SimpleBlobRenderer } from "./renderer/simplerenderer";
|
||||
import { FullRenderer } from "./renderer/fullrenderer";
|
||||
import { isBlank } from "../../util";
|
||||
import { PluginModel } from "../../plugins/plugins";
|
||||
import * as lineutil from "./lineutil";
|
||||
|
||||
import "./lines.less";
|
||||
|
||||
dayjs.extend(localizedFormat);
|
||||
|
||||
type OV<V> = mobx.IObservableValue<V>;
|
||||
@@ -1,3 +1,5 @@
|
||||
@import "../../index.less";
|
||||
|
||||
.line.line-text {
|
||||
flex-direction: row;
|
||||
padding-top: 5px;
|
||||
@@ -465,10 +467,6 @@
|
||||
border-radius: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover .cmd-hints {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.line.line-invalid {
|
||||
@@ -8,10 +8,12 @@ import cn from "classnames";
|
||||
import dayjs from "dayjs";
|
||||
import localizedFormat from "dayjs/plugin/localizedFormat";
|
||||
import { debounce, throttle } from "throttle-debounce";
|
||||
import * as T from "./types";
|
||||
import * as util from "./util";
|
||||
import * as T from "../../types";
|
||||
import * as util from "../../util";
|
||||
import * as lineutil from "./lineutil";
|
||||
|
||||
import "./lines.less";
|
||||
|
||||
dayjs.extend(localizedFormat);
|
||||
type OV<V> = mobx.IObservableValue<V>;
|
||||
type OArr<V> = mobx.IObservableArray<V>;
|
||||
@@ -1,7 +1,7 @@
|
||||
import dayjs from "dayjs";
|
||||
import localizedFormat from "dayjs/plugin/localizedFormat";
|
||||
import { isBlank, getDateStr } from "./util";
|
||||
import { LineType, WebLine, RendererContext } from "./types";
|
||||
import { isBlank, getDateStr } from "../../util";
|
||||
import { LineType, WebLine, RendererContext } from "../../types";
|
||||
|
||||
dayjs.extend(localizedFormat);
|
||||
|
||||
@@ -1,25 +1,12 @@
|
||||
import * as React from "react";
|
||||
import * as mobxReact from "mobx-react";
|
||||
import * as mobx from "mobx";
|
||||
import { sprintf } from "sprintf-js";
|
||||
import { boundMethod } from "autobind-decorator";
|
||||
import { If, For, When, Otherwise, Choose } from "tsx-control-statements/components";
|
||||
import type {
|
||||
RendererModelInitializeParams,
|
||||
TermOptsType,
|
||||
RendererContext,
|
||||
RendererOpts,
|
||||
SimpleBlobRendererComponent,
|
||||
RendererModelContainerApi,
|
||||
RendererPluginType,
|
||||
PtyDataType,
|
||||
RendererModel,
|
||||
RendererOptsUpdate,
|
||||
LineType,
|
||||
TermContextUnion,
|
||||
RendererContainerType,
|
||||
} from "./types";
|
||||
import { PacketDataBuffer } from "./ptydata";
|
||||
} from "../../../types";
|
||||
import { debounce, throttle } from "throttle-debounce";
|
||||
|
||||
type OV<V> = mobx.IObservableValue<V>;
|
||||
@@ -19,12 +19,12 @@ import type {
|
||||
LineType,
|
||||
TermContextUnion,
|
||||
RendererContainerType,
|
||||
} from "./types";
|
||||
import * as T from "./types";
|
||||
import { PacketDataBuffer } from "./ptydata";
|
||||
} from "../../../types";
|
||||
import * as T from "../../../types";
|
||||
import { PacketDataBuffer } from "../../../ptydata";
|
||||
import { debounce, throttle } from "throttle-debounce";
|
||||
import * as util from "./util";
|
||||
import { GlobalModel } from "./model";
|
||||
import * as util from "../../../util";
|
||||
import { GlobalModel } from "../../../model";
|
||||
|
||||
type OV<V> = mobx.IObservableValue<V>;
|
||||
type CV<V> = mobx.IComputedValue<V>;
|
||||
@@ -0,0 +1,357 @@
|
||||
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 dayjs from "dayjs";
|
||||
import localizedFormat from "dayjs/plugin/localizedFormat";
|
||||
import { GlobalModel } from "../../model";
|
||||
import { Markdown } from "../../common/common";
|
||||
|
||||
dayjs.extend(localizedFormat);
|
||||
|
||||
type OV<V> = mobx.IObservableValue<V>;
|
||||
|
||||
@mobxReact.observer
|
||||
class DisconnectedModal extends React.Component<{}, {}> {
|
||||
logRef: any = React.createRef();
|
||||
showLog: mobx.IObservableValue<boolean> = mobx.observable.box(false);
|
||||
|
||||
@boundMethod
|
||||
restartServer() {
|
||||
GlobalModel.restartLocalServer();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
tryReconnect() {
|
||||
GlobalModel.ws.connectNow("manual");
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this.logRef.current != null) {
|
||||
this.logRef.current.scrollTop = this.logRef.current.scrollHeight;
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
if (this.logRef.current != null) {
|
||||
this.logRef.current.scrollTop = this.logRef.current.scrollHeight;
|
||||
}
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
handleShowLog(): void {
|
||||
mobx.action(() => {
|
||||
this.showLog.set(!this.showLog.get());
|
||||
})();
|
||||
}
|
||||
|
||||
render() {
|
||||
let model = GlobalModel;
|
||||
let logLine: string = null;
|
||||
let idx: number = 0;
|
||||
return (
|
||||
<div className="prompt-modal disconnected-modal modal is-active">
|
||||
<div className="modal-background"></div>
|
||||
<div className="modal-content">
|
||||
<div className="message-header">
|
||||
<div className="modal-title">Prompt Client Disconnected</div>
|
||||
</div>
|
||||
<If condition={this.showLog.get()}>
|
||||
<div className="inner-content">
|
||||
<div className="ws-log" ref={this.logRef}>
|
||||
<For each="logLine" index="idx" of={GlobalModel.ws.wsLog}>
|
||||
<div key={idx} className="ws-logline">
|
||||
{logLine}
|
||||
</div>
|
||||
</For>
|
||||
</div>
|
||||
</div>
|
||||
</If>
|
||||
<footer>
|
||||
<div className="footer-text-link" style={{ marginLeft: 10 }} onClick={this.handleShowLog}>
|
||||
<If condition={!this.showLog.get()}>
|
||||
<i className="fa-sharp fa-solid fa-plus" /> Show Log
|
||||
</If>
|
||||
<If condition={this.showLog.get()}>
|
||||
<i className="fa-sharp fa-solid fa-minus" /> Hide Log
|
||||
</If>
|
||||
</div>
|
||||
<div className="flex-spacer" />
|
||||
<button onClick={this.tryReconnect} className="button">
|
||||
<span className="icon">
|
||||
<i className="fa-sharp fa-solid fa-rotate" />
|
||||
</span>
|
||||
<span>Try Reconnect</span>
|
||||
</button>
|
||||
<button onClick={this.restartServer} className="button is-danger" style={{ marginLeft: 10 }}>
|
||||
<span className="icon">
|
||||
<i className="fa-sharp fa-solid fa-triangle-exclamation" />
|
||||
</span>
|
||||
<span>Restart Server</span>
|
||||
</button>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@mobxReact.observer
|
||||
class ClientStopModal extends React.Component<{}, {}> {
|
||||
@boundMethod
|
||||
refreshClient() {
|
||||
GlobalModel.refreshClient();
|
||||
}
|
||||
|
||||
render() {
|
||||
let model = GlobalModel;
|
||||
let cdata = model.clientData.get();
|
||||
let title = "Client Not Ready";
|
||||
return (
|
||||
<div className="prompt-modal client-stop-modal modal is-active">
|
||||
<div className="modal-background"></div>
|
||||
<div className="modal-content">
|
||||
<div className="message-header">
|
||||
<div className="modal-title">[prompt] {title}</div>
|
||||
</div>
|
||||
<div className="inner-content">
|
||||
<If condition={cdata == null}>
|
||||
<div>Cannot get client data.</div>
|
||||
</If>
|
||||
</div>
|
||||
<footer>
|
||||
<button onClick={this.refreshClient} className="button">
|
||||
<span className="icon">
|
||||
<i className="fa-sharp fa-solid fa-rotate" />
|
||||
</span>
|
||||
<span>Hard Refresh Client</span>
|
||||
</button>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@mobxReact.observer
|
||||
class LoadingSpinner extends React.Component<{}, {}> {
|
||||
render() {
|
||||
return (
|
||||
<div className="loading-spinner">
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@mobxReact.observer
|
||||
class AlertModal extends React.Component<{}, {}> {
|
||||
@boundMethod
|
||||
closeModal(): void {
|
||||
GlobalModel.cancelAlert();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
handleOK(): void {
|
||||
GlobalModel.confirmAlert();
|
||||
}
|
||||
|
||||
render() {
|
||||
let message = GlobalModel.alertMessage.get();
|
||||
if (message == null) {
|
||||
return null;
|
||||
}
|
||||
let title = message.title ?? (message.confirm ? "Confirm" : "Alert");
|
||||
let isConfirm = message.confirm;
|
||||
return (
|
||||
<div className="modal prompt-modal is-active alert-modal">
|
||||
<div className="modal-background" />
|
||||
<div className="modal-content">
|
||||
<header>
|
||||
<p className="modal-title">
|
||||
<i className="fa-sharp fa-solid fa-triangle-exclamation" /> {title}
|
||||
</p>
|
||||
<div className="close-icon">
|
||||
<i onClick={this.closeModal} className="fa-sharp fa-solid fa-times" />
|
||||
</div>
|
||||
</header>
|
||||
<If condition={message.markdown}>
|
||||
<Markdown text={message.message} extraClassName="inner-content" />
|
||||
</If>
|
||||
<If condition={!message.markdown}>
|
||||
<div className="inner-content content">
|
||||
<p>{message.message}</p>
|
||||
</div>
|
||||
</If>
|
||||
<footer>
|
||||
<If condition={isConfirm}>
|
||||
<div onClick={this.closeModal} className="button is-prompt-cancel is-outlined is-small">
|
||||
Cancel
|
||||
</div>
|
||||
<div onClick={this.handleOK} className="button is-prompt-green is-outlined is-small">
|
||||
OK
|
||||
</div>
|
||||
</If>
|
||||
<If condition={!isConfirm}>
|
||||
<div onClick={this.handleOK} className="button is-prompt-green is-small">
|
||||
OK
|
||||
</div>
|
||||
</If>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@mobxReact.observer
|
||||
class WelcomeModal extends React.Component<{}, {}> {
|
||||
totalPages: number = 3;
|
||||
pageNum: OV<number> = mobx.observable.box(1, { name: "welcome-pagenum" });
|
||||
|
||||
@boundMethod
|
||||
closeModal(): void {
|
||||
mobx.action(() => {
|
||||
GlobalModel.welcomeModalOpen.set(false);
|
||||
})();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
goNext(): void {
|
||||
mobx.action(() => {
|
||||
this.pageNum.set(this.pageNum.get() + 1);
|
||||
})();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
goPrev(): void {
|
||||
mobx.action(() => {
|
||||
this.pageNum.set(this.pageNum.get() - 1);
|
||||
})();
|
||||
}
|
||||
|
||||
renderDot(num: number): any {
|
||||
if (num == this.pageNum.get()) {
|
||||
return <i key={String(num)} className="fa-sharp fa-solid fa-circle" />;
|
||||
}
|
||||
return <i key={String(num)} className="fa-sharp fa-regular fa-circle" />;
|
||||
}
|
||||
|
||||
renderDots(): any {
|
||||
let elems: any = [];
|
||||
for (let i = 1; i <= this.totalPages; i++) {
|
||||
let elem = this.renderDot(i);
|
||||
elems.push(elem);
|
||||
}
|
||||
return elems;
|
||||
}
|
||||
|
||||
render() {
|
||||
let pageNum = this.pageNum.get();
|
||||
return (
|
||||
<div className={cn("modal welcome-modal prompt-modal is-active")}>
|
||||
<div className="modal-background" />
|
||||
<div className="modal-content">
|
||||
<header>
|
||||
<div className="modal-title">welcome to [prompt]</div>
|
||||
<div className="close-icon">
|
||||
<i onClick={this.closeModal} className="fa-sharp fa-solid fa-times" />
|
||||
</div>
|
||||
</header>
|
||||
<div className={cn("inner-content content", { "is-hidden": pageNum != 1 })}>
|
||||
<p>
|
||||
Prompt is a new terminal to help save you time and keep your command-line life organized.
|
||||
Here's a couple quick tips to get your started!
|
||||
</p>
|
||||
</div>
|
||||
<footer>
|
||||
<If condition={pageNum > 1}>
|
||||
<button className={cn("button is-dark prev-button is-small")} onClick={this.goPrev}>
|
||||
<span className="icon is-small">
|
||||
<i className="fa-sharp fa-regular fa-angle-left" />
|
||||
</span>
|
||||
<span>Prev</span>
|
||||
</button>
|
||||
</If>
|
||||
<If condition={pageNum == 1}>
|
||||
<div className="prev-spacer" />
|
||||
</If>
|
||||
<div className="flex-spacer" />
|
||||
<div className="dots">{this.renderDots()}</div>
|
||||
<div className="flex-spacer" />
|
||||
<If condition={pageNum < this.totalPages}>
|
||||
<button className="button is-dark next-button is-small" onClick={this.goNext}>
|
||||
<span>Next</span>
|
||||
<span className="icon is-small">
|
||||
<i className="fa-sharp fa-regular fa-angle-right" />
|
||||
</span>
|
||||
</button>
|
||||
</If>
|
||||
<If condition={pageNum == this.totalPages}>
|
||||
<button className="button is-dark next-button is-small" onClick={this.closeModal}>
|
||||
<span>Done</span>
|
||||
</button>
|
||||
</If>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@mobxReact.observer
|
||||
class TosModal extends React.Component<{}, {}> {
|
||||
@boundMethod
|
||||
acceptTos(): void {
|
||||
GlobalCommandRunner.clientAcceptTos();
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className={cn("modal tos-modal prompt-modal is-active")}>
|
||||
<div className="modal-background" />
|
||||
<div className="modal-content">
|
||||
<header>
|
||||
<div className="modal-title">Welcome to [prompt]</div>
|
||||
</header>
|
||||
<div className="inner-content">
|
||||
<div className="content">
|
||||
<p>Thank you for downloading Prompt!</p>
|
||||
<p>
|
||||
Prompt is a new terminal designed to help you save time and organize your command life.
|
||||
Prompt is currently in beta. If you'd like to give feedback, run into problems, have
|
||||
questions, or need help, please join the Prompt{" "}
|
||||
<a target="_blank" href={util.makeExternLink("https://discord.gg/XfvZ334gwU")}>
|
||||
discord server
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
<p>
|
||||
Prompt is free to use, no email or registration required (unless you're using the cloud
|
||||
features).
|
||||
</p>
|
||||
<p>
|
||||
<a target="_blank" href={util.makeExternLink("https://www.commandline.dev/tos.html")}>
|
||||
Full Terms of Service
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<footer>
|
||||
<div className="flex-spacer" />
|
||||
<div onClick={this.acceptTos} className="button is-prompt-green is-outlined is-small">
|
||||
Accept Terms of Service
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export { WelcomeModal, LoadingSpinner, ClientStopModal, AlertModal, DisconnectedModal, TosModal };
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user