feat(web): emoji picker
Plain system-emoji grid (README §3.3's mockup itself has no custom emoji asset list, just gray placeholder tiles captioned "use system emoji or a branded pack" -- matches the old app's own reasoning, no WeChat/QQ-style sticker art available). Recent-emoji tab persists via localStorage, capped at 30, same as the old app's send-message.jsx. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
59d1033a92
commit
aa3e464b35
@@ -5,6 +5,7 @@ import type { StoredMessage } from 'tinode-sdk';
|
||||
import { Drafty } from 'tinode-sdk';
|
||||
|
||||
import { Icon } from '@/app/Icon';
|
||||
import { EmojiPanel } from '@/features/messages/EmojiPanel';
|
||||
import { ForwardPickerModal } from '@/features/messages/ForwardPickerModal';
|
||||
import { MessageContextMenu } from '@/features/messages/MessageContextMenu';
|
||||
import { MessageRow } from '@/features/messages/MessageBubble';
|
||||
@@ -46,6 +47,7 @@ export function ConversationView() {
|
||||
const [loadingOlder, setLoadingOlder] = useState(false);
|
||||
const [replyTo, setReplyTo] = useState<StoredMessage | null>(null);
|
||||
const [forwardMsg, setForwardMsg] = useState<StoredMessage | null>(null);
|
||||
const [emojiOpen, setEmojiOpen] = useState(false);
|
||||
const streamRef = useRef<HTMLDivElement>(null);
|
||||
const autoScrollRef = useRef(true);
|
||||
|
||||
@@ -288,8 +290,24 @@ export function ConversationView() {
|
||||
</button>
|
||||
</div>
|
||||
) : null}
|
||||
<div className="flex items-center gap-1 px-1 pb-1">
|
||||
<Icon name="sentiment_satisfied_alt" className="grid h-8.5 w-8.5 place-items-center rounded text-[22px] text-icon-default" />
|
||||
<div className="relative flex items-center gap-1 px-1 pb-1">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setEmojiOpen((v) => !v)}
|
||||
className={`grid h-8.5 w-8.5 place-items-center rounded text-[22px] ${emojiOpen ? 'bg-accent-soft-bg text-accent' : 'text-icon-default'}`}
|
||||
>
|
||||
<Icon name="sentiment_satisfied_alt" />
|
||||
</button>
|
||||
{emojiOpen ? (
|
||||
<div className="absolute bottom-full left-0 z-20 mb-2">
|
||||
<EmojiPanel
|
||||
onPick={(emoji) => {
|
||||
setDraft((d) => d + emoji);
|
||||
setEmojiOpen(false);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
<label className="grid h-8.5 w-8.5 cursor-pointer place-items-center rounded text-[22px] text-icon-default">
|
||||
<Icon name="image" />
|
||||
<input type="file" accept="image/*" onChange={handlePickImage} className="hidden" />
|
||||
|
||||
Reference in New Issue
Block a user