diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index 76bddcdaf1..33d117aa3d 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -3,7 +3,7 @@ import '../ts/window.d.ts'; -import React from 'react'; +import React, { StrictMode } from 'react'; import 'sanitize.css'; import '../stylesheets/manifest.scss'; @@ -153,6 +153,14 @@ window.ConversationController.isSignalConversationId = () => false; window.ConversationController.onConvoMessageMount = noop; window.reduxStore = mockStore; +function withStrictMode(Story, context) { + return ( + + + + ); +} + const withGlobalTypesProvider = (Story, context) => { const theme = context.globals.theme === 'light' ? ThemeType.light : ThemeType.dark; @@ -234,6 +242,7 @@ function withFunProvider(Story, context) { } export const decorators = [ + withStrictMode, withGlobalTypesProvider, withMockStoreProvider, withScrollLockProvider, diff --git a/ts/components/MediaPermissionsModal.stories.tsx b/ts/components/MediaPermissionsModal.stories.tsx index 7462947603..cc6e8e1a32 100644 --- a/ts/components/MediaPermissionsModal.stories.tsx +++ b/ts/components/MediaPermissionsModal.stories.tsx @@ -1,6 +1,6 @@ // Copyright 2025 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import React, { StrictMode } from 'react'; +import React from 'react'; import { action } from '@storybook/addon-actions'; import { type ComponentMeta } from '../storybook/types'; import type { PropsType } from './MediaPermissionsModal'; @@ -11,11 +11,7 @@ const { i18n } = window.SignalContext; type TemplateProps = Omit; function Template(props: TemplateProps) { - return ( - - - - ); + return ; } export default { diff --git a/ts/components/fun/FunEmoji.stories.tsx b/ts/components/fun/FunEmoji.stories.tsx index e499ac0bdf..a744461de6 100644 --- a/ts/components/fun/FunEmoji.stories.tsx +++ b/ts/components/fun/FunEmoji.stories.tsx @@ -2,7 +2,7 @@ // SPDX-License-Identifier: AGPL-3.0-only import { useVirtualizer } from '@tanstack/react-virtual'; import { chunk } from 'lodash'; -import React, { StrictMode, useCallback, useEffect, useRef } from 'react'; +import React, { useCallback, useEffect, useRef } from 'react'; import { type ComponentMeta } from '../../storybook/types'; import type { FunStaticEmojiProps } from './FunEmoji'; import { FunStaticEmoji } from './FunEmoji'; @@ -57,65 +57,63 @@ export function All(props: AllProps): JSX.Element { }, [rowVirtualizer, props.size]); return ( - +
-
- {rowVirtualizer.getVirtualItems().map(rowItem => { - const row = rows[rowItem.index]; - return ( -
- {row.map(emojiVariantKey => { - const variant = getEmojiVariantByKey(emojiVariantKey); - const parentKey = - getEmojiParentKeyByVariantKey(emojiVariantKey); - const parent = getEmojiParentByKey(parentKey); - return ( -
- -
- ); - })} -
- ); - })} -
+ {rowVirtualizer.getVirtualItems().map(rowItem => { + const row = rows[rowItem.index]; + return ( +
+ {row.map(emojiVariantKey => { + const variant = getEmojiVariantByKey(emojiVariantKey); + const parentKey = + getEmojiParentKeyByVariantKey(emojiVariantKey); + const parent = getEmojiParentByKey(parentKey); + return ( +
+ +
+ ); + })} +
+ ); + })}
- +
); } diff --git a/ts/components/fun/FunEmojiPicker.stories.tsx b/ts/components/fun/FunEmojiPicker.stories.tsx index 79c23b2778..12b5417874 100644 --- a/ts/components/fun/FunEmojiPicker.stories.tsx +++ b/ts/components/fun/FunEmojiPicker.stories.tsx @@ -1,6 +1,6 @@ // Copyright 2025 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import React, { StrictMode, useCallback, useState } from 'react'; +import React, { useCallback, useState } from 'react'; import { Button } from 'react-aria-components'; import { action } from '@storybook/addon-actions'; import { type ComponentMeta } from '../../storybook/types'; @@ -26,34 +26,32 @@ function Template(props: TemplateProps): JSX.Element { }, []); return ( - - null} - onOpenCustomizePreferredReactionsModal={() => null} - onSelectEmoji={() => null} - // Stickers - installedStickerPacks={packs} - showStickerPickerHint={false} - onClearStickerPickerHint={() => null} - onSelectSticker={() => null} - // Gifs - fetchGifsSearch={() => Promise.reject()} - fetchGifsFeatured={() => Promise.reject()} - fetchGif={() => Promise.reject()} - onSelectGif={() => null} - > - - - - - + null} + onOpenCustomizePreferredReactionsModal={() => null} + onSelectEmoji={() => null} + // Stickers + installedStickerPacks={packs} + showStickerPickerHint={false} + onClearStickerPickerHint={() => null} + onSelectSticker={() => null} + // Gifs + fetchGifsSearch={() => Promise.reject()} + fetchGifsFeatured={() => Promise.reject()} + fetchGif={() => Promise.reject()} + onSelectGif={() => null} + > + + + + ); } diff --git a/ts/components/fun/FunPicker.stories.tsx b/ts/components/fun/FunPicker.stories.tsx index 1d86da19f2..1f7ce1d3ba 100644 --- a/ts/components/fun/FunPicker.stories.tsx +++ b/ts/components/fun/FunPicker.stories.tsx @@ -1,6 +1,6 @@ // Copyright 2025 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import React, { StrictMode, useCallback, useState } from 'react'; +import React, { useCallback, useState } from 'react'; import { Button } from 'react-aria-components'; import { action } from '@storybook/addon-actions'; import { type ComponentMeta } from '../../storybook/types'; @@ -23,34 +23,32 @@ function Template(props: TemplateProps) { }, []); return ( - - null} - onOpenCustomizePreferredReactionsModal={() => null} - onSelectEmoji={() => null} - // Stickers - installedStickerPacks={packs} - showStickerPickerHint={false} - onClearStickerPickerHint={() => null} - onSelectSticker={() => null} - // Gifs - fetchGifsSearch={() => Promise.resolve(MOCK_GIFS_PAGINATED_ONE_PAGE)} - fetchGifsFeatured={() => Promise.resolve(MOCK_GIFS_PAGINATED_ONE_PAGE)} - fetchGif={() => Promise.resolve(new Blob([new Uint8Array(1)]))} - onSelectGif={() => null} - > - - - - - + null} + onOpenCustomizePreferredReactionsModal={() => null} + onSelectEmoji={() => null} + // Stickers + installedStickerPacks={packs} + showStickerPickerHint={false} + onClearStickerPickerHint={() => null} + onSelectSticker={() => null} + // Gifs + fetchGifsSearch={() => Promise.resolve(MOCK_GIFS_PAGINATED_ONE_PAGE)} + fetchGifsFeatured={() => Promise.resolve(MOCK_GIFS_PAGINATED_ONE_PAGE)} + fetchGif={() => Promise.resolve(new Blob([new Uint8Array(1)]))} + onSelectGif={() => null} + > + + + + ); } diff --git a/ts/components/fun/FunStickerPicker.stories.tsx b/ts/components/fun/FunStickerPicker.stories.tsx index 2f4b645ae8..30c5d4ce19 100644 --- a/ts/components/fun/FunStickerPicker.stories.tsx +++ b/ts/components/fun/FunStickerPicker.stories.tsx @@ -1,6 +1,6 @@ // Copyright 2025 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import React, { StrictMode, useCallback, useState } from 'react'; +import React, { useCallback, useState } from 'react'; import { Button } from 'react-aria-components'; import { action } from '@storybook/addon-actions'; import enMessages from '../../../_locales/en/messages.json'; @@ -28,38 +28,32 @@ function Template(props: TemplateProps): JSX.Element { }, []); return ( - - null} - onOpenCustomizePreferredReactionsModal={() => null} - onSelectEmoji={() => null} - // Stickers - installedStickerPacks={packs} - showStickerPickerHint={false} - onClearStickerPickerHint={() => null} - onSelectSticker={() => null} - // Gifs - fetchGifsSearch={() => Promise.reject()} - fetchGifsFeatured={() => Promise.reject()} - fetchGif={() => Promise.reject()} - onSelectGif={() => null} - > - - - - - + null} + onOpenCustomizePreferredReactionsModal={() => null} + onSelectEmoji={() => null} + // Stickers + installedStickerPacks={packs} + showStickerPickerHint={false} + onClearStickerPickerHint={() => null} + onSelectSticker={() => null} + // Gifs + fetchGifsSearch={() => Promise.reject()} + fetchGifsFeatured={() => Promise.reject()} + fetchGif={() => Promise.reject()} + onSelectGif={() => null} + > + + + + ); } diff --git a/ts/quill/mentions/blot.tsx b/ts/quill/mentions/blot.tsx index 40671022db..f2e0d4ab69 100644 --- a/ts/quill/mentions/blot.tsx +++ b/ts/quill/mentions/blot.tsx @@ -1,7 +1,7 @@ // Copyright 2020 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import React from 'react'; +import React, { StrictMode } from 'react'; import EmbedBlot from '@signalapp/quill-cjs/blots/embed'; import { render } from 'react-dom'; @@ -47,14 +47,16 @@ export class MentionBlot extends EmbedBlot { const mentionSpan = document.createElement('span'); render( - - - - @ - - - - , + + + + + @ + + + + + , mentionSpan ); diff --git a/ts/shims/renderClearingDataView.tsx b/ts/shims/renderClearingDataView.tsx index 80a99614b4..3a3d142852 100644 --- a/ts/shims/renderClearingDataView.tsx +++ b/ts/shims/renderClearingDataView.tsx @@ -1,7 +1,7 @@ // Copyright 2021 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import React from 'react'; +import React, { StrictMode } from 'react'; import { render } from 'react-dom'; import { ClearingData } from '../components/ClearingData'; @@ -10,9 +10,11 @@ import { FunDefaultEnglishEmojiLocalizationProvider } from '../components/fun/Fu export function renderClearingDataView(): void { render( - - - , + + + + + , document.getElementById('app-container') ); } diff --git a/ts/util/longRunningTaskWrapper.tsx b/ts/util/longRunningTaskWrapper.tsx index 81931e94cb..ea06de9053 100644 --- a/ts/util/longRunningTaskWrapper.tsx +++ b/ts/util/longRunningTaskWrapper.tsx @@ -1,7 +1,7 @@ // Copyright 2021 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import React from 'react'; +import React, { StrictMode } from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; import * as Errors from '../types/errors'; @@ -33,9 +33,11 @@ export async function longRunningTaskWrapper({ log.info(`longRunningTaskWrapper/${idLog}: Creating spinner`); render( - - - , + + + + + , progressNode ); spinnerStart = Date.now(); diff --git a/ts/util/showConfirmationDialog.tsx b/ts/util/showConfirmationDialog.tsx index d7dd94c5dc..7e9564fed8 100644 --- a/ts/util/showConfirmationDialog.tsx +++ b/ts/util/showConfirmationDialog.tsx @@ -1,7 +1,7 @@ // Copyright 2015 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import React from 'react'; +import React, { StrictMode } from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; import { ConfirmationDialog } from '../components/ConfirmationDialog'; import { FunDefaultEnglishEmojiLocalizationProvider } from '../components/fun/FunEmojiLocalizationProvider'; @@ -56,37 +56,39 @@ export function showConfirmationDialog( confirmationDialogPreviousFocus = document.activeElement as HTMLElement; render( - - { - options.resolve(); + + + { + options.resolve(); + }, + style: options.confirmStyle, + text: options.okText || window.i18n('icu:ok'), }, - style: options.confirmStyle, - text: options.okText || window.i18n('icu:ok'), - }, - ]} - cancelText={options.cancelText || window.i18n('icu:cancel')} - i18n={window.i18n} - onCancel={() => { - if (options.reject) { - options.reject( - new Error('showConfirmationDialog: onCancel called') - ); - } - }} - onClose={() => { - removeConfirmationDialog(); - }} - title={options.title} - noMouseClose={options.noMouseClose} - > - {options.description} - - , + ]} + cancelText={options.cancelText || window.i18n('icu:cancel')} + i18n={window.i18n} + onCancel={() => { + if (options.reject) { + options.reject( + new Error('showConfirmationDialog: onCancel called') + ); + } + }} + onClose={() => { + removeConfirmationDialog(); + }} + title={options.title} + noMouseClose={options.noMouseClose} + > + {options.description} + + +
, confirmationDialogViewNode ); } diff --git a/ts/windows/about/app.tsx b/ts/windows/about/app.tsx index fb05e129b3..2c4feb2646 100644 --- a/ts/windows/about/app.tsx +++ b/ts/windows/about/app.tsx @@ -1,7 +1,7 @@ // Copyright 2023 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import React from 'react'; +import React, { StrictMode } from 'react'; import ReactDOM from 'react-dom'; import { About } from '../../components/About'; @@ -14,15 +14,17 @@ const { AboutWindowProps } = window.Signal; strictAssert(AboutWindowProps, 'window values not provided'); ReactDOM.render( - - window.SignalContext.executeMenuRole('close')} - appEnv={AboutWindowProps.appEnv} - platform={AboutWindowProps.platform} - arch={AboutWindowProps.arch} - i18n={i18n} - version={window.SignalContext.getVersion()} - /> - , + + + window.SignalContext.executeMenuRole('close')} + appEnv={AboutWindowProps.appEnv} + platform={AboutWindowProps.platform} + arch={AboutWindowProps.arch} + i18n={i18n} + version={window.SignalContext.getVersion()} + /> + + , document.getElementById('app') ); diff --git a/ts/windows/debuglog/app.tsx b/ts/windows/debuglog/app.tsx index 44899c7cc3..3483403641 100644 --- a/ts/windows/debuglog/app.tsx +++ b/ts/windows/debuglog/app.tsx @@ -1,7 +1,7 @@ // Copyright 2023 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import React from 'react'; +import React, { StrictMode } from 'react'; import { render } from 'react-dom'; import { DebugLogWindow } from '../../components/DebugLogWindow'; import { FunDefaultEnglishEmojiLocalizationProvider } from '../../components/fun/FunEmojiLocalizationProvider'; @@ -13,14 +13,16 @@ const { DebugLogWindowProps } = window.Signal; strictAssert(DebugLogWindowProps, 'window values not provided'); render( - - window.SignalContext.executeMenuRole('close')} - downloadLog={DebugLogWindowProps.downloadLog} - i18n={i18n} - fetchLogs={DebugLogWindowProps.fetchLogs} - uploadLogs={DebugLogWindowProps.uploadLogs} - /> - , + + + window.SignalContext.executeMenuRole('close')} + downloadLog={DebugLogWindowProps.downloadLog} + i18n={i18n} + fetchLogs={DebugLogWindowProps.fetchLogs} + uploadLogs={DebugLogWindowProps.uploadLogs} + /> + + , document.getElementById('app') ); diff --git a/ts/windows/permissions/app.tsx b/ts/windows/permissions/app.tsx index bf89d22248..466a54363c 100644 --- a/ts/windows/permissions/app.tsx +++ b/ts/windows/permissions/app.tsx @@ -1,7 +1,7 @@ // Copyright 2023 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import React from 'react'; +import React, { StrictMode } from 'react'; import ReactDOM from 'react-dom'; import { PermissionsPopup } from '../../components/PermissionsPopup'; @@ -27,13 +27,15 @@ if (forCalling) { } ReactDOM.render( - - - , + + + + + , document.getElementById('app') ); diff --git a/ts/windows/screenShare/app.tsx b/ts/windows/screenShare/app.tsx index 1dc1a89593..8ab18e7d1a 100644 --- a/ts/windows/screenShare/app.tsx +++ b/ts/windows/screenShare/app.tsx @@ -1,7 +1,7 @@ // Copyright 2023 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import React from 'react'; +import React, { StrictMode } from 'react'; import ReactDOM from 'react-dom'; import { CallingScreenSharingController } from '../../components/CallingScreenSharingController'; @@ -29,17 +29,19 @@ function render() { strictAssert(ScreenShareWindowProps, 'window values not provided'); ReactDOM.render( - -
- -
-
, + + +
+ +
+
+
, document.getElementById('app') ); diff --git a/ts/windows/settings/app.tsx b/ts/windows/settings/app.tsx index bda771947f..61a9ba9bd2 100644 --- a/ts/windows/settings/app.tsx +++ b/ts/windows/settings/app.tsx @@ -1,7 +1,7 @@ // Copyright 2023 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import React from 'react'; +import React, { StrictMode } from 'react'; import ReactDOM from 'react-dom'; import type { PropsPreloadType } from '../../components/Preferences'; @@ -135,122 +135,124 @@ SettingsWindowProps.onRender( zoomFactor, }: PropsPreloadType) => { ReactDOM.render( - , + + + , document.getElementById('app') ); }