refac
This commit is contained in:
@@ -11,6 +11,9 @@
|
|||||||
import emojiGroups from '$lib/emoji-groups.json';
|
import emojiGroups from '$lib/emoji-groups.json';
|
||||||
import emojiShortCodes from '$lib/emoji-shortcodes.json';
|
import emojiShortCodes from '$lib/emoji-shortcodes.json';
|
||||||
|
|
||||||
|
import { settings } from '$lib/stores';
|
||||||
|
import { updateUserSettings } from '$lib/apis/users';
|
||||||
|
|
||||||
const i18n = getContext('i18n');
|
const i18n = getContext('i18n');
|
||||||
|
|
||||||
export let onClose = () => {};
|
export let onClose = () => {};
|
||||||
@@ -20,12 +23,37 @@
|
|||||||
export let user = null;
|
export let user = null;
|
||||||
export let selected = null;
|
export let selected = null;
|
||||||
|
|
||||||
|
const MAX_RECENT = 30;
|
||||||
|
|
||||||
let show = false;
|
let show = false;
|
||||||
let emojis = emojiShortCodes;
|
let emojis = emojiShortCodes;
|
||||||
let search = '';
|
let search = '';
|
||||||
let flattenedEmojis = [];
|
let flattenedEmojis = [];
|
||||||
let emojiRows = [];
|
let emojiRows = [];
|
||||||
|
|
||||||
|
let saveDebounceTimer: ReturnType<typeof setTimeout> | null = null;
|
||||||
|
|
||||||
|
$: recentEmojiNames = ($settings?.recentEmojis ?? [])
|
||||||
|
.filter((name) => emojiShortCodes[name])
|
||||||
|
.slice(0, MAX_RECENT);
|
||||||
|
|
||||||
|
function saveRecentEmoji(emojiName: string) {
|
||||||
|
// Remove if already present, then prepend
|
||||||
|
const updated = [emojiName, ...recentEmojiNames.filter((n) => n !== emojiName)].slice(
|
||||||
|
0,
|
||||||
|
MAX_RECENT
|
||||||
|
);
|
||||||
|
|
||||||
|
// Update store immediately (reactive UI)
|
||||||
|
settings.set({ ...$settings, recentEmojis: updated });
|
||||||
|
|
||||||
|
// Debounce backend save (avoid API spam on rapid picks)
|
||||||
|
if (saveDebounceTimer) clearTimeout(saveDebounceTimer);
|
||||||
|
saveDebounceTimer = setTimeout(async () => {
|
||||||
|
await updateUserSettings(localStorage.token, { ui: { ...$settings, recentEmojis: updated } });
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
// Reactive statement to filter the emojis based on search query
|
// Reactive statement to filter the emojis based on search query
|
||||||
$: {
|
$: {
|
||||||
if (search) {
|
if (search) {
|
||||||
@@ -55,6 +83,22 @@
|
|||||||
// Flatten emoji groups and group them into rows of 8 for virtual scrolling
|
// Flatten emoji groups and group them into rows of 8 for virtual scrolling
|
||||||
$: {
|
$: {
|
||||||
flattenedEmojis = [];
|
flattenedEmojis = [];
|
||||||
|
|
||||||
|
// Add "Recently Used" group first (only when not searching)
|
||||||
|
if (!search && recentEmojiNames.length > 0) {
|
||||||
|
flattenedEmojis.push({ type: 'group', label: $i18n.t('Recently Used') });
|
||||||
|
flattenedEmojis.push(
|
||||||
|
...recentEmojiNames.map((emoji) => ({
|
||||||
|
type: 'emoji',
|
||||||
|
name: emoji,
|
||||||
|
shortCodes:
|
||||||
|
typeof emojiShortCodes[emoji] === 'string'
|
||||||
|
? [emojiShortCodes[emoji]]
|
||||||
|
: emojiShortCodes[emoji]
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Object.keys(emojiGroups).forEach((group) => {
|
Object.keys(emojiGroups).forEach((group) => {
|
||||||
const groupEmojis = emojiGroups[group].filter((emoji) => emojis[emoji]);
|
const groupEmojis = emojiGroups[group].filter((emoji) => emojis[emoji]);
|
||||||
if (groupEmojis.length > 0) {
|
if (groupEmojis.length > 0) {
|
||||||
@@ -97,6 +141,7 @@
|
|||||||
// Handle emoji selection
|
// Handle emoji selection
|
||||||
function selectEmoji(emoji) {
|
function selectEmoji(emoji) {
|
||||||
const selectedCode = emoji.shortCodes[0];
|
const selectedCode = emoji.shortCodes[0];
|
||||||
|
saveRecentEmoji(emoji.name);
|
||||||
if (selected === selectedCode) {
|
if (selected === selectedCode) {
|
||||||
onSubmit(null);
|
onSubmit(null);
|
||||||
} else {
|
} else {
|
||||||
@@ -140,10 +185,10 @@
|
|||||||
{:else}
|
{:else}
|
||||||
<div class="w-full flex ml-0.5">
|
<div class="w-full flex ml-0.5">
|
||||||
<VirtualList rowHeight={ROW_HEIGHT} items={emojiRows} height={384} let:item>
|
<VirtualList rowHeight={ROW_HEIGHT} items={emojiRows} height={384} let:item>
|
||||||
<div class="w-full">
|
<div class="w-full mb-2.5">
|
||||||
{#if item.length === 1 && item[0].type === 'group'}
|
{#if item.length === 1 && item[0].type === 'group'}
|
||||||
<!-- Render group header -->
|
<!-- Render group header -->
|
||||||
<div class="text-xs font-medium mb-2 text-gray-500 dark:text-gray-400">
|
<div class="text-xs font-medium -mb-1 text-gray-500 dark:text-gray-400">
|
||||||
{item[0].label}
|
{item[0].label}
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
|
|||||||
@@ -219,6 +219,7 @@ type Settings = {
|
|||||||
chatDirection?: 'LTR' | 'RTL' | 'auto';
|
chatDirection?: 'LTR' | 'RTL' | 'auto';
|
||||||
ctrlEnterToSend?: boolean;
|
ctrlEnterToSend?: boolean;
|
||||||
renderMarkdownInPreviews?: boolean;
|
renderMarkdownInPreviews?: boolean;
|
||||||
|
recentEmojis?: string[];
|
||||||
|
|
||||||
system?: string;
|
system?: string;
|
||||||
seed?: number;
|
seed?: number;
|
||||||
|
|||||||
Reference in New Issue
Block a user