aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/util/DragManager.ts1
-rw-r--r--src/client/views/GestureOverlay.tsx4
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx14
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx66
-rw-r--r--src/client/views/nodes/DocumentView.tsx17
-rw-r--r--src/client/views/nodes/FormattedTextBox.tsx28
-rw-r--r--src/client/views/nodes/RadialMenu.tsx8
-rw-r--r--src/client/views/nodes/WebBox.tsx46
-rw-r--r--src/mobile/MobileInkOverlay.tsx1
-rw-r--r--src/mobile/MobileInterface.tsx43
-rw-r--r--src/server/authentication/models/current_user_utils.ts3
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([], {