feat(api,userbot,frontend): search peers without chats and start tracking them

This commit is contained in:
hh committed 2026-08-05 23:46:54 +02:00
1 parent dcf95bd9d4
commit 92fd20137e
21 files changed
+936 -65

No files matched your search

+46 -14
View File
@@ -1,16 +1,18 @@
import { searchMessages } from "$lib/api/endpoints";
import type { SearchHit } from "$lib/api/types";
import { discoverPeers, searchMessages } from "$lib/api/endpoints";
import type { DiscoverItem, SearchHit } from "$lib/api/types";
import { chats } from "$lib/stores/chats.svelte";
const DEBOUNCE_MS = 250;
const REMOTE_DEBOUNCE_MS = 700;
const MIN_LENGTH = 1;
function createSearch() {
let active = $state(false);
let query = $state("");
let messageHits = $state<SearchHit[]>([]);
let peerResults = $state<DiscoverItem[]>([]);
let loading = $state(false);
let timer: ReturnType<typeof setTimeout> | null = null;
let timers: ReturnType<typeof setTimeout>[] = [];
let seq = 0;
const trimmed = $derived(query.trim());
@@ -23,9 +25,12 @@ function createSearch() {
(chat.title ?? "").toLowerCase().includes(needle)
);
});
const peerHits = $derived.by(() => {
const shown = new Set(chatHits.map((chat) => chat.chat_id));
return peerResults.filter((item) => !shown.has(item.chat_id));
});
async function run(value: string) {
const current = ++seq;
async function runMessages(value: string, current: number) {
try {
const hits = await searchMessages(value);
if (current === seq) {
@@ -42,21 +47,46 @@ function createSearch() {
}
}
function schedule() {
if (timer) {
async function runPeers(value: string, current: number, remote: boolean) {
try {
const items = await discoverPeers(value, remote);
if (current === seq) {
peerResults = items;
}
} catch {
if (current === seq && !remote) {
peerResults = [];
}
}
}
function clearTimers() {
for (const timer of timers) {
clearTimeout(timer);
}
timers = [];
}
function schedule() {
clearTimers();
const value = trimmed;
const current = ++seq;
if (value.length < MIN_LENGTH) {
seq++;
messageHits = [];
peerResults = [];
loading = false;
return;
}
loading = true;
timer = setTimeout(() => {
run(value).catch(() => undefined);
}, DEBOUNCE_MS);
timers.push(
setTimeout(() => {
runMessages(value, current).catch(() => undefined);
runPeers(value, current, false).catch(() => undefined);
}, DEBOUNCE_MS),
setTimeout(() => {
runPeers(value, current, true).catch(() => undefined);
}, REMOTE_DEBOUNCE_MS)
);
}
return {
@@ -78,6 +108,9 @@ function createSearch() {
get chatHits() {
return chatHits;
},
get peerHits() {
return peerHits;
},
open() {
active = true;
},
@@ -89,11 +122,10 @@ function createSearch() {
active = false;
query = "";
messageHits = [];
peerResults = [];
loading = false;
seq++;
if (timer) {
clearTimeout(timer);
}
clearTimers();
},
};
}