From 3ecb3ef3587f347c41e4a7651854bab14cc3701d Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 28 Sep 2023 13:54:25 +0100 Subject: [PATCH 01/13] update index.js --- .../HTMLRenderers/PreRenderer/index.js | 84 +++++++++---------- 1 file changed, 40 insertions(+), 44 deletions(-) diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/PreRenderer/index.js b/src/components/HTMLEngineProvider/HTMLRenderers/PreRenderer/index.js index efc9e432cba..e4aec144613 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/PreRenderer/index.js +++ b/src/components/HTMLEngineProvider/HTMLRenderers/PreRenderer/index.js @@ -1,70 +1,66 @@ -import React from 'react'; +import React, {useCallback, useEffect, useRef} from 'react'; import _ from 'underscore'; -import withLocalize from '../../../withLocalize'; + +import ControlSelection from '../../../../libs/ControlSelection'; +import * as DeviceCapabilities from '../../../../libs/DeviceCapabilities'; import htmlRendererPropTypes from '../htmlRendererPropTypes'; import BasePreRenderer from './BasePreRenderer'; -import * as DeviceCapabilities from '../../../../libs/DeviceCapabilities'; -import ControlSelection from '../../../../libs/ControlSelection'; - -class PreRenderer extends React.Component { - constructor(props) { - super(props); - this.scrollNode = this.scrollNode.bind(this); - this.debouncedIsScrollingVertically = _.debounce(this.isScrollingVertically.bind(this), 100, true); - } +const isScrollingVertically = (event) => + // Mark as vertical scrolling only when absolute value of deltaY is more than the double of absolute + // value of deltaX, so user can use trackpad scroll on the code block horizontally at a wide angle. + Math.abs(event.deltaY) > Math.abs(event.deltaX) * 2; - componentDidMount() { - if (!this.ref) { - return; - } - this.ref.getScrollableNode().addEventListener('wheel', this.scrollNode); - } +const debouncedIsScrollingVertically = (event) => _.debounce(isScrollingVertically(event), 100, true); - componentWillUnmount() { - this.ref.getScrollableNode().removeEventListener('wheel', this.scrollNode); - } +function PreRenderer(props) { + const scrollViewRef = useRef(); /** - * Check if user is scrolling vertically based on deltaX and deltaY. We debounce this - * method in the constructor to make sure it's called only for the first event. + * Checks if user is scrolling vertically based on deltaX and deltaY. We debounce this + * method in order to make sure it's called only for the first event. * @param {WheelEvent} event Wheel event * @returns {Boolean} true if user is scrolling vertically */ - isScrollingVertically(event) { - // Mark as vertical scrolling only when absolute value of deltaY is more than the double of absolute - // value of deltaX, so user can use trackpad scroll on the code block horizontally at a wide angle. - return Math.abs(event.deltaY) > Math.abs(event.deltaX) * 2; - } /** * Manually scrolls the code block if code block horizontal scrollable, then prevents the event from being passed up to the parent. * @param {Object} event native event */ - scrollNode(event) { - const node = this.ref.getScrollableNode(); + const scrollNode = useCallback((event) => { + const node = scrollViewRef.current.getScrollableNode(); const horizontalOverflow = node.scrollWidth > node.offsetWidth; - const isScrollingVertically = this.debouncedIsScrollingVertically(event); - if (event.currentTarget === node && horizontalOverflow && !isScrollingVertically) { + if (event.currentTarget === node && horizontalOverflow && !debouncedIsScrollingVertically(event)) { node.scrollLeft += event.deltaX; event.preventDefault(); event.stopPropagation(); } - } + }, []); + + useEffect(() => { + const eventListenerRefValue = scrollViewRef.current; + if (!eventListenerRefValue) { + return; + } + eventListenerRefValue.getScrollableNode().addEventListener('wheel', scrollNode); + + return () => { + eventListenerRefValue.getScrollableNode().removeEventListener('wheel', scrollNode); + }; + }, [scrollNode]); - render() { - return ( - (this.ref = el)} - onPressIn={() => DeviceCapabilities.canUseTouchScreen() && ControlSelection.block()} - onPressOut={() => ControlSelection.unblock()} - /> - ); - } + return ( + DeviceCapabilities.canUseTouchScreen() && ControlSelection.block()} + onPressOut={ControlSelection.unblock} + /> + ); } PreRenderer.propTypes = htmlRendererPropTypes; +PreRenderer.displayName = 'PreRenderer'; -export default withLocalize(PreRenderer); +export default PreRenderer; \ No newline at end of file From eb52c3e5d55cc62c2a50d4ce067ff3caf3d92a62 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 4 Oct 2023 07:28:32 +0100 Subject: [PATCH 02/13] migrate clipboard to TS --- src/libs/Clipboard/index.native.js | 18 ----- src/libs/Clipboard/index.native.ts | 19 ++++++ src/libs/Clipboard/{index.js => index.ts} | 83 +++++++++++++++-------- src/libs/Clipboard/types.ts | 9 +++ src/types/modules/react-native-web.d.ts | 7 ++ 5 files changed, 88 insertions(+), 48 deletions(-) delete mode 100644 src/libs/Clipboard/index.native.js create mode 100644 src/libs/Clipboard/index.native.ts rename src/libs/Clipboard/{index.js => index.ts} (53%) create mode 100644 src/libs/Clipboard/types.ts create mode 100644 src/types/modules/react-native-web.d.ts diff --git a/src/libs/Clipboard/index.native.js b/src/libs/Clipboard/index.native.js deleted file mode 100644 index d6345ac94a3..00000000000 --- a/src/libs/Clipboard/index.native.js +++ /dev/null @@ -1,18 +0,0 @@ -import Clipboard from '@react-native-community/clipboard'; - -/** - * Sets a string on the Clipboard object via @react-native-community/clipboard - * - * @param {String} text - */ -const setString = (text) => { - Clipboard.setString(text); -}; - -export default { - setString, - - // We don't want to set HTML on native platforms so noop them. - canSetHtml: () => false, - setHtml: () => {}, -}; diff --git a/src/libs/Clipboard/index.native.ts b/src/libs/Clipboard/index.native.ts new file mode 100644 index 00000000000..bc7da7ad9d3 --- /dev/null +++ b/src/libs/Clipboard/index.native.ts @@ -0,0 +1,19 @@ +import RNCClipboard from '@react-native-community/clipboard'; +import {SetString, Clipboard} from './types'; + +/** + * Sets a string on the Clipboard object via @react-native-community/clipboard + */ +const setString: SetString = (text) => { + RNCClipboard.setString(text); +}; + +const clipboard: Clipboard = { + setString, + + // We don't want to set HTML on native platforms so noop them. + canSetHtml: () => false, + setHtml: () => {}, +}; + +export default clipboard; diff --git a/src/libs/Clipboard/index.js b/src/libs/Clipboard/index.ts similarity index 53% rename from src/libs/Clipboard/index.js rename to src/libs/Clipboard/index.ts index b770b2f2c78..fe0515edc58 100644 --- a/src/libs/Clipboard/index.js +++ b/src/libs/Clipboard/index.ts @@ -1,17 +1,37 @@ // on Web/desktop this import will be replaced with `react-native-web` -import {Clipboard} from 'react-native-web'; -import lodashGet from 'lodash/get'; +import {Clipboard as RNWClipboard} from 'react-native-web'; import CONST from '../../CONST'; import * as Browser from '../Browser'; +import {SetString, Clipboard} from './types'; -const canSetHtml = () => lodashGet(navigator, 'clipboard.write'); +type ComposerSelection = { + start: number; + end: number; + direction: 'forward' | 'backward' | 'none'; +}; + +type AnchorSelection = { + anchorOffset: number; + focusOffset: number; + anchorNode: Node; + focusNode: Node; +}; + +type Nullable = {[K in keyof T]: T[K] | null}; +type OriginalSelection = ComposerSelection | Partial>; + +/* +* @param {this: void} object The object to query. +*/ + +const canSetHtml = () => (...args: ClipboardItems) => navigator?.clipboard?.write([...args]); /** * Deprecated method to write the content as HTML to clipboard. - * @param {String} html HTML representation - * @param {String} text Plain text representation + * @param HTML representation + * @param Plain text representation */ -function setHTMLSync(html, text) { +function setHTMLSync(html: string, text: string) { const node = document.createElement('span'); node.textContent = html; node.style.all = 'unset'; @@ -22,16 +42,16 @@ function setHTMLSync(html, text) { node.addEventListener('copy', (e) => { e.stopPropagation(); e.preventDefault(); - e.clipboardData.clearData(); - e.clipboardData.setData('text/html', html); - e.clipboardData.setData('text/plain', text); + e.clipboardData?.clearData(); + e.clipboardData?.setData('text/html', html); + e.clipboardData?.setData('text/plain', text); }); document.body.appendChild(node); - const selection = window.getSelection(); - const firstAnchorChild = selection.anchorNode && selection.anchorNode.firstChild; + const selection = window?.getSelection(); + const firstAnchorChild = selection?.anchorNode?.firstChild; const isComposer = firstAnchorChild instanceof HTMLTextAreaElement; - let originalSelection = null; + let originalSelection: OriginalSelection | null = null; if (isComposer) { originalSelection = { start: firstAnchorChild.selectionStart, @@ -40,17 +60,17 @@ function setHTMLSync(html, text) { }; } else { originalSelection = { - anchorNode: selection.anchorNode, - anchorOffset: selection.anchorOffset, - focusNode: selection.focusNode, - focusOffset: selection.focusOffset, + anchorNode: selection?.anchorNode, + anchorOffset: selection?.anchorOffset, + focusNode: selection?.focusNode, + focusOffset: selection?.focusOffset, }; } - selection.removeAllRanges(); + selection?.removeAllRanges(); const range = document.createRange(); range.selectNodeContents(node); - selection.addRange(range); + selection?.addRange(range); try { document.execCommand('copy'); @@ -59,12 +79,14 @@ function setHTMLSync(html, text) { // See https://dvcs.w3.org/hg/editing/raw-file/tip/editing.html#the-copy-command for more details. } - selection.removeAllRanges(); + selection?.removeAllRanges(); if (isComposer) { - firstAnchorChild.setSelectionRange(originalSelection.start, originalSelection.end, originalSelection.direction); + const composerSelection = originalSelection as ComposerSelection; + firstAnchorChild.setSelectionRange(composerSelection.start, composerSelection.end, composerSelection.direction); } else { - selection.setBaseAndExtent(originalSelection.anchorNode, originalSelection.anchorOffset, originalSelection.focusNode, originalSelection.focusOffset); + const anchorSelection = originalSelection as AnchorSelection; + selection?.setBaseAndExtent(anchorSelection.anchorNode, anchorSelection.anchorOffset, anchorSelection.focusNode, anchorSelection.focusOffset); } document.body.removeChild(node); @@ -72,10 +94,10 @@ function setHTMLSync(html, text) { /** * Writes the content as HTML if the web client supports it. - * @param {String} html HTML representation - * @param {String} text Plain text representation + * @param HTML representation + * @param Plain text representation */ -const setHtml = (html, text) => { +const setHtml = (html: string, text: string) => { if (!html || !text) { return; } @@ -92,9 +114,10 @@ const setHtml = (html, text) => { setHTMLSync(html, text); } else { navigator.clipboard.write([ - // eslint-disable-next-line no-undef new ClipboardItem({ + // eslint-disable-next-line @typescript-eslint/naming-convention 'text/html': new Blob([html], {type: 'text/html'}), + // eslint-disable-next-line @typescript-eslint/naming-convention 'text/plain': new Blob([text], {type: 'text/plain'}), }), ]); @@ -103,15 +126,15 @@ const setHtml = (html, text) => { /** * Sets a string on the Clipboard object via react-native-web - * - * @param {String} text */ -const setString = (text) => { - Clipboard.setString(text); +const setString: SetString = (text) => { + RNWClipboard.setString(text); }; -export default { +const clipboard: Clipboard = { setString, canSetHtml, setHtml, }; + +export default clipboard; diff --git a/src/libs/Clipboard/types.ts b/src/libs/Clipboard/types.ts new file mode 100644 index 00000000000..e4b7cb1b533 --- /dev/null +++ b/src/libs/Clipboard/types.ts @@ -0,0 +1,9 @@ +type SetString = (text: string) => void; + +type Clipboard = { + setString: SetString; + canSetHtml: () => void; + setHtml: (html: string, text: string) => void; +} + +export type {SetString, Clipboard}; \ No newline at end of file diff --git a/src/types/modules/react-native-web.d.ts b/src/types/modules/react-native-web.d.ts new file mode 100644 index 00000000000..067e2f95e07 --- /dev/null +++ b/src/types/modules/react-native-web.d.ts @@ -0,0 +1,7 @@ +declare module 'react-native-web' { + type SetString = (text: string) => void; + + const Clipboard: { + setString: SetString; + } +} \ No newline at end of file From 82abacaa4985587dd730465d75652aa37a12b00d Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 4 Oct 2023 07:56:04 +0100 Subject: [PATCH 03/13] fix lint --- src/libs/Clipboard/index.ts | 9 ++++++--- src/libs/Clipboard/types.ts | 4 ++-- src/types/modules/react-native-web.d.ts | 6 +++--- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/libs/Clipboard/index.ts b/src/libs/Clipboard/index.ts index fe0515edc58..8c2d1be1afd 100644 --- a/src/libs/Clipboard/index.ts +++ b/src/libs/Clipboard/index.ts @@ -21,10 +21,13 @@ type Nullable = {[K in keyof T]: T[K] | null}; type OriginalSelection = ComposerSelection | Partial>; /* -* @param {this: void} object The object to query. -*/ + * @param {this: void} object The object to query. + */ -const canSetHtml = () => (...args: ClipboardItems) => navigator?.clipboard?.write([...args]); +const canSetHtml = + () => + (...args: ClipboardItems) => + navigator?.clipboard?.write([...args]); /** * Deprecated method to write the content as HTML to clipboard. diff --git a/src/libs/Clipboard/types.ts b/src/libs/Clipboard/types.ts index e4b7cb1b533..92a90df85e0 100644 --- a/src/libs/Clipboard/types.ts +++ b/src/libs/Clipboard/types.ts @@ -4,6 +4,6 @@ type Clipboard = { setString: SetString; canSetHtml: () => void; setHtml: (html: string, text: string) => void; -} +}; -export type {SetString, Clipboard}; \ No newline at end of file +export type {SetString, Clipboard}; diff --git a/src/types/modules/react-native-web.d.ts b/src/types/modules/react-native-web.d.ts index 067e2f95e07..da723e9a811 100644 --- a/src/types/modules/react-native-web.d.ts +++ b/src/types/modules/react-native-web.d.ts @@ -1,7 +1,7 @@ declare module 'react-native-web' { type SetString = (text: string) => void; - + const Clipboard: { setString: SetString; - } -} \ No newline at end of file + }; +} From 40226f38242c79e2cf02d535af3713ce9d402d53 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 4 Oct 2023 09:16:21 +0100 Subject: [PATCH 04/13] remove redundant JSDOC and Move Nullable to utils --- src/libs/Clipboard/index.ts | 15 +++------------ src/types/utils/Nullable.ts | 3 +++ 2 files changed, 6 insertions(+), 12 deletions(-) create mode 100644 src/types/utils/Nullable.ts diff --git a/src/libs/Clipboard/index.ts b/src/libs/Clipboard/index.ts index 8c2d1be1afd..3166cab1bed 100644 --- a/src/libs/Clipboard/index.ts +++ b/src/libs/Clipboard/index.ts @@ -3,6 +3,7 @@ import {Clipboard as RNWClipboard} from 'react-native-web'; import CONST from '../../CONST'; import * as Browser from '../Browser'; import {SetString, Clipboard} from './types'; +import Nullable from '../../types/utils/Nullable'; type ComposerSelection = { start: number; @@ -17,13 +18,8 @@ type AnchorSelection = { focusNode: Node; }; -type Nullable = {[K in keyof T]: T[K] | null}; type OriginalSelection = ComposerSelection | Partial>; -/* - * @param {this: void} object The object to query. - */ - const canSetHtml = () => (...args: ClipboardItems) => @@ -31,8 +27,6 @@ const canSetHtml = /** * Deprecated method to write the content as HTML to clipboard. - * @param HTML representation - * @param Plain text representation */ function setHTMLSync(html: string, text: string) { const node = document.createElement('span'); @@ -84,9 +78,8 @@ function setHTMLSync(html: string, text: string) { selection?.removeAllRanges(); - if (isComposer) { - const composerSelection = originalSelection as ComposerSelection; - firstAnchorChild.setSelectionRange(composerSelection.start, composerSelection.end, composerSelection.direction); + if (isComposer && 'start' in originalSelection) { + firstAnchorChild.setSelectionRange(originalSelection.start, originalSelection.end, originalSelection.direction); } else { const anchorSelection = originalSelection as AnchorSelection; selection?.setBaseAndExtent(anchorSelection.anchorNode, anchorSelection.anchorOffset, anchorSelection.focusNode, anchorSelection.focusOffset); @@ -97,8 +90,6 @@ function setHTMLSync(html: string, text: string) { /** * Writes the content as HTML if the web client supports it. - * @param HTML representation - * @param Plain text representation */ const setHtml = (html: string, text: string) => { if (!html || !text) { diff --git a/src/types/utils/Nullable.ts b/src/types/utils/Nullable.ts new file mode 100644 index 00000000000..caba46ef5b5 --- /dev/null +++ b/src/types/utils/Nullable.ts @@ -0,0 +1,3 @@ +type Nullable = {[K in keyof T]: T[K] | null}; + +export default Nullable; From dfc7be9bd67acee2ba2253ab4afa41170e065bd9 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 4 Oct 2023 09:25:30 +0100 Subject: [PATCH 05/13] Update src/types/modules/react-native-web.d.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fábio Henriques --- src/types/modules/react-native-web.d.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/types/modules/react-native-web.d.ts b/src/types/modules/react-native-web.d.ts index da723e9a811..f7db951eada 100644 --- a/src/types/modules/react-native-web.d.ts +++ b/src/types/modules/react-native-web.d.ts @@ -1,7 +1,11 @@ +/* eslint-disable import/prefer-default-export */ +/* eslint-disable @typescript-eslint/consistent-type-definitions */ declare module 'react-native-web' { - type SetString = (text: string) => void; + class Clipboard { + static isAvailable(): boolean; + static getString(): Promise; + static setString(text: string): boolean; + } - const Clipboard: { - setString: SetString; - }; + export {Clipboard}; } From 4bf68670f7af143b6c576cc8bf83076d6cd607f4 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 4 Oct 2023 10:07:42 +0100 Subject: [PATCH 06/13] fix reviews --- src/libs/Clipboard/index.native.ts | 20 ++++++++++---------- src/libs/Clipboard/index.ts | 19 +++++++++---------- src/libs/Clipboard/types.ts | 10 +++------- src/types/utils/Nullable.ts | 3 --- 4 files changed, 22 insertions(+), 30 deletions(-) delete mode 100644 src/types/utils/Nullable.ts diff --git a/src/libs/Clipboard/index.native.ts b/src/libs/Clipboard/index.native.ts index bc7da7ad9d3..4a805b466d5 100644 --- a/src/libs/Clipboard/index.native.ts +++ b/src/libs/Clipboard/index.native.ts @@ -1,19 +1,19 @@ -import RNCClipboard from '@react-native-community/clipboard'; -import {SetString, Clipboard} from './types'; +import Clipboard from '@react-native-community/clipboard'; +import {SetString, CanSetHtml, SetHtml} from './types'; /** * Sets a string on the Clipboard object via @react-native-community/clipboard */ const setString: SetString = (text) => { - RNCClipboard.setString(text); + Clipboard.setString(text); }; -const clipboard: Clipboard = { - setString, +// We don't want to set HTML on native platforms so noop them. +const canSetHtml: CanSetHtml = () => false; +const setHtml: SetHtml = () => {}; - // We don't want to set HTML on native platforms so noop them. - canSetHtml: () => false, - setHtml: () => {}, +export default { + setString, + canSetHtml, + setHtml, }; - -export default clipboard; diff --git a/src/libs/Clipboard/index.ts b/src/libs/Clipboard/index.ts index 3166cab1bed..975780f561a 100644 --- a/src/libs/Clipboard/index.ts +++ b/src/libs/Clipboard/index.ts @@ -1,9 +1,8 @@ // on Web/desktop this import will be replaced with `react-native-web` -import {Clipboard as RNWClipboard} from 'react-native-web'; +import {Clipboard} from 'react-native-web'; import CONST from '../../CONST'; import * as Browser from '../Browser'; -import {SetString, Clipboard} from './types'; -import Nullable from '../../types/utils/Nullable'; +import {SetString, SetHtml, CanSetHtml} from './types'; type ComposerSelection = { start: number; @@ -18,9 +17,11 @@ type AnchorSelection = { focusNode: Node; }; -type OriginalSelection = ComposerSelection | Partial>; +type NullableObject = {[K in keyof T]: T[K] | null}; -const canSetHtml = +type OriginalSelection = ComposerSelection | Partial>; + +const canSetHtml: CanSetHtml = () => (...args: ClipboardItems) => navigator?.clipboard?.write([...args]); @@ -91,7 +92,7 @@ function setHTMLSync(html: string, text: string) { /** * Writes the content as HTML if the web client supports it. */ -const setHtml = (html: string, text: string) => { +const setHtml: SetHtml = (html: string, text: string) => { if (!html || !text) { return; } @@ -122,13 +123,11 @@ const setHtml = (html: string, text: string) => { * Sets a string on the Clipboard object via react-native-web */ const setString: SetString = (text) => { - RNWClipboard.setString(text); + Clipboard.setString(text); }; -const clipboard: Clipboard = { +export default { setString, canSetHtml, setHtml, }; - -export default clipboard; diff --git a/src/libs/Clipboard/types.ts b/src/libs/Clipboard/types.ts index 92a90df85e0..1d899144a2b 100644 --- a/src/libs/Clipboard/types.ts +++ b/src/libs/Clipboard/types.ts @@ -1,9 +1,5 @@ type SetString = (text: string) => void; +type SetHtml = (html: string, text: string) => void; +type CanSetHtml = (() => (...args: ClipboardItems) => Promise) | (() => boolean); -type Clipboard = { - setString: SetString; - canSetHtml: () => void; - setHtml: (html: string, text: string) => void; -}; - -export type {SetString, Clipboard}; +export type {SetString, CanSetHtml, SetHtml}; diff --git a/src/types/utils/Nullable.ts b/src/types/utils/Nullable.ts deleted file mode 100644 index caba46ef5b5..00000000000 --- a/src/types/utils/Nullable.ts +++ /dev/null @@ -1,3 +0,0 @@ -type Nullable = {[K in keyof T]: T[K] | null}; - -export default Nullable; From 6fb578b18db90da362ae195f7bfe32c22c538037 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 26 Oct 2023 08:23:50 +0100 Subject: [PATCH 07/13] use react native clipboard --- src/libs/Clipboard/index.native.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/Clipboard/index.native.ts b/src/libs/Clipboard/index.native.ts index 4a805b466d5..f7eb43ba803 100644 --- a/src/libs/Clipboard/index.native.ts +++ b/src/libs/Clipboard/index.native.ts @@ -1,8 +1,8 @@ -import Clipboard from '@react-native-community/clipboard'; +import Clipboard from '@react-native-clipboard/clipboard'; import {SetString, CanSetHtml, SetHtml} from './types'; /** - * Sets a string on the Clipboard object via @react-native-community/clipboard + * Sets a string on the Clipboard object via @react-native-clipboard/clipboard */ const setString: SetString = (text) => { Clipboard.setString(text); From bbdcb42cceb2d1c5b455c4e18cc966fdfe3e6c5f Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Mon, 30 Oct 2023 11:22:45 +0100 Subject: [PATCH 08/13] disable lint for function --- src/libs/Clipboard/index.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libs/Clipboard/index.ts b/src/libs/Clipboard/index.ts index 070d1b40e27..f5f2eeb5db3 100644 --- a/src/libs/Clipboard/index.ts +++ b/src/libs/Clipboard/index.ts @@ -109,9 +109,8 @@ const setHtml: SetHtml = (html: string, text: string) => { } else { navigator.clipboard.write([ new ClipboardItem({ - // eslint-disable-next-line @typescript-eslint/naming-convention + /* eslint-disable @typescript-eslint/naming-convention */ 'text/html': new Blob([html], {type: 'text/html'}), - // eslint-disable-next-line @typescript-eslint/naming-convention 'text/plain': new Blob([text], {type: 'text/plain'}), }), ]); From cf823bbd51099477d1862e80bc7797d3239a5fbd Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Mon, 30 Oct 2023 14:31:07 +0100 Subject: [PATCH 09/13] fix lint --- src/libs/Clipboard/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/Clipboard/index.ts b/src/libs/Clipboard/index.ts index 8bf8f23d066..23e899c995e 100644 --- a/src/libs/Clipboard/index.ts +++ b/src/libs/Clipboard/index.ts @@ -1,7 +1,7 @@ import Clipboard from '@react-native-clipboard/clipboard'; -import {SetString, SetHtml, CanSetHtml} from './types'; import * as Browser from '@libs/Browser'; import CONST from '@src/CONST'; +import {SetString, SetHtml, CanSetHtml} from './types'; type ComposerSelection = { start: number; From 0febe75a6e6f2b6d47085c9a57351b42b95ba199 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Mon, 30 Oct 2023 14:36:40 +0100 Subject: [PATCH 10/13] fix prettier --- src/libs/Clipboard/index.native.ts | 2 +- src/libs/Clipboard/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/Clipboard/index.native.ts b/src/libs/Clipboard/index.native.ts index f7eb43ba803..f78c5e4ab23 100644 --- a/src/libs/Clipboard/index.native.ts +++ b/src/libs/Clipboard/index.native.ts @@ -1,5 +1,5 @@ import Clipboard from '@react-native-clipboard/clipboard'; -import {SetString, CanSetHtml, SetHtml} from './types'; +import {CanSetHtml, SetHtml, SetString} from './types'; /** * Sets a string on the Clipboard object via @react-native-clipboard/clipboard diff --git a/src/libs/Clipboard/index.ts b/src/libs/Clipboard/index.ts index 23e899c995e..e2fc82a133a 100644 --- a/src/libs/Clipboard/index.ts +++ b/src/libs/Clipboard/index.ts @@ -1,7 +1,7 @@ import Clipboard from '@react-native-clipboard/clipboard'; import * as Browser from '@libs/Browser'; import CONST from '@src/CONST'; -import {SetString, SetHtml, CanSetHtml} from './types'; +import {CanSetHtml, SetHtml, SetString} from './types'; type ComposerSelection = { start: number; From 3f9f30fe4d0ba6e9558ab31ae997edb3c2bee49f Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 2 Nov 2023 05:51:51 +0100 Subject: [PATCH 11/13] return func if selection is null --- src/libs/Clipboard/index.ts | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/libs/Clipboard/index.ts b/src/libs/Clipboard/index.ts index 653219ec5e9..b703b0b4d7f 100644 --- a/src/libs/Clipboard/index.ts +++ b/src/libs/Clipboard/index.ts @@ -18,7 +18,7 @@ type AnchorSelection = { type NullableObject = {[K in keyof T]: T[K] | null}; -type OriginalSelection = ComposerSelection | Partial>; +type OriginalSelection = ComposerSelection | NullableObject; const canSetHtml: CanSetHtml = () => @@ -46,7 +46,12 @@ function setHTMLSync(html: string, text: string) { document.body.appendChild(node); const selection = window?.getSelection(); - const firstAnchorChild = selection?.anchorNode?.firstChild; + + if (selection === null) { + return; + } + + const firstAnchorChild = selection.anchorNode?.firstChild; const isComposer = firstAnchorChild instanceof HTMLTextAreaElement; let originalSelection: OriginalSelection | null = null; if (isComposer) { @@ -57,17 +62,17 @@ function setHTMLSync(html: string, text: string) { }; } else { originalSelection = { - anchorNode: selection?.anchorNode, - anchorOffset: selection?.anchorOffset, - focusNode: selection?.focusNode, - focusOffset: selection?.focusOffset, + anchorNode: selection.anchorNode, + anchorOffset: selection.anchorOffset, + focusNode: selection.focusNode, + focusOffset: selection.focusOffset, }; } - selection?.removeAllRanges(); + selection.removeAllRanges(); const range = document.createRange(); range.selectNodeContents(node); - selection?.addRange(range); + selection.addRange(range); try { document.execCommand('copy'); @@ -76,7 +81,7 @@ function setHTMLSync(html: string, text: string) { // See https://dvcs.w3.org/hg/editing/raw-file/tip/editing.html#the-copy-command for more details. } - selection?.removeAllRanges(); + selection.removeAllRanges(); const anchorSelection = originalSelection as AnchorSelection; @@ -85,7 +90,7 @@ function setHTMLSync(html: string, text: string) { } else if (anchorSelection.anchorNode && anchorSelection.focusNode) { // When copying to the clipboard here, the original values of anchorNode and focusNode will be null since there will be no user selection. // We are adding a check to prevent null values from being passed to setBaseAndExtent, in accordance with the standards of the Selection API as outlined here: https://w3c.github.io/selection-api/#dom-selection-setbaseandextent. - selection?.setBaseAndExtent(anchorSelection.anchorNode, anchorSelection.anchorOffset, anchorSelection.focusNode, anchorSelection.focusOffset); + selection.setBaseAndExtent(anchorSelection.anchorNode, anchorSelection.anchorOffset, anchorSelection.focusNode, anchorSelection.focusOffset); } document.body.removeChild(node); From f5838d2606d989c6780677a325faeb0b2819732b Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 2 Nov 2023 06:03:14 +0100 Subject: [PATCH 12/13] undo return func if selection is null --- src/libs/Clipboard/index.ts | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/libs/Clipboard/index.ts b/src/libs/Clipboard/index.ts index b703b0b4d7f..d6427cfdc91 100644 --- a/src/libs/Clipboard/index.ts +++ b/src/libs/Clipboard/index.ts @@ -18,7 +18,7 @@ type AnchorSelection = { type NullableObject = {[K in keyof T]: T[K] | null}; -type OriginalSelection = ComposerSelection | NullableObject; +type OriginalSelection = ComposerSelection | Partial>; const canSetHtml: CanSetHtml = () => @@ -47,11 +47,7 @@ function setHTMLSync(html: string, text: string) { const selection = window?.getSelection(); - if (selection === null) { - return; - } - - const firstAnchorChild = selection.anchorNode?.firstChild; + const firstAnchorChild = selection?.anchorNode?.firstChild; const isComposer = firstAnchorChild instanceof HTMLTextAreaElement; let originalSelection: OriginalSelection | null = null; if (isComposer) { @@ -62,17 +58,17 @@ function setHTMLSync(html: string, text: string) { }; } else { originalSelection = { - anchorNode: selection.anchorNode, - anchorOffset: selection.anchorOffset, - focusNode: selection.focusNode, - focusOffset: selection.focusOffset, + anchorNode: selection?.anchorNode, + anchorOffset: selection?.anchorOffset, + focusNode: selection?.focusNode, + focusOffset: selection?.focusOffset, }; } - selection.removeAllRanges(); + selection?.removeAllRanges(); const range = document.createRange(); range.selectNodeContents(node); - selection.addRange(range); + selection?.addRange(range); try { document.execCommand('copy'); @@ -81,7 +77,7 @@ function setHTMLSync(html: string, text: string) { // See https://dvcs.w3.org/hg/editing/raw-file/tip/editing.html#the-copy-command for more details. } - selection.removeAllRanges(); + selection?.removeAllRanges(); const anchorSelection = originalSelection as AnchorSelection; @@ -90,7 +86,7 @@ function setHTMLSync(html: string, text: string) { } else if (anchorSelection.anchorNode && anchorSelection.focusNode) { // When copying to the clipboard here, the original values of anchorNode and focusNode will be null since there will be no user selection. // We are adding a check to prevent null values from being passed to setBaseAndExtent, in accordance with the standards of the Selection API as outlined here: https://w3c.github.io/selection-api/#dom-selection-setbaseandextent. - selection.setBaseAndExtent(anchorSelection.anchorNode, anchorSelection.anchorOffset, anchorSelection.focusNode, anchorSelection.focusOffset); + selection?.setBaseAndExtent(anchorSelection.anchorNode, anchorSelection.anchorOffset, anchorSelection.focusNode, anchorSelection.focusOffset); } document.body.removeChild(node); From 9618154df909b298363bfb545abb44a42f9abe5f Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 2 Nov 2023 06:13:50 +0100 Subject: [PATCH 13/13] return func if selection is null --- src/libs/Clipboard/index.ts | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/libs/Clipboard/index.ts b/src/libs/Clipboard/index.ts index d6427cfdc91..b703b0b4d7f 100644 --- a/src/libs/Clipboard/index.ts +++ b/src/libs/Clipboard/index.ts @@ -18,7 +18,7 @@ type AnchorSelection = { type NullableObject = {[K in keyof T]: T[K] | null}; -type OriginalSelection = ComposerSelection | Partial>; +type OriginalSelection = ComposerSelection | NullableObject; const canSetHtml: CanSetHtml = () => @@ -47,7 +47,11 @@ function setHTMLSync(html: string, text: string) { const selection = window?.getSelection(); - const firstAnchorChild = selection?.anchorNode?.firstChild; + if (selection === null) { + return; + } + + const firstAnchorChild = selection.anchorNode?.firstChild; const isComposer = firstAnchorChild instanceof HTMLTextAreaElement; let originalSelection: OriginalSelection | null = null; if (isComposer) { @@ -58,17 +62,17 @@ function setHTMLSync(html: string, text: string) { }; } else { originalSelection = { - anchorNode: selection?.anchorNode, - anchorOffset: selection?.anchorOffset, - focusNode: selection?.focusNode, - focusOffset: selection?.focusOffset, + anchorNode: selection.anchorNode, + anchorOffset: selection.anchorOffset, + focusNode: selection.focusNode, + focusOffset: selection.focusOffset, }; } - selection?.removeAllRanges(); + selection.removeAllRanges(); const range = document.createRange(); range.selectNodeContents(node); - selection?.addRange(range); + selection.addRange(range); try { document.execCommand('copy'); @@ -77,7 +81,7 @@ function setHTMLSync(html: string, text: string) { // See https://dvcs.w3.org/hg/editing/raw-file/tip/editing.html#the-copy-command for more details. } - selection?.removeAllRanges(); + selection.removeAllRanges(); const anchorSelection = originalSelection as AnchorSelection; @@ -86,7 +90,7 @@ function setHTMLSync(html: string, text: string) { } else if (anchorSelection.anchorNode && anchorSelection.focusNode) { // When copying to the clipboard here, the original values of anchorNode and focusNode will be null since there will be no user selection. // We are adding a check to prevent null values from being passed to setBaseAndExtent, in accordance with the standards of the Selection API as outlined here: https://w3c.github.io/selection-api/#dom-selection-setbaseandextent. - selection?.setBaseAndExtent(anchorSelection.anchorNode, anchorSelection.anchorOffset, anchorSelection.focusNode, anchorSelection.focusOffset); + selection.setBaseAndExtent(anchorSelection.anchorNode, anchorSelection.anchorOffset, anchorSelection.focusNode, anchorSelection.focusOffset); } document.body.removeChild(node);