From c1f49a0974982b803c565b6ac3c8931be7c8972f Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 8 May 2020 16:57:30 -0400 Subject: added " " for switching between pan/zoom & marquee. --- src/client/views/PreviewCursor.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/views/PreviewCursor.tsx') diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx index df30c1215..80c7f3d25 100644 --- a/src/client/views/PreviewCursor.tsx +++ b/src/client/views/PreviewCursor.tsx @@ -81,7 +81,7 @@ export class PreviewCursor extends React.Component<{}> { if (e.key !== "Escape" && e.key !== "Backspace" && e.key !== "Delete" && e.key !== "CapsLock" && e.key !== "Alt" && e.key !== "Shift" && e.key !== "Meta" && e.key !== "Control" && e.key !== "Insert" && e.key !== "Home" && e.key !== "End" && e.key !== "PageUp" && e.key !== "PageDown" && - e.key !== "NumLock" && + e.key !== "NumLock" && e.key !== " " && (e.keyCode < 112 || e.keyCode > 123) && // F1 thru F12 keys !e.key.startsWith("Arrow") && !e.defaultPrevented) { -- cgit v1.2.3-70-g09d2 From 4914965affb984e04e847460ce1b5750807b316f Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 9 May 2020 15:56:11 -0400 Subject: fixed missing gear in golden layout. fixed double dragging events. changed dragging to give prefernce to modifier keys over dropactions. changed names of Documents to Catalog. added document copy past with ctrl c/ctrl v --- src/client/util/DragManager.ts | 7 ++----- src/client/views/GlobalKeyHandler.ts | 10 ++++++++++ src/client/views/MainView.tsx | 3 +-- src/client/views/PreviewCursor.tsx | 13 +++++++++++++ src/client/views/collections/CollectionDockingView.tsx | 2 +- src/client/views/collections/CollectionSubView.tsx | 10 ++++++---- src/client/views/collections/CollectionTreeView.tsx | 3 +-- src/client/views/collections/CollectionView.tsx | 10 +++++----- src/client/views/nodes/DocumentView.tsx | 15 ++++++++++----- src/server/authentication/models/current_user_utils.ts | 14 +++++++------- 10 files changed, 56 insertions(+), 31 deletions(-) (limited to 'src/client/views/PreviewCursor.tsx') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index cc8cc38dd..4f547e2f7 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -176,7 +176,7 @@ export namespace DragManager { element: HTMLElement, dropFunc: (e: Event, de: DropEvent) => void, doc?: Doc, - preDropFunc?: (e: Event, de: DropEvent) => void, + preDropFunc?: (e: Event, de: DropEvent, targetAction: dropActionType) => void, ): DragDropDisposer { if ("canDrop" in element.dataset) { throw new Error( @@ -187,10 +187,7 @@ export namespace DragManager { const handler = (e: Event) => dropFunc(e, (e as CustomEvent).detail); const preDropHandler = (e: Event) => { const de = (e as CustomEvent).detail; - if (de.complete.docDragData && doc?.targetDropAction) { - de.complete.docDragData.dropAction = StrCast(doc.targetDropAction) as dropActionType; - } - preDropFunc?.(e, de); + preDropFunc?.(e, de, StrCast(doc?.targetDropAction) as dropActionType); }; element.addEventListener("dashOnDrop", handler); doc && element.addEventListener("dashPreDrop", preDropHandler); diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index c73e1a66a..d9281ac24 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -15,6 +15,7 @@ import { DocumentView } from "./nodes/DocumentView"; import GoogleAuthenticationManager from "../apis/GoogleAuthenticationManager"; import { CollectionFreeFormView } from "./collections/collectionFreeForm/CollectionFreeFormView"; import { MarqueeView } from "./collections/collectionFreeForm/MarqueeView"; +import { Id } from "../../new_fields/FieldSymbols"; const modifiers = ["control", "meta", "shift", "alt"]; type KeyHandler = (keycode: string, e: KeyboardEvent) => KeyControlInfo | Promise; @@ -240,8 +241,17 @@ export default class KeyManager { break; case "a": case "v": + stopPropagation = false; + preventDefault = false; + break; case "x": case "c": + SelectionManager.SelectedDocuments().length && navigator.clipboard.writeText("__DashDocId:" + SelectionManager.SelectedDocuments()[0].Document[Id]); + // window.getSelection()?.removeAllRanges(); + // let range = document.createRange(); + // range.selectNode(SelectionManager.SelectedDocuments()[0].ContentDiv!); + // window.getSelection()?.addRange(range); + // document.execCommand('copy'); stopPropagation = false; preventDefault = false; break; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index fad6bf295..b6dfe60e5 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -249,8 +249,7 @@ export class MainView extends React.Component { title: "Collection " + workspaceCount, }; const freeformDoc = CurrentUserUtils.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions); - Doc.AddDocToList(Doc.GetProto(Doc.UserDoc().myDocuments as Doc), "data", freeformDoc); - const mainDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600, path: [Doc.UserDoc().myDocuments as Doc] }], { title: `Workspace ${workspaceCount}` }, id, "row"); + const mainDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600, path: [Doc.UserDoc().myCatalog as Doc] }], { title: `Workspace ${workspaceCount}` }, id, "row"); const toggleTheme = ScriptField.MakeScript(`self.darkScheme = !self.darkScheme`); mainDoc.contextMenuScripts = new List([toggleTheme!]); diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx index 80c7f3d25..b9036bf1e 100644 --- a/src/client/views/PreviewCursor.tsx +++ b/src/client/views/PreviewCursor.tsx @@ -6,6 +6,7 @@ import "./PreviewCursor.scss"; import { Docs } from '../documents/Documents'; import { Doc } from '../../new_fields/Doc'; import { Transform } from "../util/Transform"; +import { DocServer } from '../DocServer'; @observer export class PreviewCursor extends React.Component<{}> { @@ -49,6 +50,18 @@ export class PreviewCursor extends React.Component<{}> { })); } + if (e.clipboardData.getData("text/plain").includes("__DashDocId:")) { + const docid = e.clipboardData.getData("text/plain").split("__DashDocId:")[1]; + return DocServer.GetRefField(docid).then(doc => { + if (doc instanceof Doc) { + const alias = Doc.MakeAlias(doc); + alias.x = newPoint[0]; + alias.y = newPoint[1]; + PreviewCursor._addDocument(alias); + } + }); + } + // creates text document return PreviewCursor._addLiveTextDoc(Docs.Create.TextDocument("", { _width: 500, diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index c1edc0fe7..6fdb96f0d 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -527,7 +527,7 @@ export class CollectionDockingView extends React.Component(schemaCtor: (doc: Doc) => T, moreProps?: protected onGesture(e: Event, ge: GestureUtils.GestureEvent) { } - protected onInternalPreDrop(e: Event, de: DragManager.DropEvent) { + protected onInternalPreDrop(e: Event, de: DragManager.DropEvent, targetAction: dropActionType) { if (de.complete.docDragData) { - if (de.complete.docDragData.draggedDocuments.some(d => this.childDocs.includes(d))) { - de.complete.docDragData.dropAction = "move"; + // if targetDropAction is, say 'alias', but we're just dragging within a collection, we want to ignore the targetAction. + // otherwise, the targetAction should become the actual action (which can still be overridden by the userDropAction -eg, shift/ctrl keys) + if (targetAction && !de.complete.docDragData.draggedDocuments.some(d => d.context === this.props.Document && this.childDocs.includes(d))) { + de.complete.docDragData.dropAction = targetAction; } e.stopPropagation(); } diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 58d021b5c..7086ba380 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -410,7 +410,6 @@ class TreeView extends React.Component { @computed get renderTitle() { TraceMobx(); - const onItemDown = SetupDrag(this._tref, () => this.dataDoc, this.move, this.props.dropAction, this.props.treeViewId[Id], true); (!TreeView._editTitleScript) && (TreeView._editTitleScript = ScriptField.MakeFunction("setInPlace(self, 'editTitle', true)")); const headerElements = ( <> @@ -432,7 +431,7 @@ class TreeView extends React.Component { ); return <> -
boolean; // allows a document that renders a Collection view to filter or modify any documents added to the collection (see PresBox for an example) + filterAddDocument: (doc: Doc | Doc[]) => boolean; // allows a document that renders a Collection view to filter or modify any documents added to the collection (see PresBox for an example) childLayoutTemplate?: () => Opt; // specify a layout Doc template to use for children of the collection childLayoutString?: string; // specify a layout string to use for children of the collection } export interface CollectionRenderProps { - addDocument: (document: Doc) => boolean; - removeDocument: (document: Doc) => boolean; - moveDocument: (document: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean) => boolean; + addDocument: (document: Doc | Doc[]) => boolean; + removeDocument: (document: Doc | Doc[]) => boolean; + moveDocument: (document: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => boolean; active: () => boolean; whenActiveChanged: (isActive: boolean) => void; PanelWidth: () => number; @@ -152,7 +152,7 @@ export class CollectionView extends Touchable boolean): boolean => { + moveDocument = (doc: Doc, targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean): boolean => { if (Doc.AreProtosEqual(this.props.Document, targetCollection)) { return true; } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index e3b69b8f3..ebfc38a54 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -4,7 +4,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; import * as rp from "request-promise"; -import { Doc, DocListCast, HeightSym, Opt, WidthSym } from "../../../new_fields/Doc"; +import { Doc, DocListCast, HeightSym, Opt, WidthSym, DataSym } from "../../../new_fields/Doc"; import { Document } from '../../../new_fields/documentSchemas'; import { Id } from '../../../new_fields/FieldSymbols'; import { InkTool } from '../../../new_fields/InkField'; @@ -15,7 +15,7 @@ import { BoolCast, Cast, NumCast, StrCast } from "../../../new_fields/Types"; import { ImageField } from '../../../new_fields/URLField'; import { TraceMobx } from '../../../new_fields/util'; import { GestureUtils } from '../../../pen-gestures/GestureUtils'; -import { emptyFunction, OmitKeys, returnOne, returnTransparent, Utils } from "../../../Utils"; +import { emptyFunction, OmitKeys, returnOne, returnTransparent, Utils, emptyPath } from "../../../Utils"; import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils'; import { ClientRecommender } from '../../ClientRecommender'; import { DocServer } from "../../DocServer"; @@ -549,7 +549,7 @@ export class DocumentView extends DocComponent(Docu if (!e.altKey && (!this.topMost || this.Document.onDragStart || this.onClickHandler) && (e.buttons === 1 || InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE))) { document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); - this.startDragging(this._downX, this._downY, this.props.dropAction ? this.props.dropAction : this.Document.dropAction ? this.Document.dropAction as any : e.ctrlKey || e.altKey ? "alias" : undefined); + this.startDragging(this._downX, this._downY, ((e.ctrlKey || e.altKey) && "alias") || (this.props.dropAction || this.Document.dropAction || undefined) as dropActionType); } } e.stopPropagation(); // doesn't actually stop propagation since all our listeners are listening to events on 'document' however it does mark the event as cancelBubble=true which we test for in the move event handlers @@ -721,6 +721,7 @@ export class DocumentView extends DocComponent(Docu let open = cm.findByDescription("Add a Perspective..."); const openItems: ContextMenuProps[] = open && "subitems" in open ? open.subitems : []; + openItems.push({ description: "New Echo ", event: () => this.props.addDocTab(Doc.MakeAlias(this.props.Document), "onRight"), icon: "layer-group" }); openItems.push({ description: "Open Fields ", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "onRight"), icon: "layer-group" }); templateDoc && openItems.push({ description: "Open Template ", event: () => this.props.addDocTab(templateDoc, "onRight"), icon: "eye" }); if (!open) { @@ -864,8 +865,12 @@ export class DocumentView extends DocComponent(Docu const path = this.props.LibraryPath.reduce((p: string, d: Doc) => p + "/" + (Doc.AreProtosEqual(d, (Doc.UserDoc()["tabs-button-library"] as Doc).sourcePanel as Doc) ? "" : d.title), ""); cm.addItem({ description: `path: ${path}`, event: () => { - this.props.LibraryPath.map(lp => Doc.GetProto(lp).treeViewOpen = lp.treeViewOpen = true); - Doc.linkFollowHighlight(this.props.Document); + if (this.props.LibraryPath !== emptyPath) { + this.props.LibraryPath.map(lp => Doc.GetProto(lp).treeViewOpen = lp.treeViewOpen = true); + Doc.linkFollowHighlight(this.props.Document); + } else { + Doc.AddDocToList(Doc.GetProto(Doc.UserDoc().myCatalog as Doc), "data", this.props.Document[DataSym]); + } }, icon: "check" }); } diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index a776b6f10..bebf77a8c 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -507,13 +507,13 @@ export class CurrentUserUtils { return doc.myWorkspaces as Doc; } - static setupDocumentCollection(doc: Doc) { - if (doc.myDocuments === undefined) { - doc.myDocuments = new PrefetchProxy(Docs.Create.TreeDocument([], { - title: "DOCUMENTS", _height: 42, forceActive: true, boxShadow: "0 0", treeViewPreventOpen: false, lockedPosition: true, + static setupCatalog(doc: Doc) { + if (doc.myCatalog === undefined) { + doc.myCatalog = new PrefetchProxy(Docs.Create.TreeDocument([], { + title: "CATALOG", _height: 42, forceActive: true, boxShadow: "0 0", treeViewPreventOpen: false, lockedPosition: true, })); } - return doc.myDocuments as Doc; + return doc.myCatalog as Doc; } static setupRecentlyClosed(doc: Doc) { // setup Recently Closed library item @@ -533,7 +533,7 @@ export class CurrentUserUtils { // setup the Library button which will display the library panel. This panel includes a collection of workspaces, documents, and recently closed views static setupLibraryPanel(doc: Doc, sidebarContainer: Doc) { const workspaces = CurrentUserUtils.setupWorkspaces(doc); - const documents = CurrentUserUtils.setupDocumentCollection(doc); + const documents = CurrentUserUtils.setupCatalog(doc); const recentlyClosed = CurrentUserUtils.setupRecentlyClosed(doc); if (doc["tabs-button-library"] === undefined) { @@ -541,7 +541,7 @@ export class CurrentUserUtils { _width: 50, _height: 25, title: "Library", _fontSize: 10, letterSpacing: "0px", textTransform: "unset", borderRounding: "5px 5px 0px 0px", boxShadow: "3px 3px 0px rgb(34, 34, 34)", sourcePanel: new PrefetchProxy(Docs.Create.TreeDocument([workspaces, documents, recentlyClosed, doc], { - title: "Library", _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "move", lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true + title: "Library", _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias", lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true })) as any as Doc, targetContainer: new PrefetchProxy(sidebarContainer) as any as Doc, onClick: ScriptField.MakeScript("this.targetContainer.proto = this.sourcePanel;") -- cgit v1.2.3-70-g09d2 From 638fb6b16c4d69090e3806cca0a1a1909ec612c9 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 9 May 2020 21:43:04 -0400 Subject: added document clone and paste for all collections --- src/client/views/DocumentDecorations.tsx | 4 +- src/client/views/GlobalKeyHandler.ts | 65 +++++++++++++--- src/client/views/MainView.tsx | 2 + src/client/views/PreviewCursor.tsx | 91 ++++++++++++---------- .../views/collections/CollectionTreeView.tsx | 6 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 12 ++- .../collections/collectionFreeForm/MarqueeView.tsx | 5 +- 7 files changed, 127 insertions(+), 58 deletions(-) (limited to 'src/client/views/PreviewCursor.tsx') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 9b6105811..1054822c7 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -174,8 +174,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> } @undoBatch @action - onCloseClick = async (e: PointerEvent) => { - if (e.button === 0) { + onCloseClick = async (e: PointerEvent | undefined) => { + if (!e?.button) { const recent = Cast(Doc.UserDoc().myRecentlyClosed, Doc) as Doc; const selected = SelectionManager.SelectedDocuments().slice(); SelectionManager.DeselectAll(); diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index d9281ac24..3fd14735b 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -1,10 +1,10 @@ -import { UndoManager } from "../util/UndoManager"; +import { UndoManager, undoBatch } from "../util/UndoManager"; import { SelectionManager } from "../util/SelectionManager"; import { CollectionDockingView } from "./collections/CollectionDockingView"; import { MainView } from "./MainView"; import { DragManager } from "../util/DragManager"; import { action, runInAction } from "mobx"; -import { Doc } from "../../new_fields/Doc"; +import { Doc, DocListCast } from "../../new_fields/Doc"; import { DictationManager } from "../util/DictationManager"; import SharingManager from "../util/SharingManager"; import { Cast, PromiseValue, NumCast } from "../../new_fields/Types"; @@ -16,6 +16,11 @@ import GoogleAuthenticationManager from "../apis/GoogleAuthenticationManager"; import { CollectionFreeFormView } from "./collections/collectionFreeForm/CollectionFreeFormView"; import { MarqueeView } from "./collections/collectionFreeForm/MarqueeView"; import { Id } from "../../new_fields/FieldSymbols"; +import { DocumentDecorations } from "./DocumentDecorations"; +import { DocumentType } from "../documents/DocumentTypes"; +import { DocServer } from "../DocServer"; +import { List } from "../../new_fields/List"; +import { DateField } from "../../new_fields/DateField"; const modifiers = ["control", "meta", "shift", "alt"]; type KeyHandler = (keycode: string, e: KeyboardEvent) => KeyControlInfo | Promise; @@ -245,15 +250,25 @@ export default class KeyManager { preventDefault = false; break; case "x": + if (SelectionManager.SelectedDocuments().length) { + const bds = DocumentDecorations.Instance.Bounds; + const pt = [bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2]; + const text = `__DashDocId(${pt[0]},${pt[1]}):` + SelectionManager.SelectedDocuments().map(dv => dv.Document[Id]).join(":"); + SelectionManager.SelectedDocuments().length && navigator.clipboard.writeText(text); + DocumentDecorations.Instance.onCloseClick(undefined); + stopPropagation = false; + preventDefault = false; + } + break; case "c": - SelectionManager.SelectedDocuments().length && navigator.clipboard.writeText("__DashDocId:" + SelectionManager.SelectedDocuments()[0].Document[Id]); - // window.getSelection()?.removeAllRanges(); - // let range = document.createRange(); - // range.selectNode(SelectionManager.SelectedDocuments()[0].ContentDiv!); - // window.getSelection()?.addRange(range); - // document.execCommand('copy'); - stopPropagation = false; - preventDefault = false; + if (SelectionManager.SelectedDocuments().length) { + const bds = DocumentDecorations.Instance.Bounds; + const pt = [bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2]; + const text = `__DashDocId(${pt[0]},${pt[1]}):` + SelectionManager.SelectedDocuments().map(dv => dv.Document[Id]).join(":"); + SelectionManager.SelectedDocuments().length && navigator.clipboard.writeText(text);; + stopPropagation = false; + preventDefault = false; + } break; } @@ -263,6 +278,36 @@ export default class KeyManager { }; }); + public paste(e: ClipboardEvent) { + if (e.clipboardData?.getData("text/plain") !== "" && e.clipboardData?.getData("text/plain").startsWith("__DashDocId(")) { + const first = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0] : undefined; + if (first?.props.Document.type === DocumentType.COL) { + const docids = e.clipboardData.getData("text/plain").split(":"); + let count = 1; + const list: Doc[] = []; + const targetDataDoc = Doc.GetProto(first.props.Document); + const fieldKey = Doc.LayoutFieldKey(first.props.Document); + const docList = DocListCast(targetDataDoc[fieldKey]); + docids.map((did, i) => i && DocServer.GetRefField(did).then(doc => { + count++; + if (doc instanceof Doc) { + list.push(doc); + } + if (count === docids.length) { + const added = list.filter(d => !docList.includes(d)); + if (added.length) { + added.map(doc => doc.context = targetDataDoc); + undoBatch(() => { + targetDataDoc[fieldKey] = new List([...docList, ...added]); + targetDataDoc[fieldKey + "-lastModified"] = new DateField(new Date(Date.now())); + })(); + } + } + })); + } + } + } + async printClipboard() { const text: string = await navigator.clipboard.readText(); } diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index b6dfe60e5..cbaae63bc 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -83,12 +83,14 @@ export class MainView extends React.Component { firstScriptTag.parentNode!.insertBefore(tag, firstScriptTag); window.removeEventListener("keydown", KeyManager.Instance.handle); window.addEventListener("keydown", KeyManager.Instance.handle); + window.addEventListener("paste", KeyManager.Instance.paste); } componentWillUnMount() { window.removeEventListener("keydown", KeyManager.Instance.handle); window.removeEventListener("pointerdown", this.globalPointerDown); window.removeEventListener("pointerup", this.globalPointerUp); + window.removeEventListener("paste", KeyManager.Instance.paste); } constructor(props: Readonly<{}>) { diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx index b9036bf1e..14b5b3fce 100644 --- a/src/client/views/PreviewCursor.tsx +++ b/src/client/views/PreviewCursor.tsx @@ -7,13 +7,15 @@ import { Docs } from '../documents/Documents'; import { Doc } from '../../new_fields/Doc'; import { Transform } from "../util/Transform"; import { DocServer } from '../DocServer'; +import { NumCast } from '../../new_fields/Types'; +import { undoBatch } from '../util/UndoManager'; @observer export class PreviewCursor extends React.Component<{}> { static _onKeyPress?: (e: KeyboardEvent) => void; static _getTransform: () => Transform; + static _addDocument: (doc: Doc | Doc[]) => void; static _addLiveTextDoc: (doc: Doc) => void; - static _addDocument: (doc: Doc) => boolean; static _nudge: (x: number, y: number) => boolean; @observable static _clickPoint = [0, 0]; @observable public static Visible = false; @@ -28,62 +30,73 @@ export class PreviewCursor extends React.Component<{}> { const newPoint = PreviewCursor._getTransform().transformPoint(PreviewCursor._clickPoint[0], PreviewCursor._clickPoint[1]); runInAction(() => PreviewCursor.Visible = false); + // tests for URL and makes web document + const re: any = /^https?:\/\//g; if (e.clipboardData.getData("text/plain") !== "") { // tests for youtube and makes video document if (e.clipboardData.getData("text/plain").indexOf("www.youtube.com/watch") !== -1) { const url = e.clipboardData.getData("text/plain").replace("youtube.com/watch?v=", "youtube.com/embed/"); - return PreviewCursor._addDocument(Docs.Create.VideoDocument(url, { + undoBatch(() => PreviewCursor._addDocument(Docs.Create.VideoDocument(url, { title: url, _width: 400, _height: 315, _nativeWidth: 600, _nativeHeight: 472.5, x: newPoint[0], y: newPoint[1] - })); + })))(); } - // tests for URL and makes web document - const re: any = /^https?:\/\//g; - if (re.test(e.clipboardData.getData("text/plain"))) { + else if (re.test(e.clipboardData.getData("text/plain"))) { const url = e.clipboardData.getData("text/plain"); - return PreviewCursor._addDocument(Docs.Create.WebDocument(url, { + undoBatch(() => PreviewCursor._addDocument(Docs.Create.WebDocument(url, { title: url, _width: 500, _height: 300, // nativeWidth: 300, nativeHeight: 472.5, x: newPoint[0], y: newPoint[1] - })); + })))(); } - if (e.clipboardData.getData("text/plain").includes("__DashDocId:")) { - const docid = e.clipboardData.getData("text/plain").split("__DashDocId:")[1]; - return DocServer.GetRefField(docid).then(doc => { + else if (e.clipboardData.getData("text/plain").startsWith("__DashDocId(")) { + const docids = e.clipboardData.getData("text/plain").split(":"); + const strs = docids[0].split(","); + const ptx = Number(strs[0].substring("__DashDocId(".length)); + const pty = Number(strs[1].substring(0, strs[1].length - 1)); + const center = PreviewCursor._getTransform().transformPoint(ptx, pty); + let count = 1; + const list: Doc[] = []; + docids.map((did, i) => i && DocServer.GetRefField(did).then(doc => { + count++; if (doc instanceof Doc) { - const alias = Doc.MakeAlias(doc); - alias.x = newPoint[0]; - alias.y = newPoint[1]; - PreviewCursor._addDocument(alias); + const alias = Doc.MakeClone(doc); + alias.x = newPoint[0] + NumCast(doc.x) - center[0]; + alias.y = newPoint[1] + NumCast(doc.y) - center[1]; + list.push(alias); } - }); - } + if (count === docids.length) { + undoBatch(() => PreviewCursor._addDocument(list))(); + } + })); - // creates text document - return PreviewCursor._addLiveTextDoc(Docs.Create.TextDocument("", { - _width: 500, - limitHeight: 400, - _autoHeight: true, - x: newPoint[0], - y: newPoint[1], - title: "-pasted text-" - })); - } - //pasting in images - if (e.clipboardData.getData("text/html") !== "" && e.clipboardData.getData("text/html").includes(" PreviewCursor._addLiveTextDoc(Docs.Create.TextDocument("", { + _width: 500, + limitHeight: 400, + _autoHeight: true, + x: newPoint[0], + y: newPoint[1], + title: "-pasted text-" + })))(); + } + } else + //pasting in images + if (e.clipboardData.getData("text/html") !== "" && e.clipboardData.getData("text/html").includes(" PreviewCursor._addDocument(Docs.Create.ImageDocument( + arr[1], { + _width: 300, title: arr[1], + x: newPoint[0], + y: newPoint[1], + })))(); + } } } @@ -125,7 +138,7 @@ export class PreviewCursor extends React.Component<{}> { onKeyPress: (e: KeyboardEvent) => void, addLiveText: (doc: Doc) => void, getTransform: () => Transform, - addDocument: (doc: Doc) => boolean, + addDocument: (doc: Doc | Doc[]) => boolean, nudge: (nudgeX: number, nudgeY: number) => boolean) { this._clickPoint = [x, y]; this._onKeyPress = onKeyPress; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index f6fcc1ac4..8cd34e7ed 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -396,7 +396,7 @@ class TreeView extends React.Component { } showContextMenu = (e: React.MouseEvent) => { - simulateMouseClick(this._docRef.current!.ContentDiv!, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30); + this._docRef.current?.ContentDiv && simulateMouseClick(this._docRef.current.ContentDiv, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30); e.stopPropagation(); } focusOnDoc = (doc: Doc) => DocumentManager.Instance.getFirstDocumentView(doc)?.props.focus(doc, true); @@ -772,6 +772,9 @@ export class CollectionTreeView extends CollectionSubView; } + onKeyPress = (e: React.KeyboardEvent) => { + console.log(e); + } render() { if (!(this.props.Document instanceof Doc)) return (null); const dropAction = StrCast(this.props.Document.childDropAction) as dropActionType; @@ -786,6 +789,7 @@ export class CollectionTreeView extends CollectionSubView this._mainEle && this._mainEle.scrollHeight > this._mainEle.clientHeight && e.stopPropagation()} onDrop={this.onTreeDrop} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 6cc0cfcd2..1bc59c727 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1246,8 +1246,16 @@ export class CollectionFreeFormView extends CollectionSubView + return {this.children} diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 1addea6a1..35d925bca 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -24,13 +24,10 @@ import React = require("react"); interface MarqueeViewProps { getContainerTransform: () => Transform; getTransform: () => Transform; - addDocument: (doc: Doc) => boolean; activeDocuments: () => Doc[]; selectDocuments: (docs: Doc[], ink: { Document: Doc, Ink: Map }[]) => void; - removeDocument: (doc: Doc) => boolean; addLiveTextDocument: (doc: Doc) => void; isSelected: () => boolean; - isAnnotationOverlay?: boolean; nudge: (x: number, y: number) => boolean; setPreviewCursor?: (func: (x: number, y: number, drag: boolean) => void) => void; } @@ -248,7 +245,7 @@ export class MarqueeView extends React.Component Date: Mon, 11 May 2020 14:59:54 -0400 Subject: changed Cors behavior for WebBox(On for everything except GoogldDocs). Update Freeze to work for ctrl-resizing text, and showing full screen. reorged context menus. --- src/client/views/DocumentButtonBar.tsx | 2 +- src/client/views/DocumentDecorations.scss | 1 + src/client/views/DocumentDecorations.tsx | 1 + src/client/views/MainView.tsx | 1 + src/client/views/PreviewCursor.tsx | 2 +- .../views/collections/CollectionDockingView.tsx | 12 ++++---- .../views/collections/CollectionStackingView.tsx | 1 + .../collectionFreeForm/CollectionFreeFormView.tsx | 27 +++++++++--------- src/client/views/nodes/DocumentView.tsx | 25 ++++++---------- src/client/views/nodes/ImageBox.tsx | 33 +++++++++++++--------- src/client/views/nodes/WebBox.tsx | 8 ++---- .../views/nodes/formattedText/FormattedTextBox.tsx | 18 +++++++++++- .../formattedText/FormattedTextBoxComment.tsx | 2 +- src/new_fields/Doc.ts | 26 +++++++++++------ .../authentication/models/current_user_utils.ts | 2 +- 15 files changed, 94 insertions(+), 67 deletions(-) (limited to 'src/client/views/PreviewCursor.tsx') diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index 48685302a..10d9ec401 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -194,7 +194,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV e.preventDefault(); let googleDoc = await Cast(dataDoc.googleDoc, Doc); if (!googleDoc) { - const options = { _width: 600, _nativeWidth: 960, _nativeHeight: 800, isAnnotating: false }; + const options = { _width: 600, _nativeWidth: 960, _nativeHeight: 800, isAnnotating: false, UseCors: false }; googleDoc = Docs.Create.WebDocument(googleDocUrl, options); dataDoc.googleDoc = googleDoc; } diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss index 4f34eb9e3..15eb537da 100644 --- a/src/client/views/DocumentDecorations.scss +++ b/src/client/views/DocumentDecorations.scss @@ -72,6 +72,7 @@ $linkGap : 3px; grid-column-start: 5; grid-column-end: 7; border-radius: 100%; + background: dimgray; .borderRadiusTooltip { width: 10px; diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 1054822c7..9669c21a9 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -301,6 +301,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> } SelectionManager.SelectedDocuments().forEach(action((element: DocumentView) => { + if (e.ctrlKey && !element.props.Document._nativeHeight) element.toggleNativeDimensions(); if (dX !== 0 || dY !== 0 || dW !== 0 || dH !== 0) { const doc = Document(element.rootDoc); let nwidth = doc._nativeWidth || 0; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index cbaae63bc..560dd5d11 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -249,6 +249,7 @@ export class MainView extends React.Component { _width: this._panelWidth * .7, _height: this._panelHeight, title: "Collection " + workspaceCount, + _LODdisable: true }; const freeformDoc = CurrentUserUtils.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions); const mainDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600, path: [Doc.UserDoc().myCatalog as Doc] }], { title: `Workspace ${workspaceCount}` }, id, "row"); diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx index 14b5b3fce..2ddca369a 100644 --- a/src/client/views/PreviewCursor.tsx +++ b/src/client/views/PreviewCursor.tsx @@ -46,7 +46,7 @@ export class PreviewCursor extends React.Component<{}> { else if (re.test(e.clipboardData.getData("text/plain"))) { const url = e.clipboardData.getData("text/plain"); undoBatch(() => PreviewCursor._addDocument(Docs.Create.WebDocument(url, { - title: url, _width: 500, _height: 300, + title: url, _width: 500, _height: 300, UseCors: true, // nativeWidth: 300, nativeHeight: 472.5, x: newPoint[0], y: newPoint[1] })))(); diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 296b2453b..50e3b73eb 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -755,8 +755,10 @@ export class DockedFrameRenderer extends React.Component { } get layoutDoc() { return this._document && Doc.Layout(this._document); } - panelWidth = () => this.layoutDoc && this.layoutDoc.maxWidth ? Math.min(Math.max(NumCast(this.layoutDoc._width), NumCast(this.layoutDoc._nativeWidth)), this._panelWidth) : this._panelWidth; - panelHeight = () => this._panelHeight; + nativeAspect = () => this.nativeWidth() ? this.nativeWidth() / this.nativeHeight() : 0; + panelWidth = () => this.layoutDoc?.maxWidth ? Math.min(Math.max(NumCast(this.layoutDoc._width), NumCast(this.layoutDoc._nativeWidth)), this._panelWidth) : + (this.nativeAspect() && this.nativeAspect() < this._panelWidth / this._panelHeight ? this._panelHeight * this.nativeAspect() : this._panelWidth); + panelHeight = () => this.nativeAspect() && this.nativeAspect() > this._panelWidth / this._panelHeight ? this._panelWidth / this.nativeAspect() : this._panelHeight; nativeWidth = () => !this.layoutDoc!._fitWidth ? NumCast(this.layoutDoc!._nativeWidth) || this._panelWidth : 0; nativeHeight = () => !this.layoutDoc!._fitWidth ? NumCast(this.layoutDoc!._nativeHeight) || this._panelHeight : 0; @@ -794,7 +796,7 @@ export class DockedFrameRenderer extends React.Component { return Transform.Identity(); } get previewPanelCenteringOffset() { return this.nativeWidth() ? (this._panelWidth - this.nativeWidth() * this.contentScaling()) / 2 : 0; } - get widthpercent() { return this.nativeWidth() ? `${(this.nativeWidth() * this.contentScaling()) / this.panelWidth() * 100}%` : undefined; } + get widthpercent() { return this.nativeWidth() ? `${(this.nativeWidth() * this.contentScaling()) / this._panelWidth * 100}%` : undefined; } addDocTab = (doc: Doc, location: string, libraryPath?: Doc[]) => { SelectionManager.DeselectAll(); @@ -832,8 +834,8 @@ export class DockedFrameRenderer extends React.Component { ContentScaling={this.contentScaling} PanelWidth={this.panelWidth} PanelHeight={this.panelHeight} - NativeHeight={returnZero} - NativeWidth={returnZero} + NativeHeight={this.nativeHeight} + NativeWidth={this.nativeWidth} ScreenToLocalTransform={this.ScreenToLocalTransform} renderDepth={0} parentActive={returnTrue} diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index c199988c0..979e9e3f8 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -432,6 +432,7 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument) if (!e.isPropagationStopped()) { const subItems: ContextMenuProps[] = []; subItems.push({ description: `${this.props.Document.fillColumn ? "Variable Size" : "Autosize"} Column`, event: () => this.props.Document.fillColumn = !this.props.Document.fillColumn, icon: "plus" }); + subItems.push({ description: `${this.Document._autoHeight ? "Variable Height" : "Auto Height"}`, event: () => this.layoutDoc._autoHeight = !this.layoutDoc._autoHeight, icon: "plus" }); ContextMenu.Instance.addItem({ description: "Options...", subitems: subItems, icon: "eye" }); } } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index d24ba6bb0..129b245b8 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -113,8 +113,8 @@ export class CollectionFreeFormView extends CollectionSubView !this.nativeWidth && !this.isAnnotationOverlay ? this.props.PanelWidth() / 2 / this.parentScaling : 0; // shift so pan position is at center of window for non-overlay collections - private centeringShiftY = () => !this.nativeHeight && !this.isAnnotationOverlay ? this.props.PanelHeight() / 2 / this.parentScaling : 0;// shift so pan position is at center of window for non-overlay collections + private centeringShiftX = () => !this.isAnnotationOverlay ? this.props.PanelWidth() / 2 / this.parentScaling / this.contentScaling : 0; // shift so pan position is at center of window for non-overlay collections + private centeringShiftY = () => !this.isAnnotationOverlay ? this.props.PanelHeight() / 2 / this.parentScaling / this.contentScaling : 0;// shift so pan position is at center of window for non-overlay collections private getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth + 1, -this.borderWidth + 1).translate(-this.centeringShiftX(), -this.centeringShiftY()).transform(this.getLocalTransform()); private getTransformOverlay = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth + 1, -this.borderWidth + 1); private getContainerTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth, -this.borderWidth); @@ -340,12 +340,12 @@ export class CollectionFreeFormView extends CollectionSubView { + Doc.toggleNativeDimensions(this.layoutDoc, this.props.ContentScaling(), this.props.NativeWidth(), this.props.NativeHeight()); + } private thumbIdentifier?: number; @@ -1138,6 +1138,7 @@ export class CollectionFreeFormView extends CollectionSubView { this.props.Document._panX = this.props.Document._panY = 0; this.props.Document.scale = 1; }, icon: "compress-arrows-alt" }); + optionItems.push({ description: !this.layoutDoc._nativeWidth || !this.layoutDoc._nativeHeight ? "Freeze" : "Unfreeze", event: this.toggleNativeDimensions, icon: "snowflake" }); optionItems.push({ description: `${this.Document._LODdisable ? "Enable LOD" : "Disable LOD"}`, event: () => this.Document._LODdisable = !this.Document._LODdisable, icon: "table" }); optionItems.push({ description: `${this.fitToContent ? "Unset" : "Set"} Fit To Container`, event: () => this.Document._fitToBox = !this.fitToContent, icon: !this.fitToContent ? "expand-arrows-alt" : "compress-arrows-alt" }); optionItems.push({ description: `${this.Document.useClusters ? "Uncluster" : "Use Clusters"}`, event: () => this.updateClusters(!this.Document.useClusters), icon: "braille" }); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index aca0433bb..6c9ade83f 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -648,18 +648,8 @@ export class DocumentView extends DocComponent(Docu @undoBatch @action - public static unfreezeNativeDimensions(layoutDoc: Doc) { - layoutDoc._nativeWidth = undefined; - layoutDoc._nativeHeight = undefined; - } - toggleNativeDimensions = () => { - if (this.Document._nativeWidth || this.Document._nativeHeight) { - DocumentView.unfreezeNativeDimensions(this.layoutDoc); - } - else { - Doc.freezeNativeDimensions(this.layoutDoc, this.props.PanelWidth(), this.props.PanelHeight()); - } + Doc.toggleNativeDimensions(this.layoutDoc, this.props.ContentScaling(), this.props.PanelWidth(), this.props.PanelHeight()); } @undoBatch @@ -735,10 +725,6 @@ export class DocumentView extends DocComponent(Docu let options = cm.findByDescription("Options..."); const optionItems: ContextMenuProps[] = options && "subitems" in options ? options.subitems : []; - optionItems.push({ description: `${this.Document._chromeStatus !== "disabled" ? "Hide" : "Show"} Chrome`, event: () => this.Document._chromeStatus = (this.Document._chromeStatus !== "disabled" ? "disabled" : "enabled"), icon: "project-diagram" }); - optionItems.push({ description: `${this.Document._autoHeight ? "Variable Height" : "Auto Height"}`, event: () => this.layoutDoc._autoHeight = !this.layoutDoc._autoHeight, icon: "plus" }); - optionItems.push({ description: this.Document.lockedPosition ? "Unlock Position" : "Lock Position", event: this.toggleLockPosition, icon: BoolCast(this.Document.lockedPosition) ? "unlock" : "lock" }); - optionItems.push({ description: this.Document.lockedTransform ? "Unlock Transform" : "Lock Transform", event: this.toggleLockTransform, icon: BoolCast(this.Document.lockedTransform) ? "unlock" : "lock" }); if (!options) { options = { description: "Options...", subitems: optionItems, icon: "compass" }; cm.addItem(options); @@ -757,6 +743,7 @@ export class DocumentView extends DocComponent(Docu onClicks.push({ description: "Edit onClick Script", event: () => UndoManager.RunInBatch(() => Doc.makeCustomViewClicked(this.props.Document, undefined, "onClick"), "edit onClick"), icon: "edit" }); !existingOnClick && cm.addItem({ description: "OnClick...", subitems: onClicks, icon: "hand-point-right" }); + const funcs: ContextMenuProps[] = []; if (this.Document.onDragStart) { funcs.push({ description: "Drag an Alias", icon: "edit", event: () => this.Document.dragFactory && (this.Document.onDragStart = ScriptField.MakeFunction('getAlias(this.dragFactory)')) }); @@ -768,7 +755,9 @@ export class DocumentView extends DocComponent(Docu const more = cm.findByDescription("More..."); const moreItems: ContextMenuProps[] = more && "subitems" in more ? more.subitems : []; 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._nativeWidth || !this.Document._nativeHeight ? "Freeze" : "Unfreeze", event: this.toggleNativeDimensions, icon: "snowflake" }); + 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.lockedTransform ? "Unlock Transform" : "Lock Transform", event: this.toggleLockTransform, icon: BoolCast(this.Document.lockedTransform) ? "unlock" : "lock" }); + moreItems.push({ description: this.Document.lockedPosition ? "Unlock Position" : "Lock Position", event: this.toggleLockPosition, icon: BoolCast(this.Document.lockedPosition) ? "unlock" : "lock" }); if (!ClientUtils.RELEASE) { // let copies: ContextMenuProps[] = []; @@ -794,6 +783,7 @@ export class DocumentView extends DocComponent(Docu // a.download = `DocExport-${this.props.Document[Id]}.zip`; // a.click(); }); + const recommender_subitems: ContextMenuProps[] = []; recommender_subitems.push({ @@ -826,6 +816,9 @@ export class DocumentView extends DocComponent(Docu moreItems.push({ description: "Publish", event: () => DocUtils.Publish(this.props.Document, this.Document.title || "", this.props.addDocument, this.props.removeDocument), icon: "file" }); moreItems.push({ description: "Undo Debug Test", event: () => UndoManager.TraceOpenBatches(), icon: "exclamation" }); !more && cm.addItem({ description: "More...", subitems: moreItems, icon: "hand-point-right" }); + + cm.moveAfter(cm.findByDescription("More...")!, cm.findByDescription("OnClick...")!); + runInAction(() => { if (!ClientUtils.RELEASE) { const setWriteMode = (mode: DocServer.WriteMode) => { diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 4153c184e..d85373e98 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -157,21 +157,20 @@ export class ImageBox extends ViewBoxAnnotatableComponent Utils.CopyText(field.url.href), icon: "expand-arrows-alt" }); funcs.push({ description: "Rotate", event: this.rotate, icon: "expand-arrows-alt" }); - funcs.push({ - description: "Reset Native Dimensions", event: action(async () => { - const curNW = NumCast(this.dataDoc[this.fieldKey + "-nativeWidth"]); - const curNH = NumCast(this.dataDoc[this.fieldKey + "-nativeHeight"]); - if (this.props.PanelWidth() / this.props.PanelHeight() > curNW / curNH) { - this.dataDoc[this.fieldKey + "-nativeWidth"] = this.props.PanelHeight() * curNW / curNH; - this.dataDoc[this.fieldKey + "-nativeHeight"] = this.props.PanelHeight(); - } else { - this.dataDoc[this.fieldKey + "-nativeWidth"] = this.props.PanelWidth(); - this.dataDoc[this.fieldKey + "-nativeHeight"] = this.props.PanelWidth() * curNH / curNW; - } - }), icon: "expand-arrows-alt" - }); + // funcs.push({ + // description: "Reset Native Dimensions", event: action(async () => { + // const curNW = NumCast(this.dataDoc[this.fieldKey + "-nativeWidth"]); + // const curNH = NumCast(this.dataDoc[this.fieldKey + "-nativeHeight"]); + // if (this.props.PanelWidth() / this.props.PanelHeight() > curNW / curNH) { + // this.dataDoc[this.fieldKey + "-nativeWidth"] = this.props.PanelHeight() * curNW / curNH; + // this.dataDoc[this.fieldKey + "-nativeHeight"] = this.props.PanelHeight(); + // } else { + // this.dataDoc[this.fieldKey + "-nativeWidth"] = this.props.PanelWidth(); + // this.dataDoc[this.fieldKey + "-nativeHeight"] = this.props.PanelWidth() * curNH / curNW; + // } + // }), icon: "expand-arrows-alt" + // }); const existingAnalyze = ContextMenu.Instance.findByDescription("Analyzers..."); const modes: ContextMenuProps[] = existingAnalyze && "subitems" in existingAnalyze ? existingAnalyze.subitems : []; @@ -181,6 +180,12 @@ export class ImageBox extends ViewBoxAnnotatableComponent Utils.CopyText(field.url.href), icon: "expand-arrows-alt" }); + !existingMore && ContextMenu.Instance.addItem({ description: "More...", subitems: mores, icon: "hand-point-right" }); } } diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 8239d6fdf..384a6e8a5 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -129,14 +129,12 @@ export class WebBox extends ViewBoxAnnotatableComponent { + toggleAnnotationMode = () => { if (!this.layoutDoc.isAnnotating) { - //DocumentView.unfreezeNativeDimensions(this.layoutDoc); this.layoutDoc.lockedTransform = false; this.layoutDoc.isAnnotating = true; } else { - //Doc.freezeNativeDimensions(this.layoutDoc, this.props.PanelWidth(), this.props.PanelHeight()); this.layoutDoc.lockedTransform = true; this.layoutDoc.isAnnotating = false; } @@ -158,10 +156,10 @@ export class WebBox extends ViewBoxAnnotatableComponent
-
+
-
+
{ + Doc.toggleNativeDimensions(this.layoutDoc, this.props.ContentScaling(), this.props.NativeWidth(), this.props.NativeHeight()); + } public static get DefaultLayout(): Doc | string | undefined { return Cast(Doc.UserDoc().defaultTextLayout, Doc, null) || StrCast(Doc.UserDoc().defaultTextLayout, null); @@ -438,6 +443,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp Doc.AddDocToList(Cast(Doc.UserDoc()["template-notes"], Doc, null), "data", this.rootDoc); }, icon: "eye" }); + //funcs.push({ description: `${this.Document._autoHeight ? "Variable Height" : "Auto Height"}`, event: () => this.layoutDoc._autoHeight = !this.layoutDoc._autoHeight, icon: "plus" }); + funcs.push({ description: !this.layoutDoc._nativeWidth || !this.layoutDoc._nativeHeight ? "Freeze" : "Unfreeze", event: this.toggleNativeDimensions, icon: "snowflake" }); funcs.push({ description: "Toggle Single Line", event: () => this.layoutDoc._singleLine = !this.layoutDoc._singleLine, icon: "expand-arrows-alt" }); funcs.push({ description: "Toggle Sidebar", event: () => this.layoutDoc._showSidebar = !this.layoutDoc._showSidebar, icon: "expand-arrows-alt" }); funcs.push({ description: "Toggle Dictation Icon", event: () => this.layoutDoc._showAudio = !this.layoutDoc._showAudio, icon: "expand-arrows-alt" }); @@ -649,10 +656,14 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp } } ); - this._disposers.height = reaction( + this._disposers.autoHeight = reaction( () => [this.layoutDoc[WidthSym](), this.layoutDoc._autoHeight], () => this.tryUpdateHeight() ); + this._disposers.height = reaction( + () => this.layoutDoc[HeightSym](), + height => height <= 20 && (this.layoutDoc._autoHeight = true) + ); this.setupEditor(this.config, this.props.fieldKey); @@ -1206,6 +1217,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp render() { TraceMobx(); const style: { [key: string]: any } = {}; + const scale = this.props.ContentScaling() * NumCast(this.layoutDoc.scale, 1); const divKeys = ["width", "height", "background"]; const replacer = (match: any, expr: string, offset: any, string: any) => { // bcz: this executes a script to convert a propery expression string: { script } into a value return ScriptField.MakeFunction(expr, { self: Doc.name, this: Doc.name })?.script.run({ self: this.rootDoc, this: this.layoutDoc }).result as string || ""; @@ -1258,6 +1270,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx index 9ad5aafb8..a33717855 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx @@ -91,7 +91,7 @@ export class FormattedTextBoxComment { (doc: Doc, followLinkLocation: string) => textBox.props.addDocTab(doc, e.ctrlKey ? "inTab" : followLinkLocation)); } } else if (textBox && (FormattedTextBoxComment.tooltipText as any).href) { - textBox.props.addDocTab(Docs.Create.WebDocument((FormattedTextBoxComment.tooltipText as any).href, { title: (FormattedTextBoxComment.tooltipText as any).href, _width: 200, _height: 400 }), "onRight"); + textBox.props.addDocTab(Docs.Create.WebDocument((FormattedTextBoxComment.tooltipText as any).href, { title: (FormattedTextBoxComment.tooltipText as any).href, _width: 200, _height: 400, UseCors: true }), "onRight"); } keep && textBox && FormattedTextBoxComment.start !== undefined && textBox.adoptAnnotation( FormattedTextBoxComment.start, FormattedTextBoxComment.end, FormattedTextBoxComment.mark); diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index e0627fb37..a1e1e11b1 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -20,7 +20,6 @@ import { deleteProperty, getField, getter, makeEditable, makeReadOnly, setter, u import { Docs, DocumentOptions } from "../client/documents/Documents"; import { PdfField, VideoField, AudioField, ImageField } from "./URLField"; import { LinkManager } from "../client/util/LinkManager"; -import { string32 } from "../../deploy/assets/pdf.worker"; export namespace Field { export function toKeyValueString(doc: Doc, key: string): string { @@ -936,19 +935,28 @@ export namespace Doc { } } } - - export function freezeNativeDimensions(layoutDoc: Doc, width: number, height: number): void { - layoutDoc._autoHeight = false; - if (!layoutDoc._nativeWidth) { - layoutDoc._nativeWidth = NumCast(layoutDoc._width, width); - layoutDoc._nativeHeight = NumCast(layoutDoc._height, height); - } - } export function assignDocToField(doc: Doc, field: string, id: string) { DocServer.GetRefField(id).then(layout => layout instanceof Doc && (doc[field] = layout)); return id; } + export function toggleNativeDimensions(layoutDoc: Doc, contentScale: number, panelWidth: number, panelHeight: number) { + runInAction(() => { + if (layoutDoc._nativeWidth || layoutDoc._nativeHeight) { + layoutDoc.scale = NumCast(layoutDoc.scale, 1) * contentScale; + layoutDoc._nativeWidth = undefined; + layoutDoc._nativeHeight = undefined; + } + else { + layoutDoc._autoHeight = false; + if (!layoutDoc._nativeWidth) { + layoutDoc._nativeWidth = NumCast(layoutDoc._width, panelWidth); + layoutDoc._nativeHeight = NumCast(layoutDoc._height, panelHeight); + } + } + }); + } + export function isDocPinned(doc: Doc) { //add this new doc to props.Document const curPres = Cast(Doc.UserDoc().activePresentation, Doc) as Doc; diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index bebf77a8c..b6ff10bab 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -315,7 +315,7 @@ export class CurrentUserUtils { { _width: 250, _height: 250, title: "container" }); } if (doc.emptyWebpage === undefined) { - doc.emptyWebpage = Docs.Create.WebDocument("", { title: "New Webpage", _width: 600 }); + doc.emptyWebpage = Docs.Create.WebDocument("", { title: "New Webpage", _width: 600, UseCors: true }); } return [ { title: "Drag a collection", label: "Col", icon: "folder", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyCollection as Doc }, -- cgit v1.2.3-70-g09d2 From 4bd011dcc6a3f009fa10932c7c6ca1932b784fde Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Tue, 12 May 2020 17:21:48 -0400 Subject: fixed copy paste of documents in freeform collections. --- src/client/views/GlobalKeyHandler.ts | 4 ++-- src/client/views/PreviewCursor.tsx | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'src/client/views/PreviewCursor.tsx') diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 1b16b15bb..b52a0063b 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -263,8 +263,8 @@ export default class KeyManager { case "c": if (SelectionManager.SelectedDocuments().length) { const bds = DocumentDecorations.Instance.Bounds; - const pt = [bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2]; - const text = `__DashDocId(${pt[0]},${pt[1]}):` + SelectionManager.SelectedDocuments().map(dv => dv.Document[Id]).join(":"); + const pt = SelectionManager.SelectedDocuments()[0].props.ScreenToLocalTransform().transformPoint(bds.x + (bds.r - bds.x) / 2, bds.y + (bds.b - bds.y) / 2); + const text = `__DashDocId(${pt?.[0] || 0},${pt?.[1] || 0}):` + SelectionManager.SelectedDocuments().map(dv => dv.Document[Id]).join(":"); SelectionManager.SelectedDocuments().length && navigator.clipboard.writeText(text); stopPropagation = false; preventDefault = false; diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx index 2ddca369a..f7a7944c9 100644 --- a/src/client/views/PreviewCursor.tsx +++ b/src/client/views/PreviewCursor.tsx @@ -7,8 +7,8 @@ import { Docs } from '../documents/Documents'; import { Doc } from '../../new_fields/Doc'; import { Transform } from "../util/Transform"; import { DocServer } from '../DocServer'; -import { NumCast } from '../../new_fields/Types'; import { undoBatch } from '../util/UndoManager'; +import { NumCast } from '../../new_fields/Types'; @observer export class PreviewCursor extends React.Component<{}> { @@ -57,22 +57,23 @@ export class PreviewCursor extends React.Component<{}> { const strs = docids[0].split(","); const ptx = Number(strs[0].substring("__DashDocId(".length)); const pty = Number(strs[1].substring(0, strs[1].length - 1)); - const center = PreviewCursor._getTransform().transformPoint(ptx, pty); let count = 1; const list: Doc[] = []; docids.map((did, i) => i && DocServer.GetRefField(did).then(doc => { count++; if (doc instanceof Doc) { const alias = Doc.MakeClone(doc); - alias.x = newPoint[0] + NumCast(doc.x) - center[0]; - alias.y = newPoint[1] + NumCast(doc.y) - center[1]; + const deltaX = NumCast(doc.x) - ptx; + const deltaY = NumCast(doc.y) - pty; + alias.x = newPoint[0] + deltaX; + alias.y = newPoint[1] + deltaY; list.push(alias); } if (count === docids.length) { undoBatch(() => PreviewCursor._addDocument(list))(); } })); - + e.stopPropagation(); } else { // creates text document undoBatch(() => PreviewCursor._addLiveTextDoc(Docs.Create.TextDocument("", { -- cgit v1.2.3-70-g09d2