From 146f8622d5bac2edc6b09f57c173bd057dfbcfad Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 8 Jul 2022 00:17:26 -0400
Subject: restructured currentUserUtils to avoid having import cycles.

---
 src/client/views/collections/CollectionSubView.tsx | 286 ++++++++++++---------
 1 file changed, 159 insertions(+), 127 deletions(-)

(limited to 'src/client/views/collections/CollectionSubView.tsx')

diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 03450b798..5479929bd 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -1,24 +1,23 @@
-import { action, computed, IReactionDisposer, reaction, observable, runInAction } from "mobx";
-import CursorField from "../../../fields/CursorField";
-import { Doc, Opt, Field, DocListCast, AclPrivate, StrListCast } from "../../../fields/Doc";
-import { Id } from "../../../fields/FieldSymbols";
-import { List } from "../../../fields/List";
-import { listSpec } from "../../../fields/Schema";
-import { ScriptField } from "../../../fields/ScriptField";
-import { WebField } from "../../../fields/URLField";
-import { Cast, ScriptCast, NumCast, StrCast } from "../../../fields/Types";
-import { GestureUtils } from "../../../pen-gestures/GestureUtils";
-import { Utils, returnFalse, returnEmptyFilter } from "../../../Utils";
-import { DocServer } from "../../DocServer";
-import { ImageUtils } from "../../util/Import & Export/ImageUtils";
-import { InteractionUtils } from "../../util/InteractionUtils";
-import { undoBatch, UndoManager } from "../../util/UndoManager";
-import { DocComponent } from "../DocComponent";
-import React = require("react");
+import { action, computed, observable } from 'mobx';
 import ReactLoading from 'react-loading';
 import * as rp from 'request-promise';
-import { Networking } from "../../Network";
-
+import CursorField from '../../../fields/CursorField';
+import { AclPrivate, Doc, DocListCast, Field, Opt, StrListCast } from '../../../fields/Doc';
+import { Id } from '../../../fields/FieldSymbols';
+import { List } from '../../../fields/List';
+import { listSpec } from '../../../fields/Schema';
+import { ScriptField } from '../../../fields/ScriptField';
+import { Cast, ScriptCast, StrCast } from '../../../fields/Types';
+import { WebField } from '../../../fields/URLField';
+import { GestureUtils } from '../../../pen-gestures/GestureUtils';
+import { returnFalse, Utils } from '../../../Utils';
+import { DocServer } from '../../DocServer';
+import { Networking } from '../../Network';
+import { ImageUtils } from '../../util/Import & Export/ImageUtils';
+import { InteractionUtils } from '../../util/InteractionUtils';
+import { undoBatch, UndoManager } from '../../util/UndoManager';
+import { DocComponent } from '../DocComponent';
+import React = require('react');
 
 export interface SubCollectionViewProps extends CollectionViewProps {
     CollectionView: Opt<CollectionView>;
@@ -33,7 +32,8 @@ export function CollectionSubView<X>(moreProps?: X) {
         protected _mainCont?: HTMLDivElement;
         @observable _focusFilters: Opt<string[]>; // docFilters that are overridden when previewing a link to an anchor which has docFilters set on it
         @observable _focusRangeFilters: Opt<string[]>; // docRangeFilters that are overridden when previewing a link to an anchor which has docRangeFilters set on it
-        protected createDashEventsTarget = (ele: HTMLDivElement | null) => { //used for stacking and masonry view
+        protected createDashEventsTarget = (ele: HTMLDivElement | null) => {
+            //used for stacking and masonry view
             this.dropDisposer?.();
             this.gestureDisposer?.();
             this._multiTouchDisposer?.();
@@ -43,8 +43,9 @@ export function CollectionSubView<X>(moreProps?: X) {
                 this.gestureDisposer = GestureUtils.MakeGestureTarget(ele, this.onGesture.bind(this));
                 this._multiTouchDisposer = InteractionUtils.MakeMultiTouchTarget(ele, this.onTouchStart.bind(this));
             }
-        }
-        protected CreateDropTarget(ele: HTMLDivElement) { //used in schema view
+        };
+        protected CreateDropTarget(ele: HTMLDivElement) {
+            //used in schema view
             this.createDashEventsTarget(ele);
         }
 
@@ -54,13 +55,12 @@ export function CollectionSubView<X>(moreProps?: X) {
         }
 
         @computed get dataDoc() {
-            return (this.props.DataDoc instanceof Doc && this.props.Document.isTemplateForField ? Doc.GetProto(this.props.DataDoc) :
-                this.props.Document.resolvedDataDoc ? this.props.Document : Doc.GetProto(this.props.Document)); // if the layout document has a resolvedDataDoc, then we don't want to get its parent which would be the unexpanded template
+            return this.props.DataDoc instanceof Doc && this.props.Document.isTemplateForField ? Doc.GetProto(this.props.DataDoc) : this.props.Document.resolvedDataDoc ? this.props.Document : Doc.GetProto(this.props.Document); // if the layout document has a resolvedDataDoc, then we don't want to get its parent which would be the unexpanded template
         }
 
         rootSelected = (outsideReaction?: boolean) => {
             return this.props.isSelected(outsideReaction) || (this.rootDoc && this.props.rootSelected(outsideReaction));
-        }
+        };
 
         // The data field for rendering this collection will be on the this.props.Document unless we're rendering a template in which case we try to use props.DataDoc.
         // When a document has a DataDoc but it's not a template, then it contains its own rendering data, but needs to pass the DataDoc through
@@ -73,10 +73,12 @@ export function CollectionSubView<X>(moreProps?: X) {
             return this.dataDoc[this.props.fieldKey];
         }
 
-        get childLayoutPairs(): { layout: Doc; data: Doc; }[] {
+        get childLayoutPairs(): { layout: Doc; data: Doc }[] {
             const { Document, DataDoc } = this.props;
-            const validPairs = this.childDocs.map(doc => Doc.GetLayoutDataDocPair(Document, !this.props.isAnnotationOverlay ? DataDoc : undefined, doc)).
-                filter(pair => {  // filter out any documents that have a proto that we don't have permissions to
+            const validPairs = this.childDocs
+                .map(doc => Doc.GetLayoutDataDocPair(Document, !this.props.isAnnotationOverlay ? DataDoc : undefined, doc))
+                .filter(pair => {
+                    // filter out any documents that have a proto that we don't have permissions to
                     return pair.layout && (!pair.layout.proto || (pair.layout.proto instanceof Doc && GetEffectiveAcl(pair.layout.proto) !== AclPrivate));
                 });
             return validPairs.map(({ data, layout }) => ({ data: data as Doc, layout: layout! })); // this mapping is a bit of a hack to coerce types
@@ -85,21 +87,24 @@ export function CollectionSubView<X>(moreProps?: X) {
             return Cast(this.dataField, listSpec(Doc));
         }
         collectionFilters = () => this._focusFilters ?? StrListCast(this.props.Document._docFilters);
-        collectionRangeDocFilters = () => this._focusRangeFilters ?? Cast(this.props.Document._docRangeFilters, listSpec("string"), []);
+        collectionRangeDocFilters = () => this._focusRangeFilters ?? Cast(this.props.Document._docRangeFilters, listSpec('string'), []);
         childDocFilters = () => [...(this.props.docFilters?.().filter(f => Utils.IsRecursiveFilter(f)) || []), ...this.collectionFilters()];
         unrecursiveDocFilters = () => [...(this.props.docFilters?.().filter(f => !Utils.IsRecursiveFilter(f)) || [])];
         childDocRangeFilters = () => [...(this.props.docRangeFilters?.() || []), ...this.collectionRangeDocFilters()];
-        IsFiltered = () => this.collectionFilters().length || this.collectionRangeDocFilters().length ? "hasFilter" :
-            this.props.docFilters?.().filter(f => Utils.IsRecursiveFilter(f)).length || this.props.docRangeFilters().length ? "inheritsFilter" : undefined
+        IsFiltered = () =>
+            this.collectionFilters().length || this.collectionRangeDocFilters().length ? 'hasFilter' : this.props.docFilters?.().filter(f => Utils.IsRecursiveFilter(f)).length || this.props.docRangeFilters().length ? 'inheritsFilter' : undefined;
         searchFilterDocs = () => this.props.searchFilterDocs?.() ?? DocListCast(this.props.Document._searchFilterDocs);
         @computed.struct get childDocs() {
             TraceMobx();
             let rawdocs: (Doc | Promise<Doc>)[] = [];
-            if (this.dataField instanceof Doc) { // if collection data is just a document, then promote it to a singleton list;
+            if (this.dataField instanceof Doc) {
+                // if collection data is just a document, then promote it to a singleton list;
                 rawdocs = [this.dataField];
-            } else if (Cast(this.dataField, listSpec(Doc), null)) { // otherwise, if the collection data is a list, then use it.  
+            } else if (Cast(this.dataField, listSpec(Doc), null)) {
+                // otherwise, if the collection data is a list, then use it.
                 rawdocs = Cast(this.dataField, listSpec(Doc), null);
-            } else {   // Finally, if it's not a doc or a list and the document is a template, we try to render the root doc.
+            } else {
+                // Finally, if it's not a doc or a list and the document is a template, we try to render the root doc.
                 // For example, if an image doc is rendered with a slide template, the template will try to render the data field as a collection.
                 // Since the data field is actually an image, we set the list of documents to the singleton of root document's proto which will be an image.
                 const rootDoc = Cast(this.props.Document.rootDocument, Doc, null);
@@ -117,19 +122,19 @@ export function CollectionSubView<X>(moreProps?: X) {
                 return childDocs.filter(cd => !cd.cookies); // remove any documents that require a cookie if there are no filters to provide one
             }
 
-            // console.log(CurrentUserUtils.ActiveDashboard._docFilters);
+            // console.log(Doc.ActiveDashboard._docFilters);
             // if (!this.props.Document._docFilters && this.props.Document.currentFilter) {
             //     (this.props.Document.currentFilter as Doc).filterBoolean = (this.props.ContainingCollectionDoc?.currentFilter as Doc)?.filterBoolean;
             // }
             const docsforFilter: Doc[] = [];
-            childDocs.forEach((d) => {
+            childDocs.forEach(d => {
                 // if (DocUtils.Excluded(d, docFilters)) return;
-                let notFiltered = d.z || Doc.IsSystem(d) || (DocUtils.FilterDocs([d], this.unrecursiveDocFilters(), docRangeFilters, viewSpecScript, this.props.Document).length > 0);
+                let notFiltered = d.z || Doc.IsSystem(d) || DocUtils.FilterDocs([d], this.unrecursiveDocFilters(), docRangeFilters, viewSpecScript, this.props.Document).length > 0;
                 if (notFiltered) {
-                    notFiltered = ((!searchDocs.length || searchDocs.includes(d)) && (DocUtils.FilterDocs([d], childDocFilters, docRangeFilters, viewSpecScript, this.props.Document).length > 0));
+                    notFiltered = (!searchDocs.length || searchDocs.includes(d)) && DocUtils.FilterDocs([d], childDocFilters, docRangeFilters, viewSpecScript, this.props.Document).length > 0;
                     const fieldKey = Doc.LayoutFieldKey(d);
-                    const annos = !Field.toString(Doc.LayoutField(d) as Field).includes("CollectionView");
-                    const data = d[annos ? fieldKey + "-annotations" : fieldKey];
+                    const annos = !Field.toString(Doc.LayoutField(d) as Field).includes('CollectionView');
+                    const data = d[annos ? fieldKey + '-annotations' : fieldKey];
                     if (data !== undefined) {
                         let subDocs = DocListCast(data);
                         if (subDocs.length > 0) {
@@ -137,11 +142,12 @@ export function CollectionSubView<X>(moreProps?: X) {
                             notFiltered = notFiltered || (!searchDocs.length && DocUtils.FilterDocs(subDocs, childDocFilters, docRangeFilters, viewSpecScript, d).length);
                             while (subDocs.length > 0 && !notFiltered) {
                                 newarray = [];
-                                subDocs.forEach((t) => {
+                                subDocs.forEach(t => {
                                     const fieldKey = Doc.LayoutFieldKey(t);
-                                    const annos = !Field.toString(Doc.LayoutField(t) as Field).includes("CollectionView");
-                                    notFiltered = notFiltered || ((!searchDocs.length || searchDocs.includes(t)) && ((!childDocFilters.length && !docRangeFilters.length) || DocUtils.FilterDocs([t], childDocFilters, docRangeFilters, viewSpecScript, d).length));
-                                    DocListCast(t[annos ? fieldKey + "-annotations" : fieldKey]).forEach((newdoc) => newarray.push(newdoc));
+                                    const annos = !Field.toString(Doc.LayoutField(t) as Field).includes('CollectionView');
+                                    notFiltered =
+                                        notFiltered || ((!searchDocs.length || searchDocs.includes(t)) && ((!childDocFilters.length && !docRangeFilters.length) || DocUtils.FilterDocs([t], childDocFilters, docRangeFilters, viewSpecScript, d).length));
+                                    DocListCast(t[annos ? fieldKey + '-annotations' : fieldKey]).forEach(newdoc => newarray.push(newdoc));
                                 });
                                 subDocs = newarray;
                             }
@@ -157,7 +163,7 @@ export function CollectionSubView<X>(moreProps?: X) {
         protected async setCursorPosition(position: [number, number]) {
             let ind;
             const doc = this.props.Document;
-            const id = CurrentUserUtils.id;
+            const id = Doc.UserDoc()[Id];
             const email = Doc.CurrentUserEmail;
             const pos = { x: position[0], y: position[1] };
             if (id && email) {
@@ -167,7 +173,7 @@ export function CollectionSubView<X>(moreProps?: X) {
                 }
                 // The following conditional detects a recurring bug we've seen on the server
                 if (proto[Id] === Docs.Prototypes.get(DocumentType.COL)[Id]) {
-                    alert("COLLECTION PROTO CURSOR ISSUE DETECTED! Check console for more info...");
+                    alert('COLLECTION PROTO CURSOR ISSUE DETECTED! Check console for more info...');
                     console.log(doc);
                     console.log(proto);
                     throw new Error(`AHA! You were trying to set a cursor on a collection's proto, which is the original collection proto! Look at the two previously printed lines for document values!`);
@@ -186,8 +192,7 @@ export function CollectionSubView<X>(moreProps?: X) {
         }
 
         @undoBatch
-        protected onGesture(e: Event, ge: GestureUtils.GestureEvent) {
-        }
+        protected onGesture(e: Event, ge: GestureUtils.GestureEvent) {}
 
         protected onInternalPreDrop(e: Event, de: DragManager.DropEvent, targetAction: dropActionType) {
             if (de.complete.docDragData) {
@@ -210,12 +215,16 @@ export function CollectionSubView<X>(moreProps?: X) {
                 const dropAction = docDragData.dropAction || docDragData.userDropAction;
                 const targetDocments = DocListCast(this.dataDoc[this.props.fieldKey]);
                 const someMoved = !docDragData.userDropAction && docDragData.draggedDocuments.some(drag => targetDocments.includes(drag));
-                if (someMoved) docDragData.droppedDocuments = docDragData.droppedDocuments.map((drop, i) => targetDocments.includes(docDragData.draggedDocuments[i]) ? docDragData.draggedDocuments[i] : drop);
-                if ((!dropAction || dropAction === "same" || dropAction === "move" || someMoved) && docDragData.moveDocument) {
+                if (someMoved) docDragData.droppedDocuments = docDragData.droppedDocuments.map((drop, i) => (targetDocments.includes(docDragData.draggedDocuments[i]) ? docDragData.draggedDocuments[i] : drop));
+                if ((!dropAction || dropAction === 'same' || dropAction === 'move' || someMoved) && docDragData.moveDocument) {
                     const movedDocs = docDragData.droppedDocuments.filter((d, i) => docDragData.draggedDocuments[i] === d);
                     const addedDocs = docDragData.droppedDocuments.filter((d, i) => docDragData.draggedDocuments[i] !== d);
                     if (movedDocs.length) {
-                        const canAdd = this.props.Document._viewType === CollectionViewType.Pile || de.embedKey || (!this.props.isAnnotationOverlay || this.props.Document.allowOverlayDrop) ||
+                        const canAdd =
+                            this.props.Document._viewType === CollectionViewType.Pile ||
+                            de.embedKey ||
+                            !this.props.isAnnotationOverlay ||
+                            this.props.Document.allowOverlayDrop ||
                             Doc.AreProtosEqual(Cast(movedDocs[0].annotationOn, Doc, null), this.props.Document);
                         added = docDragData.moveDocument(movedDocs, this.props.Document, canAdd ? this.addDocument : returnFalse);
                     } else {
@@ -228,11 +237,10 @@ export function CollectionSubView<X>(moreProps?: X) {
                     ScriptCast(this.props.Document.dropConverter)?.script.run({ dragData: docDragData });
                     added = this.addDocument(docDragData.droppedDocuments);
                 }
-                !added && alert("You cannot perform this move");
+                !added && alert('You cannot perform this move');
                 e.stopPropagation();
                 return added;
-            }
-            else if (de.complete.annoDragData) {
+            } else if (de.complete.annoDragData) {
                 const dropCreator = de.complete.annoDragData.dropDocCreator;
                 de.complete.annoDragData.dropDocCreator = () => {
                     const dropped = dropCreator(this.props.isAnnotationOverlay ? this.rootDoc : undefined);
@@ -253,11 +261,11 @@ export function CollectionSubView<X>(moreProps?: X) {
             }
 
             const { dataTransfer } = e;
-            const html = dataTransfer.getData("text/html");
-            const text = dataTransfer.getData("text/plain");
-            const uriList = dataTransfer.getData("text/uri-list");
+            const html = dataTransfer.getData('text/html');
+            const text = dataTransfer.getData('text/plain');
+            const uriList = dataTransfer.getData('text/uri-list');
 
-            if (text && text.startsWith("<div")) {
+            if (text && text.startsWith('<div')) {
                 return;
             }
 
@@ -271,11 +279,15 @@ export function CollectionSubView<X>(moreProps?: X) {
                     const href = FormattedTextBox.GetHref(html);
                     if (href) {
                         const docid = FormattedTextBox.GetDocFromUrl(href);
-                        if (docid) { // prosemirror text containing link to dash document
+                        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 as number; f.y = options.y as number; } // should be in CollectionFreeFormView
-                                    (f instanceof Doc) && addDocument(f);
+                                    if (options.x || options.y) {
+                                        f.x = options.x as number;
+                                        f.y = options.y as number;
+                                    } // should be in CollectionFreeFormView
+                                    f instanceof Doc && addDocument(f);
                                 }
                             });
                         } else {
@@ -286,47 +298,50 @@ export function CollectionSubView<X>(moreProps?: X) {
                     }
                     return;
                 }
-                if (!html.startsWith("<a")) {
-                    const tags = html.split("<");
-                    if (tags[0] === "") tags.splice(0, 1);
-                    let img = tags[0].startsWith("img") ? tags[0] : tags.length > 1 && tags[1].startsWith("img") ? tags[1] : "";
-                    const cors = img.includes("corsProxy") ? img.match(/http.*corsProxy\//)![0] : "";
-                    img = cors ? img.replace(cors, "") : img;
+                if (!html.startsWith('<a')) {
+                    const tags = html.split('<');
+                    if (tags[0] === '') tags.splice(0, 1);
+                    let img = tags[0].startsWith('img') ? tags[0] : tags.length > 1 && tags[1].startsWith('img') ? tags[1] : '';
+                    const cors = img.includes('corsProxy') ? img.match(/http.*corsProxy\//)![0] : '';
+                    img = cors ? img.replace(cors, '') : img;
                     if (img) {
-                        const split = img.split("src=\"")[1].split("\"")[0];
+                        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] });
+                        if (split.startsWith('data:image') && split.includes('base64')) {
+                            const [{ accessPaths }] = await Networking.PostToServer('/uploadRemoteImage', { sources: [split] });
                             source = Utils.prepend(accessPaths.agnostic.client);
                         }
-                        if (source.startsWith("http")) {
+                        if (source.startsWith('http')) {
                             const doc = Docs.Create.ImageDocument(source, { ...options, _width: 300 });
                             ImageUtils.ExtractExif(doc);
                             addDocument(doc);
                         }
                         return;
                     } else {
-                        const path = window.location.origin + "/doc/";
+                        const path = window.location.origin + '/doc/';
                         if (text.startsWith(path)) {
-                            const docid = text.replace(Doc.globalServerPath(), "").split("?")[0];
+                            const docid = text.replace(Doc.globalServerPath(), '').split('?')[0];
                             DocServer.GetRefField(docid).then(f => {
                                 if (f instanceof Doc) {
-                                    if (options.x || options.y) { f.x = options.x as number; f.y = options.y as number;  } // should be in CollectionFreeFormView
-                                    (f instanceof Doc) && addDocument(f);
+                                    if (options.x || options.y) {
+                                        f.x = options.x as number;
+                                        f.y = options.y as number;
+                                    } // should be in CollectionFreeFormView
+                                    f instanceof Doc && addDocument(f);
                                 }
                             });
                         } else {
                             const srcWeb = SelectionManager.Views().lastElement();
                             const srcUrl = (srcWeb?.Document.data as WebField)?.url?.href?.match(/https?:\/\/[^/]*/)?.[0];
-                            const reg = new RegExp(Utils.prepend(""), "g");
+                            const reg = new RegExp(Utils.prepend(''), 'g');
                             const modHtml = srcUrl ? html.replace(reg, srcUrl) : html;
-                            const backgroundColor = tags.map(tag => tag.match(/.*(background-color: ?[^;]*)/)?.[1]?.replace(/background-color: ?(.*)/, "$1")).filter(t => t)?.[0];
-                            const htmlDoc = Docs.Create.HtmlDocument(modHtml, { ...options, title: srcUrl ? "from:" + srcUrl : "-web clip-", _width: 300, _height: 300, backgroundColor });
-                            Doc.GetProto(htmlDoc)["data-text"] = Doc.GetProto(htmlDoc).text = text;
+                            const backgroundColor = tags.map(tag => tag.match(/.*(background-color: ?[^;]*)/)?.[1]?.replace(/background-color: ?(.*)/, '$1')).filter(t => t)?.[0];
+                            const htmlDoc = Docs.Create.HtmlDocument(modHtml, { ...options, title: srcUrl ? 'from:' + srcUrl : '-web clip-', _width: 300, _height: 300, backgroundColor });
+                            Doc.GetProto(htmlDoc)['data-text'] = Doc.GetProto(htmlDoc).text = text;
                             addDocument(htmlDoc);
                             if (srcWeb) {
-                                const iframe = SelectionManager.Views()[0].ContentDiv?.getElementsByTagName("iframe")?.[0];
-                                const focusNode = (iframe?.contentDocument?.getSelection()?.focusNode as any);
+                                const iframe = SelectionManager.Views()[0].ContentDiv?.getElementsByTagName('iframe')?.[0];
+                                const focusNode = iframe?.contentDocument?.getSelection()?.focusNode as any;
                                 if (focusNode) {
                                     const anchor = srcWeb?.ComponentView?.getAnchor?.();
                                     anchor && DocUtils.MakeLink({ doc: htmlDoc }, { doc: anchor });
@@ -339,11 +354,10 @@ export function CollectionSubView<X>(moreProps?: X) {
             }
 
             if (uriList || text) {
-                if ((uriList || text).includes("www.youtube.com/watch") || text.includes("www.youtube.com/embed")) {
-
-                    const batch = UndoManager.StartBatch("youtube upload");
+                if ((uriList || text).includes('www.youtube.com/watch') || text.includes('www.youtube.com/embed')) {
+                    const batch = UndoManager.StartBatch('youtube upload');
                     const generatedDocuments: Doc[] = [];
-                    this.slowLoadDocuments((uriList || text).split("v=")[1].split("&")[0], options, generatedDocuments, text, completed, e.clientX, e.clientY, addDocument).then(batch.end);
+                    this.slowLoadDocuments((uriList || text).split('v=')[1].split('&')[0], options, generatedDocuments, text, completed, e.clientX, e.clientY, addDocument).then(batch.end);
 
                     return;
                 }
@@ -374,15 +388,16 @@ export function CollectionSubView<X>(moreProps?: X) {
                 //     alias._height = 512;
                 //     alias._width = 400;
                 //     addDocument(alias);
-                // } else 
+                // } else
                 {
-                    const newDoc = Docs.Create.WebDocument(uriList.split("#annotations:")[0], {// clean hypothes.is URLs that reference a specific annotation (eg. https://en.wikipedia.org/wiki/Cartoon#annotations:t7qAeNbCEeqfG5972KR2Ig)
+                    const newDoc = Docs.Create.WebDocument(uriList.split('#annotations:')[0], {
+                        // clean hypothes.is URLs that reference a specific annotation (eg. https://en.wikipedia.org/wiki/Cartoon#annotations:t7qAeNbCEeqfG5972KR2Ig)
                         ...options,
-                        title: uriList.split("#annotations:")[0],
+                        title: uriList.split('#annotations:')[0],
                         _width: 400,
                         _height: 512,
                         _nativeWidth: 850,
-                        useCors: true
+                        useCors: true,
                     });
                     addDocument(newDoc);
                 }
@@ -394,82 +409,99 @@ export function CollectionSubView<X>(moreProps?: X) {
             const files: File[] = [];
             const generatedDocuments: Doc[] = [];
             if (!length) {
-                alert("No uploadable content found.");
+                alert('No uploadable content found.');
                 return;
             }
 
-            const batch = UndoManager.StartBatch("collection view drop");
+            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")) {
+                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"];
+                    const type = (await rp.head(Utils.CorsProxy(stringContents)))['content-type'];
                     if (type) {
                         const doc = await DocUtils.DocumentFromType(type, Utils.CorsProxy(stringContents), options);
                         doc && generatedDocuments.push(doc);
                     }
                 }
-                if (item.kind === "file") {
+                if (item.kind === 'file') {
                     const file = item.getAsFile();
                     file?.type && files.push(file);
 
-                    file?.type === "application/json" && Utils.readUploadedFileAsText(file).then(result => {
-                        const json = JSON.parse(result as string);
-                        addDocument(Docs.Create.TreeDocument(
-                            json["rectangular-puzzle"].crossword.clues[0].clue.map((c: any) => {
-                                const label = Docs.Create.LabelDocument({ title: c["#text"], _width: 120, _height: 20 });
-                                const proto = Doc.GetProto(label);
-                                proto._width = 120;
-                                proto._height = 20;
-                                return proto;
-                            }
-                            ), { _width: 150, _height: 600, title: "across", backgroundColor: "white", _singleLine: true }));
-                    });
+                    file?.type === 'application/json' &&
+                        Utils.readUploadedFileAsText(file).then(result => {
+                            const json = JSON.parse(result as string);
+                            addDocument(
+                                Docs.Create.TreeDocument(
+                                    json['rectangular-puzzle'].crossword.clues[0].clue.map((c: any) => {
+                                        const label = Docs.Create.LabelDocument({ title: c['#text'], _width: 120, _height: 20 });
+                                        const proto = Doc.GetProto(label);
+                                        proto._width = 120;
+                                        proto._height = 20;
+                                        return proto;
+                                    }),
+                                    { _width: 150, _height: 600, title: 'across', backgroundColor: 'white', _singleLine: true }
+                                )
+                            );
+                        });
                 }
             }
             this.slowLoadDocuments(files, options, generatedDocuments, text, completed, e.clientX, e.clientY, addDocument).then(batch.end);
         }
-        slowLoadDocuments = async (files: (File[] | string), options: DocumentOptions, generatedDocuments: Doc[], text: string, completed: ((doc: Doc[]) => void) | undefined, clientX: number, clientY: number, addDocument: (doc: Doc | Doc[]) => boolean) => {
-            const disposer = OverlayView.Instance.addElement(
-                <ReactLoading type={"spinningBubbles"} color={"green"} height={250} width={250} />, { x: clientX - 125, y: clientY - 125 });
-            if (typeof files === "string") {
-                generatedDocuments.push(...await DocUtils.uploadYoutubeVideo(files, options));
+        slowLoadDocuments = async (
+            files: File[] | string,
+            options: DocumentOptions,
+            generatedDocuments: Doc[],
+            text: string,
+            completed: ((doc: Doc[]) => void) | undefined,
+            clientX: number,
+            clientY: number,
+            addDocument: (doc: Doc | Doc[]) => boolean
+        ) => {
+            const disposer = OverlayView.Instance.addElement(<ReactLoading type={'spinningBubbles'} color={'green'} height={250} width={250} />, { x: clientX - 125, y: clientY - 125 });
+            if (typeof files === 'string') {
+                generatedDocuments.push(...(await DocUtils.uploadYoutubeVideo(files, options)));
             } else {
-                generatedDocuments.push(...await DocUtils.uploadFilesToDocs(files, options));
+                generatedDocuments.push(...(await DocUtils.uploadFilesToDocs(files, options)));
             }
             if (generatedDocuments.length) {
                 // Creating a dash document
                 const isFreeformView = this.props.Document._viewType === CollectionViewType.Freeform;
-                const set = !isFreeformView ? generatedDocuments :
-                    generatedDocuments.length > 1 ? generatedDocuments.map(d => { DocUtils.iconify(d); return d; }) : [];
+                const set = !isFreeformView
+                    ? generatedDocuments
+                    : generatedDocuments.length > 1
+                    ? generatedDocuments.map(d => {
+                          DocUtils.iconify(d);
+                          return d;
+                      })
+                    : [];
                 if (completed) completed(set);
                 else {
                     if (isFreeformView && generatedDocuments.length > 1) {
-                        addDocument(DocUtils.pileup(generatedDocuments, options.x as number, options.y as number)!,);
+                        addDocument(DocUtils.pileup(generatedDocuments, options.x as number, options.y as number)!);
                     } else {
                         generatedDocuments.forEach(addDocument);
                     }
                 }
             } else {
-                if (text && !text.includes("https://")) {
+                if (text && !text.includes('https://')) {
                     addDocument(Docs.Create.TextDocument(text, { ...options, title: text.substring(0, 20), _width: 400, _height: 315 }));
                 } else {
-                    alert("Document upload failed - possibly an unsupported file type.");
+                    alert('Document upload failed - possibly an unsupported file type.');
                 }
             }
             disposer();
-        }
+        };
     }
 
     return CollectionSubView;
 }
 
-import { DragManager, dropActionType } from "../../util/DragManager";
-import { Docs, DocumentOptions, DocUtils } from "../../documents/Documents";
-import { CurrentUserUtils } from "../../util/CurrentUserUtils";
-import { DocumentType } from "../../documents/DocumentTypes";
-import { FormattedTextBox, GoogleRef } from "../nodes/formattedText/FormattedTextBox";
-import { CollectionView, CollectionViewType, CollectionViewProps } from "./CollectionView";
-import { SelectionManager } from "../../util/SelectionManager";
-import { OverlayView } from "../OverlayView";
-import { GetEffectiveAcl, TraceMobx } from "../../../fields/util";
\ No newline at end of file
+import { GetEffectiveAcl, TraceMobx } from '../../../fields/util';
+import { Docs, DocumentOptions, DocUtils } from '../../documents/Documents';
+import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
+import { DragManager, dropActionType } from '../../util/DragManager';
+import { SelectionManager } from '../../util/SelectionManager';
+import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
+import { OverlayView } from '../OverlayView';
+import { CollectionView, CollectionViewProps } from './CollectionView';
-- 
cgit v1.2.3-70-g09d2

