From 0df1fc3fd85c1dea84dcaec5a934fc08f0da6832 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 4 Oct 2023 07:46:05 -0400 Subject: several fixes for webclips, linking to pdf/web, fonticon dropdowns. removed sliderbox. reduce uses of scriptContext fixed web clipping annotations to be in correct spot and not to crash because of using a url that it doesn't have. fixed pdf/web links to not use anchor from other end of link. because of sharing of GetAnchor global. added a backup when presbox overwrites a doc's data field. removed sliderBox. fixed fontIcon dropdowns to not call click script twice. removed scriptContext where it wasn't needed which is everywhere except TreeViews. --- src/client/documents/DocumentTypes.ts | 3 +- src/client/documents/Documents.ts | 8 -- src/client/util/CurrentUserUtils.ts | 2 +- src/client/views/MainView.tsx | 2 - src/client/views/StyleProvider.tsx | 2 - .../views/collections/CollectionNoteTakingView.tsx | 1 - .../collections/CollectionStackedTimeline.tsx | 37 +++----- .../views/collections/CollectionStackingView.tsx | 1 - .../collectionSchema/CollectionSchemaView.tsx | 1 - src/client/views/nodes/DocumentContentsView.tsx | 2 - src/client/views/nodes/FontIconBox/FontIconBox.tsx | 1 - src/client/views/nodes/PDFBox.tsx | 2 +- src/client/views/nodes/SliderBox.scss | 19 ---- src/client/views/nodes/SliderBox.tsx | 103 --------------------- src/client/views/nodes/WebBox.scss | 1 - src/client/views/nodes/WebBox.tsx | 80 +++++++++++----- src/client/views/nodes/trails/PresBox.tsx | 7 +- src/client/views/pdf/PDFViewer.tsx | 5 +- 18 files changed, 82 insertions(+), 195 deletions(-) delete mode 100644 src/client/views/nodes/SliderBox.scss delete mode 100644 src/client/views/nodes/SliderBox.tsx (limited to 'src') diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts index f8d129e79..87010f770 100644 --- a/src/client/documents/DocumentTypes.ts +++ b/src/client/documents/DocumentTypes.ts @@ -30,14 +30,13 @@ export enum DocumentType { // special purpose wrappers that either take no data or are compositions of lower level types LINK = 'link', IMPORT = 'import', - SLIDER = 'slider', PRES = 'presentation', PRESELEMENT = 'preselement', COLOR = 'color', YOUTUBE = 'youtube', COMPARISON = 'comparison', GROUP = 'group', - PUSHPIN = "pushpin", + PUSHPIN = 'pushpin', SCRIPTDB = 'scriptdb', // database of scripts GROUPDB = 'groupdb', // database of groups diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index f7ceef4f4..a79a62b57 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -54,7 +54,6 @@ import { PhysicsSimulationBox } from '../views/nodes/PhysicsBox/PhysicsSimulatio import { RecordingBox } from '../views/nodes/RecordingBox/RecordingBox'; import { ScreenshotBox } from '../views/nodes/ScreenshotBox'; import { ScriptingBox } from '../views/nodes/ScriptingBox'; -import { SliderBox } from '../views/nodes/SliderBox'; import { TaskCompletionBox } from '../views/nodes/TaskCompletedBox'; import { PresBox } from '../views/nodes/trails/PresBox'; import { PresElementBox } from '../views/nodes/trails/PresElementBox'; @@ -628,13 +627,6 @@ export namespace Docs { options: {}, }, ], - [ - DocumentType.SLIDER, - { - layout: { view: SliderBox, dataField: defaultDataKey }, - options: {}, - }, - ], [ DocumentType.PRES, { diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 2ea5972ee..cc8f72ddf 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -820,7 +820,7 @@ export class CurrentUserUtils { // When the user views one of these documents, it will be added to the sharing documents 'viewed' list field // The sharing document also stores the user's color value which helps distinguish shared documents from personal documents static setupSharedDocs(doc: Doc, sharingDocumentId: string) { - const dblClkScript = "{scriptContext.openLevel(documentView); addDocToList(scriptContext.props.treeView.props.Document, 'viewed', documentView.rootDoc);}"; + const dblClkScript = "{scriptContext.openLevel(documentView); addDocToList(documentView.props.treeViewDoc, 'viewed', documentView.rootDoc);}"; const sharedScripts = { treeView_ChildDoubleClick: dblClkScript, } const sharedDocOpts:DocumentOptions = { diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index d6f5d63fe..0a3389fc2 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -728,7 +728,6 @@ export class MainView extends React.Component { PanelHeight={this.leftMenuFlyoutHeight} renderDepth={0} isContentActive={returnTrue} - scriptContext={CollectionDockingView.Instance?.props.Document} focus={emptyFunction} whenChildContentsActiveChanged={emptyFunction} bringToFront={emptyFunction} @@ -766,7 +765,6 @@ export class MainView extends React.Component { childFilters={returnEmptyFilter} childFiltersByRanges={returnEmptyFilter} searchFilterDocs={returnEmptyDoclist} - scriptContext={this} /> ); diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index d7537bffb..8417a6f5b 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -21,7 +21,6 @@ import { InkingStroke } from './InkingStroke'; import { DocumentView, DocumentViewProps } from './nodes/DocumentView'; import { FieldViewProps } from './nodes/FieldView'; import { KeyValueBox } from './nodes/KeyValueBox'; -import { SliderBox } from './nodes/SliderBox'; import './StyleProvider.scss'; import React = require('react'); import { PropertiesView } from './PropertiesView'; @@ -215,7 +214,6 @@ export function DefaultStyleProvider(doc: Opt, props: Opt ); diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index ad3160a08..c4650647c 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -58,9 +58,7 @@ export class CollectionStackedTimeline extends CollectionSubView CollectionStackedTimeline.RangeScript; - rangePlayScript = () => CollectionStackedTimeline.RangePlayScript; + @computed get rangeClick() { + // prettier-ignore + return ScriptField.MakeFunction('stackedTimeline.clickAnchor(this, clientX)', + { stackedTimeline: 'any', clientX: 'number' }, { stackedTimeline: this as any } + )!; + } + @computed get rangePlay() { + // prettier-ignore + return ScriptField.MakeFunction('stackedTimeline.playOnClick(this, clientX)', + { stackedTimeline: 'any', clientX: 'number' }, { stackedTimeline: this as any })!; + } + rangeClickScript = () => this.rangeClick; + rangePlayScript = () => this.rangePlay; // handles key events for for creating key anchors, scrubbing, exiting trim @action @@ -835,7 +825,6 @@ class StackedTimelineAnchor extends React.Component hideResizeHandles={true} bringToFront={emptyFunction} contextMenuItems={this.contextMenuItems} - scriptContext={this.props.stackedTimeline} /> ), }; diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 36f8bc101..c43a9d2b8 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -361,7 +361,6 @@ export class CollectionStackingView extends CollectionSubView ); diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index d2b61167e..f73c037f4 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -972,7 +972,6 @@ class CollectionSchemaViewDocs extends React.Component ); diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 8ac9d6804..e1de2fa76 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -41,7 +41,6 @@ import { PhysicsSimulationBox } from './PhysicsBox/PhysicsSimulationBox'; import { RecordingBox } from './RecordingBox'; import { ScreenshotBox } from './ScreenshotBox'; import { ScriptingBox } from './ScriptingBox'; -import { SliderBox } from './SliderBox'; import { PresBox } from './trails/PresBox'; import { VideoBox } from './VideoBox'; import { WebBox } from './WebBox'; @@ -240,7 +239,6 @@ export class DocumentContentsView extends React.Component< FontIconBox, LabelBox, EquationBox, - SliderBox, FieldView, CollectionFreeFormView, CollectionDockingView, diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx index 14a3d16ef..d2e1293da 100644 --- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx @@ -240,7 +240,6 @@ export class FontIconBox extends DocComponent() { text: typeof value === 'string' ? value.charAt(0).toUpperCase() + value.slice(1) : StrCast(DocCast(value)?.title), val: value, style: getStyle(value), - onClick: undoable(() => script.script.run({ this: this.layoutDoc, self: this.rootDoc, value }), value), // shortcut: '#', })); diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 73a5be90a..cf44649a2 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -242,7 +242,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent() { - public static LayoutString(fieldKey: string) { - return FieldView.LayoutString(SliderBox, fieldKey); - } - - get minThumbKey() { - return this.fieldKey + '-minThumb'; - } - get maxThumbKey() { - return this.fieldKey + '-maxThumb'; - } - get minKey() { - return this.fieldKey + '-min'; - } - get maxKey() { - return this.fieldKey + '-max'; - } - specificContextMenu = (e: React.MouseEvent): void => { - const funcs: ContextMenuProps[] = []; - funcs.push({ description: 'Edit Thumb Change Script', icon: 'edit', event: (obj: any) => ScriptBox.EditButtonScript('On Thumb Change ...', this.props.Document, 'onThumbChange', obj.x, obj.y) }); - ContextMenu.Instance.addItem({ description: 'Options...', subitems: funcs, icon: 'asterisk' }); - }; - onChange = (values: readonly number[]) => - runInAction(() => { - this.dataDoc[this.minThumbKey] = values[0]; - this.dataDoc[this.maxThumbKey] = values[1]; - ScriptCast(this.layoutDoc.onThumbChanged, null)?.script.run({ - self: this.rootDoc, - scriptContext: this.props.scriptContext, - range: values, - this: this.layoutDoc, - }); - }); - - render() { - const domain = [NumCast(this.layoutDoc[this.minKey]), NumCast(this.layoutDoc[this.maxKey])]; - const defaultValues = [NumCast(this.dataDoc[this.minThumbKey]), NumCast(this.dataDoc[this.maxThumbKey])]; - return domain[1] <= domain[0] ? null : ( -
e.stopPropagation()} style={{ boxShadow: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BoxShadow) }}> -
- - {railProps => } - - {({ handles, activeHandleID, getHandleProps }) => ( -
- {handles.map((handle, i) => { - const value = i === 0 ? defaultValues[0] : defaultValues[1]; - return ( -
- -
- ); - })} -
- )} -
- - {({ tracks, getTrackProps }) => ( -
- {tracks.map(({ id, source, target }) => ( - - ))} -
- )} -
- - {({ ticks }) => ( -
- {ticks.map(tick => ( - val.toString()} /> - ))} -
- )} -
-
-
-
- ); - } -} diff --git a/src/client/views/nodes/WebBox.scss b/src/client/views/nodes/WebBox.scss index 75847c100..511c91da0 100644 --- a/src/client/views/nodes/WebBox.scss +++ b/src/client/views/nodes/WebBox.scss @@ -176,7 +176,6 @@ width: 100%; height: 100%; transform-origin: top left; - overflow: auto; .webBox-iframe { width: 100%; diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 27c19105f..d4ba7a48f 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -62,10 +62,8 @@ export class WebBox extends ViewBoxAnnotatableComponent(); private _searchString = ''; private _scrollTimer: any; + private _getAnchor: (savedAnnotations: Opt>, addAsAnnotation: boolean) => Opt = () => undefined; - private get _getAnchor() { - return AnchorMenu.Instance?.GetAnchor; - } @observable private _webUrl = ''; // url of the src parameter of the embedded iframe but not necessarily the rendered page - eg, when following a link, the rendered page changes but we don't want the src parameter to also change as that would cause an unnecessary re-render. @observable private _hackHide = false; // apparently changing the value of the 'sandbox' prop doesn't necessarily apply it to the active iframe. so thisforces the ifrmae to be rebuilt when allowScripts is toggled @observable private _searching: boolean = false; @@ -186,13 +184,15 @@ export class WebBox extends ViewBoxAnnotatableComponent { - this._annotationKeySuffix = () => this._urlHash + '_annotations'; - const reqdFuncs: { [key: string]: string } = {}; + this._annotationKeySuffix = () => (this._urlHash ? this._urlHash + '_' : '') + 'annotations'; // bcz: need to make sure that doc.data_annotations points to the currently active web page's annotations (this could/should be when the doc is created) - reqdFuncs[this.fieldKey + '_annotations'] = `copyField(this["${this.fieldKey}_"+urlHash(this["${this.fieldKey}"]?.url?.toString())+"_annotations"])`; - reqdFuncs[this.fieldKey + '_annotations-setter'] = `this["${this.fieldKey}_"+urlHash(this["${this.fieldKey}"]?.url?.toString())+"_annotations"] = value`; - reqdFuncs[this.fieldKey + '_sidebar'] = `copyField(this["${this.fieldKey}_"+urlHash(this["${this.fieldKey}"]?.url?.toString())+"_sidebar"])`; - DocUtils.AssignScripts(this.dataDoc, {}, reqdFuncs); + if (this._url) { + const reqdFuncs: { [key: string]: string } = {}; + reqdFuncs[this.fieldKey + '_annotations'] = `copyField(this["${this.fieldKey}_"+urlHash(this["${this.fieldKey}"]?.url?.toString())+"annotations"])`; + reqdFuncs[this.fieldKey + '_annotations-setter'] = `this["${this.fieldKey}_"+urlHash(this["${this.fieldKey}"]?.url?.toString())+"annotations"] = value`; + reqdFuncs[this.fieldKey + '_sidebar'] = `copyField(this["${this.fieldKey}_"+urlHash(this["${this.fieldKey}"]?.url?.toString())+"sidebar"])`; + DocUtils.AssignScripts(this.dataDoc, {}, reqdFuncs); + } }); this._disposers.urlchange = reaction( () => WebCast(this.rootDoc.data), @@ -264,14 +264,16 @@ export class WebBox extends ViewBoxAnnotatableComponent this.createTextAnnotation(sel, !sel.isCollapsed ? sel.getRangeAt(0) : undefined); AnchorMenu.Instance.jumpTo(e.clientX * scale + mainContBounds.translateX, e.clientY * scale + mainContBounds.translateY - NumCast(this.layoutDoc._layout_scrollTop) * scale); // Changing which document to add the annotation to (the currently selected WebBox) - GPTPopup.Instance.setSidebarId(`${this.props.fieldKey}_${this._urlHash}_sidebar`); + GPTPopup.Instance.setSidebarId(`${this.props.fieldKey}_${this._urlHash ? this._urlHash + '_' : ''}sidebar`); GPTPopup.Instance.addDoc = this.sidebarAddDocument; } } }; @action + webClipDown = (e: React.PointerEvent) => { + const mainContBounds = Utils.GetScreenTransform(this._mainCont.current!); + const scale = (this.props.NativeDimScaling?.() || 1) * mainContBounds.scale; + const word = getWordAtPoint(e.target, e.clientX, e.clientY); + this._setPreviewCursor?.(e.clientX, e.clientY, false, true, this.rootDoc); + MarqueeAnnotator.clearAnnotations(this._savedAnnotations); + e.button !== 2 && (this._marqueeing = [e.clientX, e.clientY]); + if (word || (e.target as any)?.className?.includes('rangeslider') || (e.target as any)?.onclick || (e.target as any)?.parentNode?.onclick) { + e.stopPropagation(); + setTimeout( + action(() => (this._marqueeing = undefined)), + 100 + ); // bcz: hack .. anchor menu is setup within MarqueeAnnotator so we need to at least create the marqueeAnnotator even though we aren't using it. + } else { + this._isAnnotating = true; + this.props.select(false); + e.stopPropagation(); + e.preventDefault(); + } + document.addEventListener('pointerup', this.webClipUp); + }; + webClipUp = (e: PointerEvent) => { + document.removeEventListener('pointerup', this.webClipUp); + this._getAnchor = AnchorMenu.Instance?.GetAnchor; // need to save AnchorMenu's getAnchor since a subsequent selection on another doc will overwrite this value + const sel = window.getSelection(); + if (sel && !sel.isCollapsed) { + const selRange = sel.getRangeAt(0); + this._selectionText = sel.toString(); + AnchorMenu.Instance.setSelectedText(sel.toString()); + this._textAnnotationCreator = () => this.createTextAnnotation(sel, selRange); + AnchorMenu.Instance.jumpTo(e.clientX, e.clientY); + // Changing which document to add the annotation to (the currently selected WebBox) + GPTPopup.Instance.setSidebarId(`${this.props.fieldKey}_${this._urlHash ? this._urlHash + '_' : ''}sidebar`); + GPTPopup.Instance.addDoc = this.sidebarAddDocument; + } + }; + @action iframeDown = (e: PointerEvent) => { const mainContBounds = Utils.GetScreenTransform(this._mainCont.current!); const scale = (this.props.NativeDimScaling?.() || 1) * mainContBounds.scale; @@ -396,9 +435,7 @@ export class WebBox extends ViewBoxAnnotatableComponent { - return 'InstallTrigger' in window; // navigator.userAgent.indexOf("Chrome") !== -1; - }; + isFirefox = () => 'InstallTrigger' in window; // navigator.userAgent.indexOf("Chrome") !== -1; iframeClick = () => this._iframeClick; iframeScaling = () => 1 / this.props.ScreenToLocalTransform().Scale; @@ -722,10 +759,11 @@ export class WebBox extends ViewBoxAnnotatableComponent { + this._getAnchor = AnchorMenu.Instance?.GetAnchor; this._marqueeing = undefined; this._isAnnotating = false; this._iframeClick = undefined; - const sel = this._iframe?.contentDocument?.getSelection(); + const sel = this._url ? this._iframe?.contentDocument?.getSelection() : window.document.getSelection(); if (sel?.empty) sel.empty(); // Chrome else if (sel?.removeAllRanges) sel.removeAllRanges(); // Firefox if (x !== undefined && y !== undefined) { @@ -750,7 +788,7 @@ export class WebBox extends ViewBoxAnnotatableComponent e.stopPropagation()} dangerouslySetInnerHTML={{ __html: field.html }} />; + return r && (this._scrollHeight = Number(getComputedStyle(r).height.replace('px', '')))} contentEditable onPointerDown={this.webClipDown} dangerouslySetInnerHTML={{ __html: field.html }} />; } if (field instanceof WebField) { const url = this.layoutDoc[this.fieldKey + '_useCors'] ? Utils.CorsProxy(this._webUrl) : this._webUrl; @@ -775,7 +813,7 @@ export class WebBox extends ViewBoxAnnotatableComponent { - (doc instanceof Doc ? [doc] : doc).forEach(doc => (doc.config_data = new WebField(this._url))); + this._url && (doc instanceof Doc ? [doc] : doc).forEach(doc => (doc.config_data = new WebField(this._url))); return this.addDocument(doc, annotationKey); }; diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 2a3b232bd..383b400c8 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -465,7 +465,11 @@ export class PresBox extends ViewBoxBaseComponent() { const fkey = Doc.LayoutFieldKey(bestTarget); const setData = bestTargetView?.ComponentView?.setData; if (setData) setData(activeItem.config_data); - else Doc.GetProto(bestTarget)[fkey] = activeItem.config_data instanceof ObjectField ? activeItem.config_data[Copy]() : activeItem.config_data; + else { + const current = Doc.GetProto(bestTarget)[fkey]; + Doc.GetProto(bestTarget)[fkey + '_' + Date.now()] = current instanceof ObjectField ? current[Copy]() : current; + Doc.GetProto(bestTarget)[fkey] = activeItem.config_data instanceof ObjectField ? activeItem.config_data[Copy]() : activeItem.config_data; + } bestTarget[fkey + '_usePath'] = activeItem.config_usePath; setTimeout(() => (bestTarget._dataTransition = undefined), transTime + 10); } @@ -2650,7 +2654,6 @@ export class PresBox extends ViewBoxBaseComponent() { removeDocument={returnFalse} dontRegisterView={true} focus={this.focusElement} - scriptContext={this} ScreenToLocalTransform={this.getTransform} AddToMap={this.AddToMap} RemFromMap={this.RemFromMap} diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 2a191477b..23dc084ad 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -82,9 +82,7 @@ export class PDFViewer extends React.Component { private _ignoreScroll = false; private _initialScroll: { loc: Opt; easeFunc: 'linear' | 'ease' | undefined } | undefined; private _forcedScroll = true; - get _getAnchor() { - return AnchorMenu.Instance?.GetAnchor; - } + _getAnchor: (savedAnnotations: Opt>, addAsAnnotation: boolean) => Opt = () => undefined; selectionText = () => this._selectionText; selectionContent = () => this._selectionContent; @@ -400,6 +398,7 @@ export class PDFViewer extends React.Component { @action finishMarquee = (x?: number, y?: number) => { + this._getAnchor = AnchorMenu.Instance?.GetAnchor; this.isAnnotating = false; this._marqueeing = undefined; this._textSelecting = true; -- cgit v1.2.3-70-g09d2