feat(web): bulk forward/favorite in multi-select mode
Rounds out the multi-select bottom bar (README §3.6) with 转发/收藏 alongside the existing 删除 -- reuses the single-message ForwardPickerModal/ favoriteMessages/forwardMessage machinery from the context-menu actions, just applied to the whole selected set. One "转发" button (not separate 逐条/合并 buttons) matching the old app's real dialog-internal mode toggle, which this app's simplified single-target picker doesn't model -- already noted as a scope cut in ForwardPickerModal's own docstring. Verified live: entering multi-select via a message's context menu shows 转发/收藏/删除, and bulk-favorite POSTs a real /v1/im/favorites/batch request. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
03b8098b3c
commit
d5440b962b
@@ -47,6 +47,7 @@ export function ConversationView() {
|
|||||||
const [selectedSeqs, setSelectedSeqs] = useState<Set<number>>(new Set());
|
const [selectedSeqs, setSelectedSeqs] = useState<Set<number>>(new Set());
|
||||||
const [loadingOlder, setLoadingOlder] = useState(false);
|
const [loadingOlder, setLoadingOlder] = useState(false);
|
||||||
const [recording, setRecording] = useState(false);
|
const [recording, setRecording] = useState(false);
|
||||||
|
const [bulkForwardOpen, setBulkForwardOpen] = useState(false);
|
||||||
const [replyTo, setReplyTo] = useState<StoredMessage | null>(null);
|
const [replyTo, setReplyTo] = useState<StoredMessage | null>(null);
|
||||||
const [forwardMsg, setForwardMsg] = useState<StoredMessage | null>(null);
|
const [forwardMsg, setForwardMsg] = useState<StoredMessage | null>(null);
|
||||||
const [emojiOpen, setEmojiOpen] = useState(false);
|
const [emojiOpen, setEmojiOpen] = useState(false);
|
||||||
@@ -161,6 +162,22 @@ export function ConversationView() {
|
|||||||
exitSelectMode();
|
exitSelectMode();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const bulkFavorite = () => {
|
||||||
|
if (selectedSeqs.size === 0) return;
|
||||||
|
favoriteMessages([...selectedSeqs].map((seq) => ({ topic: topicId, seq }))).catch(() => {});
|
||||||
|
exitSelectMode();
|
||||||
|
};
|
||||||
|
|
||||||
|
const bulkForward = (targetTopic: string) => {
|
||||||
|
const target = tinode.getTopic(targetTopic);
|
||||||
|
for (const seq of selectedSeqs) {
|
||||||
|
const msg = topic.findMessage(seq);
|
||||||
|
if (msg) forwardMessage(topicId, msg, target);
|
||||||
|
}
|
||||||
|
setBulkForwardOpen(false);
|
||||||
|
exitSelectMode();
|
||||||
|
};
|
||||||
|
|
||||||
const handleAction = (action: MessageAction) => {
|
const handleAction = (action: MessageAction) => {
|
||||||
const msg = menu?.msg;
|
const msg = menu?.msg;
|
||||||
setMenu(null);
|
setMenu(null);
|
||||||
@@ -275,6 +292,24 @@ export function ConversationView() {
|
|||||||
|
|
||||||
{selectMode ? (
|
{selectMode ? (
|
||||||
<div className="flex h-18 flex-none items-center justify-around border-t border-border-panel bg-white">
|
<div className="flex h-18 flex-none items-center justify-around border-t border-border-panel bg-white">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setBulkForwardOpen(true)}
|
||||||
|
disabled={selectedSeqs.size === 0}
|
||||||
|
className="flex flex-col items-center gap-1 text-text-secondary disabled:opacity-40"
|
||||||
|
>
|
||||||
|
<Icon name="reply" className="text-[22px]" />
|
||||||
|
<span className="text-xs">转发</span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={bulkFavorite}
|
||||||
|
disabled={selectedSeqs.size === 0}
|
||||||
|
className="flex flex-col items-center gap-1 text-text-secondary disabled:opacity-40"
|
||||||
|
>
|
||||||
|
<Icon name="inventory_2" className="text-[22px]" />
|
||||||
|
<span className="text-xs">收藏</span>
|
||||||
|
</button>
|
||||||
<button type="button" onClick={bulkDelete} className="flex flex-col items-center gap-1 text-danger-text">
|
<button type="button" onClick={bulkDelete} className="flex flex-col items-center gap-1 text-danger-text">
|
||||||
<Icon name="delete_outline" className="text-[22px]" />
|
<Icon name="delete_outline" className="text-[22px]" />
|
||||||
<span className="text-xs">删除</span>
|
<span className="text-xs">删除</span>
|
||||||
@@ -379,6 +414,8 @@ export function ConversationView() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
|
{bulkForwardOpen ? <ForwardPickerModal onClose={() => setBulkForwardOpen(false)} onPick={bulkForward} /> : null}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user