Add list field to feed form

This commit is contained in:
Jon Staab 2024-04-24 16:38:50 -07:00
parent 44ce59c807
commit 12f134f26c
9 changed files with 58 additions and 26 deletions

View File

@ -12,7 +12,7 @@
import Toggle from "src/partials/Toggle.svelte"
import Modal from "src/partials/Modal.svelte"
import FeedForm from "src/app/shared/FeedForm.svelte"
import {feedLoader, displayPubkey} from "src/engine"
import {feedLoader, displayRelayUrl, displayPubkey} from "src/engine"
export let value
@ -71,19 +71,15 @@
{/if}
{#if feedType === FeedType.Relay}
<Chip class="mb-2 mr-2 inline-block">
On {quantify(feed[1], "relay")}
On {feed[1].length === 1 ? displayRelayUrl(feed[1][0]) : `${feed[1].length} relays`}
</Chip>
{:else if feedType === FeedType.List}
<Chip class="mb-2 mr-2 inline-block">
From {quantify(feed.slice(1), "list")}
</Chip>
{:else if feedType === FeedType.LOL}
<Chip class="mb-2 mr-2 inline-block">
From {quantify(feed.slice(1), "list")} of lists
From {quantify(feed.slice(1).length, "list")}
</Chip>
{:else if feedType === FeedType.DVM}
<Chip class="mb-2 mr-2 inline-block">
From {quantify(feed.slice(1), "DVM")}
From {quantify(feed.slice(1).length, "DVM")}
</Chip>
{:else if feedType === FeedType.Filter}
{#if feed.length > 2}

View File

@ -14,7 +14,7 @@
import Select from "src/partials/Select.svelte"
import SearchSelect from "src/partials/SearchSelect.svelte"
import FilterField from "src/app/shared/FilterField.svelte"
import {searchRelayUrls, displayRelayUrl} from "src/engine"
import {searchRelayUrls, searchListAddrs, displayListByAddress, displayRelayUrl} from "src/engine"
export let feed
export let onChange
@ -40,13 +40,10 @@
const onTypeChange = type => setAtCursor([type])
const onRelayChange = urls => setAtCursor(urls, [1])
const displayFeed = ([type, ...feed]) =>
switcherFn(type, {
[FeedType.Filter]: () => quantify(feed.length, "filter"),
[FeedType.List]: () => quantify(feed.length, "list"),
[FeedType.LOL]: () => quantify(feed.length, "list") + " of lists",
[FeedType.DVM]: () => quantify(feed.length, "DVM"),
[FeedType.Relay]: () =>
quantify(feed.slice(1).length, "feed") + " on " + quantify(feed[0].length, "relays"),
@ -68,8 +65,7 @@
<Field label="Feed Type">
<Select value={feedType} onChange={onTypeChange}>
<option value={FeedType.Filter}>Standard</option>
<option value={FeedType.List}>List</option>
<option value={FeedType.LOL}>List of lists</option>
<option value={FeedType.List}>From lists</option>
<option value={FeedType.DVM}>Data vending machine</option>
<option value={FeedType.Relay}>Relays</option>
<option value={FeedType.Union}>Union</option>
@ -88,11 +84,11 @@
multiple
value={feed[1] || []}
search={$searchRelayUrls}
onChange={onRelayChange}>
onChange={urls => setAtCursor(urls, [1])}>
<span slot="item" let:item>{displayRelayUrl(item)}</span>
</SearchSelect>
<p slot="info">Select which relays you'd like to limit loading feeds from.</p>
<p></p></Field>
</Field>
{:else if feedType === FeedType.Filter}
{#each current.slice(1) as filter, filterIdx ([current.length, filterIdx].join(':'))}
{@const feedIdx = inc(filterIdx)}
@ -111,7 +107,19 @@
<i class="fa fa-plus" /> Add filter
</Anchor>
</div>
{:else if feedType === FeedType.List}{:else if feedType === FeedType.LOL}{:else if feedType === FeedType.DVM}{/if}
{:else if feedType === FeedType.List}
<Field label="List Selections">
<SearchSelect
multiple
value={feed.slice(1)}
search={$searchListAddrs}
onChange={addrs => setAtCursor([FeedType.List, ...addrs])}>
<span slot="item" let:item>{displayListByAddress(item)}</span>
</SearchSelect>
<p slot="info">Select which lists you'd like to view.</p>
</Field>
{:else if feedType === FeedType.DVM}
{/if}
{#each subFeeds as subFeed, i (displayFeed(subFeed) + i)}
<Card class="flex items-center justify-between">
<span class="text-lg">{displayFeed(subFeed)}</span>
@ -133,7 +141,6 @@
<Menu>
<MenuItem on:click={() => addFeed(FeedType.Filter)}>Standard Feed</MenuItem>
<MenuItem on:click={() => addFeed(FeedType.List)}>List Feed</MenuItem>
<MenuItem on:click={() => addFeed(FeedType.LOL)}>Lists of Lists</MenuItem>
<MenuItem on:click={() => addFeed(FeedType.DVM)}>DVM Feed</MenuItem>
</Menu>
</div>

View File

@ -10,6 +10,7 @@ import {
isContextAddress,
decodeAddress,
} from "@welshman/util"
import {Tracker} from "@welshman/net"
import type {Feed, Loader} from "@welshman/feeds"
import {FeedLoader as CoreFeedLoader, FeedType} from "@welshman/feeds"
import {LOCAL_RELAY_URL, noteKinds, reactionKinds, repostKinds} from "src/util/nostr"
@ -68,13 +69,14 @@ export class FeedLoader {
}
const promises = []
const tracker = new Tracker()
// Use relays specified in feeds
if (relays.length > 0) {
promises.push(load({filters, relays, onEvent}))
promises.push(load({filters, relays, tracker, onEvent}))
} else {
if (!this.opts.skipCache) {
promises.push(load({filters, relays: [LOCAL_RELAY_URL], onEvent}))
promises.push(load({filters, relays: [LOCAL_RELAY_URL], tracker, onEvent}))
}
if (!this.opts.skipNetwork) {
@ -85,7 +87,7 @@ export class FeedLoader {
}
for (const {relay, filters} of selections) {
promises.push(load({filters, relays: [relay], onEvent}))
promises.push(load({filters, relays: [relay], tracker, onEvent}))
}
}
}

View File

@ -40,9 +40,7 @@
<Note note={$root} />
{#if showAncestors}
{#each $ancestors as ancestor (ancestor.id)}
<div in:fly={{y: 20}}>
<Note topLevel showParent={false} note={ancestor} />
</div>
<Note topLevel showParent={false} note={ancestor} />
{/each}
{:else if $ancestors.length > 0}
<Anchor

View File

@ -1,9 +1,10 @@
import {whereEq, sortBy} from "ramda"
import {whereEq, pluck, sortBy} from "ramda"
import {derivedCollection} from "@welshman/lib"
import {pubkey} from "src/engine/session/state"
import {deletes} from "src/engine/events/state"
import type {List} from "./model"
import {_lists} from "./state"
import {getListSearch} from './utils'
export const lists = derivedCollection<List>("address", [_lists, deletes], ([$l, $d]) =>
$l.filter(l => !$d.has(l.address)),
@ -23,3 +24,7 @@ export const userLists = derivedCollection<List>("address", [lists, pubkey], ([$
return sortBy(getName, Array.from(m.values()))
})
export const searchLists = lists.derived(getListSearch)
export const searchListAddrs = searchLists.derived(search => term => pluck('address', search(term)))

View File

@ -1,5 +1,6 @@
export * from "./model"
export * from "./state"
export * from "./utils"
export * from "./derived"
export * from "./projections"
export * from "./commands"

11
src/engine/lists/utils.ts Normal file
View File

@ -0,0 +1,11 @@
import {fuzzy} from "src/util/misc"
import type {List} from "./model"
import {_lists} from './state'
export const displayList = (list: List) => list?.title || ""
export const displayListByAddress = (address: string) => displayList(_lists.key(address).get())
export const getListSearch = ($lists: List[]): ((term: string) => List[]) => {
return fuzzy($lists, {keys: ["title", "description"]})
}

View File

@ -35,6 +35,7 @@
export const clearValue = () => {
value = multiple ? [] : null
onChange?.(value)
}
export const clearTerm = () => {
@ -47,6 +48,7 @@
const remove = item => {
value = multiple ? reject(equals(item), value) : null
onChange?.(value)
}
const select = item => {

View File

@ -88,11 +88,21 @@ export const createScroller = (
loadMore: () => Promise<void>,
{delay = 1000, threshold = 2000, reverse = false, element}: ScrollerOpts = {},
) => {
const getScrollElement = () => {
let e = element
while (e.parentElement && e.scrollTop === 0) {
e = e.parentElement
}
return e
}
let done = false
const check = async () => {
// While we have empty space, fill it
const {scrollY, innerHeight} = window
const {scrollHeight, scrollTop} = element
const {scrollHeight, scrollTop} = getScrollElement()
const offset = Math.abs(scrollTop || scrollY)
const shouldLoad = offset + innerHeight + threshold > scrollHeight