Emoji Picker: Update recent emojis after picker is closed

This commit is contained in:
Alexander Zinchuk 2021-05-09 03:42:58 +03:00
parent 4559e0ff8f
commit cf044474a4
3 changed files with 39 additions and 15 deletions

View File

@ -124,7 +124,7 @@ type DispatchProps = Pick<GlobalActions, (
'sendMessage' | 'editMessage' | 'saveDraft' | 'forwardMessages' |
'clearDraft' | 'showError' | 'setStickerSearchQuery' | 'setGifSearchQuery' |
'openPollModal' | 'closePollModal' | 'loadScheduledHistory' | 'openChat' | 'closePaymentModal' |
'clearReceipt'
'clearReceipt' | 'addRecentEmoji'
)>;
enum MainButtonState {
@ -189,6 +189,7 @@ const Composer: FC<OwnProps & StateProps & DispatchProps> = ({
closePaymentModal,
openChat,
clearReceipt,
addRecentEmoji,
}) => {
// eslint-disable-next-line no-null/no-null
const appendixRef = useRef<HTMLDivElement>(null);
@ -835,6 +836,7 @@ const Composer: FC<OwnProps & StateProps & DispatchProps> = ({
onGifSelect={handleGifSelect}
onRemoveSymbol={removeSymbol}
onSearchOpen={handleSearchOpen}
addRecentEmoji={addRecentEmoji}
/>
</div>
</div>
@ -948,5 +950,6 @@ export default memo(withGlobal<OwnProps>(
'clearReceipt',
'loadScheduledHistory',
'openChat',
'addRecentEmoji',
]),
)(Composer));

View File

@ -3,7 +3,7 @@ import React, {
} from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn';
import { GlobalState, GlobalActions } from '../../../global/types';
import { GlobalState } from '../../../global/types';
import { MENU_TRANSITION_DURATION } from '../../../config';
import { MEMO_EMPTY_ARRAY } from '../../../util/memo';
@ -31,11 +31,10 @@ import './EmojiPicker.scss';
type OwnProps = {
className?: string;
onEmojiSelect: (emoji: string) => void;
onEmojiSelect: (emoji: string, name: string) => void;
};
type StateProps = Pick<GlobalState, 'recentEmojis'>;
type DispatchProps = Pick<GlobalActions, 'addRecentEmoji'>;
type EmojiCategoryData = { id: string; name: string; emojis: string[] };
const ICONS_BY_CATEGORY: Record<string, string> = {
@ -63,8 +62,8 @@ let emojiDataPromise: Promise<EmojiModule>;
let emojiRawData: EmojiRawData;
let emojiData: EmojiData;
const EmojiPicker: FC<OwnProps & StateProps & DispatchProps> = ({
className, onEmojiSelect, recentEmojis, addRecentEmoji,
const EmojiPicker: FC<OwnProps & StateProps> = ({
className, onEmojiSelect, recentEmojis,
}) => {
// eslint-disable-next-line no-null/no-null
const containerRef = useRef<HTMLDivElement>(null);
@ -161,9 +160,8 @@ const EmojiPicker: FC<OwnProps & StateProps & DispatchProps> = ({
}, []);
const handleEmojiSelect = useCallback((emoji: string, name: string) => {
onEmojiSelect(emoji);
addRecentEmoji({ emoji: name });
}, [addRecentEmoji, onEmojiSelect]);
onEmojiSelect(emoji, name);
}, [onEmojiSelect]);
const canRenderContents = useAsyncRendering([], MENU_TRANSITION_DURATION);
@ -228,5 +226,4 @@ async function ensureEmojiData() {
export default memo(withGlobal<OwnProps>(
(global): StateProps => pick(global, ['recentEmojis']),
(setGlobal, actions): DispatchProps => pick(actions, ['addRecentEmoji']),
)(EmojiPicker));

View File

@ -1,11 +1,11 @@
import React, {
FC, memo, useState, useCallback, useEffect, useLayoutEffect,
FC, memo, useCallback, useEffect, useLayoutEffect, useRef, useState,
} from '../../../lib/teact/teact';
import { ApiSticker, ApiVideo } from '../../../api/types';
import { IAllowedAttachmentOptions } from '../../../modules/helpers';
import { IS_TOUCH_ENV, IS_MOBILE_SCREEN } from '../../../util/environment';
import { IS_MOBILE_SCREEN, IS_TOUCH_ENV } from '../../../util/environment';
import { fastRaf } from '../../../util/schedulers';
import buildClassName from '../../../util/buildClassName';
import useShowTransition from '../../../hooks/useShowTransition';
@ -18,7 +18,7 @@ import Transition from '../../ui/Transition';
import EmojiPicker from './EmojiPicker';
import StickerPicker from './StickerPicker';
import GifPicker from './GifPicker';
import SymbolMenuFooter, { SymbolMenuTabs, SYMBOL_MENU_TAB_TITLES } from './SymbolMenuFooter';
import SymbolMenuFooter, { SYMBOL_MENU_TAB_TITLES, SymbolMenuTabs } from './SymbolMenuFooter';
import Portal from '../../ui/Portal';
import './SymbolMenu.scss';
@ -35,6 +35,7 @@ export type OwnProps = {
onGifSelect: (gif: ApiVideo) => void;
onRemoveSymbol: () => void;
onSearchOpen: (type: 'stickers' | 'gifs') => void;
addRecentEmoji: AnyToVoidFunction;
};
let isActivated = false;
@ -43,9 +44,10 @@ const SymbolMenu: FC<OwnProps> = ({
isOpen, allowedAttachmentOptions,
onLoad, onClose,
onEmojiSelect, onStickerSelect, onGifSelect,
onRemoveSymbol, onSearchOpen,
onRemoveSymbol, onSearchOpen, addRecentEmoji,
}) => {
const [activeTab, setActiveTab] = useState<number>(0);
const [recentEmojis, setRecentEmojis] = useState<string[]>([]);
const [handleMouseEnter, handleMouseLeave] = useMouseInside(isOpen, onClose);
const { shouldRender, transitionClassNames } = useShowTransition(isOpen, onClose, false, false);
@ -80,6 +82,28 @@ const SymbolMenu: FC<OwnProps> = ({
};
}, [isOpen]);
const recentEmojisRef = useRef(recentEmojis);
recentEmojisRef.current = recentEmojis;
useEffect(() => {
if (!recentEmojisRef.current.length) {
return;
}
recentEmojisRef.current.forEach((name) => {
addRecentEmoji({ emoji: name });
});
setRecentEmojis([]);
}, [isOpen, activeTab, addRecentEmoji]);
const handleEmojiSelect = useCallback((emoji: string, name: string) => {
setRecentEmojis((emojis) => {
return [...emojis, name];
});
onEmojiSelect(emoji);
}, [onEmojiSelect]);
const handleSearch = useCallback((type: 'stickers' | 'gifs') => {
onClose();
onSearchOpen(type);
@ -95,7 +119,7 @@ const SymbolMenu: FC<OwnProps> = ({
return (
<EmojiPicker
className="picker-tab"
onEmojiSelect={onEmojiSelect}
onEmojiSelect={handleEmojiSelect}
/>
);
case SymbolMenuTabs.Stickers: