feat(frontend): add repo type to mention autocomplete system
Add 'repo' to MentionType across all editor types, include repos in the @ trigger pool, add repo badge (green chip), Repos section in the mention dropdown, and MentionBadge styles. Wire projectRepos from room context into IMEditor mentionItems.
This commit is contained in:
parent
adbc0705db
commit
c8eba28e7a
@ -76,7 +76,7 @@ export const MessageInput = forwardRef<MessageInputHandle, MessageInputProps>(fu
|
||||
{roomName, onSend, replyingTo, onCancelReply},
|
||||
ref,
|
||||
) {
|
||||
const {members, activeRoomId, roomAiConfigs, wsClient} = useRoom();
|
||||
const {members, activeRoomId, roomAiConfigs, projectRepos, wsClient} = useRoom();
|
||||
|
||||
// Ref passed to the inner IMEditor
|
||||
const innerEditorRef = useRef<IMEditorHandle | null>(null);
|
||||
@ -147,12 +147,18 @@ export const MessageInput = forwardRef<MessageInputHandle, MessageInputProps>(fu
|
||||
channels: [] as { id: string; label: string; type: 'channel'; avatar?: string }[],
|
||||
ai: roomAiConfigs.map((cfg) => ({
|
||||
id: cfg.model,
|
||||
label: cfg.modelName ?? cfg.model,
|
||||
label: cfg.modelName || 'Unknown AI',
|
||||
type: 'ai' as const,
|
||||
})),
|
||||
repos: projectRepos.map((r) => ({
|
||||
id: r.repo_name,
|
||||
label: r.repo_name,
|
||||
type: 'repo' as const,
|
||||
description: r.description ?? undefined,
|
||||
})),
|
||||
commands: SLASH_COMMANDS,
|
||||
specialMentions: SPECIAL_MENTIONS,
|
||||
}), [members, roomAiConfigs]);
|
||||
}), [members, roomAiConfigs, projectRepos]);
|
||||
|
||||
// File upload handler — POST to /rooms/{room_id}/upload
|
||||
const handleUploadFile = async (file: File): Promise<{ id: string; url: string }> => {
|
||||
|
||||
@ -26,6 +26,7 @@ export interface IMEditorProps {
|
||||
users: MentionItem[];
|
||||
channels: MentionItem[];
|
||||
ai: MentionItem[];
|
||||
repos: MentionItem[];
|
||||
commands: MentionItem[];
|
||||
specialMentions?: MentionItem[];
|
||||
};
|
||||
@ -151,6 +152,7 @@ function getBadge(type: MentionType): { label: string; cls: string } | null {
|
||||
if (type === 'ai') return {label: 'AI', cls: 'bg-blue-50 text-blue-600'};
|
||||
if (type === 'channel') return {label: '#', cls: 'bg-gray-100 text-gray-500'};
|
||||
if (type === 'command') return {label: 'cmd', cls: 'bg-amber-50 text-amber-600'};
|
||||
if (type === 'repo') return {label: 'repo', cls: 'bg-green-50 text-green-600'};
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -173,12 +175,13 @@ function serializeAstNode(node: EditorNode): string {
|
||||
|
||||
// ─── Mention Dropdown (sectioned by type) ────────────────────────────────────
|
||||
|
||||
const SECTION_ORDER = ['special_here', 'special_channel', 'ai', 'user', 'channel', 'command'] as const;
|
||||
const SECTION_ORDER = ['special_here', 'special_channel', 'ai', 'user', 'repo', 'channel', 'command'] as const;
|
||||
const SECTION_LABELS: Record<string, string> = {
|
||||
special_here: 'Notify',
|
||||
special_channel: 'Notify',
|
||||
ai: 'AI',
|
||||
user: 'Members',
|
||||
repo: 'Repositories',
|
||||
channel: 'Channels',
|
||||
command: 'Commands',
|
||||
};
|
||||
@ -356,7 +359,8 @@ export const IMEditor = forwardRef<IMEditorHandle, IMEditorProps>(function IMEdi
|
||||
...(mentionItems.specialMentions ?? []),
|
||||
...mentionItems.ai,
|
||||
...mentionItems.users,
|
||||
], [mentionItems.specialMentions, mentionItems.ai, mentionItems.users]);
|
||||
...mentionItems.repos,
|
||||
], [mentionItems.specialMentions, mentionItems.ai, mentionItems.users, mentionItems.repos]);
|
||||
|
||||
const hashPool = useMemo(() => [...mentionItems.channels], [mentionItems.channels]);
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
* Core types for the IM editor (mentions, files, emojis).
|
||||
*/
|
||||
|
||||
export type MentionType = 'user' | 'channel' | 'ai' | 'command' | 'special_here' | 'special_channel';
|
||||
export type MentionType = 'user' | 'channel' | 'ai' | 'repo' | 'command' | 'special_here' | 'special_channel';
|
||||
|
||||
export interface MentionItem {
|
||||
id: string;
|
||||
|
||||
@ -42,6 +42,11 @@ const TYPE_STYLE: Record<MentionType, { light: string; dark?: string; prefix: st
|
||||
dark: 'dark:bg-orange-900/30 dark:text-orange-300',
|
||||
prefix: '@',
|
||||
},
|
||||
repo: {
|
||||
light: 'bg-teal-50 text-teal-600',
|
||||
dark: 'dark:bg-teal-900/30 dark:text-teal-300',
|
||||
prefix: '@',
|
||||
},
|
||||
};
|
||||
|
||||
export function MentionBadge({ type, label, onClick, id, className }: MentionBadgeProps) {
|
||||
|
||||
@ -7,6 +7,7 @@ export type MentionType =
|
||||
| 'user'
|
||||
| 'channel'
|
||||
| 'ai'
|
||||
| 'repo'
|
||||
| 'command'
|
||||
| 'special_here'
|
||||
| 'special_channel';
|
||||
@ -15,6 +16,7 @@ export const MENTION_TYPES: MentionType[] = [
|
||||
'user',
|
||||
'channel',
|
||||
'ai',
|
||||
'repo',
|
||||
'command',
|
||||
'special_here',
|
||||
'special_channel',
|
||||
@ -84,6 +86,11 @@ export function serializeAiMention(aiId: string, aiName: string): string {
|
||||
return serializeMention('ai', aiId, aiName);
|
||||
}
|
||||
|
||||
/** Build a mention token from a repo mention. */
|
||||
export function serializeRepoMention(repoName: string, label?: string): string {
|
||||
return serializeMention('repo', repoName, label ?? repoName);
|
||||
}
|
||||
|
||||
/** Build a mention token from a command mention. */
|
||||
export function serializeCommandMention(commandId: string, commandName: string): string {
|
||||
return serializeMention('command', commandId, commandName);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user