diff options
author | Stanley Yip <stanley_yip@brown.edu> | 2020-02-23 14:24:07 -0500 |
---|---|---|
committer | Stanley Yip <stanley_yip@brown.edu> | 2020-02-23 14:24:07 -0500 |
commit | f1fcbeea5fb103b7623e795e72aacd4dfacc6c70 (patch) | |
tree | b599d8743157ea6552714949e998ae0954f3d854 /src | |
parent | a8b19e82d8c9a8350609e64e60848dbfbbbb6dcd (diff) | |
parent | 0299ecb4db88560fe623b429f36191402c00b264 (diff) |
final commits before demo
Diffstat (limited to 'src')
-rw-r--r-- | src/client/util/DragManager.ts | 1 | ||||
-rw-r--r-- | src/client/views/GestureOverlay.tsx | 4 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 14 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/MarqueeView.tsx | 66 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 17 | ||||
-rw-r--r-- | src/client/views/nodes/FormattedTextBox.tsx | 28 | ||||
-rw-r--r-- | src/client/views/nodes/RadialMenu.tsx | 8 | ||||
-rw-r--r-- | src/client/views/nodes/WebBox.tsx | 46 | ||||
-rw-r--r-- | src/mobile/MobileInkOverlay.tsx | 1 | ||||
-rw-r--r-- | src/mobile/MobileInterface.tsx | 43 | ||||
-rw-r--r-- | src/server/authentication/models/current_user_utils.ts | 3 |
11 files changed, 153 insertions, 78 deletions
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index bf64e0bdb..5d4b8fc8a 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -289,7 +289,6 @@ export namespace DragManager { if (!ele.parentNode) dragDiv.appendChild(ele); const dragElement = ele.parentNode === dragDiv ? ele : ele.cloneNode(true) as HTMLElement; const rect = ele.getBoundingClientRect(); - console.log("boudning", rect); const scaleX = rect.width / ele.offsetWidth, scaleY = rect.height / ele.offsetHeight; xs.push(rect.left); diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index 460a764e8..11ad26cbe 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -28,10 +28,12 @@ import { List } from "../../new_fields/List"; import { CollectionViewType } from "./collections/CollectionView"; import TouchScrollableMenu, { TouchScrollableMenuItem } from "./TouchScrollableMenu"; import { RadialMenu } from "./nodes/RadialMenu"; -import { SelectionManager } from "../util/SelectionManager"; import MobileInterface from "../../mobile/MobileInterface"; import { MobileInkOverlayContent } from "../../server/Message"; import MobileInkOverlay from "../../mobile/MobileInkOverlay"; +import { RadialMenu } from "./nodes/RadialMenu"; +import { SelectionManager } from "../util/SelectionManager"; + @observer export default class GestureOverlay extends Touchable { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 2f50fd710..047a3a1cc 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -86,7 +86,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { @observable private _pullCoords: number[] = [0, 0]; @observable private _pullDirection: string = ""; - public get displayName() { return "CollectionFreeFormView(" + this.props.Document.title ?.toString() + ")"; } // this makes mobx trace() statements more descriptive + public get displayName() { return "CollectionFreeFormView(" + this.props.Document.title?.toString() + ")"; } // this makes mobx trace() statements more descriptive @observable.shallow _layoutElements: ViewDefResult[] = []; // shallow because some layout items (eg pivot labels) are just generated 'divs' and can't be frozen as observables @observable _clusterSets: (Doc[])[] = []; @@ -255,7 +255,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { docs.map(doc => this._clusterSets[doc.cluster = NumCast(docFirst.cluster)].push(doc)); } childLayouts.map(child => !this._clusterSets.some((set, i) => Doc.IndexOf(child, set) !== -1 && child.cluster === i) && this.updateCluster(child)); - childLayouts.map(child => Doc.GetProto(child).clusterStr = child.cluster ?.toString()); + childLayouts.map(child => Doc.GetProto(child).clusterStr = child.cluster?.toString()); } } @@ -434,9 +434,9 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { console.log("end"); if (this._inkToTextStartX && this._inkToTextStartY) { const end = this.getTransform().transformPoint(Math.max(...ge.points.map(p => p.X)), Math.max(...ge.points.map(p => p.Y))); - const setDocs = this.getActiveDocuments().filter(s => s.proto ?.type === "text" && s.color); + const setDocs = this.getActiveDocuments().filter(s => s.proto?.type === "text" && s.color); const sets = setDocs.map((sd) => { - return Cast(sd.data, RichTextField) ?.Text as string; + return Cast(sd.data, RichTextField)?.Text as string; }); if (sets.length && sets[0]) { this._wordPalette.clear(); @@ -883,8 +883,8 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { } getCalculatedPositions(params: { doc: Doc, index: number, collection: Doc, docs: Doc[], state: any }): { x?: number, y?: number, z?: number, width?: number, height?: number, transition?: string, state?: any } { - const result = this.Document.arrangeScript ?.script.run(params, console.log); - if (result ?.success) { + const result = this.Document.arrangeScript?.script.run(params, console.log); + if (result?.success) { return { ...result, transition: "transform 1s" }; } const layoutDoc = Doc.Layout(params.doc); @@ -1114,7 +1114,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { } @computed get placeholder() { return <div className="collectionfreeformview-placeholder" style={{ background: this.Document.backgroundColor }}> - <span className="collectionfreeformview-placeholderSpan">{this.props.Document.title ?.toString()}</span> + <span className="collectionfreeformview-placeholderSpan">{this.props.Document.title?.toString()}</span> </div>; } @computed get marqueeView() { diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index d4faa4dc1..fb476b54b 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -1,7 +1,7 @@ import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast, DataSym, WidthSym, HeightSym } from "../../../../new_fields/Doc"; -import { InkField } from "../../../../new_fields/InkField"; +import { InkField, InkData } from "../../../../new_fields/InkField"; import { List } from "../../../../new_fields/List"; import { listSpec } from "../../../../new_fields/Schema"; import { SchemaHeaderField } from "../../../../new_fields/SchemaHeaderField"; @@ -382,8 +382,18 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque wordToColor.set(word, colors[i]); }); }); - const inkFields = inks.map(i => Cast(i.data, InkField)); - CognitiveServices.Inking.Appliers.InterpretStrokes(inkFields.filter(i => i instanceof InkField).map(i => i!.inkData)).then((results) => { + const strokes: InkData[] = []; + inks.forEach(i => { + const d = Cast(i.data, InkField); + const x = NumCast(i.x); + const y = NumCast(i.y); + const left = Math.min(...d?.inkData.map(pd => pd.X) ?? [0]); + const top = Math.min(...d?.inkData.map(pd => pd.Y) ?? [0]); + if (d) { + strokes.push(d.inkData.map(pd => ({ X: pd.X + x - left, Y: pd.Y + y - top }))); + } + }); + CognitiveServices.Inking.Appliers.InterpretStrokes(strokes).then((results) => { // const wordResults = results.filter((r: any) => r.category === "inkWord"); // console.log(wordResults); // console.log(results); @@ -403,29 +413,33 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque // } // }) // } - const wordResults = results.filter((r: any) => r.category === "inkWord"); - for (const word of wordResults) { - const indices: number[] = word.strokeIds; - indices.forEach(i => { - const otherInks: Doc[] = []; - indices.forEach(i2 => i2 !== i && otherInks.push(inks[i2])); - inks[i].relatedInks = new List<Doc>(otherInks); - const uniqueColors: string[] = []; - Array.from(wordToColor.values()).forEach(c => uniqueColors.indexOf(c) === -1 && uniqueColors.push(c)); - inks[i].alternativeColors = new List<string>(uniqueColors); - if (wordToColor.has(word.recognizedText.toLowerCase())) { - inks[i].color = wordToColor.get(word.recognizedText.toLowerCase()); - } - else if (word.alternates) { - for (const alt of word.alternates) { - if (wordToColor.has(alt.recognizedString.toLowerCase())) { - inks[i].color = wordToColor.get(alt.recognizedString.toLowerCase()); - break; - } - } - } - }); - } + // const wordResults = results.filter((r: any) => r.category === "inkWord"); + // for (const word of wordResults) { + // const indices: number[] = word.strokeIds; + // indices.forEach(i => { + // const otherInks: Doc[] = []; + // indices.forEach(i2 => i2 !== i && otherInks.push(inks[i2])); + // inks[i].relatedInks = new List<Doc>(otherInks); + // const uniqueColors: string[] = []; + // Array.from(wordToColor.values()).forEach(c => uniqueColors.indexOf(c) === -1 && uniqueColors.push(c)); + // inks[i].alternativeColors = new List<string>(uniqueColors); + // if (wordToColor.has(word.recognizedText.toLowerCase())) { + // inks[i].color = wordToColor.get(word.recognizedText.toLowerCase()); + // } + // else if (word.alternates) { + // for (const alt of word.alternates) { + // if (wordToColor.has(alt.recognizedString.toLowerCase())) { + // inks[i].color = wordToColor.get(alt.recognizedString.toLowerCase()); + // break; + // } + // } + // } + // }); + // } + const lines = results.filter((r: any) => r.category === "line"); + console.log(lines); + const text = lines.map((l: any) => l.recognizedText).join("\r\n"); + this.props.addDocument(Docs.Create.TextDocument(text, { _width: this.Bounds.width, _height: this.Bounds.height, x: this.Bounds.left + this.Bounds.width, y: this.Bounds.top, title: text })); }); } } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 9182eb4c0..09abd6d1d 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -165,14 +165,13 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu me.touchEvent.stopPropagation(); me.touchEvent.preventDefault(); e.stopPropagation(); - - + if (RadialMenu.Instance.used) { + this.onContextMenu(me.touches[0]); + } } @action onRadialMenu = (e: Event, me: InteractionUtils.MultiTouchEvent<React.TouchEvent>): void => { - console.log("DISPLAYMENUUUU"); - console.log(me.touchEvent.touches); // console.log(InteractionUtils.GetMyTargetTouches(me, this.prevPoints, true)); // const pt = InteractionUtils.GetMyTargetTouches(me, this.prevPoints, true)[0]; const pt = me.touchEvent.touches[me.touchEvent.touches.length - 1]; @@ -744,7 +743,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu return; } e.persist(); - e.stopPropagation(); + e?.stopPropagation(); if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3 || e.isDefaultPrevented()) { e.preventDefault(); @@ -836,12 +835,12 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu ext_recommender_subitems.push({ description: "arXiv", - event: () => this.externalRecommendation(e, "arxiv"), + event: () => this.externalRecommendation("arxiv"), icon: "brain" }); ext_recommender_subitems.push({ description: "Bing", - event: () => this.externalRecommendation(e, "bing"), + event: () => this.externalRecommendation("bing"), icon: "brain" }); @@ -891,7 +890,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu if (!this.topMost) { // DocumentViews should stop propagation of this event - e.stopPropagation(); + me?.stopPropagation(); } ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); if (!SelectionManager.IsSelected(this, true)) { @@ -964,7 +963,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu } @action - externalRecommendation = async (e: React.MouseEvent, api: string) => { + externalRecommendation = async (api: string) => { if (!ClientRecommender.Instance) new ClientRecommender({ title: "Client Recommender" }); ClientRecommender.Instance.reset_docs(); const doc = Doc.GetDataDoc(this.props.Document); diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 0d97c3029..213af43c6 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -700,7 +700,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & setTimeout(async () => { const targetField = Doc.LayoutFieldKey(pdfDoc); const targetAnnotations = await DocListCastAsync(pdfDoc[DataSym][targetField + "-annotations"]);// bcz: better to have the PDF's view handle updating its own annotations - targetAnnotations?.push(pdfRegion); + targetAnnotations ?.push(pdfRegion); }); const link = DocUtils.MakeLink({ doc: this.props.Document, ctx: this.props.ContainingCollectionDoc }, { doc: pdfRegion, ctx: pdfDoc }, "note on " + pdfDoc.title, "pasted PDF link"); @@ -742,14 +742,14 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & const rtfField = Cast(this.props.Document._textTemplate || this.dataDoc[fieldKey], RichTextField); if (this.ProseRef) { const self = this; - this._editorView?.destroy(); + this._editorView ?.destroy(); this._editorView = new EditorView(this.ProseRef, { - state: rtfField?.Data ? EditorState.fromJSON(config, JSON.parse(rtfField.Data)) : EditorState.create(config), + state: rtfField ?.Data ? EditorState.fromJSON(config, JSON.parse(rtfField.Data)) : EditorState.create(config), handleScrollToSelection: (editorView) => { const ref = editorView.domAtPos(editorView.state.selection.from); let refNode = ref.node as any; while (refNode && !("getBoundingClientRect" in refNode)) refNode = refNode.parentElement; - const r1 = refNode?.getBoundingClientRect(); + const r1 = refNode ?.getBoundingClientRect(); const r3 = self._ref.current!.getBoundingClientRect(); if (r1.top < r3.top || r1.top > r3.bottom) { r1 && (self._scrollRef.current!.scrollTop += (r1.top - r3.top) * self.props.ScreenToLocalTransform().Scale); @@ -848,11 +848,11 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & this.tryUpdateHeight(); // see if we need to preserve the insertion point - const prosediv = this.ProseRef?.children?.[0] as any; - const keeplocation = prosediv?.keeplocation; + const prosediv = this.ProseRef ?.children ?.[0] as any; + const keeplocation = prosediv ?.keeplocation; prosediv && (prosediv.keeplocation = undefined); - const pos = this._editorView?.state.selection.$from.pos || 1; - keeplocation && setTimeout(() => this._editorView?.dispatch(this._editorView?.state.tr.setSelection(TextSelection.create(this._editorView.state.doc, pos)))); + const pos = this._editorView ?.state.selection.$from.pos || 1; + keeplocation && setTimeout(() => this._editorView ?.dispatch(this._editorView ?.state.tr.setSelection(TextSelection.create(this._editorView.state.doc, pos)))); // jump rich text menu to this textbox const { current } = this._ref; @@ -876,13 +876,13 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & if ((this._editorView!.root as any).getSelection().isCollapsed) { // this is a hack to allow the cursor to be placed at the end of a document when the document ends in an inline dash comment. Apparently Chrome on Windows has a bug/feature which breaks this when clicking after the end of the text. const pcords = this._editorView!.posAtCoords({ left: e.clientX, top: e.clientY }); const node = pcords && this._editorView!.state.doc.nodeAt(pcords.pos); // get what prosemirror thinks the clicked node is (if it's null, then we didn't click on any text) - if (pcords && node?.type === this._editorView!.state.schema.nodes.dashComment) { + if (pcords && node ?.type === this._editorView!.state.schema.nodes.dashComment) { this._editorView!.dispatch(this._editorView!.state.tr.setSelection(TextSelection.create(this._editorView!.state.doc, pcords.pos + 2))); e.preventDefault(); } if (!node && this.ProseRef) { const lastNode = this.ProseRef.children[this.ProseRef.children.length - 1].children[this.ProseRef.children[this.ProseRef.children.length - 1].children.length - 1]; // get the last prosemirror div - if (e.clientY > lastNode?.getBoundingClientRect().bottom) { // if we clicked below the last prosemirror div, then set the selection to be the end of the document + if (e.clientY > lastNode ?.getBoundingClientRect().bottom) { // if we clicked below the last prosemirror div, then set the selection to be the end of the document this._editorView!.dispatch(this._editorView!.state.tr.setSelection(TextSelection.create(this._editorView!.state.doc, this._editorView!.state.doc.content.size))); } } @@ -939,7 +939,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & for (let off = 1; off < 100; off++) { const pos = this._editorView!.posAtCoords({ left: x + off, top: y }); const node = pos && this._editorView!.state.doc.nodeAt(pos.pos); - if (node?.type === schema.nodes.list_item) { + if (node ?.type === schema.nodes.list_item) { list_node = node; break; } @@ -984,7 +984,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & const self = FormattedTextBox; return new Plugin({ view(newView) { - RichTextMenu.Instance.changeView(newView); + RichTextMenu.Instance && RichTextMenu.Instance.changeView(newView); return RichTextMenu.Instance; } }); @@ -1021,7 +1021,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & } if (e.key === "Escape") { this._editorView!.dispatch(state.tr.setSelection(TextSelection.create(state.doc, state.selection.from, state.selection.from))); - (document.activeElement as any).blur?.(); + (document.activeElement as any).blur ?.(); SelectionManager.DeselectAll(); } e.stopPropagation(); @@ -1043,7 +1043,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & @action tryUpdateHeight(limitHeight?: number) { - let scrollHeight = this._ref.current?.scrollHeight; + let scrollHeight = this._ref.current ?.scrollHeight; if (!this.layoutDoc.animateToPos && this.layoutDoc._autoHeight && scrollHeight && getComputedStyle(this._ref.current!.parentElement!).top === "0px") { // if top === 0, then the text box is growing upward (as the overlay caption) which doesn't contribute to the height computation if (limitHeight && scrollHeight > limitHeight) { diff --git a/src/client/views/nodes/RadialMenu.tsx b/src/client/views/nodes/RadialMenu.tsx index a6fb72a7b..d7f7c2e33 100644 --- a/src/client/views/nodes/RadialMenu.tsx +++ b/src/client/views/nodes/RadialMenu.tsx @@ -5,6 +5,8 @@ import { RadialMenuItem, RadialMenuProps } from "./RadialMenuItem"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import Measure from "react-measure"; import "./RadialMenu.scss"; +import MobileInkOverlay from "../../../mobile/MobileInkOverlay"; +import MobileInterface from "../../../mobile/MobileInterface"; @observer export class RadialMenu extends React.Component { @@ -23,6 +25,8 @@ export class RadialMenu extends React.Component { @observable private _mouseDown: boolean = false; private _reactionDisposer?: IReactionDisposer; + public used: boolean = false; + catchTouch = (te: React.TouchEvent) => { console.log("caught"); @@ -35,6 +39,7 @@ export class RadialMenu extends React.Component { this._mouseDown = true; this._mouseX = e.clientX; this._mouseY = e.clientY; + this.used = false; document.addEventListener("pointermove", this.onPointerMove); } @@ -68,6 +73,7 @@ export class RadialMenu extends React.Component { } @action onPointerUp = (e: PointerEvent) => { + this.used = true; this._mouseDown = false; const curX = e.clientX; const curY = e.clientY; @@ -213,7 +219,7 @@ export class RadialMenu extends React.Component { render() { - if (!this._display) { + if (!this._display || MobileInterface.Instance) { return null; } const style = this._yRelativeToTop ? { left: this._pageX - 130, top: this._pageY - 130 } : diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 6cae4e878..f1620b80e 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -24,6 +24,7 @@ import { documentSchema } from "../../../new_fields/documentSchemas"; import { Id } from "../../../new_fields/FieldSymbols"; import { DragManager } from "../../util/DragManager"; import { ImageUtils } from "../../util/Import & Export/ImageUtils"; +import { select } from "async"; library.add(faStickyNote); @@ -189,30 +190,39 @@ export class WebBox extends DocAnnotatableComponent<FieldViewProps, WebDocument> // find the pressed element in the iframe (currently only works if its an img) let pressedElement: HTMLElement | undefined; let pressedBound: ClientRect | undefined; + let selectedText: string = ""; + let pressedImg: boolean = false; if (this._iframeRef.current) { const B = this._iframeRef.current.getBoundingClientRect(); const iframeDoc = this._iframeRef.current.contentDocument; if (B && iframeDoc) { - // check if there is selected text - const selectedText = iframeDoc.getSelection(); - if (selectedText && selectedText.toString.length > -1) { - - } - console.log("selectedText", selectedText ? selectedText.toString() : ""); - // TODO: this only works when scale = 1 as it is currently only inteded for mobile upload const element = iframeDoc.elementFromPoint(this._pressX - B.left, this._pressY - B.top); - console.log("found element", element, element && element.nodeName); - if (element && element.nodeName) {//} === "IMG") { + if (element && element.nodeName === "IMG") { pressedBound = element.getBoundingClientRect(); pressedElement = element.cloneNode(true) as HTMLElement; + pressedImg = true; + } else { + // check if there is selected text + const text = iframeDoc.getSelection(); + if (text && text.toString().length > 0) { + selectedText = text.toString(); + + // get html of the selected text + const range = text.getRangeAt(0); + const contents = range.cloneContents(); + const div = document.createElement("div"); + div.appendChild(contents); + pressedElement = div; + + pressedBound = range.getBoundingClientRect(); + } } } } // mark the pressed element if (pressedElement && pressedBound) { - console.log("clones b", pressedElement.getBoundingClientRect(), pressedBound); if (this._iframeIndicatorRef.current) { this._iframeIndicatorRef.current.style.top = pressedBound.top + "px"; this._iframeIndicatorRef.current.style.left = pressedBound.left + "px"; @@ -224,13 +234,13 @@ export class WebBox extends DocAnnotatableComponent<FieldViewProps, WebDocument> // start dragging the pressed element if long pressed this._longPressSecondsHack = setTimeout(() => { - if (pressedElement && pressedBound) { + if (pressedImg && pressedElement && pressedBound) { e.stopPropagation(); e.preventDefault(); if (pressedElement.nodeName === "IMG") { const src = pressedElement.getAttribute("src"); // TODO: may not always work if (src) { - const doc = Docs.Create.ImageDocument(src, { _width: 300 }); + const doc = Docs.Create.ImageDocument(src); ImageUtils.ExtractExif(doc); // add clone to div so that dragging ghost is placed properly @@ -240,6 +250,18 @@ export class WebBox extends DocAnnotatableComponent<FieldViewProps, WebDocument> DragManager.StartDocumentDrag([pressedElement], dragData, this._pressX, this._pressY, { hideSource: true }); } } + } else if (selectedText && pressedBound && pressedElement) { + e.stopPropagation(); + e.preventDefault(); + // create doc with the selected text's html + const doc = Docs.Create.HtmlDocument(pressedElement.innerHTML); + + // create dragging ghost with the selected text + if (this._iframeDragRef.current) this._iframeDragRef.current.appendChild(pressedElement); + + // start the drag + const dragData = new DragManager.DocumentDragData([doc]); + DragManager.StartDocumentDrag([pressedElement], dragData, this._pressX - pressedBound.top, this._pressY - pressedBound.top, { hideSource: true }); } }, 1500); } diff --git a/src/mobile/MobileInkOverlay.tsx b/src/mobile/MobileInkOverlay.tsx index 4dde3a075..1537ae034 100644 --- a/src/mobile/MobileInkOverlay.tsx +++ b/src/mobile/MobileInkOverlay.tsx @@ -102,6 +102,7 @@ export default class MobileInkOverlay extends React.Component { const complete = new DragManager.DragCompleteEvent(false, dragData); if (target) { + console.log("dispatching upload doc!!!!", target, doc); target.dispatchEvent( new CustomEvent<DragManager.DropEvent>("dashOnDrop", { diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index 83410b99d..5d3a517ae 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -35,6 +35,10 @@ import GoogleAuthenticationManager from '../client/apis/GoogleAuthenticationMana import { listSpec } from '../new_fields/Schema'; import { Id } from '../new_fields/FieldSymbols'; import { DocumentManager } from '../client/util/DocumentManager'; +import RichTextMenu from '../client/util/RichTextMenu'; +import { WebField } from "../new_fields/URLField"; +import { FieldResult } from "../new_fields/Doc"; +import { List } from '../new_fields/List'; library.add(faLongArrowAltLeft); @@ -235,17 +239,42 @@ export default class MobileInterface extends React.Component { e.preventDefault(); } + addWebToCollection = async () => { + let url = "https://en.wikipedia.org/wiki/Hedgehog"; + if (this.mainContainer) { + const data = Cast(this.mainContainer.data, listSpec(Doc)); + if (data) { + const webDoc = await data[0]; + const urlField: FieldResult<WebField> = Cast(webDoc.data, WebField); + url = urlField ? urlField.url.toString() : "https://en.wikipedia.org/wiki/Hedgehog"; + + } + } + Docs.Create.WebDocument(url, { _width: 300, _height: 300, title: "Mobile Upload Web Doc" }); + } + + clearUpload = async () => { + if (this.mainContainer) { + const data = Cast(this.mainContainer.data, listSpec(Doc)); + if (data) { + const collectionDoc = await data[1]; + const children = DocListCast(collectionDoc.data); + children.forEach(doc => { + }); + // collectionDoc[data] = new List<Doc>(); + } + } + } + renderUploadContent() { if (this.mainContainer) { return ( <div className="mobileInterface" onDragOver={this.onDragOver}> <div className="mobileInterface-inkInterfaceButtons"> - <div className="navButtons"> - <button className="mobileInterface-button cancel" onClick={this.onBack} title="Back">BACK</button> - </div> - <div className="uploadSettings"> - <button className="mobileInterface-button" onClick={this.upload} title="Upload">UPLOAD</button> - </div> + <button className="mobileInterface-button cancel" onClick={this.onBack} title="Back">BACK</button> + {/* <button className="mobileInterface-button" onClick={this.clearUpload} title="Clear Upload">CLEAR</button> */} + {/* <button className="mobileInterface-button" onClick={this.addWeb} title="Add Web Doc to Upload Collection"></button> */} + <button className="mobileInterface-button" onClick={this.upload} title="Upload">UPLOAD</button> </div> <DocumentView Document={this.mainContainer} @@ -302,6 +331,7 @@ export default class MobileInterface extends React.Component { <PreviewCursor /> {/* <ContextMenu /> */} <RadialMenu /> + <RichTextMenu /> {/* <PDFMenu /> <MarqueeOptionsMenu /> <OverlayView /> */} @@ -315,4 +345,5 @@ Scripting.addGlobal(function onSwitchMobileInking() { return MobileInterface.Ins Scripting.addGlobal(function renderMobileInking() { return MobileInterface.Instance.renderInkingContent(); }); Scripting.addGlobal(function onSwitchMobileUpload() { return MobileInterface.Instance.onSwitchUpload(); }); Scripting.addGlobal(function renderMobileUpload() { return MobileInterface.Instance.renderUploadContent(); }); +Scripting.addGlobal(function addWebToMobileUpload() { return MobileInterface.Instance.addWebToCollection(); }); diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 6c916689a..a7cc6d3e9 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -155,7 +155,8 @@ export class CurrentUserUtils { } static setupMobileUploadDoc(userDoc: Doc) { - const webDoc = Docs.Create.WebDocument("https://www.britannica.com/animal/cat", { + // const addButton = Docs.Create.FontIconDocument({ onDragStart: ScriptField.MakeScript('addWebToMobileUpload()'), title: "Add Web Doc to Upload Collection", icon: "plus", backgroundColor: "black" }) + const webDoc = Docs.Create.WebDocument("https://www.britannica.com/biography/Miles-Davis", { title: "Upload Images From the Web", _chromeStatus: "enabled", lockedPosition: true }); const uploadDoc = Docs.Create.StackingDocument([], { |