Add filter summary to feeds

This commit is contained in:
Jonathan Staab 2023-06-13 09:08:05 -07:00
parent a40b9268f6
commit d65aa309db
11 changed files with 78 additions and 14 deletions

View File

@ -2,7 +2,10 @@
# 0.2.31
- [x] Added the ability to view and write reviews on relays, with ratings
- [x] Add the ability to view and write reviews on relays, with ratings
- [x] Add support for parsing and displaying lnurl invoices
- [x] Add advanced search to feeds with a summary of the filter applied
- [x] Improve url parsing
# 0.2.30

View File

@ -17,7 +17,6 @@
- [ ] Fix unauthenticated experience. Going to an npub just spins
- [ ] Convert app store to nip 89
- [ ] Put search icon in header or hover button, open in modal
- [ ] Advanced search
# Core

View File

@ -160,6 +160,7 @@ class PublishableEvent {
}
async publish(relays, onProgress = null, verb = "EVENT") {
const event = await this.getSignedEvent()
// console.log(event); return
const promise = pool.publish({relays, event, onProgress, verb})
// Copy the event since loki mutates it to add metadata

View File

@ -10,6 +10,7 @@
import Spinner from "src/partials/Spinner.svelte"
import Modal from "src/partials/Modal.svelte"
import Content from "src/partials/Content.svelte"
import FilterSummary from "src/app/shared/FilterSummary.svelte"
import FeedAdvanced from "src/app/shared/FeedAdvanced.svelte"
import RelayFeed from "src/app/shared/RelayFeed.svelte"
import Note from "src/app/shared/Note.svelte"
@ -36,6 +37,7 @@
$: searchNotes = debounce(300, fuzzy(notes, {keys: ["content"]}))
$: filteredNotes = search ? searchNotes(search) : notes
$: mergedFilter = mergeFilter(filter, overrides)
const since = now()
const maxNotes = 100
@ -121,14 +123,12 @@
// 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 getFilter = () => mergeFilter(filter, {since, ...overrides})
const loadMore = async () => {
const _key = key
// Wait for this page to load before trying again
await cursor.loadPage({
filter: getFilter(),
filter: mergedFilter,
onChunk: chunk => {
// Stack promises to avoid too many concurrent subscriptions
p = p.then(() => key === _key && onChunk(chunk))
@ -157,7 +157,7 @@
if (!filter.until) {
sub = network.listen({
relays: getRelays(),
filter: getFilter(),
filter: mergeFilter(mergedFilter, {since}),
onChunk: chunk => {
p = p.then(() => _key === key && onChunk(chunk))
},
@ -192,7 +192,10 @@
</div>
{/if}
<FeedAdvanced onChange={start} hide={Object.keys(filter)} />
<div class="flex justify-between gap-4">
<FilterSummary filter={mergedFilter} />
<FeedAdvanced onChange={start} hide={Object.keys(filter)} />
</div>
<div class="flex flex-col gap-4">
{#each filteredNotes as note (note.id)}

View File

@ -55,7 +55,7 @@
}
</script>
<div class="flex justify-end gap-2" in:fly={{y: 20}}>
<div class="flex justify-end gap-2 p-2" in:fly={{y: 20}}>
<i
class="fa fa-search cursor-pointer"
on:click={() => {

View File

@ -0,0 +1,56 @@
<script lang="ts">
import {formatTimestampAsDate} from "src/util/misc"
import {displayPerson} from "src/util/nostr"
import Chip from "src/partials/Chip.svelte"
import {getPersonWithFallback} from "src/agent/db"
export let filter
const displayPeople = pubkeys =>
pubkeys.length === 1
? displayPerson(getPersonWithFallback(pubkeys[0]))
: `${pubkeys.length} people`
const displayTopics = topics => (topics.length === 1 ? topics[0] : `${topics.length} topics`)
const getFilterParts = f => {
const parts = []
if (filter.since && filter.until) {
const since = formatTimestampAsDate(filter.since)
const until = formatTimestampAsDate(filter.until)
parts.push(`Between ${since} and ${until}`)
} else if (filter.since) {
parts.push(`After ${formatTimestampAsDate(filter.since)}`)
} else if (filter.until) {
parts.push(`Before ${formatTimestampAsDate(filter.until)}`)
}
if (filter.authors?.length > 0) {
parts.push(`By ${displayPeople(filter.authors)}`)
}
if (filter["#p"]?.length > 0) {
parts.push(`Mentioning ${displayPeople(filter["#p"])}`)
}
if (filter["#t"]?.length > 0) {
parts.push(`Related to ${displayTopics(filter["#t"])}`)
}
if (filter.search) {
parts.push(`Matching ${filter.search}`)
}
return parts
}
$: parts = getFilterParts(filter)
</script>
<div>
{#each parts as part}
<Chip class="mr-2 mb-2">{part}</Chip>
{/each}
</div>

View File

@ -130,7 +130,7 @@
</div>
<div on:click|stopPropagation>
{#each data.mentions as p}
<Chip class="mr-1 mb-1" theme="dark" on:click={() => removeMention(p)}>
<Chip class="mr-1 mb-1" theme="dark" onClick={() => removeMention(p)}>
{displayPerson(getPersonWithFallback(p))}
</Chip>
{:else}

View File

@ -19,7 +19,6 @@
["https://nostrplebs.com", "NostrPlebs", "Get verified at nostrplebs.com."],
["https://nadar.tigerville.no", "Nadar", "Find out what relays know about your post."],
["https://pinstr.app", "Pinstr", "Create and manage collections of notes."],
["https://advancednostrsearch.vercel.app", "Advanced Search", "Find what you're looking for."],
]
document.title = "Apps"

View File

@ -46,7 +46,7 @@
relays = urls.length > 0 ? urls.map(objOf("url")) : sampleRelays(getUserReadRelays())
}
filter = [{...filter, kinds: [1]}]
filter = {...filter, kinds: [1, 1985]}
}
const setActiveTab = tab => {

View File

@ -1,7 +1,8 @@
<script lang="ts">
import cx from "classnames"
export let theme
export let theme = "dark"
export let onClick = null
const className = cx($$props.class, "inline-block rounded-full border border-solid py-1 px-2", {
"border-gray-1": theme === "dark",
@ -11,7 +12,9 @@
<div class={className}>
<div class="flex items-center gap-2">
<i class="fa fa-times cursor-pointer" on:click|preventDefault />
{#if onClick}
<i class="fa fa-times cursor-pointer" on:click|preventDefault={onClick} />
{/if}
<slot />
</div>
</div>

View File

@ -59,7 +59,7 @@
<div class="text-sm">
{#each value as item}
<Chip class="mr-1 mb-1" theme="dark" on:click={() => remove(item)}>
<Chip class="mr-1 mb-1" theme="dark" onClick={() => remove(item)}>
<slot name="item" {item}>
{item}
</slot>