diff --git a/src/app/views/FeedList.svelte b/src/app/views/FeedList.svelte
index 531957eb..f2bc8993 100644
--- a/src/app/views/FeedList.svelte
+++ b/src/app/views/FeedList.svelte
@@ -1,8 +1,10 @@
@@ -96,7 +121,7 @@
{#each $feedSearch
.searchValues(q)
- .filter(address => !feeds.find(feed => getAddress(feed.event) === address))
+ .filter(address => !initialAddrs.has(address))
.slice(0, limit) as address (address)}
{/each}
diff --git a/src/domain/feed.ts b/src/domain/feed.ts
index fdde5e95..e5ed2e6b 100644
--- a/src/domain/feed.ts
+++ b/src/domain/feed.ts
@@ -1,5 +1,5 @@
import {fromPairs, randomId} from "@welshman/lib"
-import {FEED, Tags, getAddress} from "@welshman/util"
+import {FEED, Tags} from "@welshman/util"
import type {TrustedEvent} from "@welshman/util"
import {
feedFromTags,
@@ -10,7 +10,6 @@ import {
isScopeFeed,
} from "@welshman/feeds"
import type {Feed as IFeed} from "@welshman/feeds"
-import {SearchHelper} from "src/util/misc"
import {tryJson} from "src/util/misc"
import type {PublishedList} from "./list"
@@ -81,12 +80,6 @@ export const editFeed = (feed: PublishedFeed) => ({
export const displayFeed = (feed?: Feed) => feed?.title || "[no name]"
-export class FeedSearch extends SearchHelper
{
- config = {keys: ["title", "description"]}
- getValue = (option: PublishedFeed) => getAddress(option.event)
- displayValue = (address: string) => displayFeed(this.getOption(address))
-}
-
export const isTopicFeed = f => isTagFeed(f) && f[1] === "#t"
export const isMentionFeed = f => isTagFeed(f) && f[1] === "#p"
diff --git a/src/engine/requests/pubkeys.ts b/src/engine/requests/pubkeys.ts
index 235c76c4..600d8266 100644
--- a/src/engine/requests/pubkeys.ts
+++ b/src/engine/requests/pubkeys.ts
@@ -50,7 +50,7 @@ const getFiltersForKey = (key: string, authors: string[]) => {
case "pubkey/lists":
return [{authors, kinds: LIST_KINDS}]
case "pubkey/feeds":
- return [{authors, kinds: [NAMED_BOOKMARKS, FEED]}]
+ return [{authors, kinds: [NAMED_BOOKMARKS, FEED, FEEDS]}]
case "pubkey/relays":
return [{authors, kinds: [RELAYS, INBOX_RELAYS]}]
case "pubkey/profile":
diff --git a/src/engine/state.ts b/src/engine/state.ts
index bef8e546..c997d823 100644
--- a/src/engine/state.ts
+++ b/src/engine/state.ts
@@ -116,11 +116,11 @@ import type {
} from "src/domain"
import {
RelayMode,
+ displayFeed,
EDITABLE_LIST_KINDS,
getSingletonValues,
makeSingleton,
ListSearch,
- FeedSearch,
profileHasName,
readFeed,
readList,
@@ -1350,6 +1350,20 @@ export const feedFavorites = deriveEventsMapped({
),
})
+export const feedFavoritesByAddress = withGetter(
+ derived(feedFavorites, $feedFavorites => {
+ const $feedFavoritesByAddress = new Map()
+
+ for (const singleton of $feedFavorites) {
+ for (const address of getSingletonValues("a", singleton)) {
+ pushToMapKey($feedFavoritesByAddress, address, singleton)
+ }
+ }
+
+ return $feedFavoritesByAddress
+ }),
+)
+
export const userFeedFavorites = derived(
[feedFavorites, pubkey],
([$singletons, $pubkey]: [PublishedSingleton[], string]) =>
@@ -1363,6 +1377,35 @@ export const userFavoritedFeeds = derived(userFeedFavorites, $singleton =>
.map(readFeed),
)
+export class FeedSearch extends SearchHelper {
+ getSearch = () => {
+ const $feedFavoritesByAddress = feedFavoritesByAddress.get()
+ const getScore = feed => $feedFavoritesByAddress.get(getAddress(feed.event))?.length || 0
+ const options = this.options.map(feed => ({feed, score: getScore(feed)}))
+ const fuse = new Fuse(options, {
+ keys: ["feed.title", "feed.description"],
+ shouldSort: false,
+ includeScore: true,
+ })
+
+ return (term: string) => {
+ if (!term) {
+ return sortBy(item => -item.score, options).map(item => item.feed)
+ }
+
+ return doPipe(fuse.search(term), [
+ results =>
+ sortBy((r: any) => r.score - Math.pow(Math.max(0, r.item.score), 1 / 100), results),
+ results => results.map((r: any) => r.item.feed),
+ ])
+ }
+ }
+
+ getValue = (option: PublishedFeed) => getAddress(option.event)
+
+ displayValue = (address: string) => displayFeed(this.getOption(address))
+}
+
export const feedSearch = derived(feeds, $feeds => new FeedSearch($feeds))
export const listFeeds = deriveEventsMapped({