From b33ff1abdeab12d977c86f18c567ba3e84a49297 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 22 Feb 2024 16:34:32 -0500 Subject: replaced freeform document view wrapper with more direct caching of props. --- .../views/nodes/CollectionFreeFormDocumentView.tsx | 175 ++++++++------------- 1 file changed, 64 insertions(+), 111 deletions(-) (limited to 'src/client/views/nodes/CollectionFreeFormDocumentView.tsx') diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index a0a64ab59..2800ea200 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -1,4 +1,4 @@ -import { action, computed, makeObservable, observable } from 'mobx'; +import { action, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { OmitKeys, numberRange } from '../../../Utils'; @@ -12,14 +12,16 @@ import { DocumentManager } from '../../util/DocumentManager'; import { ScriptingGlobals } from '../../util/ScriptingGlobals'; import { SelectionManager } from '../../util/SelectionManager'; import { DocComponent } from '../DocComponent'; -import { ObservableReactComponent } from '../ObservableReactComponent'; import { StyleProp } from '../StyleProvider'; import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView'; import './CollectionFreeFormDocumentView.scss'; import { DocumentView, DocumentViewProps, OpenWhere } from './DocumentView'; import { FieldViewProps } from './FieldView'; -export interface CollectionFreeFormDocumentViewWrapperProps extends DocumentViewProps { +/// Ugh, typescript has no run-time way of iterating through the keys of an interface. so we need +/// manaully keep this list of keys in synch wih the fields of the freeFormProps interface +const freeFormPropsKeys = ['x', 'y', 'z', 'zIndex', 'rotation', 'opacity', 'backgroundColor', 'color', 'highlight', 'width', 'height', 'autoDim', 'transition']; +interface freeFormProps { x: number; y: number; z: number; @@ -33,102 +35,17 @@ export interface CollectionFreeFormDocumentViewWrapperProps extends DocumentView opacity?: number; highlight?: boolean; transition?: string; - RenderCutoffProvider: (doc: Doc) => boolean; - CollectionFreeFormView: CollectionFreeFormView; -} -@observer -export class CollectionFreeFormDocumentViewWrapper extends ObservableReactComponent { - constructor(props: CollectionFreeFormDocumentViewWrapperProps) { - super(props); - makeObservable(this); - } - @observable X = this.props.x; - @observable Y = this.props.y; - @observable Z = this.props.z; - @observable ZIndex = this.props.zIndex; - @observable Rotation = this.props.rotation; - @observable Opacity = this.props.opacity; - @observable BackgroundColor = this.props.backgroundColor; - @observable Color = this.props.color; - @observable Highlight = this.props.highlight; - @observable Width = this.props.width; - @observable Height = this.props.height; - @observable AutoDim = this.props.autoDim; - @observable Transition = this.props.transition; - CollectionFreeFormView = this.props.CollectionFreeFormView; // needed for type checking - RenderCutoffProvider = this.props.RenderCutoffProvider; // needed for type checking - - get Document() { - return this._props.Document; - } - @computed get WrapperKeys() { - return Object.keys(this).filter(key => key.startsWith('w_')).map(key => key.replace('w_', '')) - .map(key => ({upper:key, lower:key[0].toLowerCase() + key.substring(1)})); // prettier-ignore - } - - // wrapper functions around prop fields that have been converted to observables to keep 'props' from ever changing. - // this way, downstream code only invalidates when it uses a specific prop, not when any prop changes - w_X = () => this.X; // prettier-ignore - w_Y = () => this.Y; // prettier-ignore - w_Z = () => this.Z; // prettier-ignore - w_ZIndex = () => this.ZIndex ?? NumCast(this.Document.zIndex); // prettier-ignore - w_Rotation = () => this.Rotation ?? NumCast(this.Document._rotation); // prettier-ignore - w_Opacity = () => this.Opacity; // prettier-ignore - w_BackgroundColor = () => this.BackgroundColor ?? Cast(this.Document._backgroundColor, 'string', null); // prettier-ignore - w_Color = () => this.Color ?? Cast(this.Document._color, 'string', null); // prettier-ignore - w_Highlight = () => this.Highlight; // prettier-ignore - w_Width = () => this.Width; // prettier-ignore - w_Height = () => this.Height; // prettier-ignore - w_AutoDim = () => this.AutoDim; // prettier-ignore - w_Transition = () => this.Transition; // prettier-ignore - - PanelWidth = () => this._props.autoDim ? this._props.PanelWidth?.() : this.Width; // prettier-ignore - PanelHeight = () => this._props.autoDim ? this._props.PanelHeight?.() : this.Height; // prettier-ignore - - componentDidUpdate(prevProps: Readonly>) { - super.componentDidUpdate(prevProps); - this.WrapperKeys.forEach(action(keys => ((this as any)[keys.upper] = (this.props as any)[keys.lower]))); - } - render() { - const layoutProps = this.WrapperKeys.reduce((val, keys) => [(val['w_' + keys.upper] = (this as any)['w_' + keys.upper]), val][1], {} as { [key: string]: Function }); - return ( - keys.lower) ).omit} // prettier-ignore - {...layoutProps} - PanelWidth={this.PanelWidth} - PanelHeight={this.PanelHeight} - /> - ); - } } export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps { - w_X: () => number; - w_Y: () => number; - w_Z: () => number; - w_ZIndex?: () => number; - w_Rotation?: () => number; - w_Color: () => string; - w_BackgroundColor: () => string; - w_Opacity: () => number | undefined; - w_Highlight: () => boolean | undefined; - w_Transition: () => string | undefined; - w_Width: () => number; - w_Height: () => number; - PanelWidth: () => number; - PanelHeight: () => number; RenderCutoffProvider: (doc: Doc) => boolean; CollectionFreeFormView: CollectionFreeFormView; } - @observer -export class CollectionFreeFormDocumentView extends DocComponent() { - constructor(props: CollectionFreeFormDocumentViewProps) { - super(props); - makeObservable(this); - } +export class CollectionFreeFormDocumentView extends DocComponent() { get displayName() { // this makes mobx trace() statements more descriptive return 'CollectionFreeFormDocumentView(' + this.Document.title + ')'; } // prettier-ignore + public static CollectionFreeFormDocViewClassName = 'collectionFreeFormDocumentView-container'; public static animFields: { key: string; val?: number }[] = [ { key: 'x' }, { key: 'y' }, @@ -145,16 +62,53 @@ export class CollectionFreeFormDocumentView extends DocComponent (Doc.LayoutFieldKey(doc) ? [Doc.LayoutFieldKey(doc)] : []); // fields that are configured to be animatable using animation frames - get CollectionFreeFormView() { - return this._props.CollectionFreeFormView; + constructor(props: CollectionFreeFormDocumentViewProps & freeFormProps) { + super(props); + makeObservable(this); + } + + get WrapperKeys() { + // each of these keys is set by the CollectionView and passed via props. however, if any one of these props changes + // (or any other prop), then it's as if they all change. + // Anything that accesses these props will then invalidate unncessarily. + // To avoid this, we copy these prop values into local observables. Now when 'props' changes, nothing invalidates. + // Instead, we copy each values into its observable which ohnly triggers invalidations if the new value is different + // than the old value, and then only things that access that observable will invalidate. + return freeFormPropsKeys + .map(key => ({upper:key[0].toUpperCase() + key.substring(1), lower:key})); // prettier-ignore + } + @observable X = this.props.x; + @observable Y = this.props.y; + @observable Z = this.props.z; + @observable ZIndex = this.props.zIndex; + @observable Rotation = this.props.rotation; + @observable Opacity = this.props.opacity; + @observable BackgroundColor = this.props.backgroundColor; + @observable Color = this.props.color; + @observable Highlight = this.props.highlight; + @observable Width = this.props.width; + @observable Height = this.props.height; + @observable AutoDim = this.props.autoDim; + @observable Transition = this.props.transition; + + componentDidUpdate(prevProps: Readonly>) { + super.componentDidUpdate(prevProps); + this.WrapperKeys.forEach(action(keys => ((this as any)[keys.upper] = (this.props as any)[keys.lower]))); } + CollectionFreeFormView = this.props.CollectionFreeFormView; // needed for type checking + // this way, downstream code only invalidates when it uses a specific prop, not when any prop changes + DataTransition = () => this._props.transition; // prettier-ignore + RenderCutoffProvider = this.props.RenderCutoffProvider; // needed for type checking + PanelWidth = () => this._props.autoDim ? this._props.PanelWidth?.() : this.Width; // prettier-ignore + PanelHeight = () => this._props.autoDim ? this._props.PanelHeight?.() : this.Height; // prettier-ignore + styleProvider = (doc: Doc | undefined, props: Opt, property: string) => { if (doc === this.layoutDoc) { switch (property) { - case StyleProp.Opacity: return this._props.w_Opacity(); // only change the opacity for this specific document, not its children - case StyleProp.BackgroundColor: return this._props.w_BackgroundColor(); - case StyleProp.Color: return this._props.w_Color(); + case StyleProp.Opacity: return this.Opacity; // only change the opacity for this specific document, not its children + case StyleProp.BackgroundColor: return this.BackgroundColor; + case StyleProp.Color: return this.Color; } // prettier-ignore } return this._props.styleProvider?.(doc, props, property); @@ -253,14 +207,14 @@ export class CollectionFreeFormDocumentView extends DocComponent { const [locX, locY] = this._props.ScreenToLocalTransform().transformDirection(x, y); - this.Document.x = this._props.w_X() + locX; - this.Document.y = this._props.w_Y() + locY; + this.Document.x = this.X + locX; + this.Document.y = this.Y + locY; }; screenToLocalTransform = () => this._props .ScreenToLocalTransform() - .translate(-this._props.w_X(), -this._props.w_Y()) - .rotateDeg(-(this._props.w_Rotation?.() || 0)); + .translate(-this.X, -this.Y) + .rotateDeg(-(this.Rotation || 0)); returnThis = () => this; /// this indicates whether the doc view is activated because of its relationshop to a group @@ -273,27 +227,26 @@ export class CollectionFreeFormDocumentView extends DocComponent key.startsWith('w_'))).omit; // prettier-ignore + return (
- {this._props.RenderCutoffProvider(this.Document) ? ( -
+ {this.RenderCutoffProvider(this.Document) ? ( +
) : ( val.lower)).omit} // prettier-ignore + DataTransition={this.DataTransition} CollectionFreeFormDocumentView={this.returnThis} styleProvider={this.styleProvider} ScreenToLocalTransform={this.screenToLocalTransform} -- cgit v1.2.3-70-g09d2 From b420caf2c7ecd386cae2cc550904522474b541aa Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 26 Mar 2024 22:34:10 -0400 Subject: added empty image tool and click on empty image to select from filesystem. fixed following links in lightbox and showing links to stackedTimelines. fixed embedding docs into text. fixed not resizing text boxes that also show up in pivot view. prevent context menu from going off top of screen. fixed freeform clustering colors and click to type. fixed links to stackedTimeline marks, and titles for marks. made title editing from doc deco and header use same syntax as keyValue. fixed marquee selection on webBoxes. turn off transitions in freeformdocview after timeout. enabled iconifying templates to propagate to "offspring". fixes images in templates. don't show headr on schema views. --- src/client/documents/Documents.ts | 52 ++++++++-------- src/client/util/DocumentManager.ts | 4 +- src/client/views/ContextMenu.tsx | 6 +- src/client/views/DocumentDecorations.tsx | 71 ++++++++-------------- src/client/views/FieldsDropdown.tsx | 1 - src/client/views/LightboxView.tsx | 2 + src/client/views/MarqueeAnnotator.tsx | 19 ++++-- src/client/views/ObservableReactComponent.tsx | 3 +- src/client/views/PropertiesView.tsx | 2 +- src/client/views/StyleProvider.tsx | 6 +- .../collections/CollectionStackedTimeline.tsx | 13 ++-- .../CollectionFreeFormLayoutEngines.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 11 ++-- .../collections/collectionFreeForm/MarqueeView.tsx | 4 +- .../collectionSchema/SchemaTableCell.tsx | 2 +- src/client/views/global/globalScripts.ts | 4 +- .../views/nodes/CollectionFreeFormDocumentView.tsx | 24 ++++++-- src/client/views/nodes/DocumentContentsView.tsx | 7 ++- src/client/views/nodes/DocumentView.tsx | 35 +++++++---- src/client/views/nodes/FieldView.tsx | 1 + src/client/views/nodes/ImageBox.tsx | 55 +++++++++++++---- src/client/views/nodes/KeyValueBox.tsx | 2 +- src/client/views/nodes/LabelBox.tsx | 2 +- src/client/views/nodes/LinkBox.tsx | 47 ++++++++++---- src/client/views/nodes/VideoBox.tsx | 5 +- src/client/views/nodes/WebBox.tsx | 65 ++++++++++++++------ .../views/nodes/formattedText/FormattedTextBox.tsx | 17 ++++-- src/client/views/nodes/trails/PresBox.tsx | 2 +- src/fields/Doc.ts | 29 +++++---- src/fields/PresField.ts | 6 -- src/fields/RichTextField.ts | 7 --- 31 files changed, 311 insertions(+), 195 deletions(-) delete mode 100644 src/fields/PresField.ts (limited to 'src/client/views/nodes/CollectionFreeFormDocumentView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 17cb6fef8..b63c5e429 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -1017,8 +1017,8 @@ export namespace Docs { } export function ImageDocument(url: string | ImageField, options: DocumentOptions = {}, overwriteDoc?: Doc) { - const imgField = url instanceof ImageField ? url : new ImageField(url); - return InstanceFromProto(Prototypes.get(DocumentType.IMG), imgField, { title: basename(imgField.url.href), ...options }, undefined, undefined, undefined, overwriteDoc); + const imgField = url instanceof ImageField ? url : url ? new ImageField(url) : undefined; + return InstanceFromProto(Prototypes.get(DocumentType.IMG), imgField, { title: basename(imgField?.url.href ?? '-no image-'), ...options }, undefined, undefined, undefined, overwriteDoc); } export function PresDocument(options: DocumentOptions = {}) { @@ -1950,6 +1950,31 @@ export namespace DocUtils { return dd; } + export function assignImageInfo(result: Upload.FileInformation, proto: Doc) { + if (Upload.isImageInformation(result)) { + const maxNativeDim = Math.min(Math.max(result.nativeHeight, result.nativeWidth), defaultNativeImageDim); + const exifRotation = StrCast((result.exifData?.data as any)?.Orientation).toLowerCase(); + proto['data-nativeOrientation'] = result.exifData?.data?.image?.Orientation ?? (exifRotation.includes('rotate 90') || exifRotation.includes('rotate 270') ? 5 : undefined); + proto['data_nativeWidth'] = result.nativeWidth < result.nativeHeight ? (maxNativeDim * result.nativeWidth) / result.nativeHeight : maxNativeDim; + proto['data_nativeHeight'] = result.nativeWidth < result.nativeHeight ? maxNativeDim : maxNativeDim / (result.nativeWidth / result.nativeHeight); + if (NumCast(proto['data-nativeOrientation']) >= 5) { + proto['data_nativeHeight'] = result.nativeWidth < result.nativeHeight ? (maxNativeDim * result.nativeWidth) / result.nativeHeight : maxNativeDim; + proto['data_nativeWidth'] = result.nativeWidth < result.nativeHeight ? maxNativeDim : maxNativeDim / (result.nativeWidth / result.nativeHeight); + } + proto.data_exif = JSON.stringify(result.exifData?.data); + proto.data_contentSize = result.contentSize; + // exif gps data coordinates are stored in DMS (Degrees Minutes Seconds), the following operation converts that to decimal coordinates + const latitude = result.exifData?.data?.GPSLatitude; + const latitudeDirection = result.exifData?.data?.GPSLatitudeRef; + const longitude = result.exifData?.data?.GPSLongitude; + const longitudeDirection = result.exifData?.data?.GPSLongitudeRef; + if (latitude !== undefined && longitude !== undefined && latitudeDirection !== undefined && longitudeDirection !== undefined) { + proto.latitude = ConvertDMSToDD(latitude[0], latitude[1], latitude[2], latitudeDirection); + proto.longitude = ConvertDMSToDD(longitude[0], longitude[1], longitude[2], longitudeDirection); + } + } + } + async function processFileupload(generatedDocuments: Doc[], name: string, type: string, result: Error | Upload.FileInformation, options: DocumentOptions, overwriteDoc?: Doc) { if (result instanceof Error) { alert(`Upload failed: ${result.message}`); @@ -1961,28 +1986,7 @@ export namespace DocUtils { if (doc) { const proto = Doc.GetProto(doc); proto.text = result.rawText; - if (Upload.isImageInformation(result)) { - const maxNativeDim = Math.min(Math.max(result.nativeHeight, result.nativeWidth), defaultNativeImageDim); - const exifRotation = StrCast((result.exifData?.data as any)?.Orientation).toLowerCase(); - proto['data-nativeOrientation'] = result.exifData?.data?.image?.Orientation ?? (exifRotation.includes('rotate 90') || exifRotation.includes('rotate 270') ? 5 : undefined); - proto['data_nativeWidth'] = result.nativeWidth < result.nativeHeight ? (maxNativeDim * result.nativeWidth) / result.nativeHeight : maxNativeDim; - proto['data_nativeHeight'] = result.nativeWidth < result.nativeHeight ? maxNativeDim : maxNativeDim / (result.nativeWidth / result.nativeHeight); - if (NumCast(proto['data-nativeOrientation']) >= 5) { - proto['data_nativeHeight'] = result.nativeWidth < result.nativeHeight ? (maxNativeDim * result.nativeWidth) / result.nativeHeight : maxNativeDim; - proto['data_nativeWidth'] = result.nativeWidth < result.nativeHeight ? maxNativeDim : maxNativeDim / (result.nativeWidth / result.nativeHeight); - } - proto.data_exif = JSON.stringify(result.exifData?.data); - proto.data_contentSize = result.contentSize; - // exif gps data coordinates are stored in DMS (Degrees Minutes Seconds), the following operation converts that to decimal coordinates - const latitude = result.exifData?.data?.GPSLatitude; - const latitudeDirection = result.exifData?.data?.GPSLatitudeRef; - const longitude = result.exifData?.data?.GPSLongitude; - const longitudeDirection = result.exifData?.data?.GPSLongitudeRef; - if (latitude !== undefined && longitude !== undefined && latitudeDirection !== undefined && longitudeDirection !== undefined) { - proto.latitude = ConvertDMSToDD(latitude[0], latitude[1], latitude[2], latitudeDirection); - proto.longitude = ConvertDMSToDD(longitude[0], longitude[1], longitude[2], longitudeDirection); - } - } + !(result instanceof Error) && DocUtils.assignImageInfo(result, proto); if (Upload.isVideoInformation(result)) { proto.data_duration = result.duration; } diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index a38a330da..40d28c690 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -59,7 +59,7 @@ export class DocumentManager { private _viewRenderedCbs: { doc: Doc; func: (dv: DocumentView) => any }[] = []; public AddViewRenderedCb = (doc: Opt, func: (dv: DocumentView) => any) => { if (doc) { - const dv = this.getDocumentView(doc); + const dv = LightboxView.LightboxDoc ? this.getLightboxDocumentView(doc) : this.getDocumentView(doc); this._viewRenderedCbs.push({ doc, func }); if (dv) { this.callAddViewFuncs(dv); @@ -262,7 +262,7 @@ export class DocumentManager { return res(this.getDocumentView(docContextPath[0])!); } options.didMove = true; - docContextPath.some(doc => TabDocView.Activate(doc)) || DocumentViewInternal.addDocTabFunc(docContextPath[0], options.openLocation ?? OpenWhere.addRight); + (!LightboxView.LightboxDoc && docContextPath.some(doc => TabDocView.Activate(doc))) || DocumentViewInternal.addDocTabFunc(docContextPath[0], options.openLocation ?? OpenWhere.addRight); this.AddViewRenderedCb(docContextPath[0], dv => res(dv)); })); if (options.openLocation === OpenWhere.lightbox) { diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index 8f4e43978..ca877b93e 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -218,11 +218,12 @@ export class ContextMenu extends ObservableReactComponent<{}> { this._width = DivWidth(r); this._height = DivHeight(r); } + this._searchRef.current?.focus(); })} style={{ display: this._display ? '' : 'none', left: this.pageX, - ...(this._yRelativeToTop ? { top: this.pageY } : { bottom: this.pageY }), + ...(this._yRelativeToTop ? { top: Math.max(0, this.pageY) } : { bottom: this.pageY }), background: SettingsManager.userBackgroundColor, color: SettingsManager.userColor, }}> @@ -265,7 +266,8 @@ export class ContextMenu extends ObservableReactComponent<{}> { const item = this.flatItems[this._selectedIndex]; if (item) { item.event({ x: this.pageX, y: this.pageY }); - } else if (this._searchString.startsWith(this._defaultPrefix)) { + } else { + //if (this._searchString.startsWith(this._defaultPrefix)) { this._defaultItem?.(this._searchString.substring(this._defaultPrefix.length)); } this.closeMenu(); diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 2fb9f0fc1..4d9b93896 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -34,6 +34,7 @@ import { Colors } from './global/globalEnums'; import { DocumentView, OpenWhereMod } from './nodes/DocumentView'; import { ImageBox } from './nodes/ImageBox'; import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; +import { KeyValueBox } from './nodes/KeyValueBox'; interface DocumentDecorationsProps { PanelWidth: number; @@ -57,7 +58,7 @@ export class DocumentDecorations extends ObservableReactComponent { - if (this._accumulatedTitle.startsWith('#') || this._accumulatedTitle.startsWith('=')) { + if (this._accumulatedTitle.startsWith('$')) { this._titleControlString = this._accumulatedTitle; - } else if (this._titleControlString.startsWith('#')) { + } else if (this._titleControlString.startsWith('$')) { if (this._accumulatedTitle.startsWith('-->#')) { SelectionManager.Docs.forEach(doc => (doc[DocData].onViewMounted = ScriptField.MakeScript(`updateTagsCollection(this)`))); } @@ -131,26 +132,7 @@ export class DocumentDecorations extends ObservableReactComponent')) { - const title = titleField.toString().replace(/\.?/, ''); - const curKey = Doc.LayoutFieldKey(d.Document); - if (curKey !== title) { - if (title) { - if (d.dataDoc[title] === undefined || d.dataDoc[title] instanceof RichTextField || typeof d.dataDoc[title] === 'string') { - d.Document.layout_fieldKey = `layout_${title}`; - d.Document[`layout_${title}`] = FormattedTextBox.LayoutString(title); - d.Document[`${title}_nativeWidth`] = d.Document[`${title}_nativeHeight`] = 0; - } - } else { - d.Document.layout_fieldKey = undefined; - } - } - } else { - Doc.SetInPlace(d.Document, titleFieldKey, titleField, true); - } + KeyValueBox.SetField(d.Document, titleFieldKey, this._accumulatedTitle); }), 'edit title' ); @@ -181,7 +163,8 @@ export class DocumentDecorations extends ObservableReactComponent this.onBackgroundMove(true, e), emptyFunction, action(e => { - !this._editingTitle && (this._accumulatedTitle = this._titleControlString.startsWith('#') ? this.selectionTitle : this._titleControlString); + const selected = SelectionManager.Views.length === 1 ? SelectionManager.Docs[0] : undefined; + !this._editingTitle && (this._accumulatedTitle = this._titleControlString.startsWith('$') ? (selected && Field.toKeyValueString(selected, this._titleControlString.substring(1))) || '-unset-' : this._titleControlString); this._editingTitle = true; this._keyinput.current && setTimeout(this._keyinput.current.focus); }) @@ -622,11 +605,8 @@ export class DocumentDecorations extends ObservableReactComponent { - this._editingTitle = false; - !hideTitle && this.titleBlur(); - })} - onChange={action(e => !hideTitle && (this._accumulatedTitle = e.target.value))} - onKeyDown={hideTitle ? emptyFunction : this.titleEntered} - onPointerDown={e => e.stopPropagation()} - /> + <> + {r - x < 150 ? null : {this._titleControlString + ':'}} + { + this._editingTitle = false; + !hideTitle && this.titleBlur(); + })} + onChange={action(e => !hideTitle && (this._accumulatedTitle = e.target.value))} + onKeyDown={hideTitle ? emptyFunction : this.titleEntered} + onPointerDown={e => e.stopPropagation()} + /> + ) : (
{hideTitle ? null : ( diff --git a/src/client/views/FieldsDropdown.tsx b/src/client/views/FieldsDropdown.tsx index 5638d34c6..6a5c2cb4c 100644 --- a/src/client/views/FieldsDropdown.tsx +++ b/src/client/views/FieldsDropdown.tsx @@ -61,7 +61,6 @@ export class FieldsDropdown extends ObservableReactComponent filteredOptions.push(pair[0])); const options = filteredOptions.sort().map(facet => ({ value: facet, label: facet })); - console.log(options); return (