mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2026-05-30 03:23:18 +01:00
Fix and deprecate usePrevious hook and update raised hands button
Co-authored-by: ayumi-signal <143036029+ayumi-signal@users.noreply.github.com>
This commit is contained in:
@@ -55,7 +55,7 @@ import { createLogger } from '../logging/log.std.ts';
|
||||
import { isGroupOrAdhocActiveCall } from '../util/isGroupOrAdhocCall.std.ts';
|
||||
import { CallingAdhocCallInfo } from './CallingAdhocCallInfo.dom.tsx';
|
||||
import { callLinkRootKeyToUrl } from '../util/callLinkRootKeyToUrl.std.ts';
|
||||
import { usePrevious } from '../hooks/usePrevious.std.ts';
|
||||
import { usePreviousDeprecated } from '../hooks/usePrevious.std.ts';
|
||||
import { copyCallLink } from '../util/copyLinksWithToast.dom.ts';
|
||||
import {
|
||||
redactNotificationProfileId,
|
||||
@@ -264,7 +264,10 @@ function ActiveCallManager({
|
||||
// For caching screenshare frames which update slowly, between Pip and CallScreen.
|
||||
const imageDataCache = useRef<CallingImageDataCache>(new Map());
|
||||
|
||||
const previousConversationId = usePrevious(conversation.id, conversation.id);
|
||||
const previousConversationId = usePreviousDeprecated(
|
||||
conversation.id,
|
||||
conversation.id
|
||||
);
|
||||
useEffect(() => {
|
||||
if (conversation.id !== previousConversationId) {
|
||||
imageDataCache.current.clear();
|
||||
|
||||
@@ -80,7 +80,7 @@ import {
|
||||
} from '../hooks/useKeyboardShortcuts.dom.tsx';
|
||||
import { useValueAtFixedRate } from '../hooks/useValueAtFixedRate.std.ts';
|
||||
import { isReconnecting as callingIsReconnecting } from '../util/callingIsReconnecting.std.ts';
|
||||
import { usePrevious } from '../hooks/usePrevious.std.ts';
|
||||
import { usePreviousDeprecated } from '../hooks/usePrevious.std.ts';
|
||||
import {
|
||||
CallingToastProvider,
|
||||
PersistentCallingToast,
|
||||
@@ -585,7 +585,7 @@ export function CallScreen({
|
||||
}, [isSendingVideo, handleSize, isLonelyInCall, setLocalPreviewContainer]);
|
||||
|
||||
const { selfViewExpanded } = activeCall;
|
||||
const previousSelfViewExpanded = usePrevious(
|
||||
const previousSelfViewExpanded = usePreviousDeprecated(
|
||||
selfViewExpanded,
|
||||
selfViewExpanded
|
||||
);
|
||||
@@ -777,7 +777,10 @@ export function CallScreen({
|
||||
const [localHandRaised, setLocalHandRaised] = useState<boolean>(
|
||||
syncedLocalHandRaised
|
||||
);
|
||||
const previousLocalHandRaised = usePrevious(localHandRaised, localHandRaised);
|
||||
const previousLocalHandRaised = usePreviousDeprecated(
|
||||
localHandRaised,
|
||||
localHandRaised
|
||||
);
|
||||
const toggleRaiseHand = useCallback(
|
||||
(raise?: boolean) => {
|
||||
const nextValue = raise ?? !localHandRaised;
|
||||
@@ -1339,7 +1342,7 @@ function useViewModeChangedToast({
|
||||
i18n: LocalizerType;
|
||||
}): void {
|
||||
const { viewMode } = activeCall;
|
||||
const previousViewMode = usePrevious(viewMode, viewMode);
|
||||
const previousViewMode = usePreviousDeprecated(viewMode, viewMode);
|
||||
const presenterAci = usePresenter(activeCall.remoteParticipants);
|
||||
|
||||
const VIEW_MODE_CHANGED_TOAST_KEY = 'view-mode-changed';
|
||||
|
||||
@@ -36,7 +36,7 @@ import type { ConversationType } from '../state/ducks/conversations.preload.ts';
|
||||
import { Avatar, AvatarSize } from './Avatar.dom.tsx';
|
||||
import { AvatarColors } from '../types/Colors.std.ts';
|
||||
import type { SetLocalPreviewContainerType } from '../services/calling.preload.ts';
|
||||
import { usePrevious } from '../hooks/usePrevious.std.ts';
|
||||
import { usePreviousDeprecated } from '../hooks/usePrevious.std.ts';
|
||||
import type { SizeCallbackType } from '../calling/VideoSupport.preload.ts';
|
||||
import { MAX_FRAME_HEIGHT } from '../calling/constants.std.ts';
|
||||
|
||||
@@ -290,7 +290,10 @@ export function CallingPip({
|
||||
};
|
||||
}, []);
|
||||
|
||||
const previousIsWindowLarge = usePrevious(isWindowLarge, isWindowLarge);
|
||||
const previousIsWindowLarge = usePreviousDeprecated(
|
||||
isWindowLarge,
|
||||
isWindowLarge
|
||||
);
|
||||
// This only runs when isWindowLarge changes, so we aggressively change height + width
|
||||
useEffect(() => {
|
||||
if (previousIsWindowLarge === isWindowLarge) {
|
||||
|
||||
@@ -13,7 +13,7 @@ import type { ConversationType } from '../state/ducks/conversations.preload.ts';
|
||||
import { ModalHost } from './ModalHost.dom.tsx';
|
||||
import { drop } from '../util/drop.std.ts';
|
||||
import { createLogger } from '../logging/log.std.ts';
|
||||
import { usePrevious } from '../hooks/usePrevious.std.ts';
|
||||
import { usePrevious, usePreviousEffect } from '../hooks/usePrevious.std.ts';
|
||||
import { useReducedMotion } from '../hooks/useReducedMotion.dom.ts';
|
||||
|
||||
const log = createLogger('CallingRaisedHandsList');
|
||||
@@ -200,24 +200,20 @@ export function CallingRaisedHandsListButton({
|
||||
[]
|
||||
);
|
||||
|
||||
const prevRaisedHandsCount = usePrevious(raisedHandsCount, raisedHandsCount);
|
||||
const prevSyncedLocalHandRaised = usePrevious(
|
||||
const prevRaisedHandsCount = usePrevious(raisedHandsCount) ?? 0;
|
||||
const prevSyncedLocalHandRaised = usePreviousEffect(
|
||||
syncedLocalHandRaised,
|
||||
syncedLocalHandRaised
|
||||
);
|
||||
|
||||
const prevShownRaisedHandsCountRef = useRef<number>(raisedHandsCount);
|
||||
const prevShownSyncedLocalHandRaisedRef = useRef<boolean>(
|
||||
syncedLocalHandRaised
|
||||
);
|
||||
|
||||
// Bouncy effect
|
||||
useEffect(() => {
|
||||
if (
|
||||
raisedHandsCount > prevRaisedHandsCount ||
|
||||
(raisedHandsCount > 0 && !isVisible)
|
||||
) {
|
||||
setIsVisible(true);
|
||||
opacitySpringApi.stop();
|
||||
drop(Promise.all(opacitySpringApi.start({ opacity: 1 })));
|
||||
if (raisedHandsCount > prevRaisedHandsCount) {
|
||||
scaleSpringApi.stop();
|
||||
drop(
|
||||
Promise.all(
|
||||
@@ -228,14 +224,33 @@ export function CallingRaisedHandsListButton({
|
||||
})
|
||||
)
|
||||
);
|
||||
} else if (raisedHandsCount === 0) {
|
||||
opacitySpringApi.stop();
|
||||
}
|
||||
}, [raisedHandsCount, prevRaisedHandsCount, scaleSpringApi]);
|
||||
|
||||
useEffect(() => {
|
||||
if (raisedHandsCount === prevRaisedHandsCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
opacitySpringApi.stop();
|
||||
if (raisedHandsCount > 0) {
|
||||
setIsVisible(true);
|
||||
drop(
|
||||
Promise.all(
|
||||
opacitySpringApi.start({
|
||||
from: { opacity: opacitySpringProps.opacity },
|
||||
to: { opacity: 1 },
|
||||
})
|
||||
)
|
||||
);
|
||||
} else {
|
||||
drop(
|
||||
Promise.all(
|
||||
opacitySpringApi.start({
|
||||
from: { opacity: opacitySpringProps.opacity },
|
||||
to: { opacity: 0 },
|
||||
onRest: () => {
|
||||
if (!raisedHandsCount) {
|
||||
onResolve: ({ cancelled }) => {
|
||||
if (!cancelled) {
|
||||
setIsVisible(false);
|
||||
}
|
||||
},
|
||||
@@ -244,11 +259,10 @@ export function CallingRaisedHandsListButton({
|
||||
);
|
||||
}
|
||||
}, [
|
||||
isVisible,
|
||||
raisedHandsCount,
|
||||
prevRaisedHandsCount,
|
||||
opacitySpringApi,
|
||||
scaleSpringApi,
|
||||
opacitySpringProps.opacity,
|
||||
setIsVisible,
|
||||
]);
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import classNames from 'classnames';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { useIsMounted } from '../hooks/useIsMounted.std.ts';
|
||||
import type { LocalizerType } from '../types/I18N.std.ts';
|
||||
import { usePrevious } from '../hooks/usePrevious.std.ts';
|
||||
import { usePreviousDeprecated } from '../hooks/usePrevious.std.ts';
|
||||
import { difference } from '../util/setUtil.std.ts';
|
||||
import { useReducedMotion } from '../hooks/useReducedMotion.dom.ts';
|
||||
|
||||
@@ -81,7 +81,7 @@ export function CallingToastProvider({
|
||||
transitionFrom?: object;
|
||||
}): JSX.Element {
|
||||
const [toasts, setToasts] = useState<Array<CallingToastStateType>>([]);
|
||||
const previousToasts = usePrevious([], toasts);
|
||||
const previousToasts = usePreviousDeprecated([], toasts);
|
||||
const timeouts = useRef<Map<string, TimeoutType>>(new Map());
|
||||
// All toasts are paused on hover or focus so that toasts don't disappear while a user
|
||||
// is attempting to interact with them
|
||||
|
||||
@@ -10,7 +10,7 @@ import { CallMode } from '../types/CallDisposition.std.ts';
|
||||
import type { ConversationType } from '../state/ducks/conversations.preload.ts';
|
||||
import type { LocalizerType } from '../types/Util.std.ts';
|
||||
import { CallingToastProvider, useCallingToasts } from './CallingToast.dom.tsx';
|
||||
import { usePrevious } from '../hooks/usePrevious.std.ts';
|
||||
import { usePreviousDeprecated } from '../hooks/usePrevious.std.ts';
|
||||
import { difference as setDifference } from '../util/setUtil.std.ts';
|
||||
import { isMoreRecentThan } from '../util/timestamp.std.ts';
|
||||
import { isGroupOrAdhocActiveCall } from '../util/isGroupOrAdhocCall.std.ts';
|
||||
@@ -58,7 +58,10 @@ export function useScreenSharingStoppedToast({
|
||||
() => getCurrentPresenter(activeCall),
|
||||
[activeCall]
|
||||
);
|
||||
const previousPresenter = usePrevious(currentPresenter, currentPresenter);
|
||||
const previousPresenter = usePreviousDeprecated(
|
||||
currentPresenter,
|
||||
currentPresenter
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (previousPresenter && !currentPresenter) {
|
||||
@@ -93,7 +96,10 @@ function useMutedToast({
|
||||
mutedBy: number | undefined;
|
||||
i18n: LocalizerType;
|
||||
}): void {
|
||||
const previousHasLocalAudio = usePrevious(hasLocalAudio, hasLocalAudio);
|
||||
const previousHasLocalAudio = usePreviousDeprecated(
|
||||
hasLocalAudio,
|
||||
hasLocalAudio
|
||||
);
|
||||
const { showToast, hideToast } = useCallingToasts();
|
||||
const MUTED_TOAST_KEY = 'muted';
|
||||
|
||||
@@ -131,7 +137,10 @@ function useOutgoingRingToast({
|
||||
i18n: LocalizerType;
|
||||
}): void {
|
||||
const { showToast, hideToast } = useCallingToasts();
|
||||
const previousOutgoingRing = usePrevious(outgoingRing, outgoingRing);
|
||||
const previousOutgoingRing = usePreviousDeprecated(
|
||||
outgoingRing,
|
||||
outgoingRing
|
||||
);
|
||||
const RINGING_TOAST_KEY = 'ringing';
|
||||
|
||||
useEffect(() => {
|
||||
@@ -182,7 +191,7 @@ function useRaisedHandsToast({
|
||||
return () => clearTimeout(timeout);
|
||||
}, []);
|
||||
|
||||
const previousRaisedHands = usePrevious(raisedHands, raisedHands);
|
||||
const previousRaisedHands = usePreviousDeprecated(raisedHands, raisedHands);
|
||||
const [newHands, loweredHands]: [Set<number>, Set<number>] = isLoaded
|
||||
? [
|
||||
setDifference(
|
||||
@@ -276,7 +285,7 @@ function useLowerHandSuggestionToast({
|
||||
handleLowerHand: (() => void) | undefined;
|
||||
isHandRaised: boolean | undefined;
|
||||
}): void {
|
||||
const previousSuggestLowerHand = usePrevious(
|
||||
const previousSuggestLowerHand = usePreviousDeprecated(
|
||||
suggestLowerHand,
|
||||
suggestLowerHand
|
||||
);
|
||||
@@ -343,7 +352,7 @@ function useMutedByToast({
|
||||
conversationsByDemuxId?: Map<number, ConversationType>;
|
||||
i18n: LocalizerType;
|
||||
}): void {
|
||||
const previousMutedBy = usePrevious(mutedBy, mutedBy);
|
||||
const previousMutedBy = usePreviousDeprecated(mutedBy, mutedBy);
|
||||
|
||||
const { showToast, hideToast } = useCallingToasts();
|
||||
const MUTED_BY_TOAST_KEY = 'MUTED_BY_TOAST_KEY';
|
||||
@@ -401,7 +410,7 @@ function useObservedRemoteMuteToast({
|
||||
}): void {
|
||||
const { showToast, hideToast } = useCallingToasts();
|
||||
const OBSERVED_REMOTE_MUTE_TOAST_KEY = 'OBSERVED_REMOTE_MUTE_TOAST_KEY';
|
||||
const previousObservedRemoteMute = usePrevious(
|
||||
const previousObservedRemoteMute = usePreviousDeprecated(
|
||||
observedRemoteMute,
|
||||
observedRemoteMute
|
||||
);
|
||||
|
||||
@@ -66,7 +66,7 @@ import {
|
||||
import { MediaEditor } from './MediaEditor.dom.tsx';
|
||||
import { isImageTypeSupported } from '../util/GoogleChrome.std.ts';
|
||||
import * as KeyboardLayout from '../services/keyboardLayout.dom.ts';
|
||||
import { usePrevious } from '../hooks/usePrevious.std.ts';
|
||||
import { usePreviousDeprecated } from '../hooks/usePrevious.std.ts';
|
||||
import { PanelType } from '../types/Panels.std.ts';
|
||||
import type { SmartCompositionRecordingDraftProps } from '../state/smart/CompositionRecordingDraft.preload.tsx';
|
||||
import { useEscapeHandling } from '../hooks/useEscapeHandling.dom.ts';
|
||||
@@ -527,7 +527,7 @@ export const CompositionArea = memo(function CompositionArea({
|
||||
});
|
||||
|
||||
// Focus input on first mount
|
||||
const previousFocusCounter = usePrevious<number | undefined>(
|
||||
const previousFocusCounter = usePreviousDeprecated<number | undefined>(
|
||||
focusCounter,
|
||||
focusCounter
|
||||
);
|
||||
@@ -543,8 +543,11 @@ export const CompositionArea = memo(function CompositionArea({
|
||||
}
|
||||
}, [inputApiRef, focusCounter, previousFocusCounter]);
|
||||
|
||||
const previousSendCounter = usePrevious(sendCounter, sendCounter);
|
||||
const previousConversationId = usePrevious(conversationId, conversationId);
|
||||
const previousSendCounter = usePreviousDeprecated(sendCounter, sendCounter);
|
||||
const previousConversationId = usePreviousDeprecated(
|
||||
conversationId,
|
||||
conversationId
|
||||
);
|
||||
useEffect(() => {
|
||||
if (!inputApiRef.current) {
|
||||
return;
|
||||
@@ -569,9 +572,10 @@ export const CompositionArea = memo(function CompositionArea({
|
||||
// - User begins editing another message.
|
||||
const editHistoryLength = draftEditMessage?.editHistoryLength;
|
||||
const hasEditHistoryChanged =
|
||||
usePrevious(editHistoryLength, editHistoryLength) !== editHistoryLength;
|
||||
usePreviousDeprecated(editHistoryLength, editHistoryLength) !==
|
||||
editHistoryLength;
|
||||
const hasEditedMessageChanged =
|
||||
usePrevious(editedMessageId, editedMessageId) !== editedMessageId;
|
||||
usePreviousDeprecated(editedMessageId, editedMessageId) !== editedMessageId;
|
||||
|
||||
const hasEditDraftChanged = hasEditHistoryChanged || hasEditedMessageChanged;
|
||||
useEffect(() => {
|
||||
|
||||
@@ -75,7 +75,7 @@ import { createLogger } from '../logging/log.std.ts';
|
||||
import type { LinkPreviewForUIType } from '../types/message/LinkPreviews.std.ts';
|
||||
import { StagedLinkPreview } from './conversation/StagedLinkPreview.dom.tsx';
|
||||
import type { DraftEditMessageType } from '../model-types.d.ts';
|
||||
import { usePrevious } from '../hooks/usePrevious.std.ts';
|
||||
import { usePreviousDeprecated } from '../hooks/usePrevious.std.ts';
|
||||
import {
|
||||
matchBold,
|
||||
matchItalic,
|
||||
@@ -417,11 +417,11 @@ export function CompositionInput(props: Props): ReactElement {
|
||||
return false;
|
||||
};
|
||||
|
||||
const previousFormattingEnabled = usePrevious(
|
||||
const previousFormattingEnabled = usePreviousDeprecated(
|
||||
isFormattingEnabled,
|
||||
isFormattingEnabled
|
||||
);
|
||||
const previousIsMouseDown = usePrevious(isMouseDown, isMouseDown);
|
||||
const previousIsMouseDown = usePreviousDeprecated(isMouseDown, isMouseDown);
|
||||
|
||||
useEffect(() => {
|
||||
const formattingChanged =
|
||||
@@ -779,7 +779,7 @@ export function CompositionInput(props: Props): ReactElement {
|
||||
const memberIdList = useMemo(() => {
|
||||
return JSON.stringify(sortedGroupMembers?.map(mem => mem.id));
|
||||
}, [sortedGroupMembers]);
|
||||
const previousMemberIdList = usePrevious(undefined, memberIdList);
|
||||
const previousMemberIdList = usePreviousDeprecated(undefined, memberIdList);
|
||||
|
||||
useEffect(() => {
|
||||
memberRepositoryRef.current.updateMembers(sortedGroupMembers || []);
|
||||
|
||||
@@ -5,7 +5,7 @@ import type { ReactNode, JSX } from 'react';
|
||||
import { useRef, useEffect, Children } from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { usePrevious } from '../hooks/usePrevious.std.ts';
|
||||
import { usePreviousDeprecated } from '../hooks/usePrevious.std.ts';
|
||||
import { scrollToBottom } from '../util/scrollUtil.std.ts';
|
||||
|
||||
type PropsType = {
|
||||
@@ -21,7 +21,7 @@ export function ContactPills({
|
||||
|
||||
// oxlint-disable-next-line no-react-children
|
||||
const childCount = Children.count(children);
|
||||
const previousChildCount = usePrevious(0, childCount);
|
||||
const previousChildCount = usePreviousDeprecated(0, childCount);
|
||||
|
||||
useEffect(() => {
|
||||
const hasAddedNewChild = childCount > previousChildCount;
|
||||
|
||||
@@ -30,7 +30,7 @@ import { MAX_FRAME_HEIGHT, MAX_FRAME_WIDTH } from '../calling/constants.std.ts';
|
||||
import { useValueAtFixedRate } from '../hooks/useValueAtFixedRate.std.ts';
|
||||
import { isOlderThan } from '../util/timestamp.std.ts';
|
||||
import type { CallingImageDataCache } from './CallManager.dom.tsx';
|
||||
import { usePrevious } from '../hooks/usePrevious.std.ts';
|
||||
import { usePreviousDeprecated } from '../hooks/usePrevious.std.ts';
|
||||
import type { PropsType as SmartCallingParticipantMenuProps } from '../state/smart/CallingParticipantMenu.preload.tsx';
|
||||
import type { AxoMenuBuilder } from '../axo/AxoMenuBuilder.dom.tsx';
|
||||
import { AxoIconButton } from '../axo/AxoIconButton.dom.tsx';
|
||||
@@ -129,8 +129,11 @@ export const GroupCallRemoteParticipant: FC<PropsType> = memo(
|
||||
!props.isInPip ? props.audioLevel > 0 : false,
|
||||
SPEAKING_LINGER_MS
|
||||
);
|
||||
const previousSharingScreen = usePrevious(sharingScreen, sharingScreen);
|
||||
const prevIsActiveSpeakerInSpeakerView = usePrevious(
|
||||
const previousSharingScreen = usePreviousDeprecated(
|
||||
sharingScreen,
|
||||
sharingScreen
|
||||
);
|
||||
const prevIsActiveSpeakerInSpeakerView = usePreviousDeprecated(
|
||||
isActiveSpeakerInSpeakerView,
|
||||
isActiveSpeakerInSpeakerView
|
||||
);
|
||||
|
||||
@@ -35,7 +35,7 @@ import { LeftPaneMode } from '../types/leftPane.std.ts';
|
||||
import type { LocalizerType, ThemeType } from '../types/Util.std.ts';
|
||||
import { ScrollBehavior } from '../types/Util.std.ts';
|
||||
import type { PreferredBadgeSelectorType } from '../state/selectors/badges.preload.ts';
|
||||
import { usePrevious } from '../hooks/usePrevious.std.ts';
|
||||
import { usePreviousDeprecated } from '../hooks/usePrevious.std.ts';
|
||||
import { missingCaseError } from '../util/missingCaseError.std.ts';
|
||||
import type { DurationInSeconds } from '../util/durations/index.std.ts';
|
||||
import { WidthBreakpoint, getNavSidebarWidthBreakpoint } from './_util.std.ts';
|
||||
@@ -312,7 +312,7 @@ export function LeftPane({
|
||||
dismissBackupMediaDownloadBanner,
|
||||
updateFilterByUnread,
|
||||
}: PropsType): JSX.Element {
|
||||
const previousModeSpecificProps = usePrevious(
|
||||
const previousModeSpecificProps = usePreviousDeprecated(
|
||||
modeSpecificProps,
|
||||
modeSpecificProps
|
||||
);
|
||||
@@ -599,7 +599,7 @@ export function LeftPane({
|
||||
const measureRef = useRef<HTMLDivElement>(null);
|
||||
const measureSize = useSizeObserver(measureRef);
|
||||
|
||||
const previousMeasureSize = usePrevious(null, measureSize);
|
||||
const previousMeasureSize = usePreviousDeprecated(null, measureSize);
|
||||
|
||||
const widthBreakpoint = getNavSidebarWidthBreakpoint(
|
||||
measureSize && !measureSize.hidden
|
||||
@@ -613,7 +613,7 @@ export function LeftPane({
|
||||
};
|
||||
|
||||
// Control scroll position
|
||||
const previousSelectedConversationId = usePrevious(
|
||||
const previousSelectedConversationId = usePreviousDeprecated(
|
||||
selectedConversationId,
|
||||
selectedConversationId
|
||||
);
|
||||
|
||||
@@ -10,7 +10,7 @@ import type {
|
||||
import type { LocalizerType } from '../types/Util.std.ts';
|
||||
import { Avatar, AvatarSize } from './Avatar.dom.tsx';
|
||||
import { SearchInput } from './SearchInput.dom.tsx';
|
||||
import { usePrevious } from '../hooks/usePrevious.std.ts';
|
||||
import { usePreviousDeprecated } from '../hooks/usePrevious.std.ts';
|
||||
import { Tooltip, TooltipPlacement } from './Tooltip.dom.tsx';
|
||||
import { Theme } from '../util/theme.std.ts';
|
||||
|
||||
@@ -67,12 +67,18 @@ export function LeftPaneSearchInput({
|
||||
}: PropsType): JSX.Element {
|
||||
const inputRef = useRef<null | HTMLInputElement>(null);
|
||||
|
||||
const prevSearchConversationId = usePrevious(
|
||||
const prevSearchConversationId = usePreviousDeprecated(
|
||||
undefined,
|
||||
searchConversation?.id
|
||||
);
|
||||
const prevSearchCounter = usePrevious(startSearchCounter, startSearchCounter);
|
||||
const wasSearchingGlobally = usePrevious(false, isSearchingGlobally);
|
||||
const prevSearchCounter = usePreviousDeprecated(
|
||||
startSearchCounter,
|
||||
startSearchCounter
|
||||
);
|
||||
const wasSearchingGlobally = usePreviousDeprecated(
|
||||
false,
|
||||
isSearchingGlobally
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
// When user chooses to search in a given conversation we focus the field for them
|
||||
|
||||
@@ -29,7 +29,7 @@ import { formatDateTimeForAttachment } from '../util/formatTimestamp.dom.ts';
|
||||
import { formatDuration } from '../util/formatDuration.std.ts';
|
||||
import { isGIF, isIncremental } from '../util/Attachment.std.ts';
|
||||
import { useRestoreFocus } from '../hooks/useRestoreFocus.dom.ts';
|
||||
import { usePrevious } from '../hooks/usePrevious.std.ts';
|
||||
import { usePreviousDeprecated } from '../hooks/usePrevious.std.ts';
|
||||
import { arrow } from '../util/keyboard.dom.ts';
|
||||
import { drop } from '../util/drop.std.ts';
|
||||
import { isCmdOrCtrl } from '../hooks/useKeyboardShortcuts.dom.tsx';
|
||||
@@ -117,7 +117,7 @@ export function Lightbox({
|
||||
}: PropsType): JSX.Element | null {
|
||||
const hasThumbnails = media.length > 1;
|
||||
const messageId = media.at(0)?.message.id;
|
||||
const prevMessageId = usePrevious(messageId, messageId);
|
||||
const prevMessageId = usePreviousDeprecated(messageId, messageId);
|
||||
const needsAnimation = messageId !== prevMessageId;
|
||||
const [root, setRoot] = useState<HTMLElement | undefined>();
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import { assertDev } from '../util/assert.std.ts';
|
||||
import { getClassNamesFor } from '../util/getClassNamesFor.std.ts';
|
||||
import { themeClassName } from '../util/theme.std.ts';
|
||||
import { useEscapeHandling } from '../hooks/useEscapeHandling.dom.ts';
|
||||
import { usePrevious } from '../hooks/usePrevious.std.ts';
|
||||
import { usePreviousDeprecated } from '../hooks/usePrevious.std.ts';
|
||||
import { handleOutsideClick } from '../util/handleOutsideClick.dom.ts';
|
||||
import { createLogger } from '../logging/log.std.ts';
|
||||
|
||||
@@ -57,7 +57,7 @@ export const ModalHost = memo(function ModalHostInner({
|
||||
theme,
|
||||
}: PropsType) {
|
||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||
const previousModalName = usePrevious(modalName, modalName);
|
||||
const previousModalName = usePreviousDeprecated(modalName, modalName);
|
||||
const modalContainer = useContext(ModalContainerContext) ?? document.body;
|
||||
|
||||
if (previousModalName !== modalName) {
|
||||
|
||||
@@ -72,7 +72,7 @@ import { offsetDistanceModifier } from '../util/popperUtil.std.ts';
|
||||
import { AxoButton } from '../axo/AxoButton.dom.tsx';
|
||||
import { missingCaseError } from '../util/missingCaseError.std.ts';
|
||||
import { openLinkInWebBrowser } from '../util/openLinkInWebBrowser.dom.ts';
|
||||
import { usePrevious } from '../hooks/usePrevious.std.ts';
|
||||
import { usePreviousDeprecated } from '../hooks/usePrevious.std.ts';
|
||||
import { tw } from '../axo/tw.dom.tsx';
|
||||
|
||||
const SUPPORT_URL = 'https://support.signal.org/hc/requests/new?desktop';
|
||||
@@ -168,7 +168,7 @@ export function PreferencesDonateFlow({
|
||||
CardFormValues | undefined
|
||||
>();
|
||||
|
||||
const prevStep = usePrevious(step, step);
|
||||
const prevStep = usePreviousDeprecated(step, step);
|
||||
|
||||
const hasCardFormData = useMemo(() => {
|
||||
if (!cardFormValues) {
|
||||
|
||||
@@ -35,7 +35,7 @@ import type {
|
||||
import type { LocalizerType, ThemeType } from '../../../types/Util.std.ts';
|
||||
import type { PreferredBadgeSelectorType } from '../../../state/selectors/badges.preload.ts';
|
||||
import type { Location } from '../../../types/Nav.std.ts';
|
||||
import { usePrevious } from '../../../hooks/usePrevious.std.ts';
|
||||
import { usePreviousDeprecated } from '../../../hooks/usePrevious.std.ts';
|
||||
import type { Emoji } from '../../../axo/emoji.std.ts';
|
||||
|
||||
export type PropsDataType = {
|
||||
@@ -148,7 +148,7 @@ export function GroupMemberLabelEditor({
|
||||
|
||||
// Popping the panel here after a save is far safer; we may not have re-rendered with
|
||||
// the new existing values yet when the onSuccess callback down-file is called.
|
||||
const previousIsSaving = usePrevious(isSaving, isSaving);
|
||||
const previousIsSaving = usePreviousDeprecated(isSaving, isSaving);
|
||||
useEffect(() => {
|
||||
if (!isSaving && previousIsSaving !== isSaving && !isDirty) {
|
||||
popPanelForConversation();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2025 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
import type { ForwardedRef, ReactNode, JSX } from 'react';
|
||||
import { forwardRef, memo, useCallback, useMemo, useState } from 'react';
|
||||
import { forwardRef, memo, useCallback, useMemo } from 'react';
|
||||
import { Tabs } from 'radix-ui';
|
||||
import { AnimatePresence, motion } from 'motion/react';
|
||||
import type { LocalizerType } from '../../../types/I18N.std.ts';
|
||||
@@ -19,6 +19,7 @@ import type { HydratedBodyRangesType } from '../../../types/BodyRange.std.ts';
|
||||
import { AxoSymbol } from '../../../axo/AxoSymbol.dom.tsx';
|
||||
import { missingCaseError } from '../../../util/missingCaseError.std.ts';
|
||||
import { stripNewlinesForLeftPane } from '../../../util/stripNewlinesForLeftPane.std.ts';
|
||||
import { usePrevious } from '../../../hooks/usePrevious.std.ts';
|
||||
|
||||
enum Direction {
|
||||
None = 0,
|
||||
@@ -26,18 +27,6 @@ enum Direction {
|
||||
Forwards = 1,
|
||||
}
|
||||
|
||||
// This `usePrevious()` hook is safe in React concurrent mode and doesn't break
|
||||
// when rendered multiple times with the same values in `<StrictMode>`
|
||||
function usePrevious<T>(value: T): T | null {
|
||||
const [current, setCurrent] = useState<T>(value);
|
||||
const [previous, setPrevious] = useState<T | null>(null);
|
||||
if (current !== value) {
|
||||
setCurrent(value);
|
||||
setPrevious(current);
|
||||
}
|
||||
return previous;
|
||||
}
|
||||
|
||||
export type PinMessageText = Readonly<{
|
||||
body: string;
|
||||
bodyRanges: HydratedBodyRangesType;
|
||||
|
||||
@@ -12,7 +12,7 @@ import type { PollWithResolvedVotersType } from '../../../state/selectors/messag
|
||||
import type { LocalizerType } from '../../../types/Util.std.ts';
|
||||
import { PollVotesModal } from './PollVotesModal.dom.tsx';
|
||||
import { SpinnerV2 } from '../../SpinnerV2.dom.tsx';
|
||||
import { usePrevious } from '../../../hooks/usePrevious.std.ts';
|
||||
import { usePreviousDeprecated } from '../../../hooks/usePrevious.std.ts';
|
||||
import { UserText } from '../../UserText.dom.tsx';
|
||||
|
||||
function VotedCheckmark({
|
||||
@@ -170,7 +170,10 @@ export function PollMessageContents({
|
||||
const [isPending, setIsPending] = useState(false);
|
||||
|
||||
const hasPendingVotes = poll.pendingVoteDiff && poll.pendingVoteDiff.size > 0;
|
||||
const hadPendingVotesInLastRender = usePrevious(hasPendingVotes, undefined);
|
||||
const hadPendingVotesInLastRender = usePreviousDeprecated(
|
||||
hasPendingVotes,
|
||||
undefined
|
||||
);
|
||||
|
||||
const pendingCheckTimer = useRef<NodeJS.Timeout | null>(null);
|
||||
const isIncoming = direction === 'incoming';
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
import { useEffect, useMemo } from 'react';
|
||||
import type { AciString } from '../types/ServiceId.std.ts';
|
||||
import { usePrevious } from './usePrevious.std.ts';
|
||||
import { usePreviousDeprecated } from './usePrevious.std.ts';
|
||||
|
||||
type RemoteParticipant = {
|
||||
hasRemoteVideo: boolean;
|
||||
@@ -31,7 +31,7 @@ export function useActivateSpeakerViewOnPresenting({
|
||||
switchFromPresentationView: () => void;
|
||||
}): void {
|
||||
const presenterAci = usePresenter(remoteParticipants);
|
||||
const prevPresenterAci = usePrevious(presenterAci, presenterAci);
|
||||
const prevPresenterAci = usePreviousDeprecated(presenterAci, presenterAci);
|
||||
|
||||
useEffect(() => {
|
||||
if (prevPresenterAci !== presenterAci && presenterAci) {
|
||||
|
||||
@@ -1,11 +1,51 @@
|
||||
// Copyright 2020 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { useRef } from 'react';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
|
||||
export function usePrevious<T>(initialValue: T, currentValue: T): T {
|
||||
/**
|
||||
* This `usePrevious()` hook is safe in React concurrent mode and doesn't break
|
||||
* when rendered multiple times with the same values in `<StrictMode>`
|
||||
* Note: The previous value only updates when the value changes.
|
||||
* If you want to do work once after a change and track that it was done:
|
||||
* ```
|
||||
* const [counter, setCounter] = useState(0);
|
||||
* const lastAnimatedRef = useRef();
|
||||
*
|
||||
* useEffect(() => {
|
||||
* if (counter === lastAnimatedRef.current) {
|
||||
* return;
|
||||
* }
|
||||
* lastAnimatedRef.current = counter;
|
||||
* // animate
|
||||
* }, [counter]);
|
||||
* ```
|
||||
*/
|
||||
export function usePrevious<T>(value: T): T | null {
|
||||
const [current, setCurrent] = useState<T>(value);
|
||||
const [previous, setPrevious] = useState<T | null>(null);
|
||||
if (current !== value) {
|
||||
setCurrent(value);
|
||||
setPrevious(current);
|
||||
}
|
||||
return previous;
|
||||
}
|
||||
|
||||
// TODO: DESKTOP-10151
|
||||
/** @deprecated */
|
||||
export function usePreviousDeprecated<T>(initialValue: T, currentValue: T): T {
|
||||
const previousValueRef = useRef<T>(initialValue);
|
||||
const result = previousValueRef.current;
|
||||
previousValueRef.current = currentValue;
|
||||
return result;
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
export function usePreviousEffect<T>(initialValue: T, currentValue: T): T {
|
||||
const previousValueRef = useRef<T>(initialValue);
|
||||
const result = previousValueRef.current;
|
||||
useEffect(() => {
|
||||
previousValueRef.current = currentValue;
|
||||
}, [currentValue]);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import { useState, useEffect, type JSX } from 'react';
|
||||
import type { LocalizerType } from '../types/Util.std.ts';
|
||||
import { ResolvedSendStatus } from '../types/Stories.std.ts';
|
||||
import { usePrevious } from './usePrevious.std.ts';
|
||||
import { usePreviousDeprecated } from './usePrevious.std.ts';
|
||||
import { AxoConfirmDialog } from '../axo/AxoConfirmDialog.dom.tsx';
|
||||
|
||||
export function useRetryStorySend(
|
||||
@@ -19,7 +19,7 @@ export function useRetryStorySend(
|
||||
const [hasSendFailedAlert, setHasSendFailedAlert] = useState(false);
|
||||
const [wasManuallyRetried, setWasManuallyRetried] = useState(false);
|
||||
|
||||
const previousSendStatus = usePrevious(sendStatus, sendStatus);
|
||||
const previousSendStatus = usePreviousDeprecated(sendStatus, sendStatus);
|
||||
|
||||
useEffect(() => {
|
||||
if (!wasManuallyRetried) {
|
||||
|
||||
@@ -19,7 +19,7 @@ import { getConversations } from '../selectors/conversations.dom.ts';
|
||||
import { SeenStatus } from '../../MessageSeenStatus.std.ts';
|
||||
import { markViewed } from '../ducks/conversations.preload.ts';
|
||||
import * as Errors from '../../types/errors.std.ts';
|
||||
import { usePrevious } from '../../hooks/usePrevious.std.ts';
|
||||
import { usePreviousDeprecated } from '../../hooks/usePrevious.std.ts';
|
||||
|
||||
const log = createLogger('VoiceNotesPlaybackProvider');
|
||||
|
||||
@@ -35,7 +35,10 @@ export const SmartVoiceNotesPlaybackProvider = memo(
|
||||
const active = useSelector(selectAudioPlayerActive);
|
||||
const conversations = useSelector(getConversations);
|
||||
|
||||
const previousStartPosition = usePrevious(undefined, active?.startPosition);
|
||||
const previousStartPosition = usePreviousDeprecated(
|
||||
undefined,
|
||||
active?.startPosition
|
||||
);
|
||||
|
||||
const content = active?.content;
|
||||
let url: undefined | string;
|
||||
|
||||
Reference in New Issue
Block a user