mirror of
https://github.com/coracle-social/coracle.git
synced 2024-09-30 00:41:12 +00:00
Use new feeds
This commit is contained in:
parent
1db27a5e11
commit
9f2e59e679
@ -71,7 +71,7 @@
|
||||
let subs = []
|
||||
|
||||
onMount(async () => {
|
||||
const {filters} = await feedLoader.compiler.compile(feed)
|
||||
const [{filters}] = await feedLoader.compiler.compile(feed)
|
||||
const selections = getFilterSelections(filters)
|
||||
|
||||
subs = forcePlatformRelaySelections(selections).map(({relay, filters}) =>
|
||||
|
@ -1,7 +1,8 @@
|
||||
<script lang="ts">
|
||||
import {onMount} from "svelte"
|
||||
import {Storage} from "hurdak"
|
||||
import {prop} from 'ramda'
|
||||
import {prop} from "ramda"
|
||||
import type {Filter} from "@welshman/util"
|
||||
import type {Feed} from "@welshman/feeds"
|
||||
import {createScroller} from "src/util/misc"
|
||||
import {fly} from "src/util/transition"
|
||||
@ -25,7 +26,7 @@
|
||||
export let onEvent = null
|
||||
|
||||
let element
|
||||
let filters = [{ids: []}]
|
||||
let filters: Filter[] = [{ids: []}]
|
||||
let limit = 0
|
||||
let opts = {
|
||||
feed,
|
||||
@ -54,9 +55,14 @@
|
||||
const update = async opts => {
|
||||
limit = 0
|
||||
start(opts)
|
||||
filters = feedLoader.compiler.canCompile(opts.feed)
|
||||
? prop('filters', await feedLoader.compiler.compile(opts.feed))
|
||||
: [{ids: []}]
|
||||
|
||||
if (feedLoader.compiler.canCompile(opts.feed)) {
|
||||
const requests = await feedLoader.compiler.compile(opts.feed)
|
||||
|
||||
filters = requests.flatMap(r => r.filters)
|
||||
} else {
|
||||
filters = [{ids: []}]
|
||||
}
|
||||
}
|
||||
|
||||
$: {
|
||||
|
@ -4,7 +4,7 @@
|
||||
import {isNil, clamp} from "@welshman/lib"
|
||||
import type {DynamicFilter, Feed} from "@welshman/feeds"
|
||||
import {FeedType, Scope, getSubFeeds} from "@welshman/feeds"
|
||||
import {slide} from 'src/util/transition'
|
||||
import {slide} from "src/util/transition"
|
||||
import {formatTimestampAsDate, getStringWidth} from "src/util/misc"
|
||||
import Card from "src/partials/Card.svelte"
|
||||
import Popover from "src/partials/Popover.svelte"
|
||||
@ -68,7 +68,7 @@
|
||||
if (text) {
|
||||
setPart({search: text})
|
||||
} else {
|
||||
removeParts(['search'])
|
||||
removeParts(["search"])
|
||||
}
|
||||
}
|
||||
|
||||
@ -128,7 +128,7 @@
|
||||
{:else}
|
||||
{#await feedLoader.compiler.compile(feed)}
|
||||
<!-- pass -->
|
||||
{:then { filters: [filter] }}
|
||||
{:then [{ filters: [filter] }]}
|
||||
<Popover
|
||||
class="inline-block"
|
||||
placement="bottom-end"
|
||||
@ -217,7 +217,7 @@
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if isOpen}
|
||||
{#if true || isOpen}
|
||||
<Modal onEscape={closeModal}>
|
||||
<Subheading class="ml-6">Create a custom Feed</Subheading>
|
||||
<FeedForm {feed} onCancel={closeModal} onChange={saveFeed} />
|
||||
|
@ -16,45 +16,43 @@
|
||||
import SearchSelect from "src/partials/SearchSelect.svelte"
|
||||
import FilterField from "src/app/shared/FilterField.svelte"
|
||||
import DVMField from "src/app/shared/DVMField.svelte"
|
||||
import FeedFormRelay from "src/app/shared/FeedFormRelay.svelte"
|
||||
import {searchRelayUrls, searchListAddrs, displayListByAddress, displayRelayUrl} from "src/engine"
|
||||
|
||||
export let feed
|
||||
export let onChange
|
||||
export let onCancel
|
||||
|
||||
const pushCursor = i => {
|
||||
const controller = {
|
||||
pushCursor: i => {
|
||||
cursor = [...cursor, i]
|
||||
}
|
||||
|
||||
const popCursor = i => {
|
||||
},
|
||||
popCursor: i => {
|
||||
cursor = cursor.slice(0, -1)
|
||||
}
|
||||
|
||||
const setAtCursor = (v, p = []) => {
|
||||
},
|
||||
setAtCursor: (v, p = []) => {
|
||||
feed = assocPath(cursor.concat(p), v, feed)
|
||||
}
|
||||
|
||||
const updateAtCursor = (f, p = []) => {
|
||||
},
|
||||
updateAtCursor: (f, p = []) => {
|
||||
feed = updatePath(cursor.concat(p), f, feed)
|
||||
},
|
||||
addFeed: feedType => controller.setAtCursor([...current, [feedType]]),
|
||||
removeFeed: i => controller.setAtCursor(current.toSpliced(i, 1)),
|
||||
}
|
||||
|
||||
const addFeed = feedType => setAtCursor([...current, [feedType]])
|
||||
|
||||
const removeFeed = i => setAtCursor(current.toSpliced(i, 1))
|
||||
|
||||
const onTypeChange = type => {
|
||||
if (hasSubFeeds([type])) {
|
||||
if (hasSubFeeds(current)) {
|
||||
setAtCursor([type, ...current.slice(1)])
|
||||
controller.setAtCursor([type, ...current.slice(1)])
|
||||
} else {
|
||||
setAtCursor([type, current])
|
||||
controller.setAtCursor([type, current])
|
||||
}
|
||||
} else if (type === FeedType.Filter) {
|
||||
setAtCursor([type, {}])
|
||||
controller.setAtCursor([type, {}])
|
||||
} else if (type === FeedType.DVM) {
|
||||
setAtCursor([type, {kind: 5300, tags: [], relays: []}])
|
||||
controller.setAtCursor([type, {kind: 5300, tags: [], relays: []}])
|
||||
} else {
|
||||
setAtCursor([type])
|
||||
controller.setAtCursor([type])
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,50 +86,52 @@
|
||||
value={feedType}>
|
||||
<div slot="item" class="flex flex-col items-center" let:option let:active>
|
||||
{#if option === FeedType.Filter}
|
||||
<Icon icon="people-nearby" class="w-12 h-12" color={active ? "accent" : "tinted-800"} />
|
||||
<span class="text-2xl staatliches">Standard</span>
|
||||
<Icon icon="people-nearby" class="h-12 w-12" color={active ? "accent" : "tinted-800"} />
|
||||
<span class="staatliches text-2xl">Standard</span>
|
||||
{:else if option === FeedType.Relay}
|
||||
<Icon icon="server" class="w-12 h-12" color={active ? "accent" : "tinted-800"} />
|
||||
<span class="text-2xl staatliches">Relays</span>
|
||||
<Icon icon="server" class="h-12 w-12" color={active ? "accent" : "tinted-800"} />
|
||||
<span class="staatliches text-2xl">Relays</span>
|
||||
{:else if option === FeedType.DVM}
|
||||
<Icon icon="network" class="w-12 h-12" color={active ? "accent" : "tinted-800"} />
|
||||
<span class="text-2xl staatliches">DVMs</span>
|
||||
<Icon icon="network" class="h-12 w-12" color={active ? "accent" : "tinted-800"} />
|
||||
<span class="staatliches text-2xl">DVMs</span>
|
||||
{:else}
|
||||
<span class="w-12 h-12 flex items-center justify-center">
|
||||
<span class="flex h-12 w-12 items-center justify-center">
|
||||
<i class="fa fa-2xl fa-gears" />
|
||||
</span>
|
||||
<span class="text-2xl staatliches">Advanced</span>
|
||||
<span class="staatliches text-2xl">Advanced</span>
|
||||
{/if}
|
||||
</div>
|
||||
</SelectTiles>
|
||||
</Field>
|
||||
</Card>
|
||||
{#if feedType === FeedType.Relay}
|
||||
<Field label="Relay Selections">
|
||||
<FeedFormRelay feed={current} {controller} />
|
||||
<Field label="Which relays would you like to use?">
|
||||
<SearchSelect
|
||||
multiple
|
||||
value={current[1] || []}
|
||||
search={$searchRelayUrls}
|
||||
onChange={urls => setAtCursor(urls, [1])}>
|
||||
onChange={urls => controller.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>
|
||||
</Field>
|
||||
{:else if feedType === FeedType.Filter}
|
||||
<FeedFormForRelayFeed feed={current} {controller} />
|
||||
{#each current.slice(1) as filter, filterIdx ([current.length, filterIdx].join(":"))}
|
||||
{@const feedIdx = inc(filterIdx)}
|
||||
<Card>
|
||||
<FilterField
|
||||
{filter}
|
||||
onChange={filter => setAtCursor(filter, [feedIdx])}
|
||||
onRemove={() => updateAtCursor(feed => feed.toSpliced(feedIdx, 1))} />
|
||||
onChange={filter => controller.setAtCursor(filter, [feedIdx])}
|
||||
onRemove={() => controller.updateAtCursor(feed => feed.toSpliced(feedIdx, 1))} />
|
||||
</Card>
|
||||
{#if feedIdx < current.length - 1}
|
||||
<p class="staatliches text-center">— OR —</p>
|
||||
{/if}
|
||||
{/each}
|
||||
<div class="flex">
|
||||
<Anchor button on:click={() => setAtCursor([...current, {}])}>
|
||||
<Anchor button on:click={() => controller.setAtCursor([...current, {}])}>
|
||||
<i class="fa fa-plus" /> Add filter
|
||||
</Anchor>
|
||||
</div>
|
||||
@ -141,7 +141,7 @@
|
||||
multiple
|
||||
value={current.slice(1)}
|
||||
search={$searchListAddrs}
|
||||
onChange={addrs => setAtCursor([FeedType.List, ...addrs])}>
|
||||
onChange={addrs => controller.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>
|
||||
@ -152,15 +152,17 @@
|
||||
<Card>
|
||||
<DVMField
|
||||
dvmItem={item}
|
||||
onChange={item => setAtCursor(item, [feedIdx])}
|
||||
onRemove={() => updateAtCursor(feed => feed.toSpliced(feedIdx, 1))} />
|
||||
onChange={item => controller.setAtCursor(item, [feedIdx])}
|
||||
onRemove={() => controller.updateAtCursor(feed => feed.toSpliced(feedIdx, 1))} />
|
||||
</Card>
|
||||
{#if feedIdx < current.length - 1}
|
||||
<p class="staatliches text-center">— OR —</p>
|
||||
{/if}
|
||||
{/each}
|
||||
<div class="flex">
|
||||
<Anchor button on:click={() => setAtCursor([...current, {kind: 5300, tags: [], relays: []}])}>
|
||||
<Anchor
|
||||
button
|
||||
on:click={() => controller.setAtCursor([...current, {kind: 5300, tags: [], relays: []}])}>
|
||||
<i class="fa fa-plus" /> Add DVM
|
||||
</Anchor>
|
||||
</div>
|
||||
@ -168,12 +170,14 @@
|
||||
{#each subFeeds as subFeed, i (displayFeed(subFeed) + i)}
|
||||
<Card class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-3">
|
||||
<Anchor on:click={() => removeFeed(current.indexOf(subFeed))}>
|
||||
<Anchor on:click={() => controller.removeFeed(current.indexOf(subFeed))}>
|
||||
<i class="fa fa-trash fa-sm" />
|
||||
</Anchor>
|
||||
<span class="text-lg">{displayFeed(subFeed)}</span>
|
||||
</div>
|
||||
<Anchor class="flex items-center gap-2" on:click={() => pushCursor(current.indexOf(subFeed))}>
|
||||
<Anchor
|
||||
class="flex items-center gap-2"
|
||||
on:click={() => controller.pushCursor(current.indexOf(subFeed))}>
|
||||
<i class="fa fa-edit" /> Edit
|
||||
</Anchor>
|
||||
</Card>
|
||||
@ -199,9 +203,9 @@
|
||||
</div>
|
||||
<div slot="tooltip">
|
||||
<Menu>
|
||||
<MenuItem on:click={() => addFeed(FeedType.Filter)}>Standard Feed</MenuItem>
|
||||
<MenuItem on:click={() => addFeed(FeedType.List)}>List Feed</MenuItem>
|
||||
<MenuItem on:click={() => addFeed(FeedType.DVM)}>DVM Feed</MenuItem>
|
||||
<MenuItem on:click={() => controller.addFeed(FeedType.Filter)}>Standard Feed</MenuItem>
|
||||
<MenuItem on:click={() => controller.addFeed(FeedType.List)}>List Feed</MenuItem>
|
||||
<MenuItem on:click={() => controller.addFeed(FeedType.DVM)}>DVM Feed</MenuItem>
|
||||
</Menu>
|
||||
</div>
|
||||
</Popover>
|
||||
@ -212,7 +216,7 @@
|
||||
<Anchor button on:click={onCancel}>Cancel</Anchor>
|
||||
<Anchor button accent on:click={() => onChange(feed)}>Save</Anchor>
|
||||
{:else}
|
||||
<Anchor button on:click={popCursor}>Done</Anchor>
|
||||
<Anchor button on:click={controller.popCursor}>Done</Anchor>
|
||||
{/if}
|
||||
</div>
|
||||
</FlexColumn>
|
||||
|
20
src/app/shared/FeedFormRelay.svelte
Normal file
20
src/app/shared/FeedFormRelay.svelte
Normal file
@ -0,0 +1,20 @@
|
||||
<script lang="ts">
|
||||
import {FeedType} from "@welshman/feeds"
|
||||
import Field from "src/partials/Field.svelte"
|
||||
import SearchSelect from "src/partials/SearchSelect.svelte"
|
||||
import {searchRelayUrls, displayRelayUrl} from "src/engine"
|
||||
|
||||
export let feed
|
||||
export let controller
|
||||
</script>
|
||||
|
||||
<Field label="Which relays would you like to use?">
|
||||
<SearchSelect
|
||||
multiple
|
||||
value={feed.slice(1)}
|
||||
search={$searchRelayUrls}
|
||||
onChange={urls => controller.setAtCursor([FeedType.Relay, ...urls])}>
|
||||
<span slot="item" let:item>{displayRelayUrl(item)}</span>
|
||||
</SearchSelect>
|
||||
<p slot="info">Select which relays you'd like to limit loading feeds from.</p>
|
||||
</Field>
|
@ -1,8 +1,8 @@
|
||||
<script lang="ts">
|
||||
import {filterFeed} from "@welshman/feeds"
|
||||
import {feedFromFilter} from "@welshman/feeds"
|
||||
import Calendar from "src/app/shared/Calendar.svelte"
|
||||
|
||||
export let address
|
||||
</script>
|
||||
|
||||
<Calendar group={address} feed={filterFeed({kinds: [31923], "#a": [address]})} />
|
||||
<Calendar group={address} feed={feedFromFilter({kinds: [31923], "#a": [address]})} />
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import {filterFeed} from "@welshman/feeds"
|
||||
import {feedFromFilter} from "@welshman/feeds"
|
||||
import Card from "src/partials/Card.svelte"
|
||||
import Anchor from "src/partials/Anchor.svelte"
|
||||
import Feed from "src/app/shared/Feed.svelte"
|
||||
@ -15,4 +15,4 @@
|
||||
<Anchor button accent on:click={createListing}>Create a listing</Anchor>
|
||||
</Card>
|
||||
|
||||
<Feed hideControls feed={filterFeed({kinds: [30402], "#a": [address]})} />
|
||||
<Feed hideControls feed={feedFromFilter({kinds: [30402], "#a": [address]})} />
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import {without, last} from "ramda"
|
||||
import {Tag, Tags, decodeAddress, isGroupAddress, getIdFilters} from "@welshman/util"
|
||||
import {filterFeed} from "@welshman/feeds"
|
||||
import {feedFromFilter} from "@welshman/feeds"
|
||||
import {noteKinds, generatePrivateKey} from "src/util/nostr"
|
||||
import {fly} from "src/util/transition"
|
||||
import FlexColumn from "src/partials/FlexColumn.svelte"
|
||||
@ -100,7 +100,7 @@
|
||||
shouldListen
|
||||
hideControls
|
||||
skipNetwork={isGroupAddress(decodeAddress(address))}
|
||||
feed={filterFeed({kinds: without([30402], noteKinds), "#a": [address]})} />
|
||||
feed={feedFromFilter({kinds: without([30402], noteKinds), "#a": [address]})} />
|
||||
{:else}
|
||||
{#each feedEvents as event}
|
||||
<div in:fly={{y: 20}}>
|
||||
|
@ -218,7 +218,7 @@
|
||||
"pointer-events-none opacity-50": disableActions,
|
||||
})}
|
||||
on:click={replyCtrl?.start}>
|
||||
<Icon icon="message" accent={reply ? 'accent' : 'neutral-100'} />
|
||||
<Icon icon="message" color={reply ? 'accent' : 'neutral-100'} />
|
||||
{#if $repliesCount > 0}
|
||||
<span transition:fly|local={{y: 5, duration: 100}} class="-mt-px">{$repliesCount}</span>
|
||||
{/if}
|
||||
@ -229,7 +229,7 @@
|
||||
"pointer-events-none opacity-50": disableActions || !canZap,
|
||||
})}
|
||||
on:click={startZap}>
|
||||
<Icon icon="bolt" accent={zap ? 'accent' : 'neutral-100'} />
|
||||
<Icon icon="bolt" color={zap ? 'accent' : 'neutral-100'} />
|
||||
{#if $zapsTotal > 0}
|
||||
<span transition:fly|local={{y: 5, duration: 100}} class="-mt-px"
|
||||
>{formatSats($zapsTotal)}</span>
|
||||
@ -244,7 +244,7 @@
|
||||
on:click={() => (like ? deleteReaction(like) : react("+"))}>
|
||||
<Icon
|
||||
icon="heart"
|
||||
accent={Boolean(like)}
|
||||
color={like ? 'accent' : 'neutral-100'}
|
||||
class={cx("cursor-pointer", {
|
||||
"fa-beat fa-beat-custom": like,
|
||||
})} />
|
||||
|
@ -56,6 +56,7 @@ export class FeedLoader {
|
||||
isDeleted = isDeleted.get()
|
||||
|
||||
constructor(readonly opts: FeedOpts) {
|
||||
// @ts-ignore
|
||||
window.feed = this
|
||||
|
||||
// Use a custom feed loader so we can intercept the filters
|
||||
@ -63,7 +64,7 @@ export class FeedLoader {
|
||||
...baseFeedLoader.options,
|
||||
request: async ({relays, filters, onEvent}) => {
|
||||
// Default to note kinds
|
||||
filters = filters.map(filter => ({kinds: noteKinds, ...filter}))
|
||||
filters = filters?.map(filter => ({kinds: noteKinds, ...filter})) || []
|
||||
|
||||
// Add reposts if we don't have any authors specified
|
||||
if (this.opts.includeReposts && !filters.some(f => f.authors?.length > 0)) {
|
||||
@ -74,7 +75,7 @@ export class FeedLoader {
|
||||
const tracker = new Tracker()
|
||||
|
||||
// Use relays specified in feeds
|
||||
if (relays.length > 0) {
|
||||
if (relays?.length > 0) {
|
||||
promises.push(load({filters, relays, tracker, onEvent}))
|
||||
} else {
|
||||
if (!this.opts.skipCache) {
|
||||
@ -132,12 +133,12 @@ export class FeedLoader {
|
||||
// Event selection, deferral, and parent loading
|
||||
|
||||
discardEvents = async events => {
|
||||
let strict = false
|
||||
let strict = true
|
||||
|
||||
// Be more tolerant when looking at communities
|
||||
this.feedLoader.compiler.walk(this.opts.feed, ([type, ...feed]) => {
|
||||
if (type === FeedType.Filter) {
|
||||
strict = feed.some(f => f["#a"]?.find(a => isContextAddress(decodeAddress(a))))
|
||||
this.feedLoader.compiler.walk(this.opts.feed, ([type, key, ...feed]) => {
|
||||
if (type === FeedType.Tag && key === "#a") {
|
||||
strict = strict && !feed.some(a => isContextAddress(decodeAddress(a)))
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
<script lang="ts">
|
||||
import {Scope, filterFeed} from "@welshman/feeds"
|
||||
import {Scope, feedFromFilter, intersectionFeed, kindFeed, scopeFeed} from "@welshman/feeds"
|
||||
import Calendar from "src/app/shared/Calendar.svelte"
|
||||
import {env, loadGroupMessages} from "src/engine"
|
||||
|
||||
const feed = $env.FORCE_GROUP
|
||||
? filterFeed({kinds: [31923], "#a": [$env.FORCE_GROUP]})
|
||||
: filterFeed({kinds: [31923], scopes: [Scope.Self, Scope.Follows]})
|
||||
? feedFromFilter({kinds: [31923], "#a": [$env.FORCE_GROUP]})
|
||||
: intersectionFeed(kindFeed(31923), scopeFeed(Scope.Self, Scope.Follows))
|
||||
|
||||
if ($env.FORCE_GROUP) {
|
||||
loadGroupMessages([$env.FORCE_GROUP])
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import {onMount} from "svelte"
|
||||
import {getIdOrAddress, decodeAddress} from "@welshman/util"
|
||||
import {filterFeed} from "@welshman/feeds"
|
||||
import {feedFromFilter} from "@welshman/feeds"
|
||||
import {fly} from "src/util/transition"
|
||||
import FlexColumn from "src/partials/FlexColumn.svelte"
|
||||
import Spinner from "src/partials/Spinner.svelte"
|
||||
@ -38,7 +38,7 @@
|
||||
hideControls
|
||||
shouldListen
|
||||
anchor={getIdOrAddress(event)}
|
||||
feed={filterFeed({"#a": [address]})} />
|
||||
feed={feedFromFilter({"#a": [address]})} />
|
||||
</FlexColumn>
|
||||
</div>
|
||||
{:else}
|
||||
|
@ -1,7 +1,8 @@
|
||||
<script lang="ts">
|
||||
import cx from "classnames"
|
||||
import {Tags} from "@welshman/util"
|
||||
import {Scope, filterFeed, relayFeed} from "@welshman/feeds"
|
||||
import {Scope, authorFeed, tagFeed, scopeFeed, relayFeed, intersectionFeed} from "@welshman/feeds"
|
||||
import type {Feed as TFeed} from "@welshman/feeds"
|
||||
import {theme} from "src/partials/state"
|
||||
import Anchor from "src/partials/Anchor.svelte"
|
||||
import Popover from "src/partials/Popover.svelte"
|
||||
@ -10,10 +11,10 @@
|
||||
import {session, canSign, lists, userLists} from "src/engine"
|
||||
|
||||
export let relays = []
|
||||
export let feed = filterFeed({scopes: [Scope.Follows]})
|
||||
export let feed: TFeed = scopeFeed(Scope.Follows)
|
||||
|
||||
if (relays.length > 0) {
|
||||
feed = relayFeed(relays, feed)
|
||||
feed = intersectionFeed(relayFeed(...relays), feed)
|
||||
}
|
||||
|
||||
let key = Math.random()
|
||||
@ -30,15 +31,15 @@
|
||||
const urls = tags.values("r").valueOf()
|
||||
|
||||
if (authors.length > 0) {
|
||||
feed = filterFeed({authors})
|
||||
feed = authorFeed(...authors)
|
||||
} else if (topics.length > 0) {
|
||||
feed = filterFeed({"#t": topics})
|
||||
feed = tagFeed("#t", ...topics)
|
||||
} else {
|
||||
feed = filterFeed({scopes: [Scope.Follows]})
|
||||
feed = scopeFeed(Scope.Follows)
|
||||
}
|
||||
|
||||
if (urls.length > 0) {
|
||||
feed = relayFeed(urls, feed)
|
||||
feed = intersectionFeed(relayFeed(...urls), feed)
|
||||
}
|
||||
|
||||
key = Math.random()
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import {Scope, filterFeed} from "@welshman/feeds"
|
||||
import {Scope, feedFromFilter, intersectionFeed, kindFeed, scopeFeed} from "@welshman/feeds"
|
||||
import Card from "src/partials/Card.svelte"
|
||||
import Anchor from "src/partials/Anchor.svelte"
|
||||
import Feed from "src/app/shared/Feed.svelte"
|
||||
@ -7,8 +7,8 @@
|
||||
import {env, canSign, loadGroupMessages} from "src/engine"
|
||||
|
||||
const feed = $env.FORCE_GROUP
|
||||
? filterFeed({kinds: [30402], "#a": [$env.FORCE_GROUP]})
|
||||
: filterFeed({kinds: [30402], scopes: [Scope.Self, Scope.Follows]})
|
||||
? feedFromFilter({kinds: [30402], "#a": [$env.FORCE_GROUP]})
|
||||
: intersectionFeed(kindFeed(30402), scopeFeed(Scope.Self, Scope.Follows))
|
||||
|
||||
const createListing = () => router.at("notes/create").qp({type: "listing"}).open()
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import {identity} from "ramda"
|
||||
import {stripProtocol} from "@welshman/lib"
|
||||
import {filterFeed} from "@welshman/feeds"
|
||||
import {feedFromFilter} from "@welshman/feeds"
|
||||
import {info} from "src/util/logger"
|
||||
import {ensureProto} from "src/util/misc"
|
||||
import {themeBackgroundGradient} from "src/partials/state"
|
||||
@ -30,7 +30,7 @@
|
||||
export let npub
|
||||
export let pubkey
|
||||
export let relays = []
|
||||
export let feed = filterFeed({authors: [pubkey]})
|
||||
export let feed = feedFromFilter({authors: [pubkey]})
|
||||
|
||||
const tabs = ["notes", "likes", "collections", "relays"].filter(identity)
|
||||
const person = derivePerson(pubkey)
|
||||
@ -98,7 +98,7 @@
|
||||
{:else if activeTab === "notes"}
|
||||
<Feed showGroup skipPlatform {feed} />
|
||||
{:else if activeTab === "likes"}
|
||||
<Feed showGroup hideControls feed={filterFeed({kinds: [7], authors: [pubkey]})} />
|
||||
<Feed showGroup hideControls feed={feedFromFilter({kinds: [7], authors: [pubkey]})} />
|
||||
{:else if activeTab === "collections"}
|
||||
<PersonCollections {pubkey} />
|
||||
{:else if activeTab === "relays"}
|
||||
|
@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import {batch} from "hurdak"
|
||||
import {filterFeed, relayFeed} from "@welshman/feeds"
|
||||
import {wotFeed, relayFeed, intersectionFeed, feedFromFilter} from "@welshman/feeds"
|
||||
import type {Feed as TFeed} from "@welshman/feeds"
|
||||
import {getAvgRating} from "src/util/nostr"
|
||||
import Feed from "src/app/shared/Feed.svelte"
|
||||
import Tabs from "src/partials/Tabs.svelte"
|
||||
@ -10,13 +11,13 @@
|
||||
import {deriveRelay, normalizeRelayUrl, displayRelay, getMinWot} from "src/engine"
|
||||
|
||||
export let url
|
||||
export let feed = filterFeed({min_wot: getMinWot()})
|
||||
export let feed: TFeed = wotFeed({min: getMinWot()})
|
||||
|
||||
let reviews = []
|
||||
let activeTab = "notes"
|
||||
|
||||
$: url = normalizeRelayUrl(url)
|
||||
$: feed = relayFeed([url], feed)
|
||||
$: feed = intersectionFeed(relayFeed(url), feed)
|
||||
$: rating = getAvgRating(reviews)
|
||||
|
||||
const relay = deriveRelay(url)
|
||||
@ -48,7 +49,7 @@
|
||||
{#if activeTab === "reviews"}
|
||||
<Feed
|
||||
onEvent={onReview}
|
||||
feed={filterFeed({
|
||||
feed={feedFromFilter({
|
||||
kinds: [1986],
|
||||
"#l": ["review/relay"],
|
||||
"#r": [$relay.url],
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import {filterFeed} from "@welshman/feeds"
|
||||
import {tagFeed} from "@welshman/feeds"
|
||||
import Feed from "src/app/shared/Feed.svelte"
|
||||
import Heading from "src/partials/Heading.svelte"
|
||||
import TopicActions from "src/app/shared/TopicActions.svelte"
|
||||
@ -13,4 +13,4 @@
|
||||
<TopicActions {topic} />
|
||||
</div>
|
||||
</div>
|
||||
<Feed feed={filterFeed({"#t": [topic]})} />
|
||||
<Feed feed={tagFeed("#t", topic)} />
|
||||
|
@ -1,7 +1,7 @@
|
||||
import {assocPath, uniq} from "ramda"
|
||||
import {seconds} from "hurdak"
|
||||
import {now} from "@welshman/lib"
|
||||
import {relayFeed, filterFeed} from "@welshman/feeds"
|
||||
import {relayFeed, feedFromFilter, unionFeed, intersectionFeed} from "@welshman/feeds"
|
||||
import {sessions} from "src/engine/session/state"
|
||||
import {session} from "src/engine/session/derived"
|
||||
import {loadPubkeys, subscribe} from "src/engine/network/utils"
|
||||
@ -21,9 +21,12 @@ export const loadAllMessages = ({reload = false} = {}) => {
|
||||
})
|
||||
|
||||
const loader = loadAll(
|
||||
relayFeed(
|
||||
hints.User().getUrls(),
|
||||
filterFeed({kinds: [4], authors: [pubkey], since}, {kinds: [4, 1059], "#p": [pubkey], since}),
|
||||
intersectionFeed(
|
||||
relayFeed(...hints.User().getUrls()),
|
||||
unionFeed(
|
||||
feedFromFilter({kinds: [4], authors: [pubkey], since}),
|
||||
feedFromFilter({kinds: [4, 1059], "#p": [pubkey], since}),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
|
@ -2,7 +2,14 @@ import {seconds, switcherFn} from "hurdak"
|
||||
import {Worker, writable} from "@welshman/lib"
|
||||
import type {Event, Rumor} from "@welshman/util"
|
||||
import type {LoadOpts} from "@welshman/feeds"
|
||||
import {FeedLoader, Scope, relayFeed, filterFeed} from "@welshman/feeds"
|
||||
import {
|
||||
FeedLoader,
|
||||
Scope,
|
||||
relayFeed,
|
||||
intersectionFeed,
|
||||
unionFeed,
|
||||
feedFromFilter,
|
||||
} from "@welshman/feeds"
|
||||
import {giftWrapKinds, generatePrivateKey} from "src/util/nostr"
|
||||
import {env} from "src/engine/session/state"
|
||||
import {user, session, nip44, nip04} from "src/engine/session/derived"
|
||||
@ -136,7 +143,9 @@ export const sync = (fromUrl, toUrl, filters) => {
|
||||
|
||||
worker.addGlobalHandler(event => publish({event, relays: [toUrl]}))
|
||||
|
||||
return loadAll(relayFeed([fromUrl], filterFeed(...filters)), {
|
||||
const feed = intersectionFeed(relayFeed(fromUrl), unionFeed(...filters.map(feedFromFilter)))
|
||||
|
||||
return loadAll(feed, {
|
||||
onEvent: e => worker.push(e as Event),
|
||||
})
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
<script lang="ts">
|
||||
import cx from "classnames"
|
||||
import {without} from 'ramda'
|
||||
import {without} from "ramda"
|
||||
|
||||
export let options
|
||||
export let value
|
||||
export let value = null
|
||||
export let options = []
|
||||
export let onChange = null
|
||||
export let disabled = false
|
||||
export let multiple = false
|
||||
@ -26,7 +26,11 @@
|
||||
class:cursor-pointer={!disabled}>
|
||||
{#each options as option, i}
|
||||
<div on:click={() => onClick(option)}>
|
||||
<slot name="item" {i} {option} active={multiple ? value.includes(option) : value === option} />
|
||||
<slot
|
||||
name="item"
|
||||
{i}
|
||||
{option}
|
||||
active={multiple ? value.includes(option) : value === option} />
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
@ -325,7 +325,7 @@ export const pickVals = <T>(ks: string[], x: Record<string, T>) => ks.map(k => x
|
||||
export const getStringWidth = (text: string) => {
|
||||
const span = document.createElement("span")
|
||||
|
||||
span.style = "height: 0px"
|
||||
span.setAttribute("style", "height: 0px")
|
||||
span.textContent = text
|
||||
|
||||
document.body.appendChild(span)
|
||||
|
Loading…
Reference in New Issue
Block a user