diff options
author | Bob Zeleznik <zzzman@gmail.com> | 2020-05-09 15:56:11 -0400 |
---|---|---|
committer | Bob Zeleznik <zzzman@gmail.com> | 2020-05-09 15:56:11 -0400 |
commit | 4914965affb984e04e847460ce1b5750807b316f (patch) | |
tree | e0f6805e097fc822e657e987bd75b18fbabf7e88 /src | |
parent | f5c936b8f31c39513ef925f6f62a4ed3a66a4e86 (diff) |
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
Diffstat (limited to 'src')
-rw-r--r-- | src/client/util/DragManager.ts | 7 | ||||
-rw-r--r-- | src/client/views/GlobalKeyHandler.ts | 10 | ||||
-rw-r--r-- | src/client/views/MainView.tsx | 3 | ||||
-rw-r--r-- | src/client/views/PreviewCursor.tsx | 13 | ||||
-rw-r--r-- | src/client/views/collections/CollectionDockingView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/collections/CollectionSubView.tsx | 10 | ||||
-rw-r--r-- | src/client/views/collections/CollectionTreeView.tsx | 3 | ||||
-rw-r--r-- | src/client/views/collections/CollectionView.tsx | 10 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 15 | ||||
-rw-r--r-- | src/server/authentication/models/current_user_utils.ts | 14 |
10 files changed, 56 insertions, 31 deletions
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<DropEvent>).detail); const preDropHandler = (e: Event) => { const de = (e as CustomEvent<DropEvent>).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<KeyControlInfo>; @@ -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<ScriptField>([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<SubCollectionViewProp gearSpan); tab.buttonDisposer?.(); } - }); + }, { fireImmediately: true }); tab.reactComponents = [gearSpan]; tab.element.append(gearSpan); diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index d1c2d9a76..4fef16315 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -16,7 +16,7 @@ import { DocServer } from "../../DocServer"; import { Docs, DocumentOptions } from "../../documents/Documents"; import { DocumentType } from "../../documents/DocumentTypes"; import { Networking } from "../../Network"; -import { DragManager } from "../../util/DragManager"; +import { DragManager, dropActionType } from "../../util/DragManager"; import { ImageUtils } from "../../util/Import & Export/ImageUtils"; import { InteractionUtils } from "../../util/InteractionUtils"; import { undoBatch, UndoManager } from "../../util/UndoManager"; @@ -195,10 +195,12 @@ export function CollectionSubView<T, X>(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<TreeViewProps> { @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<TreeViewProps> { <FontAwesomeIcon title="open in pane on right" icon="angle-right" size="lg" /> </div>); return <> - <div className="docContainer" ref={this._tref} title="click to edit title" id={`docContainer-${this.props.parentKey}`} onPointerDown={onItemDown} + <div className="docContainer" ref={this._tref} title="click to edit title" id={`docContainer-${this.props.parentKey}`} style={{ fontWeight: this.props.document.searchMatch ? "bold" : undefined, textDecoration: Doc.GetT(this.props.document, "title", "string", true) ? "underline" : undefined, diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index b96f8150d..6c96baede 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -69,15 +69,15 @@ export enum CollectionViewType { Pile = "pileup" } export interface CollectionViewCustomProps { - filterAddDocument: (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) + 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<Doc>; // 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<FieldViewProps & CollectionViewCus // otherwise, the document being moved must be able to be removed from its container before // moving it into the target. @action.bound - moveDocument = (doc: Doc, targetCollection: Doc | undefined, addDocument: (doc: Doc) => 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<DocumentViewProps, Document>(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<DocumentViewProps, Document>(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<DocumentViewProps, Document>(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;") |