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",
"version": "0.1.6",
"version": "0.1.7",
"main": "dist/emain.js",
"license": "Proprietary",
"dependencies": {

View File

@ -2798,7 +2798,6 @@ class Main extends React.Component<{}, {}> {
@boundMethod
handleContextMenu(e : any) {
console.log("main contextmenu");
let isInNonTermInput = false;
let activeElem = document.activeElement;
if (activeElem != null && activeElem.nodeName == "TEXTAREA") {

View File

@ -26,13 +26,25 @@ function CodeRenderer(props : any) : any {
);
}
const MaxMarkdownSize = 50000;
@mobxReact.observer
class SimpleMarkdownRenderer extends React.Component<{data : Blob, context : RendererContext, opts : RendererOpts, savedHeight : number}, {}> {
markdownText : OV<string> = mobx.observable.box(null, {name: "markdownText"});
markdownError : OV<string> = mobx.observable.box(null, {name: "markdownError"});
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) => {
if (/[\x00-\x08]/.test(text)) {
this.markdownError.set(sprintf("error: not rendering markdown, binary characters detected"));
return;
}
mobx.action(() => {
this.markdownText.set(text);
})();
@ -40,6 +52,9 @@ class SimpleMarkdownRenderer extends React.Component<{data : Blob, context : Ren
}
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) {
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),
code: CodeRenderer,
};
let opts = this.props.opts;
let markdownText = this.markdownText.get();
return (
<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}/>
</div>
</div>

View File

@ -2409,6 +2409,9 @@ class Model {
if (isBlank(plugin.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);
if (existingPlugin != null) {
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);
}
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() {
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 {GlobalModel, GlobalCommandRunner, TabColors} from "./model";
import {Toggle} from "./elements";
import {LineType} from "./types";
import {LineType, RendererPluginType} from "./types";
type OV<V> = mobx.IObservableValue<V>;
type OArr<V> = mobx.IObservableArray<V>;
@ -232,8 +232,18 @@ class SessionSettingsModal extends React.Component<{sessionId : string}, {}> {
@mobxReact.observer
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) {
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
@ -245,9 +255,68 @@ class LineSettingsModal extends React.Component<{line : LineType}, {}> {
@boundMethod
handleOK() : void {
let {line} = this.props;
mobx.action(() => {
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() {
@ -271,9 +340,22 @@ class LineSettingsModal extends React.Component<{line : LineType}, {}> {
Renderer
</div>
<div className="settings-input">
xxx
{this.renderRendererDropdown()}
</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>
<footer>
<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;
}
}
.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 {
@ -3006,10 +3023,18 @@ input[type=checkbox] {
}
}
.markdown-renderer {
.markdown-error {
color: @term-red;
font-size: 14px;
padding: 5px;
}
}
.markdown-renderer .markdown {
padding: 5px;
line-height: 1.5;
blockquote {
background-color: #222;
}

View File

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