aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/CollectionSubView.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/collections/CollectionSubView.tsx')
-rw-r--r--src/client/views/collections/CollectionSubView.tsx264
1 files changed, 139 insertions, 125 deletions
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index e80e1c802..042385dcd 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -57,7 +57,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
this.gestureDisposer?.();
this.multiTouchDisposer?.();
if (ele) {
- this.dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this));
+ this.dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this));
this.gestureDisposer = GestureUtils.MakeGestureTarget(ele, this.onGesture.bind(this));
this.multiTouchDisposer = InteractionUtils.MakeMultiTouchTarget(ele, this.onTouchStart.bind(this));
}
@@ -156,7 +156,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
@undoBatch
@action
- protected drop(e: Event, de: DragManager.DropEvent): boolean {
+ protected onInternalDrop(e: Event, de: DragManager.DropEvent): boolean {
const docDragData = de.complete.docDragData;
(this.props.Document.dropConverter instanceof ScriptField) &&
this.props.Document.dropConverter.script.run({ dragData: docDragData }); /// bcz: check this
@@ -195,158 +195,172 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
@undoBatch
@action
- protected async onDrop(e: React.DragEvent, options: DocumentOptions, completed?: () => void) {
+ protected async onExternalDrop(e: React.DragEvent, options: DocumentOptions, completed?: () => void) {
if (e.ctrlKey) {
e.stopPropagation(); // bcz: this is a hack to stop propagation when dropping an image on a text document with shift+ctrl
return;
}
- const html = e.dataTransfer.getData("text/html");
- const text = e.dataTransfer.getData("text/plain");
+
+ const { dataTransfer } = e;
+ const html = dataTransfer.getData("text/html");
+ const text = dataTransfer.getData("text/plain");
if (text && text.startsWith("<div")) {
return;
}
+
e.stopPropagation();
e.preventDefault();
-
- if (html && FormattedTextBox.IsFragment(html)) {
- const href = FormattedTextBox.GetHref(html);
- if (href) {
- const docid = FormattedTextBox.GetDocFromUrl(href);
- if (docid) { // prosemirror text containing link to dash document
- DocServer.GetRefField(docid).then(f => {
- if (f instanceof Doc) {
- if (options.x || options.y) { f.x = options.x; f.y = options.y; } // should be in CollectionFreeFormView
- (f instanceof Doc) && this.props.addDocument(f);
- }
- });
- } else {
- this.props.addDocument && this.props.addDocument(Docs.Create.WebDocument(href, { ...options, title: href }));
- }
- } else if (text) {
- this.props.addDocument && this.props.addDocument(Docs.Create.TextDocument(text, { ...options, _width: 100, _height: 25 }));
- }
+ const { addDocument } = this.props;
+ if (!addDocument) {
+ alert("this.props.addDocument does not exist. Aborting drop operation.");
return;
}
- if (html && !html.startsWith("<a")) {
- const tags = html.split("<");
- if (tags[0] === "") tags.splice(0, 1);
- const img = tags[0].startsWith("img") ? tags[0] : tags.length > 1 && tags[1].startsWith("img") ? tags[1] : "";
- if (img) {
- const split = img.split("src=\"")[1].split("\"")[0];
- let source = split;
- if (split.startsWith("data:image") && split.includes("base64")) {
- const [{ accessPaths }] = await Networking.PostToServer("/uploadRemoteImage", { sources: [split] });
- source = Utils.prepend(accessPaths.agnostic.client);
+
+ if (html) {
+ if (FormattedTextBox.IsFragment(html)) {
+ const href = FormattedTextBox.GetHref(html);
+ if (href) {
+ const docid = FormattedTextBox.GetDocFromUrl(href);
+ if (docid) { // prosemirror text containing link to dash document
+ DocServer.GetRefField(docid).then(f => {
+ if (f instanceof Doc) {
+ if (options.x || options.y) { f.x = options.x; f.y = options.y; } // should be in CollectionFreeFormView
+ (f instanceof Doc) && addDocument(f);
+ }
+ });
+ } else {
+ addDocument(Docs.Create.WebDocument(href, { ...options, title: href }));
+ }
+ } else if (text) {
+ addDocument(Docs.Create.TextDocument(text, { ...options, _width: 100, _height: 25 }));
}
- const doc = Docs.Create.ImageDocument(source, { ...options, _width: 300 });
- ImageUtils.ExtractExif(doc);
- this.props.addDocument(doc);
return;
- } else {
- const path = window.location.origin + "/doc/";
- if (text.startsWith(path)) {
- const docid = text.replace(Utils.prepend("/doc/"), "").split("?")[0];
- DocServer.GetRefField(docid).then(f => {
- if (f instanceof Doc) {
- if (options.x || options.y) { f.x = options.x; f.y = options.y; } // should be in CollectionFreeFormView
- (f instanceof Doc) && this.props.addDocument(f);
- }
- });
+ }
+ if (!html.startsWith("<a")) {
+ const tags = html.split("<");
+ if (tags[0] === "") tags.splice(0, 1);
+ const img = tags[0].startsWith("img") ? tags[0] : tags.length > 1 && tags[1].startsWith("img") ? tags[1] : "";
+ if (img) {
+ const split = img.split("src=\"")[1].split("\"")[0];
+ let source = split;
+ if (split.startsWith("data:image") && split.includes("base64")) {
+ const [{ accessPaths }] = await Networking.PostToServer("/uploadRemoteImage", { sources: [split] });
+ source = Utils.prepend(accessPaths.agnostic.client);
+ }
+ const doc = Docs.Create.ImageDocument(source, { ...options, _width: 300 });
+ ImageUtils.ExtractExif(doc);
+ addDocument(doc);
+ return;
} else {
- const htmlDoc = Docs.Create.HtmlDocument(html, { ...options, title: "-web page-", _width: 300, _height: 300 });
- Doc.GetProto(htmlDoc)["data-text"] = text;
- this.props.addDocument(htmlDoc);
+ const path = window.location.origin + "/doc/";
+ if (text.startsWith(path)) {
+ const docid = text.replace(Utils.prepend("/doc/"), "").split("?")[0];
+ DocServer.GetRefField(docid).then(f => {
+ if (f instanceof Doc) {
+ if (options.x || options.y) { f.x = options.x; f.y = options.y; } // should be in CollectionFreeFormView
+ (f instanceof Doc) && this.props.addDocument(f);
+ }
+ });
+ } else {
+ const htmlDoc = Docs.Create.HtmlDocument(html, { ...options, title: "-web page-", _width: 300, _height: 300 });
+ Doc.GetProto(htmlDoc)["data-text"] = text;
+ this.props.addDocument(htmlDoc);
+ }
+ return;
}
- return;
}
}
- if (text && text.indexOf("www.youtube.com/watch") !== -1) {
- const url = text.replace("youtube.com/watch?v=", "youtube.com/embed/");
- this.props.addDocument(Docs.Create.VideoDocument(url, { ...options, title: url, _width: 400, _height: 315, _nativeWidth: 600, _nativeHeight: 472.5 }));
- return;
- }
- let matches: RegExpExecArray | null;
- if ((matches = /(https:\/\/)?docs\.google\.com\/document\/d\/([^\\]+)\/edit/g.exec(text)) !== null) {
- const newBox = Docs.Create.TextDocument("", { ...options, _width: 400, _height: 200, title: "Awaiting title from Google Docs..." });
- const proto = newBox.proto!;
- const documentId = matches[2];
- proto[GoogleRef] = documentId;
- proto.data = "Please select this document and then click on its pull button to load its contents from from Google Docs...";
- proto.backgroundColor = "#eeeeff";
- this.props.addDocument(newBox);
- // const parent = Docs.Create.StackingDocument([newBox], { title: `Google Doc Import (${documentId})` });
- // CollectionDockingView.Instance.AddRightSplit(parent, undefined);
- // proto.height = parent[HeightSym]();
- return;
- }
- if ((matches = /(https:\/\/)?photos\.google\.com\/(u\/3\/)?album\/([^\\]+)/g.exec(text)) !== null) {
- const albums = await GooglePhotos.Transactions.ListAlbums();
- const albumId = matches[3];
- const mediaItems = await GooglePhotos.Query.AlbumSearch(albumId);
- console.log(mediaItems);
- return;
+
+ if (text) {
+ if (text.includes("www.youtube.com/watch")) {
+ const url = text.replace("youtube.com/watch?v=", "youtube.com/embed/");
+ addDocument(Docs.Create.VideoDocument(url, {
+ ...options,
+ title: url,
+ _width: 400,
+ _height: 315,
+ _nativeWidth: 600,
+ _nativeHeight: 472.5
+ }));
+ return;
+ }
+ let matches: RegExpExecArray | null;
+ if ((matches = /(https:\/\/)?docs\.google\.com\/document\/d\/([^\\]+)\/edit/g.exec(text)) !== null) {
+ const newBox = Docs.Create.TextDocument("", { ...options, _width: 400, _height: 200, title: "Awaiting title from Google Docs..." });
+ const proto = newBox.proto!;
+ const documentId = matches[2];
+ proto[GoogleRef] = documentId;
+ proto.data = "Please select this document and then click on its pull button to load its contents from from Google Docs...";
+ proto.backgroundColor = "#eeeeff";
+ addDocument(newBox);
+ return;
+ }
+ if ((matches = /(https:\/\/)?photos\.google\.com\/(u\/3\/)?album\/([^\\]+)/g.exec(text)) !== null) {
+ const albumId = matches[3];
+ const mediaItems = await GooglePhotos.Query.AlbumSearch(albumId);
+ console.log(mediaItems);
+ return;
+ }
}
+
const { items } = e.dataTransfer;
const { length } = items;
const files: File[] = [];
- if (length) {
- const batch = UndoManager.StartBatch("collection view drop");
- const promises: Promise<void>[] = [];
- // tslint:disable-next-line:prefer-for-of
- for (let i = 0; i < length; i++) {
- const item = e.dataTransfer.items[i];
- if (item.kind === "string" && item.type.indexOf("uri") !== -1) {
- let str: string;
- const prom = new Promise<string>(resolve => item.getAsString(resolve))
- .then(action((s: string) => rp.head(Utils.CorsProxy(str = s))))
- .then(result => {
- const type = result["content-type"];
- if (type) {
- Docs.Get.DocumentFromType(type, str, options)
- .then(doc => doc && this.props.addDocument(doc));
- }
- });
- promises.push(prom);
- }
- if (item.kind === "file") {
- const file = item.getAsFile();
- file && file.type && files.push(file);
+ const generatedDocuments: Doc[] = [];
+ if (!length) {
+ alert("No uploadable content found.");
+ return;
+ }
+
+ const batch = UndoManager.StartBatch("collection view drop");
+ for (let i = 0; i < length; i++) {
+ const item = e.dataTransfer.items[i];
+ if (item.kind === "string" && item.type.includes("uri")) {
+ const stringContents = await new Promise<string>(resolve => item.getAsString(resolve));
+ const type = (await rp.head(Utils.CorsProxy(stringContents)))["content-type"];
+ if (type) {
+ const doc = await Docs.Get.DocumentFromType(type, stringContents, options);
+ doc && generatedDocuments.push(doc);
}
}
- promises.push(Networking.UploadFilesToServer(files).then(responses => responses.forEach(({ source: { name, type }, result }) => {
- if (result instanceof Error) {
- alert(`Upload failed: ${result.message}`);
- return;
- }
- const full = { ...options, _width: 300, title: name };
- const pathname = Utils.prepend(result.accessPaths.agnostic.client);
- Docs.Get.DocumentFromType(type, pathname, full).then(doc => {
- if (doc) {
- const proto = Doc.GetProto(doc);
- proto.fileUpload = basename(pathname).replace("upload_", "").replace(/\.[a-z0-9]*$/, "");
- if (Upload.isImageInformation(result)) {
- proto["data-nativeWidth"] = result.nativeWidth;
- proto["data-nativeHeight"] = result.nativeHeight;
- proto.contentSize = result.contentSize;
- }
- this.props?.addDocument(doc);
- }
- });
- })));
- if (promises.length) {
- Promise.all(promises).finally(() => { completed && completed(); batch.end(); });
- } else {
- if (text && !text.includes("https://")) {
- this.props.addDocument(Docs.Create.TextDocument(text, { ...options, _width: 400, _height: 315 }));
- }
- batch.end();
+ if (item.kind === "file") {
+ const file = item.getAsFile();
+ file && file.type && files.push(file);
+ }
+ }
+ for (const { source: { name, type }, result } of await Networking.UploadFilesToServer(files)) {
+ if (result instanceof Error) {
+ alert(`Upload failed: ${result.message}`);
+ return;
}
+ const full = { ...options, _width: 300, title: name };
+ const pathname = Utils.prepend(result.accessPaths.agnostic.client);
+ const doc = await Docs.Get.DocumentFromType(type, pathname, full);
+ if (!doc) {
+ continue;
+ }
+ const proto = Doc.GetProto(doc);
+ proto.fileUpload = basename(pathname).replace("upload_", "").replace(/\.[a-z0-9]*$/, "");
+ if (Upload.isImageInformation(result)) {
+ proto["data-nativeWidth"] = result.nativeWidth;
+ proto["data-nativeHeight"] = result.nativeHeight;
+ proto.contentSize = result.contentSize;
+ }
+ generatedDocuments.push(doc);
+ }
+ if (generatedDocuments.length) {
+ generatedDocuments.forEach(addDocument);
+ completed && completed();
} else {
- alert("No uploadable content found.");
+ if (text && !text.includes("https://")) {
+ addDocument(Docs.Create.TextDocument(text, { ...options, _width: 400, _height: 315 }));
+ }
}
+ batch.end();
}
}
+
return CollectionSubView;
}