Auto-scroll the left pane less frequently
This commit is contained in:
parent
3d5f30560d
commit
c97bb0feee
5 changed files with 43 additions and 59 deletions
|
@ -9,6 +9,7 @@ import React, {
|
||||||
ReactNode,
|
ReactNode,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
|
|
||||||
|
import { usePrevious } from '../util/hooks';
|
||||||
import { scrollToBottom } from '../util/scrollToBottom';
|
import { scrollToBottom } from '../util/scrollToBottom';
|
||||||
|
|
||||||
type PropsType = {
|
type PropsType = {
|
||||||
|
@ -19,9 +20,7 @@ export const ContactPills: FunctionComponent<PropsType> = ({ children }) => {
|
||||||
const elRef = useRef<null | HTMLDivElement>(null);
|
const elRef = useRef<null | HTMLDivElement>(null);
|
||||||
|
|
||||||
const childCount = Children.count(children);
|
const childCount = Children.count(children);
|
||||||
const previousChildCountRef = useRef<number>(childCount);
|
const previousChildCount = usePrevious(0, childCount);
|
||||||
const previousChildCount = previousChildCountRef.current;
|
|
||||||
previousChildCountRef.current = childCount;
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const hasAddedNewChild = childCount > previousChildCount;
|
const hasAddedNewChild = childCount > previousChildCount;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright 2019-2021 Signal Messenger, LLC
|
// Copyright 2019-2021 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import React, { useRef, useEffect, useMemo, CSSProperties } from 'react';
|
import React, { useEffect, useMemo, CSSProperties } from 'react';
|
||||||
import Measure, { MeasuredComponentProps } from 'react-measure';
|
import Measure, { MeasuredComponentProps } from 'react-measure';
|
||||||
import { isNumber } from 'lodash';
|
import { isNumber } from 'lodash';
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@ import {
|
||||||
|
|
||||||
import * as OS from '../OS';
|
import * as OS from '../OS';
|
||||||
import { LocalizerType } from '../types/Util';
|
import { LocalizerType } from '../types/Util';
|
||||||
|
import { usePrevious } from '../util/hooks';
|
||||||
import { missingCaseError } from '../util/missingCaseError';
|
import { missingCaseError } from '../util/missingCaseError';
|
||||||
|
|
||||||
import { ConversationList } from './ConversationList';
|
import { ConversationList } from './ConversationList';
|
||||||
|
@ -140,9 +141,10 @@ export const LeftPane: React.FC<PropsType> = ({
|
||||||
startSettingGroupMetadata,
|
startSettingGroupMetadata,
|
||||||
toggleConversationInChooseMembers,
|
toggleConversationInChooseMembers,
|
||||||
}) => {
|
}) => {
|
||||||
const previousModeSpecificPropsRef = useRef(modeSpecificProps);
|
const previousModeSpecificProps = usePrevious(
|
||||||
const previousModeSpecificProps = previousModeSpecificPropsRef.current;
|
modeSpecificProps,
|
||||||
previousModeSpecificPropsRef.current = modeSpecificProps;
|
modeSpecificProps
|
||||||
|
);
|
||||||
|
|
||||||
// The left pane can be in various modes: the inbox, the archive, the composer, etc.
|
// The left pane can be in various modes: the inbox, the archive, the composer, etc.
|
||||||
// Ideally, this would render subcomponents such as `<LeftPaneInbox>` or
|
// Ideally, this would render subcomponents such as `<LeftPaneInbox>` or
|
||||||
|
@ -331,6 +333,15 @@ export const LeftPane: React.FC<PropsType> = ({
|
||||||
|
|
||||||
const getRow = useMemo(() => helper.getRow.bind(helper), [helper]);
|
const getRow = useMemo(() => helper.getRow.bind(helper), [helper]);
|
||||||
|
|
||||||
|
const previousSelectedConversationId = usePrevious(
|
||||||
|
selectedConversationId,
|
||||||
|
selectedConversationId
|
||||||
|
);
|
||||||
|
const rowIndexToScrollTo: undefined | number =
|
||||||
|
previousSelectedConversationId === selectedConversationId
|
||||||
|
? undefined
|
||||||
|
: helper.getRowIndexToScrollTo(selectedConversationId);
|
||||||
|
|
||||||
// We ensure that the listKey differs between some modes (e.g. inbox/archived), ensuring
|
// We ensure that the listKey differs between some modes (e.g. inbox/archived), ensuring
|
||||||
// that AutoSizer properly detects the new size of its slot in the flexbox. The
|
// that AutoSizer properly detects the new size of its slot in the flexbox. The
|
||||||
// archive explainer text at the top of the archive view causes problems otherwise.
|
// archive explainer text at the top of the archive view causes problems otherwise.
|
||||||
|
@ -403,9 +414,7 @@ export const LeftPane: React.FC<PropsType> = ({
|
||||||
}}
|
}}
|
||||||
renderMessageSearchResult={renderMessageSearchResult}
|
renderMessageSearchResult={renderMessageSearchResult}
|
||||||
rowCount={helper.getRowCount()}
|
rowCount={helper.getRowCount()}
|
||||||
scrollToRowIndex={helper.getRowIndexToScrollTo(
|
scrollToRowIndex={rowIndexToScrollTo}
|
||||||
selectedConversationId
|
|
||||||
)}
|
|
||||||
shouldRecomputeRowHeights={shouldRecomputeRowHeights}
|
shouldRecomputeRowHeights={shouldRecomputeRowHeights}
|
||||||
showChooseGroupMembers={showChooseGroupMembers}
|
showChooseGroupMembers={showChooseGroupMembers}
|
||||||
startNewConversationFromPhoneNumber={
|
startNewConversationFromPhoneNumber={
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright 2020 Signal Messenger, LLC
|
// Copyright 2020-2021 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import React, { useState, useRef, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import Measure from 'react-measure';
|
import Measure from 'react-measure';
|
||||||
|
|
||||||
import { Timestamp } from './Timestamp';
|
import { Timestamp } from './Timestamp';
|
||||||
|
@ -11,6 +11,7 @@ import {
|
||||||
CallingNotificationType,
|
CallingNotificationType,
|
||||||
getCallingNotificationText,
|
getCallingNotificationText,
|
||||||
} from '../../util/callingNotification';
|
} from '../../util/callingNotification';
|
||||||
|
import { usePrevious } from '../../util/hooks';
|
||||||
import { missingCaseError } from '../../util/missingCaseError';
|
import { missingCaseError } from '../../util/missingCaseError';
|
||||||
import { Tooltip, TooltipPlacement } from '../Tooltip';
|
import { Tooltip, TooltipPlacement } from '../Tooltip';
|
||||||
|
|
||||||
|
@ -34,23 +35,18 @@ type PropsType = CallingNotificationType & PropsActionsType & PropsHousekeeping;
|
||||||
export const CallingNotification: React.FC<PropsType> = React.memo(props => {
|
export const CallingNotification: React.FC<PropsType> = React.memo(props => {
|
||||||
const { conversationId, i18n, messageId, messageSizeChanged } = props;
|
const { conversationId, i18n, messageId, messageSizeChanged } = props;
|
||||||
|
|
||||||
const previousHeightRef = useRef<null | number>(null);
|
|
||||||
const [height, setHeight] = useState<null | number>(null);
|
const [height, setHeight] = useState<null | number>(null);
|
||||||
|
const previousHeight = usePrevious<null | number>(null, height);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (height === null) {
|
if (height === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (previousHeight !== null && height !== previousHeight) {
|
||||||
previousHeightRef.current !== null &&
|
|
||||||
height !== previousHeightRef.current
|
|
||||||
) {
|
|
||||||
messageSizeChanged(messageId, conversationId);
|
messageSizeChanged(messageId, conversationId);
|
||||||
}
|
}
|
||||||
|
}, [height, previousHeight, conversationId, messageId, messageSizeChanged]);
|
||||||
previousHeightRef.current = height;
|
|
||||||
}, [height, conversationId, messageId, messageSizeChanged]);
|
|
||||||
|
|
||||||
let timestamp: number;
|
let timestamp: number;
|
||||||
let callType: 'audio' | 'video';
|
let callType: 'audio' | 'video';
|
||||||
|
|
|
@ -5,6 +5,13 @@ import * as React from 'react';
|
||||||
import { ActionCreatorsMapObject, bindActionCreators } from 'redux';
|
import { ActionCreatorsMapObject, bindActionCreators } from 'redux';
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
|
|
||||||
|
export function usePrevious<T>(initialValue: T, currentValue: T): T {
|
||||||
|
const previousValueRef = React.useRef<T>(initialValue);
|
||||||
|
const result = previousValueRef.current;
|
||||||
|
previousValueRef.current = currentValue;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// Restore focus on teardown
|
// Restore focus on teardown
|
||||||
export const useRestoreFocus = (
|
export const useRestoreFocus = (
|
||||||
// The ref for the element to receive initial focus
|
// The ref for the element to receive initial focus
|
||||||
|
|
|
@ -14375,20 +14375,11 @@
|
||||||
"rule": "React-useRef",
|
"rule": "React-useRef",
|
||||||
"path": "ts/components/ContactPills.js",
|
"path": "ts/components/ContactPills.js",
|
||||||
"line": " const elRef = react_1.useRef(null);",
|
"line": " const elRef = react_1.useRef(null);",
|
||||||
"lineNumber": 28,
|
"lineNumber": 29,
|
||||||
"reasonCategory": "usageTrusted",
|
"reasonCategory": "usageTrusted",
|
||||||
"updated": "2021-03-01T18:34:36.638Z",
|
"updated": "2021-03-01T18:34:36.638Z",
|
||||||
"reasonDetail": "Used for scrolling. Doesn't otherwise manipulate the DOM"
|
"reasonDetail": "Used for scrolling. Doesn't otherwise manipulate the DOM"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"rule": "React-useRef",
|
|
||||||
"path": "ts/components/ContactPills.js",
|
|
||||||
"line": " const previousChildCountRef = react_1.useRef(childCount);",
|
|
||||||
"lineNumber": 30,
|
|
||||||
"reasonCategory": "usageTrusted",
|
|
||||||
"updated": "2021-03-01T18:34:36.638Z",
|
|
||||||
"reasonDetail": "Doesn't reference the DOM. Refers to a number"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"rule": "React-useRef",
|
"rule": "React-useRef",
|
||||||
"path": "ts/components/ConversationList.js",
|
"path": "ts/components/ConversationList.js",
|
||||||
|
@ -14495,24 +14486,6 @@
|
||||||
"reasonCategory": "falseMatch",
|
"reasonCategory": "falseMatch",
|
||||||
"updated": "2020-07-21T18:34:59.251Z"
|
"updated": "2020-07-21T18:34:59.251Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"rule": "React-useRef",
|
|
||||||
"path": "ts/components/LeftPane.js",
|
|
||||||
"line": " const previousModeSpecificPropsRef = react_1.useRef(modeSpecificProps);",
|
|
||||||
"lineNumber": 52,
|
|
||||||
"reasonCategory": "usageTrusted",
|
|
||||||
"updated": "2021-02-12T16:25:08.285Z",
|
|
||||||
"reasonDetail": "Doesn't interact with the DOM."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"rule": "React-useRef",
|
|
||||||
"path": "ts/components/LeftPane.tsx",
|
|
||||||
"line": " const previousModeSpecificPropsRef = useRef(modeSpecificProps);",
|
|
||||||
"lineNumber": 143,
|
|
||||||
"reasonCategory": "usageTrusted",
|
|
||||||
"updated": "2021-02-12T16:25:08.285Z",
|
|
||||||
"reasonDetail": "Doesn't interact with the DOM."
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"rule": "React-createRef",
|
"rule": "React-createRef",
|
||||||
"path": "ts/components/Lightbox.js",
|
"path": "ts/components/Lightbox.js",
|
||||||
|
@ -14584,15 +14557,6 @@
|
||||||
"updated": "2020-12-04T00:11:08.128Z",
|
"updated": "2020-12-04T00:11:08.128Z",
|
||||||
"reasonDetail": "Used to add (and remove) event listeners."
|
"reasonDetail": "Used to add (and remove) event listeners."
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"rule": "React-useRef",
|
|
||||||
"path": "ts/components/conversation/CallingNotification.js",
|
|
||||||
"line": " const previousHeightRef = react_1.useRef(null);",
|
|
||||||
"lineNumber": 37,
|
|
||||||
"reasonCategory": "usageTrusted",
|
|
||||||
"updated": "2020-12-04T00:11:08.128Z",
|
|
||||||
"reasonDetail": "Doesn't interact with the DOM."
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"rule": "React-useRef",
|
"rule": "React-useRef",
|
||||||
"path": "ts/components/conversation/ContactModal.js",
|
"path": "ts/components/conversation/ContactModal.js",
|
||||||
|
@ -15174,11 +15138,20 @@
|
||||||
"reasonCategory": "falseMatch",
|
"reasonCategory": "falseMatch",
|
||||||
"updated": "2020-09-08T23:07:22.682Z"
|
"updated": "2020-09-08T23:07:22.682Z"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"rule": "React-useRef",
|
||||||
|
"path": "ts/util/hooks.js",
|
||||||
|
"line": " const previousValueRef = React.useRef(initialValue);",
|
||||||
|
"lineNumber": 29,
|
||||||
|
"reasonCategory": "usageTrusted",
|
||||||
|
"updated": "2021-03-18T21:41:28.361Z",
|
||||||
|
"reasonDetail": "A generic hook. Typically not to be used with non-DOM values."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"rule": "React-useRef",
|
"rule": "React-useRef",
|
||||||
"path": "ts/util/hooks.js",
|
"path": "ts/util/hooks.js",
|
||||||
"line": " const unobserveRef = React.useRef(null);",
|
"line": " const unobserveRef = React.useRef(null);",
|
||||||
"lineNumber": 95,
|
"lineNumber": 102,
|
||||||
"reasonCategory": "usageTrusted",
|
"reasonCategory": "usageTrusted",
|
||||||
"updated": "2021-01-08T15:46:32.143Z",
|
"updated": "2021-01-08T15:46:32.143Z",
|
||||||
"reasonDetail": "Doesn't manipulate the DOM. This is just a function."
|
"reasonDetail": "Doesn't manipulate the DOM. This is just a function."
|
||||||
|
|
Loading…
Reference in a new issue