Merge branch 'rm-frequent-emoji-defaults' into 'main'

Remove frequentlyUsedEmoji defaults

See merge request soapbox-pub/soapbox!3265
fix-error-messages
Alex Gleason 2024-11-18 17:36:31 +00:00
commit 4637e208b2
4 zmienionych plików z 29 dodań i 51 usunięć

Wyświetl plik

@ -8,12 +8,12 @@ import { closeModal, openModal } from 'soapbox/actions/modals.ts';
import EmojiComponent from 'soapbox/components/ui/emoji.tsx';
import HStack from 'soapbox/components/ui/hstack.tsx';
import IconButton from 'soapbox/components/ui/icon-button.tsx';
import EmojiPickerDropdown, { getFrequentlyUsedEmojis } from 'soapbox/features/emoji/components/emoji-picker-dropdown.tsx';
import EmojiPickerDropdown from 'soapbox/features/emoji/components/emoji-picker-dropdown.tsx';
import emojiData from 'soapbox/features/emoji/data.ts';
import { useAppDispatch } from 'soapbox/hooks/useAppDispatch.ts';
import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts';
import { useClickOutside } from 'soapbox/hooks/useClickOutside.ts';
import { useFeatures } from 'soapbox/hooks/useFeatures.ts';
import { useFrequentlyUsedEmojis } from 'soapbox/hooks/useFrequentlyUsedEmojis.ts';
import { useSoapboxConfig } from 'soapbox/hooks/useSoapboxConfig.ts';
import { userTouching } from 'soapbox/is-mobile.ts';
@ -74,7 +74,7 @@ const EmojiSelector: React.FC<IEmojiSelector> = ({
}): JSX.Element => {
const { allowedEmoji } = useSoapboxConfig();
const { customEmojiReacts } = useFeatures();
const shortcodes = useAppSelector((state) => getFrequentlyUsedEmojis(state));
const frequentlyUsedEmojis = useFrequentlyUsedEmojis();
const dispatch = useAppDispatch();
const [expanded, setExpanded] = useState(false);
@ -138,7 +138,8 @@ const EmojiSelector: React.FC<IEmojiSelector> = ({
onClose?.();
});
const recentEmojis = shortcodes.reduce<string[]>((results, shortcode) => {
/** Frequently used emojis converted from shortcodes to native. */
const frequentNative = frequentlyUsedEmojis.reduce<string[]>((results, shortcode) => {
const emoji = emojiData.emojis[shortcode]?.skins[0]?.native;
if (emoji) {
results.push(emoji);
@ -146,7 +147,8 @@ const EmojiSelector: React.FC<IEmojiSelector> = ({
return results;
}, []);
const emojis = new Set([...recentEmojis, ...allowedEmoji]);
/** Set of native emojis to display in the selector. */
const emojis = new Set([...frequentNative, ...allowedEmoji]);
return (
<div

Wyświetl plik

@ -1,7 +1,5 @@
import { Map as ImmutableMap } from 'immutable';
import { useEffect, useState, useLayoutEffect, Suspense } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { createSelector } from 'reselect';
import { chooseEmoji } from 'soapbox/actions/emojis.ts';
import { changeSetting } from 'soapbox/actions/settings.ts';
@ -9,9 +7,8 @@ import { useCustomEmojis } from 'soapbox/api/hooks/useCustomEmojis.ts';
import { buildCustomEmojis } from 'soapbox/features/emoji/index.ts';
import { EmojiPicker } from 'soapbox/features/ui/util/async-components.ts';
import { useAppDispatch } from 'soapbox/hooks/useAppDispatch.ts';
import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts';
import { useFrequentlyUsedEmojis } from 'soapbox/hooks/useFrequentlyUsedEmojis.ts';
import { useTheme } from 'soapbox/hooks/useTheme.ts';
import { RootState } from 'soapbox/store.ts';
import type { Emoji, CustomEmoji, NativeEmoji } from 'soapbox/features/emoji/index.ts';
import type { CustomEmoji as MastodonCustomEmoji } from 'soapbox/schemas/custom-emoji.ts';
@ -52,46 +49,6 @@ export interface IEmojiPickerDropdown {
update?: (() => any) | null;
}
const perLine = 8;
const lines = 2;
const DEFAULTS = [
'+1',
'grinning',
'kissing_heart',
'heart_eyes',
'laughing',
'stuck_out_tongue_winking_eye',
'sweat_smile',
'joy',
'yum',
'disappointed',
'thinking_face',
'weary',
'sob',
'sunglasses',
'heart',
'ok_hand',
];
export const getFrequentlyUsedEmojis = createSelector([
(state: RootState) => state.settings.get('frequentlyUsedEmojis', ImmutableMap()),
], (emojiCounters: ImmutableMap<string, number>) => {
let emojis = emojiCounters
.keySeq()
.sort((a, b) => emojiCounters.get(a)! - emojiCounters.get(b)!)
.reverse()
.slice(0, perLine * lines)
.toArray();
if (emojis.length < DEFAULTS.length) {
const uniqueDefaults = DEFAULTS.filter(emoji => !emojis.includes(emoji));
emojis = emojis.concat(uniqueDefaults.slice(0, DEFAULTS.length - emojis.length));
}
return emojis;
});
/** Filter custom emojis to only ones visible in the picker, and sort them alphabetically. */
function filterCustomEmojis(customEmojis: MastodonCustomEmoji[]) {
return customEmojis.filter(e => e.visible_in_picker).sort((a, b) => {
@ -141,7 +98,7 @@ const EmojiPickerDropdown: React.FC<IEmojiPickerDropdown> = ({
const theme = useTheme();
const { customEmojis } = useCustomEmojis();
const frequentlyUsedEmojis = useAppSelector((state) => getFrequentlyUsedEmojis(state));
const frequentlyUsedEmojis = useFrequentlyUsedEmojis();
const handlePick = (emoji: any) => {
setVisible?.(false);
@ -232,7 +189,7 @@ const EmojiPickerDropdown: React.FC<IEmojiPickerDropdown> = ({
custom={withCustom ? [{ emojis: buildCustomEmojis(filterCustomEmojis(customEmojis)) }] : undefined}
title={title}
onEmojiSelect={handlePick}
recent={frequentlyUsedEmojis}
recent={frequentlyUsedEmojis.slice(0, 16)}
perLine={8}
skin={handleSkinTone}
emojiSize={22}

Wyświetl plik

@ -0,0 +1,15 @@
import { useMemo } from 'react';
import { useSettings } from 'soapbox/hooks/useSettings.ts';
/** Return a sorted list of most used emoji **shortcodes** from settings. */
export function useFrequentlyUsedEmojis(): string[] {
const { frequentlyUsedEmojis } = useSettings();
return useMemo(() => {
return Object.entries(frequentlyUsedEmojis)
.sort((a, b) => b[1] - a[1])
.map(([emoji]) => emoji);
}, [frequentlyUsedEmojis]);
}

Wyświetl plik

@ -75,6 +75,10 @@ const settingsSchema = z.object({
}),
/** Settings notifications that have been dismissed. See `useSettingsNotifications` hook. */
dismissedSettingsNotifications: z.array(z.string()).catch([]),
frequentlyUsedEmojis: z.record(
z.string(),
z.number().int().nonnegative(),
).catch({}),
});
type Settings = z.infer<typeof settingsSchema>;