diff options
author | mehekj <mehek.jethani@gmail.com> | 2022-10-12 13:21:07 -0400 |
---|---|---|
committer | mehekj <mehek.jethani@gmail.com> | 2022-10-12 13:21:07 -0400 |
commit | 0b3a83acd4f75b7f6ff4b9bb7daf4377dede51a1 (patch) | |
tree | 438789f7e7f50e5eb9829e1f301b4d043d8d4906 /src/client/views/nodes/DocumentView.tsx | |
parent | 69ca9baca6ff1da272a5191187542351bd242ccc (diff) | |
parent | eb5f75785fd28acb50f1b30434e89223fff00185 (diff) |
Merge branch 'master' into schema-mehek
Diffstat (limited to 'src/client/views/nodes/DocumentView.tsx')
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 132 |
1 files changed, 69 insertions, 63 deletions
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 74143a731..145d8bf3d 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1,8 +1,9 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { Tooltip } from '@material-ui/core'; import { action, computed, IReactionDisposer, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; -import { AclAdmin, AclEdit, AclPrivate, DataSym, Doc, DocListCast, Field, HeightSym, Opt, StrListCast, WidthSym } from '../../../fields/Doc'; +import { AclAdmin, AclEdit, AclPrivate, DataSym, Doc, DocListCast, Field, Opt, StrListCast, WidthSym } from '../../../fields/Doc'; import { Document } from '../../../fields/documentSchemas'; import { Id } from '../../../fields/FieldSymbols'; import { InkTool } from '../../../fields/InkField'; @@ -10,7 +11,7 @@ import { List } from '../../../fields/List'; import { ObjectField } from '../../../fields/ObjectField'; import { listSpec } from '../../../fields/Schema'; import { ScriptField } from '../../../fields/ScriptField'; -import { BoolCast, Cast, DocCast, ImageCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; +import { BoolCast, Cast, ImageCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; import { AudioField } from '../../../fields/URLField'; import { GetEffectiveAcl, SharingPermissions, TraceMobx } from '../../../fields/util'; import { MobileInterface } from '../../../mobile/MobileInterface'; @@ -20,6 +21,7 @@ import { DocServer } from '../../DocServer'; import { Docs, DocUtils } from '../../documents/Documents'; import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; import { Networking } from '../../Network'; +import { DictationManager } from '../../util/DictationManager'; import { DocumentManager } from '../../util/DocumentManager'; import { DragManager, dropActionType } from '../../util/DragManager'; import { InteractionUtils } from '../../util/InteractionUtils'; @@ -37,7 +39,6 @@ import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; import { DocComponent } from '../DocComponent'; import { EditableView } from '../EditableView'; -import { InkingStroke } from '../InkingStroke'; import { LightboxView } from '../LightboxView'; import { StyleProp } from '../StyleProvider'; import { CollectionFreeFormDocumentView } from './CollectionFreeFormDocumentView'; @@ -52,8 +53,6 @@ import { RadialMenu } from './RadialMenu'; import { ScriptingBox } from './ScriptingBox'; import { PresBox } from './trails/PresBox'; import React = require('react'); -import { DictationManager } from '../../util/DictationManager'; -import { Tooltip } from '@material-ui/core'; const { Howl } = require('howler'); interface Window { @@ -81,12 +80,13 @@ export interface DocFocusOptions { instant?: boolean; // whether focus should happen instantly (as opposed to smooth zoom) } export type DocAfterFocusFunc = (notFocused: boolean) => Promise<ViewAdjustment>; -export type DocFocusFunc = (doc: Doc, options?: DocFocusOptions) => void; +export type DocFocusFunc = (doc: Doc, options: DocFocusOptions) => void; export type StyleProviderFunc = (doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string) => any; export interface DocComponentView { updateIcon?: () => void; // updates the icon representation of the document getAnchor?: () => Doc; // returns an Anchor Doc that represents the current state of the doc's componentview (e.g., the current playhead location of a an audio/video box) scrollFocus?: (doc: Doc, smooth: boolean) => Opt<number>; // returns the duration of the focus + brushView?: (view: { width: number; height: number; panX: number; panY: number }) => void; setViewSpec?: (anchor: Doc, preview: boolean) => void; // sets viewing information for a componentview, typically when following a link. 'preview' tells the view to use the values without writing to the document reverseNativeScaling?: () => boolean; // DocumentView's setup screenToLocal based on the doc having a nativeWidth/Height. However, some content views (e.g., FreeFormView w/ fitContentsToBox set) may ignore the native dimensions so this flags the DocumentView to not do Nativre scaling. shrinkWrap?: () => void; // requests a document to display all of its contents with no white space. currently only implemented (needed?) for freeform views @@ -498,8 +498,8 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps .ScreenToLocalTransform() .scale(this.NativeDimScaling) .transformDirection(x - left, y - top); - dragData.offset[0] = Math.min(this.rootDoc[WidthSym](), dragData.offset[0]); - dragData.offset[1] = Math.min(this.rootDoc[HeightSym](), dragData.offset[1]); + // dragData.offset[0] = Math.min(this.rootDoc[WidthSym](), dragData.offset[0]); // bcz: this was breaking dragging rotated objects since the offset may be out of bounds with regard to the unrotated document + // dragData.offset[1] = Math.min(this.rootDoc[HeightSym](), dragData.offset[1]); dragData.dropAction = dropAction; dragData.treeViewDoc = this.props.treeViewDoc; dragData.removeDocument = this.props.removeDocument; @@ -534,7 +534,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps } }; - focus = (anchor: Doc, options?: DocFocusOptions) => { + focus = (anchor: Doc, options: DocFocusOptions) => { LightboxView.SetCookie(StrCast(anchor['cookies-set'])); // copying over VIEW fields immediately allows the view type to switch to create the right _componentView Array.from(Object.keys(Doc.GetProto(anchor))) @@ -582,7 +582,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps console.log ); UndoManager.RunInBatch(() => (func().result?.select === true ? this.props.select(false) : ''), 'on double click'); - } else if (!Doc.IsSystem(this.rootDoc)) { + } else if (!Doc.IsSystem(this.rootDoc) && !this.rootDoc.isLinkButton) { UndoManager.RunInBatch(() => LightboxView.AddDocTab(this.rootDoc, 'lightbox', this.props.LayoutTemplate?.(), this.props.addDocTab), 'double tap'); SelectionManager.DeselectAll(); Doc.UnBrushDoc(this.props.Document); @@ -881,9 +881,9 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps const existingOnClick = cm.findByDescription('OnClick...'); const onClicks: ContextMenuProps[] = existingOnClick && 'subitems' in existingOnClick ? existingOnClick.subitems : []; - const zorders = cm.findByDescription('ZOrder...'); - const zorderItems: ContextMenuProps[] = zorders && 'subitems' in zorders ? zorders.subitems : []; if (this.props.bringToFront !== emptyFunction) { + const zorders = cm.findByDescription('ZOrder...'); + const zorderItems: ContextMenuProps[] = zorders && 'subitems' in zorders ? zorders.subitems : []; zorderItems.push({ description: 'Bring to Front', event: () => SelectionManager.Views().forEach(dv => dv.props.bringToFront(dv.rootDoc, false)), icon: 'expand-arrows-alt' }); zorderItems.push({ description: 'Send to Back', event: () => SelectionManager.Views().forEach(dv => dv.props.bringToFront(dv.rootDoc, true)), icon: 'expand-arrows-alt' }); zorderItems.push({ @@ -891,8 +891,8 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps event: undoBatch(action(() => (this.rootDoc._raiseWhenDragged = this.rootDoc._raiseWhenDragged === undefined ? false : undefined))), icon: 'expand-arrows-alt', }); + !zorders && cm.addItem({ description: 'ZOrder...', noexpand: true, subitems: zorderItems, icon: 'compass' }); } - !zorders && cm.addItem({ description: 'ZOrder...', noexpand: true, subitems: zorderItems, icon: 'compass' }); !Doc.noviceMode && onClicks.push({ description: 'Enter Portal', event: this.makeIntoPortal, icon: 'window-restore' }); !Doc.noviceMode && onClicks.push({ description: 'Toggle Detail', event: this.setToggleDetail, icon: 'concierge-bell' }); @@ -1001,7 +1001,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps LightboxView.LightboxDoc !== this.rootDoc && this.thumb && !Doc.AreProtosEqual(DocumentLinksButton.StartLink, this.rootDoc) && - !Doc.isBrushedHighlightedDegree(this.props.Document) && + (!Doc.isBrushedHighlightedDegree(this.props.Document) || this.rootDoc._viewType === CollectionViewType.Docking) && !this._componentView?.isAnyChildContentActive?.() ? true : false; @@ -1259,46 +1259,47 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps SharingManager.Instance.users.find(users => users.user.email === this.dataDoc.author)?.sharingDoc.userColor, Doc.UserDoc().showTitle && [DocumentType.RTF, DocumentType.COL].includes(this.rootDoc.type as any) ? StrCast(Doc.SharingDoc().userColor) : 'rgba(0,0,0,0.4)' ); - const titleView = !showTitle ? null : ( - <div - className={`documentView-titleWrapper${showTitleHover ? '-hover' : ''}`} - key="title" - style={{ - position: this.headerMargin ? 'relative' : 'absolute', - height: this.titleHeight, - width: !this.headerMargin ? `calc(100% - 18px)` : '100%', // leave room for annotation button - color: lightOrDark(background), - background, - pointerEvents: this.onClickHandler || this.Document.ignoreClick ? 'none' : this.isContentActive() || this.props.isDocumentActive?.() ? 'all' : undefined, - }}> - <EditableView - ref={this._titleRef} - contents={showTitle - .split(';') - .map(field => field.trim()) - .map(field => targetDoc[field]?.toString()) - .join('\\')} - display={'block'} - fontSize={10} - GetValue={() => (showTitle.split(';').length === 1 ? showTitle + '=' + Field.toString(targetDoc[showTitle.split(';')[0]] as any as Field) : '#' + showTitle)} - SetValue={undoBatch((input: string) => { - if (input?.startsWith('#')) { - if (this.props.showTitle) { - this.rootDoc._showTitle = input?.substring(1) ? input.substring(1) : undefined; + const titleView = + !showTitle || Doc.noviceMode ? null : ( + <div + className={`documentView-titleWrapper${showTitleHover ? '-hover' : ''}`} + key="title" + style={{ + position: this.headerMargin ? 'relative' : 'absolute', + height: this.titleHeight, + width: !this.headerMargin ? `calc(100% - 18px)` : '100%', // leave room for annotation button + color: lightOrDark(background), + background, + pointerEvents: this.onClickHandler || this.Document.ignoreClick ? 'none' : this.isContentActive() || this.props.isDocumentActive?.() ? 'all' : undefined, + }}> + <EditableView + ref={this._titleRef} + contents={showTitle + .split(';') + .map(field => field.trim()) + .map(field => targetDoc[field]?.toString()) + .join('\\')} + display={'block'} + fontSize={10} + GetValue={() => (showTitle.split(';').length === 1 ? showTitle + '=' + Field.toString(targetDoc[showTitle.split(';')[0]] as any as Field) : '#' + showTitle)} + SetValue={undoBatch((input: string) => { + if (input?.startsWith('#')) { + if (this.props.showTitle) { + this.rootDoc._showTitle = input?.substring(1) ? input.substring(1) : undefined; + } else { + Doc.UserDoc().showTitle = input?.substring(1) ? input.substring(1) : 'creationDate'; + } } else { - Doc.UserDoc().showTitle = input?.substring(1) ? input.substring(1) : 'creationDate'; + var value = input.replace(new RegExp(showTitle + '='), '') as string | number; + if (showTitle !== 'title' && Number(value).toString() === value) value = Number(value); + if (showTitle.includes('Date') || showTitle === 'author') return true; + Doc.SetInPlace(targetDoc, showTitle, value, true); } - } else { - var value = input.replace(new RegExp(showTitle + '='), '') as string | number; - if (showTitle !== 'title' && Number(value).toString() === value) value = Number(value); - if (showTitle.includes('Date') || showTitle === 'author') return true; - Doc.SetInPlace(targetDoc, showTitle, value, true); - } - return true; - })} - /> - </div> - ); + return true; + })} + /> + </div> + ); return this.props.hideTitle || (!showTitle && !showCaption) ? ( this.contents ) : ( @@ -1322,7 +1323,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps @observable _isHovering = false; @observable _: string = ''; _hoverTimeout: any = undefined; - @computed get renderDoc() { + renderDoc = (style: object) => { TraceMobx(); const thumb = ImageCast(this.layoutDoc['thumb-frozen'], ImageCast(this.layoutDoc.thumb))?.url?.href.replace('.png', '_m.png'); const isButton = this.props.Document.type === DocumentType.FONTICON; @@ -1344,8 +1345,10 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps ); })} style={{ + ...style, background: isButton || thumb ? undefined : this.backgroundColor, opacity: this.opacity, + cursor: Doc.ActiveTool === InkTool.None ? 'grab' : 'crosshair', color: StrCast(this.layoutDoc.color, 'inherit'), fontFamily: StrCast(this.Document._fontFamily, 'inherit'), fontSize: Cast(this.Document._fontSize, 'string', null), @@ -1358,7 +1361,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps </div> ) ); - } + }; render() { TraceMobx(); const highlightIndex = this.props.LayoutTemplateString ? (Doc.IsHighlighted(this.props.Document) ? 6 : Doc.DocBrushStatus.unbrushed) : Doc.isBrushedHighlightedDegree(this.props.Document); // bcz: Argh!! need to identify a tree view doc better than a LayoutTemlatString @@ -1369,13 +1372,20 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps highlighting = highlighting && this.props.focus !== emptyFunction && this.layoutDoc.title !== '[pres element template]'; // bcz: hack to turn off highlighting onsidebar panel documents. need to flag a document as not highlightable in a more direct way const borderPath = this.props.styleProvider?.(this.props.Document, this.props, StyleProp.BorderPath) || { path: undefined }; - const internal = PresBox.EffectsProvider(this.layoutDoc, this.renderDoc) || this.renderDoc; const boxShadow = this.props.treeViewDoc ? null : highlighting && this.borderRounding && highlightStyle !== 'dashed' ? `0 0 0 ${highlightIndex}px ${highlightColor}` : this.boxShadow || (this.props.Document.isTemplateForField ? 'black 0.2vw 0.2vw 0.8vw' : undefined); + const renderDoc = this.renderDoc({ + borderRadius: this.borderRounding, + outline: highlighting && !this.borderRounding ? `${highlightColor} ${highlightStyle} ${highlightIndex}px` : 'solid 0px', + border: highlighting && this.borderRounding && highlightStyle === 'dashed' ? `${highlightStyle} ${highlightColor} ${highlightIndex}px` : undefined, + boxShadow, + clipPath: borderPath.path ? `path('${borderPath.path}')` : undefined, + }); + const animRenderDoc = PresBox.Instance?.isActiveItemTarget(this.layoutDoc) ? PresBox.AnimationEffect(renderDoc, PresBox.Instance.activeItem) : renderDoc; // Return surrounding highlight return ( <div @@ -1391,19 +1401,15 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps display: this.hidden ? 'inline' : undefined, borderRadius: this.borderRounding, pointerEvents: this.pointerEvents, - outline: highlighting && !this.borderRounding ? `${highlightColor} ${highlightStyle} ${highlightIndex}px` : 'solid 0px', - border: highlighting && this.borderRounding && highlightStyle === 'dashed' ? `${highlightStyle} ${highlightColor} ${highlightIndex}px` : undefined, - boxShadow, - clipPath: borderPath.path ? `path('${borderPath.path}')` : undefined, }}> {!borderPath.path ? ( - internal + animRenderDoc ) : ( <> {/* <div style={{ clipPath: `path('${borderPath.fill}')` }}> - {internal} + {animRenderDoc} </div> */} - {internal} + {animRenderDoc} <div key="border2" className="documentView-customBorder" style={{ pointerEvents: 'none' }}> <svg style={{ overflow: 'visible' }} viewBox={`0 0 ${this.props.PanelWidth()} ${this.props.PanelHeight()}`}> <path d={borderPath.path} style={{ stroke: 'black', fill: 'transparent', strokeWidth: borderPath.width }} /> @@ -1552,7 +1558,7 @@ export class DocumentView extends React.Component<DocumentViewProps> { } toggleNativeDimensions = () => this.docView && Doc.toggleNativeDimensions(this.layoutDoc, this.docView.NativeDimScaling, this.props.PanelWidth(), this.props.PanelHeight()); - focus = (doc: Doc, options?: DocFocusOptions) => this.docView?.focus(doc, options); + focus = (doc: Doc, options: DocFocusOptions) => this.docView?.focus(doc, options); getBounds = () => { if (!this.docView || !this.docView.ContentDiv || this.props.Document.presBox || this.docView.props.treeViewDoc || Doc.AreProtosEqual(this.props.Document, Doc.UserDoc())) { return undefined; |