Emoji Picker: Update recent emojis after picker is closed
This commit is contained in:
parent
4559e0ff8f
commit
cf044474a4
@ -124,7 +124,7 @@ type DispatchProps = Pick<GlobalActions, (
|
|||||||
'sendMessage' | 'editMessage' | 'saveDraft' | 'forwardMessages' |
|
'sendMessage' | 'editMessage' | 'saveDraft' | 'forwardMessages' |
|
||||||
'clearDraft' | 'showError' | 'setStickerSearchQuery' | 'setGifSearchQuery' |
|
'clearDraft' | 'showError' | 'setStickerSearchQuery' | 'setGifSearchQuery' |
|
||||||
'openPollModal' | 'closePollModal' | 'loadScheduledHistory' | 'openChat' | 'closePaymentModal' |
|
'openPollModal' | 'closePollModal' | 'loadScheduledHistory' | 'openChat' | 'closePaymentModal' |
|
||||||
'clearReceipt'
|
'clearReceipt' | 'addRecentEmoji'
|
||||||
)>;
|
)>;
|
||||||
|
|
||||||
enum MainButtonState {
|
enum MainButtonState {
|
||||||
@ -189,6 +189,7 @@ const Composer: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
closePaymentModal,
|
closePaymentModal,
|
||||||
openChat,
|
openChat,
|
||||||
clearReceipt,
|
clearReceipt,
|
||||||
|
addRecentEmoji,
|
||||||
}) => {
|
}) => {
|
||||||
// eslint-disable-next-line no-null/no-null
|
// eslint-disable-next-line no-null/no-null
|
||||||
const appendixRef = useRef<HTMLDivElement>(null);
|
const appendixRef = useRef<HTMLDivElement>(null);
|
||||||
@ -835,6 +836,7 @@ const Composer: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
onGifSelect={handleGifSelect}
|
onGifSelect={handleGifSelect}
|
||||||
onRemoveSymbol={removeSymbol}
|
onRemoveSymbol={removeSymbol}
|
||||||
onSearchOpen={handleSearchOpen}
|
onSearchOpen={handleSearchOpen}
|
||||||
|
addRecentEmoji={addRecentEmoji}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -948,5 +950,6 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
'clearReceipt',
|
'clearReceipt',
|
||||||
'loadScheduledHistory',
|
'loadScheduledHistory',
|
||||||
'openChat',
|
'openChat',
|
||||||
|
'addRecentEmoji',
|
||||||
]),
|
]),
|
||||||
)(Composer));
|
)(Composer));
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import React, {
|
|||||||
} from '../../../lib/teact/teact';
|
} from '../../../lib/teact/teact';
|
||||||
import { withGlobal } from '../../../lib/teact/teactn';
|
import { withGlobal } from '../../../lib/teact/teactn';
|
||||||
|
|
||||||
import { GlobalState, GlobalActions } from '../../../global/types';
|
import { GlobalState } from '../../../global/types';
|
||||||
|
|
||||||
import { MENU_TRANSITION_DURATION } from '../../../config';
|
import { MENU_TRANSITION_DURATION } from '../../../config';
|
||||||
import { MEMO_EMPTY_ARRAY } from '../../../util/memo';
|
import { MEMO_EMPTY_ARRAY } from '../../../util/memo';
|
||||||
@ -31,11 +31,10 @@ import './EmojiPicker.scss';
|
|||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
className?: string;
|
className?: string;
|
||||||
onEmojiSelect: (emoji: string) => void;
|
onEmojiSelect: (emoji: string, name: string) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
type StateProps = Pick<GlobalState, 'recentEmojis'>;
|
type StateProps = Pick<GlobalState, 'recentEmojis'>;
|
||||||
type DispatchProps = Pick<GlobalActions, 'addRecentEmoji'>;
|
|
||||||
type EmojiCategoryData = { id: string; name: string; emojis: string[] };
|
type EmojiCategoryData = { id: string; name: string; emojis: string[] };
|
||||||
|
|
||||||
const ICONS_BY_CATEGORY: Record<string, string> = {
|
const ICONS_BY_CATEGORY: Record<string, string> = {
|
||||||
@ -63,8 +62,8 @@ let emojiDataPromise: Promise<EmojiModule>;
|
|||||||
let emojiRawData: EmojiRawData;
|
let emojiRawData: EmojiRawData;
|
||||||
let emojiData: EmojiData;
|
let emojiData: EmojiData;
|
||||||
|
|
||||||
const EmojiPicker: FC<OwnProps & StateProps & DispatchProps> = ({
|
const EmojiPicker: FC<OwnProps & StateProps> = ({
|
||||||
className, onEmojiSelect, recentEmojis, addRecentEmoji,
|
className, onEmojiSelect, recentEmojis,
|
||||||
}) => {
|
}) => {
|
||||||
// eslint-disable-next-line no-null/no-null
|
// eslint-disable-next-line no-null/no-null
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
@ -161,9 +160,8 @@ const EmojiPicker: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleEmojiSelect = useCallback((emoji: string, name: string) => {
|
const handleEmojiSelect = useCallback((emoji: string, name: string) => {
|
||||||
onEmojiSelect(emoji);
|
onEmojiSelect(emoji, name);
|
||||||
addRecentEmoji({ emoji: name });
|
}, [onEmojiSelect]);
|
||||||
}, [addRecentEmoji, onEmojiSelect]);
|
|
||||||
|
|
||||||
const canRenderContents = useAsyncRendering([], MENU_TRANSITION_DURATION);
|
const canRenderContents = useAsyncRendering([], MENU_TRANSITION_DURATION);
|
||||||
|
|
||||||
@ -228,5 +226,4 @@ async function ensureEmojiData() {
|
|||||||
|
|
||||||
export default memo(withGlobal<OwnProps>(
|
export default memo(withGlobal<OwnProps>(
|
||||||
(global): StateProps => pick(global, ['recentEmojis']),
|
(global): StateProps => pick(global, ['recentEmojis']),
|
||||||
(setGlobal, actions): DispatchProps => pick(actions, ['addRecentEmoji']),
|
|
||||||
)(EmojiPicker));
|
)(EmojiPicker));
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
import React, {
|
import React, {
|
||||||
FC, memo, useState, useCallback, useEffect, useLayoutEffect,
|
FC, memo, useCallback, useEffect, useLayoutEffect, useRef, useState,
|
||||||
} from '../../../lib/teact/teact';
|
} from '../../../lib/teact/teact';
|
||||||
|
|
||||||
import { ApiSticker, ApiVideo } from '../../../api/types';
|
import { ApiSticker, ApiVideo } from '../../../api/types';
|
||||||
|
|
||||||
import { IAllowedAttachmentOptions } from '../../../modules/helpers';
|
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 { fastRaf } from '../../../util/schedulers';
|
||||||
import buildClassName from '../../../util/buildClassName';
|
import buildClassName from '../../../util/buildClassName';
|
||||||
import useShowTransition from '../../../hooks/useShowTransition';
|
import useShowTransition from '../../../hooks/useShowTransition';
|
||||||
@ -18,7 +18,7 @@ import Transition from '../../ui/Transition';
|
|||||||
import EmojiPicker from './EmojiPicker';
|
import EmojiPicker from './EmojiPicker';
|
||||||
import StickerPicker from './StickerPicker';
|
import StickerPicker from './StickerPicker';
|
||||||
import GifPicker from './GifPicker';
|
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 Portal from '../../ui/Portal';
|
||||||
|
|
||||||
import './SymbolMenu.scss';
|
import './SymbolMenu.scss';
|
||||||
@ -35,6 +35,7 @@ export type OwnProps = {
|
|||||||
onGifSelect: (gif: ApiVideo) => void;
|
onGifSelect: (gif: ApiVideo) => void;
|
||||||
onRemoveSymbol: () => void;
|
onRemoveSymbol: () => void;
|
||||||
onSearchOpen: (type: 'stickers' | 'gifs') => void;
|
onSearchOpen: (type: 'stickers' | 'gifs') => void;
|
||||||
|
addRecentEmoji: AnyToVoidFunction;
|
||||||
};
|
};
|
||||||
|
|
||||||
let isActivated = false;
|
let isActivated = false;
|
||||||
@ -43,9 +44,10 @@ const SymbolMenu: FC<OwnProps> = ({
|
|||||||
isOpen, allowedAttachmentOptions,
|
isOpen, allowedAttachmentOptions,
|
||||||
onLoad, onClose,
|
onLoad, onClose,
|
||||||
onEmojiSelect, onStickerSelect, onGifSelect,
|
onEmojiSelect, onStickerSelect, onGifSelect,
|
||||||
onRemoveSymbol, onSearchOpen,
|
onRemoveSymbol, onSearchOpen, addRecentEmoji,
|
||||||
}) => {
|
}) => {
|
||||||
const [activeTab, setActiveTab] = useState<number>(0);
|
const [activeTab, setActiveTab] = useState<number>(0);
|
||||||
|
const [recentEmojis, setRecentEmojis] = useState<string[]>([]);
|
||||||
|
|
||||||
const [handleMouseEnter, handleMouseLeave] = useMouseInside(isOpen, onClose);
|
const [handleMouseEnter, handleMouseLeave] = useMouseInside(isOpen, onClose);
|
||||||
const { shouldRender, transitionClassNames } = useShowTransition(isOpen, onClose, false, false);
|
const { shouldRender, transitionClassNames } = useShowTransition(isOpen, onClose, false, false);
|
||||||
@ -80,6 +82,28 @@ const SymbolMenu: FC<OwnProps> = ({
|
|||||||
};
|
};
|
||||||
}, [isOpen]);
|
}, [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') => {
|
const handleSearch = useCallback((type: 'stickers' | 'gifs') => {
|
||||||
onClose();
|
onClose();
|
||||||
onSearchOpen(type);
|
onSearchOpen(type);
|
||||||
@ -95,7 +119,7 @@ const SymbolMenu: FC<OwnProps> = ({
|
|||||||
return (
|
return (
|
||||||
<EmojiPicker
|
<EmojiPicker
|
||||||
className="picker-tab"
|
className="picker-tab"
|
||||||
onEmojiSelect={onEmojiSelect}
|
onEmojiSelect={handleEmojiSelect}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
case SymbolMenuTabs.Stickers:
|
case SymbolMenuTabs.Stickers:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user