mirror of
https://github.com/coracle-social/coracle.git
synced 2024-09-18 19:23:40 +00:00
Add filter summary to feeds
This commit is contained in:
parent
a40b9268f6
commit
d65aa309db
@ -2,7 +2,10 @@
|
|||||||
|
|
||||||
# 0.2.31
|
# 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
|
# 0.2.30
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
- [ ] Fix unauthenticated experience. Going to an npub just spins
|
- [ ] Fix unauthenticated experience. Going to an npub just spins
|
||||||
- [ ] Convert app store to nip 89
|
- [ ] Convert app store to nip 89
|
||||||
- [ ] Put search icon in header or hover button, open in modal
|
- [ ] Put search icon in header or hover button, open in modal
|
||||||
- [ ] Advanced search
|
|
||||||
|
|
||||||
# Core
|
# Core
|
||||||
|
|
||||||
|
@ -160,6 +160,7 @@ class PublishableEvent {
|
|||||||
}
|
}
|
||||||
async publish(relays, onProgress = null, verb = "EVENT") {
|
async publish(relays, onProgress = null, verb = "EVENT") {
|
||||||
const event = await this.getSignedEvent()
|
const event = await this.getSignedEvent()
|
||||||
|
// console.log(event); return
|
||||||
const promise = pool.publish({relays, event, onProgress, verb})
|
const promise = pool.publish({relays, event, onProgress, verb})
|
||||||
|
|
||||||
// Copy the event since loki mutates it to add metadata
|
// Copy the event since loki mutates it to add metadata
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
import Spinner from "src/partials/Spinner.svelte"
|
import Spinner from "src/partials/Spinner.svelte"
|
||||||
import Modal from "src/partials/Modal.svelte"
|
import Modal from "src/partials/Modal.svelte"
|
||||||
import Content from "src/partials/Content.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 FeedAdvanced from "src/app/shared/FeedAdvanced.svelte"
|
||||||
import RelayFeed from "src/app/shared/RelayFeed.svelte"
|
import RelayFeed from "src/app/shared/RelayFeed.svelte"
|
||||||
import Note from "src/app/shared/Note.svelte"
|
import Note from "src/app/shared/Note.svelte"
|
||||||
@ -36,6 +37,7 @@
|
|||||||
|
|
||||||
$: 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 +123,12 @@
|
|||||||
// 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 = () => (overrides?.search ? [{url: "wss://relay.nostr.band"}] : relays)
|
||||||
|
|
||||||
const getFilter = () => mergeFilter(filter, {since, ...overrides})
|
|
||||||
|
|
||||||
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: getFilter(),
|
filter: mergedFilter,
|
||||||
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))
|
||||||
@ -157,7 +157,7 @@
|
|||||||
if (!filter.until) {
|
if (!filter.until) {
|
||||||
sub = network.listen({
|
sub = network.listen({
|
||||||
relays: getRelays(),
|
relays: getRelays(),
|
||||||
filter: getFilter(),
|
filter: mergeFilter(mergedFilter, {since}),
|
||||||
onChunk: chunk => {
|
onChunk: chunk => {
|
||||||
p = p.then(() => _key === key && onChunk(chunk))
|
p = p.then(() => _key === key && onChunk(chunk))
|
||||||
},
|
},
|
||||||
@ -192,7 +192,10 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/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">
|
<div class="flex flex-col gap-4">
|
||||||
{#each filteredNotes as note (note.id)}
|
{#each filteredNotes as note (note.id)}
|
||||||
|
@ -55,7 +55,7 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</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
|
<i
|
||||||
class="fa fa-search cursor-pointer"
|
class="fa fa-search cursor-pointer"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
|
56
src/app/shared/FilterSummary.svelte
Normal file
56
src/app/shared/FilterSummary.svelte
Normal 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>
|
@ -130,7 +130,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div on:click|stopPropagation>
|
<div on:click|stopPropagation>
|
||||||
{#each data.mentions as p}
|
{#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))}
|
{displayPerson(getPersonWithFallback(p))}
|
||||||
</Chip>
|
</Chip>
|
||||||
{:else}
|
{:else}
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
["https://nostrplebs.com", "NostrPlebs", "Get verified at nostrplebs.com."],
|
["https://nostrplebs.com", "NostrPlebs", "Get verified at nostrplebs.com."],
|
||||||
["https://nadar.tigerville.no", "Nadar", "Find out what relays know about your post."],
|
["https://nadar.tigerville.no", "Nadar", "Find out what relays know about your post."],
|
||||||
["https://pinstr.app", "Pinstr", "Create and manage collections of notes."],
|
["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"
|
document.title = "Apps"
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
relays = urls.length > 0 ? urls.map(objOf("url")) : sampleRelays(getUserReadRelays())
|
relays = urls.length > 0 ? urls.map(objOf("url")) : sampleRelays(getUserReadRelays())
|
||||||
}
|
}
|
||||||
|
|
||||||
filter = [{...filter, kinds: [1]}]
|
filter = {...filter, kinds: [1, 1985]}
|
||||||
}
|
}
|
||||||
|
|
||||||
const setActiveTab = tab => {
|
const setActiveTab = tab => {
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import cx from "classnames"
|
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", {
|
const className = cx($$props.class, "inline-block rounded-full border border-solid py-1 px-2", {
|
||||||
"border-gray-1": theme === "dark",
|
"border-gray-1": theme === "dark",
|
||||||
@ -11,7 +12,9 @@
|
|||||||
|
|
||||||
<div class={className}>
|
<div class={className}>
|
||||||
<div class="flex items-center gap-2">
|
<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 />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -59,7 +59,7 @@
|
|||||||
|
|
||||||
<div class="text-sm">
|
<div class="text-sm">
|
||||||
{#each value as item}
|
{#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}>
|
<slot name="item" {item}>
|
||||||
{item}
|
{item}
|
||||||
</slot>
|
</slot>
|
||||||
|
Loading…
Reference in New Issue
Block a user