fix(web): 转发选择器好友/群聊分开全选

原来是列表整体一个全选按钮,选中后好友和群聊会一起被勾上。改成
好友、群聊两个分组各自独立的全选/取消全选,互不影响,方便只想
批量选中其中一类的场景(比如只发给所有群,不带上私聊好友)。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Your Name
2026-09-10 19:15:29 +08:00
co-authored by Claude Sonnet 5
parent 46b3288880
commit e3217a5de9
@@ -55,18 +55,23 @@ export function ForwardPickerModal({ onPick, onClose }: ForwardPickerModalProps)
});
};
const visibleTopics = useMemo(() => filtered.map((c) => c.topic).filter((t): t is string => !!t), [filtered]);
const allVisibleSelected = visibleTopics.length > 0 && visibleTopics.every((t) => selected.has(t));
const toggleSelectAll = () => {
// 好友/群聊各自独立的全选 -- 一次转发常常只想覆盖其中一类(比如"发给所有群"但不想带上私聊
// 好友),一个笼统的全选做不到这一点,所以拆成两个独立开关而不是列表整体一个。
const friendTopics = useMemo(() => friends.map((c) => c.topic).filter((t): t is string => !!t), [friends]);
const groupTopics = useMemo(() => groups.map((c) => c.topic).filter((t): t is string => !!t), [groups]);
const allFriendsSelected = friendTopics.length > 0 && friendTopics.every((t) => selected.has(t));
const allGroupsSelected = groupTopics.length > 0 && groupTopics.every((t) => selected.has(t));
const toggleSectionSelectAll = (topics: string[], allSelected: boolean) => {
setSelected((prev) => {
if (allVisibleSelected) {
if (allSelected) {
// Only drop the ones the CURRENT search actually shows -- a selection made under an earlier,
// now-cleared query shouldn't be wiped out by un-selecting "all" of a narrower view.
const next = new Set(prev);
for (const t of visibleTopics) next.delete(t);
for (const t of topics) next.delete(t);
return next;
}
return new Set([...prev, ...visibleTopics]);
return new Set([...prev, ...topics]);
});
};
@@ -121,22 +126,35 @@ export function ForwardPickerModal({ onPick, onClose }: ForwardPickerModalProps)
className="ml-2 w-full bg-transparent text-sm outline-none placeholder:text-text-placeholder-2"
/>
</div>
{visibleTopics.length ? (
<button type="button" onClick={toggleSelectAll} className="mt-2 text-xs text-accent">
{allVisibleSelected ? '取消全选' : '全选'}
</button>
) : null}
</div>
<div className="flex-1 overflow-y-auto px-2 py-2">
{friends.length ? (
<>
<div className="px-3 pb-1 pt-2 text-xs text-text-tertiary-2">好友</div>
<div className="flex items-center justify-between px-3 pb-1 pt-2">
<span className="text-xs text-text-tertiary-2">好友</span>
<button
type="button"
onClick={() => toggleSectionSelectAll(friendTopics, allFriendsSelected)}
className="text-xs text-accent"
>
{allFriendsSelected ? '取消全选' : '全选'}
</button>
</div>
{friends.map(renderRow)}
</>
) : null}
{groups.length ? (
<>
<div className="px-3 pb-1 pt-2 text-xs text-text-tertiary-2">群聊</div>
<div className="flex items-center justify-between px-3 pb-1 pt-2">
<span className="text-xs text-text-tertiary-2">群聊</span>
<button
type="button"
onClick={() => toggleSectionSelectAll(groupTopics, allGroupsSelected)}
className="text-xs text-accent"
>
{allGroupsSelected ? '取消全选' : '全选'}
</button>
</div>
{groups.map(renderRow)}
</>
) : null}