mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-01-03 18:47:56 +01:00
finish up basic line settings
This commit is contained in:
parent
b1535b9b9d
commit
920a327f70
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "Prompt",
|
"name": "Prompt",
|
||||||
"version": "0.1.6",
|
"version": "0.1.7",
|
||||||
"main": "dist/emain.js",
|
"main": "dist/emain.js",
|
||||||
"license": "Proprietary",
|
"license": "Proprietary",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -2798,7 +2798,6 @@ class Main extends React.Component<{}, {}> {
|
|||||||
|
|
||||||
@boundMethod
|
@boundMethod
|
||||||
handleContextMenu(e : any) {
|
handleContextMenu(e : any) {
|
||||||
console.log("main contextmenu");
|
|
||||||
let isInNonTermInput = false;
|
let isInNonTermInput = false;
|
||||||
let activeElem = document.activeElement;
|
let activeElem = document.activeElement;
|
||||||
if (activeElem != null && activeElem.nodeName == "TEXTAREA") {
|
if (activeElem != null && activeElem.nodeName == "TEXTAREA") {
|
||||||
|
@ -26,13 +26,25 @@ function CodeRenderer(props : any) : any {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MaxMarkdownSize = 50000;
|
||||||
|
|
||||||
@mobxReact.observer
|
@mobxReact.observer
|
||||||
class SimpleMarkdownRenderer extends React.Component<{data : Blob, context : RendererContext, opts : RendererOpts, savedHeight : number}, {}> {
|
class SimpleMarkdownRenderer extends React.Component<{data : Blob, context : RendererContext, opts : RendererOpts, savedHeight : number}, {}> {
|
||||||
markdownText : OV<string> = mobx.observable.box(null, {name: "markdownText"});
|
markdownText : OV<string> = mobx.observable.box(null, {name: "markdownText"});
|
||||||
|
markdownError : OV<string> = mobx.observable.box(null, {name: "markdownError"});
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
let prtn = this.props.data.text()
|
let dataBlob = this.props.data;
|
||||||
|
if (dataBlob.size > 50000) {
|
||||||
|
this.markdownError.set(sprintf("error: markdown too large to render size=%d", dataBlob.size));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let prtn = dataBlob.text()
|
||||||
prtn.then((text) => {
|
prtn.then((text) => {
|
||||||
|
if (/[\x00-\x08]/.test(text)) {
|
||||||
|
this.markdownError.set(sprintf("error: not rendering markdown, binary characters detected"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
mobx.action(() => {
|
mobx.action(() => {
|
||||||
this.markdownText.set(text);
|
this.markdownText.set(text);
|
||||||
})();
|
})();
|
||||||
@ -40,6 +52,9 @@ class SimpleMarkdownRenderer extends React.Component<{data : Blob, context : Ren
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
if (this.markdownError.get() != null) {
|
||||||
|
return <div className="markdown-renderer"><div className="markdown-error">{this.markdownError.get()}</div></div>;
|
||||||
|
}
|
||||||
if (this.markdownText.get() == null) {
|
if (this.markdownText.get() == null) {
|
||||||
return <div className="markdown-renderer" style={{height: this.props.savedHeight}}/>
|
return <div className="markdown-renderer" style={{height: this.props.savedHeight}}/>
|
||||||
}
|
}
|
||||||
@ -53,10 +68,11 @@ class SimpleMarkdownRenderer extends React.Component<{data : Blob, context : Ren
|
|||||||
h6: (props) => HeaderRenderer(props, 6),
|
h6: (props) => HeaderRenderer(props, 6),
|
||||||
code: CodeRenderer,
|
code: CodeRenderer,
|
||||||
};
|
};
|
||||||
|
let opts = this.props.opts;
|
||||||
let markdownText = this.markdownText.get();
|
let markdownText = this.markdownText.get();
|
||||||
return (
|
return (
|
||||||
<div className="markdown-renderer">
|
<div className="markdown-renderer">
|
||||||
<div className="markdown content">
|
<div className="markdown content" style={{maxHeight: opts.maxSize.height, maxWidth: opts.maxSize.width, overflow: "auto"}}>
|
||||||
<ReactMarkdown children={this.markdownText.get()} remarkPlugins={[remarkGfm]} components={markdownComponents}/>
|
<ReactMarkdown children={this.markdownText.get()} remarkPlugins={[remarkGfm]} components={markdownComponents}/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
17
src/model.ts
17
src/model.ts
@ -2409,6 +2409,9 @@ class Model {
|
|||||||
if (isBlank(plugin.name)) {
|
if (isBlank(plugin.name)) {
|
||||||
throw new Error("invalid plugin, no name");
|
throw new Error("invalid plugin, no name");
|
||||||
}
|
}
|
||||||
|
if (plugin.name == "terminal" || plugin.name == "none") {
|
||||||
|
throw new Error(sprintf("invalid plugin, name '%s' is reserved", plugin.name));
|
||||||
|
}
|
||||||
let existingPlugin = this.getRendererPluginByName(plugin.name);
|
let existingPlugin = this.getRendererPluginByName(plugin.name);
|
||||||
if (existingPlugin != null) {
|
if (existingPlugin != null) {
|
||||||
throw new Error(sprintf("plugin with name %s already registered", plugin.name));
|
throw new Error(sprintf("plugin with name %s already registered", plugin.name));
|
||||||
@ -3213,6 +3216,20 @@ class CommandRunner {
|
|||||||
GlobalModel.submitCommand("line", "view", [sessionId, screenId, String(lineNum)], {"nohist": "1"}, false);
|
GlobalModel.submitCommand("line", "view", [sessionId, screenId, String(lineNum)], {"nohist": "1"}, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lineArchive(lineArg : string, archive : boolean) {
|
||||||
|
let kwargs = {"nohist": "1"};
|
||||||
|
let archiveStr = (archive ? "1" : "0");
|
||||||
|
GlobalModel.submitCommand("line", "archive", [lineArg, archiveStr], kwargs, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
lineSet(lineArg : string, opts : {renderer? : string}) {
|
||||||
|
let kwargs = {"nohist": "1"};
|
||||||
|
if ("renderer" in opts) {
|
||||||
|
kwargs["renderer"] = opts.renderer ?? "";
|
||||||
|
}
|
||||||
|
GlobalModel.submitCommand("line", "set", [lineArg], kwargs, false);
|
||||||
|
}
|
||||||
|
|
||||||
createNewSession() {
|
createNewSession() {
|
||||||
GlobalModel.submitCommand("session", "open", null, {"nohist": "1"}, false);
|
GlobalModel.submitCommand("session", "open", null, {"nohist": "1"}, false);
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import {If, For, When, Otherwise, Choose} from "tsx-control-statements/component
|
|||||||
import cn from "classnames";
|
import cn from "classnames";
|
||||||
import {GlobalModel, GlobalCommandRunner, TabColors} from "./model";
|
import {GlobalModel, GlobalCommandRunner, TabColors} from "./model";
|
||||||
import {Toggle} from "./elements";
|
import {Toggle} from "./elements";
|
||||||
import {LineType} from "./types";
|
import {LineType, RendererPluginType} from "./types";
|
||||||
|
|
||||||
type OV<V> = mobx.IObservableValue<V>;
|
type OV<V> = mobx.IObservableValue<V>;
|
||||||
type OArr<V> = mobx.IObservableArray<V>;
|
type OArr<V> = mobx.IObservableArray<V>;
|
||||||
@ -232,8 +232,18 @@ class SessionSettingsModal extends React.Component<{sessionId : string}, {}> {
|
|||||||
|
|
||||||
@mobxReact.observer
|
@mobxReact.observer
|
||||||
class LineSettingsModal extends React.Component<{line : LineType}, {}> {
|
class LineSettingsModal extends React.Component<{line : LineType}, {}> {
|
||||||
|
tempArchived : OV<boolean>;
|
||||||
|
tempRenderer : OV<string>;
|
||||||
|
rendererDropdownActive : OV<boolean> = mobx.observable.box(false, {name: "lineSettings-rendererDropdownActive"});
|
||||||
|
|
||||||
constructor(props : any) {
|
constructor(props : any) {
|
||||||
super(props);
|
super(props);
|
||||||
|
let {line} = props;
|
||||||
|
if (line == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.tempArchived = mobx.observable.box(!!line.archived, {name: "lineSettings-tempArchived"});
|
||||||
|
this.tempRenderer = mobx.observable.box(line.renderer, {name: "lineSettings-renderer"});
|
||||||
}
|
}
|
||||||
|
|
||||||
@boundMethod
|
@boundMethod
|
||||||
@ -245,9 +255,68 @@ class LineSettingsModal extends React.Component<{line : LineType}, {}> {
|
|||||||
|
|
||||||
@boundMethod
|
@boundMethod
|
||||||
handleOK() : void {
|
handleOK() : void {
|
||||||
|
let {line} = this.props;
|
||||||
mobx.action(() => {
|
mobx.action(() => {
|
||||||
GlobalModel.lineSettingsModal.set(null);
|
GlobalModel.lineSettingsModal.set(null);
|
||||||
})();
|
})();
|
||||||
|
if (this.tempRenderer.get() != line.renderer) {
|
||||||
|
GlobalCommandRunner.lineSet(line.lineid, {
|
||||||
|
"renderer": this.tempRenderer.get(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (this.tempArchived.get() != !!line.archived) {
|
||||||
|
GlobalCommandRunner.lineArchive(line.lineid, this.tempArchived.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@boundMethod
|
||||||
|
handleChangeArchived(val : boolean) : void {
|
||||||
|
mobx.action(() => {
|
||||||
|
this.tempArchived.set(val);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
|
@boundMethod
|
||||||
|
toggleRendererDropdown() : void {
|
||||||
|
mobx.action(() => {
|
||||||
|
this.rendererDropdownActive.set(!this.rendererDropdownActive.get());
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
|
@boundMethod
|
||||||
|
clickSetRenderer(renderer : string) : void {
|
||||||
|
mobx.action(() => {
|
||||||
|
this.tempRenderer.set(renderer);
|
||||||
|
this.rendererDropdownActive.set(false);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
|
renderRendererDropdown() : any {
|
||||||
|
let {line} = this.props;
|
||||||
|
let renderer = this.tempRenderer.get() ?? "terminal";
|
||||||
|
let plugins = GlobalModel.rendererPlugins;
|
||||||
|
let plugin : RendererPluginType = null;
|
||||||
|
return (
|
||||||
|
<div className={cn("dropdown", "renderer-dropdown", {"is-active": this.rendererDropdownActive.get()})}>
|
||||||
|
<div className="dropdown-trigger">
|
||||||
|
<button onClick={this.toggleRendererDropdown} className="button is-small is-dark">
|
||||||
|
<span><i className="fa-sharp fa-solid fa-fill"/> {renderer}</span>
|
||||||
|
<span className="icon is-small">
|
||||||
|
<i className="fa-sharp fa-regular fa-angle-down" aria-hidden="true"></i>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="dropdown-menu" role="menu">
|
||||||
|
<div className="dropdown-content has-background-black">
|
||||||
|
<div onClick={() => this.clickSetRenderer("none") } key="none" className="dropdown-item">none</div>
|
||||||
|
<div onClick={() => this.clickSetRenderer(null) } key="terminal" className="dropdown-item">terminal</div>
|
||||||
|
<For each="plugin" of={plugins}>
|
||||||
|
<div onClick={() => this.clickSetRenderer(plugin.name) } key={plugin.name} className="dropdown-item">{plugin.name}</div>
|
||||||
|
</For>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -271,9 +340,22 @@ class LineSettingsModal extends React.Component<{line : LineType}, {}> {
|
|||||||
Renderer
|
Renderer
|
||||||
</div>
|
</div>
|
||||||
<div className="settings-input">
|
<div className="settings-input">
|
||||||
xxx
|
{this.renderRendererDropdown()}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="settings-field">
|
||||||
|
<div className="settings-label">
|
||||||
|
Archived
|
||||||
|
</div>
|
||||||
|
<div className="settings-input">
|
||||||
|
<Toggle checked={this.tempArchived.get()} onChange={this.handleChangeArchived}/>
|
||||||
|
<div className="action-text">
|
||||||
|
<If condition={this.tempArchived.get() && this.tempArchived.get() != !!line.archived}>will be archived</If>
|
||||||
|
<If condition={!this.tempArchived.get() && this.tempArchived.get() != !!line.archived}>will be un-archived</If>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style={{height: 50}}/>
|
||||||
</div>
|
</div>
|
||||||
<footer>
|
<footer>
|
||||||
<div onClick={this.closeModal} className="button is-prompt-cancel is-outlined is-small">Cancel</div>
|
<div onClick={this.closeModal} className="button is-prompt-cancel is-outlined is-small">Cancel</div>
|
||||||
|
25
src/sh2.less
25
src/sh2.less
@ -2633,6 +2633,23 @@ input[type=checkbox] {
|
|||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dropdown {
|
||||||
|
.dropdown-menu .dropdown-content {
|
||||||
|
.dropdown-item {
|
||||||
|
color: white;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
background-color: #333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-menu {
|
||||||
|
max-height: 120px;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal.prompt-modal {
|
.modal.prompt-modal {
|
||||||
@ -3006,6 +3023,14 @@ input[type=checkbox] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.markdown-renderer {
|
||||||
|
.markdown-error {
|
||||||
|
color: @term-red;
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.markdown-renderer .markdown {
|
.markdown-renderer .markdown {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
const VERSION = "v0.1.6";
|
const VERSION = "v0.1.7";
|
||||||
module.exports = VERSION;
|
module.exports = VERSION;
|
||||||
|
Loading…
Reference in New Issue
Block a user