feat(backend,frontend): search everywhere in buttons, links and message data, a jump from search or an alert lights up the found words and buttons
This commit is contained in:
1 parent
acfa726e61
commit
d660079c02
21 files changed
+840
-76
No files matched your search
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { untrack } from "svelte";
|
||||
import { visible } from "#lib/actions/visible.js";
|
||||
import SearchEverywhere from "#lib/components/search/SearchEverywhere.svelte";
|
||||
import SearchMessageItem from "#lib/components/search/SearchMessageItem.svelte";
|
||||
import Button from "#lib/components/ui/Button.svelte";
|
||||
import EmptyState from "#lib/components/ui/EmptyState.svelte";
|
||||
@@ -15,7 +16,9 @@
|
||||
const DEBOUNCE_MS = 250;
|
||||
|
||||
const pager = createHitPager();
|
||||
const everywhere = createHitPager();
|
||||
let query = $state("");
|
||||
let deep = $state(false);
|
||||
let typing = $state(false);
|
||||
let timer: ReturnType<typeof setTimeout> | null = null;
|
||||
|
||||
@@ -23,14 +26,30 @@
|
||||
page.params.chatId ? Number(page.params.chatId) : null
|
||||
);
|
||||
|
||||
const needle = $derived(query.trim());
|
||||
const empty = $derived(
|
||||
needle !== "" &&
|
||||
!(typing || deep || pager.loading || pager.failed) &&
|
||||
pager.hits.length === 0
|
||||
);
|
||||
|
||||
function run() {
|
||||
typing = false;
|
||||
const value = query.trim();
|
||||
deep = false;
|
||||
everywhere.run(null);
|
||||
pager.run(
|
||||
value && chatId !== null ? { chat_id: chatId, query: value } : null
|
||||
needle && chatId !== null ? { chat_id: chatId, query: needle } : null
|
||||
);
|
||||
}
|
||||
|
||||
function searchEverywhere() {
|
||||
if (chatId === null) {
|
||||
return;
|
||||
}
|
||||
deep = true;
|
||||
everywhere.run({ chat_id: chatId, everywhere: true, query: needle });
|
||||
}
|
||||
|
||||
$effect(() => {
|
||||
if (chatId !== null) {
|
||||
untrack(run);
|
||||
@@ -46,11 +65,11 @@
|
||||
timer = setTimeout(run, DEBOUNCE_MS);
|
||||
}
|
||||
|
||||
function openHit(messageId: number) {
|
||||
function openHit(messageId: number, marks: string[]) {
|
||||
if (chatId === null) {
|
||||
return;
|
||||
}
|
||||
ui.requestJump(chatId, messageId);
|
||||
ui.requestJump(chatId, messageId, marks);
|
||||
if (isMobile()) {
|
||||
ui.closePanel();
|
||||
}
|
||||
@@ -73,9 +92,9 @@
|
||||
{#each pager.hits as hit (`${hit.chat_id}:${hit.message_id}`)}
|
||||
<SearchMessageItem
|
||||
{hit}
|
||||
href={search.hitHref(hit.chat_id, hit.message_id)}
|
||||
href={search.hitHref(hit.chat_id, hit.message_id, pager.terms)}
|
||||
inChat
|
||||
onclick={() => openHit(hit.message_id)}
|
||||
onclick={() => openHit(hit.message_id, pager.terms)}
|
||||
terms={pager.terms}
|
||||
/>
|
||||
{/each}
|
||||
@@ -96,7 +115,19 @@
|
||||
>{t("search.retry")}</Button
|
||||
>
|
||||
</div>
|
||||
{:else if query.trim() && !typing}
|
||||
{/if}
|
||||
<SearchEverywhere
|
||||
href={(hit) => search.hitHref(hit.chat_id, hit.message_id, [needle])}
|
||||
inChat
|
||||
{needle}
|
||||
onopen={(hit) => openHit(hit.message_id, [needle])}
|
||||
onstart={searchEverywhere}
|
||||
pager={everywhere}
|
||||
ready={!(typing || pager.loading || pager.failed || pager.hasMore)}
|
||||
shown={pager.hits}
|
||||
started={deep}
|
||||
/>
|
||||
{#if empty}
|
||||
<EmptyState title={t("search.nothing")} />
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user