diff options
Diffstat (limited to 'src/client/views/nodes/formattedText/FormattedTextBox.tsx')
-rw-r--r-- | src/client/views/nodes/formattedText/FormattedTextBox.tsx | 72 |
1 files changed, 39 insertions, 33 deletions
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index ae26f170b..731ab1d53 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -14,7 +14,7 @@ import * as React from 'react'; import { BsMarkdownFill } from 'react-icons/bs'; import { DateField } from '../../../../fields/DateField'; import { Doc, DocListCast, Field, Opt } from '../../../../fields/Doc'; -import { AclAdmin, AclAugment, AclEdit, AclSelfEdit, DocCss, ForceServerWrite, UpdatingFromServer } from '../../../../fields/DocSymbols'; +import { AclAdmin, AclAugment, AclEdit, AclSelfEdit, DocCss, DocData, ForceServerWrite, UpdatingFromServer } from '../../../../fields/DocSymbols'; import { Id } from '../../../../fields/FieldSymbols'; import { InkTool } from '../../../../fields/InkField'; import { List } from '../../../../fields/List'; @@ -42,7 +42,7 @@ import { CollectionStackingView } from '../../collections/CollectionStackingView import { CollectionTreeView } from '../../collections/CollectionTreeView'; import { ContextMenu } from '../../ContextMenu'; import { ContextMenuProps } from '../../ContextMenuItem'; -import { ViewBoxAnnotatableComponent } from '../../DocComponent'; +import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../../DocComponent'; import { Colors } from '../../global/globalEnums'; import { LightboxView } from '../../LightboxView'; import { AnchorMenu } from '../../pdf/AnchorMenu'; @@ -50,8 +50,8 @@ import { GPTPopup } from '../../pdf/GPTPopup/GPTPopup'; import { SidebarAnnos } from '../../SidebarAnnos'; import { StyleProp } from '../../StyleProvider'; import { media_state } from '../AudioBox'; -import { DocFocusOptions, DocumentView, DocumentViewInternal, OpenWhere } from '../DocumentView'; -import { FieldView, FieldViewProps } from '../FieldView'; +import { DocumentView, DocumentViewInternal, OpenWhere } from '../DocumentView'; +import { FocusViewOptions, FieldView, FieldViewProps } from '../FieldView'; import { LinkInfo } from '../LinkDocPreview'; import { PinProps, PresBox } from '../trails'; import { DashDocCommentView } from './DashDocCommentView'; @@ -68,10 +68,8 @@ import { RichTextRules } from './RichTextRules'; import { schema } from './schema_rts'; import { SummaryView } from './SummaryView'; // import * as applyDevTools from 'prosemirror-dev-tools'; - -export interface FormattedTextBoxProps {} @observer -export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps & FormattedTextBoxProps>() { +export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implements ViewBoxInterface { public static LayoutString(fieldStr: string) { return FieldView.LayoutString(FormattedTextBox, fieldStr); } @@ -91,6 +89,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps private _scrollRef: React.RefObject<HTMLDivElement> = React.createRef(); private _editorView: Opt<EditorView>; public _applyingChange: string = ''; + private _inDrop = false; private _finishingLink = false; private _searchIndex = 0; private _lastTimedMark: Mark | undefined = undefined; @@ -123,7 +122,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps } @computed get noSidebar() { - return this._props.docViewPath().lastElement()?._props.hideDecorationTitle || this._props.noSidebar || this.Document._layout_noSidebar; + return this.DocumentView?.()._props.hideDecorationTitle || this._props.noSidebar || this.Document._layout_noSidebar; } @computed get layout_sidebarWidthPercent() { return this._showSidebar ? '20%' : StrCast(this.layoutDoc._layout_sidebarWidthPercent, '0%'); @@ -202,7 +201,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps return url.startsWith(document.location.origin) ? new URL(url).pathname.split('doc/').lastElement() : ''; // docId } - constructor(props: any) { + constructor(props: FieldViewProps) { super(props); makeObservable(this); FormattedTextBox.Instance = this; @@ -271,14 +270,15 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps if (target) { anchor.followLinkAudio = true; let stopFunc: any; - Doc.GetProto(target).mediaState = media_state.Recording; - Doc.GetProto(target).audioAnnoState = 'recording'; - DocumentViewInternal.recordAudioAnnotation(Doc.GetProto(target), Doc.LayoutFieldKey(target), stop => (stopFunc = stop)); + const targetData = target[DocData]; + targetData.mediaState = media_state.Recording; + targetData.audioAnnoState = 'recording'; + DocumentViewInternal.recordAudioAnnotation(targetData, Doc.LayoutFieldKey(target), stop => (stopFunc = stop)); let reactionDisposer = reaction( () => target.mediaState, action(dictation => { if (!dictation) { - Doc.GetProto(target).audioAnnoState = 'stopped'; + targetData.audioAnnoState = 'stopped'; stopFunc(); reactionDisposer(); } @@ -310,7 +310,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps return target; }; - DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(this._props.docViewPath().lastElement(), () => this.getAnchor(true), targetCreator), e.pageX, e.pageY); + DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(this.DocumentView?.()!, () => this.getAnchor(true), targetCreator), e.pageX, e.pageY); }); const coordsB = this._editorView!.coordsAtPos(this._editorView!.state.selection.to); this._props.rootSelected?.() && AnchorMenu.Instance.jumpTo(coordsB.left, coordsB.bottom); @@ -356,7 +356,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps textChange && (dataDoc[this.fieldKey + '_modificationDate'] = new DateField(new Date(Date.now()))); if ((!prevData && !protoData) || newText || (!newText && !templateData)) { // if no template, or there's text that didn't come from the layout template, write it to the document. (if this is driven by a template, then this overwrites the template text which is intended) - if ((this._finishingLink || this._props.isContentActive()) && removeSelection(newJson) !== removeSelection(prevData?.Data)) { + if ((this._finishingLink || this._props.isContentActive() || this._inDrop) && removeSelection(newJson) !== removeSelection(prevData?.Data)) { const numstring = NumCast(dataDoc[this.fieldKey], null); dataDoc[this.fieldKey] = numstring !== undefined ? Number(newText) : new RichTextField(newJson, newText); dataDoc[this.fieldKey + '_noTemplate'] = true; // mark the data field as being split from the template if it has been edited @@ -433,7 +433,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps autoLink = () => { const newAutoLinks = new Set<Doc>(); - const oldAutoLinks = LinkManager.Links(this._props.Document).filter(link => link.link_relationship === LinkManager.AutoKeywords); + const oldAutoLinks = LinkManager.Links(this.Document).filter(link => link.link_relationship === LinkManager.AutoKeywords); if (this._editorView?.state.doc.textContent) { const isNodeSel = this._editorView.state.selection instanceof NodeSelection; const f = this._editorView.state.selection.from; @@ -451,7 +451,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps updateTitle = () => { const title = StrCast(this.dataDoc.title, Cast(this.dataDoc.title, RichTextField, null)?.Text); if ( - !this._props.dontRegisterView && // (this._props.Document.isTemplateForField === "text" || !this._props.Document.isTemplateForField) && // only update the title if the data document's data field is changing + !this._props.dontRegisterView && // (this.Document.isTemplateForField === "text" || !this.Document.isTemplateForField) && // only update the title if the data document's data field is changing (title.startsWith('-') || title.startsWith('@')) && this._editorView && !this.dataDoc.title_custom && @@ -494,7 +494,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps DocUtils.MakeLink(this.Document, target, { link_relationship: LinkManager.AutoKeywords })!); newAutoLinks.add(alink); // DocCast(alink.link_anchor_1).followLinkLocation = 'add:right'; - const allAnchors = [{ href: Doc.localServerPath(target), title: 'a link', anchorId: this._props.Document[Id] }]; + const allAnchors = [{ href: Doc.localServerPath(target), title: 'a link', anchorId: this.Document[Id] }]; allAnchors.push(...(node.marks.find((m: Mark) => m.type.name === schema.marks.autoLinkAnchor.name)?.attrs.allAnchors ?? [])); const link = editorView.state.schema.marks.autoLinkAnchor.create({ allAnchors, title: 'auto term' }); tr = tr.addMark(pos, pos + node.nodeSize, link); @@ -572,18 +572,19 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps if (dragData) { const dataDoc = Doc.IsDelegateField(DocCast(this.layoutDoc.proto), this.fieldKey) ? DocCast(this.layoutDoc.proto) : this.dataDoc; const effectiveAcl = GetEffectiveAcl(dataDoc); - const draggedDoc = dragData.draggedDocuments.lastElement(); + const draggedDoc = dragData.droppedDocuments.lastElement(); let added: Opt<boolean>; + const dropAction = dragData.dropAction || dragData.userDropAction; if ([AclEdit, AclAdmin, AclSelfEdit].includes(effectiveAcl)) { // replace text contents when dragging with Alt if (de.altKey) { const fieldKey = Doc.LayoutFieldKey(draggedDoc); - if (draggedDoc[fieldKey] instanceof RichTextField && !Doc.AreProtosEqual(draggedDoc, this._props.Document)) { + if (draggedDoc[fieldKey] instanceof RichTextField && !Doc.AreProtosEqual(draggedDoc, this.Document)) { Doc.GetProto(this.dataDoc)[this.fieldKey] = Field.Copy(draggedDoc[fieldKey]); } // embed document when drag marked as embed - } else if (de.embedKey) { + } else if (de.embedKey || dropAction) { const node = schema.nodes.dashDoc.create({ width: NumCast(draggedDoc._width), height: NumCast(draggedDoc._height), @@ -591,20 +592,25 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps docId: draggedDoc[Id], float: 'unset', }); - if (!['embed', 'copy'].includes((dragData.dropAction ?? '') as any)) { + if (!['embed', 'copy'].includes((dropAction ?? '') as any)) { added = dragData.removeDocument?.(draggedDoc) ? true : false; + } else { + added = true; } if (added) { draggedDoc._freeform_fitContentsToBox = true; Doc.SetContainer(draggedDoc, this.Document); const view = this._editorView!; try { + this._inDrop = true; const pos = view.posAtCoords({ left: de.x, top: de.y })?.pos; pos && view.dispatch(view.state.tr.insert(pos, node)); added = pos ? true : false; // pos will be null if you don't drop onto an actual text location } catch (e) { console.log('Drop failed', e); added = false; + } finally { + this._inDrop = false; } } } @@ -991,7 +997,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps }; const link = DocUtils.MakeLinkToActiveAudio(textanchorFunc, false).lastElement(); if (link) { - Doc.GetProto(link).isDictation = true; + link[DocData].isDictation = true; const audioanchor = Cast(link.link_anchor_2, Doc, null); const textanchor = Cast(link.link_anchor_1, Doc, null); if (audioanchor) { @@ -1001,7 +1007,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps audioId: audioanchor[Id], textId: textanchor[Id], }); - Doc.GetProto(textanchor).title = 'dictation:' + audiotag.attrs.timeCode; + textanchor[DocData].title = 'dictation:' + audiotag.attrs.timeCode; const tr = this._editorView.state.tr.insert(this._editorView.state.doc.content.size, audiotag); const tr2 = tr.setSelection(TextSelection.create(tr.doc, tr.doc.content.size)); this._editorView.dispatch(tr.setSelection(TextSelection.create(tr2.doc, tr2.doc.content.size))); @@ -1056,7 +1062,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps return anchorDoc ?? this.Document; } - getView = async (doc: Doc, options: DocFocusOptions) => { + getView = async (doc: Doc, options: FocusViewOptions) => { if (DocListCast(this.dataDoc[this.SidebarKey]).find(anno => Doc.AreProtosEqual(doc.layout_unrendered ? DocCast(doc.annotationOn) : doc, anno))) { if (!this.SidebarShown) { this.toggleSidebar(false); @@ -1066,7 +1072,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps } return new Promise<Opt<DocumentView>>(res => DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv))); }; - focus = (textAnchor: Doc, options: DocFocusOptions) => { + focus = (textAnchor: Doc, options: FocusViewOptions) => { const focusSpeed = options.zoomTime ?? 500; const textAnchorId = textAnchor[Id]; const findAnchorFrag = (frag: Fragment, editor: EditorView) => { @@ -1141,7 +1147,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps return Doc.NativeAspect(this.Document, this.dataDoc, false) ? this._props.NativeDimScaling?.() || 1 : 1; } componentDidMount() { - !this._props.dontSelectOnLoad && this._props.setContentView?.(this); // this tells the DocumentView that this AudioBox is the "content" of the document. this allows the DocumentView to indirectly call getAnchor() on the AudioBox when making a link. + !this._props.dontSelectOnLoad && this._props.setContentViewBox?.(this); // this tells the DocumentView that this AudioBox is the "content" of the document. this allows the DocumentView to indirectly call getAnchor() on the AudioBox when making a link. this._cachedLinks = LinkManager.Links(this.Document); this._disposers.breakupDictation = reaction(() => Doc.RecordingEvent, this.breakupDictation); this._disposers.layout_autoHeight = reaction( @@ -1410,7 +1416,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps (this._editorView as any).TextView = this; } - const selectOnLoad = Doc.AreProtosEqual(this._props.TemplateDataDocument ?? this.Document, FormattedTextBox.SelectOnLoad) && (!LightboxView.LightboxDoc || LightboxView.IsLightboxDocView(this._props.docViewPath())); + const selectOnLoad = Doc.AreProtosEqual(this._props.TemplateDataDocument ?? this.Document, FormattedTextBox.SelectOnLoad) && (!LightboxView.LightboxDoc || LightboxView.Contains(this.DocumentView?.())); if (this._editorView && selectOnLoad && !this._props.dontRegisterView && !this._props.dontSelectOnLoad && this.isActiveTab(this.ProseRef)) { const selLoadChar = FormattedTextBox.SelectOnLoadChar; FormattedTextBox.SelectOnLoad = undefined; @@ -1531,7 +1537,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps } if (!state || !editor || !this.ProseRef?.children[0].className.includes('-focused')) return; if (!state.selection.empty && !(state.selection instanceof NodeSelection)) this.setupAnchorMenu(); - else if (this._props.isContentActive(true)) { + else if (this._props.isContentActive()) { const pcords = editor.posAtCoords({ left: e.clientX, top: e.clientY }); let xpos = pcords?.pos || 0; while (xpos > 0 && !state.doc.resolve(xpos).node()?.isTextblock) { @@ -1764,7 +1770,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps return toNum(height) + Math.max(0, toNum(marginTop)) + Math.max(0, toNum(marginBottom)); }; const proseHeight = !this.ProseRef ? 0 : children.reduce((p, child) => p + toHgt(child), margins); - const scrollHeight = this.ProseRef && Math.min(NumCast(this.layoutDoc.layout_maxAutoHeight, proseHeight), proseHeight); + const scrollHeight = this.ProseRef && proseHeight; if (this._props.setHeight && scrollHeight && !this._props.dontRegisterView) { // if top === 0, then the text box is growing upward (as the overlay caption) which doesn't contribute to the height computation const setScrollHeight = () => (this.dataDoc[this.fieldKey + '_scrollHeight'] = scrollHeight); @@ -1777,7 +1783,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps } } }; - fitContentsToBox = () => BoolCast(this._props.Document._freeform_fitContentsToBox); + fitContentsToBox = () => BoolCast(this.Document._freeform_fitContentsToBox); sidebarContentScaling = () => (this._props.NativeDimScaling?.() || 1) * NumCast(this.layoutDoc._freeform_scale, 1); sidebarAddDocument = (doc: Doc | Doc[], sidebarKey: string = this.SidebarKey) => { if (!this.layoutDoc._layout_showSidebar) this.toggleSidebar(); @@ -1852,7 +1858,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps setHeight={this.setSidebarHeight} /> ) : ( - <div onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => SelectionManager.SelectView(this._props.DocumentView?.()!, false), true)}> + <div onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => SelectionManager.SelectView(this.DocumentView?.()!, false), true)}> <ComponentTag {...this._props} ref={this._sidebarTagRef as any} @@ -2011,7 +2017,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps cursor: this._props.isContentActive() ? 'text' : undefined, height: this._props.height ? 'max-content' : undefined, overflow: this.layout_autoHeight ? 'hidden' : undefined, - pointerEvents: Doc.ActiveTool === InkTool.None && !this._props.onBrowseClick?.() ? undefined : 'none', + pointerEvents: Doc.ActiveTool === InkTool.None && !this._props.onBrowseClickScript?.() ? undefined : 'none', }} onContextMenu={this.specificContextMenu} onKeyDown={this.onKeyDown} |