);
}
function filterShortcodes(emojis, searchTerm) {
searchTerm = searchTerm.toLowerCase();
// Return an array of shortcodes that start with or contain the search term, sorted by relevance and limited to the first 5
return emojis
.sort((a, b) => {
let aLower = a.shortcode.toLowerCase();
let bLower = b.shortcode.toLowerCase();
let aStartsWith = aLower.startsWith(searchTerm);
let bStartsWith = bLower.startsWith(searchTerm);
let aContains = aLower.includes(searchTerm);
let bContains = bLower.includes(searchTerm);
let bothStartWith = aStartsWith && bStartsWith;
let bothContain = aContains && bContains;
return bothStartWith
? a.length - b.length
: aStartsWith
? -1
: bStartsWith
? 1
: bothContain
? a.length - b.length
: aContains
? -1
: bContains
? 1
: 0;
})
.slice(0, 5);
}
function encodeHTML(str) {
return str.replace(/[&<>"']/g, function (char) {
return '' + char.charCodeAt(0) + ';';
});
}
function removeNullUndefined(obj) {
for (let key in obj) {
if (obj[key] === null || obj[key] === undefined) {
delete obj[key];
}
}
return obj;
}
function CustomEmojisModal({
masto,
instance,
onClose = () => {},
onSelect = () => {},
}) {
const [uiState, setUIState] = useState('default');
const customEmojisList = useRef([]);
const [customEmojis, setCustomEmojis] = useState([]);
const recentlyUsedCustomEmojis = useMemo(
() => store.account.get('recentlyUsedCustomEmojis') || [],
);
const searcherRef = useRef();
useEffect(() => {
setUIState('loading');
(async () => {
try {
const [emojis, searcher] = await getCustomEmojis(instance, masto);
console.log('emojis', emojis);
searcherRef.current = searcher;
setCustomEmojis(emojis);
setUIState('default');
} catch (e) {
setUIState('error');
console.error(e);
}
})();
}, []);
const customEmojisCatList = useMemo(() => {
// Group emojis by category
const emojisCat = {
'--recent--': recentlyUsedCustomEmojis.filter((emoji) =>
customEmojis.find((e) => e.shortcode === emoji.shortcode),
),
};
const othersCat = [];
customEmojis.forEach((emoji) => {
customEmojisList.current?.push?.(emoji);
if (!emoji.category) {
othersCat.push(emoji);
return;
}
if (!emojisCat[emoji.category]) {
emojisCat[emoji.category] = [];
}
emojisCat[emoji.category].push(emoji);
});
if (othersCat.length) {
emojisCat['--others--'] = othersCat;
}
return emojisCat;
}, [customEmojis]);
const scrollableRef = useRef();
const [matches, setMatches] = useState(null);
const onFind = useCallback(
(e) => {
const { value } = e.target;
if (value) {
const results = searcherRef.current?.search(value, {
limit: CUSTOM_EMOJIS_COUNT,
});
setMatches(results.map((r) => r.item));
scrollableRef.current?.scrollTo?.(0, 0);
} else {
setMatches(null);
}
},
[customEmojis],
);
const onSelectEmoji = useCallback(
(emoji) => {
onSelect?.(emoji);
onClose?.();
queueMicrotask(() => {
let recentlyUsedCustomEmojis =
store.account.get('recentlyUsedCustomEmojis') || [];
const recentlyUsedEmojiIndex = recentlyUsedCustomEmojis.findIndex(
(e) => e.shortcode === emoji.shortcode,
);
if (recentlyUsedEmojiIndex !== -1) {
// Move emoji to index 0
recentlyUsedCustomEmojis.splice(recentlyUsedEmojiIndex, 1);
recentlyUsedCustomEmojis.unshift(emoji);
} else {
recentlyUsedCustomEmojis.unshift(emoji);
// Remove unavailable ones
recentlyUsedCustomEmojis = recentlyUsedCustomEmojis.filter((e) =>
customEmojisList.current?.find?.(
(emoji) => emoji.shortcode === e.shortcode,
),
);
// Limit to 10
recentlyUsedCustomEmojis = recentlyUsedCustomEmojis.slice(0, 10);
}
// Store back
store.account.set('recentlyUsedCustomEmojis', recentlyUsedCustomEmojis);
});
},
[onSelect],
);
return (