finish up basic line settings

This commit is contained in:
sawka 2023-03-17 14:46:25 -07:00
parent b1535b9b9d
commit 920a327f70
7 changed files with 147 additions and 8 deletions

View File

@ -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": {

View File

@ -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") {

View File

@ -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>

View File

@ -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);
} }

View File

@ -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>

View File

@ -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;

View File

@ -1,2 +1,2 @@
const VERSION = "v0.1.6"; const VERSION = "v0.1.7";
module.exports = VERSION; module.exports = VERSION;