diff --git a/ts/groups/joinViaLink.ts b/ts/groups/joinViaLink.ts index 8da1518c9a..2e52b02962 100644 --- a/ts/groups/joinViaLink.ts +++ b/ts/groups/joinViaLink.ts @@ -1,8 +1,7 @@ // Copyright 2021 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import { unmountComponentAtNode } from 'react-dom'; -import { createRoot } from 'react-dom/client'; +import { createRoot, type Root } from 'react-dom/client'; import type { ConversationAttributesType } from '../model-types.d'; import type { ConversationModel } from '../models/conversations'; @@ -211,9 +210,9 @@ export async function joinViaLink(value: string): Promise { const closeDialog = async () => { try { - if (groupV2InfoNode) { - unmountComponentAtNode(groupV2InfoNode); - groupV2InfoNode = undefined; + if (groupV2InfoRoot) { + groupV2InfoRoot.unmount(); + groupV2InfoRoot = undefined; } window.reduxActions.conversations.setPreJoinConversation(undefined); @@ -234,9 +233,9 @@ export async function joinViaLink(value: string): Promise { const join = async () => { try { - if (groupV2InfoNode) { - unmountComponentAtNode(groupV2InfoNode); - groupV2InfoNode = undefined; + if (groupV2InfoRoot) { + groupV2InfoRoot.unmount(); + groupV2InfoRoot = undefined; } window.reduxActions.conversations.setPreJoinConversation(undefined); @@ -387,10 +386,11 @@ export async function joinViaLink(value: string): Promise { log.info(`${logId}: Showing modal`); - let groupV2InfoNode: HTMLDivElement | undefined = - document.createElement('div'); + const groupV2InfoNode = document.createElement('div'); + let groupV2InfoRoot: Root | undefined; - createRoot(groupV2InfoNode).render( + groupV2InfoRoot = createRoot(groupV2InfoNode); + groupV2InfoRoot.render( createGroupV2JoinModal(window.reduxStore, { join, onClose: closeDialog }) ); @@ -426,7 +426,7 @@ export async function joinViaLink(value: string): Promise { }; // Dialog has been dismissed; we'll delete the unneeeded avatar - if (!groupV2InfoNode) { + if (!groupV2InfoRoot) { await window.Signal.Migrations.deleteAttachmentData( attributes.avatar.path ); diff --git a/ts/util/longRunningTaskWrapper.tsx b/ts/util/longRunningTaskWrapper.tsx index 858fc3152a..c965aa3955 100644 --- a/ts/util/longRunningTaskWrapper.tsx +++ b/ts/util/longRunningTaskWrapper.tsx @@ -2,8 +2,7 @@ // SPDX-License-Identifier: AGPL-3.0-only import React, { StrictMode } from 'react'; -import { unmountComponentAtNode } from 'react-dom'; -import { createRoot } from 'react-dom/client'; +import { createRoot, type Root } from 'react-dom/client'; import * as Errors from '../types/errors'; import { createLogger } from '../logging/log'; @@ -29,13 +28,14 @@ export async function longRunningTaskWrapper({ const ONE_SECOND = 1000; const TWO_SECONDS = 2000; - let progressNode: HTMLDivElement | undefined; + let progressRoot: Root | undefined; let spinnerStart; let progressTimeout: NodeJS.Timeout | undefined = setTimeout(() => { - progressNode = document.createElement('div'); + const progressNode = document.createElement('div'); log.info(`${idLog}: Creating spinner`); - createRoot(progressNode).render( + progressRoot = createRoot(progressNode); + progressRoot.render( @@ -54,7 +54,7 @@ export async function longRunningTaskWrapper({ clearTimeoutIfNecessary(progressTimeout); progressTimeout = undefined; - if (progressNode) { + if (progressRoot) { const now = Date.now(); if (spinnerStart && now - spinnerStart < ONE_SECOND) { log.info( @@ -62,8 +62,8 @@ export async function longRunningTaskWrapper({ ); await sleep(ONE_SECOND); } - unmountComponentAtNode(progressNode); - progressNode = undefined; + progressRoot.unmount(); + progressRoot = undefined; } return result; @@ -72,9 +72,9 @@ export async function longRunningTaskWrapper({ clearTimeoutIfNecessary(progressTimeout); progressTimeout = undefined; - if (progressNode) { - unmountComponentAtNode(progressNode); - progressNode = undefined; + if (progressRoot) { + progressRoot.unmount(); + progressRoot = undefined; } if (!suppressErrorDialog) { diff --git a/ts/util/showConfirmationDialog.tsx b/ts/util/showConfirmationDialog.tsx index 6fdd6877f2..0682e03467 100644 --- a/ts/util/showConfirmationDialog.tsx +++ b/ts/util/showConfirmationDialog.tsx @@ -2,8 +2,7 @@ // SPDX-License-Identifier: AGPL-3.0-only import React, { StrictMode } from 'react'; -import { unmountComponentAtNode } from 'react-dom'; -import { createRoot } from 'react-dom/client'; +import { createRoot, type Root } from 'react-dom/client'; import { ConfirmationDialog } from '../components/ConfirmationDialog'; import { FunDefaultEnglishEmojiLocalizationProvider } from '../components/fun/FunEmojiLocalizationProvider'; @@ -20,18 +19,17 @@ type ConfirmationDialogViewProps = { resolve: () => void; }; -let confirmationDialogViewNode: HTMLElement | undefined; +let confirmationDialogRoot: Root | undefined; let confirmationDialogPreviousFocus: HTMLElement | undefined; function removeConfirmationDialog() { - if (!confirmationDialogViewNode) { + if (!confirmationDialogRoot) { return; } window.reduxActions?.globalModals.toggleConfirmationModal(false); - unmountComponentAtNode(confirmationDialogViewNode); - document.body.removeChild(confirmationDialogViewNode); + confirmationDialogRoot.unmount(); if ( confirmationDialogPreviousFocus && @@ -39,24 +37,25 @@ function removeConfirmationDialog() { ) { confirmationDialogPreviousFocus.focus(); } - confirmationDialogViewNode = undefined; + confirmationDialogRoot = undefined; } export function showConfirmationDialog( options: ConfirmationDialogViewProps ): void { - if (confirmationDialogViewNode) { + if (confirmationDialogRoot) { removeConfirmationDialog(); } window.reduxActions?.globalModals.toggleConfirmationModal(true); - confirmationDialogViewNode = document.createElement('div'); + const confirmationDialogViewNode = document.createElement('div'); document.body.appendChild(confirmationDialogViewNode); confirmationDialogPreviousFocus = document.activeElement as HTMLElement; - createRoot(confirmationDialogViewNode).render( + confirmationDialogRoot = createRoot(confirmationDialogViewNode); + confirmationDialogRoot.render(