Various fixes for message forwarding

This commit is contained in:
Josh Perez 2021-04-28 13:44:48 -07:00 committed by GitHub
parent 3face767aa
commit 353becffac
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 222 additions and 44 deletions

View file

@ -27,7 +27,7 @@ import { BodyRangeType, LocalizerType } from '../types/Util';
import { ModalHost } from './ModalHost';
import { StagedLinkPreview } from './conversation/StagedLinkPreview';
import { assert } from '../util/assert';
import { filterAndSortConversations } from '../util/filterAndSortConversations';
import { filterAndSortConversationsByRecent } from '../util/filterAndSortConversations';
export type DataPropsType = {
attachments?: Array<AttachmentType>;
@ -85,8 +85,8 @@ export const ForwardMessageModal: FunctionComponent<PropsType> = ({
Array<ConversationType>
>([]);
const [searchTerm, setSearchTerm] = useState('');
const [filteredContacts, setFilteredContacts] = useState(
filterAndSortConversations(candidateConversations, '')
const [filteredConversations, setFilteredConversations] = useState(
filterAndSortConversationsByRecent(candidateConversations, '')
);
const [attachmentsToForward, setAttachmentsToForward] = useState(attachments);
const [isEditingMessage, setIsEditingMessage] = useState(false);
@ -148,14 +148,17 @@ export const ForwardMessageModal: FunctionComponent<PropsType> = ({
const normalizedSearchTerm = searchTerm.trim();
useEffect(() => {
const timeout = setTimeout(() => {
setFilteredContacts(
filterAndSortConversations(candidateConversations, normalizedSearchTerm)
setFilteredConversations(
filterAndSortConversationsByRecent(
candidateConversations,
normalizedSearchTerm
)
);
}, 200);
return () => {
clearTimeout(timeout);
};
}, [candidateConversations, normalizedSearchTerm, setFilteredContacts]);
}, [candidateConversations, normalizedSearchTerm, setFilteredConversations]);
const contactLookup = useMemo(() => {
const map = new Map();
@ -165,7 +168,7 @@ export const ForwardMessageModal: FunctionComponent<PropsType> = ({
return map;
}, [candidateConversations]);
const toggleSelectedContact = useCallback(
const toggleSelectedConversation = useCallback(
(conversationId: string) => {
let removeContact = false;
const nextSelectedContacts = selectedContacts.filter(contact => {
@ -187,9 +190,17 @@ export const ForwardMessageModal: FunctionComponent<PropsType> = ({
[contactLookup, selectedContacts, setSelectedContacts]
);
const rowCount = filteredContacts.length;
const handleBackOrClose = useCallback(() => {
if (isEditingMessage) {
setIsEditingMessage(false);
} else {
onClose();
}
}, [isEditingMessage, onClose, setIsEditingMessage]);
const rowCount = filteredConversations.length;
const getRow = (index: number): undefined | Row => {
const contact = filteredContacts[index];
const contact = filteredConversations[index];
if (!contact) {
return undefined;
}
@ -209,8 +220,18 @@ export const ForwardMessageModal: FunctionComponent<PropsType> = ({
};
};
useEffect(() => {
const timeout = setTimeout(() => {
inputRef.current?.focus();
}, 100);
return () => {
clearTimeout(timeout);
};
}, []);
return (
<ModalHost onClose={onClose}>
<ModalHost onEscape={handleBackOrClose} onClose={onClose}>
<div className="module-ForwardMessageModal">
<div
className={classNames('module-ForwardMessageModal__header', {
@ -328,11 +349,6 @@ export const ForwardMessageModal: FunctionComponent<PropsType> = ({
<div
className="module-ForwardMessageModal__list-wrapper"
ref={measureRef}
onKeyDown={event => {
if (event.key === 'Enter') {
inputRef.current?.focus();
}
}}
>
<ConversationList
dimensions={contentRect.bounds}
@ -349,7 +365,7 @@ export const ForwardMessageModal: FunctionComponent<PropsType> = ({
disabledReason !==
ContactCheckboxDisabledReason.MaximumContactsSelected
) {
toggleSelectedContact(conversationId);
toggleSelectedConversation(conversationId);
}
}}
onSelectConversation={shouldNeverBeCalled}

View file

@ -7,13 +7,14 @@ import { createPortal } from 'react-dom';
import { Theme, themeClassName } from '../util/theme';
export type PropsType = {
readonly onEscape?: () => unknown;
readonly onClose: () => unknown;
readonly children: React.ReactElement;
readonly theme?: Theme;
};
export const ModalHost = React.memo(
({ onClose, children, theme }: PropsType) => {
({ onEscape, onClose, children, theme }: PropsType) => {
const [root, setRoot] = React.useState<HTMLElement | null>(null);
useEffect(() => {
@ -30,7 +31,11 @@ export const ModalHost = React.memo(
useEffect(() => {
const handler = (event: KeyboardEvent) => {
if (event.key === 'Escape') {
onClose();
if (onEscape) {
onEscape();
} else {
onClose();
}
event.preventDefault();
event.stopPropagation();
@ -41,7 +46,7 @@ export const ModalHost = React.memo(
return () => {
document.removeEventListener('keydown', handler);
};
}, [onClose]);
}, [onEscape, onClose]);
// This makes it easier to write dialogs to be hosted here; they won't have to worry
// as much about preventing propagation of mouse events.

View file

@ -14,7 +14,7 @@ import { LocalizerType } from '../../../../types/Util';
import { assert } from '../../../../util/assert';
import { getOwn } from '../../../../util/getOwn';
import { missingCaseError } from '../../../../util/missingCaseError';
import { filterAndSortConversations } from '../../../../util/filterAndSortConversations';
import { filterAndSortConversationsByTitle } from '../../../../util/filterAndSortConversations';
import { ConversationType } from '../../../../state/ducks/conversations';
import { ModalHost } from '../../../ModalHost';
import { ContactPills } from '../../../ContactPills';
@ -72,13 +72,16 @@ export const ChooseGroupMembersModal: FunctionComponent<PropsType> = ({
const canContinue = Boolean(selectedContacts.length);
const [filteredContacts, setFilteredContacts] = useState(
filterAndSortConversations(candidateContacts, '')
filterAndSortConversationsByTitle(candidateContacts, '')
);
const normalizedSearchTerm = searchTerm.trim();
useEffect(() => {
const timeout = setTimeout(() => {
setFilteredContacts(
filterAndSortConversations(candidateContacts, normalizedSearchTerm)
filterAndSortConversationsByTitle(
candidateContacts,
normalizedSearchTerm
)
);
}, 200);
return () => {