From 051b406f2bc5cdefcc21b2c1bd810c9104926ca4 Mon Sep 17 00:00:00 2001 From: Jon Staab Date: Wed, 17 Apr 2024 08:49:51 -0700 Subject: [PATCH] Work on recursive feed editor --- .editorconfig | 3 + src/app/shared/FeedControls.svelte | 32 ++++-- src/app/shared/FeedForm.svelte | 97 +++++++++++++----- src/app/shared/FilterAuthorsField.svelte | 44 ++++++++ src/app/shared/FilterField.svelte | 114 +++++++++++++++++++++ src/app/shared/FilterKindsField.svelte | 51 +++++++++ src/app/shared/FilterMentionsField.svelte | 30 ++++++ src/app/shared/FilterSearchField.svelte | 20 ++++ src/app/shared/FilterTimeframeField.svelte | 28 +++++ src/app/shared/FilterTopicsField.svelte | 20 ++++ src/app/util/feeds.ts | 7 +- src/app/views/EventDetail.svelte | 3 +- src/app/views/Feeds.svelte | 9 +- src/app/views/PersonDetail.svelte | 3 +- src/app/views/RelayDetail.svelte | 4 +- src/app/views/TopicFeed.svelte | 2 +- src/engine/people/derived.ts | 4 +- src/partials/Select.svelte | 10 +- src/partials/SelectButton.svelte | 11 +- src/util/nostr.ts | 2 +- 20 files changed, 440 insertions(+), 54 deletions(-) create mode 100644 .editorconfig create mode 100644 src/app/shared/FilterAuthorsField.svelte create mode 100644 src/app/shared/FilterField.svelte create mode 100644 src/app/shared/FilterKindsField.svelte create mode 100644 src/app/shared/FilterMentionsField.svelte create mode 100644 src/app/shared/FilterSearchField.svelte create mode 100644 src/app/shared/FilterTimeframeField.svelte create mode 100644 src/app/shared/FilterTopicsField.svelte diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..76a93c06 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,3 @@ +[*] +indent_style = space +indent_size = 2 diff --git a/src/app/shared/FeedControls.svelte b/src/app/shared/FeedControls.svelte index eae4553b..2bcd8b4e 100644 --- a/src/app/shared/FeedControls.svelte +++ b/src/app/shared/FeedControls.svelte @@ -18,7 +18,13 @@ export let value - const isOpen = writable(false) + const openModal = () => { + isOpen = true + } + + const closeModal = () => { + isOpen = false + } const toggleReplies = () => { value = {...value, shouldHideReplies: !value.shouldHideReplies} @@ -32,15 +38,27 @@ feed = [feed[0], omit(keys, feed[1])] as Feed } + const setFeed = f => { + feed = f + } + const saveFeed = () => { value = {...value, feed} } + const setAndSaveFeed = f => { + setFeed(f) + saveFeed() + closeModal() + } + const displayPeople = pubkeys => pubkeys.length === 1 ? displayPubkey(pubkeys[0]) : `${pubkeys.length} people` const displayTopics = topics => (topics.length === 1 ? topics[0] : `${topics.length} topics`) + let isOpen = false + $: feed = value.feed $: feedType = feed[0] $: subFeeds = getSubFeeds(feed) @@ -54,7 +72,7 @@ Show replies - isOpen.set(true)} /> +
Showing notes:
@@ -116,7 +134,7 @@ setPart({scopes: [Scope.Global]})}> Global - isOpen.set(true)}> + Custom @@ -157,16 +175,16 @@ {/if}
isOpen.set(true)}> + on:click={openModal}>
-{#if $isOpen} - isOpen.set(false)}> +{#if isOpen} + Customize Feed - + {/if} diff --git a/src/app/shared/FeedForm.svelte b/src/app/shared/FeedForm.svelte index 0a725c5c..978da8e2 100644 --- a/src/app/shared/FeedForm.svelte +++ b/src/app/shared/FeedForm.svelte @@ -1,34 +1,63 @@ - + - + @@ -39,37 +68,59 @@

- Select which feed type you'd like to use. In addition to some basic feed types, - nostr also supports combinations of sub-feeds using set operators for advanced - use cases. -

- + Select which feed type you'd like to use. In addition to some basic feed types, nostr also + supports combinations of sub-feeds using set operators for advanced use cases. +

+

{#if feedType === FeedType.Relay} + onChange={onRelayChange}> {displayRelayUrl(item)} -

- Select which relays you'd like to limit loading feeds from. -

- +

Select which relays you'd like to limit loading feeds from.

+

{:else if feedType === FeedType.Filter} - {#each feed.slice(1) as filter} - + {#each feed.slice(1) as filter, i} + + onFilterChange(filter, inc(i))} /> + {/each} {:else if feedType === FeedType.List} {:else if feedType === FeedType.LOL} {:else if feedType === FeedType.DVM} {/if} {#each subFeeds as subFeed, i} - + + {displayFeed(subFeed)} + setCursor(subFeed)}> + Edit + {#if i < subFeeds.length - 1} -

OR

+

— OR —

{/if} {/each} +
+ {#if hasSubFeeds(feed)} + + + Add feed + +
+ + addFeed(FeedType.Filter)}>Standard Feed + addFeed(FeedType.List)}>List Feed + addFeed(FeedType.LOL)}>Lists of Lists + addFeed(FeedType.DVM)}>DVM Feed + +
+
+ {/if} + onCancel()}>Cancel + onChange(feed)}>Save +
diff --git a/src/app/shared/FilterAuthorsField.svelte b/src/app/shared/FilterAuthorsField.svelte new file mode 100644 index 00000000..d980f03f --- /dev/null +++ b/src/app/shared/FilterAuthorsField.svelte @@ -0,0 +1,44 @@ + + + + + Authors + + + {#if !filter.scopes} + +
+ {#if context === "value"} + {displayPubkey(item)} + {:else} + + {/if} +
+
+ {/if} +
diff --git a/src/app/shared/FilterField.svelte b/src/app/shared/FilterField.svelte new file mode 100644 index 00000000..18b65c3c --- /dev/null +++ b/src/app/shared/FilterField.svelte @@ -0,0 +1,114 @@ + + + + {#each sections as section} +
+ {#if section === "kinds"} + removeSection("kinds")} /> + {:else if section === "search"} + removeSection("search")} /> + {:else if section === "topics"} + removeSection("topics")} /> + {:else if section === "authors"} + removeSection("authors")} /> + {:else if section === "mentions"} + removeSection("mentions")} /> + {:else if section === "topics"} + removeSection("topics")} /> + {:else if section === "timeframe"} + removeSection("timeframe")} /> + {/if} +
+ {/each} +
+ + + Add filter + +
+ + {#if !sections.includes("topics")} + addSection("topics")}>Topics + {/if} + {#if !sections.includes("authors")} + addSection("authors")}>Authors + {/if} + {#if !sections.includes("mentions")} + addSection("mentions")}>Mentions + {/if} + {#if !sections.includes("timeframe")} + addSection("timeframe")}>Timeframe + {/if} + {#if !sections.includes("search")} + addSection("search")}>Search + {/if} + {#if !sections.includes("kinds")} + addSection("kinds")}>Kinds + {/if} + +
+
+
+
diff --git a/src/app/shared/FilterKindsField.svelte b/src/app/shared/FilterKindsField.svelte new file mode 100644 index 00000000..595e45eb --- /dev/null +++ b/src/app/shared/FilterKindsField.svelte @@ -0,0 +1,51 @@ + + + + + Kinds + + +
{kinds.find(k => k.kind === item)?.label} (kind {item})
+
+
diff --git a/src/app/shared/FilterMentionsField.svelte b/src/app/shared/FilterMentionsField.svelte new file mode 100644 index 00000000..e680fac5 --- /dev/null +++ b/src/app/shared/FilterMentionsField.svelte @@ -0,0 +1,30 @@ + + + + + Mentions + + +
+ {#if context === "value"} + {displayPubkey(item)} + {:else} + + {/if} +
+
+
diff --git a/src/app/shared/FilterSearchField.svelte b/src/app/shared/FilterSearchField.svelte new file mode 100644 index 00000000..eb031c67 --- /dev/null +++ b/src/app/shared/FilterSearchField.svelte @@ -0,0 +1,20 @@ + + + + + Search + + + + + diff --git a/src/app/shared/FilterTimeframeField.svelte b/src/app/shared/FilterTimeframeField.svelte new file mode 100644 index 00000000..32809910 --- /dev/null +++ b/src/app/shared/FilterTimeframeField.svelte @@ -0,0 +1,28 @@ + + +
+ + + Since + + + + + + +
diff --git a/src/app/shared/FilterTopicsField.svelte b/src/app/shared/FilterTopicsField.svelte new file mode 100644 index 00000000..ff6ce256 --- /dev/null +++ b/src/app/shared/FilterTopicsField.svelte @@ -0,0 +1,20 @@ + + + + + Topics + + + diff --git a/src/app/util/feeds.ts b/src/app/util/feeds.ts index 9a7d8747..abf1770a 100644 --- a/src/app/util/feeds.ts +++ b/src/app/util/feeds.ts @@ -12,7 +12,7 @@ import { } from "@coracle.social/util" import type {Feed, Loader} from "@coracle.social/feeds" import {FeedLoader as CoreFeedLoader, FeedType} from "@coracle.social/feeds" -import {LOCAL_RELAY_URL, reactionKinds, repostKinds} from "src/util/nostr" +import {LOCAL_RELAY_URL, noteKinds, reactionKinds, repostKinds} from "src/util/nostr" import type {DisplayEvent, Event} from "src/engine" import { feedLoader as baseFeedLoader, @@ -67,12 +67,17 @@ export class FeedLoader { this.feedLoader = new CoreFeedLoader({ ...baseFeedLoader.options, request: async ({relays, filters, onEvent}) => { + // Default to note kinds + 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)) { filters = addRepostFilters(filters) } const promises = [] + // Use relays specified in feeds if (relays.length > 0) { promises.push(load({filters, relays, onEvent})) } else { diff --git a/src/app/views/EventDetail.svelte b/src/app/views/EventDetail.svelte index 20ce9d69..8bb821f1 100644 --- a/src/app/views/EventDetail.svelte +++ b/src/app/views/EventDetail.svelte @@ -2,7 +2,6 @@ import {onMount} from "svelte" import {getIdOrAddress, decodeAddress} from "@coracle.social/util" import {filterFeed} from "@coracle.social/feeds" - import {noteKinds} from "src/util/nostr" import {fly} from "src/util/transition" import FlexColumn from "src/partials/FlexColumn.svelte" import Spinner from "src/partials/Spinner.svelte" @@ -39,7 +38,7 @@ hideControls shouldListen anchor={getIdOrAddress(event)} - feed={filterFeed({kinds: noteKinds, "#a": [address]})} /> + feed={filterFeed({"#a": [address]})} />
{:else} diff --git a/src/app/views/Feeds.svelte b/src/app/views/Feeds.svelte index a55e5171..38c58b17 100644 --- a/src/app/views/Feeds.svelte +++ b/src/app/views/Feeds.svelte @@ -2,7 +2,6 @@ import cx from "classnames" import {Tags} from "@coracle.social/util" import {Scope, filterFeed, relayFeed} from "@coracle.social/feeds" - import {noteKinds} from "src/util/nostr" import {theme} from "src/partials/state" import Anchor from "src/partials/Anchor.svelte" import Popover from "src/partials/Popover.svelte" @@ -11,7 +10,7 @@ import {session, canSign, lists, userLists} from "src/engine" export let relays = [] - export let feed = filterFeed({kinds: noteKinds, scopes: [Scope.Follows]}) + export let feed = filterFeed({scopes: [Scope.Follows]}) if (relays.length > 0) { feed = relayFeed(relays, feed) @@ -31,11 +30,11 @@ const urls = tags.values("r").valueOf() if (authors.length > 0) { - feed = filterFeed({kinds: noteKinds, authors}) + feed = filterFeed({authors}) } else if (topics.length > 0) { - feed = filterFeed({kinds: noteKinds, "#t": topics}) + feed = filterFeed({"#t": topics}) } else { - feed = filterFeed({kinds: noteKinds, scopes: [Scope.Follows]}) + feed = filterFeed({scopes: [Scope.Follows]}) } if (urls.length > 0) { diff --git a/src/app/views/PersonDetail.svelte b/src/app/views/PersonDetail.svelte index 41f7f2b2..10c8695e 100644 --- a/src/app/views/PersonDetail.svelte +++ b/src/app/views/PersonDetail.svelte @@ -4,7 +4,6 @@ import {filterFeed} from "@coracle.social/feeds" import {info} from "src/util/logger" import {ensureProto} from "src/util/misc" - import {noteKinds} from "src/util/nostr" import {themeBackgroundGradient} from "src/partials/state" import Tabs from "src/partials/Tabs.svelte" import Anchor from "src/partials/Anchor.svelte" @@ -31,7 +30,7 @@ export let npub export let pubkey export let relays = [] - export let feed = filterFeed({kinds: noteKinds, authors: [pubkey]}) + export let feed = filterFeed({authors: [pubkey]}) const tabs = ["notes", "likes", "collections", "relays"].filter(identity) const person = derivePerson(pubkey) diff --git a/src/app/views/RelayDetail.svelte b/src/app/views/RelayDetail.svelte index f5ce267a..9a66afae 100644 --- a/src/app/views/RelayDetail.svelte +++ b/src/app/views/RelayDetail.svelte @@ -1,7 +1,7 @@
- onChange(value)}>
diff --git a/src/partials/SelectButton.svelte b/src/partials/SelectButton.svelte index f11adf34..116c1615 100644 --- a/src/partials/SelectButton.svelte +++ b/src/partials/SelectButton.svelte @@ -1,10 +1,12 @@ @@ -19,10 +21,15 @@
0, - "bg-accent text-white": value === option, + "bg-accent text-white": multiple ? value.includes(option) : value === option, })} on:click={() => { - value = option + if (multiple) { + value = value.includes(option) ? without([option], value) : [...value, option] + } else { + value = option + } + onChange?.(value) }}> {displayOption(option)} diff --git a/src/util/nostr.ts b/src/util/nostr.ts index fc8234a3..89d04715 100644 --- a/src/util/nostr.ts +++ b/src/util/nostr.ts @@ -25,7 +25,7 @@ export const isKeyValid = (key: string) => { return true } -export const noteKinds = [1, 30023, 9802, 1808, 32123, 31923, 30402] +export const noteKinds = [1, 30023, 9802, 1808, 31337, 31923, 30402] export const reactionKinds = [7, 9735] export const repostKinds = [6, 16] export const giftWrapKinds = [1059, 1060]