diff options
author | bobzel <zzzman@gmail.com> | 2024-05-14 23:15:24 -0400 |
---|---|---|
committer | bobzel <zzzman@gmail.com> | 2024-05-14 23:15:24 -0400 |
commit | 3534aaf88a3c30a474b3b5a5b7f04adfe6f15fac (patch) | |
tree | 47fb7a8671b209bd4d76e0f755a5b035c6936607 /src/client/views/nodes/WebBox.tsx | |
parent | 87bca251d87b5a95da06b2212400ce9427152193 (diff) | |
parent | 5cb7ad90e120123ca572e8ef5b1aa6ca41581134 (diff) |
Merge branch 'restoringEslint' into sarah-ai-visualization
Diffstat (limited to 'src/client/views/nodes/WebBox.tsx')
-rw-r--r-- | src/client/views/nodes/WebBox.tsx | 235 |
1 files changed, 156 insertions, 79 deletions
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 033b01d24..8835ea5e7 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -1,22 +1,26 @@ +/* eslint-disable jsx-a11y/control-has-associated-label */ +/* eslint-disable jsx-a11y/no-static-element-interactions */ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { htmlToText } from 'html-to-text'; import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import * as WebRequest from 'web-request'; -import { Doc, DocListCast, Field, Opt } from '../../../fields/Doc'; +import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, ClientUtils, DivHeight, getWordAtPoint, lightOrDark, returnFalse, returnOne, returnZero, setupMoveUpEvents, smoothScroll } from '../../../ClientUtils'; +import { Doc, DocListCast, Field, FieldType, Opt } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; import { HtmlField } from '../../../fields/HtmlField'; import { InkTool } from '../../../fields/InkField'; import { List } from '../../../fields/List'; import { RefField } from '../../../fields/RefField'; import { listSpec } from '../../../fields/Schema'; -import { Cast, NumCast, StrCast, WebCast } from '../../../fields/Types'; +import { Cast, NumCast, StrCast, toList, WebCast } from '../../../fields/Types'; import { ImageField, WebField } from '../../../fields/URLField'; import { TraceMobx } from '../../../fields/util'; -import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, DivHeight, emptyFunction, getWordAtPoint, lightOrDark, returnFalse, returnOne, returnZero, setupMoveUpEvents, smoothScroll, stringHash, Utils } from '../../../Utils'; -import { Docs, DocUtils } from '../../documents/Documents'; -import { DocumentManager } from '../../util/DocumentManager'; +import { emptyFunction, stringHash } from '../../../Utils'; +import { Docs } from '../../documents/Documents'; +import { DocumentType } from '../../documents/DocumentTypes'; +import { DocUtils } from '../../documents/DocUtils'; import { ScriptingGlobals } from '../../util/ScriptingGlobals'; import { SnappingManager } from '../../util/SnappingManager'; import { undoBatch, UndoManager } from '../../util/UndoManager'; @@ -24,24 +28,27 @@ import { MarqueeOptionsMenu } from '../collections/collectionFreeForm'; import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; -import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent'; +import { ViewBoxAnnotatableComponent } from '../DocComponent'; import { Colors } from '../global/globalEnums'; -import { LightboxView } from '../LightboxView'; import { MarqueeAnnotator } from '../MarqueeAnnotator'; import { AnchorMenu } from '../pdf/AnchorMenu'; import { Annotation } from '../pdf/Annotation'; import { GPTPopup } from '../pdf/GPTPopup/GPTPopup'; +import { PinDocView, PinProps } from '../PinFuncs'; import { SidebarAnnos } from '../SidebarAnnos'; -import { StyleProp } from '../StyleProvider'; -import { DocumentView, OpenWhere } from './DocumentView'; -import { FieldView, FieldViewProps, FocusViewOptions } from './FieldView'; +import { StyleProp } from '../StyleProp'; +import { ViewBoxInterface } from '../ViewBoxInterface'; +import { DocumentView } from './DocumentView'; +import { FieldView, FieldViewProps } from './FieldView'; +import { FocusViewOptions } from './FocusViewOptions'; import { LinkInfo } from './LinkDocPreview'; -import { PinProps, PresBox } from './trails'; +import { OpenWhere } from './OpenWhere'; import './WebBox.scss'; + const { CreateImage } = require('./WebBoxRenderer'); -const _global = (window /* browser */ || global) /* node */ as any; + @observer -export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implements ViewBoxInterface { +export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(WebBox, fieldKey); } @@ -105,7 +112,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem } @action - search = (searchString: string, bwd?: boolean, clear: boolean = false) => { + override search = (searchString: string, bwd?: boolean, clear: boolean = false) => { if (!this._searching && !clear) { this._searching = true; setTimeout(() => { @@ -141,19 +148,19 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem const scrollTop = NumCast(this.layoutDoc._layout_scrollTop); const nativeWidth = NumCast(this.layoutDoc.nativeWidth); const nativeHeight = (nativeWidth * this._props.PanelHeight()) / this._props.PanelWidth(); - var htmlString = this._iframe.contentDocument && new XMLSerializer().serializeToString(this._iframe.contentDocument); + let htmlString = this._iframe.contentDocument && new XMLSerializer().serializeToString(this._iframe.contentDocument); if (!htmlString) { - htmlString = await (await fetch(Utils.CorsProxy(this.webField!.href))).text(); + htmlString = await (await fetch(ClientUtils.CorsProxy(this.webField!.href))).text(); } this.layoutDoc.thumb = undefined; this.Document.thumbLockout = true; // lock to prevent multiple thumb updates. CreateImage(this._webUrl.endsWith('/') ? this._webUrl.substring(0, this._webUrl.length - 1) : this._webUrl, this._iframe.contentDocument?.styleSheets ?? [], htmlString, nativeWidth, nativeHeight, scrollTop) - .then((data_url: any) => { - if (data_url.includes('<!DOCTYPE')) { + .then((dataUrl: any) => { + if (dataUrl.includes('<!DOCTYPE')) { console.log('BAD DATA IN THUMB CREATION'); return; } - Utils.convertDataUri(data_url, this.layoutDoc[Id] + '-icon' + new Date().getTime(), true, this.layoutDoc[Id] + '-icon').then(returnedfilename => + ClientUtils.convertDataUri(dataUrl, this.layoutDoc[Id] + '-icon' + new Date().getTime(), true, this.layoutDoc[Id] + '-icon').then(returnedfilename => setTimeout( action(() => { this.Document.thumbLockout = false; @@ -166,7 +173,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem ) ); }) - .catch(function (error: any) { + .catch((error: any) => { console.error('oops, something went wrong!', error); }); }; @@ -187,7 +194,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem }); this._disposers.urlchange = reaction( () => WebCast(this.dataDoc.data), - url => this.submitURL(false, false) + () => this.submitURL(false, false) ); this._disposers.titling = reaction( () => StrCast(this.Document.title), @@ -199,8 +206,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem this._disposers.layout_autoHeight = reaction( () => this.layoutDoc._layout_autoHeight, - layout_autoHeight => { - if (layout_autoHeight) { + layoutAutoHeight => { + if (layoutAutoHeight) { this.layoutDoc._nativeHeight = NumCast(this.Document[this._props.fieldKey + '_nativeHeight']); this._props.setHeight?.(NumCast(this.Document[this._props.fieldKey + '_nativeHeight']) * (this._props.NativeDimScaling?.() || 1)); } @@ -219,8 +226,10 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem } } // else it's an HTMLfield } else if (this.webField && !this.dataDoc.text) { - WebRequest.get(Utils.CorsProxy(this.webField.href)) // - .then(result => result && (this.dataDoc.text = htmlToText(result.content))); + WebRequest.get(ClientUtils.CorsProxy(this.webField.href)) // + .then(result => { + result && (this.dataDoc.text = htmlToText(result.content)); + }); } this._disposers.scrollReaction = reaction( @@ -254,7 +263,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem const clientRects = selRange.getClientRects(); for (let i = 0; i < clientRects.length; i++) { const rect = clientRects.item(i); - const mainrect = this._url ? { translateX: 0, translateY: 0, scale: 1 } : Utils.GetScreenTransform(this._mainCont.current); + const mainrect = this._url ? { translateX: 0, translateY: 0, scale: 1 } : ClientUtils.GetScreenTransform(this._mainCont.current); if (rect && rect.width !== this._mainCont.current.clientWidth) { const annoBox = document.createElement('div'); annoBox.className = 'marqueeAnnotator-annotationBox'; @@ -283,27 +292,39 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem focus = (anchor: Doc, options: FocusViewOptions) => { if (anchor !== this.Document && this._outerRef.current) { const windowHeight = this._props.PanelHeight() / (this._props.NativeDimScaling?.() || 1); - const scrollTo = Utils.scrollIntoView(NumCast(anchor.y), NumCast(anchor._height), NumCast(this.layoutDoc._layout_scrollTop), windowHeight, windowHeight * 0.1, Math.max(NumCast(anchor.y) + NumCast(anchor._height), this._scrollHeight)); + const scrollTo = ClientUtils.scrollIntoView( + NumCast(anchor.y), + NumCast(anchor._height), + NumCast(this.layoutDoc._layout_scrollTop), + windowHeight, + windowHeight * 0.1, + Math.max(NumCast(anchor.y) + NumCast(anchor._height), this._scrollHeight) + ); if (scrollTo !== undefined) { if (this._initialScroll === undefined) { const focusTime = options.zoomTime ?? 500; this.goTo(scrollTo, focusTime, options.easeFunc); return focusTime; - } else { - this._initialScroll = scrollTo; } + this._initialScroll = scrollTo; } } + return undefined; }; @action - getView = (doc: Doc, options: FocusViewOptions) => { - if (Doc.AreProtosEqual(doc, this.Document)) return new Promise<Opt<DocumentView>>(res => res(this.DocumentView?.())); + getView = (doc: Doc /* , options: FocusViewOptions */) => { + if (Doc.AreProtosEqual(doc, this.Document)) + return new Promise<Opt<DocumentView>>(res => { + res(this.DocumentView?.()); + }); if (this.Document.layout_fieldKey === 'layout_icon') this.DocumentView?.().iconify(); const webUrl = WebCast(doc.config_data)?.url; if (this._url && webUrl && webUrl.href !== this._url) this.setData(webUrl.href); if (this._sidebarRef?.current?.makeDocUnfiltered(doc) && !this.SidebarShown) this.toggleSidebar(false); - return new Promise<Opt<DocumentView>>(res => DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv))); + return new Promise<Opt<DocumentView>>(res => { + DocumentView.addViewRenderedCb(doc, dv => res(dv)); + }); }; sidebarAddDocTab = (doc: Doc, where: OpenWhere) => { @@ -314,14 +335,16 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem return this._props.addDocTab(doc, where); }; getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => { - let ele: Opt<HTMLDivElement> = undefined; + let ele: Opt<HTMLDivElement>; try { const contents = this._iframe?.contentWindow?.getSelection()?.getRangeAt(0).cloneContents(); if (contents) { ele = document.createElement('div'); ele.append(contents); } - } catch (e) {} + } catch (e) { + /* empty */ + } const visibleAnchor = this._getAnchor(this._savedAnnotations, true); const anchor = visibleAnchor ?? @@ -330,7 +353,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem y: NumCast(this.layoutDoc._layout_scrollTop), annotationOn: this.Document, }); - PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), scrollable: pinProps?.pinData ? true : false, pannable: true } }, this.Document); + PinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), scrollable: !!pinProps?.pinData, pannable: true } }, this.Document); anchor.text = ele?.textContent ?? ''; anchor.text_html = ele?.innerHTML ?? this._selectionText; addAsAnnotation && this.addDocumentWrapper(anchor); @@ -356,7 +379,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem this._textAnnotationCreator = undefined; this.DocumentView?.()?.cleanupPointerEvents(); // pointerup events aren't generated on containing document view, so we have to invoke it here. if (this._iframe?.contentWindow && this._iframe.contentDocument && !this._iframe.contentWindow.getSelection()?.isCollapsed) { - const mainContBounds = Utils.GetScreenTransform(this._mainCont.current!); + const mainContBounds = ClientUtils.GetScreenTransform(this._mainCont.current!); const scale = (this._props.NativeDimScaling?.() || 1) * mainContBounds.scale; const sel = this._iframe.contentWindow.getSelection(); if (sel) { @@ -387,7 +410,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem e?.stopPropagation(); setTimeout(() => { // if menu comes up right away, the down event can still be active causing a menu item to be selected - this.specificContextMenu(undefined as any); + this.specificContextMenu(); this.DocumentView?.().onContextMenu(undefined, theclick[0], theclick[1]); }); } @@ -462,6 +485,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem const sheets = document.head.appendChild(style); return (sheets as any).sheet; } + return undefined; } addWebStyleSheetRule(sheet: any, selector: any, css: any, selectorPrefix = '.') { const propText = @@ -476,7 +500,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem _iframetimeout: any = undefined; @observable _warning = 0; @action - iframeLoaded = (e: any) => { + iframeLoaded = () => { const iframe = this._iframe; if (this._initialScroll !== undefined) { this.setScrollPos(this._initialScroll); @@ -491,7 +515,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem runInAction(() => this._warning++); href = undefined; } - let requrlraw = decodeURIComponent(href?.replace(Utils.prepend('') + '/corsProxy/', '') ?? this._url.toString()); + let requrlraw = decodeURIComponent(href?.replace(ClientUtils.prepend('') + '/corsProxy/', '') ?? this._url.toString()); if (requrlraw !== this._url.toString()) { if (requrlraw.match(/q=.*&/)?.length && this._url.toString().match(/q=.*&/)?.length) { const matches = requrlraw.match(/[^a-zA-z]q=[^&]*/g); @@ -544,16 +568,16 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem 'click', undoBatch( action((e: MouseEvent) => { - let href = ''; + let eleHref = ''; for (let ele = e.target as any; ele; ele = ele.parentElement) { - href = (typeof ele.href === 'string' ? ele.href : ele.href?.baseVal) || ele.parentElement?.href || href; + eleHref = (typeof ele.href === 'string' ? ele.href : ele.href?.baseVal) || ele.parentElement?.href || eleHref; } const origin = this.webField?.origin; - if (href && origin) { + if (eleHref && origin) { const batch = UndoManager.StartBatch('webclick'); e.stopPropagation(); setTimeout(() => { - this.setData(href.replace(Utils.prepend(''), origin)); + this.setData(eleHref.replace(ClientUtils.prepend(''), origin)); batch.end(); }); if (this._outerRef.current) { @@ -599,7 +623,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem clearStyleSheetRules(WebBox.webStyleSheet); this._scrollTimer = undefined; const newScrollTop = scrollTop > iframeHeight ? iframeHeight : scrollTop; - if (!LinkInfo.Instance?.LinkInfo && this._outerRef.current && newScrollTop !== this.layoutDoc.thumbScrollTop && (!LightboxView.LightboxDoc || LightboxView.Contains(this.DocumentView?.()))) { + if (!LinkInfo.Instance?.LinkInfo && this._outerRef.current && newScrollTop !== this.layoutDoc.thumbScrollTop && (!DocumentView.LightboxDoc() || DocumentView.LightboxContains(this.DocumentView?.()))) { this.layoutDoc.thumb = undefined; this.layoutDoc.thumbScrollTop = undefined; this.layoutDoc.thumbNativeWidth = undefined; @@ -632,12 +656,17 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem this._scrollHeight = 0; if (this._webUrl === this._url) { this._webUrl = curUrl; - setTimeout(action(() => (this._webUrl = this._url))); + setTimeout( + action(() => { + this._webUrl = this._url; + }) + ); } else { this._webUrl = this._url; } return true; } + return undefined; }); return false; }; @@ -655,12 +684,17 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem this._scrollHeight = 0; if (this._webUrl === this._url) { this._webUrl = curUrl; - setTimeout(action(() => (this._webUrl = this._url))); + setTimeout( + action(() => { + this._webUrl = this._url; + }) + ); } else { this._webUrl = this._url; } return true; } + return undefined; }); return false; }; @@ -692,13 +726,13 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem const html = dataTransfer.getData('text/html'); const uri = dataTransfer.getData('text/uri-list'); const url = uri || html || this._url || ''; - const newurl = url.startsWith(window.location.origin) ? url.replace(window.location.origin, this._url?.match(/http[s]?:\/\/[^\/]*/)?.[0] || '') : url; + const newurl = url.startsWith(window.location.origin) ? url.replace(window.location.origin, this._url?.match(/http[s]?:\/\/[^/]*/)?.[0] || '') : url; this.setData(newurl); e.stopPropagation(); }; @action - setData = (data: Field | Promise<RefField | undefined>) => { + setData = (data: FieldType | Promise<RefField | undefined>) => { if (!(typeof data === 'string') && !(data instanceof WebField)) return false; if (Field.toString(data) === this._url) return false; this._scrollHeight = 0; @@ -715,19 +749,31 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem e.stopPropagation(); }; - specificContextMenu = (e: React.MouseEvent | PointerEvent): void => { + specificContextMenu = (): void => { const cm = ContextMenu.Instance; const funcs: ContextMenuProps[] = []; if (!cm.findByDescription('Options...')) { !Doc.noviceMode && - funcs.push({ description: (this.layoutDoc[this.fieldKey + '_useCors'] ? "Don't Use" : 'Use') + ' Cors', event: () => (this.layoutDoc[this.fieldKey + '_useCors'] = !this.layoutDoc[this.fieldKey + '_useCors']), icon: 'snowflake' }); + funcs.push({ + description: (this.layoutDoc[this.fieldKey + '_useCors'] ? "Don't Use" : 'Use') + ' Cors', + event: () => { + this.layoutDoc[this.fieldKey + '_useCors'] = !this.layoutDoc[this.fieldKey + '_useCors']; + }, + icon: 'snowflake', + }); funcs.push({ description: (this.dataDoc[this.fieldKey + '_allowScripts'] ? 'Prevent' : 'Allow') + ' Scripts', event: () => { this.dataDoc[this.fieldKey + '_allowScripts'] = !this.dataDoc[this.fieldKey + '_allowScripts']; if (this._iframe) { - runInAction(() => (this._hackHide = true)); - setTimeout(action(() => (this._hackHide = false))); + runInAction(() => { + this._hackHide = true; + }); + setTimeout( + action(() => { + this._hackHide = false; + }) + ); } }, icon: 'snowflake', @@ -765,7 +811,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem setupMoveUpEvents( this, e, - action(e => { + action(() => { MarqueeAnnotator.clearAnnotations(this._savedAnnotations); return true; }), @@ -789,7 +835,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem @observable lighttext = false; @computed get urlContent() { - if (this.ScreenToLocalBoxXf().Scale > 25) return <div></div>; + if (this.ScreenToLocalBoxXf().Scale > 25) return <div />; setTimeout( action(() => { if (this._initialScroll === undefined && !this._webPageHasBeenRendered) { @@ -811,19 +857,23 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem })} contentEditable onPointerDown={this.webClipDown} + // eslint-disable-next-line react/no-danger dangerouslySetInnerHTML={{ __html: field.html }} /> ); } if (field instanceof WebField) { - const url = this.layoutDoc[this.fieldKey + '_useCors'] ? Utils.CorsProxy(this._webUrl) : this._webUrl; + const url = this.layoutDoc[this.fieldKey + '_useCors'] ? ClientUtils.CorsProxy(this._webUrl) : this._webUrl; const scripts = this.dataDoc[this.fieldKey + '_allowScripts'] || this._webUrl.includes('wikipedia.org') || this._webUrl.includes('google.com') || this._webUrl.startsWith('https://bing'); - //if (!scripts) console.log('No scripts for: ' + url); + // if (!scripts) console.log('No scripts for: ' + url); return ( <iframe + title="web iframe" key={this._warning} className="webBox-iframe" - ref={action((r: HTMLIFrameElement | null) => (this._iframe = r))} + ref={action((r: HTMLIFrameElement | null) => { + this._iframe = r; + })} style={{ pointerEvents: SnappingManager.IsResizing ? 'none' : undefined }} src={url} onLoad={this.iframeLoaded} @@ -834,12 +884,24 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem /> ); } - return <iframe className="webBox-iframe" ref={action((r: HTMLIFrameElement | null) => (this._iframe = r))} src={'https://crossorigin.me/https://cs.brown.edu'} />; + return ( + <iframe + title="web frame" + className="webBox-iframe" + ref={action((r: HTMLIFrameElement | null) => { + this._iframe = r; + })} + src="https://crossorigin.me/https://cs.brown.edu" + /> + ); } - addDocumentWrapper = (doc: Doc | Doc[], annotationKey?: string) => { - this._url && (doc instanceof Doc ? [doc] : doc).forEach(doc => (doc.config_data = new WebField(this._url))); - return this.addDocument(doc, annotationKey); + addDocumentWrapper = (docs: Doc | Doc[], annotationKey?: string) => { + this._url && + toList(docs).forEach(doc => { + doc.config_data = new WebField(this._url); + }); + return this.addDocument(docs, annotationKey); }; sidebarAddDocument = (doc: Doc | Doc[], sidebarKey?: string) => { @@ -853,7 +915,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem setupMoveUpEvents( this, e, - action((e, down, delta) => { + action((moveEv, down, delta) => { this._draggingSidebar = true; const localDelta = this._props .ScreenToLocalTransform() @@ -871,7 +933,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem } return false; }), - action((e, movement, isClick) => { + action((upEv, movement, isClick) => { this._draggingSidebar = false; !isClick && batch.end(); }), @@ -892,14 +954,14 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem backgroundColor: this.SidebarShown ? Colors.MEDIUM_BLUE : Colors.BLACK, }} onPointerDown={e => this.sidebarBtnDown(e, true)}> - <FontAwesomeIcon style={{ color: Colors.WHITE }} icon={'comment-alt'} size="sm" /> + <FontAwesomeIcon style={{ color: Colors.WHITE }} icon="comment-alt" size="sm" /> </div> ); } @observable _previewNativeWidth: Opt<number> = undefined; @observable _previewWidth: Opt<number> = undefined; toggleSidebar = action((preview: boolean = false) => { - var nativeWidth = NumCast(this.layoutDoc[this.fieldKey + '_nativeWidth']); + let nativeWidth = NumCast(this.layoutDoc[this.fieldKey + '_nativeWidth']); if (!nativeWidth) { const defaultNativeWidth = NumCast(this.Document.nativeWidth, this.dataDoc[this.fieldKey] instanceof WebField ? 850 : NumCast(this.Document._width)); Doc.SetNativeWidth(this.dataDoc, Doc.NativeWidth(this.dataDoc) || defaultNativeWidth); @@ -938,7 +1000,9 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem }; _innerCollectionView: CollectionFreeFormView | undefined; zoomScaling = () => this._innerCollectionView?.zoomScaling() ?? 1; - setInnerContent = (component: ViewBoxInterface) => (this._innerCollectionView = component as CollectionFreeFormView); + setInnerContent = (component: ViewBoxInterface<any>) => { + this._innerCollectionView = component as CollectionFreeFormView; + }; @computed get content() { const interactive = this._props.isContentActive() && this._props.pointerEvents?.() !== 'none' && Doc.ActiveTool === InkTool.None; @@ -969,24 +1033,25 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem {this.inlineTextAnnotations .sort((a, b) => NumCast(a.y) - NumCast(b.y)) .map(anno => ( - <Annotation {...this._props} fieldKey={this.annotationKey} pointerEvents={this.pointerEvents} dataDoc={this.dataDoc} anno={anno} key={`${anno[Id]}-annotation`} /> + // eslint-disable-next-line react/jsx-props-no-spreading + <Annotation {...this._props} fieldKey={this.annotationKey} pointerEvents={this.pointerEvents} containerDataDoc={this.dataDoc} annoDoc={anno} key={`${anno[Id]}-annotation`} /> ))} </div> ); } @computed get SidebarShown() { - return this._showSidebar || this.layoutDoc._layout_showSidebar ? true : false; + return !!(this._showSidebar || this.layoutDoc._layout_showSidebar); } renderAnnotations = (childFilters: () => string[]) => ( <CollectionFreeFormView + // eslint-disable-next-line react/jsx-props-no-spreading {...this._props} setContentViewBox={this.setInnerContent} NativeWidth={returnZero} NativeHeight={returnZero} - originTopLeft={false} - isAnnotationOverlayScrollable={true} + isAnnotationOverlayScrollable renderDepth={this._props.renderDepth + 1} - isAnnotationOverlay={true} + isAnnotationOverlay fieldKey={this.annotationKey} setPreviewCursor={this.setPreviewCursor} PanelWidth={this.panelWidth} @@ -1029,7 +1094,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem }} // when active, block wheel events from propagating since they're handled by the iframe onWheel={this.onZoomWheel} - onScroll={e => this.setDashScrollTop(this._outerRef.current?.scrollTop || 0)} + onScroll={() => this.setDashScrollTop(this._outerRef.current?.scrollTop || 0)} onPointerDown={this.onMarqueeDown}> <div className="webBox-innerContent" style={{ height: (this._webPageHasBeenRendered && this._scrollHeight > this._props.PanelHeight() && this._scrollHeight) || '100%', pointerEvents }}> {this.content} @@ -1045,7 +1110,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem return ( <div className="webBox-ui" onPointerDown={e => e.stopPropagation()} style={{ display: this._props.isContentActive() ? 'flex' : 'none' }}> <div className="webBox-overlayCont" onPointerDown={e => e.stopPropagation()} style={{ left: `${this._searching ? 0 : 100}%` }}> - <button className="webBox-overlayButton" title={'search'} /> + <button type="button" className="webBox-overlayButton" title="search" /> <input className="webBox-searchBar" placeholder="Search" @@ -1056,13 +1121,14 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem e.stopPropagation(); }} /> - <button className="webBox-search" title="Search" onClick={e => this.search(this._searchString, e.shiftKey)}> + <button type="button" className="webBox-search" title="Search" onClick={e => this.search(this._searchString, e.shiftKey)}> <FontAwesomeIcon icon="search" size="sm" /> </button> </div> <button + type="button" className="webBox-overlayButton" - title={'search'} + title="search" onClick={action(() => { this._searching = !this._searching; this.search('', false, true); @@ -1075,14 +1141,18 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem </div> ); } - searchStringChanged = (e: React.ChangeEvent<HTMLInputElement>) => (this._searchString = e.currentTarget.value); - setPreviewCursor = (func?: (x: number, y: number, drag: boolean, hide: boolean, doc: Opt<Doc>) => void) => (this._setPreviewCursor = func); + searchStringChanged = (e: React.ChangeEvent<HTMLInputElement>) => { + this._searchString = e.currentTarget.value; + }; + setPreviewCursor = (func?: (x: number, y: number, drag: boolean, hide: boolean, doc: Opt<Doc>) => void) => { + this._setPreviewCursor = func; + }; panelWidth = () => this._props.PanelWidth() / (this._props.NativeDimScaling?.() || 1) - this.sidebarWidth() + WebBox.sidebarResizerWidth; panelHeight = () => this._props.PanelHeight() / (this._props.NativeDimScaling?.() || 1); scrollXf = () => this.ScreenToLocalBoxXf().translate(0, NumCast(this.layoutDoc._layout_scrollTop)); anchorMenuClick = () => this._sidebarRef.current?.anchorMenuClick; - transparentFilter = () => [...this._props.childFilters(), Utils.TransparentBackgroundFilter]; - opaqueFilter = () => [...this._props.childFilters(), Utils.noDragDocsFilter, ...(SnappingManager.CanEmbed ? [] : [Utils.OpaqueBackgroundFilter])]; + transparentFilter = () => [...this._props.childFilters(), ClientUtils.TransparentBackgroundFilter]; + opaqueFilter = () => [...this._props.childFilters(), ClientUtils.noDragDocsFilter, ...(SnappingManager.CanEmbed ? [] : [ClientUtils.OpaqueBackgroundFilter])]; childStyleProvider = (doc: Doc | undefined, props: Opt<FieldViewProps>, property: string): any => { if (doc instanceof Doc && property === StyleProp.PointerEvents) { if (this.inlineTextAnnotations.includes(doc)) return 'none'; @@ -1149,6 +1219,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem <div style={{ position: 'absolute', height: '100%', right: 0, top: 0, width: `calc(100 * ${this.sidebarWidth() / this._props.PanelWidth()}%` }}> <SidebarAnnos ref={this._sidebarRef} + // eslint-disable-next-line react/jsx-props-no-spreading {...this._props} whenChildContentsActiveChanged={this.whenChildContentsActiveChanged} fieldKey={this.fieldKey + '_' + this._urlHash} @@ -1169,6 +1240,12 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem ); } } +// eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function urlHash(url: string) { return stringHash(url); }); + +Docs.Prototypes.TemplateMap.set(DocumentType.WEB, { + layout: { view: WebBox, dataField: 'data' }, + options: { acl: '', _height: 300, _layout_fitWidth: true, _layout_nativeDimEditable: true, _layout_reflowVertical: true, waitForDoubleClickToClick: 'always', systemIcon: 'BsGlobe' }, +}); |