Full featured auto complete

This commit is contained in:
2025-10-12 16:55:32 +08:00
parent e624c2bb3e
commit 37ea882ef7
8 changed files with 347 additions and 275 deletions

View File

@@ -1,10 +1,12 @@
using DysonNetwork.Shared.Models;
using DysonNetwork.Shared.Registry;
using Microsoft.EntityFrameworkCore;
namespace DysonNetwork.Sphere.Autocompletion;
public class AutocompletionService(AppDatabase db)
public class AutocompletionService(AppDatabase db, AccountClientHelper accountsHelper)
{
public async Task<List<DysonNetwork.Shared.Models.Autocompletion>> GetAutocompletion(string content, int limit = 10)
public async Task<List<DysonNetwork.Shared.Models.Autocompletion>> GetAutocompletion(string content, Guid? chatId = null, Guid? realmId = null, int limit = 10)
{
if (string.IsNullOrWhiteSpace(content))
return [];
@@ -14,7 +16,8 @@ public class AutocompletionService(AppDatabase db)
var afterAt = content[1..];
string type;
string query;
if (afterAt.Contains('/'))
bool hadSlash = afterAt.Contains('/');
if (hadSlash)
{
var parts = afterAt.Split('/', 2);
type = parts[0];
@@ -25,7 +28,8 @@ public class AutocompletionService(AppDatabase db)
type = "u";
query = afterAt;
}
return await AutocompleteAt(type, query, limit);
return await AutocompleteAt(type, query, chatId, realmId, hadSlash, limit);
}
if (!content.StartsWith(':')) return [];
@@ -33,15 +37,49 @@ public class AutocompletionService(AppDatabase db)
var query = content[1..];
return await AutocompleteSticker(query, limit);
}
}
private async Task<List<DysonNetwork.Shared.Models.Autocompletion>> AutocompleteAt(string type, string query, int limit)
private async Task<List<DysonNetwork.Shared.Models.Autocompletion>> AutocompleteAt(string type, string query, Guid? chatId, Guid? realmId, bool hadSlash,
int limit)
{
var results = new List<DysonNetwork.Shared.Models.Autocompletion>();
switch (type)
{
case "u":
var allAccounts = await accountsHelper.SearchAccounts(query);
var filteredAccounts = allAccounts;
if (chatId.HasValue)
{
var chatMemberIds = await db.ChatMembers
.Where(m => m.ChatRoomId == chatId.Value && m.JoinedAt != null && m.LeaveAt == null)
.Select(m => m.AccountId)
.ToListAsync();
var chatMemberIdStrings = chatMemberIds.Select(id => id.ToString()).ToHashSet();
filteredAccounts = allAccounts.Where(a => chatMemberIdStrings.Contains(a.Id)).ToList();
}
else if (realmId.HasValue)
{
var realmMemberIds = await db.RealmMembers
.Where(m => m.RealmId == realmId.Value && m.LeaveAt == null)
.Select(m => m.AccountId)
.ToListAsync();
var realmMemberIdStrings = realmMemberIds.Select(id => id.ToString()).ToHashSet();
filteredAccounts = allAccounts.Where(a => realmMemberIdStrings.Contains(a.Id)).ToList();
}
var users = filteredAccounts
.Take(limit)
.Select(a => new DysonNetwork.Shared.Models.Autocompletion
{
Type = "user",
Keyword = "@" + (hadSlash ? "u/" : "") + a.Name,
Data = SnAccount.FromProtoValue(a)
})
.ToList();
results.AddRange(users);
break;
case "p":
var publishers = await db.Publishers
.Where(p => EF.Functions.Like(p.Name, $"{query}%") || EF.Functions.Like(p.Nick, $"{query}%"))
@@ -49,7 +87,7 @@ public class AutocompletionService(AppDatabase db)
.Select(p => new DysonNetwork.Shared.Models.Autocompletion
{
Type = "publisher",
Keyword = p.Name,
Keyword = "@p/" + p.Name,
Data = p
})
.ToListAsync();
@@ -63,7 +101,7 @@ public class AutocompletionService(AppDatabase db)
.Select(r => new DysonNetwork.Shared.Models.Autocompletion
{
Type = "realm",
Keyword = r.Slug,
Keyword = "@r/" + r.Slug,
Data = r
})
.ToListAsync();
@@ -77,7 +115,7 @@ public class AutocompletionService(AppDatabase db)
.Select(c => new DysonNetwork.Shared.Models.Autocompletion
{
Type = "chat",
Keyword = c.Name!,
Keyword = "@c/" + c.Name,
Data = c
})
.ToListAsync();