| 1 | #nullable enable |
| 2 | |
| 3 | using CascadeIDE.Models.Intercom; |
| 4 | |
| 5 | namespace CascadeIDE.Features.Chat; |
| 6 | |
| 7 | public sealed class MessageAnchorSlashCompletionProvider : IMessageAnchorSlashCompletionProvider |
| 8 | { |
| 9 | public const int DefaultLimit = 20; |
| 10 | |
| 11 | private readonly Func<IReadOnlyList<AttachmentAnchor>> _getSelectedMessageAnchors; |
| 12 | |
| 13 | public MessageAnchorSlashCompletionProvider(Func<IReadOnlyList<AttachmentAnchor>> getSelectedMessageAnchors) => |
| 14 | _getSelectedMessageAnchors = getSelectedMessageAnchors; |
| 15 | |
| 16 | public IReadOnlyList<MessageAnchorSlashMatch> GetMatches(string ordinalOrIdPrefix, int limit) |
| 17 | { |
| 18 | if (limit <= 0) |
| 19 | return []; |
| 20 | |
| 21 | var prefix = (ordinalOrIdPrefix ?? "").Trim(); |
| 22 | var anchors = _getSelectedMessageAnchors(); |
| 23 | if (anchors.Count == 0) |
| 24 | return []; |
| 25 | |
| 26 | var matches = new List<MessageAnchorSlashMatch>(Math.Min(anchors.Count, limit)); |
| 27 | for (var i = 0; i < anchors.Count && matches.Count < limit; i++) |
| 28 | { |
| 29 | var ordinal = (i + 1).ToString(); |
| 30 | var anchor = anchors[i]; |
| 31 | if (!matchesPrefix(prefix, ordinal, anchor)) |
| 32 | continue; |
| 33 | |
| 34 | var label = anchor.DisplayLabel ?? anchor.MemberKey ?? anchor.File ?? "—"; |
| 35 | var status = IntercomAnchorSlash.FormatOutcomeShort(anchor.ResolveOutcome); |
| 36 | var id = anchor.Id ?? ""; |
| 37 | var help = string.IsNullOrWhiteSpace(id) ? status : $"a:{id} · {status}"; |
| 38 | matches.Add(new MessageAnchorSlashMatch(ordinal, $"{ordinal} · {label}", help)); |
| 39 | } |
| 40 | |
| 41 | return matches; |
| 42 | } |
| 43 | |
| 44 | private static bool matchesPrefix(string prefix, string ordinal, AttachmentAnchor anchor) |
| 45 | { |
| 46 | if (prefix.Length == 0) |
| 47 | return true; |
| 48 | |
| 49 | if (ordinal.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) |
| 50 | return true; |
| 51 | |
| 52 | var id = anchor.Id ?? ""; |
| 53 | if (id.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) |
| 54 | return true; |
| 55 | |
| 56 | return $"a:{id}".StartsWith(prefix, StringComparison.OrdinalIgnoreCase); |
| 57 | } |
| 58 | } |
| 59 | |