From 5baffd00b994334b95130c239919f39f6774b89f Mon Sep 17 00:00:00 2001 From: Martti Malmi Date: Wed, 10 Jan 2024 20:16:30 +0200 Subject: [PATCH] fix the rest of warnings --- .../app/src/Cache/CommunityLeadersStore.tsx | 4 +- packages/app/src/Cache/TextCache.tsx | 8 +- .../Components/Event/Create/OkResponseRow.tsx | 2 +- .../app/src/Components/Event/Note/Note.tsx | 2 +- packages/app/src/Components/Event/Thread.tsx | 4 +- .../app/src/Components/Feed/RootTabItems.tsx | 40 +-- packages/app/src/Components/Feed/RootTabs.tsx | 8 +- .../Components/IntlProvider/IntlProvider.tsx | 2 +- .../src/Components/IntlProvider/langStore.tsx | 4 +- .../src/Components/IntlProvider/useLocale.tsx | 10 +- .../Spotlight/SpotlightThreadModal.tsx | 2 +- .../Components/Trending/TrendingHashtags.tsx | 2 +- .../src/Components/Trending/TrendingPosts.tsx | 2 +- .../app/src/Hooks/useCommunityLeaders.tsx | 10 +- packages/app/src/Hooks/useRates.tsx | 12 +- .../app/src/Hooks/useTextTransformCache.tsx | 4 +- packages/app/src/Pages/Layout/Header.tsx | 2 +- packages/app/src/Pages/Root.tsx | 273 ------------------ .../app/src/Pages/Root/ConversationsTab.tsx | 5 + packages/app/src/Pages/Root/DefaultTab.tsx | 12 + .../src/Pages/Root/FollowedByFriendsTab.tsx | 15 + packages/app/src/Pages/Root/GlobalTab.tsx | 101 +++++++ packages/app/src/Pages/Root/NotesTab.tsx | 50 ++++ packages/app/src/Pages/{ => Root}/Root.css | 0 packages/app/src/Pages/Root/RootRoutes.tsx | 25 ++ packages/app/src/Pages/Root/RootTabRoutes.tsx | 67 +++++ packages/app/src/Pages/Root/TagsTab.tsx | 17 ++ packages/app/src/Pages/onboarding/index.tsx | 2 +- .../app/src/Pages/settings/Preferences.tsx | 2 +- packages/app/src/Pages/settings/Relays.tsx | 15 +- packages/app/src/Pages/settings/Routes.tsx | 14 +- .../app/src/Pages/settings/saveRelays.tsx | 15 + packages/app/src/Utils/Const.ts | 2 +- packages/app/src/Utils/Thread/ChainKey.tsx | 18 ++ .../app/src/Utils/Thread/ThreadContext.tsx | 14 + .../Thread/ThreadContextWrapper.tsx} | 37 +-- packages/app/src/index.tsx | 3 +- 37 files changed, 415 insertions(+), 390 deletions(-) delete mode 100644 packages/app/src/Pages/Root.tsx create mode 100644 packages/app/src/Pages/Root/ConversationsTab.tsx create mode 100644 packages/app/src/Pages/Root/DefaultTab.tsx create mode 100644 packages/app/src/Pages/Root/FollowedByFriendsTab.tsx create mode 100644 packages/app/src/Pages/Root/GlobalTab.tsx create mode 100644 packages/app/src/Pages/Root/NotesTab.tsx rename packages/app/src/Pages/{ => Root}/Root.css (100%) create mode 100644 packages/app/src/Pages/Root/RootRoutes.tsx create mode 100644 packages/app/src/Pages/Root/RootTabRoutes.tsx create mode 100644 packages/app/src/Pages/Root/TagsTab.tsx create mode 100644 packages/app/src/Pages/settings/saveRelays.tsx create mode 100644 packages/app/src/Utils/Thread/ChainKey.tsx create mode 100644 packages/app/src/Utils/Thread/ThreadContext.tsx rename packages/app/src/{Hooks/useThreadContext.tsx => Utils/Thread/ThreadContextWrapper.tsx} (67%) diff --git a/packages/app/src/Cache/CommunityLeadersStore.tsx b/packages/app/src/Cache/CommunityLeadersStore.tsx index 7e332a7f..dd45f836 100644 --- a/packages/app/src/Cache/CommunityLeadersStore.tsx +++ b/packages/app/src/Cache/CommunityLeadersStore.tsx @@ -1,4 +1,4 @@ -import {ExternalStore} from "@snort/shared"; +import { ExternalStore } from "@snort/shared"; class CommunityLeadersStore extends ExternalStore> { #leaders: Array = []; @@ -13,4 +13,4 @@ class CommunityLeadersStore extends ExternalStore> { } } -export const LeadersStore = new CommunityLeadersStore(); \ No newline at end of file +export const LeadersStore = new CommunityLeadersStore(); diff --git a/packages/app/src/Cache/TextCache.tsx b/packages/app/src/Cache/TextCache.tsx index 310e3d16..86daedb9 100644 --- a/packages/app/src/Cache/TextCache.tsx +++ b/packages/app/src/Cache/TextCache.tsx @@ -1,6 +1,6 @@ -import {ParsedFragment} from "@snort/system"; -import {LRUCache} from "typescript-lru-cache"; +import { ParsedFragment } from "@snort/system"; +import { LRUCache } from "typescript-lru-cache"; export const TextCache = new LRUCache>({ - maxSize: 1000 -}); \ No newline at end of file + maxSize: 1000, +}); diff --git a/packages/app/src/Components/Event/Create/OkResponseRow.tsx b/packages/app/src/Components/Event/Create/OkResponseRow.tsx index f8e03667..6fcfa8f3 100644 --- a/packages/app/src/Components/Event/Create/OkResponseRow.tsx +++ b/packages/app/src/Components/Event/Create/OkResponseRow.tsx @@ -8,7 +8,7 @@ import IconButton from "@/Components/Button/IconButton"; import Icon from "@/Components/Icons/Icon"; import useEventPublisher from "@/Hooks/useEventPublisher"; import useLogin from "@/Hooks/useLogin"; -import { saveRelays } from "@/Pages/settings/Relays"; +import { saveRelays } from "@/Pages/settings/saveRelays"; import { getRelayName } from "@/Utils"; import { removeRelay } from "@/Utils/Login"; diff --git a/packages/app/src/Components/Event/Note/Note.tsx b/packages/app/src/Components/Event/Note/Note.tsx index 7696a4f7..2cb2f03f 100644 --- a/packages/app/src/Components/Event/Note/Note.tsx +++ b/packages/app/src/Components/Event/Note/Note.tsx @@ -9,8 +9,8 @@ import NoteHeader from "@/Components/Event/Note/NoteHeader"; import { NoteText } from "@/Components/Event/Note/NoteText"; import { TranslationInfo } from "@/Components/Event/Note/TranslationInfo"; import useModeration from "@/Hooks/useModeration"; -import { chainKey } from "@/Hooks/useThreadContext"; import { findTag } from "@/Utils"; +import { chainKey } from "@/Utils/Thread/ChainKey"; import messages from "../../messages"; import Text from "../../Text/Text"; diff --git a/packages/app/src/Components/Event/Thread.tsx b/packages/app/src/Components/Event/Thread.tsx index e2c0e32f..e1914508 100644 --- a/packages/app/src/Components/Event/Thread.tsx +++ b/packages/app/src/Components/Event/Thread.tsx @@ -10,7 +10,9 @@ import BackButton from "@/Components/Button/BackButton"; import Collapsed from "@/Components/Collapsed"; import Note from "@/Components/Event/EventComponent"; import NoteGhost from "@/Components/Event/Note/NoteGhost"; -import { chainKey, ThreadContext, ThreadContextWrapper } from "@/Hooks/useThreadContext"; +import { chainKey } from "@/Utils/Thread/ChainKey"; +import { ThreadContext } from "@/Utils/Thread/ThreadContext"; +import { ThreadContextWrapper } from "@/Utils/Thread/ThreadContextWrapper"; import messages from "../messages"; diff --git a/packages/app/src/Components/Feed/RootTabItems.tsx b/packages/app/src/Components/Feed/RootTabItems.tsx index 2d45e67c..4cbf9ae2 100644 --- a/packages/app/src/Components/Feed/RootTabItems.tsx +++ b/packages/app/src/Components/Feed/RootTabItems.tsx @@ -1,8 +1,8 @@ -import {ReactNode} from "react"; -import {FormattedMessage} from "react-intl"; +import { ReactNode } from "react"; +import { FormattedMessage } from "react-intl"; import Icon from "@/Components/Icons/Icon"; -import {Newest} from "@/Utils/Login"; +import { Newest } from "@/Utils/Login"; export type RootTab = | "following" @@ -22,8 +22,8 @@ export function rootTabItems(base: string, pubKey: string | undefined, tags: New show: Boolean(pubKey), element: ( <> - - + + ), }, @@ -33,8 +33,8 @@ export function rootTabItems(base: string, pubKey: string | undefined, tags: New show: true, element: ( <> - - + + ), }, @@ -44,8 +44,8 @@ export function rootTabItems(base: string, pubKey: string | undefined, tags: New show: Boolean(pubKey), element: ( <> - - + + ), }, @@ -55,8 +55,8 @@ export function rootTabItems(base: string, pubKey: string | undefined, tags: New show: Boolean(pubKey), element: ( <> - - + + ), }, @@ -66,8 +66,8 @@ export function rootTabItems(base: string, pubKey: string | undefined, tags: New show: Boolean(pubKey), element: ( <> - - + + ), }, @@ -77,8 +77,8 @@ export function rootTabItems(base: string, pubKey: string | undefined, tags: New show: true, element: ( <> - - + + ), }, @@ -88,8 +88,8 @@ export function rootTabItems(base: string, pubKey: string | undefined, tags: New show: true, element: ( <> - - + + ), }, @@ -99,8 +99,8 @@ export function rootTabItems(base: string, pubKey: string | undefined, tags: New show: tags.item.length > 0, element: ( <> - - + + ), }, @@ -111,4 +111,4 @@ export function rootTabItems(base: string, pubKey: string | undefined, tags: New element: ReactNode; }>; return menuItems; -} \ No newline at end of file +} diff --git a/packages/app/src/Components/Feed/RootTabs.tsx b/packages/app/src/Components/Feed/RootTabs.tsx index 7e778145..62850495 100644 --- a/packages/app/src/Components/Feed/RootTabs.tsx +++ b/packages/app/src/Components/Feed/RootTabs.tsx @@ -1,10 +1,10 @@ import "./RootTabs.css"; -import {Menu, MenuItem} from "@szhsin/react-menu"; -import {useEffect, useMemo, useState} from "react"; -import {useLocation, useNavigate} from "react-router-dom"; +import { Menu, MenuItem } from "@szhsin/react-menu"; +import { useEffect, useMemo, useState } from "react"; +import { useLocation, useNavigate } from "react-router-dom"; -import {RootTab, rootTabItems} from "@/Components/Feed/RootTabItems"; +import { RootTab, rootTabItems } from "@/Components/Feed/RootTabItems"; import Icon from "@/Components/Icons/Icon"; import useLogin from "@/Hooks/useLogin"; diff --git a/packages/app/src/Components/IntlProvider/IntlProvider.tsx b/packages/app/src/Components/IntlProvider/IntlProvider.tsx index eb35a1db..4084fd43 100644 --- a/packages/app/src/Components/IntlProvider/IntlProvider.tsx +++ b/packages/app/src/Components/IntlProvider/IntlProvider.tsx @@ -2,7 +2,7 @@ import { ReactNode, useEffect, useState } from "react"; import { IntlProvider as ReactIntlProvider } from "react-intl"; import { DefaultLocale } from "@/Components/IntlProvider/IntlProviderUtils"; -import {useLocale} from "@/Components/IntlProvider/useLocale"; +import { useLocale } from "@/Components/IntlProvider/useLocale"; import enMessages from "@/translations/en.json"; const getMessages = (locale: string) => { diff --git a/packages/app/src/Components/IntlProvider/langStore.tsx b/packages/app/src/Components/IntlProvider/langStore.tsx index 466e2004..b6956420 100644 --- a/packages/app/src/Components/IntlProvider/langStore.tsx +++ b/packages/app/src/Components/IntlProvider/langStore.tsx @@ -1,4 +1,4 @@ -import {ExternalStore} from "@snort/shared"; +import { ExternalStore } from "@snort/shared"; class LangStore extends ExternalStore { setLang(s: string) { @@ -11,4 +11,4 @@ class LangStore extends ExternalStore { } } -export const LangOverride = new LangStore(); \ No newline at end of file +export const LangOverride = new LangStore(); diff --git a/packages/app/src/Components/IntlProvider/useLocale.tsx b/packages/app/src/Components/IntlProvider/useLocale.tsx index fb9afaa5..185707e3 100644 --- a/packages/app/src/Components/IntlProvider/useLocale.tsx +++ b/packages/app/src/Components/IntlProvider/useLocale.tsx @@ -1,11 +1,11 @@ -import {useSyncExternalStore} from "react"; +import { useSyncExternalStore } from "react"; -import {getLocale} from "@/Components/IntlProvider/IntlProviderUtils"; -import {LangOverride} from "@/Components/IntlProvider/langStore"; +import { getLocale } from "@/Components/IntlProvider/IntlProviderUtils"; +import { LangOverride } from "@/Components/IntlProvider/langStore"; import useLogin from "@/Hooks/useLogin"; export function useLocale() { - const {language} = useLogin(s => ({language: s.appData.item.preferences.language})); + const { language } = useLogin(s => ({ language: s.appData.item.preferences.language })); const loggedOutLang = useSyncExternalStore( c => LangOverride.hook(c), () => LangOverride.snapshot(), @@ -16,4 +16,4 @@ export function useLocale() { lang: locale.toLowerCase().split(/[_-]+/)[0], setOverride: (s: string) => LangOverride.setLang(s), }; -} \ No newline at end of file +} diff --git a/packages/app/src/Components/Spotlight/SpotlightThreadModal.tsx b/packages/app/src/Components/Spotlight/SpotlightThreadModal.tsx index 50ced03d..e9554988 100644 --- a/packages/app/src/Components/Spotlight/SpotlightThreadModal.tsx +++ b/packages/app/src/Components/Spotlight/SpotlightThreadModal.tsx @@ -3,8 +3,8 @@ import { NostrLink, TaggedNostrEvent } from "@snort/system"; import { Thread } from "@/Components/Event/Thread"; import Modal from "@/Components/Modal/Modal"; import { SpotlightMedia } from "@/Components/Spotlight/SpotlightMedia"; -import { ThreadContextWrapper } from "@/Hooks/useThreadContext"; import getEventMedia from "@/Utils/getEventMedia"; +import { ThreadContextWrapper } from "@/Utils/Thread/ThreadContextWrapper"; interface SpotlightThreadModalProps { thread?: NostrLink; diff --git a/packages/app/src/Components/Trending/TrendingHashtags.tsx b/packages/app/src/Components/Trending/TrendingHashtags.tsx index f1def20a..593d770b 100644 --- a/packages/app/src/Components/Trending/TrendingHashtags.tsx +++ b/packages/app/src/Components/Trending/TrendingHashtags.tsx @@ -2,7 +2,7 @@ import classNames from "classnames"; import { ReactNode } from "react"; import { Link } from "react-router-dom"; -import {useLocale} from "@/Components/IntlProvider/useLocale"; +import { useLocale } from "@/Components/IntlProvider/useLocale"; import PageSpinner from "@/Components/PageSpinner"; import NostrBandApi from "@/External/NostrBand"; import useCachedFetch from "@/Hooks/useCachedFetch"; diff --git a/packages/app/src/Components/Trending/TrendingPosts.tsx b/packages/app/src/Components/Trending/TrendingPosts.tsx index 5cad43af..f0581f0a 100644 --- a/packages/app/src/Components/Trending/TrendingPosts.tsx +++ b/packages/app/src/Components/Trending/TrendingPosts.tsx @@ -7,7 +7,7 @@ import { ErrorOrOffline } from "@/Components/ErrorOrOffline"; import Note from "@/Components/Event/EventComponent"; import { DisplayAs, DisplayAsSelector } from "@/Components/Feed/DisplayAsSelector"; import ImageGridItem from "@/Components/Feed/ImageGridItem"; -import {useLocale} from "@/Components/IntlProvider/useLocale"; +import { useLocale } from "@/Components/IntlProvider/useLocale"; import PageSpinner from "@/Components/PageSpinner"; import { SpotlightThreadModal } from "@/Components/Spotlight/SpotlightThreadModal"; import ShortNote from "@/Components/Trending/ShortNote"; diff --git a/packages/app/src/Hooks/useCommunityLeaders.tsx b/packages/app/src/Hooks/useCommunityLeaders.tsx index 356a01a3..a02d1ac3 100644 --- a/packages/app/src/Hooks/useCommunityLeaders.tsx +++ b/packages/app/src/Hooks/useCommunityLeaders.tsx @@ -1,10 +1,10 @@ -import {unwrap} from "@snort/shared"; -import {EventKind, parseNostrLink} from "@snort/system"; -import {useEffect, useSyncExternalStore} from "react"; +import { unwrap } from "@snort/shared"; +import { EventKind, parseNostrLink } from "@snort/system"; +import { useEffect, useSyncExternalStore } from "react"; -import {LeadersStore} from "@/Cache/CommunityLeadersStore"; +import { LeadersStore } from "@/Cache/CommunityLeadersStore"; -import {useLinkList} from "./useLists"; +import { useLinkList } from "./useLists"; export function useCommunityLeaders() { const link = parseNostrLink(unwrap(CONFIG.communityLeaders).list); diff --git a/packages/app/src/Hooks/useRates.tsx b/packages/app/src/Hooks/useRates.tsx index b8427401..63a0873a 100644 --- a/packages/app/src/Hooks/useRates.tsx +++ b/packages/app/src/Hooks/useRates.tsx @@ -1,10 +1,10 @@ -import {bech32ToHex} from "@snort/shared"; -import {EventKind, RequestBuilder} from "@snort/system"; -import {useRequestBuilder} from "@snort/system-react"; -import {useMemo} from "react"; +import { bech32ToHex } from "@snort/shared"; +import { EventKind, RequestBuilder } from "@snort/system"; +import { useRequestBuilder } from "@snort/system-react"; +import { useMemo } from "react"; -import {getNewest} from "@/Utils"; -import {SnortPubkey} from "@/Utils/Const"; +import { getNewest } from "@/Utils"; +import { SnortPubkey } from "@/Utils/Const"; export function useRates(symbol: string, leaveOpen = true) { const sub = useMemo(() => { diff --git a/packages/app/src/Hooks/useTextTransformCache.tsx b/packages/app/src/Hooks/useTextTransformCache.tsx index b920a27d..8c8bfd0e 100644 --- a/packages/app/src/Hooks/useTextTransformCache.tsx +++ b/packages/app/src/Hooks/useTextTransformCache.tsx @@ -1,6 +1,6 @@ -import {transformText} from "@snort/system"; +import { transformText } from "@snort/system"; -import {TextCache} from "@/Cache/TextCache"; +import { TextCache } from "@/Cache/TextCache"; export function transformTextCached(id: string, content: string, tags: Array>) { if (content.length > 0) { diff --git a/packages/app/src/Pages/Layout/Header.tsx b/packages/app/src/Pages/Layout/Header.tsx index 15f127e7..66331cc0 100644 --- a/packages/app/src/Pages/Layout/Header.tsx +++ b/packages/app/src/Pages/Layout/Header.tsx @@ -5,7 +5,7 @@ import React, { useCallback, useMemo } from "react"; import { FormattedMessage } from "react-intl"; import { useLocation, useNavigate } from "react-router-dom"; -import {rootTabItems} from "@/Components/Feed/RootTabItems"; +import { rootTabItems } from "@/Components/Feed/RootTabItems"; import { RootTabs } from "@/Components/Feed/RootTabs"; import Icon from "@/Components/Icons/Icon"; import DisplayName from "@/Components/User/DisplayName"; diff --git a/packages/app/src/Pages/Root.tsx b/packages/app/src/Pages/Root.tsx deleted file mode 100644 index af9ce64d..00000000 --- a/packages/app/src/Pages/Root.tsx +++ /dev/null @@ -1,273 +0,0 @@ -import { unixNow } from "@snort/shared"; -import { NostrLink } from "@snort/system"; -import { SnortContext } from "@snort/system-react"; -import { lazy, useContext, useEffect, useMemo, useState } from "react"; -import { FormattedMessage } from "react-intl"; -import { Link, Outlet, RouteObject, useParams } from "react-router-dom"; - -import Timeline from "@/Components/Feed/Timeline"; -import TimelineFollows from "@/Components/Feed/TimelineFollows"; -import SuggestedProfiles from "@/Components/SuggestedProfiles"; -import { TaskList } from "@/Components/Tasks/TaskList"; -import TrendingHashtags from "@/Components/Trending/TrendingHashtags"; -import TrendingNotes from "@/Components/Trending/TrendingPosts"; -import { TimelineSubject } from "@/Feed/TimelineFeed"; -import useLogin from "@/Hooks/useLogin"; -import { DeckContext } from "@/Pages/DeckLayout"; -import Discover from "@/Pages/Discover"; -import HashTagsPage from "@/Pages/HashTagsPage"; -import { debounce, getCurrentRefCode, getRelayName, sha256 } from "@/Utils"; - -import { TopicsPage } from "./TopicsPage"; -const InviteModal = lazy(() => import("@/Components/Invite")); - -import useHistoryState from "@/Hooks/useHistoryState"; - -import messages from "./messages"; - -interface RelayOption { - url: string; - paid: boolean; -} - -export default function RootPage() { - const code = getCurrentRefCode(); - return ( - <> -
- -
- {code && } - - ); -} - -const FollowsHint = () => { - const { publicKey: pubKey, follows } = useLogin(); - if (follows.item?.length === 0 && pubKey) { - return ( - - - - ), - }} - /> - ); - } - return null; -}; - -export const GlobalTab = () => { - const { relays } = useLogin(); - const [relay, setRelay] = useHistoryState(undefined, "global-relay"); - const [allRelays, setAllRelays] = useHistoryState(undefined, "global-relay-options"); - const [now] = useState(unixNow()); - const system = useContext(SnortContext); - - function globalRelaySelector() { - if (!allRelays || allRelays.length === 0) return null; - - const paidRelays = allRelays.filter(a => a.paid); - const publicRelays = allRelays.filter(a => !a.paid); - return ( -
-

- -

- -
- ); - } - - useEffect(() => { - return debounce(500, () => { - const ret: RelayOption[] = []; - system.Sockets.forEach(v => { - if (v.connected) { - ret.push({ - url: v.address, - paid: v.info?.limitation?.payment_required ?? false, - }); - } - }); - ret.sort(a => (a.paid ? -1 : 1)); - - if (ret.length > 0 && !relay) { - setRelay(ret[0]); - } - setAllRelays(ret); - }); - }, [relays, relay]); - - return ( - <> - {globalRelaySelector()} - {relay && ( - - )} - - ); -}; - -export const FollowedByFriendsTab = () => { - const { publicKey } = useLogin(); - const subject: TimelineSubject = { - type: "global", - items: [], - discriminator: `followed-by-friends-${publicKey}`, - streams: true, - }; - - return ; -}; - -export const NotesTab = () => { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const deckContext = useContext(DeckContext); - - const noteOnClick = useMemo(() => { - if (deckContext) { - return ev => { - deckContext.setThread(NostrLink.fromEvent(ev)); - }; - } - return undefined; - }, [deckContext]); - - return ( - <> - - - - - ); -}; - -export const ConversationsTab = () => { - return ; -}; - -export const TagsTab = (params: { tag?: string }) => { - const { tag } = useParams(); - const t = params.tag ?? tag ?? ""; - const subject: TimelineSubject = { - type: "hashtag", - items: [t], - discriminator: `tags-${t}`, - streams: true, - }; - - return ; -}; - -const DefaultTab = () => { - const { preferences, publicKey } = useLogin(s => ({ - preferences: s.appData.item.preferences, - publicKey: s.publicKey, - })); - const tab = publicKey ? preferences.defaultRootTab ?? `notes` : `trending/notes`; - const elm = RootTabRoutes.find(a => a.path === tab)?.element; - return elm; -}; - -export const RootTabRoutes = [ - { - path: "", - element: , - }, - { - path: "global", - element: , - }, - { - path: "notes", - element: , - }, - { - path: "followed-by-friends", - element: , - }, - { - path: "conversations", - element: , - }, - { - path: "discover", - element: , - }, - { - path: "tag/:tag", - element: , - }, - { - path: "trending/notes", - element: , - }, - { - path: "trending/hashtags", - element: , - }, - { - path: "suggested", - element: ( -
- -
- ), - }, - { - path: "t/:tag", - element: , - }, - { - path: "topics", - element: , - }, -]; - -export const RootRoutes = [ - { - path: "/", - element: , - children: RootTabRoutes, - }, -] as RouteObject[]; diff --git a/packages/app/src/Pages/Root/ConversationsTab.tsx b/packages/app/src/Pages/Root/ConversationsTab.tsx new file mode 100644 index 00000000..a4589173 --- /dev/null +++ b/packages/app/src/Pages/Root/ConversationsTab.tsx @@ -0,0 +1,5 @@ +import TimelineFollows from "@/Components/Feed/TimelineFollows"; + +export const ConversationsTab = () => { + return ; +}; diff --git a/packages/app/src/Pages/Root/DefaultTab.tsx b/packages/app/src/Pages/Root/DefaultTab.tsx new file mode 100644 index 00000000..cb8cfb23 --- /dev/null +++ b/packages/app/src/Pages/Root/DefaultTab.tsx @@ -0,0 +1,12 @@ +import useLogin from "@/Hooks/useLogin"; +import { RootTabRoutes } from "@/Pages/Root/RootTabRoutes"; + +export const DefaultTab = () => { + const { preferences, publicKey } = useLogin(s => ({ + preferences: s.appData.item.preferences, + publicKey: s.publicKey, + })); + const tab = publicKey ? preferences.defaultRootTab ?? `notes` : `trending/notes`; + const elm = RootTabRoutes.find(a => a.path === tab)?.element; + return elm; +}; diff --git a/packages/app/src/Pages/Root/FollowedByFriendsTab.tsx b/packages/app/src/Pages/Root/FollowedByFriendsTab.tsx new file mode 100644 index 00000000..ea462674 --- /dev/null +++ b/packages/app/src/Pages/Root/FollowedByFriendsTab.tsx @@ -0,0 +1,15 @@ +import Timeline from "@/Components/Feed/Timeline"; +import { TimelineSubject } from "@/Feed/TimelineFeed"; +import useLogin from "@/Hooks/useLogin"; + +export const FollowedByFriendsTab = () => { + const { publicKey } = useLogin(); + const subject: TimelineSubject = { + type: "global", + items: [], + discriminator: `followed-by-friends-${publicKey}`, + streams: true, + }; + + return ; +}; diff --git a/packages/app/src/Pages/Root/GlobalTab.tsx b/packages/app/src/Pages/Root/GlobalTab.tsx new file mode 100644 index 00000000..36739827 --- /dev/null +++ b/packages/app/src/Pages/Root/GlobalTab.tsx @@ -0,0 +1,101 @@ +import { unixNow } from "@snort/shared"; +import { SnortContext } from "@snort/system-react"; +import { useContext, useEffect, useState } from "react"; +import { FormattedMessage } from "react-intl"; + +import Timeline from "@/Components/Feed/Timeline"; +import useHistoryState from "@/Hooks/useHistoryState"; +import useLogin from "@/Hooks/useLogin"; +import { debounce, getRelayName, sha256 } from "@/Utils"; + +interface RelayOption { + url: string; + paid: boolean; +} + +export const GlobalTab = () => { + const { relays } = useLogin(); + const [relay, setRelay] = useHistoryState(undefined, "global-relay"); + const [allRelays, setAllRelays] = useHistoryState(undefined, "global-relay-options"); + const [now] = useState(unixNow()); + const system = useContext(SnortContext); + + function globalRelaySelector() { + if (!allRelays || allRelays.length === 0) return null; + + const paidRelays = allRelays.filter(a => a.paid); + const publicRelays = allRelays.filter(a => !a.paid); + return ( +
+

+ +

+ +
+ ); + } + + useEffect(() => { + return debounce(500, () => { + const ret: RelayOption[] = []; + system.Sockets.forEach(v => { + if (v.connected) { + ret.push({ + url: v.address, + paid: v.info?.limitation?.payment_required ?? false, + }); + } + }); + ret.sort(a => (a.paid ? -1 : 1)); + + if (ret.length > 0 && !relay) { + setRelay(ret[0]); + } + setAllRelays(ret); + }); + }, [relays, relay]); + + return ( + <> + {globalRelaySelector()} + {relay && ( + + )} + + ); +}; diff --git a/packages/app/src/Pages/Root/NotesTab.tsx b/packages/app/src/Pages/Root/NotesTab.tsx new file mode 100644 index 00000000..36adee98 --- /dev/null +++ b/packages/app/src/Pages/Root/NotesTab.tsx @@ -0,0 +1,50 @@ +import { NostrLink } from "@snort/system"; +import { useContext, useMemo } from "react"; +import { FormattedMessage } from "react-intl"; +import { Link } from "react-router-dom"; + +import TimelineFollows from "@/Components/Feed/TimelineFollows"; +import { TaskList } from "@/Components/Tasks/TaskList"; +import useLogin from "@/Hooks/useLogin"; +import { DeckContext } from "@/Pages/DeckLayout"; +import messages from "@/Pages/messages"; + +const FollowsHint = () => { + const { publicKey: pubKey, follows } = useLogin(); + if (follows.item?.length === 0 && pubKey) { + return ( + + + + ), + }} + /> + ); + } + return null; +}; +export const NotesTab = () => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const deckContext = useContext(DeckContext); + + const noteOnClick = useMemo(() => { + if (deckContext) { + return ev => { + deckContext.setThread(NostrLink.fromEvent(ev)); + }; + } + return undefined; + }, [deckContext]); + + return ( + <> + + + + + ); +}; diff --git a/packages/app/src/Pages/Root.css b/packages/app/src/Pages/Root/Root.css similarity index 100% rename from packages/app/src/Pages/Root.css rename to packages/app/src/Pages/Root/Root.css diff --git a/packages/app/src/Pages/Root/RootRoutes.tsx b/packages/app/src/Pages/Root/RootRoutes.tsx new file mode 100644 index 00000000..bd7c0f38 --- /dev/null +++ b/packages/app/src/Pages/Root/RootRoutes.tsx @@ -0,0 +1,25 @@ +import { lazy } from "react"; +import { Outlet, RouteObject } from "react-router-dom"; + +import { RootTabRoutes } from "@/Pages/Root/RootTabRoutes"; +import { getCurrentRefCode } from "@/Utils"; + +const InviteModal = lazy(() => import("@/Components/Invite")); +export default function RootPage() { + const code = getCurrentRefCode(); + return ( + <> +
+ +
+ {code && } + + ); +} +export const RootRoutes = [ + { + path: "/", + element: , + children: RootTabRoutes, + }, +] as RouteObject[]; diff --git a/packages/app/src/Pages/Root/RootTabRoutes.tsx b/packages/app/src/Pages/Root/RootTabRoutes.tsx new file mode 100644 index 00000000..7bb183c8 --- /dev/null +++ b/packages/app/src/Pages/Root/RootTabRoutes.tsx @@ -0,0 +1,67 @@ +import SuggestedProfiles from "@/Components/SuggestedProfiles"; +import TrendingHashtags from "@/Components/Trending/TrendingHashtags"; +import TrendingNotes from "@/Components/Trending/TrendingPosts"; +import Discover from "@/Pages/Discover"; +import HashTagsPage from "@/Pages/HashTagsPage"; +import { ConversationsTab } from "@/Pages/Root/ConversationsTab"; +import { DefaultTab } from "@/Pages/Root/DefaultTab"; +import { FollowedByFriendsTab } from "@/Pages/Root/FollowedByFriendsTab"; +import { GlobalTab } from "@/Pages/Root/GlobalTab"; +import { NotesTab } from "@/Pages/Root/NotesTab"; +import { TagsTab } from "@/Pages/Root/TagsTab"; +import { TopicsPage } from "@/Pages/TopicsPage"; + +export const RootTabRoutes = [ + { + path: "", + element: , + }, + { + path: "global", + element: , + }, + { + path: "notes", + element: , + }, + { + path: "followed-by-friends", + element: , + }, + { + path: "conversations", + element: , + }, + { + path: "discover", + element: , + }, + { + path: "tag/:tag", + element: , + }, + { + path: "trending/notes", + element: , + }, + { + path: "trending/hashtags", + element: , + }, + { + path: "suggested", + element: ( +
+ +
+ ), + }, + { + path: "t/:tag", + element: , + }, + { + path: "topics", + element: , + }, +]; diff --git a/packages/app/src/Pages/Root/TagsTab.tsx b/packages/app/src/Pages/Root/TagsTab.tsx new file mode 100644 index 00000000..419b5f6d --- /dev/null +++ b/packages/app/src/Pages/Root/TagsTab.tsx @@ -0,0 +1,17 @@ +import { useParams } from "react-router-dom"; + +import Timeline from "@/Components/Feed/Timeline"; +import { TimelineSubject } from "@/Feed/TimelineFeed"; + +export const TagsTab = (params: { tag?: string }) => { + const { tag } = useParams(); + const t = params.tag ?? tag ?? ""; + const subject: TimelineSubject = { + type: "hashtag", + items: [t], + discriminator: `tags-${t}`, + streams: true, + }; + + return ; +}; diff --git a/packages/app/src/Pages/onboarding/index.tsx b/packages/app/src/Pages/onboarding/index.tsx index d37cc98d..b7513da5 100644 --- a/packages/app/src/Pages/onboarding/index.tsx +++ b/packages/app/src/Pages/onboarding/index.tsx @@ -4,7 +4,7 @@ import { Outlet, RouteObject } from "react-router-dom"; import Icon from "@/Components/Icons/Icon"; import { AllLanguageCodes } from "@/Components/IntlProvider/IntlProviderUtils"; -import {useLocale} from "@/Components/IntlProvider/useLocale"; +import { useLocale } from "@/Components/IntlProvider/useLocale"; import { Discover } from "./discover"; import { Moderation } from "./moderation"; diff --git a/packages/app/src/Pages/settings/Preferences.tsx b/packages/app/src/Pages/settings/Preferences.tsx index 934aae65..47dd9ca9 100644 --- a/packages/app/src/Pages/settings/Preferences.tsx +++ b/packages/app/src/Pages/settings/Preferences.tsx @@ -3,7 +3,7 @@ import "./Preferences.css"; import { FormattedMessage, useIntl } from "react-intl"; import { AllLanguageCodes } from "@/Components/IntlProvider/IntlProviderUtils"; -import {useLocale} from "@/Components/IntlProvider/useLocale"; +import { useLocale } from "@/Components/IntlProvider/useLocale"; import useLogin from "@/Hooks/useLogin"; import { unwrap } from "@/Utils"; import { DefaultImgProxy } from "@/Utils/Const"; diff --git a/packages/app/src/Pages/settings/Relays.tsx b/packages/app/src/Pages/settings/Relays.tsx index 13bfd27f..d6a095a6 100644 --- a/packages/app/src/Pages/settings/Relays.tsx +++ b/packages/app/src/Pages/settings/Relays.tsx @@ -1,5 +1,4 @@ import { unixNowMs, unwrap } from "@snort/shared"; -import { EventPublisher, FullRelaySettings, RelaySettings, SystemInterface } from "@snort/system"; import { useEffect, useMemo, useState } from "react"; import { FormattedMessage } from "react-intl"; @@ -8,25 +7,13 @@ import Relay from "@/Components/Relay/Relay"; import SnortApi, { RelayDistance } from "@/External/SnortApi"; import useEventPublisher from "@/Hooks/useEventPublisher"; import useLogin from "@/Hooks/useLogin"; +import { saveRelays } from "@/Pages/settings/saveRelays"; import { getCountry, getRelayName, sanitizeRelayUrl } from "@/Utils"; -import { Blasters } from "@/Utils/Const"; import { setRelays } from "@/Utils/Login"; import { formatShort } from "@/Utils/Number"; import messages from "./messages"; -export async function saveRelays( - system: SystemInterface, - publisher: EventPublisher | undefined, - relays: Array | Record, -) { - if (publisher) { - const ev = await publisher.relayList(relays); - await system.BroadcastEvent(ev); - await Promise.all(Blasters.map(a => system.WriteOnceToRelay(a, ev))); - } -} - const RelaySettingsPage = () => { const { publisher, system } = useEventPublisher(); const login = useLogin(); diff --git a/packages/app/src/Pages/settings/Routes.tsx b/packages/app/src/Pages/settings/Routes.tsx index f9fc7a70..e2bfea00 100644 --- a/packages/app/src/Pages/settings/Routes.tsx +++ b/packages/app/src/Pages/settings/Routes.tsx @@ -16,18 +16,14 @@ import Relay from "@/Pages/settings/Relays"; import { ToolsPage, ToolsPages } from "./tools"; import { WalletSettingsRoutes } from "./wallet"; -const SettingsPage = () => { - return ( -
- -
- ); -}; - export default [ { path: "/settings", - element: , + element: ( +
+ +
+ ), children: [ { path: "", diff --git a/packages/app/src/Pages/settings/saveRelays.tsx b/packages/app/src/Pages/settings/saveRelays.tsx new file mode 100644 index 00000000..548b52e2 --- /dev/null +++ b/packages/app/src/Pages/settings/saveRelays.tsx @@ -0,0 +1,15 @@ +import { EventPublisher, FullRelaySettings, RelaySettings, SystemInterface } from "@snort/system"; + +import { Blasters } from "@/Utils/Const"; + +export async function saveRelays( + system: SystemInterface, + publisher: EventPublisher | undefined, + relays: Array | Record, +) { + if (publisher) { + const ev = await publisher.relayList(relays); + await system.BroadcastEvent(ev); + await Promise.all(Blasters.map(a => system.WriteOnceToRelay(a, ev))); + } +} diff --git a/packages/app/src/Utils/Const.ts b/packages/app/src/Utils/Const.ts index 0f41dc0a..c575d0d4 100644 --- a/packages/app/src/Utils/Const.ts +++ b/packages/app/src/Utils/Const.ts @@ -164,4 +164,4 @@ export const MaxAboutLength = 1000; /* * Snort backend publishes rates */ -export const SnortPubkey = "npub1sn0rtcjcf543gj4wsg7fa59s700d5ztys5ctj0g69g2x6802npjqhjjtws"; \ No newline at end of file +export const SnortPubkey = "npub1sn0rtcjcf543gj4wsg7fa59s700d5ztys5ctj0g69g2x6802npjqhjjtws"; diff --git a/packages/app/src/Utils/Thread/ChainKey.tsx b/packages/app/src/Utils/Thread/ChainKey.tsx new file mode 100644 index 00000000..8cf320a1 --- /dev/null +++ b/packages/app/src/Utils/Thread/ChainKey.tsx @@ -0,0 +1,18 @@ +import { unwrap } from "@snort/shared"; +import { EventExt, NostrLink, TaggedNostrEvent } from "@snort/system"; + +/** + * Get the chain key as a reply event + */ +export function replyChainKey(ev: TaggedNostrEvent) { + const t = EventExt.extractThread(ev); + return t?.replyTo?.value ?? t?.root?.value; +} + +/** + * Get the chain key of this event + */ +export function chainKey(ev: TaggedNostrEvent) { + const link = NostrLink.fromEvent(ev); + return unwrap(link.toEventTag())[1]; +} diff --git a/packages/app/src/Utils/Thread/ThreadContext.tsx b/packages/app/src/Utils/Thread/ThreadContext.tsx new file mode 100644 index 00000000..8ce0c06c --- /dev/null +++ b/packages/app/src/Utils/Thread/ThreadContext.tsx @@ -0,0 +1,14 @@ +/* eslint-disable no-debugger */ +import { TaggedNostrEvent } from "@snort/system"; +import { createContext } from "react"; + +interface ThreadContext { + current: string; + root?: TaggedNostrEvent; + chains: Map>; + data: Array; + reactions: Array; + setCurrent: (i: string) => void; +} + +export const ThreadContext = createContext({} as ThreadContext); diff --git a/packages/app/src/Hooks/useThreadContext.tsx b/packages/app/src/Utils/Thread/ThreadContextWrapper.tsx similarity index 67% rename from packages/app/src/Hooks/useThreadContext.tsx rename to packages/app/src/Utils/Thread/ThreadContextWrapper.tsx index 1c33bb1b..413cc58f 100644 --- a/packages/app/src/Hooks/useThreadContext.tsx +++ b/packages/app/src/Utils/Thread/ThreadContextWrapper.tsx @@ -1,39 +1,12 @@ -/* eslint-disable no-debugger */ import { unwrap } from "@snort/shared"; -import { EventExt, NostrLink, TaggedNostrEvent, u256 } from "@snort/system"; -import { createContext, ReactNode, useMemo, useState } from "react"; +import { NostrLink, TaggedNostrEvent, u256 } from "@snort/system"; +import { ReactNode, useMemo, useState } from "react"; import { useLocation } from "react-router-dom"; import useThreadFeed from "@/Feed/ThreadFeed"; - -import useModeration from "./useModeration"; - -export interface ThreadContext { - current: string; - root?: TaggedNostrEvent; - chains: Map>; - data: Array; - reactions: Array; - setCurrent: (i: string) => void; -} - -export const ThreadContext = createContext({} as ThreadContext); - -/** - * Get the chain key as a reply event - */ -export function replyChainKey(ev: TaggedNostrEvent) { - const t = EventExt.extractThread(ev); - return t?.replyTo?.value ?? t?.root?.value; -} - -/** - * Get the chain key of this event - */ -export function chainKey(ev: TaggedNostrEvent) { - const link = NostrLink.fromEvent(ev); - return unwrap(link.toEventTag())[1]; -} +import useModeration from "@/Hooks/useModeration"; +import { chainKey, replyChainKey } from "@/Utils/Thread/ChainKey"; +import { ThreadContext } from "@/Utils/Thread/ThreadContext"; export function ThreadContextWrapper({ link, children }: { link: NostrLink; children?: ReactNode }) { const location = useLocation(); diff --git a/packages/app/src/index.tsx b/packages/app/src/index.tsx index 887cc66f..aed9d61f 100644 --- a/packages/app/src/index.tsx +++ b/packages/app/src/index.tsx @@ -29,7 +29,8 @@ import NostrLinkHandler from "@/Pages/NostrLinkHandler"; import NotificationsPage from "@/Pages/Notifications/Notifications"; import { OnboardingRoutes } from "@/Pages/onboarding"; import ProfilePage from "@/Pages/Profile/ProfilePage"; -import { RootRoutes, RootTabRoutes } from "@/Pages/Root"; +import { RootRoutes } from "@/Pages/Root/RootRoutes"; +import { RootTabRoutes } from "@/Pages/Root/RootTabRoutes"; import SearchPage from "@/Pages/SearchPage"; import SettingsRoutes from "@/Pages/settings/Routes"; import { SubscribeRoutes } from "@/Pages/subscribe";