mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-22 19:30:15 +01:00
📧 feat: Mention "@" Command Popover (#2635)
* feat: initial mockup * wip: activesetting, may use or not use * wip: mention with useCombobox usage * feat: connect textarea to new mention popover * refactor: consolidate icon logic for Landing/convos * refactor: cleanup URL logic * refactor(useTextarea): key up handler * wip: render desired mention options * refactor: improve mention detection * feat: modular chat the default option * WIP: first pass mention selection * feat: scroll mention items with keypad * chore(showMentionPopoverFamily): add typing to atomFamily * feat: removeAtSymbol * refactor(useListAssistantsQuery): use defaultOrderQuery as default param * feat: assistants mentioning * fix conversation switch errors * filter mention selections based on startup settings and available endpoints * fix: mentions model spec icon URL * style: archive icon * fix: convo renaming behavior on click * fix(Convo): toggle hover state * style: EditMenu refactor * fix: archive chats table * fix: errorsToString import * chore: remove comments * chore: remove comment * feat: mention descriptions * refactor: make sure continue hover button is always last, add correct fork button alt text
This commit is contained in:
parent
89b1e33be0
commit
b6d6343f54
35 changed files with 1048 additions and 217 deletions
62
client/src/components/Endpoints/ConvoIcon.tsx
Normal file
62
client/src/components/Endpoints/ConvoIcon.tsx
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
import { EModelEndpoint } from 'librechat-data-provider';
|
||||
import type { Assistant, TConversation, TEndpointsConfig, TPreset } from 'librechat-data-provider';
|
||||
import { icons } from '~/components/Chat/Menus/Endpoints/Icons';
|
||||
import ConvoIconURL from '~/components/Endpoints/ConvoIconURL';
|
||||
import { getEndpointField, getIconKey, getIconEndpoint } from '~/utils';
|
||||
|
||||
export default function ConvoIcon({
|
||||
conversation,
|
||||
endpointsConfig,
|
||||
assistantMap,
|
||||
className = '',
|
||||
containerClassName = '',
|
||||
context,
|
||||
size,
|
||||
}: {
|
||||
conversation: TConversation | TPreset | null;
|
||||
endpointsConfig: TEndpointsConfig;
|
||||
assistantMap: Record<string, Assistant>;
|
||||
containerClassName?: string;
|
||||
context?: 'message' | 'nav' | 'landing' | 'menu-item';
|
||||
className?: string;
|
||||
size?: number;
|
||||
}) {
|
||||
const iconURL = conversation?.iconURL;
|
||||
let endpoint = conversation?.endpoint;
|
||||
endpoint = getIconEndpoint({ endpointsConfig, iconURL, endpoint });
|
||||
const assistant =
|
||||
endpoint === EModelEndpoint.assistants && assistantMap?.[conversation?.assistant_id ?? ''];
|
||||
const assistantName = (assistant && assistant?.name) || '';
|
||||
|
||||
const avatar = (assistant && (assistant?.metadata?.avatar as string)) || '';
|
||||
const endpointIconURL = getEndpointField(endpointsConfig, endpoint, 'iconURL');
|
||||
const iconKey = getIconKey({ endpoint, endpointsConfig, endpointIconURL });
|
||||
const Icon = icons[iconKey];
|
||||
return (
|
||||
<>
|
||||
{iconURL && iconURL.includes('http') ? (
|
||||
<ConvoIconURL
|
||||
preset={conversation}
|
||||
endpointIconURL={endpointIconURL}
|
||||
assistantName={assistantName}
|
||||
assistantAvatar={avatar}
|
||||
context={context}
|
||||
/>
|
||||
) : (
|
||||
<div className={containerClassName}>
|
||||
{endpoint &&
|
||||
Icon &&
|
||||
Icon({
|
||||
size,
|
||||
context,
|
||||
className,
|
||||
iconURL: endpointIconURL,
|
||||
assistantName,
|
||||
endpoint,
|
||||
avatar,
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -41,7 +41,9 @@ const ConvoIconURL: React.FC<ConvoIconURLProps> = ({
|
|||
},
|
||||
) => React.JSX.Element;
|
||||
|
||||
if (!iconURL?.includes('http')) {
|
||||
const isURL = iconURL && (iconURL.includes('http') || iconURL.startsWith('/images/'));
|
||||
|
||||
if (!isURL) {
|
||||
Icon = icons[iconURL] ?? icons.unknown;
|
||||
} else {
|
||||
Icon = () => (
|
||||
|
|
|
|||
65
client/src/components/Endpoints/EndpointIcon.tsx
Normal file
65
client/src/components/Endpoints/EndpointIcon.tsx
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
import { EModelEndpoint } from 'librechat-data-provider';
|
||||
import type { Assistant, TConversation, TEndpointsConfig, TPreset } from 'librechat-data-provider';
|
||||
import ConvoIconURL from '~/components/Endpoints/ConvoIconURL';
|
||||
import MinimalIcon from '~/components/Endpoints/MinimalIcon';
|
||||
import { getEndpointField, getIconEndpoint } from '~/utils';
|
||||
|
||||
export default function EndpointIcon({
|
||||
conversation,
|
||||
endpointsConfig,
|
||||
className = 'mr-0',
|
||||
assistantMap,
|
||||
context,
|
||||
}: {
|
||||
conversation: TConversation | TPreset | null;
|
||||
endpointsConfig: TEndpointsConfig;
|
||||
containerClassName?: string;
|
||||
context?: 'message' | 'nav' | 'landing' | 'menu-item';
|
||||
assistantMap?: Record<string, Assistant>;
|
||||
className?: string;
|
||||
size?: number;
|
||||
}) {
|
||||
const convoIconURL = conversation?.iconURL ?? '';
|
||||
let endpoint = conversation?.endpoint;
|
||||
endpoint = getIconEndpoint({ endpointsConfig, iconURL: convoIconURL, endpoint });
|
||||
|
||||
const endpointType = getEndpointField(endpointsConfig, endpoint, 'type');
|
||||
const endpointIconURL = getEndpointField(endpointsConfig, endpoint, 'iconURL');
|
||||
|
||||
const assistant =
|
||||
endpoint === EModelEndpoint.assistants && assistantMap?.[conversation?.assistant_id ?? ''];
|
||||
const assistantAvatar = (assistant && (assistant?.metadata?.avatar as string)) || '';
|
||||
const assistantName = (assistant && assistant?.name) || '';
|
||||
|
||||
const iconURL = assistantAvatar || convoIconURL;
|
||||
|
||||
let icon: React.ReactNode | null = null;
|
||||
if (iconURL && (iconURL.includes('http') || iconURL.startsWith('/images/'))) {
|
||||
icon = ConvoIconURL({
|
||||
preset: {
|
||||
...(conversation as TPreset),
|
||||
iconURL,
|
||||
},
|
||||
context,
|
||||
endpointIconURL,
|
||||
assistantAvatar,
|
||||
assistantName,
|
||||
});
|
||||
} else {
|
||||
icon = MinimalIcon({
|
||||
size: 20,
|
||||
iconURL: endpointIconURL,
|
||||
endpoint,
|
||||
endpointType,
|
||||
model: conversation?.model,
|
||||
error: false,
|
||||
className,
|
||||
isCreatedByUser: false,
|
||||
chatGptLabel: undefined,
|
||||
modelLabel: undefined,
|
||||
jailbreak: undefined,
|
||||
});
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
export { default as Icon } from './Icon';
|
||||
export { default as MinimalIcon } from './MinimalIcon';
|
||||
export { default as ConvoIcon } from './ConvoIcon';
|
||||
export { default as EndpointIcon } from './EndpointIcon';
|
||||
export { default as ConvoIconURL } from './ConvoIconURL';
|
||||
export { default as EndpointSettings } from './EndpointSettings';
|
||||
export { default as SaveAsPresetDialog } from './SaveAsPresetDialog';
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue