diff options
-rw-r--r-- | src/client/util/RichTextSchema.tsx | 2 | ||||
-rw-r--r-- | src/client/views/PreviewCursor.tsx | 83 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/MarqueeView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/nodes/FormattedTextBox.tsx | 48 | ||||
-rw-r--r-- | src/client/views/nodes/WebBox.scss | 10 | ||||
-rw-r--r-- | src/client/views/nodes/WebBox.tsx | 47 |
6 files changed, 153 insertions, 39 deletions
diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index 6d2abfaa2..9fdda4845 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -105,7 +105,6 @@ export const nodes: { [index: string]: NodeSpec } = { // } // }] }, - // :: NodeSpec An inline image (`<img>`) node. Supports `src`, // `alt`, and `href` attributes. The latter two default to the empty // string. @@ -197,7 +196,6 @@ export const nodes: { [index: string]: NodeSpec } = { ...listItem, content: 'paragraph block*' }, - }; const emDOM: DOMOutputSpecArray = ["em", 0]; diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx index e7a5475ed..d8e161ab6 100644 --- a/src/client/views/PreviewCursor.tsx +++ b/src/client/views/PreviewCursor.tsx @@ -1,13 +1,20 @@ -import { action, observable } from 'mobx'; +import { action, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import "normalize.css"; import * as React from 'react'; import "./PreviewCursor.scss"; +import { Docs } from '../documents/Documents'; +// import { Transform } from 'prosemirror-transform'; +import { Doc } from '../../new_fields/Doc'; +import { Transform } from "../util/Transform"; @observer export class PreviewCursor extends React.Component<{}> { private _prompt = React.createRef<HTMLDivElement>(); static _onKeyPress?: (e: KeyboardEvent) => void; + static _getTransform: () => Transform; + static _addLiveTextDoc: (doc: Doc) => void; + static _addDocument: (doc: Doc, allowDuplicates: false) => boolean; @observable static _clickPoint = [0, 0]; @observable public static Visible = false; //when focus is lost, this will remove the preview cursor @@ -20,12 +27,67 @@ export class PreviewCursor extends React.Component<{}> { document.addEventListener("keydown", this.onKeyPress); document.addEventListener("paste", this.paste); } + paste = (e: ClipboardEvent) => { - console.log(e.clipboardData); - if (e.clipboardData) { - console.log(e.clipboardData.getData("text/html")); - console.log(e.clipboardData.getData("text/csv")); - console.log(e.clipboardData.getData("text/plain")); + if (PreviewCursor.Visible) { + if (e.clipboardData) { + let newPoint = PreviewCursor._getTransform().transformPoint(PreviewCursor._clickPoint[0], PreviewCursor._clickPoint[1]); + runInAction(() => { PreviewCursor.Visible = false; }); + + + if (e.clipboardData.getData("text/plain") !== "") { + + // tests for youtube and makes video document + if (e.clipboardData.getData("text/plain").indexOf("www.youtube.com/watch") !== -1) { + const url = e.clipboardData.getData("text/plain").replace("youtube.com/watch?v=", "youtube.com/embed/"); + PreviewCursor._addDocument(Docs.Create.VideoDocument(url, { + title: url, width: 400, height: 315, + nativeWidth: 600, nativeHeight: 472.5, + x: newPoint[0], y: newPoint[1] + }), false); + return; + } + + // tests for URL and makes web document + let re: any = /^https?:\/\//g; + if (re.test(e.clipboardData.getData("text/plain"))) { + const url = e.clipboardData.getData("text/plain") + PreviewCursor._addDocument(Docs.Create.WebDocument(url, { + title: url, width: 300, height: 300, + // nativeWidth: 300, nativeHeight: 472.5, + x: newPoint[0], y: newPoint[1] + }), false); + return; + } + + // creates text document + let newBox = Docs.Create.TextDocument({ + width: 200, height: 100, + x: newPoint[0], + y: newPoint[1], + title: "-pasted text-" + }); + + newBox.proto!.autoHeight = true; + PreviewCursor._addLiveTextDoc(newBox); + return; + } + //pasting in images + if (e.clipboardData.getData("text/html") !== "" && e.clipboardData.getData("text/html").includes("<img src=")) { + let re: any = /<img src="(.*?)"/g; + let arr: any[] = re.exec(e.clipboardData.getData("text/html")); + + let img: Doc = Docs.Create.ImageDocument( + arr[1], { + width: 300, title: arr[1], + x: newPoint[0], + y: newPoint[1], + }); + PreviewCursor._addDocument(img, false); + return; + } + + } } } @@ -49,9 +111,16 @@ export class PreviewCursor extends React.Component<{}> { } } @action - public static Show(x: number, y: number, onKeyPress: (e: KeyboardEvent) => void) { + public static Show(x: number, y: number, + onKeyPress: (e: KeyboardEvent) => void, + addLiveText: (doc: Doc) => void, + getTransform: () => Transform, + addDocument: (doc: Doc, allowDuplicates: false) => boolean) { this._clickPoint = [x, y]; this._onKeyPress = onKeyPress; + this._addLiveTextDoc = addLiveText; + this._getTransform = getTransform; + this._addDocument = addDocument; setTimeout(action(() => this.Visible = true), (1)); } render() { diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 221237365..27eafd769 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -203,7 +203,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps> onClick = (e: React.MouseEvent): void => { if (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD) { - PreviewCursor.Show(e.clientX, e.clientY, this.onKeyPress); + PreviewCursor.Show(e.clientX, e.clientY, this.onKeyPress, this.props.addLiveTextDocument, this.props.getTransform, this.props.addDocument); // let the DocumentView stopPropagation of this event when it selects this document } else { // why do we get a click event when the cursor have moved a big distance? // let's cut it off here so no one else has to deal with it. diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 5492a457d..0e04bacf7 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -34,16 +34,12 @@ import "./FormattedTextBox.scss"; import React = require("react"); import { GoogleApiClientUtils, Pulls, Pushes } from '../../apis/google_docs/GoogleApiClientUtils'; import { DocumentDecorations } from '../DocumentDecorations'; -import { MainOverlayTextBox } from '../MainOverlayTextBox'; import { DictationManager } from '../../util/DictationManager'; import { ReplaceStep } from 'prosemirror-transform'; library.add(faEdit); library.add(faSmile, faTextHeight, faUpload); -// FormattedTextBox: Displays an editable plain text node that maps to a specified Key of a Document -// - export const Blank = `{"doc":{"type":"doc","content":[]},"selection":{"type":"text","anchor":0,"head":0}}`; export interface FormattedTextBoxProps { @@ -147,27 +143,29 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe paste = (e: ClipboardEvent) => { if (e.clipboardData && this._editorView) { - let pdfPasteText = `${Utils.GenerateDeterministicGuid("pdf paste")}`; - for (let i = 0; i < e.clipboardData.items.length; i++) { - let item = e.clipboardData.items.item(i); - if (item.type === "text/plain") { - item.getAsString((text) => { - let pdfPasteIndex = text.indexOf(pdfPasteText); - if (pdfPasteIndex > -1) { - let insertText = text.substr(0, pdfPasteIndex); - const tx = this._editorView!.state.tr.insertText(insertText); - // tx.setSelection(new Selection(tx.)) - const state = this._editorView!.state; - this._editorView!.dispatch(tx); - if (FormattedTextBox._toolTipTextMenu) { - // this._toolTipTextMenu.makeLinkWithState(state) - } - e.stopPropagation(); - e.preventDefault(); - } - }); - } - } + // let pdfPasteText = `${Utils.GenerateDeterministicGuid("pdf paste")}`; + // for (let i = 0; i < e.clipboardData.items.length; i++) { + // let item = e.clipboardData.items.item(i); + // console.log(item) + // if (item.type === "text/plain") { + // console.log("plain") + // item.getAsString((text) => { + // let pdfPasteIndex = text.indexOf(pdfPasteText); + // if (pdfPasteIndex > -1) { + // let insertText = text.substr(0, pdfPasteIndex); + // const tx = this._editorView!.state.tr.insertText(insertText); + // // tx.setSelection(new Selection(tx.)) + // const state = this._editorView!.state; + // this._editorView!.dispatch(tx); + // if (FormattedTextBox._toolTipTextMenu) { + // // this._toolTipTextMenu.makeLinkWithState(state) + // } + // e.stopPropagation(); + // e.preventDefault(); + // } + // }); + // } + // } } } diff --git a/src/client/views/nodes/WebBox.scss b/src/client/views/nodes/WebBox.scss index 07774263c..43220df71 100644 --- a/src/client/views/nodes/WebBox.scss +++ b/src/client/views/nodes/WebBox.scss @@ -1,3 +1,5 @@ +@import "../globalCssVariables.scss"; + .webBox-cont, .webBox-cont-interactive { padding: 0vw; @@ -61,6 +63,14 @@ width: 40px; transform-origin: top left; } + + .switchToText { + color: $main-accent; + } + + .switchToText:hover { + color: $dark-color; + } } button:hover { diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 9b66b2431..f0140d04b 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -1,7 +1,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { action, observable } from "mobx"; import { observer } from "mobx-react"; -import { FieldResult } from "../../../new_fields/Doc"; +import { FieldResult, Doc } from "../../../new_fields/Doc"; import { HtmlField } from "../../../new_fields/HtmlField"; import { InkTool } from "../../../new_fields/InkField"; import { Cast, NumCast } from "../../../new_fields/Types"; @@ -13,6 +13,12 @@ import { FieldView, FieldViewProps } from './FieldView'; import { KeyValueBox } from "./KeyValueBox"; import "./WebBox.scss"; import React = require("react"); +import { SelectionManager } from "../../util/SelectionManager"; +import { Docs } from "../../documents/Documents"; +import { faStickyNote } from "@fortawesome/free-solid-svg-icons"; +import { library } from "@fortawesome/fontawesome-svg-core"; + +library.add(faStickyNote) @observer export class WebBox extends React.Component<FieldViewProps> { @@ -64,6 +70,29 @@ export class WebBox extends React.Component<FieldViewProps> { } } + + switchToText = () => { + let url: string = ""; + let field = Cast(this.props.Document[this.props.fieldKey], WebField); + if (field) url = field.url.href; + + let newBox = Docs.Create.TextDocument({ + x: NumCast(this.props.Document.x), + y: NumCast(this.props.Document.y), + title: url, + width: 200, + height: 70, + documentText: "@@@" + url + }); + + SelectionManager.SelectedDocuments().map(dv => { + dv.props.addDocument && dv.props.addDocument(newBox, false); + dv.props.removeDocument && dv.props.removeDocument(dv.props.Document); + }); + + Doc.BrushDoc(newBox); + } + urlEditor() { return ( <div className="webView-urlEditor" style={{ top: this.collapsed ? -70 : 0 }}> @@ -86,9 +115,19 @@ export class WebBox extends React.Component<FieldViewProps> { onChange={this.onURLChange} onKeyDown={this.onValueKeyDown} /> - <button className="submitUrl" onClick={this.submitURL}> - SUBMIT URL - </button> + <div style={{ + display: "flex", + flexDirection: "row", + justifyContent: "space-between", + minWidth: "100px", + }}> + <button className="submitUrl" onClick={this.submitURL}> + SUBMIT + </button> + <div className="switchToText" title="Convert web to text doc" onClick={this.switchToText} style={{ display: "flex", alignItems: "center", justifyContent: "center" }} > + <FontAwesomeIcon icon={faStickyNote} size={"lg"} /> + </div> + </div> </div> </div> </div> |