diff options
author | bobzel <zzzman@gmail.com> | 2024-09-02 09:26:37 -0400 |
---|---|---|
committer | bobzel <zzzman@gmail.com> | 2024-09-02 09:26:37 -0400 |
commit | cda69e48361fce8d71a4dc66edd9dd976a27f52d (patch) | |
tree | 82b9a1a5967ae88a9534f89f7eaed3aeb289652f /src/client/views/nodes/WebBox.tsx | |
parent | c01828308714874589d1f60c33ca59df4c656c0c (diff) | |
parent | a958577d4c27b276aa37484e3f895e196138b17c (diff) |
Merge branch 'master' into alyssa-starter
Diffstat (limited to 'src/client/views/nodes/WebBox.tsx')
-rw-r--r-- | src/client/views/nodes/WebBox.tsx | 75 |
1 files changed, 40 insertions, 35 deletions
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index da947face..1fd73c226 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -1,6 +1,5 @@ -/* eslint-disable jsx-a11y/control-has-associated-label */ -/* eslint-disable jsx-a11y/no-static-element-interactions */ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { Property } from 'csstype'; import { htmlToText } from 'html-to-text'; import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; @@ -23,7 +22,7 @@ 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'; +import { undoable, UndoManager } from '../../util/UndoManager'; import { MarqueeOptionsMenu } from '../collections/collectionFreeForm'; import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView'; import { ContextMenu } from '../ContextMenu'; @@ -67,7 +66,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { private _sidebarRef = React.createRef<SidebarAnnos>(); private _searchRef = React.createRef<HTMLInputElement>(); private _searchString = ''; - private _scrollTimer: any; + private _scrollTimer: NodeJS.Timeout | undefined; private _getAnchor: (savedAnnotations: Opt<ObservableMap<number, HTMLDivElement[]>>, addAsAnnotation: boolean) => Opt<Doc> = () => undefined; @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. @@ -85,7 +84,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { this._marqueeing = val; } @observable private _iframe: HTMLIFrameElement | null = null; - @observable private _savedAnnotations = new ObservableMap<number, HTMLDivElement[]>(); + @observable private _savedAnnotations = new ObservableMap<number, (HTMLDivElement & { marqueeing?: boolean })[]>(); @observable private _scrollHeight = NumCast(this.layoutDoc.scrollHeight); @computed get _url() { return this.webField?.toString() || ''; @@ -123,11 +122,12 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { }); } try { + const contentWindow = this._iframe?.contentWindow; if (clear) { - this._iframe?.contentWindow?.getSelection()?.empty(); + contentWindow?.getSelection()?.empty(); } - if (searchString) { - (this._iframe?.contentWindow as any)?.find(searchString, false, bwd, true); + if (searchString && contentWindow && 'find' in contentWindow) { + (contentWindow.find as (str: string, caseSens?: boolean, backward?: boolean, wrapAround?: boolean) => void)(searchString, false, bwd, true); } } catch (e) { console.log('WebBox search error', e); @@ -144,7 +144,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { } }; - updateThumb = async () => { + updateIcon = async () => { if (!this._iframe) return; const scrollTop = NumCast(this.layoutDoc._layout_scrollTop); const nativeWidth = NumCast(this.layoutDoc.nativeWidth); @@ -156,7 +156,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { 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((dataUrl: any) => { + .then((dataUrl: string) => { if (dataUrl.includes('<!DOCTYPE')) { console.log('BAD DATA IN THUMB CREATION'); return; @@ -174,7 +174,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { ) ); }) - .catch((error: any) => { + .catch((error: object) => { console.error('oops, something went wrong!', error); }); }; @@ -361,8 +361,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { return anchor; }; - _textAnnotationCreator: (() => ObservableMap<number, HTMLDivElement[]>) | undefined; - savedAnnotationsCreator: () => ObservableMap<number, HTMLDivElement[]> = () => this._textAnnotationCreator?.() || this._savedAnnotations; + _textAnnotationCreator: (() => ObservableMap<number, (HTMLDivElement & { marqueeing?: boolean })[]>) | undefined; + savedAnnotationsCreator: () => ObservableMap<number, (HTMLDivElement & { marqueeing?: boolean })[]> = () => this._textAnnotationCreator?.() || this._savedAnnotations; @action iframeMove = (e: PointerEvent) => { @@ -399,7 +399,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { .transformPoint(e.clientX, e.clientY - NumCast(this.layoutDoc.layout_scrollTop)); if (!this._marqueeref.current?.isEmpty) this._marqueeref.current?.onEnd(theclick[0], theclick[1]); else { - if (!(e.target as any)?.tagName?.includes('INPUT')) this.finishMarquee(theclick[0], theclick[1]); + if (!(e.target as HTMLElement)?.tagName?.includes('INPUT')) this.finishMarquee(theclick[0], theclick[1]); this._getAnchor = AnchorMenu.Instance?.GetAnchor; this.marqueeing = undefined; } @@ -426,11 +426,12 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { sel.empty(); // Chrome else if (sel?.removeAllRanges) sel.removeAllRanges(); // Firefox // bcz: NEED TO unrotate e.clientX and e.clientY - const word = getWordAtPoint(e.target, e.clientX, e.clientY); + const target = e.target as HTMLElement; + const word = target && getWordAtPoint(target, e.clientX, e.clientY); this._setPreviewCursor?.(e.clientX, e.clientY, false, true, this.Document); MarqueeAnnotator.clearAnnotations(this._savedAnnotations); - if (!word && !(e.target as any)?.className?.includes('rangeslider') && !(e.target as any)?.onclick && !(e.target as any)?.parentNode?.onclick) { + if (!word && !target?.className?.includes('rangeslider') && !target?.onclick && !target?.parentElement?.onclick) { if (e.button !== 2) this.marqueeing = [e.clientX, e.clientY]; e.preventDefault(); } @@ -469,8 +470,9 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { .inverse() .transformPoint(e.clientX, e.clientY - NumCast(this.layoutDoc.layout_scrollTop)); MarqueeAnnotator.clearAnnotations(this._savedAnnotations); - const word = getWordAtPoint(e.target, e.clientX, e.clientY); - if (!word && !(e.target as any)?.className?.includes('rangeslider') && !(e.target as any)?.onclick && !(e.target as any)?.parentNode?.onclick) { + const target = e.target as HTMLElement; + const word = target && getWordAtPoint(target, e.clientX, e.clientY); + if (!word && !target?.className?.includes('rangeslider') && !target?.onclick && !target?.parentElement?.onclick) { this.marqueeing = theclick; this._marqueeref.current?.onInitiateSelection(this.marqueeing); this._iframe?.contentDocument?.addEventListener('pointermove', this.iframeMove); @@ -479,16 +481,16 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { }; isFirefox = () => 'InstallTrigger' in window; // navigator.userAgent.indexOf("Chrome") !== -1; - addWebStyleSheet(document: any, styleType: string = 'text/css') { + addWebStyleSheet(document: Document | null | undefined, styleType: string = 'text/css') { if (document) { const style = document.createElement('style'); style.type = styleType; const sheets = document.head.appendChild(style); - return (sheets as any).sheet; + return sheets.sheet; } return undefined; } - addWebStyleSheetRule(sheet: any, selector: any, css: any, selectorPrefix = '.') { + addWebStyleSheetRule(sheet: CSSStyleSheet | null | undefined, selector: string, css: { [key: string]: string }, selectorPrefix = '.') { const propText = typeof css === 'string' ? css @@ -498,7 +500,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { return sheet?.insertRule(selectorPrefix + selector + '{' + propText + '}', sheet.cssRules.length); } - _iframetimeout: any = undefined; + _iframetimeout: NodeJS.Timeout | undefined = undefined; @observable _warning = 0; @action iframeLoaded = () => { @@ -520,7 +522,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { 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); - const newsearch = matches?.lastElement()!; + const newsearch = matches?.lastElement() || ''; if (matches) { requrlraw = requrlraw.substring(0, requrlraw.indexOf(newsearch)); for (let i = 1; i < Array.from(matches)?.length; i++) { @@ -567,11 +569,13 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { ); iframeContent.addEventListener( 'click', - undoBatch( + undoable( action((e: MouseEvent) => { let eleHref = ''; - for (let ele = e.target as any; ele; ele = ele.parentElement) { - eleHref = (typeof ele.href === 'string' ? ele.href : ele.href?.baseVal) || ele.parentElement?.href || eleHref; + for (let ele = e.target as HTMLElement | Element | null; ele; ele = ele.parentElement) { + if (ele instanceof HTMLAnchorElement) { + eleHref = (typeof ele.href === 'string' ? ele.href : eleHref) || (ele.parentElement && 'href' in ele.parentElement ? (ele.parentElement.href as string) : eleHref); + } } const origin = this.webField?.origin; if (eleHref && origin) { @@ -586,7 +590,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { this._outerRef.current.scrollLeft = 0; } } - }) + }), + 'follow web link' ) ); iframe.contentDocument.addEventListener('wheel', this.iframeWheel, { passive: false }); @@ -790,7 +795,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { }, icon: 'snowflake', }); - funcs.push({ description: 'Create Thumbnail', event: () => this.updateThumb(), icon: 'portrait' }); + !Doc.noviceMode && funcs.push({ description: 'Update Icon', event: () => this.updateIcon(), icon: 'portrait' }); cm.addItem({ description: 'Options...', subitems: funcs, icon: 'asterisk' }); } }; @@ -850,10 +855,10 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { return ( <span className="webBox-htmlSpan" - ref={action((r: any) => { + ref={action((r: HTMLSpanElement) => { if (r) { this._scrollHeight = DivHeight(r); - this.lighttext = Array.from(r.children).some((c: any) => c instanceof HTMLElement && lightOrDark(getComputedStyle(c).color) !== Colors.WHITE); + this.lighttext = Array.from(r.children).some((c: Element) => c instanceof HTMLElement && lightOrDark(getComputedStyle(c).color) !== Colors.WHITE); } })} contentEditable @@ -1001,7 +1006,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { }; _innerCollectionView: CollectionFreeFormView | undefined; zoomScaling = () => this._innerCollectionView?.zoomScaling() ?? 1; - setInnerContent = (component: ViewBoxInterface<any>) => { + setInnerContent = (component: ViewBoxInterface<FieldViewProps>) => { this._innerCollectionView = component as CollectionFreeFormView; }; @@ -1083,7 +1088,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { @computed get webpage() { TraceMobx(); const previewScale = this._previewNativeWidth ? 1 - this.sidebarWidth() / this._previewNativeWidth : 1; - const pointerEvents = this.layoutDoc._lockedPosition ? 'none' : (this._props.pointerEvents?.() as any); + const pointerEvents = this.layoutDoc._lockedPosition ? 'none' : (this._props.pointerEvents?.() as Property.PointerEvents | undefined); const scale = previewScale * (this._props.NativeDimScaling?.() || 1); return ( <div @@ -1154,7 +1159,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { anchorMenuClick = () => this._sidebarRef.current?.anchorMenuClick; 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 => { + childStyleProvider = (doc: Doc | undefined, props: Opt<FieldViewProps>, property: string) => { if (doc instanceof Doc && property === StyleProp.PointerEvents) { if (this.inlineTextAnnotations.includes(doc)) return 'none'; } @@ -1168,7 +1173,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { render() { TraceMobx(); const previewScale = this._previewNativeWidth ? 1 - this.sidebarWidth() / this._previewNativeWidth : 1; - const pointerEvents = this.layoutDoc._lockedPosition ? 'none' : (this._props.pointerEvents?.() as any); + const pointerEvents = this.layoutDoc._lockedPosition ? 'none' : (this._props.pointerEvents?.() as Property.PointerEvents); const scale = previewScale * (this._props.NativeDimScaling?.() || 1); return ( <div @@ -1178,7 +1183,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { pointerEvents: this.pointerEvents(), // position: SnappingManager.IsDragging ? 'absolute' : undefined, }}> - <div className="webBox-background" style={{ backgroundColor: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BackgroundColor) }} /> + <div className="webBox-background" style={{ backgroundColor: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BackgroundColor) as string }} /> <div className="webBox-container" style={{ |