Upgrade to React 18
This commit is contained in:
parent
560dcb91d9
commit
14d098f40f
46 changed files with 1210 additions and 1796 deletions
|
@ -6,7 +6,6 @@ module.exports = {
|
|||
// Detects the type of file being babel'd (either esmodule or commonjs)
|
||||
sourceType: 'unambiguous',
|
||||
plugins: [
|
||||
'react-hot-loader/babel',
|
||||
'lodash',
|
||||
'@babel/plugin-transform-typescript',
|
||||
'@babel/plugin-proposal-class-properties',
|
||||
|
|
|
@ -3882,30 +3882,6 @@ Signal Desktop makes use of the following open source projects.
|
|||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
## react-hot-loader
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016 Dan Abramov
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
## react-intl
|
||||
|
||||
Copyright 2019 Oath Inc.
|
||||
|
@ -3984,53 +3960,6 @@ Signal Desktop makes use of the following open source projects.
|
|||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
## react-router-dom
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) React Training 2016-2018
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
## react-textarea-autosize
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013 Andrey Popp
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
## react-virtualized
|
||||
|
||||
The MIT License (MIT)
|
||||
|
|
25
package.json
25
package.json
|
@ -176,19 +176,16 @@
|
|||
"protobufjs": "7.3.2",
|
||||
"proxy-agent": "6.4.0",
|
||||
"qrcode-generator": "1.4.4",
|
||||
"react": "17.0.2",
|
||||
"react": "18.3.1",
|
||||
"react-aria": "3.35.1",
|
||||
"react-aria-components": "1.4.1",
|
||||
"react-blurhash": "0.3.0",
|
||||
"react-contextmenu": "2.14.0",
|
||||
"react-dom": "17.0.2",
|
||||
"react-hot-loader": "4.13.1",
|
||||
"react-intl": "6.8.7",
|
||||
"react-dom": "18.3.1",
|
||||
"react-intl": "7.1.11",
|
||||
"react-popper": "2.3.0",
|
||||
"react-redux": "8.1.3",
|
||||
"react-router-dom": "5.0.1",
|
||||
"react-textarea-autosize": "8.5.5",
|
||||
"react-virtualized": "9.22.5",
|
||||
"react-redux": "9.2.0",
|
||||
"react-virtualized": "9.22.6",
|
||||
"read-last-lines": "1.8.0",
|
||||
"redux": "5.0.1",
|
||||
"redux-logger": "3.0.6",
|
||||
|
@ -267,8 +264,7 @@
|
|||
"@types/react": "17.0.45",
|
||||
"@types/react-dom": "17.0.17",
|
||||
"@types/react-redux": "7.1.34",
|
||||
"@types/react-router-dom": "4.3.4",
|
||||
"@types/react-virtualized": "9.21.30",
|
||||
"@types/react-virtualized": "9.22.2",
|
||||
"@types/redux-logger": "3.0.13",
|
||||
"@types/semver": "7.5.8",
|
||||
"@types/sinon": "17.0.3",
|
||||
|
@ -348,13 +344,15 @@
|
|||
"pnpm": {
|
||||
"overrides": {
|
||||
"@storybook/core>node-fetch": "$node-fetch",
|
||||
"@types/react": "17.0.45",
|
||||
"@types/react-dom": "17.0.17",
|
||||
"@types/react": "18.3.20",
|
||||
"@types/react-dom": "18.3.6",
|
||||
"eslint-config-airbnb-typescript-prettier>eslint-plugin-prettier": "5.2.1",
|
||||
"canvas": "-",
|
||||
"jsdom": "-",
|
||||
"thenify-all>thenify": "3.3.1",
|
||||
"@electron/rebuild@3.7.0>@electron/node-gyp": "10.2.0-electron.2"
|
||||
"@electron/rebuild@3.7.0>@electron/node-gyp": "10.2.0-electron.2",
|
||||
"react-contextmenu>react": "18.3.1",
|
||||
"react-contextmenu>react-dom": "18.3.1"
|
||||
},
|
||||
"patchedDependencies": {
|
||||
"@types/backbone@1.4.22": "patches/@types+backbone+1.4.22.patch",
|
||||
|
@ -369,7 +367,6 @@
|
|||
"react-contextmenu@2.14.0": "patches/react-contextmenu+2.14.0.patch",
|
||||
"@vitest/expect@2.0.5": "patches/@vitest+expect+2.0.5.patch",
|
||||
"got@11.8.5": "patches/got+11.8.5.patch",
|
||||
"react-textarea-autosize@8.5.5": "patches/react-textarea-autosize+8.5.5.patch",
|
||||
"growing-file@0.1.3": "patches/growing-file+0.1.3.patch",
|
||||
"websocket@1.0.34": "patches/websocket+1.0.34.patch",
|
||||
"@types/websocket@1.0.0": "patches/@types+websocket+1.0.0.patch",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
diff --git a/modules/ContextMenu.js b/modules/ContextMenu.js
|
||||
index 2f88213..41e47ea 100644
|
||||
index 2f8821393f15a1ce85132385688f08cd6e390bf4..41e47ea740636f81bdd484a7093d0ea3169eb9d5 100644
|
||||
--- a/modules/ContextMenu.js
|
||||
+++ b/modules/ContextMenu.js
|
||||
@@ -81,6 +81,11 @@ var ContextMenu = function (_AbstractMenu) {
|
||||
|
@ -53,7 +53,7 @@ index 2f88213..41e47ea 100644
|
|||
}
|
||||
}
|
||||
diff --git a/modules/SubMenu.js b/modules/SubMenu.js
|
||||
index ad1dc70..c919be8 100644
|
||||
index ad1dc7043c13cbc30f1659d5b82696ed974c996a..c919be8d12329dd5bcf77d3660b85edb83714bb8 100644
|
||||
--- a/modules/SubMenu.js
|
||||
+++ b/modules/SubMenu.js
|
||||
@@ -129,6 +129,7 @@ var SubMenu = function (_AbstractMenu) {
|
||||
|
@ -142,14 +142,45 @@ index ad1dc70..c919be8 100644
|
|||
}
|
||||
}
|
||||
diff --git a/src/index.d.ts b/src/index.d.ts
|
||||
index 753ce90..c5971a4 100644
|
||||
index 753ce9081490fd90b4354e6e73937dc85957689c..e8a8b0815a7ca61ef9bc488299cda08e181267bc 100644
|
||||
--- a/src/index.d.ts
|
||||
+++ b/src/index.d.ts
|
||||
@@ -14,6 +14,7 @@ declare module "react-contextmenu" {
|
||||
@@ -14,6 +14,8 @@ declare module "react-contextmenu" {
|
||||
preventHideOnResize?: boolean,
|
||||
preventHideOnScroll?: boolean,
|
||||
preventHideOnScroll?: boolean,
|
||||
style?: React.CSSProperties,
|
||||
+ avoidFocusRestoreOnBlur?: boolean;
|
||||
+ children?: React.ReactNode;
|
||||
}
|
||||
|
||||
export interface ContextMenuTriggerProps {
|
||||
@@ -25,6 +27,7 @@ declare module "react-contextmenu" {
|
||||
renderTag?: React.ElementType,
|
||||
mouseButton?: number,
|
||||
disableIfShiftIsPressed?: boolean,
|
||||
+ children?: React.ReactNode,
|
||||
}
|
||||
|
||||
export interface MenuItemProps {
|
||||
@@ -35,6 +38,7 @@ declare module "react-contextmenu" {
|
||||
divider?: boolean,
|
||||
preventClose?: boolean,
|
||||
onClick?: {(event: React.TouchEvent<HTMLDivElement> | React.MouseEvent<HTMLDivElement>, data: Object, target: HTMLElement): void} | Function,
|
||||
+ children?: React.ReactNode,
|
||||
}
|
||||
|
||||
export interface SubMenuProps {
|
||||
@@ -45,11 +49,13 @@ declare module "react-contextmenu" {
|
||||
rtl?: boolean,
|
||||
preventCloseOnClick?: boolean,
|
||||
onClick?: {(event: React.TouchEvent<HTMLDivElement> | React.MouseEvent<HTMLDivElement>, data: Object, target: HTMLElement): void} | Function,
|
||||
+ children?: React.ReactNode,
|
||||
}
|
||||
|
||||
export interface ConnectMenuProps {
|
||||
id: string;
|
||||
trigger: any;
|
||||
+ children?: React.ReactNode;
|
||||
}
|
||||
|
||||
export const ContextMenu: React.ComponentClass<ContextMenuProps>;
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
diff --git a/dist/react-textarea-autosize.browser.cjs.js b/dist/react-textarea-autosize.browser.cjs.js
|
||||
index 37d2acb..7f76a65 100644
|
||||
--- a/dist/react-textarea-autosize.browser.cjs.js
|
||||
+++ b/dist/react-textarea-autosize.browser.cjs.js
|
||||
@@ -122,7 +122,7 @@ var SIZING_STYLE = ['borderBottomWidth', 'borderLeftWidth', 'borderRightWidth',
|
||||
'tabSize', 'textIndent',
|
||||
// non-standard
|
||||
'textRendering', 'textTransform', 'width', 'wordBreak', 'wordSpacing', 'scrollbarGutter'];
|
||||
-var isIE = !!document.documentElement.currentStyle ;
|
||||
+var isIE = false;
|
||||
var getSizingData = function getSizingData(node) {
|
||||
var style = window.getComputedStyle(node);
|
||||
if (style === null) {
|
||||
diff --git a/dist/react-textarea-autosize.browser.development.cjs.js b/dist/react-textarea-autosize.browser.development.cjs.js
|
||||
index 51e50d5..29a11e3 100644
|
||||
--- a/dist/react-textarea-autosize.browser.development.cjs.js
|
||||
+++ b/dist/react-textarea-autosize.browser.development.cjs.js
|
||||
@@ -122,7 +122,7 @@ var SIZING_STYLE = ['borderBottomWidth', 'borderLeftWidth', 'borderRightWidth',
|
||||
'tabSize', 'textIndent',
|
||||
// non-standard
|
||||
'textRendering', 'textTransform', 'width', 'wordBreak', 'wordSpacing', 'scrollbarGutter'];
|
||||
-var isIE = !!document.documentElement.currentStyle ;
|
||||
+var isIE = false;
|
||||
var getSizingData = function getSizingData(node) {
|
||||
var style = window.getComputedStyle(node);
|
||||
if (style === null) {
|
||||
diff --git a/dist/react-textarea-autosize.browser.development.esm.js b/dist/react-textarea-autosize.browser.development.esm.js
|
||||
index bbaa14c..4eac3f8 100644
|
||||
--- a/dist/react-textarea-autosize.browser.development.esm.js
|
||||
+++ b/dist/react-textarea-autosize.browser.development.esm.js
|
||||
@@ -94,7 +94,7 @@ var SIZING_STYLE = ['borderBottomWidth', 'borderLeftWidth', 'borderRightWidth',
|
||||
'tabSize', 'textIndent',
|
||||
// non-standard
|
||||
'textRendering', 'textTransform', 'width', 'wordBreak', 'wordSpacing', 'scrollbarGutter'];
|
||||
-var isIE = !!document.documentElement.currentStyle ;
|
||||
+var isIE = false;
|
||||
var getSizingData = function getSizingData(node) {
|
||||
var style = window.getComputedStyle(node);
|
||||
if (style === null) {
|
||||
diff --git a/dist/react-textarea-autosize.browser.esm.js b/dist/react-textarea-autosize.browser.esm.js
|
||||
index 7376e08..196b550 100644
|
||||
--- a/dist/react-textarea-autosize.browser.esm.js
|
||||
+++ b/dist/react-textarea-autosize.browser.esm.js
|
||||
@@ -94,7 +94,7 @@ var SIZING_STYLE = ['borderBottomWidth', 'borderLeftWidth', 'borderRightWidth',
|
||||
'tabSize', 'textIndent',
|
||||
// non-standard
|
||||
'textRendering', 'textTransform', 'width', 'wordBreak', 'wordSpacing', 'scrollbarGutter'];
|
||||
-var isIE = !!document.documentElement.currentStyle ;
|
||||
+var isIE = false;
|
||||
var getSizingData = function getSizingData(node) {
|
||||
var style = window.getComputedStyle(node);
|
||||
if (style === null) {
|
2243
pnpm-lock.yaml
generated
2243
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
|
@ -48,6 +48,7 @@
|
|||
resize: none;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
field-sizing: content;
|
||||
|
||||
&:disabled {
|
||||
color: inherit;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright 2024 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type { ChangeEvent, KeyboardEvent } from 'react';
|
||||
import React, { useCallback, useState, useEffect, useRef } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import classNames from 'classnames';
|
||||
|
@ -35,14 +36,14 @@ export function AutoSizeInput({
|
|||
const getClassName = getClassNamesFor('AutoSizeInput', moduleClassName);
|
||||
|
||||
const handleChange = useCallback(
|
||||
e => {
|
||||
(e: ChangeEvent<HTMLInputElement>) => {
|
||||
onChange(e.target.value);
|
||||
},
|
||||
[onChange]
|
||||
);
|
||||
|
||||
const handleKeyDown = useCallback(
|
||||
event => {
|
||||
(event: KeyboardEvent) => {
|
||||
if (onEnter && event.key === 'Enter') {
|
||||
onEnter();
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ export function AvatarEditor({
|
|||
const [editMode, setEditMode] = useState<EditMode>(EditMode.Main);
|
||||
|
||||
const getSelectedAvatar = useCallback(
|
||||
avatarToFind =>
|
||||
(avatarToFind: AvatarDataType | undefined) =>
|
||||
localAvatarData.find(avatarData =>
|
||||
isSameAvatarData(avatarData, avatarToFind)
|
||||
),
|
||||
|
@ -146,7 +146,7 @@ export function AvatarEditor({
|
|||
]
|
||||
);
|
||||
|
||||
const handleAvatarLoaded = useCallback(avatarBuffer => {
|
||||
const handleAvatarLoaded = useCallback((avatarBuffer: Uint8Array) => {
|
||||
setAvatarPreview(avatarBuffer);
|
||||
setInitialAvatar(avatarBuffer);
|
||||
}, []);
|
||||
|
|
|
@ -180,14 +180,14 @@ export function CallsNewCall({
|
|||
}, [directConversations, groupConversations]);
|
||||
|
||||
const isRowLoaded = useCallback(
|
||||
({ index }) => {
|
||||
({ index }: { index: number }) => {
|
||||
return rows.at(index) != null;
|
||||
},
|
||||
[rows]
|
||||
);
|
||||
|
||||
const rowHeight = useCallback(
|
||||
({ index }) => {
|
||||
({ index }: { index: number }) => {
|
||||
if (rows.at(index)?.kind === 'conversation') {
|
||||
return ListTile.heightCompact;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import * as React from 'react';
|
||||
import type { MouseEvent } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { Manager, Reference } from 'react-popper';
|
||||
import Quill, { Delta } from '@signalapp/quill-cjs';
|
||||
|
@ -950,7 +951,7 @@ export function CompositionInput(props: Props): React.ReactElement {
|
|||
const getClassName = getClassNamesFor(BASE_CLASS_NAME, moduleClassName);
|
||||
|
||||
const onMouseDown = React.useCallback(
|
||||
event => {
|
||||
(event: MouseEvent) => {
|
||||
const target = event.target as HTMLElement;
|
||||
try {
|
||||
// If the user is actually clicking the format menu, we drop this event
|
||||
|
|
|
@ -7,9 +7,10 @@ import type { EmojiPickDataType } from './emoji/EmojiPicker';
|
|||
import type { InputApi } from './CompositionInput';
|
||||
import { CompositionInput } from './CompositionInput';
|
||||
import { EmojiButton } from './emoji/EmojiButton';
|
||||
import type {
|
||||
DraftBodyRanges,
|
||||
HydratedBodyRangesType,
|
||||
import {
|
||||
hydrateRanges,
|
||||
type DraftBodyRanges,
|
||||
type HydratedBodyRangesType,
|
||||
} from '../types/BodyRange';
|
||||
import type { ThemeType } from '../types/Util';
|
||||
import type { Props as EmojiButtonProps } from './emoji/EmojiButton';
|
||||
|
@ -20,6 +21,7 @@ import type { FunEmojiSelection } from './fun/panels/FunPanelEmojis';
|
|||
import type { EmojiSkinTone } from './fun/data/emojis';
|
||||
import { FunEmojiPickerButton } from './fun/FunButton';
|
||||
import { isFunPickerEnabled } from './fun/isFunPickerEnabled';
|
||||
import type { GetConversationByIdType } from '../state/selectors/conversations';
|
||||
|
||||
export type CompositionTextAreaProps = {
|
||||
bodyRanges: HydratedBodyRangesType | null;
|
||||
|
@ -48,6 +50,7 @@ export type CompositionTextAreaProps = {
|
|||
getPreferredBadge: PreferredBadgeSelectorType;
|
||||
draftText: string;
|
||||
theme: ThemeType;
|
||||
conversationSelector: GetConversationByIdType;
|
||||
} & Pick<EmojiButtonProps, 'recentEmojis' | 'emojiSkinToneDefault'>;
|
||||
|
||||
/**
|
||||
|
@ -78,6 +81,7 @@ export function CompositionTextArea({
|
|||
emojiSkinToneDefault,
|
||||
theme,
|
||||
whenToShowRemainingCount = Infinity,
|
||||
conversationSelector,
|
||||
}: CompositionTextAreaProps): JSX.Element {
|
||||
const inputApiRef = useRef<InputApi | undefined>();
|
||||
const [characterCount, setCharacterCount] = useState(
|
||||
|
@ -128,6 +132,10 @@ export function CompositionTextArea({
|
|||
bodyRanges: updatedBodyRanges,
|
||||
caretLocation,
|
||||
messageText: newValue,
|
||||
}: {
|
||||
bodyRanges: DraftBodyRanges;
|
||||
caretLocation?: number | undefined;
|
||||
messageText: string;
|
||||
}) => {
|
||||
const inputEl = inputApiRef.current;
|
||||
if (!inputEl) {
|
||||
|
@ -139,6 +147,9 @@ export function CompositionTextArea({
|
|||
maxLength
|
||||
);
|
||||
|
||||
const hydratedBodyRanges =
|
||||
hydrateRanges(updatedBodyRanges, conversationSelector) ?? [];
|
||||
|
||||
if (maxLength !== undefined) {
|
||||
// if we had to truncate
|
||||
if (newValueSized.length < newValue.length) {
|
||||
|
@ -149,13 +160,13 @@ export function CompositionTextArea({
|
|||
// was modifying text in the middle of the editor
|
||||
// a better solution would be to prevent the change to begin with, but
|
||||
// quill makes this VERY difficult
|
||||
inputEl.setContents(newValueSized, updatedBodyRanges, true);
|
||||
inputEl.setContents(newValueSized, hydratedBodyRanges, true);
|
||||
}
|
||||
}
|
||||
setCharacterCount(newCharacterCount);
|
||||
onChange(newValue, updatedBodyRanges, caretLocation);
|
||||
onChange(newValue, hydratedBodyRanges, caretLocation);
|
||||
},
|
||||
[maxLength, onChange]
|
||||
[maxLength, onChange, conversationSelector]
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -14,6 +14,7 @@ import { EmojiSkinTone } from './fun/data/emojis';
|
|||
import { LoadingState } from '../util/loadable';
|
||||
import { VIDEO_MP4 } from '../types/MIME';
|
||||
import { drop } from '../util/drop';
|
||||
import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation';
|
||||
|
||||
const { i18n } = window.SignalContext;
|
||||
|
||||
|
@ -38,6 +39,7 @@ function RenderCompositionTextArea(props: SmartCompositionTextAreaProps) {
|
|||
ourConversationId="me"
|
||||
platform="darwin"
|
||||
emojiSkinToneDefault={EmojiSkinTone.None}
|
||||
conversationSelector={() => getDefaultConversation()}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2025 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
import React, { type ComponentType, useEffect, useMemo } from 'react';
|
||||
import { useId, VisuallyHidden } from 'react-aria';
|
||||
import React, { type ComponentType, useEffect, useMemo, useId } from 'react';
|
||||
import { VisuallyHidden } from 'react-aria';
|
||||
import type { LocalizerType } from '../types/I18N';
|
||||
import { Button, ButtonVariant } from './Button';
|
||||
import { Modal } from './Modal';
|
||||
|
|
|
@ -70,6 +70,7 @@ const useProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
|||
ourConversationId="me"
|
||||
platform="darwin"
|
||||
emojiSkinToneDefault={EmojiSkinTone.None}
|
||||
conversationSelector={() => getDefaultConversation()}
|
||||
/>
|
||||
),
|
||||
showToast: action('showToast'),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type { ClipboardEvent, ReactNode } from 'react';
|
||||
import type { ClipboardEvent, KeyboardEvent, ReactNode } from 'react';
|
||||
import React, {
|
||||
forwardRef,
|
||||
useCallback,
|
||||
|
@ -114,7 +114,7 @@ export const Input = forwardRef<
|
|||
}, [expandable]);
|
||||
|
||||
const handleKeyDown = useCallback(
|
||||
event => {
|
||||
(event: KeyboardEvent) => {
|
||||
if (onEnter && event.key === 'Enter') {
|
||||
onEnter();
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
import React, {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useId,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
|
@ -27,7 +28,6 @@ import type { LocalizerType } from '../types/Util';
|
|||
import type { MIMEType } from '../types/MIME';
|
||||
import type { Props as StickerButtonProps } from './stickers/StickerButton';
|
||||
import type { imageToBlurHash } from '../util/imageToBlurHash';
|
||||
|
||||
import { MediaEditorFabricAnalogTimeSticker } from '../mediaEditor/MediaEditorFabricAnalogTimeSticker';
|
||||
import { MediaEditorFabricCropRect } from '../mediaEditor/MediaEditorFabricCropRect';
|
||||
import { MediaEditorFabricDigitalTimeSticker } from '../mediaEditor/MediaEditorFabricDigitalTimeSticker';
|
||||
|
@ -60,7 +60,6 @@ import { hydrateRanges } from '../types/BodyRange';
|
|||
import { useConfirmDiscard } from '../hooks/useConfirmDiscard';
|
||||
import { useFabricHistory } from '../mediaEditor/useFabricHistory';
|
||||
import { usePortal } from '../hooks/usePortal';
|
||||
import { useUniqueId } from '../hooks/useUniqueId';
|
||||
import { isFunPickerEnabled } from './fun/isFunPickerEnabled';
|
||||
import { FunEmojiPicker } from './fun/FunEmojiPicker';
|
||||
import { FunEmojiPickerButton, FunStickerPickerButton } from './fun/FunButton';
|
||||
|
@ -195,7 +194,7 @@ export function MediaEditor({
|
|||
|
||||
const inputApiRef = useRef<InputApi | undefined>();
|
||||
|
||||
const canvasId = useUniqueId();
|
||||
const canvasId = useId();
|
||||
|
||||
const [imageState, setImageState] =
|
||||
useState<ImageStateType>(INITIAL_IMAGE_STATE);
|
||||
|
@ -237,7 +236,7 @@ export function MediaEditor({
|
|||
);
|
||||
|
||||
const handlePickSticker = useCallback(
|
||||
(_packId, _stickerId, src: string) => {
|
||||
(_packId: string, _stickerId: number, src: string) => {
|
||||
async function run() {
|
||||
if (!fabricCanvas) {
|
||||
return;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2023 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type { Key } from 'react';
|
||||
import type { Key, ReactNode } from 'react';
|
||||
import React from 'react';
|
||||
import { Tabs, TabList, Tab, TabPanel } from 'react-aria-components';
|
||||
import classNames from 'classnames';
|
||||
|
@ -189,12 +189,12 @@ export type NavTabsProps = Readonly<{
|
|||
navTabsCollapsed: boolean;
|
||||
onShowSettings: () => void;
|
||||
onStartUpdate: () => unknown;
|
||||
onNavTabSelected(tab: NavTab): void;
|
||||
onToggleNavTabsCollapse(collapsed: boolean): void;
|
||||
onNavTabSelected: (tab: NavTab) => void;
|
||||
onToggleNavTabsCollapse: (collapsed: boolean) => void;
|
||||
onToggleProfileEditor: () => void;
|
||||
renderCallsTab(props: NavTabPanelProps): JSX.Element;
|
||||
renderChatsTab(props: NavTabPanelProps): JSX.Element;
|
||||
renderStoriesTab(props: NavTabPanelProps): JSX.Element;
|
||||
renderCallsTab: () => ReactNode;
|
||||
renderChatsTab: () => ReactNode;
|
||||
renderStoriesTab: () => ReactNode;
|
||||
selectedNavTab: NavTab;
|
||||
storiesEnabled: boolean;
|
||||
theme: ThemeType;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type { AudioDevice } from '@signalapp/ringrtc';
|
||||
import React, {
|
||||
useCallback,
|
||||
|
@ -8,11 +7,11 @@ import React, {
|
|||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
useId,
|
||||
} from 'react';
|
||||
import { noop, partition } from 'lodash';
|
||||
import classNames from 'classnames';
|
||||
import * as LocaleMatcher from '@formatjs/intl-localematcher';
|
||||
|
||||
import type { MediaDeviceSettings } from '../types/Calling';
|
||||
import type { ValidationResultType as BackupValidationResultType } from '../services/backups';
|
||||
import type {
|
||||
|
@ -35,12 +34,10 @@ import type {
|
|||
SentMediaQualityType,
|
||||
ThemeType,
|
||||
} from '../types/Util';
|
||||
|
||||
import { Button, ButtonVariant } from './Button';
|
||||
import { ChatColorPicker } from './ChatColorPicker';
|
||||
import { Checkbox } from './Checkbox';
|
||||
import { WidthBreakpoint } from './_util';
|
||||
|
||||
import { ConfirmationDialog } from './ConfirmationDialog';
|
||||
import { DisappearingTimeDialog } from './DisappearingTimeDialog';
|
||||
import { PhoneNumberDiscoverability } from '../util/phoneNumberDiscoverability';
|
||||
|
@ -57,7 +54,6 @@ import {
|
|||
} from '../util/expirationTimer';
|
||||
import { DurationInSeconds } from '../util/durations';
|
||||
import { useEscapeHandling } from '../hooks/useEscapeHandling';
|
||||
import { useUniqueId } from '../hooks/useUniqueId';
|
||||
import { focusableSelector } from '../util/focusableSelectors';
|
||||
import { Modal } from './Modal';
|
||||
import { SearchInput } from './SearchInput';
|
||||
|
@ -384,10 +380,10 @@ export function Preferences({
|
|||
whoCanSeeMe,
|
||||
zoomFactor,
|
||||
}: PropsType): JSX.Element {
|
||||
const storiesId = useUniqueId();
|
||||
const themeSelectId = useUniqueId();
|
||||
const zoomSelectId = useUniqueId();
|
||||
const languageId = useUniqueId();
|
||||
const storiesId = useId();
|
||||
const themeSelectId = useId();
|
||||
const zoomSelectId = useId();
|
||||
const languageId = useId();
|
||||
|
||||
const [confirmDelete, setConfirmDelete] = useState(false);
|
||||
const [confirmStoriesOff, setConfirmStoriesOff] = useState(false);
|
||||
|
|
|
@ -352,7 +352,7 @@ export function ProfileEditor({
|
|||
|
||||
// To make AvatarEditor re-render less often
|
||||
const handleAvatarLoaded = useCallback(
|
||||
avatar => {
|
||||
(avatar: Uint8Array) => {
|
||||
setAvatarBuffer(avatar);
|
||||
setOldAvatarBuffer(avatar);
|
||||
},
|
||||
|
|
|
@ -1,31 +1,16 @@
|
|||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type { ReactNode } from 'react';
|
||||
import type { ProfilerOnRenderCallback, ReactNode } from 'react';
|
||||
import React from 'react';
|
||||
import * as log from '../logging/log';
|
||||
|
||||
type InternalPropsType = Readonly<{
|
||||
id: string;
|
||||
children: ReactNode;
|
||||
|
||||
onRender(
|
||||
id: string,
|
||||
phase: 'mount' | 'update',
|
||||
actualDuration: number,
|
||||
baseDuration: number,
|
||||
startTime: number,
|
||||
commitTime: number,
|
||||
interactions: Set<unknown>
|
||||
): void;
|
||||
}>;
|
||||
|
||||
export type PropsType = Readonly<{
|
||||
id: string;
|
||||
children: ReactNode;
|
||||
}>;
|
||||
|
||||
const onRender: InternalPropsType['onRender'] = (
|
||||
const onRender: ProfilerOnRenderCallback = (
|
||||
id,
|
||||
phase,
|
||||
actual,
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import React, { forwardRef, useEffect, useRef, useState } from 'react';
|
||||
import TextareaAutosize from 'react-textarea-autosize';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import type { LocalizerType, RenderTextCallbackType } from '../types/Util';
|
||||
|
@ -241,7 +240,7 @@ export const TextAttachment = forwardRef<HTMLTextAreaElement, PropsType>(
|
|||
}}
|
||||
>
|
||||
{onChange ? (
|
||||
<TextareaAutosize
|
||||
<textarea
|
||||
dir="auto"
|
||||
className="TextAttachment__text__container TextAttachment__text__textarea"
|
||||
disabled={!isEditingText}
|
||||
|
|
|
@ -538,30 +538,27 @@ export function TextStoryCreator({
|
|||
data-popper-arrow
|
||||
className="StoryCreator__popper__arrow"
|
||||
/>
|
||||
{objectMap<BackgroundStyleType>(
|
||||
BackgroundStyle,
|
||||
(bg, backgroundValue) => (
|
||||
<button
|
||||
aria-label={i18n('icu:StoryCreator__story-bg')}
|
||||
className={classNames({
|
||||
StoryCreator__bg: true,
|
||||
'StoryCreator__bg--selected':
|
||||
selectedBackground === backgroundValue,
|
||||
})}
|
||||
key={String(bg)}
|
||||
onClick={() => {
|
||||
setSelectedBackground(backgroundValue);
|
||||
setIsColorPickerShowing(false);
|
||||
}}
|
||||
type="button"
|
||||
style={{
|
||||
background: getBackgroundColor(
|
||||
getBackground(backgroundValue)
|
||||
),
|
||||
}}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
{objectMap(BackgroundStyle, (bg, backgroundValue) => (
|
||||
<button
|
||||
aria-label={i18n('icu:StoryCreator__story-bg')}
|
||||
className={classNames({
|
||||
StoryCreator__bg: true,
|
||||
'StoryCreator__bg--selected':
|
||||
selectedBackground === backgroundValue,
|
||||
})}
|
||||
key={String(bg)}
|
||||
onClick={() => {
|
||||
setSelectedBackground(backgroundValue);
|
||||
setIsColorPickerShowing(false);
|
||||
}}
|
||||
type="button"
|
||||
style={{
|
||||
background: getBackgroundColor(
|
||||
getBackground(backgroundValue)
|
||||
),
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
<button
|
||||
|
|
|
@ -182,7 +182,7 @@ export const VoiceNotesPlaybackContext =
|
|||
React.createContext<Contents>(globalContents);
|
||||
|
||||
export type VoiceNotesPlaybackProps = {
|
||||
children?: React.ReactNode | React.ReactChildren;
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -158,7 +158,7 @@ export function ImageGrid({
|
|||
);
|
||||
|
||||
const showAttachmentOrNoLongerAvailableToast = React.useCallback(
|
||||
attachmentIndex =>
|
||||
(attachmentIndex: number) =>
|
||||
attachments[attachmentIndex].isPermanentlyUndownloadable
|
||||
? showMediaNoLongerAvailableToast
|
||||
: showVisualAttachment,
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import React, { useMemo } from 'react';
|
||||
|
||||
import React, { useMemo, useId } from 'react';
|
||||
import type { ConversationTypeType } from '../../../state/ducks/conversations';
|
||||
import type { LocalizerType } from '../../../types/Util';
|
||||
import { PanelSection } from './PanelSection';
|
||||
|
@ -12,7 +11,6 @@ import { Select } from '../../Select';
|
|||
import { isConversationMuted } from '../../../util/isConversationMuted';
|
||||
import { getMuteOptions } from '../../../util/getMuteOptions';
|
||||
import { parseIntOrThrow } from '../../../util/parseIntOrThrow';
|
||||
import { useUniqueId } from '../../../hooks/useUniqueId';
|
||||
|
||||
export type PropsType = {
|
||||
id: string;
|
||||
|
@ -39,8 +37,8 @@ export function ConversationNotificationsSettings({
|
|||
setMuteExpiration,
|
||||
setDontNotifyForMentionsIfMuted,
|
||||
}: PropsType): JSX.Element {
|
||||
const muteNotificationsSelectId = useUniqueId();
|
||||
const mentionsSelectId = useUniqueId();
|
||||
const muteNotificationsSelectId = useId();
|
||||
const mentionsSelectId = useId();
|
||||
const muteOptions = useMemo(
|
||||
() => [
|
||||
...(isConversationMuted({ muteExpiresAt })
|
||||
|
|
|
@ -1,22 +1,17 @@
|
|||
// Copyright 2020 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import React, { useId, useState } from 'react';
|
||||
import type { ConversationType } from '../../../state/ducks/conversations';
|
||||
import type { LocalizerType } from '../../../types/Util';
|
||||
|
||||
import { ConfirmationDialog } from '../../ConfirmationDialog';
|
||||
import { ConversationDetailsIcon, IconType } from './ConversationDetailsIcon';
|
||||
import { PanelRow } from './PanelRow';
|
||||
import { PanelSection } from './PanelSection';
|
||||
import { Select } from '../../Select';
|
||||
import { SignalService as Proto } from '../../../protobuf';
|
||||
|
||||
import { copyGroupLink } from '../../../util/copyLinksWithToast';
|
||||
import { drop } from '../../../util/drop';
|
||||
import { useDelayedRestoreFocus } from '../../../hooks/useRestoreFocus';
|
||||
import { useUniqueId } from '../../../hooks/useUniqueId';
|
||||
|
||||
const AccessControlEnum = Proto.AccessControl.AccessRequired;
|
||||
|
||||
|
@ -43,8 +38,8 @@ export function GroupLinkManagement({
|
|||
isAdmin,
|
||||
setAccessControlAddFromInviteLinkSetting,
|
||||
}: PropsType): JSX.Element {
|
||||
const groupLinkSelectId = useUniqueId();
|
||||
const approveSelectId = useUniqueId();
|
||||
const groupLinkSelectId = useId();
|
||||
const approveSelectId = useId();
|
||||
|
||||
if (conversation === undefined) {
|
||||
throw new Error('GroupLinkManagement rendered without a conversation');
|
||||
|
|
|
@ -1,17 +1,13 @@
|
|||
// Copyright 2020 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import React, { useId } from 'react';
|
||||
import type { ConversationType } from '../../../state/ducks/conversations';
|
||||
import type { LocalizerType } from '../../../types/Util';
|
||||
import { getAccessControlOptions } from '../../../util/getAccessControlOptions';
|
||||
import { SignalService as Proto } from '../../../protobuf';
|
||||
|
||||
import { PanelRow } from './PanelRow';
|
||||
import { PanelSection } from './PanelSection';
|
||||
import { Select } from '../../Select';
|
||||
import { useUniqueId } from '../../../hooks/useUniqueId';
|
||||
|
||||
export type PropsDataType = {
|
||||
conversation?: ConversationType;
|
||||
|
@ -33,9 +29,9 @@ export function GroupV2Permissions({
|
|||
setAccessControlMembersSetting,
|
||||
setAnnouncementsOnly,
|
||||
}: PropsType): JSX.Element {
|
||||
const addMembersSelectId = useUniqueId();
|
||||
const groupInfoSelectId = useUniqueId();
|
||||
const announcementSelectId = useUniqueId();
|
||||
const addMembersSelectId = useId();
|
||||
const groupInfoSelectId = useId();
|
||||
const announcementSelectId = useId();
|
||||
|
||||
if (conversation === undefined) {
|
||||
throw new Error('GroupV2Permissions rendered without a conversation');
|
||||
|
|
|
@ -59,7 +59,7 @@ export function AttachmentSection({
|
|||
/>
|
||||
);
|
||||
default:
|
||||
return missingCaseError(type);
|
||||
throw missingCaseError(type);
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright 2025 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useEffect, useState, useId } from 'react';
|
||||
import type { Meta } from '@storybook/react';
|
||||
import { useId, VisuallyHidden } from 'react-aria';
|
||||
import { VisuallyHidden } from 'react-aria';
|
||||
import { FunGif, FunGifPreview } from './FunGif';
|
||||
import { LoadingState } from '../../util/loadable';
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// Copyright 2025 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
import type { ChangeEvent } from 'react';
|
||||
import React, { useCallback } from 'react';
|
||||
import { VisuallyHidden } from 'react-aria';
|
||||
import { getInteractionModality } from '@react-aria/interactions';
|
||||
|
@ -19,8 +20,8 @@ export function FunSearch(props: FunSearchProps): JSX.Element {
|
|||
const { shouldAutoFocus, onChangeShouldAutoFocus } = useFunContext();
|
||||
|
||||
const handleChange = useCallback(
|
||||
event => {
|
||||
onSearchInputChange(event.target.value);
|
||||
(event: ChangeEvent<HTMLInputElement>) => {
|
||||
onSearchInputChange(event.currentTarget.value);
|
||||
},
|
||||
[onSearchInputChange]
|
||||
);
|
||||
|
|
|
@ -12,8 +12,8 @@ import React, {
|
|||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
useId,
|
||||
} from 'react';
|
||||
import { useId } from 'react-aria';
|
||||
import type { Selection } from 'react-aria-components';
|
||||
import { ListBox, ListBoxItem } from 'react-aria-components';
|
||||
import {
|
||||
|
|
|
@ -3,9 +3,8 @@
|
|||
import type { Transition } from 'framer-motion';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import type { ReactNode } from 'react';
|
||||
import React, { useCallback } from 'react';
|
||||
import React, { useCallback, useId } from 'react';
|
||||
import type { Key } from 'react-aria';
|
||||
import { useId } from 'react-aria';
|
||||
import { Tab, TabList, TabPanel, Tabs } from 'react-aria-components';
|
||||
import type { FunPickerTabKey } from '../constants';
|
||||
|
||||
|
|
|
@ -9,9 +9,10 @@ import React, {
|
|||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
useId,
|
||||
} from 'react';
|
||||
import type { PressEvent } from 'react-aria';
|
||||
import { useId, VisuallyHidden } from 'react-aria';
|
||||
import { VisuallyHidden } from 'react-aria';
|
||||
import { LRUCache } from 'lru-cache';
|
||||
import { FunItemButton } from '../base/FunItem';
|
||||
import {
|
||||
|
|
|
@ -1,27 +1,28 @@
|
|||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useMemo, useSyncExternalStore } from 'react';
|
||||
|
||||
// Allows this to work in Node process
|
||||
let reducedMotionQuery: MediaQueryList;
|
||||
function getReducedMotionQuery() {
|
||||
if (reducedMotionQuery == null) {
|
||||
reducedMotionQuery = window.matchMedia('(prefers-reduced-motion)');
|
||||
}
|
||||
return reducedMotionQuery;
|
||||
export function useMediaQuery(query: string): boolean {
|
||||
const api = useMemo(() => {
|
||||
const mediaQuery = window.matchMedia(query);
|
||||
|
||||
function subscribe(onChange: () => void) {
|
||||
mediaQuery.addEventListener('change', onChange);
|
||||
return () => {
|
||||
mediaQuery.removeEventListener('change', onChange);
|
||||
};
|
||||
}
|
||||
|
||||
function getSnapshot() {
|
||||
return mediaQuery.matches;
|
||||
}
|
||||
|
||||
return { subscribe, getSnapshot };
|
||||
}, [query]);
|
||||
return useSyncExternalStore(api.subscribe, api.getSnapshot);
|
||||
}
|
||||
|
||||
export function useReducedMotion(): boolean {
|
||||
const [matches, setMatches] = useState(getReducedMotionQuery().matches);
|
||||
useEffect(() => {
|
||||
function onChange(event: MediaQueryListEvent) {
|
||||
setMatches(event.matches);
|
||||
}
|
||||
getReducedMotionQuery().addEventListener('change', onChange);
|
||||
return () => {
|
||||
getReducedMotionQuery().removeEventListener('change', onChange);
|
||||
};
|
||||
}, []);
|
||||
return matches;
|
||||
return useMediaQuery('(prefers-reduced-motion)');
|
||||
}
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { useMemo, useState } from 'react';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
export function useUniqueId(): string {
|
||||
return useMemo(() => uuid(), []);
|
||||
}
|
||||
|
||||
let nextElementId = 0;
|
||||
|
||||
export function useElementId(
|
||||
namePrefix: string
|
||||
): [id: string, selector: string] {
|
||||
// Prefixed to avoid starting with a number (which is invalid in CSS selectors)
|
||||
const [id] = useState(() => {
|
||||
const currentId = nextElementId;
|
||||
nextElementId += 1;
|
||||
return `${namePrefix}-${currentId}`;
|
||||
});
|
||||
// Return the ID and a selector that can be used in CSS or JS
|
||||
return [id, `#${id}`] as const;
|
||||
}
|
|
@ -10,6 +10,7 @@ import { useItemsActions } from '../ducks/items';
|
|||
import { getPreferredBadgeSelector } from '../selectors/badges';
|
||||
import { useComposerActions } from '../ducks/composer';
|
||||
import { getTextFormattingEnabled } from '../selectors/items';
|
||||
import { getConversationSelector } from '../selectors/conversations';
|
||||
|
||||
export type SmartCompositionTextAreaProps = Pick<
|
||||
CompositionTextAreaProps,
|
||||
|
@ -39,6 +40,7 @@ export const SmartCompositionTextArea = memo(function SmartCompositionTextArea(
|
|||
|
||||
const getPreferredBadge = useSelector(getPreferredBadgeSelector);
|
||||
const isFormattingEnabled = useSelector(getTextFormattingEnabled);
|
||||
const conversationSelector = useSelector(getConversationSelector);
|
||||
|
||||
return (
|
||||
<CompositionTextArea
|
||||
|
@ -52,6 +54,7 @@ export const SmartCompositionTextArea = memo(function SmartCompositionTextArea(
|
|||
onTextTooLong={onTextTooLong}
|
||||
platform={platform}
|
||||
ourConversationId={ourConversationId}
|
||||
conversationSelector={conversationSelector}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
|
|
@ -45,6 +45,7 @@ import { getLocalDeleteWarningShown } from '../selectors/items';
|
|||
import { getDeleteSyncSendEnabled } from '../selectors/items-extra';
|
||||
import { isConversationEverUnregistered } from '../../util/isConversationUnregistered';
|
||||
import { isDirectConversation } from '../../util/whatTypeOfConversation';
|
||||
import type { DurationInSeconds } from '../../util/durations';
|
||||
|
||||
export type OwnProps = {
|
||||
id: string;
|
||||
|
@ -182,7 +183,7 @@ export const SmartConversationHeader = memo(function SmartConversationHeader({
|
|||
}, [destroyMessages, conversation.id]);
|
||||
|
||||
const onConversationDisappearingMessagesChange = useCallback(
|
||||
seconds => {
|
||||
(seconds: DurationInSeconds) => {
|
||||
setDisappearingMessages(conversation.id, seconds);
|
||||
},
|
||||
[setDisappearingMessages, conversation.id]
|
||||
|
@ -197,7 +198,7 @@ export const SmartConversationHeader = memo(function SmartConversationHeader({
|
|||
}, [onMarkUnread, conversation.id]);
|
||||
|
||||
const onConversationMuteExpirationChange = useCallback(
|
||||
seconds => {
|
||||
(seconds: number) => {
|
||||
setMuteExpiration(conversation.id, seconds);
|
||||
},
|
||||
[setMuteExpiration, conversation.id]
|
||||
|
|
|
@ -5,7 +5,10 @@ import React, { useCallback, forwardRef, memo } from 'react';
|
|||
import { useSelector } from 'react-redux';
|
||||
import { useRecentEmojis } from '../selectors/emojis';
|
||||
import { useEmojisActions as useEmojiActions } from '../ducks/emojis';
|
||||
import type { Props as EmojiPickerProps } from '../../components/emoji/EmojiPicker';
|
||||
import type {
|
||||
EmojiPickDataType,
|
||||
Props as EmojiPickerProps,
|
||||
} from '../../components/emoji/EmojiPicker';
|
||||
import { EmojiPicker } from '../../components/emoji/EmojiPicker';
|
||||
import { getIntl } from '../selectors/user';
|
||||
import { getEmojiSkinToneDefault } from '../selectors/items';
|
||||
|
@ -39,7 +42,7 @@ export const SmartEmojiPicker = memo(
|
|||
const { onUseEmoji } = useEmojiActions();
|
||||
|
||||
const handlePickEmoji = useCallback(
|
||||
data => {
|
||||
(data: EmojiPickDataType) => {
|
||||
onUseEmoji({ shortName: data.shortName, skinTone: EmojiSkinTone.None });
|
||||
onPickEmoji(data);
|
||||
},
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
// Copyright 2023 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type { ReactNode } from 'react';
|
||||
import React, { memo, useCallback } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import type { NavTabPanelProps } from '../../components/NavTabs';
|
||||
import { NavTabs } from '../../components/NavTabs';
|
||||
import { getIntl, getTheme } from '../selectors/user';
|
||||
import {
|
||||
|
@ -27,10 +27,10 @@ import { getCallHistoryUnreadCount } from '../selectors/callHistory';
|
|||
|
||||
export type SmartNavTabsProps = Readonly<{
|
||||
navTabsCollapsed: boolean;
|
||||
onToggleNavTabsCollapse(navTabsCollapsed: boolean): void;
|
||||
renderCallsTab(props: NavTabPanelProps): JSX.Element;
|
||||
renderChatsTab(props: NavTabPanelProps): JSX.Element;
|
||||
renderStoriesTab(props: NavTabPanelProps): JSX.Element;
|
||||
onToggleNavTabsCollapse: (navTabsCollapsed: boolean) => void;
|
||||
renderCallsTab: () => ReactNode;
|
||||
renderChatsTab: () => ReactNode;
|
||||
renderStoriesTab: () => ReactNode;
|
||||
}>;
|
||||
|
||||
export const SmartNavTabs = memo(function SmartNavTabs({
|
||||
|
|
|
@ -35,6 +35,8 @@ import { useAudioPlayerActions } from '../ducks/audioPlayer';
|
|||
import { useGlobalModalActions } from '../ducks/globalModals';
|
||||
import { useStoriesActions } from '../ducks/stories';
|
||||
import { useIsWindowActive } from '../../hooks/useIsWindowActive';
|
||||
import type { DraftBodyRanges } from '../../types/BodyRange';
|
||||
import type { StoryViewType } from '../../types/Stories';
|
||||
|
||||
export const SmartStoryViewer = memo(function SmartStoryViewer() {
|
||||
const {
|
||||
|
@ -98,17 +100,22 @@ export const SmartStoryViewer = memo(function SmartStoryViewer() {
|
|||
);
|
||||
|
||||
const handleReactToStory = useCallback(
|
||||
async (emoji, story) => {
|
||||
async (emoji: string, story: StoryViewType) => {
|
||||
const { messageId } = story;
|
||||
reactToStory(emoji, messageId);
|
||||
},
|
||||
[reactToStory]
|
||||
);
|
||||
const handleReplyToStory = useCallback(
|
||||
(message, mentions, timestamp, story) => {
|
||||
(
|
||||
message: string,
|
||||
bodyRanges: DraftBodyRanges,
|
||||
timestamp: number,
|
||||
story: StoryViewType
|
||||
) => {
|
||||
const conversationId = storyInfo?.conversationStory?.conversationId;
|
||||
strictAssert(conversationId != null, 'conversationId is required');
|
||||
replyToStory(conversationId, message, mentions, timestamp, story);
|
||||
replyToStory(conversationId, message, bodyRanges, timestamp, story);
|
||||
},
|
||||
[storyInfo, replyToStory]
|
||||
);
|
||||
|
|
|
@ -748,258 +748,6 @@
|
|||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-14T18:53:33.345Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.browser.cjs.js",
|
||||
"line": " var libRef = React__namespace.useRef(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.browser.cjs.js",
|
||||
"line": " var heightRef = React__namespace.useRef(0);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.browser.cjs.js",
|
||||
"line": " var measurementsCacheRef = React__namespace.useRef();",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.browser.development.cjs.js",
|
||||
"line": " var libRef = React__namespace.useRef(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.browser.development.cjs.js",
|
||||
"line": " var heightRef = React__namespace.useRef(0);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.browser.development.cjs.js",
|
||||
"line": " var measurementsCacheRef = React__namespace.useRef();",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.browser.development.esm.js",
|
||||
"line": " var libRef = React.useRef(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.browser.development.esm.js",
|
||||
"line": " var heightRef = React.useRef(0);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.browser.development.esm.js",
|
||||
"line": " var measurementsCacheRef = React.useRef();",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.browser.esm.js",
|
||||
"line": " var libRef = React.useRef(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.browser.esm.js",
|
||||
"line": " var heightRef = React.useRef(0);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.browser.esm.js",
|
||||
"line": " var measurementsCacheRef = React.useRef();",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.cjs.js",
|
||||
"line": " var libRef = React__namespace.useRef(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.cjs.js",
|
||||
"line": " React__namespace.useRef(0);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.cjs.js",
|
||||
"line": " React__namespace.useRef();",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.development.cjs.js",
|
||||
"line": " var libRef = React__namespace.useRef(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.development.cjs.js",
|
||||
"line": " React__namespace.useRef(0);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.development.cjs.js",
|
||||
"line": " React__namespace.useRef();",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.development.esm.js",
|
||||
"line": " var libRef = React.useRef(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.development.esm.js",
|
||||
"line": " React.useRef(0);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.development.esm.js",
|
||||
"line": " React.useRef();",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.development.worker.cjs.js",
|
||||
"line": " var libRef = React__namespace.useRef(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.development.worker.cjs.js",
|
||||
"line": " React__namespace.useRef(0);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.development.worker.cjs.js",
|
||||
"line": " React__namespace.useRef();",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.development.worker.esm.js",
|
||||
"line": " var libRef = React.useRef(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.development.worker.esm.js",
|
||||
"line": " React.useRef(0);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.development.worker.esm.js",
|
||||
"line": " React.useRef();",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.esm.js",
|
||||
"line": " var libRef = React.useRef(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.esm.js",
|
||||
"line": " React.useRef(0);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.esm.js",
|
||||
"line": " React.useRef();",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.worker.cjs.js",
|
||||
"line": " var libRef = React__namespace.useRef(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.worker.cjs.js",
|
||||
"line": " React__namespace.useRef(0);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.worker.cjs.js",
|
||||
"line": " React__namespace.useRef();",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.worker.esm.js",
|
||||
"line": " var libRef = React.useRef(null);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.worker.esm.js",
|
||||
"line": " React.useRef(0);",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "node_modules/react-textarea-autosize/dist/react-textarea-autosize.worker.esm.js",
|
||||
"line": " React.useRef();",
|
||||
"reasonCategory": "usageTrusted",
|
||||
"updated": "2024-11-16T00:31:42.167Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-useRef",
|
||||
"path": "ts/calling/useGetCallingFrameBuffer.ts",
|
||||
|
|
|
@ -88,13 +88,11 @@ const excludedFilesRegexp = RegExp(
|
|||
'^node_modules/react-aria-components/.+',
|
||||
'^node_modules/react-contextmenu/.+',
|
||||
'^node_modules/react-dom/.+',
|
||||
'^node_modules/react-hot-loader/.+',
|
||||
'^node_modules/react-icon-base/.+',
|
||||
'^node_modules/react-input-autosize/.+',
|
||||
'^node_modules/react-popper/.+',
|
||||
'^node_modules/react-redux/.+',
|
||||
'^node_modules/react-router/.+',
|
||||
'^node_modules/react-router-dom/.+',
|
||||
'^node_modules/react-select/.+',
|
||||
'^node_modules/react-transition-group/.+',
|
||||
'^node_modules/react-virtualized/.+',
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
// Copyright 2022 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
export function objectMap<T>(
|
||||
export function objectMap<T, R>(
|
||||
obj: Record<string, T>,
|
||||
f: (key: keyof typeof obj, value: (typeof obj)[keyof typeof obj]) => unknown
|
||||
): Array<unknown> {
|
||||
f: (key: keyof typeof obj, value: (typeof obj)[keyof typeof obj]) => R
|
||||
): Array<R> {
|
||||
const keys: Array<keyof typeof obj> = Object.keys(obj);
|
||||
return keys.map(key => f(key, obj[key]));
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
import type { IntlShape } from 'react-intl';
|
||||
import { createIntl, createIntlCache } from 'react-intl';
|
||||
import type { ReactNode } from 'react';
|
||||
import type { LocaleMessageType, LocaleMessagesType } from '../types/I18N';
|
||||
import type {
|
||||
LocalizerType,
|
||||
|
@ -26,7 +27,7 @@ export function isLocaleMessageType(
|
|||
}
|
||||
|
||||
export type SetupI18nOptionsType = Readonly<{
|
||||
renderEmojify: (parts: ReadonlyArray<unknown>) => JSX.Element | void;
|
||||
renderEmojify: (parts: ReadonlyArray<unknown>) => ReactNode;
|
||||
}>;
|
||||
|
||||
export function createCachedIntl(
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import { assertDev } from './assert';
|
||||
|
||||
export function shouldNeverBeCalled(..._args: ReadonlyArray<unknown>): void {
|
||||
export function shouldNeverBeCalled(..._args: ReadonlyArray<unknown>): never {
|
||||
assertDev(false, 'This should never be called. Doing nothing');
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue