Pre-alpha: React with any emoji, behind flag
This commit is contained in:
parent
d13c3d3350
commit
0865a5481c
31 changed files with 572 additions and 234 deletions
|
@ -1,6 +1,7 @@
|
|||
import { take, uniq } from 'lodash';
|
||||
import { EmojiPickDataType } from '../../components/emoji/EmojiPicker';
|
||||
import dataInterface from '../../sql/Client';
|
||||
import { useBoundActions } from '../../util/hooks';
|
||||
|
||||
const { updateEmojiUsage } = dataInterface;
|
||||
|
||||
|
@ -12,32 +13,34 @@ export type EmojisStateType = {
|
|||
|
||||
// Actions
|
||||
|
||||
type UseEmojiPayloadType = string;
|
||||
type UseEmojiAction = {
|
||||
type OnUseEmojiPayloadType = string;
|
||||
type OnUseEmojiAction = {
|
||||
type: 'emojis/USE_EMOJI';
|
||||
payload: Promise<UseEmojiPayloadType>;
|
||||
payload: Promise<OnUseEmojiPayloadType>;
|
||||
};
|
||||
type UseEmojiFulfilledAction = {
|
||||
type OnUseEmojiFulfilledAction = {
|
||||
type: 'emojis/USE_EMOJI_FULFILLED';
|
||||
payload: UseEmojiPayloadType;
|
||||
payload: OnUseEmojiPayloadType;
|
||||
};
|
||||
|
||||
export type EmojisActionType = UseEmojiAction | UseEmojiFulfilledAction;
|
||||
export type EmojisActionType = OnUseEmojiAction | OnUseEmojiFulfilledAction;
|
||||
|
||||
// Action Creators
|
||||
|
||||
export const actions = {
|
||||
useEmoji,
|
||||
onUseEmoji,
|
||||
};
|
||||
|
||||
function useEmoji({ shortName }: EmojiPickDataType): UseEmojiAction {
|
||||
export const useActions = () => useBoundActions(actions);
|
||||
|
||||
function onUseEmoji({ shortName }: EmojiPickDataType): OnUseEmojiAction {
|
||||
return {
|
||||
type: 'emojis/USE_EMOJI',
|
||||
payload: doUseEmoji(shortName),
|
||||
};
|
||||
}
|
||||
|
||||
async function doUseEmoji(shortName: string): Promise<UseEmojiPayloadType> {
|
||||
async function doUseEmoji(shortName: string): Promise<OnUseEmojiPayloadType> {
|
||||
await updateEmojiUsage(shortName);
|
||||
|
||||
return shortName;
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
import { omit } from 'lodash';
|
||||
import { createSelector } from 'reselect';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { StateType } from '../reducer';
|
||||
import * as storageShim from '../../shims/storage';
|
||||
import { isShortName } from '../../components/emoji/lib';
|
||||
import { useBoundActions } from '../../util/hooks';
|
||||
|
||||
// State
|
||||
|
||||
|
@ -53,6 +58,8 @@ export const actions = {
|
|||
resetItems,
|
||||
};
|
||||
|
||||
export const useActions = () => useBoundActions(actions);
|
||||
|
||||
function putItem(key: string, value: any): ItemPutAction {
|
||||
storageShim.put(key, value);
|
||||
|
||||
|
@ -123,3 +130,12 @@ export function reducer(
|
|||
|
||||
return state;
|
||||
}
|
||||
|
||||
// Selectors
|
||||
|
||||
const selectRecentEmojis = createSelector(
|
||||
({ emojis }: StateType) => emojis.recents,
|
||||
recents => recents.filter(isShortName)
|
||||
);
|
||||
|
||||
export const useRecentEmojis = () => useSelector(selectRecentEmojis);
|
||||
|
|
|
@ -81,7 +81,7 @@ const dispatchPropsMap = {
|
|||
mapDispatchToProps.removeItem('showStickersIntroduction'),
|
||||
clearShowPickerHint: () =>
|
||||
mapDispatchToProps.removeItem('showStickerPickerHint'),
|
||||
onPickEmoji: mapDispatchToProps.useEmoji,
|
||||
onPickEmoji: mapDispatchToProps.onUseEmoji,
|
||||
};
|
||||
|
||||
const smart = connect(mapStateToProps, dispatchPropsMap);
|
||||
|
|
57
ts/state/smart/EmojiPicker.tsx
Normal file
57
ts/state/smart/EmojiPicker.tsx
Normal file
|
@ -0,0 +1,57 @@
|
|||
import * as React from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { get } from 'lodash';
|
||||
import { StateType } from '../reducer';
|
||||
import { useActions as useItemActions, useRecentEmojis } from '../ducks/items';
|
||||
import { useActions as useEmojiActions } from '../ducks/emojis';
|
||||
|
||||
import {
|
||||
EmojiPicker,
|
||||
Props as EmojiPickerProps,
|
||||
} from '../../components/emoji/EmojiPicker';
|
||||
import { getIntl } from '../selectors/user';
|
||||
import { LocalizerType } from '../../types/Util';
|
||||
|
||||
export const SmartEmojiPicker = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
Pick<EmojiPickerProps, 'onPickEmoji' | 'onClose' | 'style'>
|
||||
>(({ onPickEmoji, onClose, style }, ref) => {
|
||||
const i18n = useSelector<StateType, LocalizerType>(getIntl);
|
||||
const skinTone = useSelector<StateType, number>(state =>
|
||||
get(state, ['items', 'skinTone'], 0)
|
||||
);
|
||||
|
||||
const recentEmojis = useRecentEmojis();
|
||||
|
||||
const { putItem } = useItemActions();
|
||||
|
||||
const onSetSkinTone = React.useCallback(
|
||||
tone => {
|
||||
putItem('skinTone', tone);
|
||||
},
|
||||
[putItem]
|
||||
);
|
||||
|
||||
const { onUseEmoji } = useEmojiActions();
|
||||
|
||||
const handlePickEmoji = React.useCallback(
|
||||
data => {
|
||||
onUseEmoji({ shortName: data.shortName });
|
||||
onPickEmoji(data);
|
||||
},
|
||||
[onUseEmoji, onPickEmoji]
|
||||
);
|
||||
|
||||
return (
|
||||
<EmojiPicker
|
||||
ref={ref}
|
||||
i18n={i18n}
|
||||
skinTone={skinTone}
|
||||
onSetSkinTone={onSetSkinTone}
|
||||
onPickEmoji={handlePickEmoji}
|
||||
recentEmojis={recentEmojis}
|
||||
onClose={onClose}
|
||||
style={style}
|
||||
/>
|
||||
);
|
||||
});
|
|
@ -3,6 +3,7 @@ import React from 'react';
|
|||
import { connect } from 'react-redux';
|
||||
import { mapDispatchToProps } from '../actions';
|
||||
import { Timeline } from '../../components/conversation/Timeline';
|
||||
import { RenderEmojiPickerProps } from '../../components/conversation/ReactionPicker';
|
||||
import { StateType } from '../reducer';
|
||||
|
||||
import { getIntl } from '../selectors/user';
|
||||
|
@ -16,6 +17,7 @@ import { SmartTimelineItem } from './TimelineItem';
|
|||
import { SmartTypingBubble } from './TypingBubble';
|
||||
import { SmartLastSeenIndicator } from './LastSeenIndicator';
|
||||
import { SmartTimelineLoadingRow } from './TimelineLoadingRow';
|
||||
import { SmartEmojiPicker } from './EmojiPicker';
|
||||
|
||||
// Workaround: A react component's required properties are filtering up through connect()
|
||||
// https://github.com/DefinitelyTyped/DefinitelyTyped/issues/31363
|
||||
|
@ -41,6 +43,22 @@ function renderItem(
|
|||
{...actionProps}
|
||||
conversationId={conversationId}
|
||||
id={messageId}
|
||||
renderEmojiPicker={renderEmojiPicker}
|
||||
/>
|
||||
);
|
||||
}
|
||||
function renderEmojiPicker({
|
||||
ref,
|
||||
onPickEmoji,
|
||||
onClose,
|
||||
style,
|
||||
}: RenderEmojiPickerProps): JSX.Element {
|
||||
return (
|
||||
<SmartEmojiPicker
|
||||
ref={ref}
|
||||
onPickEmoji={onPickEmoji}
|
||||
onClose={onClose}
|
||||
style={style}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue