Attachment Modal: Support Emoji Tooltip, fix layout and pasting from clipboard (#1093)
This commit is contained in:
parent
73e32621a5
commit
f7972c87f3
@ -9,6 +9,7 @@ import { getFileExtension } from '../../common/helpers/documentInfo';
|
|||||||
import captureEscKeyListener from '../../../util/captureEscKeyListener';
|
import captureEscKeyListener from '../../../util/captureEscKeyListener';
|
||||||
import usePrevious from '../../../hooks/usePrevious';
|
import usePrevious from '../../../hooks/usePrevious';
|
||||||
import useMentionTooltip from './hooks/useMentionTooltip';
|
import useMentionTooltip from './hooks/useMentionTooltip';
|
||||||
|
import useEmojiTooltip from './hooks/useEmojiTooltip';
|
||||||
import useLang from '../../../hooks/useLang';
|
import useLang from '../../../hooks/useLang';
|
||||||
|
|
||||||
import Button from '../../ui/Button';
|
import Button from '../../ui/Button';
|
||||||
@ -16,6 +17,7 @@ import Modal from '../../ui/Modal';
|
|||||||
import File from '../../common/File';
|
import File from '../../common/File';
|
||||||
import MessageInput from './MessageInput';
|
import MessageInput from './MessageInput';
|
||||||
import MentionTooltip from './MentionTooltip';
|
import MentionTooltip from './MentionTooltip';
|
||||||
|
import EmojiTooltip from './EmojiTooltip.async';
|
||||||
|
|
||||||
import './AttachmentModal.scss';
|
import './AttachmentModal.scss';
|
||||||
|
|
||||||
@ -23,9 +25,12 @@ export type OwnProps = {
|
|||||||
attachments: ApiAttachment[];
|
attachments: ApiAttachment[];
|
||||||
caption: string;
|
caption: string;
|
||||||
canSuggestMembers?: boolean;
|
canSuggestMembers?: boolean;
|
||||||
|
canSuggestEmoji?: boolean;
|
||||||
currentUserId?: number;
|
currentUserId?: number;
|
||||||
groupChatMembers?: ApiChatMember[];
|
groupChatMembers?: ApiChatMember[];
|
||||||
usersById?: Record<number, ApiUser>;
|
usersById?: Record<number, ApiUser>;
|
||||||
|
recentEmojis: string[];
|
||||||
|
addRecentEmoji: AnyToVoidFunction;
|
||||||
onCaptionUpdate: (html: string) => void;
|
onCaptionUpdate: (html: string) => void;
|
||||||
onSend: () => void;
|
onSend: () => void;
|
||||||
onClear: () => void;
|
onClear: () => void;
|
||||||
@ -38,7 +43,9 @@ const AttachmentModal: FC<OwnProps> = ({
|
|||||||
groupChatMembers,
|
groupChatMembers,
|
||||||
currentUserId,
|
currentUserId,
|
||||||
usersById,
|
usersById,
|
||||||
|
recentEmojis,
|
||||||
onCaptionUpdate,
|
onCaptionUpdate,
|
||||||
|
addRecentEmoji,
|
||||||
onSend,
|
onSend,
|
||||||
onClear,
|
onClear,
|
||||||
}) => {
|
}) => {
|
||||||
@ -59,6 +66,15 @@ const AttachmentModal: FC<OwnProps> = ({
|
|||||||
currentUserId,
|
currentUserId,
|
||||||
usersById,
|
usersById,
|
||||||
);
|
);
|
||||||
|
const {
|
||||||
|
isEmojiTooltipOpen, closeEmojiTooltip, filteredEmojis, insertEmoji,
|
||||||
|
} = useEmojiTooltip(
|
||||||
|
isOpen,
|
||||||
|
caption,
|
||||||
|
recentEmojis,
|
||||||
|
EDITABLE_INPUT_MODAL_ID,
|
||||||
|
onCaptionUpdate,
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => (isOpen ? captureEscKeyListener(onClear) : undefined), [isOpen, onClear]);
|
useEffect(() => (isOpen ? captureEscKeyListener(onClear) : undefined), [isOpen, onClear]);
|
||||||
|
|
||||||
@ -144,6 +160,13 @@ const AttachmentModal: FC<OwnProps> = ({
|
|||||||
filteredChatMembers={mentionFilteredMembers}
|
filteredChatMembers={mentionFilteredMembers}
|
||||||
usersById={usersById}
|
usersById={usersById}
|
||||||
/>
|
/>
|
||||||
|
<EmojiTooltip
|
||||||
|
isOpen={isEmojiTooltipOpen}
|
||||||
|
emojis={filteredEmojis}
|
||||||
|
onClose={closeEmojiTooltip}
|
||||||
|
onEmojiSelect={insertEmoji}
|
||||||
|
addRecentEmoji={addRecentEmoji}
|
||||||
|
/>
|
||||||
<MessageInput
|
<MessageInput
|
||||||
id="caption-input-text"
|
id="caption-input-text"
|
||||||
html={caption}
|
html={caption}
|
||||||
|
|||||||
@ -256,7 +256,7 @@
|
|||||||
padding-top: calc(1rem - var(--border-width));
|
padding-top: calc(1rem - var(--border-width));
|
||||||
padding-bottom: calc(1rem - var(--border-width));
|
padding-bottom: calc(1rem - var(--border-width));
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
line-height: 1.5rem;
|
line-height: 1.375rem;
|
||||||
|
|
||||||
&.overflown {
|
&.overflown {
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
@ -276,7 +276,7 @@
|
|||||||
|
|
||||||
.placeholder-text {
|
.placeholder-text {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 1rem;
|
bottom: .9375rem;
|
||||||
color: var(--color-placeholders);
|
color: var(--color-placeholders);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
|
||||||
@ -318,6 +318,8 @@
|
|||||||
min-height: 3.5rem;
|
min-height: 3.5rem;
|
||||||
max-height: 26rem;
|
max-height: 26rem;
|
||||||
line-height: 1.3125;
|
line-height: 1.3125;
|
||||||
|
padding-top: calc(1.15625rem - var(--border-width));
|
||||||
|
padding-bottom: calc(1.15625rem - var(--border-width));
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
height: 2.875rem;
|
height: 2.875rem;
|
||||||
@ -359,13 +361,14 @@
|
|||||||
|
|
||||||
#caption-input-text {
|
#caption-input-text {
|
||||||
.form-control {
|
.form-control {
|
||||||
|
height: 3.25rem;
|
||||||
min-height: 3.25rem;
|
min-height: 3.25rem;
|
||||||
max-height: 15rem;
|
max-height: 15rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.placeholder-text {
|
.placeholder-text {
|
||||||
bottom: 1rem;
|
bottom: .8125rem;
|
||||||
left: 1rem;
|
left: .90625rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -301,9 +301,9 @@ const Composer: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
setHtml,
|
setHtml,
|
||||||
);
|
);
|
||||||
|
|
||||||
const insertTextAndUpdateCursor = useCallback((text: string) => {
|
const insertTextAndUpdateCursor = useCallback((text: string, inputId: string = EDITABLE_INPUT_ID) => {
|
||||||
const selection = window.getSelection()!;
|
const selection = window.getSelection()!;
|
||||||
const messageInput = document.getElementById(EDITABLE_INPUT_ID)!;
|
const messageInput = document.getElementById(inputId)!;
|
||||||
const newHtml = renderText(text, ['escape_html', 'emoji_html', 'br_html'])
|
const newHtml = renderText(text, ['escape_html', 'emoji_html', 'br_html'])
|
||||||
.join('')
|
.join('')
|
||||||
.replace(/\u200b+/g, '\u200b');
|
.replace(/\u200b+/g, '\u200b');
|
||||||
@ -679,7 +679,9 @@ const Composer: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
groupChatMembers={groupChatMembers}
|
groupChatMembers={groupChatMembers}
|
||||||
currentUserId={currentUserId}
|
currentUserId={currentUserId}
|
||||||
usersById={usersById}
|
usersById={usersById}
|
||||||
|
recentEmojis={recentEmojis}
|
||||||
onCaptionUpdate={setHtml}
|
onCaptionUpdate={setHtml}
|
||||||
|
addRecentEmoji={addRecentEmoji}
|
||||||
onSend={shouldSchedule ? openCalendar : handleSend}
|
onSend={shouldSchedule ? openCalendar : handleSend}
|
||||||
onClear={handleClearAttachment}
|
onClear={handleClearAttachment}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -8,7 +8,7 @@ const CLIPBOARD_ACCEPTED_TYPES = ['image/png', 'image/jpeg', 'image/gif'];
|
|||||||
const MAX_MESSAGE_LENGTH = 4096;
|
const MAX_MESSAGE_LENGTH = 4096;
|
||||||
|
|
||||||
export default (
|
export default (
|
||||||
insertTextAndUpdateCursor: (text: string) => void,
|
insertTextAndUpdateCursor: (text: string, inputId?: string) => void,
|
||||||
setAttachments: StateHookSetter<ApiAttachment[]>,
|
setAttachments: StateHookSetter<ApiAttachment[]>,
|
||||||
editedMessage: ApiMessage | undefined,
|
editedMessage: ApiMessage | undefined,
|
||||||
) => {
|
) => {
|
||||||
@ -43,7 +43,7 @@ export default (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (pastedText) {
|
if (pastedText) {
|
||||||
insertTextAndUpdateCursor(pastedText);
|
insertTextAndUpdateCursor(pastedText, input ? input.id : undefined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -56,7 +56,7 @@ export default function useEmojiTooltip(
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!html || !emojiIds.length) {
|
if (!isAllowed || !html || !emojiIds.length) {
|
||||||
unmarkIsOpen();
|
unmarkIsOpen();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -82,7 +82,7 @@ export default function useEmojiTooltip(
|
|||||||
} else {
|
} else {
|
||||||
unmarkIsOpen();
|
unmarkIsOpen();
|
||||||
}
|
}
|
||||||
}, [emojiIds, html, markIsOpen, recentEmojis, unmarkIsOpen]);
|
}, [emojiIds, html, isAllowed, markIsOpen, recentEmojis, unmarkIsOpen]);
|
||||||
|
|
||||||
const insertEmoji = useCallback((textEmoji: string) => {
|
const insertEmoji = useCallback((textEmoji: string) => {
|
||||||
const atIndex = html.lastIndexOf(':');
|
const atIndex = html.lastIndexOf(':');
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user