diff --git a/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png b/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index c326c6d9..00000000 Binary files a/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png b/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png deleted file mode 100644 index bb739c6a..00000000 Binary files a/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png b/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index c326c6d9..00000000 Binary files a/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png b/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index cb07e1e6..00000000 Binary files a/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png b/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png deleted file mode 100644 index 78eb7ca6..00000000 Binary files a/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png b/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index cb07e1e6..00000000 Binary files a/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png b/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index f87ae8a6..00000000 Binary files a/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png b/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png deleted file mode 100644 index 4ee33824..00000000 Binary files a/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png b/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index f87ae8a6..00000000 Binary files a/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png b/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 0028ffcc..00000000 Binary files a/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png b/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png deleted file mode 100644 index ecf07a72..00000000 Binary files a/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png b/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 0028ffcc..00000000 Binary files a/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png b/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b5ae1b66..00000000 Binary files a/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png b/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png deleted file mode 100644 index c472850f..00000000 Binary files a/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png b/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index b5ae1b66..00000000 Binary files a/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/src-tauri/icons/ios/AppIcon-20x20@1x.png b/src-tauri/icons/ios/AppIcon-20x20@1x.png deleted file mode 100644 index 628f3d5f..00000000 Binary files a/src-tauri/icons/ios/AppIcon-20x20@1x.png and /dev/null differ diff --git a/src-tauri/icons/ios/AppIcon-20x20@2x-1.png b/src-tauri/icons/ios/AppIcon-20x20@2x-1.png deleted file mode 100644 index edf739c8..00000000 Binary files a/src-tauri/icons/ios/AppIcon-20x20@2x-1.png and /dev/null differ diff --git a/src-tauri/icons/ios/AppIcon-20x20@2x.png b/src-tauri/icons/ios/AppIcon-20x20@2x.png deleted file mode 100644 index edf739c8..00000000 Binary files a/src-tauri/icons/ios/AppIcon-20x20@2x.png and /dev/null differ diff --git a/src-tauri/icons/ios/AppIcon-20x20@3x.png b/src-tauri/icons/ios/AppIcon-20x20@3x.png deleted file mode 100644 index 8333a05e..00000000 Binary files a/src-tauri/icons/ios/AppIcon-20x20@3x.png and /dev/null differ diff --git a/src-tauri/icons/ios/AppIcon-29x29@1x.png b/src-tauri/icons/ios/AppIcon-29x29@1x.png deleted file mode 100644 index ea70093c..00000000 Binary files a/src-tauri/icons/ios/AppIcon-29x29@1x.png and /dev/null differ diff --git a/src-tauri/icons/ios/AppIcon-29x29@2x-1.png b/src-tauri/icons/ios/AppIcon-29x29@2x-1.png deleted file mode 100644 index 56d598e4..00000000 Binary files a/src-tauri/icons/ios/AppIcon-29x29@2x-1.png and /dev/null differ diff --git a/src-tauri/icons/ios/AppIcon-29x29@2x.png b/src-tauri/icons/ios/AppIcon-29x29@2x.png deleted file mode 100644 index 56d598e4..00000000 Binary files a/src-tauri/icons/ios/AppIcon-29x29@2x.png and /dev/null differ diff --git a/src-tauri/icons/ios/AppIcon-29x29@3x.png b/src-tauri/icons/ios/AppIcon-29x29@3x.png deleted file mode 100644 index ad378bd6..00000000 Binary files a/src-tauri/icons/ios/AppIcon-29x29@3x.png and /dev/null differ diff --git a/src-tauri/icons/ios/AppIcon-40x40@1x.png b/src-tauri/icons/ios/AppIcon-40x40@1x.png deleted file mode 100644 index edf739c8..00000000 Binary files a/src-tauri/icons/ios/AppIcon-40x40@1x.png and /dev/null differ diff --git a/src-tauri/icons/ios/AppIcon-40x40@2x-1.png b/src-tauri/icons/ios/AppIcon-40x40@2x-1.png deleted file mode 100644 index f8c0e414..00000000 Binary files a/src-tauri/icons/ios/AppIcon-40x40@2x-1.png and /dev/null differ diff --git a/src-tauri/icons/ios/AppIcon-40x40@2x.png b/src-tauri/icons/ios/AppIcon-40x40@2x.png deleted file mode 100644 index f8c0e414..00000000 Binary files a/src-tauri/icons/ios/AppIcon-40x40@2x.png and /dev/null differ diff --git a/src-tauri/icons/ios/AppIcon-40x40@3x.png b/src-tauri/icons/ios/AppIcon-40x40@3x.png deleted file mode 100644 index ea58b4be..00000000 Binary files a/src-tauri/icons/ios/AppIcon-40x40@3x.png and /dev/null differ diff --git a/src-tauri/icons/ios/AppIcon-512@2x.png b/src-tauri/icons/ios/AppIcon-512@2x.png deleted file mode 100644 index d48cfe8b..00000000 Binary files a/src-tauri/icons/ios/AppIcon-512@2x.png and /dev/null differ diff --git a/src-tauri/icons/ios/AppIcon-60x60@2x.png b/src-tauri/icons/ios/AppIcon-60x60@2x.png deleted file mode 100644 index ea58b4be..00000000 Binary files a/src-tauri/icons/ios/AppIcon-60x60@2x.png and /dev/null differ diff --git a/src-tauri/icons/ios/AppIcon-60x60@3x.png b/src-tauri/icons/ios/AppIcon-60x60@3x.png deleted file mode 100644 index fba5f8db..00000000 Binary files a/src-tauri/icons/ios/AppIcon-60x60@3x.png and /dev/null differ diff --git a/src-tauri/icons/ios/AppIcon-76x76@1x.png b/src-tauri/icons/ios/AppIcon-76x76@1x.png deleted file mode 100644 index 0eb02242..00000000 Binary files a/src-tauri/icons/ios/AppIcon-76x76@1x.png and /dev/null differ diff --git a/src-tauri/icons/ios/AppIcon-76x76@2x.png b/src-tauri/icons/ios/AppIcon-76x76@2x.png deleted file mode 100644 index 65b7666b..00000000 Binary files a/src-tauri/icons/ios/AppIcon-76x76@2x.png and /dev/null differ diff --git a/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png b/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png deleted file mode 100644 index a4e4d95b..00000000 Binary files a/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png and /dev/null differ diff --git a/src-tauri/src/commands/metadata.rs b/src-tauri/src/commands/metadata.rs index 5057e619..202c6577 100644 --- a/src-tauri/src/commands/metadata.rs +++ b/src-tauri/src/commands/metadata.rs @@ -5,7 +5,7 @@ use specta::Type; use std::{str::FromStr, time::Duration}; use tauri::{Emitter, Manager, State}; -use crate::{common::process_event, Nostr, RichEvent}; +use crate::{common::process_event, Nostr, RichEvent, FETCH_LIMIT}; #[derive(Clone, Serialize, Deserialize, Type)] pub struct Mention { @@ -259,6 +259,35 @@ pub async fn get_all_newsfeeds( Ok(alt_events) } +#[tauri::command] +#[specta::specta] +pub async fn get_all_local_newsfeeds( + until: Option, + state: State<'_, Nostr>, +) -> Result, String> { + let client = &state.client; + + let as_of = match until { + Some(until) => Timestamp::from_str(&until).unwrap_or(Timestamp::now()), + None => Timestamp::now(), + }; + + let filter = Filter::new() + .kind(Kind::FollowSet) + .limit(FETCH_LIMIT) + .until(as_of); + + let events = client + .database() + .query(vec![filter]) + .await + .map_err(|err| err.to_string())?; + + let alt_events = process_event(client, events, false).await; + + Ok(alt_events) +} + #[tauri::command] #[specta::specta] pub async fn set_interest( @@ -361,6 +390,35 @@ pub async fn get_all_interests( Ok(alt_events) } +#[tauri::command] +#[specta::specta] +pub async fn get_all_local_interests( + until: Option, + state: State<'_, Nostr>, +) -> Result, String> { + let client = &state.client; + + let as_of = match until { + Some(until) => Timestamp::from_str(&until).unwrap_or(Timestamp::now()), + None => Timestamp::now(), + }; + + let filter = Filter::new() + .kinds(vec![Kind::Interests, Kind::InterestSet]) + .limit(FETCH_LIMIT) + .until(as_of); + + let events = client + .database() + .query(vec![filter]) + .await + .map_err(|err| err.to_string())?; + + let alt_events = process_event(client, events, false).await; + + Ok(alt_events) +} + #[tauri::command] #[specta::specta] pub async fn get_all_profiles(state: State<'_, Nostr>) -> Result, String> { diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 7f552233..95f3297c 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -97,9 +97,11 @@ fn main() { set_group, get_group, get_all_newsfeeds, + get_all_local_newsfeeds, set_interest, get_interest, get_all_interests, + get_all_local_interests, set_wallet, load_wallet, remove_wallet, diff --git a/src/commands.gen.ts b/src/commands.gen.ts index dcd0f64a..c4f7d368 100644 --- a/src/commands.gen.ts +++ b/src/commands.gen.ts @@ -208,6 +208,14 @@ async getAllNewsfeeds(id: string) : Promise> { else return { status: "error", error: e as any }; } }, +async getAllLocalNewsfeeds(until: string | null) : Promise> { + try { + return { status: "ok", data: await TAURI_INVOKE("get_all_local_newsfeeds", { until }) }; +} catch (e) { + if(e instanceof Error) throw e; + else return { status: "error", error: e as any }; +} +}, async setInterest(title: string, description: string | null, image: string | null, hashtags: string[]) : Promise> { try { return { status: "ok", data: await TAURI_INVOKE("set_interest", { title, description, image, hashtags }) }; @@ -232,6 +240,14 @@ async getAllInterests(id: string) : Promise> { else return { status: "error", error: e as any }; } }, +async getAllLocalInterests(until: string | null) : Promise> { + try { + return { status: "ok", data: await TAURI_INVOKE("get_all_local_interests", { until }) }; +} catch (e) { + if(e instanceof Error) throw e; + else return { status: "error", error: e as any }; +} +}, async setWallet(uri: string) : Promise> { try { return { status: "ok", data: await TAURI_INVOKE("set_wallet", { uri }) }; diff --git a/src/routes.gen.ts b/src/routes.gen.ts index 2ffd00ed..ebc67a2d 100644 --- a/src/routes.gen.ts +++ b/src/routes.gen.ts @@ -51,6 +51,12 @@ const ColumnsLayoutSearchLazyImport = createFileRoute( const ColumnsLayoutOnboardingLazyImport = createFileRoute( '/columns/_layout/onboarding', )() +const ColumnsLayoutDiscoverNewsfeedsLazyImport = createFileRoute( + '/columns/_layout/discover-newsfeeds', +)() +const ColumnsLayoutDiscoverInterestsLazyImport = createFileRoute( + '/columns/_layout/discover-interests', +)() const ColumnsLayoutUsersIdLazyImport = createFileRoute( '/columns/_layout/users/$id', )() @@ -196,6 +202,28 @@ const ColumnsLayoutOnboardingLazyRoute = import('./routes/columns/_layout/onboarding.lazy').then((d) => d.Route), ) +const ColumnsLayoutDiscoverNewsfeedsLazyRoute = + ColumnsLayoutDiscoverNewsfeedsLazyImport.update({ + id: '/discover-newsfeeds', + path: '/discover-newsfeeds', + getParentRoute: () => ColumnsLayoutRoute, + } as any).lazy(() => + import('./routes/columns/_layout/discover-newsfeeds.lazy').then( + (d) => d.Route, + ), + ) + +const ColumnsLayoutDiscoverInterestsLazyRoute = + ColumnsLayoutDiscoverInterestsLazyImport.update({ + id: '/discover-interests', + path: '/discover-interests', + getParentRoute: () => ColumnsLayoutRoute, + } as any).lazy(() => + import('./routes/columns/_layout/discover-interests.lazy').then( + (d) => d.Route, + ), + ) + const SettingsIdWalletRoute = SettingsIdWalletImport.update({ id: '/wallet', path: '/wallet', @@ -469,6 +497,20 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof SettingsIdWalletImport parentRoute: typeof SettingsIdLazyImport } + '/columns/_layout/discover-interests': { + id: '/columns/_layout/discover-interests' + path: '/discover-interests' + fullPath: '/columns/discover-interests' + preLoaderRoute: typeof ColumnsLayoutDiscoverInterestsLazyImport + parentRoute: typeof ColumnsLayoutImport + } + '/columns/_layout/discover-newsfeeds': { + id: '/columns/_layout/discover-newsfeeds' + path: '/discover-newsfeeds' + fullPath: '/columns/discover-newsfeeds' + preLoaderRoute: typeof ColumnsLayoutDiscoverNewsfeedsLazyImport + parentRoute: typeof ColumnsLayoutImport + } '/columns/_layout/onboarding': { id: '/columns/_layout/onboarding' path: '/onboarding' @@ -602,6 +644,8 @@ const ColumnsLayoutCreateNewsfeedRouteWithChildren = interface ColumnsLayoutRouteChildren { ColumnsLayoutCreateNewsfeedRoute: typeof ColumnsLayoutCreateNewsfeedRouteWithChildren ColumnsLayoutGlobalRoute: typeof ColumnsLayoutGlobalRoute + ColumnsLayoutDiscoverInterestsLazyRoute: typeof ColumnsLayoutDiscoverInterestsLazyRoute + ColumnsLayoutDiscoverNewsfeedsLazyRoute: typeof ColumnsLayoutDiscoverNewsfeedsLazyRoute ColumnsLayoutOnboardingLazyRoute: typeof ColumnsLayoutOnboardingLazyRoute ColumnsLayoutSearchLazyRoute: typeof ColumnsLayoutSearchLazyRoute ColumnsLayoutTrendingLazyRoute: typeof ColumnsLayoutTrendingLazyRoute @@ -620,6 +664,10 @@ const ColumnsLayoutRouteChildren: ColumnsLayoutRouteChildren = { ColumnsLayoutCreateNewsfeedRoute: ColumnsLayoutCreateNewsfeedRouteWithChildren, ColumnsLayoutGlobalRoute: ColumnsLayoutGlobalRoute, + ColumnsLayoutDiscoverInterestsLazyRoute: + ColumnsLayoutDiscoverInterestsLazyRoute, + ColumnsLayoutDiscoverNewsfeedsLazyRoute: + ColumnsLayoutDiscoverNewsfeedsLazyRoute, ColumnsLayoutOnboardingLazyRoute: ColumnsLayoutOnboardingLazyRoute, ColumnsLayoutSearchLazyRoute: ColumnsLayoutSearchLazyRoute, ColumnsLayoutTrendingLazyRoute: ColumnsLayoutTrendingLazyRoute, @@ -685,6 +733,8 @@ export interface FileRoutesByFullPath { '/settings/$id/general': typeof SettingsIdGeneralRoute '/settings/$id/relay': typeof SettingsIdRelayRoute '/settings/$id/wallet': typeof SettingsIdWalletRoute + '/columns/discover-interests': typeof ColumnsLayoutDiscoverInterestsLazyRoute + '/columns/discover-newsfeeds': typeof ColumnsLayoutDiscoverNewsfeedsLazyRoute '/columns/onboarding': typeof ColumnsLayoutOnboardingLazyRoute '/columns/search': typeof ColumnsLayoutSearchLazyRoute '/columns/trending': typeof ColumnsLayoutTrendingLazyRoute @@ -720,6 +770,8 @@ export interface FileRoutesByTo { '/settings/$id/general': typeof SettingsIdGeneralRoute '/settings/$id/relay': typeof SettingsIdRelayRoute '/settings/$id/wallet': typeof SettingsIdWalletRoute + '/columns/discover-interests': typeof ColumnsLayoutDiscoverInterestsLazyRoute + '/columns/discover-newsfeeds': typeof ColumnsLayoutDiscoverNewsfeedsLazyRoute '/columns/onboarding': typeof ColumnsLayoutOnboardingLazyRoute '/columns/search': typeof ColumnsLayoutSearchLazyRoute '/columns/trending': typeof ColumnsLayoutTrendingLazyRoute @@ -758,6 +810,8 @@ export interface FileRoutesById { '/settings/$id/general': typeof SettingsIdGeneralRoute '/settings/$id/relay': typeof SettingsIdRelayRoute '/settings/$id/wallet': typeof SettingsIdWalletRoute + '/columns/_layout/discover-interests': typeof ColumnsLayoutDiscoverInterestsLazyRoute + '/columns/_layout/discover-newsfeeds': typeof ColumnsLayoutDiscoverNewsfeedsLazyRoute '/columns/_layout/onboarding': typeof ColumnsLayoutOnboardingLazyRoute '/columns/_layout/search': typeof ColumnsLayoutSearchLazyRoute '/columns/_layout/trending': typeof ColumnsLayoutTrendingLazyRoute @@ -796,6 +850,8 @@ export interface FileRouteTypes { | '/settings/$id/general' | '/settings/$id/relay' | '/settings/$id/wallet' + | '/columns/discover-interests' + | '/columns/discover-newsfeeds' | '/columns/onboarding' | '/columns/search' | '/columns/trending' @@ -830,6 +886,8 @@ export interface FileRouteTypes { | '/settings/$id/general' | '/settings/$id/relay' | '/settings/$id/wallet' + | '/columns/discover-interests' + | '/columns/discover-newsfeeds' | '/columns/onboarding' | '/columns/search' | '/columns/trending' @@ -866,6 +924,8 @@ export interface FileRouteTypes { | '/settings/$id/general' | '/settings/$id/relay' | '/settings/$id/wallet' + | '/columns/_layout/discover-interests' + | '/columns/_layout/discover-newsfeeds' | '/columns/_layout/onboarding' | '/columns/_layout/search' | '/columns/_layout/trending' @@ -975,6 +1035,8 @@ export const routeTree = rootRoute "children": [ "/columns/_layout/create-newsfeed", "/columns/_layout/global", + "/columns/_layout/discover-interests", + "/columns/_layout/discover-newsfeeds", "/columns/_layout/onboarding", "/columns/_layout/search", "/columns/_layout/trending", @@ -1040,6 +1102,14 @@ export const routeTree = rootRoute "filePath": "settings.$id/wallet.tsx", "parent": "/settings/$id" }, + "/columns/_layout/discover-interests": { + "filePath": "columns/_layout/discover-interests.lazy.tsx", + "parent": "/columns/_layout" + }, + "/columns/_layout/discover-newsfeeds": { + "filePath": "columns/_layout/discover-newsfeeds.lazy.tsx", + "parent": "/columns/_layout" + }, "/columns/_layout/onboarding": { "filePath": "columns/_layout/onboarding.lazy.tsx", "parent": "/columns/_layout" diff --git a/src/routes/columns/_layout/discover-interests.lazy.tsx b/src/routes/columns/_layout/discover-interests.lazy.tsx new file mode 100644 index 00000000..7b6655ed --- /dev/null +++ b/src/routes/columns/_layout/discover-interests.lazy.tsx @@ -0,0 +1,182 @@ +import { commands } from "@/commands.gen"; +import { toLumeEvents } from "@/commons"; +import { Spinner, User } from "@/components"; +import { LumeWindow } from "@/system"; +import { ArrowDown } from "@phosphor-icons/react"; +import * as ScrollArea from "@radix-ui/react-scroll-area"; +import { useInfiniteQuery } from "@tanstack/react-query"; +import { createLazyFileRoute } from "@tanstack/react-router"; +import { nanoid } from "nanoid"; +import type { NostrEvent } from "nostr-tools"; +import { type RefObject, useCallback, useRef } from "react"; +import { Virtualizer } from "virtua"; + +export const Route = createLazyFileRoute("/columns/_layout/discover-interests")( + { + component: Screen, + }, +); + +function Screen() { + const { + isLoading, + isError, + error, + isFetchingNextPage, + hasNextPage, + fetchNextPage, + data, + } = useInfiniteQuery({ + queryKey: ["local-interests"], + initialPageParam: 0, + queryFn: async ({ pageParam }: { pageParam: number }) => { + const until = pageParam > 0 ? pageParam.toString() : null; + const res = await commands.getAllLocalInterests(until); + + if (res.status === "ok") { + const data = toLumeEvents(res.data); + return data; + } else { + throw new Error(res.error); + } + }, + getNextPageParam: (lastPage) => { + const lastEvent = lastPage.at(-1); + + if (lastEvent) { + return lastEvent.created_at - 1; + } + }, + select: (data) => + data?.pages + .flat() + .filter( + (item) => item.tags.filter((tag) => tag[0] === "p")?.length > 0, + ), + refetchOnWindowFocus: false, + }); + + const ref = useRef(null); + + const renderItem = useCallback( + (item: NostrEvent) => { + const name = + item.tags.find((tag) => tag[0] === "title")?.[1] || "Unnamed"; + const label = + item.tags.find((tag) => tag[0] === "label")?.[1] || nanoid(); + + return ( +
+
+ + +
+ {item.tags + .filter((tag) => tag[0] === "t") + .map((tag) => ( +
+ {tag[1].includes("#") ? tag[1] : `#${tag[1]}`} +
+ ))} +
+
+ + + + +
+
+
+
+ + + + + +
{name}
+
+
+ +
+
+
+ ); + }, + [data], + ); + + return ( + + + }> + {isLoading ? ( +
+ + Loading... +
+ ) : isError ? ( +
+

{error?.message ?? "Error"}

+
+ ) : !data?.length ? ( +
+

Empty.

+
+ ) : ( + data?.map((item) => renderItem(item)) + )} + {hasNextPage ? ( + + ) : null} +
+
+ + + + +
+ ); +} diff --git a/src/routes/columns/_layout/discover-newsfeeds.lazy.tsx b/src/routes/columns/_layout/discover-newsfeeds.lazy.tsx new file mode 100644 index 00000000..5b3c2fa6 --- /dev/null +++ b/src/routes/columns/_layout/discover-newsfeeds.lazy.tsx @@ -0,0 +1,184 @@ +import { commands } from "@/commands.gen"; +import { toLumeEvents } from "@/commons"; +import { Spinner, User } from "@/components"; +import { LumeWindow } from "@/system"; +import { ArrowDown } from "@phosphor-icons/react"; +import * as ScrollArea from "@radix-ui/react-scroll-area"; +import { useInfiniteQuery } from "@tanstack/react-query"; +import { createLazyFileRoute } from "@tanstack/react-router"; +import { nanoid } from "nanoid"; +import type { NostrEvent } from "nostr-tools"; +import { type RefObject, useCallback, useRef } from "react"; +import { Virtualizer } from "virtua"; + +export const Route = createLazyFileRoute("/columns/_layout/discover-newsfeeds")( + { + component: Screen, + }, +); + +function Screen() { + const { + isLoading, + isError, + error, + isFetchingNextPage, + hasNextPage, + fetchNextPage, + data, + } = useInfiniteQuery({ + queryKey: ["local-newsfeeds"], + initialPageParam: 0, + queryFn: async ({ pageParam }: { pageParam: number }) => { + const until = pageParam > 0 ? pageParam.toString() : null; + const res = await commands.getAllLocalNewsfeeds(until); + + if (res.status === "ok") { + const data = toLumeEvents(res.data); + return data; + } else { + throw new Error(res.error); + } + }, + getNextPageParam: (lastPage) => { + const lastEvent = lastPage.at(-1); + + if (lastEvent) { + return lastEvent.created_at - 1; + } + }, + select: (data) => + data?.pages + .flat() + .filter( + (item) => item.tags.filter((tag) => tag[0] === "p")?.length > 0, + ), + refetchOnWindowFocus: false, + }); + + const ref = useRef(null); + + const renderItem = useCallback( + (item: NostrEvent) => { + const name = + item.tags.find((tag) => tag[0] === "title")?.[1] || "Unnamed"; + + const label = item.tags.find((tag) => tag[0] === "d")?.[1] || nanoid(); + + return ( +
+
+ + +
+ {item.tags + .filter((tag) => tag[0] === "p") + .map((tag) => ( + + + + + + ))} +
+
+ + + + +
+
+
+
+ + + + + +
{name}
+
+
+ +
+
+
+ ); + }, + [data], + ); + + return ( + + + }> + {isLoading ? ( +
+ + Loading... +
+ ) : isError ? ( +
+

{error?.message ?? "Error"}

+
+ ) : !data?.length ? ( +
+

Empty.

+
+ ) : ( + data?.map((item) => renderItem(item)) + )} + {hasNextPage ? ( + + ) : null} +
+
+ + + + +
+ ); +} diff --git a/src/routes/columns/_layout/launchpad.$id.lazy.tsx b/src/routes/columns/_layout/launchpad.$id.lazy.tsx index bc6906e6..85217b28 100644 --- a/src/routes/columns/_layout/launchpad.$id.lazy.tsx +++ b/src/routes/columns/_layout/launchpad.$id.lazy.tsx @@ -182,10 +182,20 @@ function Newsfeeds() { ) : ( data?.map((item) => renderItem(item)) )} -
+
+ ); @@ -326,10 +336,20 @@ function Interests() { ) : ( data?.map((item) => renderItem(item)) )} -
+
+ ); diff --git a/src/system/useEvent.ts b/src/system/useEvent.ts index 71947b39..ecc0299a 100644 --- a/src/system/useEvent.ts +++ b/src/system/useEvent.ts @@ -2,55 +2,61 @@ import { commands } from "@/commands.gen"; import type { NostrEvent } from "@/types"; import { useQuery } from "@tanstack/react-query"; import { nip19 } from "nostr-tools"; +import { useMemo } from "react"; import { LumeEvent } from "./event"; export function useEvent(id: string, repost?: string) { + const hex = useMemo(() => { + try { + const normalized = id.replace("nostr:", "").replace(/[^\w\s]/gi, ""); + const decoded = nip19.decode(normalized); + + switch (decoded.type) { + case "note": + return decoded.data; + case "nevent": + return decoded.data.id; + default: + return normalized; + } + } catch { + return id; + } + }, [id]); + const { isLoading, isError, error, data } = useQuery({ queryKey: ["ids", "event", id], queryFn: async () => { - try { - if (repost?.length) { - const nostrEvent: NostrEvent = JSON.parse(repost); - const res = await commands.getMetaFromEvent(nostrEvent.content); - - if (res.status === "ok") { - nostrEvent.meta = res.data; - } - - return new LumeEvent(nostrEvent); - } - - let normalizedId = id.replace("nostr:", "").replace(/[^\w\s]/gi, ""); - - if (normalizedId.startsWith("nevent")) { - const decoded = nip19.decode(normalizedId); - - if (decoded.type === "nevent") { - normalizedId = decoded.data.id; - } - } - - const res = await commands.getEvent(normalizedId); + if (repost?.length) { + const nostrEvent: NostrEvent = JSON.parse(repost); + const res = await commands.getMetaFromEvent(nostrEvent.content); if (res.status === "ok") { - const data = res.data; - const raw: NostrEvent = JSON.parse(data.raw); - - if (data.parsed) { - raw.meta = data.parsed; - } - - return new LumeEvent(raw); - } else { - throw new Error(res.error); + nostrEvent.meta = res.data; } - } catch (e) { - throw new Error(String(e)); + + return new LumeEvent(nostrEvent); + } + + const res = await commands.getEvent(hex); + + if (res.status === "ok") { + const data = res.data; + const raw: NostrEvent = JSON.parse(data.raw); + + if (data.parsed) { + raw.meta = data.parsed; + } + + return new LumeEvent(raw); + } else { + throw new Error(res.error); } }, refetchOnWindowFocus: false, refetchOnMount: false, refetchOnReconnect: false, + enabled: !!hex, }); return { isLoading, isError, error, data }; diff --git a/src/system/useProfile.ts b/src/system/useProfile.ts index c061bcb9..ca7cf3aa 100644 --- a/src/system/useProfile.ts +++ b/src/system/useProfile.ts @@ -19,7 +19,7 @@ export function useProfile(pubkey: string, data?: string) { case "naddr": return decoded.data.pubkey; default: - return pubkey; + return normalized; } } catch { return pubkey;