mirror of
https://github.com/lobehub/lobe-chat.git
synced 2026-06-13 19:20:04 +00:00
🐛 fix: group agent rename problem (#12511)
* chore: align agent rename usage with agent profile editor * fix: agent content emoji picker popupProps * chore: agent and agent group use emoji background color in session list * chore: remove fixed popupProps
This commit is contained in:
@@ -1,4 +1,8 @@
|
||||
import { type SidebarAgentItem, type SidebarAgentListResponse, type SidebarGroup } from '@lobechat/types';
|
||||
import {
|
||||
type SidebarAgentItem,
|
||||
type SidebarAgentListResponse,
|
||||
type SidebarGroup,
|
||||
} from '@lobechat/types';
|
||||
import { cleanObject } from '@lobechat/utils';
|
||||
import { and, desc, eq, ilike, inArray, not, or } from 'drizzle-orm';
|
||||
|
||||
@@ -10,7 +14,7 @@ import {
|
||||
sessionGroups,
|
||||
sessions,
|
||||
} from '../../schemas';
|
||||
import { type LobeChatDatabase } from '../../type';
|
||||
import { type LobeChatDatabase } from '../../type';
|
||||
|
||||
// Re-export types for backward compatibility
|
||||
export type {
|
||||
@@ -41,6 +45,7 @@ export class HomeRepository {
|
||||
.select({
|
||||
agentSessionGroupId: agents.sessionGroupId,
|
||||
avatar: agents.avatar,
|
||||
backgroundColor: agents.backgroundColor,
|
||||
description: agents.description,
|
||||
id: agents.id,
|
||||
pinned: agents.pinned,
|
||||
@@ -94,6 +99,7 @@ export class HomeRepository {
|
||||
agentItems: Array<{
|
||||
agentSessionGroupId: string | null;
|
||||
avatar: string | null;
|
||||
backgroundColor: string | null;
|
||||
description: string | null;
|
||||
id: string;
|
||||
pinned: boolean | null;
|
||||
@@ -126,6 +132,7 @@ export class HomeRepository {
|
||||
const allItems: Array<SidebarAgentItem & { groupId: string | null }> = [
|
||||
...agentItems.map((a) => ({
|
||||
avatar: a.avatar,
|
||||
backgroundColor: a.backgroundColor,
|
||||
description: a.description,
|
||||
groupId: a.agentSessionGroupId ?? a.sessionGroupId,
|
||||
id: a.id,
|
||||
@@ -138,7 +145,7 @@ export class HomeRepository {
|
||||
...chatGroupItems.map((g) => ({
|
||||
// If group has custom avatar, use it (string); otherwise fallback to member avatars (array)
|
||||
avatar: g.avatar ? g.avatar : (memberAvatarsMap.get(g.id) ?? null),
|
||||
backgroundColor: g.avatar ? g.backgroundColor : null,
|
||||
backgroundColor: g.backgroundColor,
|
||||
description: g.description,
|
||||
groupAvatar: g.avatar,
|
||||
groupId: g.groupId,
|
||||
@@ -198,6 +205,7 @@ export class HomeRepository {
|
||||
const agentResults = await this.db
|
||||
.select({
|
||||
avatar: agents.avatar,
|
||||
backgroundColor: agents.backgroundColor,
|
||||
description: agents.description,
|
||||
id: agents.id,
|
||||
pinned: agents.pinned,
|
||||
@@ -248,6 +256,7 @@ export class HomeRepository {
|
||||
...agentResults.map((a) =>
|
||||
cleanObject({
|
||||
avatar: a.avatar,
|
||||
backgroundColor: a.backgroundColor,
|
||||
description: a.description,
|
||||
id: a.id,
|
||||
pinned: a.pinned ?? a.sessionPinned ?? false,
|
||||
@@ -260,7 +269,7 @@ export class HomeRepository {
|
||||
...chatGroupResults.map((g) =>
|
||||
cleanObject({
|
||||
avatar: g.avatar ? g.avatar : (memberAvatarsMap.get(g.id) ?? null),
|
||||
backgroundColor: g.avatar ? g.backgroundColor : null,
|
||||
backgroundColor: g.backgroundColor,
|
||||
description: g.description,
|
||||
id: g.id,
|
||||
pinned: g.pinned ?? false,
|
||||
|
||||
@@ -94,6 +94,7 @@ const GroupItem = memo<GroupItemProps>(({ item, style, className }) => {
|
||||
const dropdownMenu = useGroupDropdownMenu({
|
||||
anchor,
|
||||
avatar: customAvatar,
|
||||
backgroundColor: backgroundColor || undefined,
|
||||
id,
|
||||
memberAvatars,
|
||||
pinned: pinned ?? false,
|
||||
|
||||
+12
-1
@@ -12,6 +12,7 @@ import { useHomeStore } from '@/store/home';
|
||||
interface UseGroupDropdownMenuParams {
|
||||
anchor: HTMLElement | null;
|
||||
avatar?: string;
|
||||
backgroundColor?: string;
|
||||
id: string;
|
||||
memberAvatars?: { avatar?: string; background?: string }[];
|
||||
pinned: boolean;
|
||||
@@ -21,6 +22,7 @@ interface UseGroupDropdownMenuParams {
|
||||
export const useGroupDropdownMenu = ({
|
||||
anchor,
|
||||
avatar,
|
||||
backgroundColor,
|
||||
id,
|
||||
memberAvatars,
|
||||
pinned,
|
||||
@@ -52,7 +54,15 @@ export const useGroupDropdownMenu = ({
|
||||
onClick: (info: any) => {
|
||||
info.domEvent?.stopPropagation();
|
||||
if (anchor) {
|
||||
openEditingPopover({ anchor, avatar, id, memberAvatars, title, type: 'agentGroup' });
|
||||
openEditingPopover({
|
||||
anchor,
|
||||
avatar,
|
||||
backgroundColor,
|
||||
id,
|
||||
memberAvatars,
|
||||
title,
|
||||
type: 'agentGroup',
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -97,6 +107,7 @@ export const useGroupDropdownMenu = ({
|
||||
[
|
||||
anchor,
|
||||
avatar,
|
||||
backgroundColor,
|
||||
memberAvatars,
|
||||
t,
|
||||
pinned,
|
||||
|
||||
@@ -26,7 +26,7 @@ interface AgentItemProps {
|
||||
}
|
||||
|
||||
const AgentItem = memo<AgentItemProps>(({ item, style, className }) => {
|
||||
const { id, avatar, title, pinned } = item;
|
||||
const { id, avatar, backgroundColor, title, pinned } = item;
|
||||
const { t } = useTranslation('chat');
|
||||
const { openCreateGroupModal } = useAgentModal();
|
||||
const [anchor, setAnchor] = useState<HTMLElement | null>(null);
|
||||
@@ -83,8 +83,13 @@ const AgentItem = memo<AgentItemProps>(({ item, style, className }) => {
|
||||
return <Icon spin color={cssVar.colorTextDescription} icon={Loader2} size={18} />;
|
||||
}
|
||||
|
||||
return <Avatar avatar={typeof avatar === 'string' ? avatar : undefined} />;
|
||||
}, [isUpdating, avatar]);
|
||||
return (
|
||||
<Avatar
|
||||
avatar={typeof avatar === 'string' ? avatar : undefined}
|
||||
avatarBackground={backgroundColor || undefined}
|
||||
/>
|
||||
);
|
||||
}, [isUpdating, avatar, backgroundColor]);
|
||||
|
||||
const dropdownMenu = useAgentDropdownMenu({
|
||||
anchor,
|
||||
|
||||
@@ -28,10 +28,18 @@ const AgentGroupAvatar = memo<AgentGroupAvatarProps>(
|
||||
({ avatar, backgroundColor, memberAvatars = [], size = 28 }) => {
|
||||
// If group has custom avatar, show it; otherwise show member avatars composition
|
||||
if (avatar) {
|
||||
return <Avatar avatar={avatar} background={backgroundColor} shape="square" size={size} />;
|
||||
return (
|
||||
<Avatar
|
||||
emojiScaleWithBackground
|
||||
avatar={avatar}
|
||||
background={backgroundColor}
|
||||
shape="square"
|
||||
size={size}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return <GroupAvatar avatars={memberAvatars} size={size} />;
|
||||
return <GroupAvatar avatars={memberAvatars} background={backgroundColor} size={size} />;
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -1,15 +1,31 @@
|
||||
import { ActionIcon, Avatar, Block, Flexbox, Input, stopPropagation } from '@lobehub/ui';
|
||||
import { type InputRef } from 'antd';
|
||||
import { Check } from 'lucide-react';
|
||||
import { DEFAULT_AVATAR } from '@lobechat/const';
|
||||
import {
|
||||
ActionIcon,
|
||||
Avatar,
|
||||
Block,
|
||||
Flexbox,
|
||||
Icon,
|
||||
Input,
|
||||
stopPropagation,
|
||||
Tooltip,
|
||||
} from '@lobehub/ui';
|
||||
import { type InputRef, message } from 'antd';
|
||||
import { Check, PaletteIcon } from 'lucide-react';
|
||||
import { memo, useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import EmojiPicker from '@/components/EmojiPicker';
|
||||
import BackgroundSwatches from '@/features/AgentSetting/AgentMeta/BackgroundSwatches';
|
||||
import { useIsDark } from '@/hooks/useIsDark';
|
||||
import { useAgentStore } from '@/store/agent';
|
||||
import { agentSelectors } from '@/store/agent/selectors';
|
||||
import { useFileStore } from '@/store/file';
|
||||
import { useGlobalStore } from '@/store/global';
|
||||
import { globalGeneralSelectors } from '@/store/global/selectors';
|
||||
import { useHomeStore } from '@/store/home';
|
||||
|
||||
const MAX_AVATAR_SIZE = 1024 * 1024;
|
||||
|
||||
interface AgentContentProps {
|
||||
avatar?: string;
|
||||
id: string;
|
||||
@@ -18,25 +34,31 @@ interface AgentContentProps {
|
||||
}
|
||||
|
||||
const AgentContent = memo<AgentContentProps>(({ id, title, avatar, onClose }) => {
|
||||
const { t } = useTranslation('setting');
|
||||
const locale = useGlobalStore(globalGeneralSelectors.currentLanguage);
|
||||
const isDarkMode = useIsDark();
|
||||
const uploadWithProgress = useFileStore((s) => s.uploadWithProgress);
|
||||
|
||||
const currentAvatar = avatar || '';
|
||||
const meta = useAgentStore(agentSelectors.getAgentMetaById(id));
|
||||
|
||||
const [newTitle, setNewTitle] = useState(title);
|
||||
const [newAvatar, setNewAvatar] = useState(currentAvatar);
|
||||
const [newAvatar, setNewAvatar] = useState<string | null | undefined>(avatar);
|
||||
const [newBackgroundColor, setNewBackgroundColor] = useState(meta.backgroundColor);
|
||||
const [uploading, setUploading] = useState(false);
|
||||
|
||||
const handleUpdate = useCallback(async () => {
|
||||
const hasChanges =
|
||||
(newTitle && title !== newTitle) || (newAvatar && currentAvatar !== newAvatar);
|
||||
const titleChanged = newTitle && title !== newTitle;
|
||||
const avatarChanged = newAvatar !== (avatar || undefined);
|
||||
const backgroundColorChanged = newBackgroundColor !== meta.backgroundColor;
|
||||
|
||||
if (hasChanges) {
|
||||
if (titleChanged || avatarChanged || backgroundColorChanged) {
|
||||
try {
|
||||
useHomeStore.getState().setAgentUpdatingId(id);
|
||||
|
||||
const updates: { avatar?: string; title?: string } = {};
|
||||
if (newTitle && title !== newTitle) updates.title = newTitle;
|
||||
if (newAvatar && currentAvatar !== newAvatar) updates.avatar = newAvatar;
|
||||
const updates: { avatar?: string; backgroundColor?: string; title?: string } = {};
|
||||
if (titleChanged) updates.title = newTitle;
|
||||
if (avatarChanged) updates.avatar = newAvatar || undefined;
|
||||
if (backgroundColorChanged) updates.backgroundColor = newBackgroundColor;
|
||||
|
||||
await useAgentStore.getState().optimisticUpdateAgentMeta(id, updates);
|
||||
await useHomeStore.getState().refreshAgentList();
|
||||
@@ -45,7 +67,32 @@ const AgentContent = memo<AgentContentProps>(({ id, title, avatar, onClose }) =>
|
||||
}
|
||||
}
|
||||
onClose();
|
||||
}, [newTitle, newAvatar, title, currentAvatar, id, onClose]);
|
||||
}, [newTitle, newAvatar, newBackgroundColor, title, avatar, meta.backgroundColor, id, onClose]);
|
||||
|
||||
const handleAvatarUpload = useCallback(
|
||||
async (file: File) => {
|
||||
if (file.size > MAX_AVATAR_SIZE) {
|
||||
message.error(t('settingAgent.avatar.sizeExceeded'));
|
||||
return;
|
||||
}
|
||||
|
||||
setUploading(true);
|
||||
try {
|
||||
const result = await uploadWithProgress({ file });
|
||||
if (result?.url) {
|
||||
setNewAvatar(result.url);
|
||||
}
|
||||
} finally {
|
||||
setUploading(false);
|
||||
}
|
||||
},
|
||||
[uploadWithProgress, t],
|
||||
);
|
||||
|
||||
const handleAvatarDelete = useCallback(() => {
|
||||
setNewAvatar(null);
|
||||
}, []);
|
||||
|
||||
const inputRef = useRef<InputRef>(null);
|
||||
useEffect(() => {
|
||||
requestAnimationFrame(() => {
|
||||
@@ -56,12 +103,21 @@ const AgentContent = memo<AgentContentProps>(({ id, title, avatar, onClose }) =>
|
||||
});
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Flexbox horizontal align={'center'} gap={4} style={{ width: 320 }} onClick={stopPropagation}>
|
||||
<EmojiPicker
|
||||
allowUpload
|
||||
allowDelete={!!newAvatar}
|
||||
loading={uploading}
|
||||
locale={locale}
|
||||
shape={'square'}
|
||||
value={newAvatar}
|
||||
value={newAvatar ?? undefined}
|
||||
background={
|
||||
newBackgroundColor && newBackgroundColor !== 'rgba(0,0,0,0)'
|
||||
? newBackgroundColor
|
||||
: undefined
|
||||
}
|
||||
customRender={(avatarValue) => (
|
||||
<Block
|
||||
clickable
|
||||
@@ -72,10 +128,43 @@ const AgentContent = memo<AgentContentProps>(({ id, title, avatar, onClose }) =>
|
||||
width={36}
|
||||
onClick={stopPropagation}
|
||||
>
|
||||
<Avatar emojiScaleWithBackground avatar={avatarValue} shape={'square'} size={32} />
|
||||
<Avatar
|
||||
emojiScaleWithBackground
|
||||
avatar={avatarValue || DEFAULT_AVATAR}
|
||||
shape={'square'}
|
||||
size={32}
|
||||
background={
|
||||
newBackgroundColor && newBackgroundColor !== 'rgba(0,0,0,0)'
|
||||
? newBackgroundColor
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
</Block>
|
||||
)}
|
||||
customTabs={[
|
||||
{
|
||||
label: (
|
||||
<Tooltip title={t('settingAgent.backgroundColor.title')}>
|
||||
<Icon icon={PaletteIcon} size={{ size: 20, strokeWidth: 2.5 }} />
|
||||
</Tooltip>
|
||||
),
|
||||
render: () => (
|
||||
<Flexbox padding={8} width={332}>
|
||||
<BackgroundSwatches
|
||||
gap={8}
|
||||
shape={'square'}
|
||||
size={38}
|
||||
value={newBackgroundColor}
|
||||
onChange={setNewBackgroundColor}
|
||||
/>
|
||||
</Flexbox>
|
||||
),
|
||||
value: 'background',
|
||||
},
|
||||
]}
|
||||
onChange={setNewAvatar}
|
||||
onDelete={handleAvatarDelete}
|
||||
onUpload={handleAvatarUpload}
|
||||
/>
|
||||
<Input
|
||||
defaultValue={title}
|
||||
|
||||
@@ -1,10 +1,20 @@
|
||||
import { ActionIcon, Avatar, Block, Flexbox, Input, stopPropagation } from '@lobehub/ui';
|
||||
import {
|
||||
ActionIcon,
|
||||
Avatar,
|
||||
Block,
|
||||
Flexbox,
|
||||
Icon,
|
||||
Input,
|
||||
stopPropagation,
|
||||
Tooltip,
|
||||
} from '@lobehub/ui';
|
||||
import { type InputRef, message } from 'antd';
|
||||
import { Check } from 'lucide-react';
|
||||
import { Check, PaletteIcon } from 'lucide-react';
|
||||
import { memo, useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import EmojiPicker from '@/components/EmojiPicker';
|
||||
import BackgroundSwatches from '@/features/AgentSetting/AgentMeta/BackgroundSwatches';
|
||||
import GroupAvatar from '@/features/GroupAvatar';
|
||||
import { useIsDark } from '@/hooks/useIsDark';
|
||||
import { useFileStore } from '@/store/file';
|
||||
@@ -16,6 +26,7 @@ const MAX_AVATAR_SIZE = 1024 * 1024;
|
||||
|
||||
interface GroupContentProps {
|
||||
avatar?: string;
|
||||
backgroundColor?: string;
|
||||
id: string;
|
||||
memberAvatars?: { avatar?: string; background?: string }[];
|
||||
onClose: () => void;
|
||||
@@ -24,7 +35,7 @@ interface GroupContentProps {
|
||||
}
|
||||
|
||||
const GroupContent = memo<GroupContentProps>(
|
||||
({ id, title, avatar, memberAvatars, type, onClose }) => {
|
||||
({ id, title, avatar, backgroundColor, memberAvatars, type, onClose }) => {
|
||||
const { t } = useTranslation('setting');
|
||||
const locale = useGlobalStore(globalGeneralSelectors.currentLanguage);
|
||||
const isDarkMode = useIsDark();
|
||||
@@ -34,13 +45,15 @@ const GroupContent = memo<GroupContentProps>(
|
||||
|
||||
const [newTitle, setNewTitle] = useState(title);
|
||||
const [newAvatar, setNewAvatar] = useState<string | null | undefined>(avatar);
|
||||
const [newBackgroundColor, setNewBackgroundColor] = useState(backgroundColor);
|
||||
const [uploading, setUploading] = useState(false);
|
||||
|
||||
const handleUpdate = useCallback(async () => {
|
||||
const titleChanged = newTitle && title !== newTitle;
|
||||
const avatarChanged = isAgentGroup && newAvatar !== avatar;
|
||||
const backgroundColorChanged = isAgentGroup && newBackgroundColor !== backgroundColor;
|
||||
|
||||
if (titleChanged || avatarChanged) {
|
||||
if (titleChanged || avatarChanged || backgroundColorChanged) {
|
||||
try {
|
||||
useHomeStore.getState().setGroupUpdatingId(id);
|
||||
|
||||
@@ -49,14 +62,30 @@ const GroupContent = memo<GroupContentProps>(
|
||||
} else {
|
||||
await useHomeStore
|
||||
.getState()
|
||||
.renameAgentGroup(id, newTitle || title, avatarChanged ? newAvatar : undefined);
|
||||
.renameAgentGroup(
|
||||
id,
|
||||
newTitle || title,
|
||||
avatarChanged ? newAvatar : undefined,
|
||||
backgroundColorChanged ? newBackgroundColor : undefined,
|
||||
);
|
||||
}
|
||||
} finally {
|
||||
useHomeStore.getState().setGroupUpdatingId(null);
|
||||
}
|
||||
}
|
||||
onClose();
|
||||
}, [newTitle, newAvatar, title, avatar, id, type, isAgentGroup, onClose]);
|
||||
}, [
|
||||
newTitle,
|
||||
newAvatar,
|
||||
newBackgroundColor,
|
||||
title,
|
||||
avatar,
|
||||
backgroundColor,
|
||||
id,
|
||||
type,
|
||||
isAgentGroup,
|
||||
onClose,
|
||||
]);
|
||||
|
||||
const handleAvatarUpload = useCallback(
|
||||
async (file: File) => {
|
||||
@@ -103,6 +132,11 @@ const GroupContent = memo<GroupContentProps>(
|
||||
locale={locale}
|
||||
shape={'square'}
|
||||
value={newAvatar ?? undefined}
|
||||
background={
|
||||
newBackgroundColor && newBackgroundColor !== 'rgba(0,0,0,0)'
|
||||
? newBackgroundColor
|
||||
: undefined
|
||||
}
|
||||
customRender={(avatarValue) => (
|
||||
<Block
|
||||
clickable
|
||||
@@ -119,12 +153,42 @@ const GroupContent = memo<GroupContentProps>(
|
||||
avatar={avatarValue}
|
||||
shape={'square'}
|
||||
size={32}
|
||||
background={
|
||||
newBackgroundColor && newBackgroundColor !== 'rgba(0,0,0,0)'
|
||||
? newBackgroundColor
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<GroupAvatar avatars={memberAvatars || []} size={32} />
|
||||
<GroupAvatar
|
||||
avatars={memberAvatars || []}
|
||||
background={newBackgroundColor}
|
||||
size={32}
|
||||
/>
|
||||
)}
|
||||
</Block>
|
||||
)}
|
||||
customTabs={[
|
||||
{
|
||||
label: (
|
||||
<Tooltip title={t('settingAgent.backgroundColor.title')}>
|
||||
<Icon icon={PaletteIcon} size={{ size: 20, strokeWidth: 2.5 }} />
|
||||
</Tooltip>
|
||||
),
|
||||
render: () => (
|
||||
<Flexbox padding={8} width={332}>
|
||||
<BackgroundSwatches
|
||||
gap={8}
|
||||
shape={'square'}
|
||||
size={38}
|
||||
value={newBackgroundColor}
|
||||
onChange={setNewBackgroundColor}
|
||||
/>
|
||||
</Flexbox>
|
||||
),
|
||||
value: 'background',
|
||||
},
|
||||
]}
|
||||
onChange={setNewAvatar}
|
||||
onDelete={handleAvatarDelete}
|
||||
onUpload={handleAvatarUpload}
|
||||
|
||||
@@ -30,6 +30,7 @@ const EditingPopover = () => {
|
||||
) : target ? (
|
||||
<GroupContent
|
||||
avatar={target.avatar}
|
||||
backgroundColor={target.backgroundColor}
|
||||
id={target.id}
|
||||
memberAvatars={target.memberAvatars}
|
||||
title={target.title}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { create } from 'zustand';
|
||||
export interface EditingTarget {
|
||||
anchor: HTMLElement;
|
||||
avatar?: string;
|
||||
backgroundColor?: string;
|
||||
id: string;
|
||||
memberAvatars?: { avatar?: string; background?: string }[];
|
||||
title: string;
|
||||
|
||||
@@ -10,11 +10,12 @@ import { useUserStore } from '@/store/user';
|
||||
import { userProfileSelectors } from '@/store/user/slices/auth/selectors';
|
||||
|
||||
interface GroupAvatarComponentProps extends GroupAvatarProps {
|
||||
background?: string;
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
const GroupAvatarComponent = memo<GroupAvatarComponentProps>(
|
||||
({ size = 28, avatars = [], loading, ...rest }) => {
|
||||
({ size = 28, avatars = [], background, loading, ...rest }) => {
|
||||
const [userAvatar, nickName, username] = useUserStore((s) => [
|
||||
userProfileSelectors.userAvatar(s),
|
||||
userProfileSelectors.nickName(s),
|
||||
@@ -51,6 +52,11 @@ const GroupAvatarComponent = memo<GroupAvatarComponentProps>(
|
||||
background: agent?.backgroundColor || undefined,
|
||||
...agent,
|
||||
}))}
|
||||
style={
|
||||
background && background !== 'rgba(0,0,0,0)'
|
||||
? { background, borderRadius: '22%' }
|
||||
: undefined
|
||||
}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -104,8 +104,9 @@ export class SidebarUIActionImpl {
|
||||
groupId: string,
|
||||
title: string,
|
||||
avatar?: string | null,
|
||||
backgroundColor?: string,
|
||||
): Promise<void> => {
|
||||
await chatGroupService.updateGroup(groupId, { avatar, title });
|
||||
await chatGroupService.updateGroup(groupId, { avatar, backgroundColor, title });
|
||||
await this.#get().refreshAgentList();
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user