aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/util/DragManager.ts7
-rw-r--r--src/client/views/GlobalKeyHandler.ts10
-rw-r--r--src/client/views/MainView.tsx3
-rw-r--r--src/client/views/PreviewCursor.tsx13
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx2
-rw-r--r--src/client/views/collections/CollectionSubView.tsx10
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx3
-rw-r--r--src/client/views/collections/CollectionView.tsx10
-rw-r--r--src/client/views/nodes/DocumentView.tsx15
-rw-r--r--src/server/authentication/models/current_user_utils.ts14
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;")