renderers, fix all savedheight issues with layout bounce

This commit is contained in:
sawka 2023-03-17 12:17:54 -07:00
parent ac1bba94d9
commit 8ae09f6924
5 changed files with 50 additions and 14 deletions

View File

@ -29,8 +29,30 @@ type CV<V> = mobx.IComputedValue<V>;
//
@mobxReact.observer
class SimpleImageRenderer extends React.Component<{data : Blob, context : RendererContext, opts : RendererOpts}, {}> {
class SimpleImageRenderer extends React.Component<{data : Blob, context : RendererContext, opts : RendererOpts, savedHeight : number}, {}> {
objUrl : string = null;
imageRef : React.RefObject<any> = React.createRef();
imageLoaded : OV<boolean> = mobx.observable.box(false, {name: "imageLoaded"});
componentDidMount() {
let img = this.imageRef.current;
if (img == null) {
return;
}
if (img.complete) {
this.setImageLoaded();
return;
}
img.onload = () => {
this.setImageLoaded();
};
}
setImageLoaded() {
mobx.action(() => {
this.imageLoaded.set(true);
})();
}
componentWillUnmount() {
if (this.objUrl != null) {
@ -44,9 +66,13 @@ class SimpleImageRenderer extends React.Component<{data : Blob, context : Render
this.objUrl = URL.createObjectURL(dataBlob);
}
let opts = this.props.opts;
let forceHeight : number = null;
if (!this.imageLoaded.get() && this.props.savedHeight >= 0) {
forceHeight = this.props.savedHeight;
}
return (
<div className="simple-image-renderer">
<img style={{maxHeight: opts.idealSize.height, maxWidth: opts.idealSize.width}} src={this.objUrl}/>
<div className="simple-image-renderer" style={{height: forceHeight}}>
<img ref={this.imageRef} style={{maxHeight: opts.idealSize.height, maxWidth: opts.idealSize.width}} src={this.objUrl}/>
</div>
);
}

View File

@ -27,7 +27,7 @@ function CodeRenderer(props : any) : any {
}
@mobxReact.observer
class SimpleMarkdownRenderer extends React.Component<{data : Blob, context : RendererContext, opts : RendererOpts}, {}> {
class SimpleMarkdownRenderer extends React.Component<{data : Blob, context : RendererContext, opts : RendererOpts, savedHeight : number}, {}> {
markdownText : OV<string> = mobx.observable.box(null, {name: "markdownText"});
componentDidMount() {
@ -38,9 +38,10 @@ class SimpleMarkdownRenderer extends React.Component<{data : Blob, context : Ren
})();
});
}
render() {
if (this.markdownText.get() == null) {
return null;
return <div className="markdown-renderer" style={{height: this.props.savedHeight}}/>
}
let markdownComponents = {
a: LinkRenderer,
@ -54,8 +55,10 @@ class SimpleMarkdownRenderer extends React.Component<{data : Blob, context : Ren
};
let markdownText = this.markdownText.get();
return (
<div className="markdown-renderer markdown content">
<ReactMarkdown children={this.markdownText.get()} remarkPlugins={[remarkGfm]} components={markdownComponents}/>
<div className="markdown-renderer">
<div className="markdown content">
<ReactMarkdown children={this.markdownText.get()} remarkPlugins={[remarkGfm]} components={markdownComponents}/>
</div>
</div>
);
}

View File

@ -2947,6 +2947,9 @@ input[type=checkbox] {
.simple-image-renderer {
padding: 10px;
img {
display: block;
}
}
.markdown {
@ -3003,7 +3006,7 @@ input[type=checkbox] {
}
}
.markdown-renderer.markdown {
.markdown-renderer .markdown {
padding: 5px;
line-height: 1.5;

View File

@ -7,6 +7,7 @@ import {If, For, When, Otherwise, Choose} from "tsx-control-statements/component
import type {RendererModelInitializeParams, TermOptsType, RendererContext, RendererOpts, SimpleBlobRendererComponent, RendererModelContainerApi, RendererPluginType, PtyDataType, RendererModel, RendererOptsUpdate, LineType} from "./types";
import {GlobalModel, LineContainerModel, getPtyData, Cmd} from "./model";
import {PtyDataBuffer} from "./ptydata";
import {debounce, throttle} from "throttle-debounce";
type OV<V> = mobx.IObservableValue<V>;
type CV<V> = mobx.IComputedValue<V>;
@ -20,8 +21,10 @@ class SimpleBlobRendererModel {
loading : OV<boolean>;
loadError : OV<string> = mobx.observable.box(null, {name: "renderer-loadError"});
ptyData : PtyDataType;
updateHeight_debounced : (newHeight : number) => void
constructor() {
this.updateHeight_debounced = debounce(1000, this.updateHeight.bind(this));
}
initialize(params : RendererModelInitializeParams) : void {
@ -52,7 +55,6 @@ class SimpleBlobRendererModel {
if (this.savedHeight != newHeight) {
this.savedHeight = newHeight;
this.api.saveHeight(newHeight);
console.log("saveheight", sprintf("[%d]", this.context.lineNum), newHeight);
}
}
@ -155,13 +157,15 @@ class SimpleBlobRenderer extends React.Component<{lcm : LineContainerModel, line
}
handleResize(entries : ResizeObserverEntry[]) : void {
console.log("simplerender resize", sprintf("[%d]", this.model.context.lineNum), entries);
if (this.model.loading.get()) {
return;
}
if (this.props.onHeightChange) {
this.props.onHeightChange();
}
if (!this.model.loading.get() && this.wrapperDivRef.current != null) {
let height = this.wrapperDivRef.current.offsetHeight;
this.model.updateHeight(height);
this.model.updateHeight_debounced(height);
}
}
@ -204,7 +208,7 @@ class SimpleBlobRenderer extends React.Component<{lcm : LineContainerModel, line
let dataBlob = new Blob([model.ptyData.data]);
return (
<div ref={this.wrapperDivRef}>
<Comp data={dataBlob} context={model.context} opts={model.opts}/>
<Comp data={dataBlob} context={model.context} opts={model.opts} savedHeight={this.model.savedHeight}/>
</div>
);
}

View File

@ -401,8 +401,8 @@ type RendererModel = {
receiveData : (pos : number, data : Uint8Array, reason? : string) => void,
};
type SimpleBlobRendererComponent = React.ComponentType<{data : Blob, context : RendererContext, opts : RendererOpts}>;
type SimpleJsonRendererComponent = React.ComponentType<{data : any, context : RendererContext, opts : RendererOpts}>;
type SimpleBlobRendererComponent = React.ComponentType<{data : Blob, context : RendererContext, opts : RendererOpts, savedHeight : number}>;
type SimpleJsonRendererComponent = React.ComponentType<{data : any, context : RendererContext, opts : RendererOpts, savedHeight : number}>;
type FullRendererComponent = React.ComponentType<{model : any}>;
type WindowSize = {