From ded69655dabf97c76f97271e7da8e77e3f33ec25 Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 15 Mar 2021 03:36:35 -0400 Subject: getting webBox's to work like PdfBox's - text selection & marquee. --- src/client/documents/Documents.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/client/documents/Documents.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 2ed69a993..8059509ab 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -180,7 +180,6 @@ export class DocumentOptions { templates?: List; hero?: ImageField; // primary image that best represents a compound document (e.g., for a buxton device document that has multiple images) caption?: RichTextField; - isAnnotating?: boolean; // whether we web document is annotation mode where links can't be clicked to allow annotations to be created opacity?: number; defaultBackgroundColor?: string; isLinkButton?: boolean; @@ -823,7 +822,7 @@ export namespace Docs { 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 ? "disabled" : "enabled", isAnnotating: false, _lockedTransform: true, ...options }); + return InstanceFromProto(webProto, url ? new WebField(new URL(url)) : undefined, { _chromeStatus: url ? "disabled" : "enabled", _lockedTransform: true, ...options }); } export function HtmlDocument(html: string, options: DocumentOptions = {}) { -- cgit v1.2.3-70-g09d2 From ecaf1da499b41d0f873c64cb128118a6a291229e Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 15 Mar 2021 23:42:19 -0400 Subject: fixed warnings. made savedAnnotations an ObservableMap. turned off annotationLayer when there are no annotations - text is blurry on windows Chrome with mix-blend-mode overlay --- src/Utils.ts | 22 ++++++------ src/client/documents/Documents.ts | 2 +- src/client/util/DragManager.ts | 4 +-- src/client/views/LightboxView.tsx | 7 ++-- src/client/views/MarqueeAnnotator.tsx | 41 +++++++++++----------- .../views/collections/CollectionDockingView.tsx | 2 +- src/client/views/nodes/ImageBox.tsx | 18 +++++++--- src/client/views/nodes/WebBox.tsx | 17 +++++---- .../views/nodes/formattedText/FormattedTextBox.tsx | 2 +- src/client/views/pdf/PDFViewer.tsx | 11 +++--- 10 files changed, 70 insertions(+), 56 deletions(-) (limited to 'src/client/documents/Documents.ts') diff --git a/src/Utils.ts b/src/Utils.ts index d2713762d..dab3548b3 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -484,12 +484,12 @@ const easeInOutQuad = (currentTime: number, start: number, change: number, durat export function smoothScroll(duration: number, element: HTMLElement | HTMLElement[], to: number) { const elements = (element instanceof HTMLElement ? [element] : element); - let starts = elements.map(element => element.scrollTop); - let startDate = new Date().getTime(); + const starts = elements.map(element => element.scrollTop); + const startDate = new Date().getTime(); const animateScroll = () => { const currentDate = new Date().getTime(); - let currentTime = currentDate - startDate; + const currentTime = currentDate - startDate; elements.map((element, i) => element.scrollTop = easeInOutQuad(currentTime, starts[i], to - starts[i], duration)); if (currentTime < duration) { @@ -599,12 +599,12 @@ export function lightOrDark(color: any) { } -export function getWordAtPoint(elem: any, x: number, y: number): Opt { - if (elem.nodeType == elem.TEXT_NODE) { +export function getWordAtPoint(elem: any, x: number, y: number): string | undefined { + if (elem.nodeType === elem.TEXT_NODE) { var range = elem.ownerDocument.createRange(); range.selectNodeContents(elem); var currentPos = 0; - var endPos = range.endOffset; + const endPos = range.endOffset; while (currentPos + 1 < endPos) { range.setStart(elem, currentPos); range.setEnd(elem, currentPos + 1); @@ -612,21 +612,21 @@ export function getWordAtPoint(elem: any, x: number, y: number): Opt { if (rangeRect.left <= x && rangeRect.right >= x && rangeRect.top <= y && rangeRect.bottom >= y) { range.expand("word"); - var ret = range.toString(); + const ret = range.toString(); range.detach(); return (ret); } currentPos += 1; } } else { - for (var i = 0; i < elem.childNodes.length; i++) { - var range = elem.childNodes[i].ownerDocument.createRange(); - range.selectNodeContents(elem.childNodes[i]); + for (let childNode of elem.childNodes) { + const range = childNode.ownerDocument.createRange(); + range.selectNodeContents(childNode); const rangeRect = range.getBoundingClientRect(); if (rangeRect.left <= x && rangeRect.right >= x && rangeRect.top <= y && rangeRect.bottom >= y) { range.detach(); - const word = getWordAtPoint(elem.childNodes[i], x, y); + const word = getWordAtPoint(childNode, x, y); if (word) return word; } else { range.detach(); diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 8059509ab..6e892cb6e 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -324,7 +324,7 @@ export namespace Docs { }], [DocumentType.WEB, { layout: { view: WebBox, dataField: defaultDataKey }, - options: { _height: 300, scrollHeight: 100000, _fitWidth: true } + options: { _height: 300, _fitWidth: true } }], [DocumentType.COL, { layout: { view: CollectionView, dataField: defaultDataKey }, diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 0d154bc3a..dc95193ea 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -157,8 +157,8 @@ export namespace DragManager { // used by PDFs,Text,Image,Video,Web to conditionally (if the drop completes) create a text annotation when dragging the annotate button from the AnchorMenu when a text/region selection has been made. // this is pretty clunky and should be rethought out using linkDrag or DocumentDrag export class AnchorAnnoDragData extends LinkDragData { - constructor(dragDoc: Doc, linkSourceGetAnchor: () => Doc, dropDocCreator: (annotationOn: Doc | undefined) => Doc) { - super(dragDoc, linkSourceGetAnchor); + constructor(dragView: DocumentView, linkSourceGetAnchor: () => Doc, dropDocCreator: (annotationOn: Doc | undefined) => Doc) { + super(dragView, linkSourceGetAnchor); this.dropDocCreator = dropDocCreator; this.offset = [0, 0]; } diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx index 9b14c180e..731d46502 100644 --- a/src/client/views/LightboxView.tsx +++ b/src/client/views/LightboxView.tsx @@ -30,15 +30,16 @@ export class LightboxView extends React.Component { @observable private static _docTarget: Opt; @observable private static _docFilters: string[] = []; // filters @observable private static _tourMap: Opt = []; // list of all tours available from the current target - private static _savedState: Opt<{ panX: Opt, panY: Opt, scale: Opt }>; + private static _savedState: Opt<{ panX: Opt, panY: Opt, scale: Opt, scrollTop: Opt }>; private static _history: Opt<{ doc: Doc, target?: Doc }[]> = []; private static _future: Opt = []; private static _docView: Opt; - static path: { doc: Opt, target: Opt, history: Opt<{ doc: Doc, target?: Doc }[]>, future: Opt, saved: Opt<{ panX: Opt, panY: Opt, scale: Opt }> }[] = []; + static path: { doc: Opt, target: Opt, history: Opt<{ doc: Doc, target?: Doc }[]>, future: Opt, saved: Opt<{ panX: Opt, panY: Opt, scale: Opt, scrollTop: Opt }> }[] = []; @action public static SetLightboxDoc(doc: Opt, target?: Doc, future?: Doc[]) { if (this.LightboxDoc && this.LightboxDoc !== doc && this._savedState) { this.LightboxDoc._panX = this._savedState.panX; this.LightboxDoc._panY = this._savedState.panY; + this.LightboxDoc._scrollTop = this._savedState.scrollTop; this.LightboxDoc._viewScale = this._savedState.scale; this.LightboxDoc._viewTransition = undefined; } @@ -53,6 +54,7 @@ export class LightboxView extends React.Component { panX: Cast(doc._panX, "number", null), panY: Cast(doc._panY, "number", null), scale: Cast(doc._viewScale, "number", null), + scrollTop: Cast(doc._scrollTop, "number", null), }; } } @@ -123,6 +125,7 @@ export class LightboxView extends React.Component { LightboxView.LightboxDoc._panX = saved.panX; LightboxView.LightboxDoc._panY = saved.panY; LightboxView.LightboxDoc._viewScale = saved.scale; + LightboxView.LightboxDoc._scrollTop = saved.scrollTop; LightboxView.LightboxDoc._viewTransition = undefined; } const pop = LightboxView.path.pop(); diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx index 77ace7ddb..1e97f9b41 100644 --- a/src/client/views/MarqueeAnnotator.tsx +++ b/src/client/views/MarqueeAnnotator.tsx @@ -1,22 +1,22 @@ -import { action, observable, runInAction } from "mobx"; +import { action, observable, runInAction, ObservableMap } from "mobx"; import { observer } from "mobx-react"; import { Dictionary } from "typescript-collections"; import { AclAddonly, AclAdmin, AclEdit, DataSym, Doc, Opt } from "../../fields/Doc"; import { Id } from "../../fields/FieldSymbols"; +import { List } from "../../fields/List"; +import { NumCast } from "../../fields/Types"; import { GetEffectiveAcl } from "../../fields/util"; -import { DocUtils, Docs } from "../documents/Documents"; +import { Utils } from "../../Utils"; +import { Docs } from "../documents/Documents"; +import { DocumentType } from "../documents/DocumentTypes"; import { CurrentUserUtils } from "../util/CurrentUserUtils"; import { DragManager } from "../util/DragManager"; +import { undoBatch } from "../util/UndoManager"; +import "./MarqueeAnnotator.scss"; +import { DocumentView } from "./nodes/DocumentView"; import { FormattedTextBox } from "./nodes/formattedText/FormattedTextBox"; import { AnchorMenu } from "./pdf/AnchorMenu"; -import "./MarqueeAnnotator.scss"; import React = require("react"); -import { undoBatch } from "../util/UndoManager"; -import { NumCast } from "../../fields/Types"; -import { DocumentType } from "../documents/DocumentTypes"; -import { List } from "../../fields/List"; -import { Utils } from "../../Utils"; -import { util } from "chai"; const _global = (window /* browser */ || global /* node */) as any; export interface MarqueeAnnotatorProps { @@ -26,7 +26,8 @@ export interface MarqueeAnnotatorProps { scaling?: () => number; containerOffset?: () => number[]; mainCont: HTMLDivElement; - savedAnnotations: Dictionary; + docView: DocumentView; + savedAnnotations: ObservableMap; annotationLayer: HTMLDivElement; addDocument: (doc: Doc) => boolean; getPageFromScroll?: (top: number) => number; @@ -48,7 +49,7 @@ export class MarqueeAnnotator extends React.Component { AnchorMenu.Instance.Status = "marquee"; AnchorMenu.Instance.fadeOut(true); // clear out old marquees and initialize menu for new selection - this.props.savedAnnotations.values().forEach(v => v.forEach(a => a.remove())); + Array.from(this.props.savedAnnotations.values()).forEach(v => v.forEach(a => a.remove())); this.props.savedAnnotations.clear(); }); } @@ -81,7 +82,7 @@ export class MarqueeAnnotator extends React.Component { FormattedTextBox.SelectOnLoad = target[Id]; return target; }; - DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(this.props.rootDoc, sourceAnchorCreator, targetCreator), e.pageX, e.pageY, { + DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(this.props.docView, sourceAnchorCreator, targetCreator), e.pageX, e.pageY, { dragComplete: e => { if (!e.aborted && e.annoDragData && e.annoDragData.linkSourceDoc && e.annoDragData.dropDocument && e.linkDocument) { e.annoDragData.linkSourceDoc.isPushpin = e.annoDragData.dropDocument.annotationOn === this.props.rootDoc; @@ -98,10 +99,10 @@ export class MarqueeAnnotator extends React.Component { @undoBatch @action makeAnnotationDocument = (color: string): Opt => { - if (this.props.savedAnnotations.size() === 0) return undefined; - if ((this.props.savedAnnotations.values()[0][0] as any).marqueeing) { + if (this.props.savedAnnotations.size === 0) return undefined; + if ((Array.from(this.props.savedAnnotations.values())[0][0] as any).marqueeing) { const scale = this.props.scaling?.() || 1; - const anno = this.props.savedAnnotations.values()[0][0]; + const anno = Array.from(this.props.savedAnnotations.values())[0][0]; const containerOffset = this.props.containerOffset?.() || [0, 0]; const marqueeAnno = Docs.Create.FreeformDocument([], { backgroundColor: color, annotationOn: this.props.rootDoc, title: "Annotation on " + this.props.rootDoc.title }); marqueeAnno.x = (parseInt(anno.style.left || "0") - containerOffset[0]) / scale; @@ -117,7 +118,7 @@ export class MarqueeAnnotator extends React.Component { let maxX = -Number.MAX_VALUE; let minY = Number.MAX_VALUE; const annoDocs: Doc[] = []; - this.props.savedAnnotations.forEach((key: number, value: HTMLDivElement[]) => value.map(anno => { + this.props.savedAnnotations.forEach((value: HTMLDivElement[], key: number) => value.map(anno => { const textRegion = new Doc(); textRegion.x = parseInt(anno.style.left ?? "0"); textRegion.y = parseInt(anno.style.top ?? "0"); @@ -149,20 +150,20 @@ export class MarqueeAnnotator extends React.Component { return annotationDoc as Doc ?? undefined; } - public static previewNewAnnotation = action((savedAnnotations: Dictionary, annotationLayer: HTMLDivElement, div: HTMLDivElement, page: number) => { + public static previewNewAnnotation = action((savedAnnotations: ObservableMap, annotationLayer: HTMLDivElement, div: HTMLDivElement, page: number) => { if (div.style.top) { div.style.top = (parseInt(div.style.top)/*+ this.getScrollFromPage(page)*/).toString(); } annotationLayer.append(div); div.style.backgroundColor = "#ACCEF7"; div.style.opacity = "0.5"; - const savedPage = savedAnnotations.getValue(page); + const savedPage = savedAnnotations.get(page); if (savedPage) { savedPage.push(div); - savedAnnotations.setValue(page, savedPage); + savedAnnotations.set(page, savedPage); } else { - savedAnnotations.setValue(page, [div]); + savedAnnotations.set(page, [div]); } }); diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 3556e74bc..b9757dde3 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -381,7 +381,7 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) { const otherSet = new Set(); otherdocs?.filter(doc => !docs.includes(doc)).forEach(doc => otherSet.add(doc)); tabdocs?.filter(doc => !docs.includes(doc) && doc.type !== DocumentType.KVP).forEach(doc => otherSet.add(doc)); - const vals = Array.from(otherSet.values()).filter(val => val instanceof Doc).map(d => d as Doc).filter(d => d.type !== DocumentType.KVP); + const vals = Array.from(otherSet.values()).filter(val => val instanceof Doc).map(d => d).filter(d => d.type !== DocumentType.KVP); other && (Doc.GetProto(other).data = new List(vals)); }, 0); } diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index bc01acdfd..0be0b5f30 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -1,4 +1,4 @@ -import { action, computed, IReactionDisposer, observable, reaction, runInAction } from 'mobx'; +import { action, computed, IReactionDisposer, observable, reaction, runInAction, ObservableMap } from 'mobx'; import { observer } from "mobx-react"; import { Dictionary } from 'typescript-collections'; import { DataSym, Doc, DocListCast, WidthSym } from '../../../fields/Doc'; @@ -63,7 +63,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent this.props.isSelected(), selected => !selected && setTimeout(() => { - this._savedAnnotations.values().forEach(v => v.forEach(a => a.remove())); + Array.from(this._savedAnnotations.values()).forEach(v => v.forEach(a => a.remove())); this._savedAnnotations.clear(); })); this._disposers.path = reaction(() => ({ nativeSize: this.nativeSize, width: this.layoutDoc[WidthSym]() }), @@ -337,7 +337,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent = React.createRef(); private _annotationLayer: React.RefObject = React.createRef(); @observable _marqueeing: number[] | undefined; - @observable _savedAnnotations: Dictionary = new Dictionary(); + @observable _savedAnnotations = new ObservableMap(); @computed get annotationLayer() { return
; } @@ -388,7 +388,17 @@ export class ImageBox extends ViewBoxAnnotatableComponent {this.annotationLayer} {!this._marqueeing || !this._mainCont.current || !this._annotationLayer.current ? (null) : - } + }
); } + } diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 19a5945e2..bc20c3b47 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -1,5 +1,5 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx"; +import { action, computed, IReactionDisposer, observable, reaction, runInAction, ObservableMap } from "mobx"; import { observer } from "mobx-react"; import { Dictionary } from "typescript-collections"; import * as WebRequest from 'web-request'; @@ -58,7 +58,7 @@ export class WebBox extends ViewBoxAnnotatableComponent = new Dictionary(); + @observable private _savedAnnotations = new ObservableMap(); @observable private _scrollHeight = 1500; @computed get scrollHeight() { return this._scrollHeight; } @computed get inlineTextAnnotations() { return this.allAnnotations.filter(a => a.textInlineAnnotations); } @@ -111,7 +111,7 @@ export class WebBox extends ViewBoxAnnotatableComponent iframeHeight) - this.layoutDoc._scrollTop = this._outerRef.current.scrollTop = iframeHeight; - else this.layoutDoc._scrollTop = this._outerRef.current.scrollTop = scrollTop; + this.layoutDoc._scrollTop = this._outerRef.current.scrollTop = scrollTop > iframeHeight ? iframeHeight : scrollTop; } }), timeout); } @@ -194,7 +192,7 @@ export class WebBox extends ViewBoxAnnotatableComponent this.props.isSelected(), selected => !selected && setTimeout(() => { - this._savedAnnotations.values().forEach(v => v.forEach(a => a.remove())); + Array.from(this._savedAnnotations.values()).forEach(v => v.forEach(a => a.remove())); this._savedAnnotations.clear(); })); @@ -515,7 +513,7 @@ export class WebBox extends ViewBoxAnnotatableComponent + return
{this.inlineTextAnnotations.sort((a, b) => NumCast(a.y) - NumCast(b.y)).map(anno => ) } @@ -590,6 +588,7 @@ export class WebBox extends ViewBoxAnnotatableComponent(PdfDocument) { static _annotationStyle: any = addStyleSheet(); @observable private _pageSizes: { width: number, height: number }[] = []; - @observable private _savedAnnotations: Dictionary = new Dictionary(); + @observable private _savedAnnotations = new ObservableMap(); @observable private _script: CompiledScript = CompileScript("return true") as CompiledScript; @observable private _marqueeing: number[] | undefined; @observable private _textSelecting = true; @@ -140,8 +140,8 @@ export class PDFViewer extends ViewBoxAnnotatableComponent this.props.isSelected(), selected => { if (!selected) { - this._savedAnnotations.values().forEach(v => v.forEach(a => a.remove())); - this._savedAnnotations.keys().forEach(k => this._savedAnnotations.setValue(k, [])); + Array.from(this._savedAnnotations.values()).forEach(v => v.forEach(a => a.remove())); + Array.from(this._savedAnnotations.keys()).forEach(k => this._savedAnnotations.set(k, [])); } (SelectionManager.Views().length === 1) && this.setupPdfJsViewer(); }, @@ -390,7 +390,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent this._marqueeing = undefined), 100); // bcz: hack .. anchor menu is setup within MarqueeAnnotator so we need to at least create the marqueeAnnotator even though we aren't using it. // clear out old marquees and initialize menu for new selection AnchorMenu.Instance.Status = "marquee"; - this._savedAnnotations.values().forEach(v => v.forEach(a => a.remove())); + Array.from(this._savedAnnotations.values()).forEach(v => v.forEach(a => a.remove())); this._savedAnnotations.clear(); this._styleRule = addStyleSheetRule(PDFViewer._annotationStyle, "pdfAnnotation", { "pointer-events": "none" }); document.addEventListener("pointerup", this.onSelectEnd); @@ -574,6 +574,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent} -- cgit v1.2.3-70-g09d2 From 82f319ddf3e70095b04473ecce8790f4524e8939 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 16 Mar 2021 12:03:20 -0400 Subject: cleaned up propertiesbuttons a bit. added lockTransform button. changed chromeStatus disabled to be undefined. --- src/client/documents/Documents.ts | 2 +- src/client/util/CurrentUserUtils.ts | 37 ++- src/client/views/InkingStroke.tsx | 2 - src/client/views/PropertiesButtons.tsx | 300 ++++++--------------- src/client/views/TemplateMenu.tsx | 4 +- .../collections/CollectionMasonryViewFieldRow.tsx | 4 +- .../views/collections/CollectionPileView.tsx | 2 +- src/client/views/collections/SchemaTable.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 5 - src/client/views/nodes/DocumentView.tsx | 4 +- src/client/views/nodes/PresBox.tsx | 2 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 2 +- 12 files changed, 107 insertions(+), 259 deletions(-) (limited to 'src/client/documents/Documents.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 6e892cb6e..71fc5c40d 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -822,7 +822,7 @@ export namespace Docs { 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 ? "disabled" : "enabled", _lockedTransform: true, ...options }); + return InstanceFromProto(webProto, url ? new WebField(new URL(url)) : undefined, { _chromeStatus: url ? undefined : "enabled", _lockedTransform: true, ...options }); } export function HtmlDocument(html: string, options: DocumentOptions = {}) { diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 9dda90353..6566f5f78 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -81,7 +81,7 @@ export class CurrentUserUtils { Docs.Create.MulticolumnDocument([], { title: "data", _height: 200, system: true }), Docs.Create.TextDocument("", { title: "text", _height: 100, system: true }) ], - { _width: 400, _height: 300, title: "slideView", _chromeStatus: "disabled", _xMargin: 3, _yMargin: 3, system: true } + { _width: 400, _height: 300, title: "slideView", _xMargin: 3, _yMargin: 3, system: true } ); slideTemplate.isTemplateDoc = makeTemplate(slideTemplate); doc["template-button-slides"] = CurrentUserUtils.ficon({ @@ -193,7 +193,7 @@ export class CurrentUserUtils { }; details.text = new RichTextField(JSON.stringify(detailedTemplate), buxtonFieldKeys.join(" ")); - const shared = { _chromeStatus: "disabled", _autoHeight: true, _xMargin: 0 }; + const shared = { _autoHeight: true, _xMargin: 0 }; const detailViewOpts = { title: "detailView", _width: 300, _fontFamily: "Arial", _fontSize: "12px" }; const descriptionWrapperOpts = { title: "descriptions", _height: 300, _columnWidth: -1, treeViewHideTitle: true, _pivotField: "title", system: true }; @@ -228,7 +228,7 @@ export class CurrentUserUtils { title: "Advanced Item Prototypes", _xMargin: 0, _showTitle: "title", hidden: ComputedField.MakeFunction("IsNoviceMode()") as any, _stayInCollection: true, _hideContextMenu: true, - _autoHeight: true, _width: 500, _height: 300, _fitWidth: true, _columnWidth: 35, ignoreClick: true, _lockedPosition: true, _chromeStatus: "disabled", + _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 })); } else { @@ -499,7 +499,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, - _autoHeight: true, _width: 500, _height: 300, _fitWidth: true, _columnWidth: 35, ignoreClick: true, _lockedPosition: true, _chromeStatus: "disabled", + _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 })); } else { @@ -528,7 +528,7 @@ export class CurrentUserUtils { if (doc.mySearchPanelDoc === undefined) { doc.mySearchPanelDoc = new PrefetchProxy(Docs.Create.SearchDocument({ _width: 500, _height: 300, backgroundColor: "dimGray", ignoreClick: true, _searchDoc: true, - childDropAction: "alias", _lockedPosition: true, _viewType: CollectionViewType.Schema, _chromeStatus: "disabled", title: "sidebar search stack", system: true + childDropAction: "alias", _lockedPosition: true, _viewType: CollectionViewType.Schema, title: "sidebar search stack", system: true })) as any as Doc; } } @@ -563,7 +563,7 @@ export class CurrentUserUtils { backgroundColor: "black", ignoreClick: true, _gridGap: 0, _yMargin: 0, - _yPadding: 0, _xMargin: 0, _autoHeight: false, _width: 60, _columnWidth: 60, _lockedPosition: true, _chromeStatus: "disabled", system: true + _yPadding: 0, _xMargin: 0, _autoHeight: false, _width: 60, _columnWidth: 60, _lockedPosition: true, system: true })); } // this resets all sidebar buttons to being deactivated @@ -596,7 +596,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, _chromeStatus: "disabled", title: "home", _yMargin: 100, system: true + _width: 980, ignoreClick: true, _lockedPosition: false, title: "home", _yMargin: 100, system: true })); return menu; } @@ -627,26 +627,26 @@ export class CurrentUserUtils { static mobileButton = (opts: DocumentOptions, docs: Doc[]) => Docs.Create.MulticolumnDocument(docs, { ...opts, dropAction: undefined, removeDropProperties: new List(["dropAction"]), _nativeWidth: 900, _nativeHeight: 250, _width: 900, _height: 250, _yMargin: 15, - borderRounding: "5px", boxShadow: "0 0", _chromeStatus: "disabled", system: true + borderRounding: "5px", boxShadow: "0 0", system: true }) as any as Doc // sets up the text container for the information contained within the mobile button static mobileTextContainer = (opts: DocumentOptions, docs: Doc[]) => Docs.Create.MultirowDocument(docs, { ...opts, dropAction: undefined, removeDropProperties: new List(["dropAction"]), _nativeWidth: 450, _nativeHeight: 250, _width: 450, _height: 250, _yMargin: 25, - backgroundColor: "rgba(0,0,0,0)", borderRounding: "0", boxShadow: "0 0", _chromeStatus: "disabled", ignoreClick: true, system: true + backgroundColor: "rgba(0,0,0,0)", borderRounding: "0", boxShadow: "0 0", ignoreClick: true, system: true }) as any as Doc // Sets up the title of the button static mobileButtonText = (opts: DocumentOptions, buttonTitle: string) => Docs.Create.TextDocument(buttonTitle, { ...opts, - dropAction: undefined, title: buttonTitle, _fontSize: "37px", _xMargin: 0, _yMargin: 0, ignoreClick: true, _chromeStatus: "disabled", backgroundColor: "rgba(0,0,0,0)", system: true + dropAction: undefined, title: buttonTitle, _fontSize: "37px", _xMargin: 0, _yMargin: 0, ignoreClick: true, backgroundColor: "rgba(0,0,0,0)", system: true }) as any as Doc // Sets up the description of the button static mobileButtonInfo = (opts: DocumentOptions, buttonInfo: string) => Docs.Create.TextDocument(buttonInfo, { ...opts, - dropAction: undefined, title: "info", _fontSize: "25px", _xMargin: 0, _yMargin: 0, ignoreClick: true, _chromeStatus: "disabled", backgroundColor: "rgba(0,0,0,0)", _dimMagnitude: 2, system: true + dropAction: undefined, title: "info", _fontSize: "25px", _xMargin: 0, _yMargin: 0, ignoreClick: true, backgroundColor: "rgba(0,0,0,0)", _dimMagnitude: 2, system: true }) as any as Doc @@ -671,11 +671,11 @@ export class CurrentUserUtils { static setupThumbDoc(userDoc: Doc) { if (!userDoc.thumbDoc) { const thumbDoc = Docs.Create.LinearDocument(CurrentUserUtils.setupThumbButtons(userDoc), { - _width: 100, _height: 50, ignoreClick: true, _lockedPosition: true, _chromeStatus: "disabled", title: "buttons", + _width: 100, _height: 50, ignoreClick: true, _lockedPosition: true, title: "buttons", _autoHeight: true, _yMargin: 5, linearViewIsExpanded: true, backgroundColor: "white", system: true }); thumbDoc.inkToTextDoc = Docs.Create.LinearDocument([], { - _width: 300, _height: 25, _autoHeight: true, _chromeStatus: "disabled", linearViewIsExpanded: true, flexDirection: "column", system: true + _width: 300, _height: 25, _autoHeight: true, linearViewIsExpanded: true, flexDirection: "column", system: true }); userDoc.thumbDoc = thumbDoc; } @@ -695,7 +695,7 @@ export class CurrentUserUtils { title: "Mobile Upload Collection", backgroundColor: "white", _lockedPosition: true, system: true }); return Docs.Create.StackingDocument([webDoc, uploadDoc], { - _width: screen.width, _lockedPosition: true, _chromeStatus: "disabled", title: "Upload", _autoHeight: true, _yMargin: 80, backgroundColor: "lightgray", system: true + _width: screen.width, _lockedPosition: true, title: "Upload", _autoHeight: true, _yMargin: 80, backgroundColor: "lightgray", system: true }); } @@ -715,7 +715,7 @@ 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, _chromeStatus: "disabled", system: true + _width: 500, _height: 300, ignoreClick: true, _lockedPosition: true, system: true })); } // setup a color picker @@ -728,7 +728,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, _chromeStatus: "disabled", _forceActive: true, system: true, _stayInCollection: true, _hideContextMenu: true, + title: "My Tools", _width: 500, _yMargin: 20, ignoreClick: true, _lockedPosition: true, _forceActive: true, system: true, _stayInCollection: true, _hideContextMenu: true, })) as any as Doc; doc.myTools = toolsStack; @@ -831,7 +831,6 @@ export class CurrentUserUtils { static setupSidebarContainer(doc: Doc) { if (doc.sidebar === undefined) { const sidebarContainer = new Doc(); - sidebarContainer._chromeStatus = "disabled"; sidebarContainer.system = true; doc.sidebar = new PrefetchProxy(sidebarContainer); } @@ -853,7 +852,7 @@ export class CurrentUserUtils { static blist = (opts: DocumentOptions, docs: Doc[]) => new PrefetchProxy(Docs.Create.LinearDocument(docs, { ...opts, _gridGap: 5, _xMargin: 5, _yMargin: 5, _height: 42, _width: 100, boxShadow: "0 0", _forceActive: true, dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }), - backgroundColor: "black", treeViewPreventOpen: true, _lockedPosition: true, _chromeStatus: "disabled", linearViewIsExpanded: true, system: true + backgroundColor: "black", treeViewPreventOpen: true, _lockedPosition: true, linearViewIsExpanded: true, system: true })) as any as Doc static ficon = (opts: DocumentOptions) => new PrefetchProxy(Docs.Create.FontIconDocument({ @@ -923,7 +922,7 @@ 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, _chromeStatus: "disabled", system: true + childDropAction: "alias", _autoHeight: true, _yMargin: 50, _gridGap: 15, _lockedPosition: true, system: true })); } if (doc.myImportPanel === undefined) { diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx index 46586bf1b..31279338f 100644 --- a/src/client/views/InkingStroke.tsx +++ b/src/client/views/InkingStroke.tsx @@ -28,8 +28,6 @@ export class InkingStroke extends ViewBoxBaseComponent { const data: InkData = Cast(this.dataDoc[this.fieldKey], InkField)?.inkData ?? []; CognitiveServices.Inking.Appliers.ConcatenateHandwriting(this.dataDoc, ["inkAnalysis", "handwriting"], [data]); diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index 46d5b2f71..e93abb67a 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -3,10 +3,10 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Tooltip } from '@material-ui/core'; import { action, computed, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; -import { Doc } from "../../fields/Doc"; +import { Doc, Opt } from "../../fields/Doc"; import { InkField } from '../../fields/InkField'; import { RichTextField } from '../../fields/RichTextField'; -import { Cast, NumCast, StrCast } from "../../fields/Types"; +import { BoolCast, Cast, NumCast, StrCast } from "../../fields/Types"; import { ImageField } from '../../fields/URLField'; import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager'; import { Pulls, Pushes } from '../apis/google_docs/GoogleApiClientUtils'; @@ -16,10 +16,11 @@ import { DocumentType } from '../documents/DocumentTypes'; import { SelectionManager } from '../util/SelectionManager'; import { undoBatch } from '../util/UndoManager'; import { CollectionDockingView } from './collections/CollectionDockingView'; +import { CollectionViewType } from './collections/CollectionView'; +import { DocumentView } from './nodes/DocumentView'; import { GoogleRef } from "./nodes/formattedText/FormattedTextBox"; import './PropertiesButtons.scss'; import React = require("react"); -import { CollectionViewType } from './collections/CollectionView'; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -40,26 +41,19 @@ export class PropertiesButtons extends React.Component<{}, {}> { private _pushAnimating = false; private _pullColorAnimating = false; + public static hasPushedHack = false; + public static hasPulledHack = false; + + @observable public static Instance: PropertiesButtons; + @observable private openHover = UtilityButtonState.Default; @observable private pushIcon: IconProp = "arrow-alt-circle-up"; @observable private pullIcon: IconProp = "arrow-alt-circle-down"; @observable private pullColor: string = "white"; @observable public isAnimatingFetch = false; @observable public isAnimatingPulse = false; - @observable private openHover: UtilityButtonState = UtilityButtonState.Default; - - @observable public static Instance: PropertiesButtons; - public static hasPushedHack = false; - public static hasPulledHack = false; - - @computed get selectedDoc() { return SelectionManager.SelectedSchemaDoc() || this.selectedDocumentView?.rootDoc; } - @computed get selectedDocumentView() { - if (SelectionManager.Views().length) { - return SelectionManager.Views()[0]; - } else return undefined; - } - + @computed get selectedDocumentView() { return SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined; } @computed get onClick() { return this.selectedDoc?.onClickBehavior ? this.selectedDoc?.onClickBehavior : "nothing"; } public startPullOutcome = action((success: boolean) => { @@ -185,27 +179,62 @@ export class PropertiesButtons extends React.Component<{}, {}> { ; } - @action @undoBatch - onLock = () => { - SelectionManager.Views().forEach(dv => dv.docView?.toggleLockPosition()); + @action + makeMask = (inkDoc: Doc) => { + inkDoc.isInkMask = !inkDoc.isInkMask; + inkDoc._backgroundColor = inkDoc.isInkMask ? "rgba(0,0,0,0.7)" : undefined; + inkDoc.mixBlendMode = inkDoc.isInkMask ? "hard-light" : undefined; + inkDoc.color = "#9b9b9bff"; + inkDoc._stayInCollection = inkDoc.isInkMask ? true : undefined; } - - @computed - get lockButton() { + propToggleBtn = (label: string, property: string, tooltip: (on?: any) => string, icon: (on: boolean) => string, onClick?: (dv: Opt, doc: Doc, property: string) => void) => { const targetDoc = this.selectedDoc; + const onPropToggle = (dv: Opt, doc: Doc, prop: string) => (dv?.layoutDoc || doc)[prop] = (dv?.layoutDoc || doc)[prop] ? undefined : true; return !targetDoc ? (null) : {`${this.selectedDoc?._lockedPosition ? "Unlock" : "Lock"} Position`}
} placement="top"> + title={
{tooltip(targetDoc?.[property])}
} placement="top">
-
- +
{ + if (SelectionManager.Views().length) { + SelectionManager.Views().forEach(dv => (onClick ?? onPropToggle)(dv, dv.rootDoc, property)); + } else if (targetDoc) (onClick ?? onPropToggle)(undefined, targetDoc, property); + })} > +
-
Position
+
{label}
; } + @computed get lockButton() { + return this.propToggleBtn("Position", "_lockedPosition", on => `${on ? "Unlock" : "Lock"} XY location on freeform view`, on => on ? "unlock" : "lock"); + } + @computed get panButton() { + return this.propToggleBtn("Pan", "_lockedTransform", on => `${on ? "Unlock" : "Lock"} panning of view`, on => on ? "unlock" : "lock"); + } + @computed get dictationButton() { + return this.propToggleBtn("Dictate", "_showAudio", on => `${on ? "Hide" : "Show"} dictation/recording controls`, () => "microphone"); + } + @computed get maskButton() { + return this.propToggleBtn("Mask", "isInkMask", on => on ? "Make plain ink" : "Make highlight mask", () => "paint-brush", (dv, doc) => this.makeMask(dv?.layoutDoc || doc)); + } + @computed get clustersButton() { + return this.propToggleBtn("Clusters", "_useClusters", on => `${on ? "Hide" : "Show"} clusters`, () => "braille"); + } + @computed get fitContentButton() { + return this.propToggleBtn("Fit All", "_fitToBox", on => `${on ? "Don't" : ""} fit content to container visible area`, on => on ? "expand-arrows-alt" : "compress-arrows-alt"); + } + @computed get fitWidthButton() { + return this.propToggleBtn("Fit Wid", "_fitWidth", on => `${on ? "Don't" : ""} fit content to width of container`, on => on ? "arrows-alt-h" : "arrows-alt-h"); + } + @computed get captionButton() { + return this.propToggleBtn("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.propToggleBtn("Controls", "_chromeStatus", on => `${on === "enabled" ? "Hide" : "Show"} editing UI`, on => "edit", (dv, doc) => (dv?.rootDoc || doc)._chromeStatus = (dv?.rootDoc || doc)._chromeStatus === undefined ? "enabled" : undefined); + } + @computed get titleButton() { + return this.propToggleBtn("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); + } @computed get downloadButton() { @@ -221,117 +250,35 @@ export class PropertiesButtons extends React.Component<{}, {}> { ; } - @undoBatch - setDictation = () => SelectionManager.Views().forEach(dv => dv.rootDoc._showAudio = !dv.rootDoc._showAudio) - - @computed - get dictationButton() { - const targetDoc = this.selectedDoc; - return !targetDoc ? (null) : {"Show Dictation Controls"}
} placement="top"> -
-
- -
-
Dictate
-
- ; - } - - - @undoBatch - @action - setTitle = () => { - SelectionManager.Views().forEach(dv => dv.rootDoc._showTitle = !dv.rootDoc._showTitle ? "title" : dv.rootDoc._showTitle === "title" ? "title:hover" : undefined); - } - - @computed - get titleButton() { - const targetDoc = this.selectedDoc; - return !targetDoc ? (null) : {"Show Title Header"}} placement="top"> -
-
- -
-
Title
-
-
; - } - - @undoBatch - @action - setCaption = () => { - SelectionManager.Views().forEach(dv => { - dv.rootDoc._showCaption = dv.rootDoc._showCaption === undefined ? "caption" : undefined; - console.log("caption = " + dv.rootDoc._showCaption); - }); - } - - @computed - get captionButton() { - const targetDoc = this.selectedDoc; - return !targetDoc ? (null) : {"Show Caption Footer"}} placement="top"> -
-
- -
-
Caption
-
-
; - } - - @undoBatch - @action - setChrome = () => { - SelectionManager.Views().forEach(dv => dv.rootDoc._chromeStatus = dv.rootDoc._chromeStatus === "disabled" ? "enabled" : "disabled"); - } - @computed - get chromeButton() { - const targetDoc = this.selectedDoc; - return !targetDoc ? (null) : {"Show Editing UI"}} placement="top"> + get onClickButton() { + return !this.selectedDoc ? (null) :
Choose onClick behavior
} placement="top">
-
- +
+ +
e.stopPropagation()} > + {} +
+
-
Controls
+
onclick
; } - @computed - get onClickButton() { - if (this.selectedDoc) { - return
Choose onClick behavior
} placement="top"> -
-
- -
e.stopPropagation()} > - {} -
-
-
-
onclick
-
-
; - } else { - return null; - } - } - @undoBatch @action handleOptionChange = (e: any) => { - const value = e.target.value; this.selectedDoc && (this.selectedDoc.onClickBehavior = e.target.value); - SelectionManager.Views().forEach(dv => { - dv.docView?.noOnClick(); - switch (value) { - case "enterPortal": dv.docView?.makeIntoPortal(); break; - case "toggleDetail": dv.docView?.toggleDetail(); break; - case "linkInPlace": dv.docView?.toggleFollowLink("inPlace", true, false); break; - case "linkOnRight": dv.docView?.toggleFollowLink("add:right", false, false); break; + SelectionManager.Views().filter(dv => dv.docView).map(dv => dv.docView!).forEach(docView => { + docView.noOnClick(); + switch (e.target.value) { + case "enterPortal": docView.makeIntoPortal(); break; + case "toggleDetail": docView.toggleDetail(); break; + case "linkInPlace": docView.toggleFollowLink("inPlace", true, false); break; + case "linkOnRight": docView.toggleFollowLink("add:right", false, false); break; } }); } @@ -407,98 +354,6 @@ export class PropertiesButtons extends React.Component<{}, {}> { ; } - @computed - get clustersButton() { - const targetDoc = this.selectedDoc; - return !targetDoc ? (null) :
{this.selectedDoc?._useClusters ? "Stop Showing Clusters" : "Show Clusters"}
} placement="top"> -
-
- -
-
clusters
-
-
; - } - - @action @undoBatch - changeFitToBox = () => { - if (this.selectedDoc) { - if (SelectionManager.Views().length) SelectionManager.Views().forEach(dv => dv.rootDoc._fitToBox = !dv.rootDoc._fitToBox); - else this.selectedDoc._fitToBox = !this.selectedDoc._fitToBox; - } - } - - @action @undoBatch - changeFitWidth = () => { - if (this.selectedDoc) { - if (SelectionManager.Views().length) SelectionManager.Views().forEach(dv => dv.rootDoc._fitWidth = !dv.rootDoc._fitWidth); - else this.selectedDoc._fitWidth = !this.selectedDoc._fitWidth; - } - } - - @action @undoBatch - changeClusters = () => { - if (this.selectedDoc) { - if (SelectionManager.Views().length) SelectionManager.Views().forEach(dv => dv.rootDoc._useClusters = !dv.rootDoc._useClusters); - else this.selectedDoc._useClusters = !this.selectedDoc._useClusters; - } - } - - @computed - get fitContentButton() { - const targetDoc = this.selectedDoc; - return !targetDoc ? (null) :
{this.selectedDoc?._fitToBox ? "Stop Fitting Content" : "Fit Content"}
} placement="top"> -
-
- -
-
{this.selectedDoc?._fitToBox ? "unfit" : "fit"}
-
-
; - } - - @computed - get fitWidthButton() { - const targetDoc = this.selectedDoc; - return !targetDoc ? (null) :
{this.selectedDoc?._fitWidth ? "Stop Fitting Width" : "Fit Width"}
} placement="top"> -
-
- -
-
{this.selectedDoc?._fitWidth ? "unfit" : "fit"}
-
-
; - } - - @undoBatch - @action - private makeMask = () => { - if (this.selectedDoc) { - this.selectedDoc._backgroundColor = "rgba(0,0,0,0.7)"; - this.selectedDoc.mixBlendMode = "hard-light"; - this.selectedDoc.color = "#9b9b9bff"; - this.selectedDoc._stayInCollection = true; - this.selectedDoc.isInkMask = true; - } - } - - @computed - get maskButton() { - const targetDoc = this.selectedDoc; - return !targetDoc ? (null) :
Make Mask
} placement="top"> -
-
- -
-
mask
-
-
; - } - render() { if (!this.selectedDoc) return (null); @@ -524,6 +379,9 @@ export class PropertiesButtons extends React.Component<{}, {}> {
{this.lockButton}
+
+ {this.panButton} +
{this.dictationButton}
@@ -554,4 +412,4 @@ export class PropertiesButtons extends React.Component<{}, {}> {
; } -} +} \ No newline at end of file diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index f39d5ee4c..162a2ebb8 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -81,7 +81,7 @@ export class TemplateMenu extends React.Component { @action toggleChrome = (): void => { this.props.docViews.map(dv => Doc.Layout(dv.layoutDoc)).forEach(layout => - layout._chromeStatus = (layout._chromeStatus !== "disabled" ? "disabled" : StrCast(layout._replacedChrome, "enabled"))); + layout._chromeStatus = (layout._chromeStatus !== undefined ? undefined : StrCast(layout._replacedChrome, "enabled"))); } // todo: add brushes to brushMap to save with a style name @@ -119,7 +119,7 @@ export class TemplateMenu extends React.Component { templateMenu.push()); templateMenu.push(); templateMenu.push(); - !Doc.UserDoc().noviceMode && templateMenu.push(); + !Doc.UserDoc().noviceMode && templateMenu.push(); addedTypes.concat(noteTypes).map(template => template.treeViewChecked = this.templateIsUsed(firstDoc, template)); this._addedKeys && Array.from(this._addedKeys).filter(key => !noteTypes.some(nt => nt.title === key)).forEach(template => templateMenu.push( this.toggleLayout(e, template)} />)); diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx index 9b57d4c68..2013b3f43 100644 --- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx +++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx @@ -187,7 +187,7 @@ export class CollectionMasonryViewFieldRow extends React.Component) => { if (e.button === 0 && !e.ctrlKey) { - setupMoveUpEvents(this, e, this.headerMove, emptyFunction, e => (this.props.parent.props.Document._chromeStatus === "disabled") && this.collapseSection(e)); + setupMoveUpEvents(this, e, this.headerMove, emptyFunction, e => !this.props.parent.props.Document._chromeStatus && this.collapseSection(e)); this._createAliasSelected = false; } } @@ -286,7 +286,7 @@ export class CollectionMasonryViewFieldRow extends React.Component doc) { this.Document._pileLayoutEngine = "pass"; } this._originalChrome = StrCast(this.layoutDoc._chromeStatus); - this.layoutDoc._chromeStatus = "disabled"; + this.layoutDoc._chromeStatus = undefined; } componentWillUnmount() { this.layoutDoc._chromeStatus = this._originalChrome; diff --git a/src/client/views/collections/SchemaTable.tsx b/src/client/views/collections/SchemaTable.tsx index 53801eef1..d26f53e28 100644 --- a/src/client/views/collections/SchemaTable.tsx +++ b/src/client/views/collections/SchemaTable.tsx @@ -559,7 +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} - {StrCast(this.props.Document._chromeStatus) !== "disabled" ?
this.createRow()}>+ new
+ {this.props.Document._chromeStatus ?
this.createRow()}>+ new
: undefined} {!this._showDoc ? (null) :
Doc.toggleNativeDimensions(this.layoutDoc, 1, this.nativeWidth, this.nativeHeight) - @undoBatch - @action - toggleLockTransform = () => this.layoutDoc._lockedTransform = this.layoutDoc._lockedTransform ? undefined : true - onContextMenu = (e: React.MouseEvent) => { if (this.props.isAnnotationOverlay || this.props.Document.annotationOn || !ContextMenu.Instance) return; @@ -1314,7 +1310,6 @@ export class CollectionFreeFormView extends CollectionSubView this._showAnimTimeline = !this._showAnimTimeline), icon: "eye" }); - optionItems.push({ description: this.layoutDoc._lockedTransform ? "Unlock Transform" : "Lock Transform", event: this.toggleLockTransform, icon: this.layoutDoc._lockedTransform ? "unlock" : "lock" }); this.props.renderDepth && optionItems.push({ description: "Use Background Color as Default", event: () => Cast(Doc.UserDoc().emptyCollection, Doc, null)._backgroundColor = StrCast(this.layoutDoc._backgroundColor), icon: "palette" }); if (!Doc.UserDoc().noviceMode) { optionItems.push({ description: (!Doc.NativeWidth(this.layoutDoc) || !Doc.NativeHeight(this.layoutDoc) ? "Freeze" : "Unfreeze") + " Aspect", event: this.toggleNativeDimensions, icon: "snowflake" }); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index aec6cd03d..47a3c878f 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -594,7 +594,6 @@ export class DocumentViewInternal extends DocComponent this.props.removeDocument?.(this.props.Document); @undoBatch toggleDetail = () => this.Document.onClick = ScriptField.MakeScript(`toggleDetail(self, "${this.Document.layoutKey}")`); - @undoBatch toggleLockPosition = () => this.Document._lockedPosition = this.Document._lockedPosition ? undefined : true; @undoBatch @action drop = async (e: Event, de: DragManager.DropEvent) => { @@ -689,7 +688,6 @@ export class DocumentViewInternal extends DocComponent this.Document.ignoreClick = !this.Document.ignoreClick, icon: this.Document.ignoreClick ? "unlock" : "lock" }); @@ -721,7 +719,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 !== "disabled" ? "Hide" : "Show"} Chrome`, event: () => this.Document._chromeStatus = (this.Document._chromeStatus !== "disabled" ? "disabled" : "enabled"), icon: "project-diagram" }); + moreItems.push({ description: `${this.Document._chromeStatus ? "Hide" : "Show"} Chrome`, event: () => this.Document._chromeStatus = (this.Document._chromeStatus ? undefined : "enabled"), 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" }); diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 844afe1e2..682ec5356 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -2262,7 +2262,7 @@ export class PresBox extends ViewBoxBaseComponent const mode = StrCast(this.rootDoc._viewType) as CollectionViewType; const isMini: boolean = this.toolbarWidth <= 100; return ( -
+
{isMini ? (null) :