mirror of
https://github.com/coracle-social/coracle.git
synced 2024-09-18 19:23:40 +00:00
Allow advanced filters to control entire feed
This commit is contained in:
parent
8f96398419
commit
509e316ee6
@ -27,7 +27,7 @@
|
|||||||
export let invertColors = false
|
export let invertColors = false
|
||||||
export let onEvent = null
|
export let onEvent = null
|
||||||
|
|
||||||
let sub, scroller, cursor, overrides
|
let sub, scroller, cursor
|
||||||
let key = Math.random()
|
let key = Math.random()
|
||||||
let search = ""
|
let search = ""
|
||||||
let notes = []
|
let notes = []
|
||||||
@ -37,7 +37,6 @@
|
|||||||
|
|
||||||
$: searchNotes = debounce(300, fuzzy(notes, {keys: ["content"]}))
|
$: searchNotes = debounce(300, fuzzy(notes, {keys: ["content"]}))
|
||||||
$: filteredNotes = search ? searchNotes(search) : notes
|
$: filteredNotes = search ? searchNotes(search) : notes
|
||||||
$: mergedFilter = mergeFilter(filter, overrides)
|
|
||||||
|
|
||||||
const since = now()
|
const since = now()
|
||||||
const maxNotes = 100
|
const maxNotes = 100
|
||||||
@ -121,14 +120,14 @@
|
|||||||
let p = Promise.resolve()
|
let p = Promise.resolve()
|
||||||
|
|
||||||
// If we have a search term we need to use only relays that support search
|
// If we have a search term we need to use only relays that support search
|
||||||
const getRelays = () => (overrides?.search ? [{url: "wss://relay.nostr.band"}] : relays)
|
const getRelays = () => (filter.search ? [{url: "wss://relay.nostr.band"}] : relays)
|
||||||
|
|
||||||
const loadMore = async () => {
|
const loadMore = async () => {
|
||||||
const _key = key
|
const _key = key
|
||||||
|
|
||||||
// Wait for this page to load before trying again
|
// Wait for this page to load before trying again
|
||||||
await cursor.loadPage({
|
await cursor.loadPage({
|
||||||
filter: mergedFilter,
|
filter,
|
||||||
onChunk: chunk => {
|
onChunk: chunk => {
|
||||||
// Stack promises to avoid too many concurrent subscriptions
|
// Stack promises to avoid too many concurrent subscriptions
|
||||||
p = p.then(() => key === _key && onChunk(chunk))
|
p = p.then(() => key === _key && onChunk(chunk))
|
||||||
@ -145,19 +144,19 @@
|
|||||||
key = Math.random()
|
key = Math.random()
|
||||||
}
|
}
|
||||||
|
|
||||||
const start = (_overrides = {}) => {
|
const start = (newFilter = {}) => {
|
||||||
if (!equals(_overrides, overrides)) {
|
if (!equals(newFilter, filter)) {
|
||||||
stop()
|
stop()
|
||||||
|
|
||||||
const _key = key
|
const _key = key
|
||||||
|
|
||||||
overrides = _overrides
|
filter = {...filter, ...newFilter}
|
||||||
|
|
||||||
// No point in subscribing if we have an end date
|
// No point in subscribing if we have an end date
|
||||||
if (!filter.until) {
|
if (!filter.until) {
|
||||||
sub = network.listen({
|
sub = network.listen({
|
||||||
relays: getRelays(),
|
relays: getRelays(),
|
||||||
filter: mergeFilter(mergedFilter, {since}),
|
filter: mergeFilter(filter, {since}),
|
||||||
onChunk: chunk => {
|
onChunk: chunk => {
|
||||||
p = p.then(() => _key === key && onChunk(chunk))
|
p = p.then(() => _key === key && onChunk(chunk))
|
||||||
},
|
},
|
||||||
@ -166,7 +165,7 @@
|
|||||||
|
|
||||||
cursor = new network.Cursor({
|
cursor = new network.Cursor({
|
||||||
relays: getRelays(),
|
relays: getRelays(),
|
||||||
until: overrides.until || now(),
|
until: filter.until || now(),
|
||||||
delta,
|
delta,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -193,8 +192,8 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div class="flex justify-between gap-4" in:fly={{y: 20}}>
|
<div class="flex justify-between gap-4" in:fly={{y: 20}}>
|
||||||
<FilterSummary filter={mergedFilter} />
|
<FilterSummary {filter} />
|
||||||
<FeedAdvanced onChange={start} hide={Object.keys(filter)} />
|
<FeedAdvanced {filter} onChange={start} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col gap-4">
|
<div class="flex flex-col gap-4">
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type {Filter} from "nostr-tools"
|
import type {Filter} from "nostr-tools"
|
||||||
import {pluck} from "ramda"
|
import {pluck, objOf} from "ramda"
|
||||||
import {debounce} from "throttle-debounce"
|
import {debounce} from "throttle-debounce"
|
||||||
import {createLocalDate} from "src/util/misc"
|
import {createLocalDate} from "src/util/misc"
|
||||||
import Input from "src/partials/Input.svelte"
|
import Input from "src/partials/Input.svelte"
|
||||||
@ -11,32 +11,34 @@
|
|||||||
import PersonBadge from "src/app/shared/PersonBadge.svelte"
|
import PersonBadge from "src/app/shared/PersonBadge.svelte"
|
||||||
import {searchTopics, searchPeople, getPersonWithFallback} from "src/agent/db"
|
import {searchTopics, searchPeople, getPersonWithFallback} from "src/agent/db"
|
||||||
|
|
||||||
export let hide = []
|
|
||||||
export let onChange
|
export let onChange
|
||||||
|
export let filter = {} as Filter
|
||||||
|
|
||||||
let filter = {
|
let _filter = {
|
||||||
since: null,
|
since: filter.since,
|
||||||
until: null,
|
until: filter.since,
|
||||||
authors: [],
|
search: filter.search || "",
|
||||||
search: "",
|
authors: (filter.authors || []).map(getPersonWithFallback),
|
||||||
"#t": [],
|
"#t": (filter["#t"] || []).map(objOf("name")),
|
||||||
"#p": [],
|
"#p": (filter["#p"] || []).map(getPersonWithFallback),
|
||||||
}
|
}
|
||||||
|
|
||||||
let modal = null
|
let modal = null
|
||||||
|
|
||||||
const applyFilter = debounce(300, () => {
|
const applyFilter = debounce(300, () => {
|
||||||
if (modal !== "maxi") {
|
if (modal !== "maxi") {
|
||||||
const _filter = {} as Filter
|
const newFilter = {} as Filter
|
||||||
|
|
||||||
if (filter.since) _filter.since = createLocalDate(filter.since).setHours(23, 59, 59, 0) / 1000
|
if (_filter.since)
|
||||||
if (filter.until) _filter.until = createLocalDate(filter.until).setHours(23, 59, 59, 0) / 1000
|
newFilter.since = createLocalDate(_filter.since).setHours(23, 59, 59, 0) / 1000
|
||||||
if (filter.authors.length > 0) _filter.authors = pluck("pubkey", filter.authors)
|
if (_filter.until)
|
||||||
if (filter.search) _filter.search = filter.search
|
newFilter.until = createLocalDate(_filter.until).setHours(23, 59, 59, 0) / 1000
|
||||||
if (filter["#t"].length > 0) _filter["#t"] = pluck("name", filter["#t"])
|
if (_filter.authors.length > 0) newFilter.authors = pluck("pubkey", _filter.authors)
|
||||||
if (filter["#p"].length > 0) _filter["#p"] = pluck("pubkey", filter["#p"])
|
if (_filter.search) newFilter.search = _filter.search
|
||||||
|
if (_filter["#t"].length > 0) newFilter["#t"] = pluck("name", _filter["#t"])
|
||||||
|
if (_filter["#p"].length > 0) newFilter["#p"] = pluck("pubkey", _filter["#p"])
|
||||||
|
|
||||||
onChange(_filter)
|
onChange(newFilter)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -68,7 +70,7 @@
|
|||||||
<Content size="lg">
|
<Content size="lg">
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<strong>Search</strong>
|
<strong>Search</strong>
|
||||||
<Input bind:value={filter.search} on:input={applyFilter}>
|
<Input bind:value={_filter.search} on:input={applyFilter}>
|
||||||
<i slot="before" class="fa fa-search" />
|
<i slot="before" class="fa fa-search" />
|
||||||
</Input>
|
</Input>
|
||||||
</div>
|
</div>
|
||||||
@ -76,49 +78,43 @@
|
|||||||
<div class="grid grid-cols-2 gap-2">
|
<div class="grid grid-cols-2 gap-2">
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<strong>Since</strong>
|
<strong>Since</strong>
|
||||||
<Input type="date" bind:value={filter.since} />
|
<Input type="date" bind:value={_filter.since} />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<strong>Until</strong>
|
<strong>Until</strong>
|
||||||
<Input type="date" bind:value={filter.until} />
|
<Input type="date" bind:value={_filter.until} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{#if !hide.includes("authors")}
|
<div class="flex flex-col gap-1">
|
||||||
<div class="flex flex-col gap-1">
|
<strong>Authors</strong>
|
||||||
<strong>Authors</strong>
|
<MultiSelect search={$searchPeople} bind:value={_filter.authors}>
|
||||||
<MultiSelect search={$searchPeople} bind:value={filter.authors}>
|
<div slot="item" let:item>
|
||||||
<div slot="item" let:item>
|
<div class="-my-1">
|
||||||
<div class="-my-1">
|
<PersonBadge inert person={getPersonWithFallback(item.pubkey)} />
|
||||||
<PersonBadge inert person={getPersonWithFallback(item.pubkey)} />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</MultiSelect>
|
</div>
|
||||||
</div>
|
</MultiSelect>
|
||||||
{/if}
|
</div>
|
||||||
{#if !hide.includes("#t")}
|
<div class="flex flex-col gap-1">
|
||||||
<div class="flex flex-col gap-1">
|
<strong>Topics</strong>
|
||||||
<strong>Topics</strong>
|
<MultiSelect search={$searchTopics} bind:value={_filter["#t"]}>
|
||||||
<MultiSelect search={$searchTopics} bind:value={filter["#t"]}>
|
<div slot="item" let:item>
|
||||||
<div slot="item" let:item>
|
<div class="-my-1">
|
||||||
<div class="-my-1">
|
#{item.name}
|
||||||
#{item.name}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</MultiSelect>
|
</div>
|
||||||
</div>
|
</MultiSelect>
|
||||||
{/if}
|
</div>
|
||||||
{#if !hide.includes("#p")}
|
<div class="flex flex-col gap-1">
|
||||||
<div class="flex flex-col gap-1">
|
<strong>Mentions</strong>
|
||||||
<strong>Mentions</strong>
|
<MultiSelect search={$searchPeople} bind:value={_filter["#p"]}>
|
||||||
<MultiSelect search={$searchPeople} bind:value={filter["#p"]}>
|
<div slot="item" let:item>
|
||||||
<div slot="item" let:item>
|
<div class="-my-1">
|
||||||
<div class="-my-1">
|
<PersonBadge inert person={getPersonWithFallback(item.pubkey)} />
|
||||||
<PersonBadge inert person={getPersonWithFallback(item.pubkey)} />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</MultiSelect>
|
</div>
|
||||||
</div>
|
</MultiSelect>
|
||||||
{/if}
|
</div>
|
||||||
<div class="flex justify-end">
|
<div class="flex justify-end">
|
||||||
<Anchor type="button-accent" on:click={submit}>Apply Filters</Anchor>
|
<Anchor type="button-accent" on:click={submit}>Apply Filters</Anchor>
|
||||||
</div>
|
</div>
|
||||||
|
@ -50,6 +50,9 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
{#if parts.length > 0}
|
||||||
|
<span class="mr-2 mb-2"> Showing notes: </span>
|
||||||
|
{/if}
|
||||||
{#each parts as part}
|
{#each parts as part}
|
||||||
<Chip class="mr-2 mb-2">{part}</Chip>
|
<Chip class="mr-2 mb-2">{part}</Chip>
|
||||||
{/each}
|
{/each}
|
||||||
|
Loading…
Reference in New Issue
Block a user