fix(social): allow single-char search and prefer native federated profiles

Lower minimum query length from 2 to 1 character so single-letter
searches return results.

Fix dedup to prefer native profiles (homeUserId=null) over replicated
ones. Previously the first-seen result won, which was usually the
local replicated profile (no instance badge, namespaced username).
Now when a native profile is found on the remote instance, it replaces
the replicated copy — showing the clean username with the instance badge.
This commit is contained in:
Jannis Braun
2026-03-25 02:26:33 +01:00
parent f0e72dc257
commit 7240aac2e0
2 changed files with 17 additions and 5 deletions
+1 -1
View File
@@ -483,7 +483,7 @@ export async function socialRoutes(app: FastifyInstance): Promise<void> {
const { q } = request.query; const { q } = request.query;
const db = getDb(); const db = getDb();
if (!q || q.length < 2) { if (!q || q.length < 1) {
return reply.code(200).send([]); return reply.code(200).send([]);
} }
+16 -4
View File
@@ -255,7 +255,8 @@ export const useSocialStore = create<SocialState>((set, get) => ({
const results = await Promise.allSettled(searches.map(s => s.promise)); const results = await Promise.allSettled(searches.map(s => s.promise));
const allUsers: TaggedUser[] = []; const allUsers: TaggedUser[] = [];
const seen = new Set<string>(); // Map canonical ID → index in allUsers for dedup with replacement
const seen = new Map<string, number>();
results.forEach((result, i) => { results.forEach((result, i) => {
if (result.status !== 'fulfilled') return; if (result.status !== 'fulfilled') return;
@@ -263,10 +264,21 @@ export const useSocialStore = create<SocialState>((set, get) => ({
for (const user of result.value) { for (const user of result.value) {
// Deduplicate by canonical identity: replicated profiles share // Deduplicate by canonical identity: replicated profiles share
// the same homeUserId as the native profile's id, so collapse them. // the same homeUserId as the native profile's id, so collapse them.
// Prefer the first seen (home instance is queried first → native wins). // Prefer native profiles (homeUserId is null) over replicated ones.
const canonicalId = user.homeUserId ?? user.id; const canonicalId = user.homeUserId ?? user.id;
if (seen.has(canonicalId)) continue; const isNative = !user.homeUserId;
seen.add(canonicalId); const existingIdx = seen.get(canonicalId);
if (existingIdx !== undefined) {
// Replace replicated with native when found
if (isNative) {
if (origin) normalizeUserAssets(user, origin);
allUsers[existingIdx] = { ...user, _instanceOrigin: origin };
}
continue;
}
seen.set(canonicalId, allUsers.length);
if (origin) normalizeUserAssets(user, origin); if (origin) normalizeUserAssets(user, origin);
allUsers.push({ ...user, _instanceOrigin: origin }); allUsers.push({ ...user, _instanceOrigin: origin });
} }