From 47ecf8d30f4aa5e25a659fc7f3c0c1487420150e Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Thu, 9 May 2019 20:59:10 -0400 Subject: merge with master, but haven't reconciled internal and external linking --- src/client/views/DocumentDecorations.tsx | 390 ++++++++++++++++++++++--------- 1 file changed, 276 insertions(+), 114 deletions(-) (limited to 'src/client/views/DocumentDecorations.tsx') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 16fac0694..4786b4de6 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -1,94 +1,126 @@ -import { action, computed, observable } from "mobx"; +import { action, computed, observable, runInAction, untracked, reaction } from "mobx"; import { observer } from "mobx-react"; -import { Key } from "../../fields/Key"; -import { KeyStore } from "../../fields/KeyStore"; -import { ListField } from "../../fields/ListField"; -import { NumberField } from "../../fields/NumberField"; -import { TextField } from "../../fields/TextField"; -import { emptyFunction } from "../../Utils"; +import { emptyFunction, Utils } from "../../Utils"; import { DragLinksAsDocuments, DragManager } from "../util/DragManager"; import { SelectionManager } from "../util/SelectionManager"; import { undoBatch } from "../util/UndoManager"; import './DocumentDecorations.scss'; -import { MainOverlayTextBox } from "./MainOverlayTextBox"; -import { DocumentView } from "./nodes/DocumentView"; +import { DocumentView, PositionDocument } from "./nodes/DocumentView"; import { LinkMenu } from "./nodes/LinkMenu"; +import { TemplateMenu } from "./TemplateMenu"; import React = require("react"); +import { Template, Templates } from "./Templates"; +import { CompileScript } from "../util/Scripting"; +import { IconBox } from "./nodes/IconBox"; +import { Cast, FieldValue, NumCast, StrCast } from "../../new_fields/Types"; +import { Doc, FieldResult } from "../../new_fields/Doc"; +import { listSpec } from "../../new_fields/Schema"; +import { Docs } from "../documents/Documents"; +import { List } from "../../new_fields/List"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; +import { faLink } from '@fortawesome/free-solid-svg-icons'; +import { library } from '@fortawesome/fontawesome-svg-core'; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { MINIMIZED_ICON_SIZE } from "../views/globalCssVariables.scss"; +import { CollectionView } from "./collections/CollectionView"; +import { DocumentManager } from "../util/DocumentManager"; +import { FormattedTextBox } from "./nodes/FormattedTextBox"; +import { FieldView } from "./nodes/FieldView"; + +library.add(faLink); @observer export class DocumentDecorations extends React.Component<{}, { value: string }> { static Instance: DocumentDecorations; - private _resizer = ""; private _isPointerDown = false; + private _resizing = ""; private keyinput: React.RefObject; - private _documents: DocumentView[] = SelectionManager.SelectedDocuments(); private _resizeBorderWidth = 16; - private _linkBoxHeight = 30; + private _linkBoxHeight = 20 + 3; // link button height + margin private _titleHeight = 20; private _linkButton = React.createRef(); private _linkerButton = React.createRef(); - //@observable private _title: string = this._documents[0].props.Document.Title; - @observable private _title: string = this._documents.length > 0 ? this._documents[0].props.Document.Title : ""; - @observable private _fieldKey: Key = KeyStore.Title; + private _downX = 0; + private _downY = 0; + private _iconDoc?: Doc = undefined; + @observable private _minimizedX = 0; + @observable private _minimizedY = 0; + @observable private _title: string = ""; + @observable private _edtingTitle = false; + @observable private _fieldKey = "title"; @observable private _hidden = false; @observable private _opacity = 1; - @observable private _dragging = false; - + @observable private _removeIcon = false; + @observable public Interacting = false; constructor(props: Readonly<{}>) { super(props); DocumentDecorations.Instance = this; - this.handleChange = this.handleChange.bind(this); this.keyinput = React.createRef(); + reaction(() => SelectionManager.SelectedDocuments().slice(), docs => this._edtingTitle = false); } - @action - handleChange = (event: any) => { - this._title = event.target.value; - } - - @action - enterPressed = (e: any) => { + @action titleChanged = (event: any) => { this._title = event.target.value; }; + @action titleBlur = () => { this._edtingTitle = false; }; + @action titleEntered = (e: any) => { var key = e.keyCode || e.which; // enter pressed if (key === 13) { var text = e.target.value; if (text[0] === '#') { - let command = text.slice(1, text.length); - this._fieldKey = new Key(command); - // if (command === "Title" || command === "title") { - // this._fieldKey = KeyStore.Title; - // } - // else if (command === "Width" || command === "width") { - // this._fieldKey = KeyStore.Width; - // } - this._title = "changed"; - // TODO: Change field with switch statement + this._fieldKey = text.slice(1, text.length); + this._title = this.selectionTitle; } else { - if (this._documents.length > 0) { - let field = this._documents[0].props.Document.Get(this._fieldKey); - if (field instanceof TextField) { - this._documents.forEach(d => - d.props.Document.Set(this._fieldKey, new TextField(this._title))); + if (SelectionManager.SelectedDocuments().length > 0) { + let field = SelectionManager.SelectedDocuments()[0].props.Document[this._fieldKey]; + if (typeof field === "number") { + SelectionManager.SelectedDocuments().forEach(d => { + let doc = d.props.Document.proto ? d.props.Document.proto : d.props.Document; + doc[this._fieldKey] = +this._title; + }); + } else { + SelectionManager.SelectedDocuments().forEach(d => { + let doc = d.props.Document.proto ? d.props.Document.proto : d.props.Document; + doc[this._fieldKey] = this._title; + }); } - else if (field instanceof NumberField) { - this._documents.forEach(d => - d.props.Document.Set(this._fieldKey, new NumberField(+this._title))); - } - this._title = "changed"; } } e.target.blur(); } } + @action onTitleDown = (e: React.PointerEvent): void => { + this._downX = e.clientX; + this._downY = e.clientY; + e.stopPropagation(); + this.onBackgroundDown(e); + document.removeEventListener("pointermove", this.onTitleMove); + document.removeEventListener("pointerup", this.onTitleUp); + document.addEventListener("pointermove", this.onTitleMove); + document.addEventListener("pointerup", this.onTitleUp); + } + @action onTitleMove = (e: PointerEvent): void => { + if (Math.abs(e.clientX - this._downX) > 4 || Math.abs(e.clientY - this._downY) > 4) { + this.Interacting = true; + } + if (this.Interacting) this.onBackgroundMove(e); + e.stopPropagation(); + } + @action onTitleUp = (e: PointerEvent): void => { + if (Math.abs(e.clientX - this._downX) < 4 || Math.abs(e.clientY - this._downY) < 4) { + this._title = this.selectionTitle; + this._edtingTitle = true; + } + document.removeEventListener("pointermove", this.onTitleMove); + document.removeEventListener("pointerup", this.onTitleUp); + this.onBackgroundUp(e); + } @computed get Bounds(): { x: number, y: number, b: number, r: number } { - this._documents = SelectionManager.SelectedDocuments(); return SelectionManager.SelectedDocuments().reduce((bounds, documentView) => { if (documentView.props.isTopMost) { return bounds; @@ -103,46 +135,38 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> }, { x: Number.MAX_VALUE, y: Number.MAX_VALUE, r: Number.MIN_VALUE, b: Number.MIN_VALUE }); } - - @computed - public get Hidden() { return this._hidden; } - public set Hidden(value: boolean) { this._hidden = value; } - - _lastDrag: number[] = [0, 0]; onBackgroundDown = (e: React.PointerEvent): void => { document.removeEventListener("pointermove", this.onBackgroundMove); - document.addEventListener("pointermove", this.onBackgroundMove); document.removeEventListener("pointerup", this.onBackgroundUp); + document.addEventListener("pointermove", this.onBackgroundMove); document.addEventListener("pointerup", this.onBackgroundUp); - this._lastDrag = [e.clientX, e.clientY]; e.stopPropagation(); - if (e.currentTarget.localName !== "input") { - e.preventDefault(); - } + e.preventDefault(); } @action onBackgroundMove = (e: PointerEvent): void => { let dragDocView = SelectionManager.SelectedDocuments()[0]; - const [left, top] = dragDocView.props.ScreenToLocalTransform().inverse().transformPoint(0, 0); + const [left, top] = dragDocView.props.ScreenToLocalTransform().scale(dragDocView.props.ContentScaling()).inverse().transformPoint(0, 0); + const [xoff, yoff] = dragDocView.props.ScreenToLocalTransform().scale(dragDocView.props.ContentScaling()).transformDirection(e.x - left, e.y - top); let dragData = new DragManager.DocumentDragData(SelectionManager.SelectedDocuments().map(dv => dv.props.Document)); - dragData.aliasOnDrop = false; - dragData.xOffset = e.x - left; - dragData.yOffset = e.y - top; - let move = SelectionManager.SelectedDocuments()[0].props.moveDocument; - dragData.moveDocument = move; - this._dragging = true; + dragData.xOffset = xoff; + dragData.yOffset = yoff; + dragData.moveDocument = SelectionManager.SelectedDocuments()[0].props.moveDocument; + this.Interacting = true; + this._hidden = true; document.removeEventListener("pointermove", this.onBackgroundMove); document.removeEventListener("pointerup", this.onBackgroundUp); + document.removeEventListener("pointermove", this.onTitleMove); + document.removeEventListener("pointerup", this.onTitleUp); DragManager.StartDocumentDrag(SelectionManager.SelectedDocuments().map(docView => docView.ContentDiv!), dragData, e.x, e.y, { - handlers: { - dragComplete: action(() => this._dragging = false), - }, + handlers: { dragComplete: action(() => this._hidden = this.Interacting = false) }, hideSource: true }); e.stopPropagation(); } + @action onBackgroundUp = (e: PointerEvent): void => { document.removeEventListener("pointermove", this.onBackgroundMove); document.removeEventListener("pointerup", this.onBackgroundUp); @@ -175,32 +199,121 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> document.removeEventListener("pointerup", this.onCloseUp); } } + @action onMinimizeDown = (e: React.PointerEvent): void => { e.stopPropagation(); + this._iconDoc = undefined; if (e.button === 0) { + this._downX = e.pageX; + this._downY = e.pageY; + this._removeIcon = false; + let selDoc = SelectionManager.SelectedDocuments()[0]; + let selDocPos = selDoc.props.ScreenToLocalTransform().scale(selDoc.props.ContentScaling()).inverse().transformPoint(0, 0); + this._minimizedX = selDocPos[0] + 12; + this._minimizedY = selDocPos[1] + 12; document.removeEventListener("pointermove", this.onMinimizeMove); document.addEventListener("pointermove", this.onMinimizeMove); document.removeEventListener("pointerup", this.onMinimizeUp); document.addEventListener("pointerup", this.onMinimizeUp); } } + + @action onMinimizeMove = (e: PointerEvent): void => { e.stopPropagation(); + if (Math.abs(e.pageX - this._downX) > Utils.DRAG_THRESHOLD || + Math.abs(e.pageY - this._downY) > Utils.DRAG_THRESHOLD) { + let selDoc = SelectionManager.SelectedDocuments()[0]; + let selDocPos = selDoc.props.ScreenToLocalTransform().scale(selDoc.props.ContentScaling()).inverse().transformPoint(0, 0); + let snapped = Math.abs(e.pageX - selDocPos[0]) < 20 && Math.abs(e.pageY - selDocPos[1]) < 20; + this._minimizedX = snapped ? selDocPos[0] + 4 : e.clientX; + this._minimizedY = snapped ? selDocPos[1] - 18 : e.clientY; + let selectedDocs = SelectionManager.SelectedDocuments().map(sd => sd); + + if (selectedDocs.length > 1) { + this._iconDoc = this._iconDoc ? this._iconDoc : this.createIcon(SelectionManager.SelectedDocuments(), CollectionView.LayoutString()); + this.moveIconDoc(this._iconDoc); + } else { + this.getIconDoc(selectedDocs[0]).then(icon => icon && this.moveIconDoc(this._iconDoc = icon)); + } + this._removeIcon = snapped; + } } + @action onMinimizeUp = (e: PointerEvent): void => { e.stopPropagation(); if (e.button === 0) { - SelectionManager.SelectedDocuments().map(dv => dv.minimize()); document.removeEventListener("pointermove", this.onMinimizeMove); document.removeEventListener("pointerup", this.onMinimizeUp); + let selectedDocs = SelectionManager.SelectedDocuments().map(sd => sd); + if (this._iconDoc && selectedDocs.length === 1 && this._removeIcon) { + selectedDocs[0].props.removeDocument && selectedDocs[0].props.removeDocument(this._iconDoc); + } + if (!this._removeIcon) { + if (selectedDocs.length === 1) + this.getIconDoc(selectedDocs[0]).then(icon => selectedDocs[0].props.toggleMinimized()); + else { + let docViews = SelectionManager.ViewsSortedVertically(); + let topDocView = docViews[0]; + let ind = topDocView.templates.indexOf(Templates.Bullet.Layout); + if (ind !== -1) { + topDocView.templates.splice(ind, 1); + topDocView.props.Document.subBulletDocs = undefined; + } else { + topDocView.addTemplate(Templates.Bullet); + topDocView.props.Document.subBulletDocs = new List(docViews.filter(v => v !== topDocView).map(v => v.props.Document)); + } + } + } + this._removeIcon = false; } + runInAction(() => this._minimizedX = this._minimizedY = 0); } + @action createIcon = (selected: DocumentView[], layoutString: string): Doc => { + let doc = selected[0].props.Document; + let iconDoc = Docs.IconDocument(layoutString); + iconDoc.isButton = true; + iconDoc.title = selected.length > 1 ? "ICONset" : "ICON" + StrCast(doc.title); + iconDoc.labelField = this._fieldKey; + iconDoc[this._fieldKey] = selected.length > 1 ? "collection" : undefined; + iconDoc.isMinimized = false; + iconDoc.width = Number(MINIMIZED_ICON_SIZE); + iconDoc.height = Number(MINIMIZED_ICON_SIZE); + iconDoc.x = NumCast(doc.x); + iconDoc.y = NumCast(doc.y) - 24; + iconDoc.maximizedDocs = new List(selected.map(s => s.props.Document)); + doc.minimizedDoc = iconDoc; + selected[0].props.addDocument && selected[0].props.addDocument(iconDoc, false); + return iconDoc; + } + @action + public getIconDoc = async (docView: DocumentView): Promise => { + let doc = docView.props.Document; + let iconDoc: Doc | undefined = await Cast(doc.minimizedDoc, Doc); + + if (!iconDoc || !DocumentManager.Instance.getDocumentView(iconDoc)) { + const layout = StrCast(doc.backgroundLayout, StrCast(doc.layout, FieldView.LayoutString(DocumentView))); + iconDoc = this.createIcon([docView], layout); + } + return iconDoc; + } + moveIconDoc(iconDoc: Doc) { + let selView = SelectionManager.SelectedDocuments()[0]; + let zoom = NumCast(selView.props.Document.zoomBasis, 1); + let where = (selView.props.ScreenToLocalTransform()).scale(selView.props.ContentScaling()).scale(1 / zoom). + transformPoint(this._minimizedX - 12, this._minimizedY - 12); + iconDoc.x = where[0] + NumCast(selView.props.Document.x); + iconDoc.y = where[1] + NumCast(selView.props.Document.y); + } + + @action onPointerDown = (e: React.PointerEvent): void => { e.stopPropagation(); if (e.button === 0) { this._isPointerDown = true; - this._resizer = e.currentTarget.id; + this._resizing = e.currentTarget.id; + this.Interacting = true; document.removeEventListener("pointermove", this.onPointerMove); document.addEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); @@ -221,11 +334,15 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> e.stopPropagation(); } + @action onLinkerButtonMoved = (e: PointerEvent): void => { if (this._linkerButton.current !== null) { document.removeEventListener("pointermove", this.onLinkerButtonMoved); document.removeEventListener("pointerup", this.onLinkerButtonUp); - let dragData = new DragManager.LinkDragData(SelectionManager.SelectedDocuments()[0].props.Document); + let selDoc = SelectionManager.SelectedDocuments()[0]; + let container = selDoc.props.ContainingCollectionView ? selDoc.props.ContainingCollectionView.props.Document.proto : undefined; + let dragData = new DragManager.LinkDragData(selDoc.props.Document, container ? [container] : []); + FormattedTextBox.InputBoxOverlay = undefined; DragManager.StartLinkDrag(this._linkerButton.current, dragData, e.pageX, e.pageY, { handlers: { dragComplete: action(emptyFunction), @@ -269,7 +386,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> let dX = 0, dY = 0, dW = 0, dH = 0; - switch (this._resizer) { + switch (this._resizing) { case "": break; case "documentDecorations-topLeftResizer": @@ -308,39 +425,45 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> break; } - MainOverlayTextBox.Instance.SetTextDoc(); + runInAction(() => FormattedTextBox.InputBoxOverlay = undefined); SelectionManager.SelectedDocuments().forEach(element => { const rect = element.ContentDiv ? element.ContentDiv.getBoundingClientRect() : new DOMRect(); if (rect.width !== 0) { - let doc = element.props.Document; - let width = doc.GetNumber(KeyStore.Width, 0); - let nwidth = doc.GetNumber(KeyStore.NativeWidth, 0); - let nheight = doc.GetNumber(KeyStore.NativeHeight, 0); - let height = doc.GetNumber(KeyStore.Height, nwidth ? nheight / nwidth * width : 0); - let x = doc.GetOrCreate(KeyStore.X, NumberField); - let y = doc.GetOrCreate(KeyStore.Y, NumberField); + let doc = PositionDocument(element.props.Document); + let width = FieldValue(doc.width, 0); + let nwidth = FieldValue(doc.nativeWidth, 0); + let nheight = FieldValue(doc.nativeHeight, 0); + let height = FieldValue(doc.height, nwidth ? nheight / nwidth * width : 0); + let x = FieldValue(doc.x, 0); + let y = FieldValue(doc.y, 0); let scale = width / rect.width; let actualdW = Math.max(width + (dW * scale), 20); let actualdH = Math.max(height + (dH * scale), 20); - x.Data += dX * (actualdW - width); - y.Data += dY * (actualdH - height); - var nativeWidth = doc.GetNumber(KeyStore.NativeWidth, 0); - var nativeHeight = doc.GetNumber(KeyStore.NativeHeight, 0); + x += dX * (actualdW - width); + y += dY * (actualdH - height); + doc.x = x; + doc.y = y; + var nativeWidth = FieldValue(doc.nativeWidth, 0); + var nativeHeight = FieldValue(doc.nativeHeight, 0); if (nativeWidth > 0 && nativeHeight > 0) { if (Math.abs(dW) > Math.abs(dH)) { actualdH = nativeHeight / nativeWidth * actualdW; } else actualdW = nativeWidth / nativeHeight * actualdH; } - doc.SetNumber(KeyStore.Width, actualdW); - doc.SetNumber(KeyStore.Height, actualdH); + doc.width = actualdW; + doc.height = actualdH; } }); } + @action onPointerUp = (e: PointerEvent): void => { e.stopPropagation(); + this._resizing = ""; + this.Interacting = false; + SelectionManager.ReselectAll(); if (e.button === 0) { e.preventDefault(); this._isPointerDown = false; @@ -349,17 +472,20 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> } } - getValue = (): string => { - if (this._title === "changed" && this._documents.length > 0) { - let field = this._documents[0].props.Document.Get(this._fieldKey); - if (field instanceof TextField) { - return (field).GetValue(); + @computed + get selectionTitle(): string { + if (SelectionManager.SelectedDocuments().length === 1) { + let field = SelectionManager.SelectedDocuments()[0].props.Document[this._fieldKey]; + if (typeof field === "string") { + return field; } - else if (field instanceof NumberField) { - return (field).GetValue().toString(); + else if (typeof field === "number") { + return field.toString(); } + } else if (SelectionManager.SelectedDocuments().length > 1) { + return "-multiple-"; } - return this._title; + return "-unset-"; } changeFlyoutContent = (): void => { @@ -368,53 +494,81 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> // buttonOnPointerUp = (e: React.PointerEvent): void => { // e.stopPropagation(); // } + render() { var bounds = this.Bounds; - if (bounds.x === Number.MAX_VALUE) { - return (null); - } - // console.log(this._documents.length) - // let test = this._documents[0].props.Document.Title; - if (this.Hidden) { - return (null); - } - if (isNaN(bounds.r) || isNaN(bounds.b) || isNaN(bounds.x) || isNaN(bounds.y)) { - console.log("DocumentDecorations: Bounds Error"); + let seldoc = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0] : undefined; + if (bounds.x === Number.MAX_VALUE || !seldoc || this._hidden || isNaN(bounds.r) || isNaN(bounds.b) || isNaN(bounds.x) || isNaN(bounds.y)) { return (null); } + let minimizeIcon = ( +
+ {SelectionManager.SelectedDocuments().length === 1 ? IconBox.DocumentIcon(StrCast(SelectionManager.SelectedDocuments()[0].props.Document.layout, "...")) : "..."} +
); let linkButton = null; if (SelectionManager.SelectedDocuments().length > 0) { let selFirst = SelectionManager.SelectedDocuments()[0]; - let linkToSize = selFirst.props.Document.GetData(KeyStore.LinkedToDocs, ListField, []).length; - let linkFromSize = selFirst.props.Document.GetData(KeyStore.LinkedFromDocs, ListField, []).length; + let linkToSize = Cast(selFirst.props.Document.linkedToDocs, listSpec(Doc), []).length; + let linkFromSize = Cast(selFirst.props.Document.linkedFromDocs, listSpec(Doc), []).length; let linkCount = linkToSize + linkFromSize; linkButton = (}> -
{linkCount}
-
); +
{linkCount}
+ ); } + + let templates: Map = new Map(); + Array.from(Object.values(Templates.TemplateList)).map(template => { + let sorted = SelectionManager.ViewsSortedVertically().slice().sort((doc1, doc2) => { + if (NumCast(doc1.props.Document.x) > NumCast(doc2.props.Document.x)) return 1; + if (NumCast(doc1.props.Document.x) < NumCast(doc2.props.Document.x)) return -1; + return 0; + }); + let docTemps = sorted.reduce((res: string[], doc: DocumentView, i) => { + let temps = doc.props.Document.templates; + if (temps instanceof List) { + temps.map(temp => { + if (temp !== Templates.Bullet.Layout || i === 0) { + res.push(temp); + } + }) + } + return res + }, [] as string[]); + let checked = false; + docTemps.forEach(temp => { + if (template.Layout === temp) { + checked = true; + } + }); + templates.set(template, checked); + }); + return (
1 ? 1000 : 0, }} onPointerDown={this.onBackgroundDown} onContextMenu={(e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation(); }} >
-
-
...
- + {minimizeIcon} + + {this._edtingTitle ? + : +
{`${this.selectionTitle}`}
}
X
e.preventDefault()}>
e.preventDefault()}>
@@ -425,9 +579,17 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
e.preventDefault()}>
e.preventDefault()}>
e.preventDefault()}>
- -
{linkButton}
-
+
+
+
{linkButton}
+
+
+
+ +
+
+ +
); -- cgit v1.2.3-70-g09d2 From 3451ce40cbd488cede7d29b6e39594f740e366b5 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Sat, 11 May 2019 19:15:17 -0400 Subject: basic internal drag and drop of images via embedded link --- src/client/util/DragManager.ts | 15 +++++++++ src/client/util/RichTextSchema.tsx | 26 +++++++++++++++ src/client/views/DocumentDecorations.tsx | 50 +++++++++++++++++++++++++++++ src/client/views/nodes/DocumentView.tsx | 1 + src/client/views/nodes/FormattedTextBox.tsx | 8 +++++ 5 files changed, 100 insertions(+) (limited to 'src/client/views/DocumentDecorations.tsx') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 266679c16..759698abc 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -4,6 +4,7 @@ import { Cast } from "../../new_fields/Types"; import { emptyFunction } from "../../Utils"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; import * as globalCssVariables from "../views/globalCssVariables.scss"; +import { URLField } from "../../new_fields/URLField"; export type dropActionType = "alias" | "copy" | undefined; export function SetupDrag(_reference: React.RefObject, docFunc: () => Doc, moveFunc?: DragManager.MoveFunction, dropAction?: dropActionType) { @@ -177,10 +178,24 @@ export namespace DragManager { [id: string]: any; } + export class EmbedDragData { + constructor(embeddableSourceDoc: Doc) { + this.embeddableSourceDoc = embeddableSourceDoc; + this.urlField = Cast(embeddableSourceDoc.data, URLField)!; + } + embeddableSourceDoc: Doc; + urlField: URLField; + [id: string]: any; + } + export function StartLinkDrag(ele: HTMLElement, dragData: LinkDragData, downX: number, downY: number, options?: DragOptions) { StartDrag([ele], dragData, downX, downY, options); } + export function StartEmbedDrag(ele: HTMLElement, dragData: EmbedDragData, downX: number, downY: number, options?: DragOptions) { + StartDrag([ele], dragData, downX, downY, options); + } + export let AbortDrag: () => void = emptyFunction; function StartDrag(eles: HTMLElement[], dragData: { [id: string]: any }, downX: number, downY: number, options?: DragOptions, finishDrag?: (dropData: { [id: string]: any }) => void) { diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index c0e6f7899..742ac5434 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -107,6 +107,32 @@ export const nodes: { [index: string]: NodeSpec } = { } }, + video: { + inline: true, + attrs: { + src: {}, + width: { default: "100px" }, + alt: { default: null }, + title: { default: null } + }, + group: "inline", + draggable: true, + parseDOM: [{ + tag: "video[src]", getAttrs(dom: any) { + return { + src: dom.getAttribute("src"), + title: dom.getAttribute("title"), + alt: dom.getAttribute("alt"), + width: Math.min(100, Number(dom.getAttribute("width"))), + } + } + }], + toDOM(node) { + const attrs = { style: `width: ${node.attrs.width}` } + return ["video", { ...node.attrs, ...attrs }] + } + }, + // :: NodeSpec A hard line break, represented in the DOM as `
`. hard_break: { inline: true, diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 4786b4de6..1a79c4192 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -28,6 +28,7 @@ import { CollectionView } from "./collections/CollectionView"; import { DocumentManager } from "../util/DocumentManager"; import { FormattedTextBox } from "./nodes/FormattedTextBox"; import { FieldView } from "./nodes/FieldView"; +import { URLField } from "../../new_fields/URLField"; library.add(faLink); @@ -42,6 +43,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> private _titleHeight = 20; private _linkButton = React.createRef(); private _linkerButton = React.createRef(); + private _embedButton = React.createRef(); private _downX = 0; private _downY = 0; private _iconDoc?: Doc = undefined; @@ -328,12 +330,27 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> document.removeEventListener("pointerup", this.onLinkerButtonUp); document.addEventListener("pointerup", this.onLinkerButtonUp); } + + onEmbedButtonDown = (e: React.PointerEvent): void => { + e.stopPropagation(); + document.removeEventListener("pointermove", this.onEmbedButtonMoved); + document.addEventListener("pointermove", this.onEmbedButtonMoved); + document.removeEventListener("pointerup", this.onEmbedButtonUp); + document.addEventListener("pointerup", this.onEmbedButtonUp); + } + onLinkerButtonUp = (e: PointerEvent): void => { document.removeEventListener("pointermove", this.onLinkerButtonMoved); document.removeEventListener("pointerup", this.onLinkerButtonUp); e.stopPropagation(); } + onEmbedButtonUp = (e: PointerEvent): void => { + document.removeEventListener("pointermove", this.onEmbedButtonMoved); + document.removeEventListener("pointerup", this.onEmbedButtonUp); + e.stopPropagation(); + } + @action onLinkerButtonMoved = (e: PointerEvent): void => { if (this._linkerButton.current !== null) { @@ -353,6 +370,25 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> e.stopPropagation(); } + @action + onEmbedButtonMoved = (e: PointerEvent): void => { + if (this._embedButton.current !== null) { + document.removeEventListener("pointermove", this.onEmbedButtonMoved); + document.removeEventListener("pointerup", this.onEmbedButtonUp); + + let dragDocView = SelectionManager.SelectedDocuments()[0]; + let dragData = new DragManager.EmbedDragData(dragDocView.props.Document); + + DragManager.StartEmbedDrag(dragDocView.ContentDiv!, dragData, e.x, e.y, { + handlers: { + dragComplete: action(emptyFunction), + }, + hideSource: false + }); + } + e.stopPropagation(); + } + onLinkButtonDown = (e: React.PointerEvent): void => { e.stopPropagation(); document.removeEventListener("pointermove", this.onLinkButtonMoved); @@ -495,6 +531,19 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> // e.stopPropagation(); // } + considerEmbed = () => { + let thisDoc = SelectionManager.SelectedDocuments()[0].props.Document; + let canEmbed = thisDoc.data && Cast(thisDoc.data, URLField); + if (!canEmbed) return (null); + return ( +
+
+ +
+
+ ); + } + render() { var bounds = this.Bounds; let seldoc = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0] : undefined; @@ -589,6 +638,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> + {this.considerEmbed()} diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 5aa74c703..63149187b 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -26,6 +26,7 @@ import { CurrentUserUtils } from "../../../server/authentication/models/current_ import { DocServer } from "../../DocServer"; import { Id } from "../../../new_fields/RefField"; import { PresentationView } from "../PresentationView"; +import { DatamartAugmentParameters } from "../../northstar/model/idea/idea"; const linkSchema = createSchema({ title: "string", diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index df3eb159b..791794beb 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -26,6 +26,8 @@ import { InkingControl } from "../InkingControl"; import { FieldView, FieldViewProps } from "./FieldView"; import "./FormattedTextBox.scss"; import React = require("react"); +import { View } from "@react-pdf/renderer"; +import { NodeType } from "prosemirror-model"; // FormattedTextBox: Displays an editable plain text node that maps to a specified Key of a Document // @@ -107,6 +109,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe @undoBatch @action drop = async (e: Event, de: DragManager.DropEvent) => { + // We're dealing with a link to a document if (de.data instanceof DragManager.LinkDragData) { let sourceDoc = de.data.linkSourceDocument; let destDoc = this.props.Document; @@ -116,6 +119,11 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe Doc.MakeLink(protoSrc ? protoSrc : sourceDoc, protoDest ? protoDest : destDoc); de.data.droppedDocuments.push(destDoc); e.stopPropagation(); + } else if (de.data instanceof DragManager.EmbedDragData) { + // We're dealing with an internal document drop + let url = de.data.urlField.url.href; + let model: NodeType = (url.includes(".mov") || url.includes(".mp4")) ? schema.nodes.video : schema.nodes.image; + this._editorView!.dispatch(this._editorView!.state.tr.insert(0, model.create({ src: url }))); } } -- cgit v1.2.3-70-g09d2 From fcae0da16f9413059d03638ba10ab30cdc460a42 Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 11 Jun 2019 16:45:48 -0400 Subject: fixed text input to allow typing from the bottom (caption) and to allow text boxes to grow vertically (autoHeight) --- src/client/documents/Documents.ts | 2 +- src/client/views/DocumentDecorations.tsx | 7 +++--- src/client/views/MainOverlayTextBox.tsx | 22 ++++++++++++------ .../collectionFreeForm/CollectionFreeFormView.scss | 1 + .../collections/collectionFreeForm/MarqueeView.tsx | 3 ++- src/client/views/nodes/DocumentView.tsx | 8 +++---- src/client/views/nodes/FormattedTextBox.tsx | 27 +++++++++++++++++++--- 7 files changed, 51 insertions(+), 19 deletions(-) (limited to 'src/client/views/DocumentDecorations.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 2ae127e21..b1df89dbd 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -166,7 +166,7 @@ export namespace Docs { } function CreateTextPrototype(): Doc { let textProto = setupPrototypeOptions(textProtoId, "TEXT_PROTO", FormattedTextBox.LayoutString(), - { x: 0, y: 0, width: 300, height: 150, backgroundColor: "#f1efeb" }); + { x: 0, y: 0, width: 300, backgroundColor: "#f1efeb" }); return textProto; } function CreatePdfPrototype(): Doc { diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 7260b00cf..1111cd2f5 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -442,11 +442,11 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> let actualdH = Math.max(height + (dH * scale), 20); doc.x = (doc.x || 0) + dX * (actualdW - width); doc.y = (doc.y || 0) + dY * (actualdH - height); - let proto = Doc.GetProto(doc); + let proto = Doc.GetProto(element.props.Document); let fixedAspect = e.ctrlKey || (!BoolCast(proto.ignoreAspect, false) && nwidth && nheight); if (fixedAspect && (!nwidth || !nheight)) { - proto.nativeWidth = doc.width; - proto.nativeHeight = doc.height; + proto.nativeWidth = nwidth = doc.width || 0; + proto.nativeHeight = nheight = doc.height || 0; proto.ignoreAspect = true; } if (nwidth > 0 && nheight > 0) { @@ -469,6 +469,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> } else { doc.width = zoomBasis * actualdW; doc.height = zoomBasis * actualdH; + proto.autoHeight = undefined; } } }); diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx index a0359419b..afa72d56e 100644 --- a/src/client/views/MainOverlayTextBox.tsx +++ b/src/client/views/MainOverlayTextBox.tsx @@ -9,6 +9,8 @@ import "./MainOverlayTextBox.scss"; import { FormattedTextBox } from './nodes/FormattedTextBox'; import { CollectionDockingView } from './collections/CollectionDockingView'; import { Doc } from '../../new_fields/Doc'; +import { BoolCast } from '../../new_fields/Types'; +import { auto } from 'async'; interface MainOverlayTextBoxProps { } @@ -22,6 +24,7 @@ export class MainOverlayTextBox extends React.Component private _textHideOnLeave?: boolean; private _textTargetDiv: HTMLDivElement | undefined; private _textProxyDiv: React.RefObject; + private _textBottom: boolean | undefined; public TextDoc?: Doc; constructor(props: MainOverlayTextBoxProps) { @@ -49,10 +52,12 @@ export class MainOverlayTextBox extends React.Component this._textTargetDiv.style.color = this._textColor; } this.TextFieldKey = textFieldKey!; - this._textXf = tx ? tx : () => Transform.Identity(); + let txf = tx ? tx : () => Transform.Identity(); + this._textXf = txf; this._textTargetDiv = div; this._textHideOnLeave = FormattedTextBox.InputBoxOverlay && FormattedTextBox.InputBoxOverlay.props.hideOnLeave; if (div) { + this._textBottom = textFieldKey === "caption" ? true : false; // (getComputedStyle(div) as any).bottom; this._textColor = (getComputedStyle(div) as any).color; div.style.color = "transparent"; } @@ -102,13 +107,16 @@ export class MainOverlayTextBox extends React.Component if (FormattedTextBox.InputBoxOverlay && this._textTargetDiv) { let textRect = this._textTargetDiv.getBoundingClientRect(); let s = this._textXf().Scale; - let auto = FormattedTextBox.InputBoxOverlay.props.height; - return
+ let bottom = this._textBottom ? textRect.bottom : textRect.top; + let hgt = 0; + return
- + style={{ width: `${textRect.width * s}px`, height: hgt }}> +
+ +
; } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss index e10ba9d7e..5ac2e1f9c 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss @@ -57,6 +57,7 @@ } >.jsx-parser { + position:absolute; z-index:0; } diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index c699b3437..01bbbba4c 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -93,7 +93,8 @@ export class MarqueeView extends React.Component } }); } else if (!e.ctrlKey) { - let newBox = Docs.TextDocument({ width: 200, height: 100, x: x, y: y, title: "-typed text-" }); + let newBox = Docs.TextDocument({ width: 200, height: 30, x: x, y: y, title: "-typed text-" }); + newBox.proto!.autoHeight = true; this.props.addLiveTextDocument(newBox); } e.stopPropagation(); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 19f5c7d36..2428103d1 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -317,13 +317,13 @@ export class DocumentView extends DocComponent(Docu makeBtnClicked = (): void => { let doc = Doc.GetProto(this.props.Document); doc.isButton = !BoolCast(doc.isButton, false); - if (StrCast(doc.layout).indexOf("Formatted") !== -1) { // only need to freeze the dimensions of text boxes since they don't have a native width and height naturally - if (doc.isButton && !doc.nativeWidth) { + if (doc.isButton) { + if (!doc.nativeWidth) { doc.nativeWidth = this.props.Document[WidthSym](); doc.nativeHeight = this.props.Document[HeightSym](); - } else { - doc.nativeWidth = doc.nativeHeight = undefined; } + } else { + doc.nativeWidth = doc.nativeHeight = undefined; } } fullScreenClicked = (): void => { diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 2923fd378..20e175031 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -10,7 +10,7 @@ import { EditorView } from "prosemirror-view"; import { Doc, Opt } from "../../../new_fields/Doc"; import { RichTextField } from "../../../new_fields/RichTextField"; import { createSchema, makeInterface } from "../../../new_fields/Schema"; -import { Cast, NumCast, StrCast } from "../../../new_fields/Types"; +import { Cast, NumCast, StrCast, BoolCast } from "../../../new_fields/Types"; import { DocServer } from "../../DocServer"; import { DocUtils, Docs } from '../../documents/Documents'; import { DocumentManager } from "../../util/DocumentManager"; @@ -29,6 +29,9 @@ import "./FormattedTextBox.scss"; import React = require("react"); import { Id } from '../../../new_fields/FieldSymbols'; import { MainOverlayTextBox } from '../MainOverlayTextBox'; +import { Utils } from '../../../Utils'; +import { ContextMenuProps } from '../ContextMenuItem'; +import { ContextMenu } from '../ContextMenu'; library.add(faEdit); library.add(faSmile); @@ -212,8 +215,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe } if (this.props.selectOnLoad) { - console.log("Sel on load " + this.props.Document.title + " " + doc!.title); - this.props.select(false); + //this.props.select(false); this._editorView!.focus(); } } @@ -351,6 +353,15 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe if (!this._undoTyping) { this._undoTyping = UndoManager.StartBatch("undoTyping"); } + if (this.props.isOverlay && this.props.Document.autoHeight) { + let xf = this._ref.current!.getBoundingClientRect(); + let scrBounds = this.props.ScreenToLocalTransform().transformBounds(0, 0, xf.width, xf.height); + let nh = NumCast(this.props.Document.nativeHeight, 0); + let dh = NumCast(this.props.Document.height, 0); + let sh = scrBounds.height; + this.props.Document.height = nh ? dh / nh * sh : sh; + this.props.Document.proto!.nativeHeight = nh ? sh : undefined; + } } @action @@ -361,6 +372,15 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe onPointerLeave = (e: React.PointerEvent) => { this._entered = false; } + + specificContextMenu = (e: React.MouseEvent): void => { + let subitems: ContextMenuProps[] = []; + subitems.push({ + description: BoolCast(this.props.Document.autoHeight, false) ? "Manual Height" : "Auto Height", + event: action(() => this.props.Document.autoHeight = !BoolCast(this.props.Document.autoHeight, false)), icon: "expand-arrows-alt" + }); + ContextMenu.Instance.addItem({ description: "Text Funcs...", subitems: subitems }); + } render() { let style = this.props.isOverlay ? "scroll" : "hidden"; let rounded = NumCast(this.props.Document.borderRounding) < 0 ? "-rounded" : ""; @@ -378,6 +398,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe onKeyPress={this.onKeyPress} onFocus={this.onFocused} onClick={this.onClick} + onContextMenu={this.specificContextMenu} onBlur={this.onBlur} onPointerUp={this.onPointerUp} onPointerDown={this.onPointerDown} -- cgit v1.2.3-70-g09d2 From 13e301dea2f537b67b338cc6a98d3f3b5a8e1f36 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Tue, 18 Jun 2019 20:58:32 -0400 Subject: Fixed linter errors --- src/client/northstar/dash-nodes/HistogramBox.tsx | 3 +-- src/client/util/DocumentManager.ts | 6 +++--- src/client/util/DragManager.ts | 4 +++- src/client/util/RichTextSchema.tsx | 10 +++++----- src/client/util/TooltipTextMenu.tsx | 2 +- src/client/views/ContextMenu.tsx | 4 ++-- src/client/views/DocumentDecorations.tsx | 2 +- src/client/views/MainOverlayTextBox.tsx | 2 +- src/client/views/MainView.tsx | 7 ++++--- src/client/views/PresentationView.tsx | 4 ++-- src/client/views/collections/CollectionBaseView.tsx | 2 +- src/client/views/collections/CollectionDockingView.tsx | 5 +++-- src/client/views/collections/CollectionPDFView.tsx | 2 +- src/client/views/collections/CollectionSchemaView.tsx | 11 ++++++----- src/client/views/collections/CollectionStackingView.tsx | 4 ++-- src/client/views/collections/CollectionTreeView.tsx | 10 +++++----- .../collectionFreeForm/CollectionFreeFormLinksView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- .../views/collections/collectionFreeForm/MarqueeView.tsx | 2 +- src/client/views/nodes/CollectionFreeFormDocumentView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 12 ++++++------ src/client/views/nodes/FormattedTextBox.tsx | 2 +- src/client/views/nodes/ImageBox.tsx | 3 ++- src/client/views/pdf/PDFAnnotationLayer.tsx | 2 +- src/client/views/pdf/PDFMenu.tsx | 2 +- src/client/views/pdf/PDFViewer.tsx | 4 ++-- src/server/index.ts | 2 +- 27 files changed, 59 insertions(+), 54 deletions(-) (limited to 'src/client/views/DocumentDecorations.tsx') diff --git a/src/client/northstar/dash-nodes/HistogramBox.tsx b/src/client/northstar/dash-nodes/HistogramBox.tsx index d7732ee86..a60eaea85 100644 --- a/src/client/northstar/dash-nodes/HistogramBox.tsx +++ b/src/client/northstar/dash-nodes/HistogramBox.tsx @@ -125,8 +125,7 @@ export class HistogramBox extends React.Component { let mapped = brushingDocs.map((brush, i) => { brush.backgroundColor = StyleConstants.BRUSH_COLORS[i % StyleConstants.BRUSH_COLORS.length]; let brushed = DocListCast(brush.brushingDocs); - if (!brushed.length) - return null; + if (!brushed.length) return null; return { l: brush, b: brushed[0][Id] === proto[Id] ? brushed[1] : brushed[0] }; }); runInAction(() => this.HistoOp.BrushLinks.splice(0, this.HistoOp.BrushLinks.length, ...mapped.filter(m => m) as { l: Doc, b: Doc }[])); diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index ff0c1560b..862395d74 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -35,9 +35,9 @@ export class DocumentManager { let toReturn: DocumentView | null = null; let passes = preferredCollection ? [preferredCollection, undefined] : [undefined]; - for (let i = 0; i < passes.length; i++) { + for (let pass of passes) { DocumentManager.Instance.DocumentViews.map(view => { - if (view.props.Document[Id] === id && (!passes[i] || view.props.ContainingCollectionView === preferredCollection)) { + if (view.props.Document[Id] === id && (!pass || view.props.ContainingCollectionView === preferredCollection)) { toReturn = view; return; } @@ -45,7 +45,7 @@ export class DocumentManager { if (!toReturn) { DocumentManager.Instance.DocumentViews.map(view => { let doc = view.props.Document.proto; - if (doc && doc[Id] === id && (!passes[i] || view.props.ContainingCollectionView === preferredCollection)) { + if (doc && doc[Id] === id && (!pass || view.props.ContainingCollectionView === preferredCollection)) { toReturn = view; } }); diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 89566e777..c3c92daa5 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -282,11 +282,13 @@ export namespace DragManager { // } let set = dragElement.getElementsByTagName('*'); if (dragElement.hasAttribute("style")) (dragElement as any).style.pointerEvents = "none"; - for (let i = 0; i < set.length; i++) + // tslint:disable-next-line: prefer-for-of + for (let i = 0; i < set.length; i++) { if (set[i].hasAttribute("style")) { let s = set[i]; (s as any).style.pointerEvents = "none"; } + } dragDiv.appendChild(dragElement); diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index e1e595925..943cdb4d1 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -156,12 +156,12 @@ export const nodes: { [index: string]: NodeSpec } = { title: dom.getAttribute("title"), alt: dom.getAttribute("alt"), width: Math.min(100, Number(dom.getAttribute("width"))), - } + }; } }], toDOM(node) { - const attrs = { style: `width: ${node.attrs.width}` } - return ["video", { ...node.attrs, ...attrs }] + const attrs = { style: `width: ${node.attrs.width}` }; + return ["video", { ...node.attrs, ...attrs }]; } }, @@ -285,7 +285,7 @@ export const marks: { [index: string]: MarkSpec } = { toDOM() { return ['span', { style: 'color: blue' - }] + }]; } }, @@ -536,4 +536,4 @@ schema.nodeFromJSON = (json: any) => { node.attrs.oldtext = Slice.fromJSON(schema, node.attrs.oldtextslice); } return node; -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx index 0a61b7e7d..f2559db74 100644 --- a/src/client/util/TooltipTextMenu.tsx +++ b/src/client/util/TooltipTextMenu.tsx @@ -256,7 +256,7 @@ export class TooltipTextMenu { starButton.onclick = () => { let state = this.view.state; this.insertStar(state, this.view.dispatch); - } + }; this.tooltip.appendChild(starButton); } diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index da374455e..eb1937683 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -1,8 +1,8 @@ import React = require("react"); import { ContextMenuItem, ContextMenuProps } from "./ContextMenuItem"; import { observable, action } from "mobx"; -import { observer } from "mobx-react" -import "./ContextMenu.scss" +import { observer } from "mobx-react"; +import "./ContextMenu.scss"; import { library } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faSearch, faCircle } from '@fortawesome/free-solid-svg-icons'; diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index ceca940b6..e60f8c86c 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -466,7 +466,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> SelectionManager.SelectedDocuments().forEach(element => { const rect = element.ContentDiv ? element.ContentDiv.getBoundingClientRect() : new DOMRect(); - if (rect.width !== 0 && (dX != 0 || dY != 0 || dW != 0 || dH != 0)) { + if (rect.width !== 0 && (dX !== 0 || dY !== 0 || dW !== 0 || dH !== 0)) { let doc = PositionDocument(element.props.Document); let nwidth = doc.nativeWidth || 0; let nheight = doc.nativeHeight || 0; diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx index 0de880175..b4ad5f4d7 100644 --- a/src/client/views/MainOverlayTextBox.tsx +++ b/src/client/views/MainOverlayTextBox.tsx @@ -40,7 +40,7 @@ export class MainOverlayTextBox extends React.Component this.TextDoc = box.props.Document; let sxf = Utils.GetScreenTransform(box ? box.CurrentDiv : undefined); let xf = () => { box.props.ScreenToLocalTransform(); return new Transform(-sxf.translateX, -sxf.translateY, 1 / sxf.scale); }; - this.setTextDoc(box.props.fieldKey, box.CurrentDiv, xf, BoolCast(box.props.Document.autoHeight, false) || box.props.height === "min-content") + this.setTextDoc(box.props.fieldKey, box.CurrentDiv, xf, BoolCast(box.props.Document.autoHeight, false) || box.props.height === "min-content"); } else { this.TextDoc = undefined; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index fd76cbbd3..7f979cd3b 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -237,10 +237,11 @@ export class MainView extends React.Component { } onColorClick = (e: React.MouseEvent) => { - let target = (e.nativeEvent! as any).path[0]; - let parent = (e.nativeEvent! as any).path[1]; - if (target.localName === "input" || parent.localName === "span") + let target = (e.nativeEvent as any).path[0]; + let parent = (e.nativeEvent as any).path[1]; + if (target.localName === "input" || parent.localName === "span") { e.stopPropagation(); + } } diff --git a/src/client/views/PresentationView.tsx b/src/client/views/PresentationView.tsx index d2d41a4ba..1dacbb663 100644 --- a/src/client/views/PresentationView.tsx +++ b/src/client/views/PresentationView.tsx @@ -40,8 +40,8 @@ class PresentationViewList extends React.Component { //this doc is selected className += " presentationView-selected"; } - let onEnter = (e: React.PointerEvent) => { document.libraryBrush = true; } - let onLeave = (e: React.PointerEvent) => { document.libraryBrush = false; } + let onEnter = (e: React.PointerEvent) => { document.libraryBrush = true; }; + let onLeave = (e: React.PointerEvent) => { document.libraryBrush = false; }; return (
{ @action.bound removeDocument(doc: Doc): boolean { - let docView = DocumentManager.Instance.getDocumentView(doc, this.props.ContainingCollectionView) + let docView = DocumentManager.Instance.getDocumentView(doc, this.props.ContainingCollectionView); docView && SelectionManager.DeselectDoc(docView); const props = this.props; //TODO This won't create the field if it doesn't already exist diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index f2b3528b8..5beb89315 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -347,7 +347,7 @@ export class CollectionDockingView extends React.Component CollectionDockingView.Instance.AddTab(stack, doc)} />, upDiv); tab.reactComponents = [upDiv]; tab.element.append(upDiv); @@ -432,8 +432,9 @@ export class DockedFrameRenderer extends React.Component { @observable private _document: Opt; get _stack(): any { let parent = (this.props as any).glContainer.parent.parent; - if (this._document && this._document.excludeFromLibrary && parent.parent && parent.parent.contentItems.length > 1) + if (this._document && this._document.excludeFromLibrary && parent.parent && parent.parent.contentItems.length > 1) { return parent.parent.contentItems[1]; + } return parent; } constructor(props: any) { diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx index b62d3f7bb..b2d016934 100644 --- a/src/client/views/collections/CollectionPDFView.tsx +++ b/src/client/views/collections/CollectionPDFView.tsx @@ -40,7 +40,7 @@ export class CollectionPDFView extends React.Component { // console.log(this.props.Document[HeightSym]()); }, { fireImmediately: true } - ) + ); } public static LayoutString(fieldKey: string = "data") { diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 14a7d19d0..faea8d44d 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -87,8 +87,9 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { let columnDocs = DocListCast(schemaDoc.data); if (columnDocs) { let ddoc = columnDocs.find(doc => doc.title === columnName); - if (ddoc) + if (ddoc) { return ddoc; + } } } return this.props.Document; @@ -285,7 +286,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { } getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate( - - this.borderWidth - this.DIVIDER_WIDTH - this.tableWidth, - this.borderWidth); + - this.borderWidth - this.DIVIDER_WIDTH - this.tableWidth, - this.borderWidth) get documentKeysCheckList() { @@ -334,7 +335,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { columns={this.tableColumns} column={{ ...ReactTableDefaults.column, Cell: this.renderCell, }} getTrProps={this.getTrProps} - /> + />; } @computed @@ -360,7 +361,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { addDocTab={this.props.addDocTab} setPreviewScript={this.setPreviewScript} previewScript={this.previewScript} - /> + />; } @action setPreviewScript = (script: string) => { @@ -409,7 +410,7 @@ export class CollectionSchemaPreview extends React.Component this.nativeWidth * this.contentScaling(); private PanelHeight = () => this.nativeHeight * this.contentScaling(); - private getTransform = () => this.props.getTransform().translate(-this.centeringOffset, 0).scale(1 / this.contentScaling()) + private getTransform = () => this.props.getTransform().translate(-this.centeringOffset, 0).scale(1 / this.contentScaling()); get centeringOffset() { return (this.props.width() - this.nativeWidth * this.contentScaling()) / 2; } @action onPreviewScriptChange = (e: React.ChangeEvent) => { diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index e1ac3505b..f5ad4ee95 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -101,7 +101,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { let childFocus = (doc: Doc) => { doc.libraryBrush = true; this.props.focus(this.props.Document); // just focus on this collection, not the underlying document because the API doesn't support adding an offset to focus on and we can't pan zoom our contents to be centered. - } + }; return (
doc) { whenActiveChanged={this.props.whenActiveChanged} />
); - }) + }); } onContextMenu = (e: React.MouseEvent): void => { if (!e.isPropagationStopped() && this.props.Document[Id] !== "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index b13694e9d..3e495b734 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -67,8 +67,8 @@ class TreeView extends React.Component { @undoBatch delete = () => this.props.deleteDoc(this.props.document); @undoBatch openRight = async () => this.props.addDocTab(this.props.document, "openRight"); - @action onMouseEnter = () => { this._isOver = true; } - @action onMouseLeave = () => { this._isOver = false; } + @action onMouseEnter = () => { this._isOver = true; }; + @action onMouseLeave = () => { this._isOver = false; }; onPointerEnter = (e: React.PointerEvent): void => { this.props.active() && (this.props.document.libraryBrush = true); @@ -89,8 +89,8 @@ class TreeView extends React.Component { let bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2); let before = x[1] < bounds[1]; let inside = x[0] > bounds[0] + 75 || (!before && this._bulletType === BulletType.Collapsible); - this._header!.current!.className = "treeViewItem-header" - if (inside && this._bulletType != BulletType.List) this._header!.current!.className += " treeViewItem-header-inside"; + this._header!.current!.className = "treeViewItem-header"; + if (inside && this._bulletType !== BulletType.List) this._header!.current!.className += " treeViewItem-header-inside"; else if (before) this._header!.current!.className += " treeViewItem-header-above"; else if (!before) this._header!.current!.className += " treeViewItem-header-below"; e.stopPropagation(); @@ -192,7 +192,7 @@ class TreeView extends React.Component { if (inside) { let docList = Cast(this.props.document.data, listSpec(Doc)); if (docList !== undefined) { - addDoc = (doc: Doc) => { docList && docList.push(doc); return true; } + addDoc = (doc: Doc) => { docList && docList.push(doc); return true; }; } } let added = false; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index c4dd534ed..be75c6c5c 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -109,7 +109,7 @@ export class CollectionFreeFormLinksView extends React.Component [ , ...this.views - ]; + ] render() { const containerName = `collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`; const easing = () => this.props.Document.panTransformType === "Ease"; diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index dedcc3172..05dc6f534 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -321,7 +321,7 @@ export class MarqueeView extends React.Component summary.imageSummary = imageSummary; this.props.addDocument(imageSummary, false); } - }) + }); newCollection.proto!.summaryDoc = summary; selected = [newCollection]; newCollection.x = bounds.left + bounds.width; diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index f6b1c62ee..858959d81 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -48,7 +48,7 @@ export class CollectionFreeFormDocumentView extends DocComponent this.props.PanelHeight(); getTransform = (): Transform => this.props.ScreenToLocalTransform() .translate(-this.X, -this.Y) - .scale(1 / this.contentScaling()).scale(1 / this.zoom); + .scale(1 / this.contentScaling()).scale(1 / this.zoom) animateBetweenIcon = (icon: number[], stime: number, maximizing: boolean) => { this.props.bringToFront(this.props.Document); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 7c058d91c..4992669df 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -168,8 +168,8 @@ export class DocumentView extends DocComponent(Docu public static animateBetweenIconFunc = (doc: Doc, width: number, height: number, stime: number, maximizing: boolean, cb?: (progress: number) => void) => { setTimeout(() => { let now = Date.now(); - let progress = now < stime + 200 ? Math.min(1, (now - stime) / 200) : 1 - doc.width = progress === 1 ? width : maximizing ? 25 + (width - 25) * progress : width + (25 - width) * progress + let progress = now < stime + 200 ? Math.min(1, (now - stime) / 200) : 1; + doc.width = progress === 1 ? width : maximizing ? 25 + (width - 25) * progress : width + (25 - width) * progress; doc.height = progress === 1 ? height : maximizing ? 25 + (height - 25) * progress : height + (25 - height) * progress; cb && cb(progress); if (now < stime + 200) { @@ -229,7 +229,7 @@ export class DocumentView extends DocComponent(Docu if (minimizedDoc) { let scrpt = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).inverse().transformPoint( NumCast(minimizedDoc.x) - NumCast(this.Document.x), NumCast(minimizedDoc.y) - NumCast(this.Document.y)); - this.collapseTargetsToPoint(scrpt, await DocListCastAsync(minimizedDoc.maximizedDocs)) + this.collapseTargetsToPoint(scrpt, await DocListCastAsync(minimizedDoc.maximizedDocs)); } } @@ -372,8 +372,8 @@ export class DocumentView extends DocComponent(Docu this._lastTap = Date.now(); } - deleteClicked = (): void => { this.props.removeDocument && this.props.removeDocument(this.props.Document); } - fieldsClicked = (): void => { this.props.addDocTab(Docs.KVPDocument(this.props.Document, { width: 300, height: 300 }), "onRight") }; + deleteClicked = (): void => { this.props.removeDocument && this.props.removeDocument(this.props.Document); }; + fieldsClicked = (): void => { this.props.addDocTab(Docs.KVPDocument(this.props.Document, { width: 300, height: 300 }), "onRight"); }; makeBtnClicked = (): void => { let doc = Doc.GetProto(this.props.Document); doc.isButton = !BoolCast(doc.isButton, false); @@ -527,7 +527,7 @@ export class DocumentView extends DocComponent(Docu onPointerLeave = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = false; }; isSelected = () => SelectionManager.IsSelected(this); - @action select = (ctrlPressed: boolean) => { SelectionManager.SelectDoc(this, ctrlPressed); } + @action select = (ctrlPressed: boolean) => { SelectionManager.SelectDoc(this, ctrlPressed); }; @computed get nativeWidth() { return this.Document.nativeWidth || 0; } @computed get nativeHeight() { return this.Document.nativeHeight || 0; } diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 36d902c4f..df12f261b 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -161,7 +161,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe de.data.moveDocument(de.data.draggedDocuments[0], stackDoc, (doc) => { Cast(stackDoc.data, listSpec(Doc))!.push(doc); return true; - }) + }); } } } diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 6b8b64c5f..f208ce2ce 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -188,8 +188,9 @@ export class ImageBox extends DocComponent(ImageD } @action onError = () => { let timeout = this._curSuffix === "_s" ? this._smallRetryCount : this._curSuffix === "_m" ? this._mediumRetryCount : this._largeRetryCount; - if (timeout < 10) + if (timeout < 10) { setTimeout(this.retryPath, Math.min(10000, timeout * 5)); + } } _curSuffix = "_m"; render() { diff --git a/src/client/views/pdf/PDFAnnotationLayer.tsx b/src/client/views/pdf/PDFAnnotationLayer.tsx index e92dcacbf..1f49e0d2f 100644 --- a/src/client/views/pdf/PDFAnnotationLayer.tsx +++ b/src/client/views/pdf/PDFAnnotationLayer.tsx @@ -19,6 +19,6 @@ export class PDFAnnotationLayer extends React.Component {
- ) + ); } } \ No newline at end of file diff --git a/src/client/views/pdf/PDFMenu.tsx b/src/client/views/pdf/PDFMenu.tsx index 7817e8c26..2ed891131 100644 --- a/src/client/views/pdf/PDFMenu.tsx +++ b/src/client/views/pdf/PDFMenu.tsx @@ -162,6 +162,6 @@ export default class PDFMenu extends React.Component {
- ) + ); } } \ No newline at end of file diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 69372f43b..8c0aaea00 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -198,7 +198,7 @@ class Viewer extends React.Component { { @action getPageImage = async (page: number) => { let handleError = () => this.getRenderedPage(page); - if (this._isPage[page] != "image") { + if (this._isPage[page] !== "image") { this._isPage[page] = "image"; const address = this.props.url; let res = JSON.parse(await rp.get(DocServer.prepend(`/thumbnail${address.substring("files/".length, address.length - ".pdf".length)}-${page + 1}.PNG`))); diff --git a/src/server/index.ts b/src/server/index.ts index 7ef542b01..2901f61ed 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -172,7 +172,7 @@ function LoadPage(file: string, pageNumber: number, res: Response) { canvasContext: canvasAndContext.context, viewport: viewport, canvasFactory: factory - } + }; console.log("read " + pageNumber); page.render(renderContext).promise -- cgit v1.2.3-70-g09d2 From 0674331f3611d297028526c888c718a75b012e0a Mon Sep 17 00:00:00 2001 From: bob Date: Wed, 19 Jun 2019 09:36:21 -0400 Subject: fixed resizing stacking views. changed defaults for new docs in treeView --- src/client/views/DocumentDecorations.tsx | 4 ++-- src/client/views/collections/CollectionTreeView.tsx | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src/client/views/DocumentDecorations.tsx') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index e60f8c86c..d8642d675 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -503,8 +503,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> proto.nativeWidth = (doc.width || 0) / doc.height * NumCast(proto.nativeHeight); } } else { - doc.width = zoomBasis * actualdW; - doc.height = zoomBasis * actualdH; + dW && (doc.width = zoomBasis * actualdW); + dH && (doc.height = zoomBasis * actualdH); proto.autoHeight = undefined; } } diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index f6c9ba86b..5e690361c 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -22,6 +22,8 @@ import React = require("react"); import { Transform } from '../../util/Transform'; import { SelectionManager } from '../../util/SelectionManager'; import { emptyFunction } from '../../../Utils'; +import { List } from '../../../new_fields/List'; +import { Templates } from '../Templates'; export interface TreeViewProps { @@ -144,8 +146,9 @@ class TreeView extends React.Component { GetValue={() => StrCast(this.props.document[key])} OnFillDown={(value: string) => { Doc.GetProto(this.props.document)[key] = value; - let doc = Docs.FreeformDocument([], { title: "untitled" }); + let doc = Docs.FreeformDocument([], { title: "", x: 0, y: 0, width: 100, height: 25 }); TreeView.loadId = doc[Id]; + doc.templates = new List([Templates.Title.Layout]); this.props.addDocument(doc); return true; }} -- cgit v1.2.3-70-g09d2 From e9d62f4ca0dbeb57e46239047041a8a04da7b504 Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 20 Jun 2019 11:26:16 -0400 Subject: changed color picker. fixed delting selected docs. fixed scaling items in nested panels. --- src/client/util/SelectionManager.ts | 2 +- src/client/views/DocumentDecorations.tsx | 6 ++---- src/client/views/InkingControl.tsx | 11 +++++++++-- src/client/views/MainView.tsx | 6 +++--- 4 files changed, 15 insertions(+), 10 deletions(-) (limited to 'src/client/views/DocumentDecorations.tsx') diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index 09bccb1a0..7dbb81e76 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -66,7 +66,7 @@ export namespace SelectionManager { export function GetIsDragging() { return manager.IsDragging; } export function SelectedDocuments(): Array { - return manager.SelectedDocuments; + return manager.SelectedDocuments.slice(); } export function ViewsSortedHorizontally(): DocumentView[] { let sorted = SelectionManager.SelectedDocuments().slice().sort((doc1, doc2) => { diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index d8642d675..2c0e18bbb 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -464,16 +464,14 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> runInAction(() => FormattedTextBox.InputBoxOverlay = undefined); SelectionManager.SelectedDocuments().forEach(element => { - const rect = element.ContentDiv ? element.ContentDiv.getBoundingClientRect() : new DOMRect(); - - if (rect.width !== 0 && (dX !== 0 || dY !== 0 || dW !== 0 || dH !== 0)) { + if (dX !== 0 || dY !== 0 || dW !== 0 || dH !== 0) { let doc = PositionDocument(element.props.Document); let nwidth = doc.nativeWidth || 0; let nheight = doc.nativeHeight || 0; let zoomBasis = NumCast(doc.zoomBasis, 1); let width = (doc.width || 0) / zoomBasis; let height = (doc.height || (nheight / nwidth * width)) / zoomBasis; - let scale = width / rect.width; + let scale = element.props.ScreenToLocalTransform().Scale; let actualdW = Math.max(width + (dW * scale), 20); let actualdH = Math.max(height + (dH * scale), 20); doc.x = (doc.x || 0) + dX * (actualdW - width); diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx index b98132c23..0837e07a9 100644 --- a/src/client/views/InkingControl.tsx +++ b/src/client/views/InkingControl.tsx @@ -28,11 +28,18 @@ export class InkingControl extends React.Component { switchTool = (tool: InkTool): void => { this._selectedTool = tool; } + decimalToHexString(number: number) { + if (number < 0) { + number = 0xFFFFFFFF + number + 1; + } + + return number.toString(16).toUpperCase(); + } @action switchColor = (color: ColorResult): void => { - this._selectedColor = color.hex; - SelectionManager.SelectedDocuments().forEach(doc => Doc.GetProto(doc.props.Document).backgroundColor = color.hex); + this._selectedColor = color.hex + (color.rgb.a !== undefined ? this.decimalToHexString(Math.round(color.rgb.a * 255)) : "ff"); + SelectionManager.SelectedDocuments().forEach(doc => Doc.GetProto(doc.props.Document).backgroundColor = this._selectedColor); } @action diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index e3d4ff8b5..51630c29b 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -3,7 +3,7 @@ import { faFilePdf, faFilm, faFont, faGlobeAsia, faImage, faMusic, faObjectGroup import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, configure, observable, runInAction, trace } from 'mobx'; import { observer } from 'mobx-react'; -import { CirclePicker, SliderPicker, BlockPicker, TwitterPicker } from 'react-color'; +import { CirclePicker, SliderPicker, BlockPicker, TwitterPicker, SketchPicker } from 'react-color'; import "normalize.css"; import * as React from 'react'; import Measure from 'react-measure'; @@ -272,8 +272,8 @@ export class MainView extends React.Component {
  • {btns.map(btn => -- cgit v1.2.3-70-g09d2