From 188e1e57860f58e9ebe3536a0e1f7cd84ea0db80 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 18 Mar 2021 00:08:13 -0400 Subject: cleaned up link making. Documents don't add to the Undo stack when being created and Initializing is set. Links to text regions automatically update their link line endpoints even if autoMove isn't set. regularized initialization fields to avoid special cases about setting delegate keys without a leading "_" --- src/client/views/nodes/formattedText/RichTextRules.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/views/nodes/formattedText') diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts index 4b9b78211..3fd7d61fa 100644 --- a/src/client/views/nodes/formattedText/RichTextRules.ts +++ b/src/client/views/nodes/formattedText/RichTextRules.ts @@ -90,7 +90,7 @@ export class RichTextRules { textDoc.inlineTextCount = numInlines + 1; const inlineFieldKey = "inline" + numInlines; // which field on the text document this annotation will write to const inlineLayoutKey = "layout_" + inlineFieldKey; // the field holding the layout string that will render the inline annotation - const textDocInline = Docs.Create.TextDocument("", { layoutKey: inlineLayoutKey, _width: 75, _height: 35, annotationOn: textDoc, _autoHeight: true, _fontSize: "9px", title: "inline comment" }); + const textDocInline = Docs.Create.TextDocument("", { _layoutKey: inlineLayoutKey, _width: 75, _height: 35, annotationOn: textDoc, _autoHeight: true, _fontSize: "9px", title: "inline comment" }); textDocInline.title = inlineFieldKey; // give the annotation its own title textDocInline["title-custom"] = true; // And make sure that it's 'custom' so that editing text doesn't change the title of the containing doc textDocInline.isTemplateForField = inlineFieldKey; // this is needed in case the containing text doc is converted to a template at some point -- cgit v1.2.3-70-g09d2 From 26fc8ca2af1697069eb9ba6128abd013550daf2e Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 18 Mar 2021 01:15:11 -0400 Subject: minor tweaks from last --- src/client/documents/Documents.ts | 85 +++++++--------------- .../views/nodes/formattedText/FormattedTextBox.tsx | 3 +- src/fields/util.ts | 8 +- 3 files changed, 36 insertions(+), 60 deletions(-) (limited to 'src/client/views/nodes/formattedText') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 24409933e..332f7304b 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -1,7 +1,7 @@ import { action, runInAction } from "mobx"; import { basename, extname } from "path"; import { DateField } from "../../fields/DateField"; -import { Doc, DocListCast, DocListCastAsync, Field, HeightSym, Opt, WidthSym } from "../../fields/Doc"; +import { Doc, DocListCast, DocListCastAsync, Field, HeightSym, Opt, WidthSym, Initializing } from "../../fields/Doc"; import { Id } from "../../fields/FieldSymbols"; import { HtmlField } from "../../fields/HtmlField"; import { InkField } from "../../fields/InkField"; @@ -193,6 +193,8 @@ export class DocumentOptions { presProgressivize?: boolean; borderRounding?: string; boxShadow?: string; + data?: any; + baseProto?: boolean; // is this a base prototoype dontRegisterView?: boolean; lookupField?: ScriptField; // script that returns the value of a field. This script is passed the rootDoc, layoutDoc, field, and container of the document. see PresBox. "onDoubleClick-rawScript"?: string; // onDoubleClick script in raw text form @@ -210,6 +212,7 @@ export class DocumentOptions { _removeDropProperties?: List; // list of properties that should be removed from a document when it is dropped. e.g., a creator button may be forceActive to allow it be dragged, but the forceActive property can be removed from the dropped document iconShape?: string; // shapes of the fonticon border layout_linkView?: Doc; // view template for a link document + layout_keyValue?: string; // view tempalte for key value docs linkRelationship?: string; // type of relatinoship a link represents linkDisplay?: boolean; // whether a link line should be dipslayed between the two link anchors anchor1?: Doc; @@ -444,8 +447,6 @@ export namespace Docs { }] ]); - // All document prototypes are initialized with at least these values - const defaultOptions: DocumentOptions = { x: 0, y: 0, _width: 300 }; // bcz: do we really want to set anything here? could also try to set in render() methods for types that need a default const suffix = "Proto"; /** @@ -486,30 +487,22 @@ export namespace Docs { * @param type */ const PrototypeMap: PrototypeMap = new Map(); - export function get(type: DocumentType): Doc { - return PrototypeMap.get(type)!; - } + export function get(type: DocumentType): Doc { return PrototypeMap.get(type)!; } /** * A collection of all links in the database. Ideally, this would be a search, but for now all links are cached here. */ - export function MainLinkDocument() { - return Prototypes.get(DocumentType.LINKDB); - } + export function MainLinkDocument() { return Prototypes.get(DocumentType.LINKDB); } /** * A collection of all scripts in the database */ - export function MainScriptDocument() { - return Prototypes.get(DocumentType.SCRIPTDB); - } + export function MainScriptDocument() { return Prototypes.get(DocumentType.SCRIPTDB); } /** - * A collection of all groups in the database + * A collection of all user acl groups in the database */ - export function MainGroupDocument() { - return Prototypes.get(DocumentType.GROUPDB); - } + export function MainGroupDocument() { return Prototypes.get(DocumentType.GROUPDB); } /** * This is a convenience method that is used to initialize @@ -535,14 +528,12 @@ export namespace Docs { const title = prototypeId.toUpperCase().replace(upper, `_${upper}`); // synthesize the default options, the type and title from computed values and // whatever options pertain to this specific prototype - const options = { title, type, baseProto: true, ...defaultOptions, ...(template.options || {}) }; - options.layout = layout.view?.LayoutString(layout.dataField); - const doc = Doc.assign(new Doc(prototypeId, true), { system: true, layoutKey: "layout", ...options } as any); - doc.data = template.data; - doc.layout_keyValue = KeyValueBox.LayoutString(""); - return doc; + const options: DocumentOptions = { + system: true, _layoutKey: "layout", title, type, baseProto: true, x: 0, y: 0, _width: 300, ...(template.options || {}), + layout: layout.view?.LayoutString(layout.dataField), data: template.data, layout_keyValue: KeyValueBox.LayoutString("") + }; + return Doc.assign(new Doc(prototypeId, true), options as any, undefined, true); } - } /** @@ -648,7 +639,7 @@ export namespace Docs { * main document. */ export function InstanceFromProto(proto: Doc, data: Field | undefined, options: DocumentOptions, delegId?: string, fieldKey: string = "data", protoId?: string) { - const viewKeys = ["x", "y", "system"]; + const viewKeys = ["x", "y", "system"]; // keys that should be addded to the view document even though they don't begin with an "_" const { omit: dataProps, extract: viewProps } = OmitKeys(options, viewKeys, "^_"); dataProps.system = viewProps.system; @@ -664,12 +655,11 @@ export namespace Docs { dataProps[fieldKey + "-annotations"] = new List(); const dataDoc = Doc.assign(Doc.MakeDelegate(proto, protoId), dataProps as any, undefined, true); - const viewDoc = Doc.MakeDelegate(dataDoc, delegId); viewProps.author = Doc.CurrentUserEmail; - viewProps.type !== DocumentType.LINK && viewDoc.type !== DocumentType.LABEL && DocUtils.MakeLinkToActiveAudio(viewDoc); viewProps["acl-Override"] = "None"; viewProps["acl-Public"] = Doc.UserDoc()?.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Add; - Doc.assign(viewDoc, viewProps, true, true); + const viewDoc = Doc.assign(Doc.MakeDelegate(dataDoc, delegId), viewProps, true, true); + viewProps.type !== DocumentType.LINK && viewDoc.type !== DocumentType.LABEL && DocUtils.MakeLinkToActiveAudio(viewDoc); !Doc.IsSystem(dataDoc) && ![DocumentType.PDFANNO, DocumentType.KVP, DocumentType.LINK, DocumentType.LINKANCHOR, DocumentType.TEXTANCHOR].includes(proto.type as any) && !dataDoc.isFolder && !dataProps.annotationOn && Doc.AddDocToList(Cast(Doc.UserDoc().myFileOrphans, Doc, null), "data", dataDoc); @@ -679,22 +669,16 @@ export namespace Docs { export function ImageDocument(url: string, options: DocumentOptions = {}) { const imgField = new ImageField(new URL(url)); - const inst = InstanceFromProto(Prototypes.get(DocumentType.IMG), imgField, { title: path.basename(url), ...options }); - let target = imgField.url.href; - if (new RegExp(window.location.origin).test(target)) { - const extension = path.extname(target); - target = `${target.substring(0, target.length - extension.length)}_o${extension}`; - } - return inst; + return InstanceFromProto(Prototypes.get(DocumentType.IMG), imgField, { title: path.basename(url), ...options }); } + export function PresDocument(initial: List = new List(), options: DocumentOptions = {}) { return InstanceFromProto(Prototypes.get(DocumentType.PRES), initial, options); } export function ScriptingDocument(script: Opt, options: DocumentOptions = {}, fieldKey?: string) { - const res = InstanceFromProto(Prototypes.get(DocumentType.SCRIPTING), script, options); - fieldKey && res.proto instanceof Doc && (res.proto.layout = ScriptingBox.LayoutString(fieldKey)); - return res; + return InstanceFromProto(Prototypes.get(DocumentType.SCRIPTING), script, + { ...options, layout: fieldKey ? ScriptingBox.LayoutString(fieldKey) : undefined }); } export function VideoDocument(url: string, options: DocumentOptions = {}) { @@ -718,9 +702,8 @@ export namespace Docs { } export function AudioDocument(url: string, options: DocumentOptions = {}) { - const instance = InstanceFromProto(Prototypes.get(DocumentType.AUDIO), new AudioField(new URL(url)), { useLinkSmallAnchor: true, ...options }); // hideLinkButton: false, useLinkSmallAnchor: false, - Doc.GetProto(instance).backgroundColor = ComputedField.MakeFunction("this._audioState === 'playing' ? 'green':'gray'"); - return instance; + return InstanceFromProto(Prototypes.get(DocumentType.AUDIO), new AudioField(new URL(url)), + { useLinkSmallAnchor: true, ...options, backgroundColor: ComputedField.MakeFunction("this._audioState === 'playing' ? 'green':'gray'") as any }); // hideLinkButton: false, useLinkSmallAnchor: false, } export function SearchDocument(options: DocumentOptions = {}) { @@ -766,6 +749,7 @@ export namespace Docs { export function InkDocument(color: string, tool: string, strokeWidth: string, strokeBezier: string, fillColor: string, arrowStart: string, arrowEnd: string, dash: string, points: { X: number, Y: number }[], options: DocumentOptions = {}) { const I = new Doc(); + I[Initializing] = true; I.type = DocumentType.INK; I.layout = InkingStroke.LayoutString("data"); I.color = color; @@ -788,20 +772,16 @@ export namespace Docs { I.data = new InkField(points); I["acl-Public"] = Doc.UserDoc()?.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Add; I["acl-Override"] = "None"; + I[Initializing] = false; return I; } export function PdfDocument(url: string, options: DocumentOptions = {}) { - const pdfProto = Prototypes.get(DocumentType.PDF); - pdfProto._fitWidth = true; // backward compatibility -- can be removed after db is reset - return InstanceFromProto(pdfProto, new PdfField(new URL(url)), { ...options }); + return InstanceFromProto(Prototypes.get(DocumentType.PDF), new PdfField(new URL(url)), { ...options }); } export function WebDocument(url: string, options: DocumentOptions = {}) { - const webProto = Prototypes.get(DocumentType.WEB); - webProto.scrollHeight = 100000; // backward compatibility -- can be removed after db is reset - webProto._fitWidth = true; // backward compatibility -- can be removed after db is reset - return InstanceFromProto(webProto, url ? new WebField(new URL(url)) : undefined, { _chromeStatus: url ? undefined : "enabled", _lockedTransform: true, ...options }); + return InstanceFromProto(Prototypes.get(DocumentType.WEB), url ? new WebField(new URL(url)) : undefined, { _chromeStatus: url ? undefined : "enabled", _lockedTransform: true, ...options }); } export function HtmlDocument(html: string, options: DocumentOptions = {}) { @@ -861,7 +841,6 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", ...options, _viewType: CollectionViewType.Multirow }); } - export function MasonryDocument(documents: Array, options: DocumentOptions) { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", ...options, _viewType: CollectionViewType.Masonry }); } @@ -879,11 +858,6 @@ export namespace Docs { } export function ButtonDocument(options?: DocumentOptions) { - // const btn = InstanceFromProto(Prototypes.get(DocumentType.BUTTON), undefined, { ...(options || {}), "onClick-rawScript": "-script-" }); - // btn.layoutKey = "layout_onClick"; - // btn.height = 250; - // btn.width = 200; - // btn.layout_onClick = ScriptingBox.LayoutString("onClick"); return InstanceFromProto(Prototypes.get(DocumentType.BUTTON), undefined, { ...(options || {}), "onClick-rawScript": "-script-" }); } @@ -891,7 +865,6 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.SLIDER), undefined, { ...(options || {}) }); } - export function FontIconDocument(options?: DocumentOptions) { return InstanceFromProto(Prototypes.get(DocumentType.FONTICON), undefined, { hideLinkButton: true, ...(options || {}) }); } @@ -904,11 +877,9 @@ export namespace Docs { } export function DockDocument(documents: Array, config: string, options: DocumentOptions, id?: string) { - const inst = InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { freezeChildren: "remove|add", treeViewDefaultExpandedView: "data", ...options, _viewType: CollectionViewType.Docking, dockingConfig: config }, id); const tabs = TreeDocument(documents, { title: "On-Screen Tabs", freezeChildren: "remove|add", treeViewLockExpandedView: true, treeViewDefaultExpandedView: "data", _fitWidth: true, system: true }); const all = TreeDocument([], { title: "Off-Screen Tabs", freezeChildren: "add", treeViewLockExpandedView: true, treeViewDefaultExpandedView: "data", system: true }); - Doc.GetProto(inst).data = new List([tabs, all]); - return inst; + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List([tabs, all]), { freezeChildren: "remove|add", treeViewDefaultExpandedView: "data", ...options, _viewType: CollectionViewType.Docking, dockingConfig: config }, id); } export function DirectoryImportDocument(options: DocumentOptions = {}) { diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index d64db1ee1..d44867541 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -667,7 +667,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const splitter = state.schema.marks.splitter.create({ id: Utils.GenerateGuid() }); let tr = state.tr.addMark(sel.from, sel.to, splitter); if (sel.from !== sel.to) { - const anchor = anchorDoc ?? Docs.Create.TextanchorDocument(); + const anchor = anchorDoc ?? Docs.Create.TextanchorDocument({ title: this._editorView?.state.doc.textBetween(sel.from, sel.to) }); const href = targetHref ?? Utils.prepend("/doc/" + anchor[Id]); if (anchor !== anchorDoc) this.addDocument(anchor); tr.doc.nodesBetween(sel.from, sel.to, (node: any, pos: number, parent: any) => { @@ -681,7 +681,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp this.dataDoc[ForceServerWrite] = this.dataDoc[UpdatingFromServer] = true; // need to allow permissions for adding links to readonly/augment only documents this._editorView!.dispatch(tr.removeMark(sel.from, sel.to, splitter)); this.dataDoc[UpdatingFromServer] = this.dataDoc[ForceServerWrite] = false; - Doc.GetProto(anchor).title = this._editorView?.state.doc.textBetween(sel.from, sel.to); return anchor; } return anchorDoc ?? this.rootDoc; diff --git a/src/fields/util.ts b/src/fields/util.ts index 36604c790..86f68ea6e 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -98,7 +98,10 @@ const _setterImpl = action(function (target: any, prop: string | symbol | number } !receiver[Initializing] && (!receiver[UpdatingFromServer] || receiver[ForceServerWrite]) && UndoManager.AddEvent({ redo: () => receiver[prop] = value, - undo: () => receiver[prop] = curValue + undo: () => { + // console.log("Undo: " + prop + " = " + curValue); // bcz: uncomment to log undo + receiver[prop] = curValue + } }); return true; } @@ -380,6 +383,7 @@ export function updateFunction(target: any, prop: any, value: any, receiver: any lastValue = ObjectField.MakeCopy(receiver[prop]); }, undo: action(() => { + // console.log("undo $add: " + prop, diff.items) // bcz: uncomment to log undo diff.items.forEach((item: any) => { const ind = receiver[prop].indexOf(item.value ? item.value() : item); ind !== -1 && receiver[prop].splice(ind, 1); @@ -397,6 +401,7 @@ export function updateFunction(target: any, prop: any, value: any, receiver: any lastValue = ObjectField.MakeCopy(receiver[prop]); }), undo: () => { + // console.log("undo $rem: " + prop, diff.items) // bcz: uncomment to log undo diff.items.forEach((item: any) => { const ind = (prevValue as List).indexOf(item.value ? item.value() : item); ind !== -1 && receiver[prop].indexOf(item.value ? item.value() : item) === -1 && receiver[prop].splice(ind, 0, item); @@ -410,6 +415,7 @@ export function updateFunction(target: any, prop: any, value: any, receiver: any lastValue = ObjectField.MakeCopy(receiver[prop]); }, undo: () => { + // console.log("undo list: " + prop, receiver[prop]) // bcz: uncomment to log undo receiver[prop] = ObjectField.MakeCopy(prevValue as List); lastValue = ObjectField.MakeCopy(receiver[prop]); } -- cgit v1.2.3-70-g09d2 From ed83093961b7e19df4675c9e2cf0a78eae333614 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 18 Mar 2021 11:31:20 -0400 Subject: made linkanchorbuttons not show up next to pdf annos. gave pdfannos a baseProto. made textboxes dynamically remove hashtags when deleted from text. --- src/client/documents/Documents.ts | 7 +++++++ src/client/views/DocumentButtonBar.tsx | 22 +++++++++++++++++----- src/client/views/MarqueeAnnotator.tsx | 2 +- src/client/views/StyleProvider.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 4 ++-- .../views/nodes/formattedText/FormattedTextBox.tsx | 12 ++++++++++++ 6 files changed, 40 insertions(+), 9 deletions(-) (limited to 'src/client/views/nodes/formattedText') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 332f7304b..a2850fd98 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -420,6 +420,10 @@ export namespace Docs { [DocumentType.PRESELEMENT, { layout: { view: PresElementBox, dataField: defaultDataKey } }], + [DocumentType.PDFANNO, { + layout: { view: CollectionView, dataField: defaultDataKey }, + options: { hideLinkButton: true } + }], [DocumentType.INK, { layout: { view: InkingStroke, dataField: defaultDataKey }, options: { _fontFamily: "cursive", backgroundColor: "transparent", links: ComputedField.MakeFunction("links(self)") as any } @@ -801,6 +805,9 @@ export namespace Docs { documents.map(d => d.context = inst); return inst; } + export function PdfAnnoDocument(documents: Array, options: DocumentOptions, id?: string) { + return InstanceFromProto(Prototypes.get(DocumentType.PDFANNO), new List(documents), { _chromeStatus: "collapsed", ...options, _viewType: CollectionViewType.Freeform }, id); + } export function PileDocument(documents: Array, options: DocumentOptions, id?: string) { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", backgroundColor: "black", _noAutoscroll: true, ...options, _viewType: CollectionViewType.Pile }, id); diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index 4a1ec4d6c..07b419e5f 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -184,6 +184,18 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV ; } @computed + get followLinkButton() { + const targetDoc = this.view0?.props.Document; + return !targetDoc ? (null) : {"follow primary link on click"}}> +
this.props.views().map(view => view?.docView?.toggleFollowLink(undefined, false, false)))}> + +
+
; + } + @computed get pinButton() { const targetDoc = this.view0?.props.Document; return !targetDoc ? (null) : (DocumentV const presPinWithViewIcon = ; const targetDoc = this.view0?.props.Document; return !targetDoc ? (null) :
{"Pin with current view"}
}> -
this.pinWithView(targetDoc)}> +
this.pinWithView(targetDoc)}> {presPinWithViewIcon}
; @@ -244,8 +254,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV const targetDoc = this.view0?.props.Document; return !targetDoc ? (null) :
{"Open Sharing Manager"}
}>
SharingManager.Instance.open(this.view0, targetDoc)}> - +
; } @@ -357,6 +366,9 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
{this.contextButton}
*/} + {!SelectionManager.Views()?.some(v => v.allLinks.length) ? (null) :
+ {this.followLinkButton} +
}
{this.pinButton}
diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx index 2e50c9b6d..046f327fc 100644 --- a/src/client/views/MarqueeAnnotator.tsx +++ b/src/client/views/MarqueeAnnotator.tsx @@ -114,7 +114,7 @@ export class MarqueeAnnotator extends React.Component { return marqueeAnno; } - const textRegionAnno = Docs.Create.FreeformDocument([], { type: DocumentType.PDFANNO, annotationOn: this.props.rootDoc, title: "Selection on " + this.props.rootDoc.title, _width: 1, _height: 1 }); + const textRegionAnno = Docs.Create.PdfAnnoDocument([], { annotationOn: this.props.rootDoc, title: "Selection on " + this.props.rootDoc.title, _width: 1, _height: 1 }); let maxX = -Number.MAX_VALUE; let minY = Number.MAX_VALUE; const annoDocs: Doc[] = []; diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index d9ab0d397..5cbbcce79 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -74,7 +74,7 @@ export function DefaultStyleProvider(doc: Opt, props: Opt - {this.layoutDoc.hideAllLinks ? (null) : this.allAnchors} + {this.layoutDoc.hideAllLinks ? (null) : this.allLinkEndpoints} {this.hideLinkButton ? (null) : } @@ -808,7 +808,7 @@ export class DocumentViewInternal extends DocComponent { + if (node.type === schema.nodes.dashField && node.attrs.fieldKey.startsWith("#")) { + accumTags.push(node.attrs.fieldKey) + } + }); + const curTags = Object.keys(this.dataDoc).filter(key => key.startsWith("#")); + const added = accumTags.filter(tag => !curTags.includes(tag)); + const removed = curTags.filter(tag => !accumTags.includes(tag)); + removed.forEach(r => this.dataDoc[r] = undefined); + added.forEach(a => this.dataDoc[a] = a); + let unchanged = true; if (this._applyingChange !== this.fieldKey && removeSelection(json) !== removeSelection(curProto?.Data)) { this._applyingChange = this.fieldKey; -- cgit v1.2.3-70-g09d2 From 3e2709a68e32650074e2bbc9af89fa0d66536d77 Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 19 Mar 2021 13:54:45 -0400 Subject: simplified chromeStatus to chromeHidden. fixed presBox item widths. fixed colorBox layout. --- src/client/documents/Documents.ts | 4 +- src/client/util/CurrentUserUtils.ts | 32 +++++------ .../util/Import & Export/DirectoryImportBox.tsx | 2 +- src/client/views/MainView.tsx | 4 +- src/client/views/PropertiesButtons.tsx | 5 +- src/client/views/SidebarAnnos.tsx | 1 - src/client/views/TemplateMenu.tsx | 7 +-- .../views/collections/CollectionCarousel3DView.tsx | 2 +- .../views/collections/CollectionCarouselView.tsx | 2 +- .../collections/CollectionMasonryViewFieldRow.tsx | 9 ++- .../views/collections/CollectionPileView.tsx | 10 ++-- .../views/collections/CollectionStackingView.tsx | 31 +++++------ .../CollectionStackingViewFieldColumn.tsx | 9 ++- .../views/collections/CollectionTimeView.tsx | 2 +- src/client/views/collections/CollectionView.tsx | 1 + src/client/views/collections/SchemaTable.tsx | 3 +- src/client/views/nodes/ColorBox.scss | 1 - src/client/views/nodes/ColorBox.tsx | 65 ++++++++++------------ src/client/views/nodes/DocumentView.tsx | 16 +++--- src/client/views/nodes/KeyValueBox.tsx | 2 +- src/client/views/nodes/PresBox.tsx | 6 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 1 - src/fields/documentSchemas.ts | 2 - src/fields/util.ts | 6 -- 24 files changed, 98 insertions(+), 125 deletions(-) (limited to 'src/client/views/nodes/formattedText') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index f4657d824..366275b6e 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -119,7 +119,7 @@ export class DocumentOptions { _showCaption?: string; // which field to display in the caption area. leave empty to have no caption _scrollTop?: number; // scroll location for pdfs _noAutoscroll?: boolean;// whether collections autoscroll when this item is dragged - _chromeStatus?: string; + _chromeHidden?: boolean; // whether the editing chrome for a document is hidden _layerTags?: List; // layer tags a document has (used for tab filtering "layers" in document tab) _searchDoc?: boolean; // is this a search document (used to change UI for search results in schema view) _forceActive?: boolean; // flag to handle pointer events when not selected (or otherwise active) @@ -338,7 +338,7 @@ export namespace Docs { }], [DocumentType.COL, { layout: { view: CollectionView, dataField: defaultDataKey }, - options: { _chromeStatus: "collapsed", _fitWidth: true, _panX: 0, _panY: 0, _viewScale: 1, links: ComputedField.MakeFunction("links(self)") as any } + options: { _fitWidth: true, _panX: 0, _panY: 0, _viewScale: 1, links: ComputedField.MakeFunction("links(self)") as any } }], [DocumentType.KVP, { layout: { view: KeyValueBox, dataField: defaultDataKey }, diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index fc70a6282..05e560f51 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -203,7 +203,7 @@ export class CurrentUserUtils { new SchemaHeaderField("[Long Description]", "dimGray", undefined, undefined, undefined, true), new SchemaHeaderField("[Details]", "dimGray", undefined, undefined, undefined, true), ]); - const detailView = Docs.Create.StackingDocument([carousel, descriptionWrapper], { ...shared, ...detailViewOpts, _chromeStatus: "", system: true }); + const detailView = Docs.Create.StackingDocument([carousel, descriptionWrapper], { ...shared, ...detailViewOpts, _chromeHidden: true, system: true }); detailView.isTemplateDoc = makeTemplate(detailView); details.title = "Details"; @@ -225,7 +225,7 @@ export class CurrentUserUtils { ]; if (doc["template-buttons"] === undefined) { doc["template-buttons"] = new PrefetchProxy(Docs.Create.MasonryDocument(requiredTypes, { - title: "Advanced Item Prototypes", _xMargin: 0, _showTitle: "title", _chromeStatus: "", + title: "Advanced Item Prototypes", _xMargin: 0, _showTitle: "title", _chromeHidden: true, hidden: ComputedField.MakeFunction("IsNoviceMode()") as any, _stayInCollection: true, _hideContextMenu: true, _autoHeight: true, _width: 500, _height: 300, _fitWidth: true, _columnWidth: 35, ignoreClick: true, _lockedPosition: true, @@ -367,7 +367,7 @@ export class CurrentUserUtils { }[] { if (doc.emptyPresentation === undefined) { doc.emptyPresentation = Docs.Create.PresDocument(new List(), - { title: "Untitled Presentation", _viewType: CollectionViewType.Stacking, _fitWidth: true, _width: 400, _height: 500, targetDropAction: "alias", _chromeStatus: "replaced", boxShadow: "0 0", system: true, cloneFieldFilter: new List(["system"]) }); + { title: "Untitled Presentation", _viewType: CollectionViewType.Stacking, _fitWidth: true, _width: 400, _height: 500, targetDropAction: "alias", _chromeHidden: true, boxShadow: "0 0", system: true, cloneFieldFilter: new List(["system"]) }); ((doc.emptyPresentation as Doc).proto as Doc)["dragFactory-count"] = 0; } if (doc.emptyCollection === undefined) { @@ -498,7 +498,7 @@ export class CurrentUserUtils { if (dragCreatorSet === undefined) { doc.myItemCreators = new PrefetchProxy(Docs.Create.MasonryDocument(creatorBtns, { - title: "Basic Item Creators", _showTitle: "title", _xMargin: 0, _stayInCollection: true, _hideContextMenu: true, _chromeStatus: "", + title: "Basic Item Creators", _showTitle: "title", _xMargin: 0, _stayInCollection: true, _hideContextMenu: true, _chromeHidden: true, _autoHeight: true, _width: 500, _height: 300, _fitWidth: true, _columnWidth: 35, ignoreClick: true, _lockedPosition: true, dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }), system: true })); @@ -559,7 +559,7 @@ export class CurrentUserUtils { doc.menuStack = new PrefetchProxy(Docs.Create.StackingDocument(menuBtns, { title: "menuItemPanel", childDropAction: "alias", - _chromeStatus: "", + _chromeHidden: true, dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }), backgroundColor: "black", ignoreClick: true, _gridGap: 0, @@ -597,7 +597,7 @@ export class CurrentUserUtils { // Sets up mobileMenu stacking document static setupMobileMenu() { const menu = new PrefetchProxy(Docs.Create.StackingDocument(this.setupMobileButtons(), { - _width: 980, ignoreClick: true, _lockedPosition: false, title: "home", _yMargin: 100, system: true, _chromeStatus: "" + _width: 980, ignoreClick: true, _lockedPosition: false, title: "home", _yMargin: 100, system: true, _chromeHidden: true, })); return menu; } @@ -691,13 +691,13 @@ export class CurrentUserUtils { static setupMobileUploadDoc(userDoc: Doc) { // const addButton = Docs.Create.FontIconDocument({ onDragStart: ScriptField.MakeScript('addWebToMobileUpload()'), title: "Add Web Doc to Upload Collection", icon: "plus", backgroundColor: "black" }) const webDoc = Docs.Create.WebDocument("https://www.britannica.com/biography/Miles-Davis", { - title: "Upload Images From the Web", _chromeStatus: "enabled", _lockedPosition: true, system: true + title: "Upload Images From the Web", _lockedPosition: true, system: true }); const uploadDoc = Docs.Create.StackingDocument([], { - title: "Mobile Upload Collection", backgroundColor: "white", _lockedPosition: true, system: true, _chromeStatus: "" + title: "Mobile Upload Collection", backgroundColor: "white", _lockedPosition: true, system: true, _chromeHidden: true, }); return Docs.Create.StackingDocument([webDoc, uploadDoc], { - _width: screen.width, _lockedPosition: true, title: "Upload", _autoHeight: true, _yMargin: 80, backgroundColor: "lightgray", system: true, _chromeStatus: "" + _width: screen.width, _lockedPosition: true, title: "Upload", _autoHeight: true, _yMargin: 80, backgroundColor: "lightgray", system: true, _chromeHidden: true, }); } @@ -717,14 +717,13 @@ export class CurrentUserUtils { if (doc.myCreators === undefined) { doc.myCreators = new PrefetchProxy(Docs.Create.StackingDocument([creatorBtns, templateBtns], { title: "all Creators", _yMargin: 0, _autoHeight: true, _xMargin: 0, _fitWidth: true, - _width: 500, _height: 300, ignoreClick: true, _lockedPosition: true, system: true, - _chromeStatus: "" + _width: 500, _height: 300, ignoreClick: true, _lockedPosition: true, system: true, _chromeHidden: true, })); } // setup a color picker if (doc.myColorPicker === undefined) { const color = Docs.Create.ColorDocument({ - title: "color picker", _width: 300, _dropAction: "alias", _hideContextMenu: true, _stayInCollection: true, _forceActive: true, _removeDropProperties: new List(["dropAction", "_stayInCollection", "_hideContextMenu", "forceActive"]), system: true + title: "color picker", _width: 220, _dropAction: "alias", _hideContextMenu: true, _stayInCollection: true, _forceActive: true, _removeDropProperties: new List(["dropAction", "_stayInCollection", "_hideContextMenu", "forceActive"]), system: true }); doc.myColorPicker = new PrefetchProxy(color); } @@ -732,7 +731,7 @@ export class CurrentUserUtils { if (doc.myTools === undefined) { const toolsStack = new PrefetchProxy(Docs.Create.StackingDocument([doc.myCreators as Doc, doc.myColorPicker as Doc], { title: "My Tools", _width: 500, _yMargin: 20, ignoreClick: true, _lockedPosition: true, _forceActive: true, - system: true, _stayInCollection: true, _hideContextMenu: true, _chromeStatus: "" + system: true, _stayInCollection: true, _hideContextMenu: true, _chromeHidden: true, })) as any as Doc; doc.myTools = toolsStack; @@ -910,8 +909,7 @@ export class CurrentUserUtils { if (!sharedDocs) { sharedDocs = Docs.Create.StackingDocument([], { title: "My SharedDocs", childDropAction: "alias", system: true, contentPointerEvents: "none", childLimitHeight: 0, _yMargin: 50, _gridGap: 15, - _showTitle: "title", ignoreClick: true, _lockedPosition: true, "acl-Public": SharingPermissions.Add, "_acl-Public": SharingPermissions.Add, - _chromeStatus: "" + _showTitle: "title", ignoreClick: true, _lockedPosition: true, "acl-Public": SharingPermissions.Add, "_acl-Public": SharingPermissions.Add, _chromeHidden: true, }, sharingDocumentId + "outer", sharingDocumentId); } if (sharedDocs instanceof Doc) { @@ -926,13 +924,13 @@ export class CurrentUserUtils { if (doc.myImportDocs === undefined) { doc.myImportDocs = new PrefetchProxy(Docs.Create.StackingDocument([], { title: "My ImportDocuments", _forceActive: true, ignoreClick: true, _showTitle: "title", _stayInCollection: true, _hideContextMenu: true, childLimitHeight: 0, - childDropAction: "alias", _autoHeight: true, _yMargin: 50, _gridGap: 15, _lockedPosition: true, system: true, _chromeStatus: "" + childDropAction: "alias", _autoHeight: true, _yMargin: 50, _gridGap: 15, _lockedPosition: true, system: true, _chromeHidden: true, })); } if (doc.myImportPanel === undefined) { const uploads = Cast(doc.myImportDocs, Doc, null); const newUpload = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("importDocument()"), toolTip: "Import External document", _stayInCollection: true, _hideContextMenu: true, title: "Import", icon: "upload", system: true }); - doc.myImportPanel = new PrefetchProxy(Docs.Create.StackingDocument([newUpload, uploads], { title: "My ImportPanel", _yMargin: 20, ignoreClick: true, _chromeStatus: "", _stayInCollection: true, _hideContextMenu: true, _lockedPosition: true, system: true })); + doc.myImportPanel = new PrefetchProxy(Docs.Create.StackingDocument([newUpload, uploads], { title: "My ImportPanel", _yMargin: 20, ignoreClick: true, _chromeHidden: true, _stayInCollection: true, _hideContextMenu: true, _lockedPosition: true, system: true })); } } diff --git a/src/client/util/Import & Export/DirectoryImportBox.tsx b/src/client/util/Import & Export/DirectoryImportBox.tsx index 244e96599..925b74efa 100644 --- a/src/client/util/Import & Export/DirectoryImportBox.tsx +++ b/src/client/util/Import & Export/DirectoryImportBox.tsx @@ -145,7 +145,7 @@ export class DirectoryImportBox extends React.Component { title: `Import of ${directory}`, _width: 1105, _height: 500, - _chromeStatus: "", + _chromeHidden: true, x: NumCast(doc.x), y: NumCast(doc.y) + offset }; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index c59c67574..4444a3944 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -101,7 +101,7 @@ export class MainView extends React.Component { } new InkStrokeProperties(); this._sidebarContent.proto = undefined; - DocServer.setPlaygroundFields(["x", "y", "dataTransition", "_autoHeight", "_showSidebar", "_sidebarWidthPercent", "_width", "_height", "_viewTransition", "_panX", "_panY", "_viewScale", "_scrollTop", "hidden", "_curPage", "_viewType", "_chromeStatus"]); // can play with these fields on someone else's + DocServer.setPlaygroundFields(["x", "y", "dataTransition", "_autoHeight", "_showSidebar", "_sidebarWidthPercent", "_width", "_height", "_viewTransition", "_panX", "_panY", "_viewScale", "_scrollTop", "hidden", "_curPage", "_viewType", "_chromeHidden"]); // can play with these fields on someone else's DocServer.GetRefField("rtfProto").then(proto => (proto instanceof Doc) && reaction(() => StrCast(proto.BROADCAST_MESSAGE), msg => msg && alert(msg))); @@ -232,7 +232,7 @@ export class MainView extends React.Component { })); } const pres = Docs.Create.PresDocument(new List(), - { title: "Untitled Presentation", _viewType: CollectionViewType.Stacking, _width: 400, _height: 500, targetDropAction: "alias", _chromeStatus: "replaced", boxShadow: "0 0" }); + { title: "Untitled Presentation", _viewType: CollectionViewType.Stacking, _width: 400, _height: 500, targetDropAction: "alias", _chromeHidden: true, boxShadow: "0 0" }); CollectionDockingView.AddSplit(pres, "right"); this.userDoc.activePresentation = pres; Doc.AddDocToList(this.userDoc.myPresentations as Doc, "data", pres); diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index 9afcdc28d..71f753d51 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -74,7 +74,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { return this.propertyToggleBtn("Caption", "_showCaption", on => `${on ? "Hide" : "Show"} caption footer`, on => "closed-captioning", (dv, doc) => (dv?.rootDoc || doc)._showCaption = (dv?.rootDoc || doc)._showCaption === undefined ? "caption" : undefined); } @computed get chromeButton() { - return this.propertyToggleBtn("Controls", "_chromeStatus", on => `${on === "enabled" ? "Hide" : "Show"} editing UI`, on => "edit", (dv, doc) => (dv?.rootDoc || doc)._chromeStatus = !(dv?.rootDoc || doc)._chromeStatus ? "enabled" : ""); + return this.propertyToggleBtn("Controls", "_chromeHidden", on => `${on ? "Show" : "Hide"} editing UI`, on => "edit", (dv, doc) => (dv?.rootDoc || doc)._chromeHidden = !(dv?.rootDoc || doc)._chromeHidden); } @computed get titleButton() { return this.propertyToggleBtn("Title", "_showTitle", on => "Switch between title styles", on => "text-width", (dv, doc) => (dv?.rootDoc || doc)._showTitle = !(dv?.rootDoc || doc)._showTitle ? "title" : (dv?.rootDoc || doc)._showTitle === "title" ? "title:hover" : undefined); @@ -165,8 +165,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { } @computed get onPerspectiveFlyout() { - const excludedViewTypes = Doc.UserDoc().noviceMode ? [CollectionViewType.Invalid, CollectionViewType.Docking, CollectionViewType.Pile, CollectionViewType.StackedTimeline, CollectionViewType.Stacking, CollectionViewType.Map, CollectionViewType.Linear] : - [CollectionViewType.Invalid, CollectionViewType.Docking, CollectionViewType.Pile, CollectionViewType.StackedTimeline, CollectionViewType.Linear]; + const excludedViewTypes = [CollectionViewType.Invalid, CollectionViewType.Docking, CollectionViewType.Pile, CollectionViewType.StackedTimeline, CollectionViewType.Linear]; const makeLabel = (value: string, label: string) =>
} - {/* {!this.chromeStatus || !this.props.isSelected() ? (null) : + {/* {this.chromeHidden || !this.props.isSelected() ? (null) : } */} diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 70ec1f925..caf4c59c1 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -32,7 +32,7 @@ interface CSVFieldColumnProps { docList: Doc[]; heading: string; pivotField: string; - chromeStatus: string; + chromeHidden?: boolean; columnHeaders: SchemaHeaderField[] | undefined; headingObject: SchemaHeaderField | undefined; yMargin: number; @@ -249,8 +249,7 @@ export class CollectionStackingViewFieldColumn extends React.Component
{/* the default bucket (no key value) has a tooltip that describes what it is. @@ -307,7 +306,7 @@ export class CollectionStackingViewFieldColumn extends React.Component {this.props.renderChildren(this.props.docList)}
- {(this.props.chromeStatus !== 'view-mode' && this.props.chromeStatus && type !== DocumentType.PRES) ? + {!this.props.chromeHidden && type !== DocumentType.PRES ?
doc) { } return
+ style={{ width: this.props.PanelWidth(), height: "100%" }}> {this.pivotKeyUI} {this.contents} {!this.props.isSelected() || !doTimeline ? (null) : <> diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 34fd20f1a..535bf539e 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -71,6 +71,7 @@ export interface CollectionViewProps extends FieldViewProps { // property overrides for child documents children?: never | (() => JSX.Element[]) | React.ReactNode; childDocuments?: Doc[]; // used to override the documents shown by the sub collection to an explicit list (see LinkBox) + childFitWidth?: () => boolean; childOpacity?: () => number; childHideTitle?: () => boolean; // whether to hide the documentdecorations title for children childHideDecorationTitle?: () => boolean; diff --git a/src/client/views/collections/SchemaTable.tsx b/src/client/views/collections/SchemaTable.tsx index d26f53e28..4005c751e 100644 --- a/src/client/views/collections/SchemaTable.tsx +++ b/src/client/views/collections/SchemaTable.tsx @@ -559,8 +559,7 @@ export class SchemaTable extends React.Component { onPointerDown={this.props.onPointerDown} onClick={this.props.onClick} onWheel={e => this.props.active(true) && e.stopPropagation()} onDrop={e => this.props.onDrop(e, {})} onContextMenu={this.onContextMenu} > {this.reactTable} - {this.props.Document._chromeStatus ?
this.createRow()}>+ new
- : undefined} + {this.props.Document._chromeHidden ? undefined :
this.createRow()}>+ new
} {!this._showDoc ? (null) :
{ - const targetDoc = view.props.Document.dragFactory instanceof Doc ? view.props.Document.dragFactory : - view.props.Document.layout instanceof Doc ? view.props.Document.layout : - view.props.Document.isTemplateForField ? view.props.Document : Doc.GetProto(view.props.Document); - if (targetDoc) { - if (view.props.LayoutTemplate?.() || view.props.LayoutTemplateString) { // this situation typically occurs when you have a link dot - targetDoc.backgroundColor = Doc.UserDoc().backgroundColor; // bcz: don't know how to change the color of an inline template... - } - else if (RichTextMenu.Instance?.TextViewFieldKey && window.getSelection()?.toString() !== "") { - Doc.Layout(view.props.Document)[RichTextMenu.Instance.TextViewFieldKey + "-color"] = Doc.UserDoc().backgroundColor; - } else { - Doc.Layout(view.props.Document)._backgroundColor = Doc.UserDoc().backgroundColor; // '_backgroundColor' is template specific. 'backgroundColor' would apply to all templates, but has no UI at the moment - } + SelectionManager.Views().map(view => { + const targetDoc = view.props.Document.dragFactory instanceof Doc ? view.props.Document.dragFactory : + view.props.Document.layout instanceof Doc ? view.props.Document.layout : + view.props.Document.isTemplateForField ? view.props.Document : Doc.GetProto(view.props.Document); + if (targetDoc) { + if (view.props.LayoutTemplate?.() || view.props.LayoutTemplateString) { // this situation typically occurs when you have a link dot + targetDoc.backgroundColor = Doc.UserDoc().backgroundColor; // bcz: don't know how to change the color of an inline template... } - }); - } + else if (RichTextMenu.Instance?.TextViewFieldKey && window.getSelection()?.toString() !== "") { + Doc.Layout(view.props.Document)[RichTextMenu.Instance.TextViewFieldKey + "-color"] = Doc.UserDoc().backgroundColor; + } else { + Doc.Layout(view.props.Document)._backgroundColor = Doc.UserDoc().backgroundColor; // '_backgroundColor' is template specific. 'backgroundColor' would apply to all templates, but has no UI at the moment + } + } + }); } - constructor(props: any) { - super(props); - } render() { - const selDoc = SelectionManager.Views()?.[0]?.rootDoc; + const scaling = Math.min(this.layoutDoc.fitWidth ? 10000 : this.props.PanelHeight() / this.rootDoc[HeightSym](), this.props.PanelWidth() / this.rootDoc[WidthSym]()); return
e.button === 0 && !e.ctrlKey && e.stopPropagation()} onClick={e => { (e.nativeEvent as any).stuff = true; e.stopPropagation(); }} - style={{ width: `${100}%`, height: `${100}%` }} > + onPointerDown={e => e.button === 0 && !e.ctrlKey && e.stopPropagation()} onClick={e => e.stopPropagation()} + style={{ transform: `scale(${scaling})`, width: `${100 * scaling}%`, height: `${100 * scaling}%` }} > - + CurrentUserUtils.SelectedTool === InkTool.None && ColorBox.switchColor(c)} + color={StrCast(SelectionManager.Views()?.[0]?.rootDoc?._backgroundColor, ActiveInkColor())} + presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', + '#000000', '#4A4A4A', '#9B9B9B', '#FFFFFF', '#f1efeb', 'transparent']} + /> -
-
{ActiveInkWidth() ?? 2}
- ) => { +
+
{ActiveInkWidth()}
+ ) => { SetActiveInkWidth(e.target.value); SelectionManager.Views().filter(i => StrCast(i.rootDoc.type) === DocumentType.INK).map(i => i.rootDoc.strokeWidth = Number(e.target.value)); }} /> - {/*
{ActiveInkBezierApprox() ?? 2}
- ) => { - SetActiveBezierApprox(e.target.value); - SelectionManager.SelectedDocuments().filter(i => StrCast(i.rootDoc.type) === DocumentType.INK).map(i => i.rootDoc.strokeBezier = e.target.value); - }} /> */} -
-
; } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index e15ade241..6d18f5f3e 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -101,6 +101,7 @@ export interface DocumentViewSharedProps { layerProvider: undefined | ((doc: Doc, assign?: boolean) => boolean); styleProvider: Opt; focus: DocFocusFunc; + fitWidth?: () => boolean; docFilters: () => string[]; docRangeFilters: () => string[]; searchFilterDocs: () => Doc[]; @@ -340,7 +341,7 @@ export class DocumentViewInternal extends DocComponent SharingManager.Instance.open(this.props.DocumentView()), icon: "users" }); if (!Doc.UserDoc().noviceMode) { moreItems.push({ description: "Make View of Metadata Field", event: () => Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.DataDoc), icon: "concierge-bell" }); - moreItems.push({ description: `${this.Document._chromeStatus ? "Hide" : "Show"} Chrome`, event: () => this.Document._chromeStatus = (this.Document._chromeStatus ? "" : "enabled"), icon: "project-diagram" }); + moreItems.push({ description: `${this.Document._chromeHidden ? "Show" : "Hide"} Chrome`, event: () => this.Document._chromeHidden = !this.Document._chromeHidden, icon: "project-diagram" }); if (Cast(Doc.GetProto(this.props.Document).data, listSpec(Doc))) { moreItems.push({ description: "Export to Google Photos Album", event: () => GooglePhotos.Export.CollectionToAlbum({ collection: this.props.Document }).then(console.log), icon: "caret-square-right" }); @@ -994,6 +995,7 @@ export class DocumentView extends React.Component { get ComponentView() { return this.docView?._componentView; } get allLinks() { return this.docView?.allLinks || []; } get LayoutFieldKey() { return this.docView?.LayoutFieldKey || "layout"; } + get fitWidth() { return this.props.fitWidth?.() || this.layoutDoc.fitWidth; } @computed get docViewPath() { return this.props.docViewPath ? [...this.props.docViewPath(), this] : [this]; } @computed get layoutDoc() { return Doc.Layout(this.Document, this.props.LayoutTemplate?.()); } @@ -1005,13 +1007,13 @@ export class DocumentView extends React.Component { return this.docView?._componentView?.reverseNativeScaling?.() ? 0 : returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.DataDoc, this.props.freezeDimensions)); } - @computed get shouldNotScale() { return (this.layoutDoc._fitWidth && !this.nativeWidth) || [CollectionViewType.Docking, CollectionViewType.Tree].includes(this.Document._viewType as any); } + @computed get shouldNotScale() { return (this.fitWidth && !this.nativeWidth) || [CollectionViewType.Docking, CollectionViewType.Tree].includes(this.Document._viewType as any); } @computed get effectiveNativeWidth() { return this.shouldNotScale ? 0 : (this.nativeWidth || NumCast(this.layoutDoc.width)); } @computed get effectiveNativeHeight() { return this.shouldNotScale ? 0 : (this.nativeHeight || NumCast(this.layoutDoc.height)); } @computed get nativeScaling() { if (this.shouldNotScale) return 1; const minTextScale = this.Document.type === DocumentType.RTF ? 0.1 : 0; - if (this.layoutDoc._fitWidth || this.props.PanelHeight() / this.effectiveNativeHeight > this.props.PanelWidth() / this.effectiveNativeWidth) { + if (this.fitWidth || this.props.PanelHeight() / this.effectiveNativeHeight > this.props.PanelWidth() / this.effectiveNativeWidth) { return Math.max(minTextScale, this.props.PanelWidth() / this.effectiveNativeWidth); // width-limited or fitWidth } return Math.max(minTextScale, this.props.PanelHeight() / this.effectiveNativeHeight); // height-limited or unscaled @@ -1027,7 +1029,7 @@ export class DocumentView extends React.Component { @computed get Xshift() { return this.effectiveNativeWidth ? (this.props.PanelWidth() - this.effectiveNativeWidth * this.nativeScaling) / 2 : 0; } @computed get Yshift() { return this.effectiveNativeWidth && this.effectiveNativeHeight && Math.abs(this.Xshift) < 0.001 ? (this.props.PanelHeight() - this.effectiveNativeHeight * this.nativeScaling) / 2 : 0; } @computed get centeringX() { return this.props.dontCenter?.includes("x") ? 0 : this.Xshift; } - @computed get centeringY() { return this.props.Document._fitWidth || this.props.dontCenter?.includes("y") ? 0 : this.Yshift; } + @computed get centeringY() { return this.fitWidth || this.props.dontCenter?.includes("y") ? 0 : this.Yshift; } toggleNativeDimensions = () => this.docView && Doc.toggleNativeDimensions(this.layoutDoc, this.docView.ContentScale, this.props.PanelWidth(), this.props.PanelHeight()); contentsActive = () => this.docView?.contentsActive(); @@ -1109,7 +1111,7 @@ export class DocumentView extends React.Component { position: this.props.Document.isInkMask ? "absolute" : undefined, transform: `translate(${this.centeringX}px, ${this.centeringY}px)`, width: xshift ?? `${100 * (this.props.PanelWidth() - this.Xshift * 2) / this.props.PanelWidth()}%`, - height: yshift ?? (this.props.Document._fitWidth ? `${this.panelHeight}px` : + height: yshift ?? (this.fitWidth ? `${this.panelHeight}px` : `${100 * this.effectiveNativeHeight / this.effectiveNativeWidth * this.props.PanelWidth() / this.props.PanelHeight()}%`), }}> { } getTemplate = async () => { - const parent = Docs.Create.StackingDocument([], { _width: 800, _height: 800, title: "Template", _chromeStatus: "" }); + const parent = Docs.Create.StackingDocument([], { _width: 800, _height: 800, title: "Template", _chromeHidden: true }); parent._columnWidth = 100; for (const row of this.rows.filter(row => row.isChecked)) { await this.createTemplateField(parent, row); diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 3c1fda465..88406b181 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -13,7 +13,7 @@ import { PrefetchProxy } from "../../../fields/Proxy"; import { listSpec, makeInterface } from "../../../fields/Schema"; import { ScriptField } from "../../../fields/ScriptField"; import { BoolCast, Cast, NumCast, StrCast } from "../../../fields/Types"; -import { returnFalse, returnOne } from "../../../Utils"; +import { returnFalse, returnOne, returnTrue } from '../../../Utils'; import { Docs } from "../../documents/Documents"; import { DocumentType } from "../../documents/DocumentTypes"; import { CurrentUserUtils } from "../../util/CurrentUserUtils"; @@ -195,7 +195,6 @@ export class PresBox extends ViewBoxBaseComponent componentDidMount() { this.rootDoc.presBox = this.rootDoc; this.rootDoc._forceRenderEngine = "timeline"; - this.rootDoc._replacedChrome = "replaced"; this.layoutDoc.presStatus = PresStatus.Edit; this.layoutDoc._gridGap = 0; this.layoutDoc._yMargin = 0; @@ -2262,7 +2261,7 @@ export class PresBox extends ViewBoxBaseComponent const mode = StrCast(this.rootDoc._viewType) as CollectionViewType; const isMini: boolean = this.toolbarWidth <= 100; return ( -
+
{isMini ? (null) :