From 16e435cdfeea852858f6eed647f6b7fce5d4f882 Mon Sep 17 00:00:00 2001 From: Silberengel Date: Sat, 21 Mar 2026 09:17:38 +0100 Subject: [PATCH] more refactoring --- README.md | 2 +- src/PageManager.tsx | 104 +-- src/components/ContentPreview/ZapPreview.tsx | 38 +- .../Explore/ExploreFavoriteRelays.tsx | 2 +- .../KeyboardShortcutsHelp/index.tsx | 324 ++++---- src/components/KindFilter/index.tsx | 10 +- src/components/Note/Zap.tsx | 69 +- src/components/NoteBoostBadges/index.tsx | 61 ++ src/components/NoteCard/RepostDescription.tsx | 2 +- src/components/NoteInteractions/Tabs.tsx | 14 +- src/components/NoteInteractions/index.tsx | 7 +- src/components/NoteStats/RepostButton.tsx | 14 +- src/components/NoteStats/index.tsx | 2 +- .../NotificationItem/RepostNotification.tsx | 2 +- src/components/Profile/ProfileFeed.tsx | 2 +- src/components/RepostList/index.tsx | 2 +- src/components/Sidebar/AccountButton.tsx | 6 +- .../KeyboardShortcutsHelpSidebarButton.tsx | 2 +- src/components/Sidebar/index.tsx | 2 +- src/components/TrendingNotes/index.tsx | 760 ++++-------------- src/constants.ts | 2 +- src/i18n/locales/ar.ts | 13 +- src/i18n/locales/de.ts | 26 +- src/i18n/locales/en.ts | 26 +- src/i18n/locales/es.ts | 13 +- src/i18n/locales/fa.ts | 13 +- src/i18n/locales/fr.ts | 13 +- src/i18n/locales/hi.ts | 13 +- src/i18n/locales/it.ts | 13 +- src/i18n/locales/ja.ts | 13 +- src/i18n/locales/ko.ts | 13 +- src/i18n/locales/pl.ts | 13 +- src/i18n/locales/pt-BR.ts | 13 +- src/i18n/locales/pt-PT.ts | 13 +- src/i18n/locales/ru.ts | 13 +- src/i18n/locales/th.ts | 13 +- src/i18n/locales/zh.ts | 13 +- src/pages/primary/ExplorePage/index.tsx | 147 ++-- src/pages/primary/MePage/index.tsx | 1 - .../primary/SettingsPrimaryPage/index.tsx | 2 +- src/pages/secondary/NotePage/index.tsx | 5 +- src/services/local-storage.service.ts | 25 +- src/vite-env.d.ts | 5 + 43 files changed, 741 insertions(+), 1105 deletions(-) create mode 100644 src/components/NoteBoostBadges/index.tsx diff --git a/README.md b/README.md index f8745370..95828ac4 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ High-level changes versus a “stock” Jumble-style layout: ### Explore quality-of-life -- **Relay URL search** in the Explore title bar: paste `wss://…` or a host, submit, and open the relay page with the same navigation as the relay cards. While typing, **suggestions** come from the **NIP-66 monitoring (public lively) list** on partial or full URL/host matches; you can still submit any URL the app does not know. +- **Search for Relays** on Explore (below Favorite Relays): paste `wss://…` or a host, submit, and open the relay page with the same navigation as the relay cards. While typing, **suggestions** come from the **NIP-66 monitoring (public lively) list** on partial or full URL/host matches; you can still submit any URL the app does not know. ### Other diff --git a/src/PageManager.tsx b/src/PageManager.tsx index 3a37bd9d..09201de9 100644 --- a/src/PageManager.tsx +++ b/src/PageManager.tsx @@ -622,10 +622,7 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) { const [drawerNoteId, setDrawerNoteId] = useState(null) const [panelMode, setPanelMode] = useState<'single' | 'double'>(() => storage.getPanelMode()) const navigationCounterRef = useRef(0) - const savedFeedStateRef = useRef>(new Map()) + const savedFeedStateRef = useRef>(new Map()) const currentTabStateRef = useRef>(new Map()) // Track current tab state for each page const currentPageProps = useMemo((): object | undefined => { @@ -640,20 +637,14 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) { // Get current tab state from ref (updated by components via events) const currentTab = currentTabStateRef.current.get(currentPrimaryPage) - - // Get trending tab if on search page - const trendingTab = currentTabStateRef.current.get('search') as 'relays' | 'hashtags' | 'calendar' | undefined - - // Save state (tab, trending) if any exists - if (currentTab || trendingTab) { - logger.info('PageManager: Saving page state', { - page: currentPrimaryPage, - tab: currentTab, - trendingTab + + if (currentTab) { + logger.info('PageManager: Saving page state', { + page: currentPrimaryPage, + tab: currentTab }) - savedFeedStateRef.current.set(currentPrimaryPage, { - tab: currentTab, - trendingTab + savedFeedStateRef.current.set(currentPrimaryPage, { + tab: currentTab }) } } @@ -684,19 +675,6 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) { })) currentTabStateRef.current.set(savedPrimaryPage, savedFeedState.tab) } - - // Restore trending tab for search page (map legacy 'nostr' to 'relays') - if (savedFeedState?.trendingTab && savedPrimaryPage === 'search') { - const tab = (savedFeedState.trendingTab as string) === 'nostr' ? 'relays' : savedFeedState.trendingTab - logger.info('PageManager: Restoring trending tab', { - page: savedPrimaryPage, - trendingTab: tab - }) - window.dispatchEvent(new CustomEvent('restorePageTab', { - detail: { page: 'search', tab } - })) - currentTabStateRef.current.set('search', tab) - } } } @@ -1149,19 +1127,6 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) { // Update ref immediately currentTabStateRef.current.set(currentPrimaryPage, savedFeedState.tab) } - - // Restore trending tab for search page - if (savedFeedState?.trendingTab && currentPrimaryPage === 'search') { - const tab = (savedFeedState.trendingTab as string) === 'nostr' ? 'relays' : savedFeedState.trendingTab - logger.info('PageManager: Browser back - Restoring trending tab', { - page: currentPrimaryPage, - trendingTab: tab - }) - window.dispatchEvent(new CustomEvent('restorePageTab', { - detail: { page: 'search', tab } - })) - currentTabStateRef.current.set('search', tab) - } } }, [secondaryStack.length, currentPrimaryPage]) @@ -1215,15 +1180,13 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) { // Save tab state before navigating const currentTab = currentTabStateRef.current.get(currentPrimaryPage) - const trendingTab = currentTabStateRef.current.get('search') as 'relays' | 'hashtags' | 'calendar' | undefined - - if (currentPrimaryPage && (currentTab || trendingTab)) { - logger.info('PageManager: Desktop - Saving page state', { - page: currentPrimaryPage, - tab: currentTab, - trendingTab + + if (currentPrimaryPage && currentTab) { + logger.info('PageManager: Desktop - Saving page state', { + page: currentPrimaryPage, + tab: currentTab }) - savedFeedStateRef.current.set(currentPrimaryPage, { tab: currentTab, trendingTab }) + savedFeedStateRef.current.set(currentPrimaryPage, { tab: currentTab }) } setSecondaryStack((prevStack) => { @@ -1289,19 +1252,6 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) { })) currentTabStateRef.current.set(currentPrimaryPage, savedFeedState.tab) } - - // Restore trending tab for search page - if (savedFeedState?.trendingTab && currentPrimaryPage === 'search') { - const tab = (savedFeedState.trendingTab as string) === 'nostr' ? 'relays' : savedFeedState.trendingTab - logger.info('PageManager: Desktop - Restoring trending tab', { - page: currentPrimaryPage, - trendingTab: tab - }) - window.dispatchEvent(new CustomEvent('restorePageTab', { - detail: { page: 'search', tab } - })) - currentTabStateRef.current.set('search', tab) - } } else if (secondaryStack.length > 1) { // Pop from stack directly instead of using history.go(-1) // This ensures the stack is updated immediately @@ -1347,19 +1297,6 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) { })) currentTabStateRef.current.set(currentPrimaryPage, savedFeedState.tab) } - - // Restore trending tab for search page - if (savedFeedState?.trendingTab && currentPrimaryPage === 'search') { - const tab = (savedFeedState.trendingTab as string) === 'nostr' ? 'relays' : savedFeedState.trendingTab - logger.info('PageManager: Mobile/Single-pane - Restoring trending tab', { - page: currentPrimaryPage, - trendingTab: tab - }) - window.dispatchEvent(new CustomEvent('restorePageTab', { - detail: { page: 'search', tab } - })) - currentTabStateRef.current.set('search', tab) - } return } @@ -1378,19 +1315,6 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) { })) currentTabStateRef.current.set(currentPrimaryPage, savedFeedState.tab) } - - // Restore trending tab for search page - if (savedFeedState?.trendingTab && currentPrimaryPage === 'search') { - const tab = (savedFeedState.trendingTab as string) === 'nostr' ? 'relays' : savedFeedState.trendingTab - logger.info('PageManager: Desktop - Restoring trending tab', { - page: currentPrimaryPage, - trendingTab: tab - }) - window.dispatchEvent(new CustomEvent('restorePageTab', { - detail: { page: 'search', tab } - })) - currentTabStateRef.current.set('search', tab) - } } else if (secondaryStack.length > 1) { // Pop to previous page (e.g. from /settings/general back to /settings) so Back/Close return to the list instead of closing the panel setSecondaryStack((prevStack) => { diff --git a/src/components/ContentPreview/ZapPreview.tsx b/src/components/ContentPreview/ZapPreview.tsx index 329b649f..2c5c091e 100644 --- a/src/components/ContentPreview/ZapPreview.tsx +++ b/src/components/ContentPreview/ZapPreview.tsx @@ -15,7 +15,7 @@ export default function ZapPreview({ event, className }: { event: Event; classNa if (!zapInfo || !zapInfo.senderPubkey || !zapInfo.amount) { return ( -
+
[{t('Invalid zap receipt')}]
) @@ -24,26 +24,32 @@ export default function ZapPreview({ event, className }: { event: Event; classNa const { senderPubkey, recipientPubkey, amount, comment } = zapInfo return ( -
- -
-
- - {t('zapped')} +
+ +
+
+ + {t('zapped')} {recipientPubkey && recipientPubkey !== senderPubkey && ( - + )}
-
- {formatAmount(amount)} {t('sats')} -
- {comment && ( -
+ {comment ? ( +

{comment} -

- )} +

+ ) : null} +
+ {formatAmount(amount)} + {t('sats')} +
{targetEvent && ( -
+
{t('on note')} {targetEvent.id.substring(0, 8)}...
)} diff --git a/src/components/Explore/ExploreFavoriteRelays.tsx b/src/components/Explore/ExploreFavoriteRelays.tsx index 37c3270b..a8b5d785 100644 --- a/src/components/Explore/ExploreFavoriteRelays.tsx +++ b/src/components/Explore/ExploreFavoriteRelays.tsx @@ -105,7 +105,7 @@ export default function ExploreFavoriteRelays() { {t('Using app default relays')} ) : null}
-
+
{urls.map((url) => (
diff --git a/src/components/KeyboardShortcutsHelp/index.tsx b/src/components/KeyboardShortcutsHelp/index.tsx index 6d5adf2c..0f86bac3 100644 --- a/src/components/KeyboardShortcutsHelp/index.tsx +++ b/src/components/KeyboardShortcutsHelp/index.tsx @@ -1,3 +1,4 @@ +import MarkdownArticle from '@/components/Note/MarkdownArticle/MarkdownArticle' import { Button } from '@/components/ui/button' import { Dialog, @@ -6,11 +7,14 @@ import { DialogHeader, DialogTitle } from '@/components/ui/dialog' +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' +import { createFakeEvent } from '@/lib/event' import { isRadixDialogOpen, OPEN_NEW_POST_SHORTCUT_KEY, shouldIgnoreKeyboardShortcutEvent } from '@/lib/keyboard-shortcuts' +import { cn } from '@/lib/utils' import postEditorService from '@/services/post-editor.service' import { CircleHelp } from 'lucide-react' import { @@ -23,6 +27,7 @@ import { type ReactNode } from 'react' import { useTranslation } from 'react-i18next' +import readmeMarkdown from '../../../README.md?raw' type KeyboardShortcutsHelpContextValue = { openHelp: () => void @@ -55,6 +60,162 @@ function KbdRow({ keys, label }: { keys: ReactNode; label: string }) { ) } +function ShortcutsPanel() { + const { t } = useTranslation() + return ( +
+

{t('shortcuts.intro')}

+
+

+ {t('shortcuts.sectionApp')} +

+
+ + ? + {t('shortcuts.or')} + F1 + + } + /> + + Shift + + + Alt + + + F + + } + /> + + Shift + + + Alt + + + S + + } + /> + + Shift + + + Alt + + + N + + } + /> +
+
+
+

+ {t('shortcuts.sectionSearch')} +

+
+ + + + {t('shortcuts.then')} + Enter + + } + /> + Esc} /> +
+
+
+

+ {t('shortcuts.sectionStandard')} +

+
+ + Tab + {t('shortcuts.or')} + Shift + + + Tab + + } + /> + + Enter + {t('shortcuts.or')} + Space + + } + /> + Esc} /> + + + + PgUp + PgDn + Home + End + + } + /> + + Alt + + + + + } + /> +
+
+
+ ) +} + +function ReadmeOverviewPanel({ className }: { className?: string }) { + const readmeEvent = useMemo( + () => + createFakeEvent({ + id: '0'.repeat(64), + pubkey: '0'.repeat(64), + content: readmeMarkdown, + created_at: 0, + kind: 1, + tags: [], + sig: '0'.repeat(128) + }), + [] + ) + + return ( +
+ +
+ ) +} + export function KeyboardShortcutsHelpProvider({ children }: { children: ReactNode }) { const [open, setOpen] = useState(false) const openHelp = useCallback(() => setOpen(true), []) @@ -103,144 +264,29 @@ export function KeyboardShortcutsHelpProvider({ children }: { children: ReactNod {children} - - - {t('shortcuts.title')} - {t('shortcuts.intro')} + + + {t('help.title')} + {t('shortcuts.intro')} -
-
-

- {t('shortcuts.sectionApp')} -

-
- - ? - {t('shortcuts.or')} - F1 - - } - /> - - Shift - + - Alt - + - F - - } - /> - - Shift - + - Alt - + - S - - } - /> - - Shift - + - Alt - + - N - - } - /> -
-
-
-

- {t('shortcuts.sectionSearch')} -

-
- - - - {t('shortcuts.then')} - Enter - - } - /> - Esc} - /> -
-
-
-

- {t('shortcuts.sectionStandard')} -

-
- - Tab - {t('shortcuts.or')} - Shift - + - Tab - - } - /> - - Enter - {t('shortcuts.or')} - Space - - } - /> - Esc} - /> - - - - PgUp - PgDn - Home - End - - } - /> - - Alt - + - - - } - /> -
-
-
+ + + {t('help.tabShortcuts')} + {t('help.tabOverview')} + + + + + + + +
@@ -257,8 +303,8 @@ export function KeyboardShortcutsHelpButton() { variant="ghost" size="titlebar-icon" onClick={() => openHelp()} - title={t('shortcuts.title')} - aria-label={t('shortcuts.title')} + title={t('help.title')} + aria-label={t('help.title')} > diff --git a/src/components/KindFilter/index.tsx b/src/components/KindFilter/index.tsx index 8f9f9431..792c0751 100644 --- a/src/components/KindFilter/index.tsx +++ b/src/components/KindFilter/index.tsx @@ -16,9 +16,7 @@ const KIND_1 = kinds.ShortTextNote const KIND_1111 = ExtendedKind.COMMENT const KIND_FILTER_OPTIONS = [ - { kindGroup: [kinds.Repost], label: 'Reposts' }, { kindGroup: [kinds.LongFormArticle], label: 'Articles' }, - { kindGroup: [ExtendedKind.PUBLICATION], label: 'Publications' }, { kindGroup: [ExtendedKind.WIKI_ARTICLE, ExtendedKind.WIKI_ARTICLE_MARKDOWN], label: 'Wiki Articles' }, { kindGroup: [kinds.Highlights], label: 'Highlights' }, { kindGroup: [ExtendedKind.POLL], label: 'Polls' }, @@ -212,7 +210,13 @@ export default function KindFilter({ variant="secondary" onClick={() => { setTemporaryShowKinds( - SUPPORTED_KINDS.filter((k) => k !== kinds.Repost && k !== KIND_1 && k !== KIND_1111) + SUPPORTED_KINDS.filter( + (k) => + k !== kinds.Repost && + k !== ExtendedKind.PUBLICATION && + k !== KIND_1 && + k !== KIND_1111 + ) ) setTemporaryShowKind1OPs(true) setTemporaryShowKind1Replies(true) diff --git a/src/components/Note/Zap.tsx b/src/components/Note/Zap.tsx index 1b30f61d..82cde8bf 100644 --- a/src/components/Note/Zap.tsx +++ b/src/components/Note/Zap.tsx @@ -31,7 +31,12 @@ export default function Zap({ event, className }: { event: Event; className?: st if (!zapInfo || !zapInfo.senderPubkey || !zapInfo.amount) { return ( -
+
[{t('Invalid zap receipt')}]
) @@ -40,7 +45,7 @@ export default function Zap({ event, className }: { event: Event; className?: st // Determine if this is an event zap or profile zap const isEventZap = targetEvent || zapInfo?.eventId const isProfileZap = !isEventZap && zapInfo?.recipientPubkey - + // For event zaps, we need to determine the recipient from the zapped event const actualRecipientPubkey = useMemo(() => { if (isEventZap && targetEvent) { @@ -53,20 +58,18 @@ export default function Zap({ event, className }: { event: Event; className?: st return undefined }, [isEventZap, isProfileZap, targetEvent, zapInfo?.recipientPubkey]) - if (!zapInfo || !zapInfo.senderPubkey || !zapInfo.amount) { - return ( -
- [{t('Invalid zap receipt')}] -
- ) - } - const { senderPubkey, recipientPubkey, amount, comment } = zapInfo return ( -
+
{/* Zapped note/profile link in bottom-right corner */} - -
- -
-
+ +
+ +
+
- - {t('zapped')} + + {t('zapped')} {recipientPubkey && recipientPubkey !== senderPubkey && ( <> - + )}
-
- + + {comment ? ( +
+

+ {comment} +

+
+ ) : null} + +
+ {formatAmount(amount)} - - {t('sats')} - + {t('sats')}
- {comment && ( -
- {comment} -
- )}
diff --git a/src/components/NoteBoostBadges/index.tsx b/src/components/NoteBoostBadges/index.tsx new file mode 100644 index 00000000..d2139ecd --- /dev/null +++ b/src/components/NoteBoostBadges/index.tsx @@ -0,0 +1,61 @@ +import { useNoteStatsById } from '@/hooks/useNoteStatsById' +import { shouldHideInteractions } from '@/lib/event-filtering' +import { cn } from '@/lib/utils' +import { ExtendedKind } from '@/constants' +import { useUserTrust } from '@/providers/UserTrustProvider' +import { Event } from 'nostr-tools' +import { useMemo } from 'react' +import { useTranslation } from 'react-i18next' +import UserAvatar from '../UserAvatar' + +const MAX_VISIBLE = 28 + +/** + * Small avatar strip of users who boosted (kind 6) the note — shown under the OP on the note page. + */ +export default function NoteBoostBadges({ event, className }: { event: Event; className?: string }) { + const { t } = useTranslation() + const { hideUntrustedInteractions, isUserTrusted } = useUserTrust() + const noteStats = useNoteStatsById(event.id) + + const boosters = useMemo(() => { + if (event.kind === ExtendedKind.DISCUSSION) return [] + return (noteStats?.reposts ?? []) + .filter((r) => !hideUntrustedInteractions || isUserTrusted(r.pubkey)) + .sort((a, b) => b.created_at - a.created_at) + }, [noteStats, event.kind, hideUntrustedInteractions, isUserTrusted]) + + if (shouldHideInteractions(event) || boosters.length === 0) { + return null + } + + const visible = boosters.slice(0, MAX_VISIBLE) + const overflow = boosters.length - visible.length + + return ( +
+ {visible.map((r, i) => ( +
0 && '-ml-2')} + style={{ zIndex: visible.length - i }} + > + +
+ ))} + {overflow > 0 ? ( + + +{overflow} + + ) : null} +
+ ) +} diff --git a/src/components/NoteCard/RepostDescription.tsx b/src/components/NoteCard/RepostDescription.tsx index e063ccd3..237932c5 100644 --- a/src/components/NoteCard/RepostDescription.tsx +++ b/src/components/NoteCard/RepostDescription.tsx @@ -17,7 +17,7 @@ export default function RepostDescription({
-
{t('reposted')}
+
{t('boosted')}
) } diff --git a/src/components/NoteInteractions/Tabs.tsx b/src/components/NoteInteractions/Tabs.tsx index 7609ce42..897621bb 100644 --- a/src/components/NoteInteractions/Tabs.tsx +++ b/src/components/NoteInteractions/Tabs.tsx @@ -2,11 +2,10 @@ import { cn } from '@/lib/utils' import { useTranslation } from 'react-i18next' import { useRef, useEffect, useState } from 'react' -export type TTabValue = 'replies' | 'quotes' | 'reactions' | 'reposts' | 'zaps' +export type TTabValue = 'replies' | 'quotes' | 'reactions' | 'zaps' const TABS = [ { value: 'replies', label: 'Replies' }, { value: 'zaps', label: 'Zaps' }, - { value: 'reposts', label: 'Reposts' }, { value: 'reactions', label: 'Reactions' }, { value: 'quotes', label: 'Quotes' } ] as { value: TTabValue; label: string }[] @@ -14,20 +13,21 @@ const TABS = [ export function Tabs({ selectedTab, onTabChange, - hideRepostsAndQuotes = false + hideQuotesForDiscussion = false }: { selectedTab: TTabValue onTabChange: (tab: TTabValue) => void - hideRepostsAndQuotes?: boolean + /** Hide the quotes tab on discussion threads */ + hideQuotesForDiscussion?: boolean }) { const { t } = useTranslation() const tabRefs = useRef<(HTMLDivElement | null)[]>([]) const containerRef = useRef(null) const [indicatorStyle, setIndicatorStyle] = useState({ width: 0, left: 0, top: 0 }) - // Filter tabs based on hideRepostsAndQuotes - const visibleTabs = hideRepostsAndQuotes - ? TABS.filter(tab => tab.value !== 'reposts' && tab.value !== 'quotes') + // Filter tabs based on hideBoostsAndQuotes + const visibleTabs = hideBoostsAndQuotes + ? TABS.filter((tab) => tab.value !== 'boosts' && tab.value !== 'quotes') : TABS useEffect(() => { diff --git a/src/components/NoteInteractions/index.tsx b/src/components/NoteInteractions/index.tsx index 5c20ade1..dc5cc6ca 100644 --- a/src/components/NoteInteractions/index.tsx +++ b/src/components/NoteInteractions/index.tsx @@ -7,7 +7,6 @@ import HideUntrustedContentButton from '../HideUntrustedContentButton' import QuoteList from '../QuoteList' import ReactionList from '../ReactionList' import ReplyNoteList from '../ReplyNoteList' -import RepostList from '../RepostList' import ZapList from '../ZapList' import { Tabs, TTabValue } from './Tabs' import ReplySort, { ReplySortOption } from './ReplySort' @@ -40,8 +39,8 @@ export default function NoteInteractions({ case 'reactions': list = break - case 'reposts': - if (isDiscussion) return null // Hide reposts for discussions + case 'boosts': + if (isDiscussion) return null // Hide boosts for discussions list = break case 'zaps': @@ -55,7 +54,7 @@ export default function NoteInteractions({ <>
- +
{type === 'replies' && isDiscussion && ( diff --git a/src/components/NoteStats/RepostButton.tsx b/src/components/NoteStats/RepostButton.tsx index 62ce8719..620ffdb9 100644 --- a/src/components/NoteStats/RepostButton.tsx +++ b/src/components/NoteStats/RepostButton.tsx @@ -69,16 +69,16 @@ export default function RepostButton({ event, hideCount = false }: { event: Even successCount: (evt as any).relayStatuses.filter((s: any) => s.success).length, totalCount: (evt as any).relayStatuses.length }, { - message: t('Repost published'), + message: t('Boost published'), duration: 4000 }) } else { - showSimplePublishSuccess(t('Repost published')) + showSimplePublishSuccess(t('Boost published')) } noteStatsService.updateNoteStatsByEvents([evt]) } catch (error) { - logger.error('Repost failed', { error, eventId: event.id }) + logger.error('Boost failed', { error, eventId: event.id }) } finally { setReposting(false) clearTimeout(timer) @@ -92,7 +92,7 @@ export default function RepostButton({ event, hideCount = false }: { event: Even 'flex gap-1 items-center enabled:hover:text-lime-500 px-3 h-full', hasReposted ? 'text-lime-500' : 'text-muted-foreground' )} - title={t('Repost')} + title={t('Boost')} onClick={() => { if (isSmallScreen) { setIsDrawerOpen(true) @@ -120,7 +120,7 @@ export default function RepostButton({ event, hideCount = false }: { event: Even setIsDrawerOpen(false)} /> - Repost + {t('Boost')}
- - {/* Second row controls for relays / hashtags (calendar has no sort – ordered by datetime) */} - {(activeTab === 'relays' || activeTab === 'hashtags') && ( -
- {/* Sorting controls - not shown for hashtags tab */} - {activeTab !== 'hashtags' && ( -
- Sort: -
- - - - -
-
- )} - - -
- )} - - - - {/* Popular hashtag buttons for hashtags tab */} - {activeTab === 'hashtags' && hashtagFilter === 'popular' && popularHashtags.length > 0 && ( -
- Popular hashtags: -
- {popularHashtags.map((hashtag) => ( - - ))} -
-
- )}
- - {/* Show loading message for relays tab when cache is loading */} - {activeTab === 'relays' && cacheLoading && cacheEvents.length === 0 && ( -
- Loading trending notes from your relays... -
- )} - {/* Show loading message for calendar tab */} - {activeTab === 'calendar' && calendarLoading && calendarEvents.length === 0 && ( -
- {t('Loading calendar events...')} + + {cacheLoading && cacheEvents.length === 0 ? ( +
+ {t('Loading trending notes from your relays...')}
- )} - {activeTab === 'calendar' && !calendarLoading && calendarEvents.length === 0 && ( -
- {t('No calendar events found')} + ) : null} + + {relaysFilteredEvents.map((event) => ( + + ))} + + {cacheLoading || showCount < relaysFilteredEventsAll.length ? ( +
+
+ ) : ( +
{t('no more notes')}
)} - - {activeTab === 'calendar' - ? calendarEventsByMonth.monthKeys.map((monthKey) => { - const eventsInMonth = calendarEventsByMonth.byMonth.get(monthKey) ?? [] - const [y, m] = monthKey.split('-') - const monthLabel = new Date(parseInt(y, 10), parseInt(m, 10) - 1, 1).toLocaleDateString(undefined, { - month: 'long', - year: 'numeric' - }) - return ( -
-

- {monthLabel} -

-
- {eventsInMonth.map((event) => ( - - ))} -
-
- ) - }) - : filteredEvents.map((event) => ( - - ))} - - {(() => { - const actualAvailableLength = activeTab === 'calendar' ? calendarEvents.length : relaysFilteredEventsAll.length - const isLoading = activeTab === 'relays' ? cacheLoading : activeTab === 'calendar' ? calendarLoading : false - const calendarShowingAll = activeTab === 'calendar' && !calendarLoading - - const shouldShowLoading = - isLoading || - (activeTab !== 'calendar' && showCount < actualAvailableLength) - - if (shouldShowLoading) { - return ( -
- -
- ) - } - if (calendarShowingAll && calendarEvents.length > 0) { - return ( -
- {t('Calendar events in the next {{count}} months', { count: CALENDAR_MONTHS_AHEAD })} -
- ) - } - return
{t('no more notes')}
- })()}
) } diff --git a/src/constants.ts b/src/constants.ts index 0b1ee37a..b524081e 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -267,7 +267,7 @@ export const SUPPORTED_KINDS = [ ExtendedKind.APPLICATION_HANDLER_INFO ] -/** Kinds for profile feed and favorites-style feeds: supported kinds except reposts, publications, publication content, NIP-89 handlers. */ +/** Kinds for profile feed and favorites-style feeds: supported kinds except boosts (kind 6), publications, publication content, NIP-89 handlers. */ export const PROFILE_FEED_KINDS = SUPPORTED_KINDS.filter( (k) => k !== kinds.Repost && diff --git a/src/i18n/locales/ar.ts b/src/i18n/locales/ar.ts index 63f83fe2..0f7528b8 100644 --- a/src/i18n/locales/ar.ts +++ b/src/i18n/locales/ar.ts @@ -14,7 +14,7 @@ export default { Logout: 'تسجيل الخروج', Following: 'المتابعون', followings: 'المتابعين', - reposted: 'أُعيد نشره', + boosted: 'قوّى', 'just now': 'الآن', 'n minutes ago': 'منذ {{n}} دقيقة', 'n m': '{{n}} دقيقة', @@ -41,7 +41,8 @@ export default { 'Failed to post': 'فشل النشر', 'Post successful': 'تم النشر بنجاح', 'Your post has been published': 'تم نشر مشاركتك', - Repost: 'إعادة النشر', + Boost: 'Boost', + 'Boost published': 'نُشر الـ Boost', Quote: 'اقتباس', 'Copy event ID': 'نسخ معرف الحدث', 'Copy user ID': 'نسخ معرف المستخدم', @@ -333,9 +334,9 @@ export default { 'No reactions yet': 'لا توجد تفاعلات بعد', 'No more zaps': 'لا توجد مزيد من الزابس', 'No zaps yet': 'لا توجد زابس بعد', - 'No more reposts': 'لا توجد مزيد من إعادة النشر', - 'No reposts yet': 'لا توجد إعادة نشر بعد', - Reposts: 'إعادة النشر', + 'No more boosts': 'لا مزيد من الـ Boosts', + 'No boosts yet': 'لا توجد Boosts بعد', + Boosts: 'Boosts', FollowListNotFoundConfirmation: 'لم يتم العثور على قائمة المتابعة. هل تريد إنشاء واحدة جديدة؟ إذا كنت قد تابعت مستخدمين من قبل، يرجى عدم التأكيد لأن هذه العملية ستؤدي إلى فقدان قائمة المتابعة السابقة.', MuteListNotFoundConfirmation: @@ -380,7 +381,7 @@ export default { 'quoted your note': 'اقتبس ملاحظتك', 'voted in your poll': 'صوت في استطلاعك', 'reacted to your note': 'تفاعل مع ملاحظتك', - 'reposted your note': 'أعاد نشر ملاحظتك', + 'boosted your note': 'قوّى ملاحظتك', 'zapped your note': 'زاب ملاحظتك', 'zapped you': 'زابك', 'Mark as read': 'تعليم كمقروء', diff --git a/src/i18n/locales/de.ts b/src/i18n/locales/de.ts index a2574d92..7273d475 100644 --- a/src/i18n/locales/de.ts +++ b/src/i18n/locales/de.ts @@ -8,13 +8,14 @@ export default { Home: 'Startseite', 'Relay settings': 'Relay-Einstellungen', Settings: 'Einstellungen', + 'Account menu': 'Kontomenü', SidebarRelays: 'Relays', Refresh: 'Aktualisieren', Profile: 'Profil', Logout: 'Abmelden', Following: 'Folgende', followings: 'Folgekonten', - reposted: 'erneut gepostet', + boosted: 'geboostet', 'just now': 'gerade eben', 'n minutes ago': 'vor {{n}} Minuten', 'n m': 'vor {{n}}m', @@ -48,7 +49,8 @@ export default { 'Failed to post': 'Posten fehlgeschlagen', 'Post successful': 'Beitrag erfolgreich', 'Your post has been published': 'Dein Beitrag wurde veröffentlicht', - Repost: 'Erneut posten', + Boost: 'Boost', + 'Boost published': 'Boost veröffentlicht', Quote: 'Zitat', 'Copy event ID': 'Ereignis-ID kopieren', 'Copy user ID': 'Benutzer-ID kopieren', @@ -314,6 +316,7 @@ export default { 'no more replies': 'keine weiteren Antworten', 'Relay sets': 'Relay-Sets', 'Favorite Relays': 'Lieblings-Relays', + 'Search for Relays': 'Relays suchen', 'Using app default relays': 'Standard-Relays der App', "Following's Favorites": 'Favoriten der Folgenden', 'no more relays': 'keine weiteren Relays', @@ -493,9 +496,9 @@ export default { 'No reactions yet': 'Noch keine Reaktionen', 'No more zaps': 'Keine weiteren Zaps', 'No zaps yet': 'Noch keine Zaps', - 'No more reposts': 'Keine weiteren Reposts', - 'No reposts yet': 'Noch keine Reposts', - Reposts: 'Reposts', + 'No more boosts': 'Keine weiteren Boosts', + 'No boosts yet': 'Noch keine Boosts', + Boosts: 'Boosts', FollowListNotFoundConfirmation: 'Folgeliste nicht gefunden. Möchten Sie eine neue erstellen? Wenn Sie zuvor Benutzer gefolgt haben, bestätigen Sie bitte NICHT, da diese Operation dazu führt, dass Sie Ihre vorherige Folgeliste verlieren.', MuteListNotFoundConfirmation: @@ -548,7 +551,7 @@ export default { 'quoted your note': 'hat Ihre Notiz zitiert', 'voted in your poll': 'hat in Ihrer Umfrage abgestimmt', 'reacted to your note': 'hat auf Ihre Notiz reagiert', - 'reposted your note': 'hat Ihre Notiz geteilt', + 'boosted your note': 'hat Ihre Notiz geboostet', 'zapped your note': 'hat Ihre Notiz gezappt', 'zapped you': 'hat Sie gezappt', 'Mark as read': 'Als gelesen markieren', @@ -594,6 +597,14 @@ export default { '{{count}} relays': '{{count}} Relays', 'Republishing...': 'Wird erneut veröffentlicht...', 'Trending Notes': 'Trendende Notizen', + 'Trending on Your Favorite Relays': 'Trending auf deinen Lieblings-Relays', + 'Trending on the Default Relays': 'Trending auf den Standard-Relays', + 'Loading trending notes from your relays...': 'Trendende Notizen werden geladen …', + Sort: 'Sortierung', + newest: 'neueste', + oldest: 'älteste', + 'most popular': 'beliebteste', + 'least popular': 'am wenigsten beliebt', 'Connected to': 'Verbunden mit', 'Disconnect Wallet': 'Wallet trennen', 'Are you absolutely sure?': 'Bist du dir absolut sicher?', @@ -620,6 +631,9 @@ export default { 'Richte deine Wallet ein, um Sats zu senden und zu empfangen!', 'Set up': 'Einrichten', + 'help.title': 'Hilfe', + 'help.tabShortcuts': 'Tastenkürzel', + 'help.tabOverview': 'App-Übersicht', 'shortcuts.title': 'Tastenkürzel', 'shortcuts.intro': 'Kürzel für diese App und übliche Bedienung. Kombinationen: Umschalt+Alt+Taste (unter macOS: Umschalt+Wahltaste); die Reihenfolge der Modifier beim Drücken ist egal.', diff --git a/src/i18n/locales/en.ts b/src/i18n/locales/en.ts index 3e6d9f8e..98a64a80 100644 --- a/src/i18n/locales/en.ts +++ b/src/i18n/locales/en.ts @@ -10,13 +10,14 @@ export default { 'Pinned note': 'Pinned note', 'Relay settings': 'Relays and Storage Settings', Settings: 'Settings', + 'Account menu': 'Account menu', SidebarRelays: 'Relays', Refresh: 'Refresh', Profile: 'Profile', Logout: 'Logout', Following: 'Following', followings: 'followings', - reposted: 'reposted', + boosted: 'boosted', 'just now': 'just now', 'n minutes ago': '{{n}} minutes ago', 'n m': '{{n}}m', @@ -51,7 +52,8 @@ export default { 'Failed to post': 'Failed to post', 'Post successful': 'Post successful', 'Your post has been published': 'Your post has been published', - Repost: 'Repost', + Boost: 'Boost', + 'Boost published': 'Boost published', Quote: 'Quote', 'Copy event ID': 'Copy event ID', 'Copy user ID': 'Copy user ID', @@ -381,6 +383,7 @@ export default { 'no more replies': 'no more replies', 'Relay sets': 'Relay sets', 'Favorite Relays': 'Favorite Relays', + 'Search for Relays': 'Search for Relays', 'Using app default relays': 'Using app default relays', "Following's Favorites": "Following's Favorites", 'no more relays': 'no more relays', @@ -563,9 +566,9 @@ export default { 'No reactions yet': 'No reactions yet', 'No more zaps': 'No more zaps', 'No zaps yet': 'No zaps yet', - 'No more reposts': 'No more reposts', - 'No reposts yet': 'No reposts yet', - Reposts: 'Reposts', + 'No more boosts': 'No more boosts', + 'No boosts yet': 'No boosts yet', + Boosts: 'Boosts', FollowListNotFoundConfirmation: 'Follow list not found. Do you want to create a new one? If you have followed users before, please DO NOT confirm as this operation will cause you to lose your previous follow list.', MuteListNotFoundConfirmation: @@ -615,7 +618,7 @@ export default { 'quoted your note': 'quoted your note', 'voted in your poll': 'voted in your poll', 'reacted to your note': 'reacted to your note', - 'reposted your note': 'reposted your note', + 'boosted your note': 'boosted your note', 'zapped your note': 'zapped your note', 'zapped you': 'zapped you', zapped: 'zapped', @@ -663,6 +666,14 @@ export default { '{{count}} relays': '{{count}} relays', 'Republishing...': 'Republishing...', 'Trending Notes': 'Trending Notes', + 'Trending on Your Favorite Relays': 'Trending on Your Favorite Relays', + 'Trending on the Default Relays': 'Trending on the Default Relays', + 'Loading trending notes from your relays...': 'Loading trending notes from your relays...', + Sort: 'Sort', + newest: 'newest', + oldest: 'oldest', + 'most popular': 'most popular', + 'least popular': 'least popular', 'Connected to': 'Connected to', 'Disconnect Wallet': 'Disconnect Wallet', 'Are you absolutely sure?': 'Are you absolutely sure?', @@ -706,6 +717,9 @@ export default { 'Compact': 'Compact', 'Expand': 'Expand', + 'help.title': 'Help', + 'help.tabShortcuts': 'Keyboard shortcuts', + 'help.tabOverview': 'App overview', 'shortcuts.title': 'Keyboard shortcuts', 'shortcuts.intro': 'Shortcuts for this app and common browsing. Modifier combos are Shift+Alt+key (Option+Shift+key on macOS); either modifier order works when typing.', diff --git a/src/i18n/locales/es.ts b/src/i18n/locales/es.ts index d6cb966e..de3534ff 100644 --- a/src/i18n/locales/es.ts +++ b/src/i18n/locales/es.ts @@ -14,7 +14,7 @@ export default { Logout: 'Cerrar sesión', Following: 'Siguiendo', followings: 'siguiendo', - reposted: 'retransmitido', + boosted: 'boosteado', 'just now': 'justo ahora', 'n minutes ago': 'hace {{n}} minutos', 'n m': '{{n}}m', @@ -41,7 +41,8 @@ export default { 'Failed to post': 'Error al publicar', 'Post successful': 'Publicación exitosa', 'Your post has been published': 'Tu publicación ha sido publicada', - Repost: 'Reenviar', + Boost: 'Boost', + 'Boost published': 'Boost publicado', Quote: 'Citar', 'Copy event ID': 'Copiar ID del evento', 'Copy user ID': 'Copiar ID del usuario', @@ -337,9 +338,9 @@ export default { 'No reactions yet': 'Sin reacciones aún', 'No more zaps': 'No hay más zaps', 'No zaps yet': 'Sin zaps aún', - 'No more reposts': 'No hay más reposts', - 'No reposts yet': 'Sin reposts aún', - Reposts: 'Reposts', + 'No more boosts': 'No hay más boosts', + 'No boosts yet': 'Sin boosts aún', + Boosts: 'Boosts', FollowListNotFoundConfirmation: 'Lista de seguidos no encontrada. ¿Quieres crear una nueva? Si has seguido usuarios antes, por favor NO confirmes ya que esta operación te hará perder tu lista de seguidos anterior.', MuteListNotFoundConfirmation: @@ -385,7 +386,7 @@ export default { 'quoted your note': 'citó tu nota', 'voted in your poll': 'votó en tu encuesta', 'reacted to your note': 'reaccionó a tu nota', - 'reposted your note': 'reposteó tu nota', + 'boosted your note': 'boosteó tu nota', 'zapped your note': 'zappeó tu nota', 'zapped you': 'te zappeó', 'Mark as read': 'Marcar como leído', diff --git a/src/i18n/locales/fa.ts b/src/i18n/locales/fa.ts index f43da812..435ae2f2 100644 --- a/src/i18n/locales/fa.ts +++ b/src/i18n/locales/fa.ts @@ -13,7 +13,7 @@ export default { Logout: 'خروج', Following: 'دنبال می‌کنم', followings: 'دنبال شونده‌ها', - reposted: 'بازنشر شده', + boosted: 'بوست شده', 'just now': 'همین الان', 'n minutes ago': '{{n}} دقیقه پیش', 'n m': '{{n}}د', @@ -40,7 +40,8 @@ export default { 'Failed to post': 'ارسال ناموفق', 'Post successful': 'ارسال موفق', 'Your post has been published': 'پست شما منتشر شد', - Repost: 'بازنشر', + Boost: 'بوست', + 'Boost published': 'بوست منتشر شد', Quote: 'نقل قول', 'Copy event ID': 'کپی شناسه رویداد', 'Copy user ID': 'کپی شناسه کاربر', @@ -334,9 +335,9 @@ export default { 'No reactions yet': 'هنوز هیچ واکنشی وجود ندارد', 'No more zaps': 'هیچ زپی بیشتر وجود ندارد', 'No zaps yet': 'هنوز هیچ زپی وجود ندارد', - 'No more reposts': 'هیچ بازنشر بیشتری وجود ندارد', - 'No reposts yet': 'هنوز هیچ بازنشر وجود ندارد', - Reposts: 'بازنشرها', + 'No more boosts': 'بوست دیگری نیست', + 'No boosts yet': 'هنوز بوستی نیست', + Boosts: 'بوست‌ها', FollowListNotFoundConfirmation: 'فهرست دنبال‌کنندگان پیدا نشد. آیا می‌خواهید یکی جدید ایجاد کنید؟ اگر قبلاً کاربرانی را دنبال کرده‌اید، لطفاً تأیید نکنید زیرا این عملیات باعث از دست رفتن فهرست دنبال‌کنندگان قبلی شما خواهد شد.', MuteListNotFoundConfirmation: @@ -381,7 +382,7 @@ export default { 'quoted your note': 'یادداشت شما را نقل قول کرد', 'voted in your poll': 'در نظرسنجی شما رأی داد', 'reacted to your note': 'به یادداشت شما واکنش نشان داد', - 'reposted your note': 'یادداشت شما را بازنشر کرد', + 'boosted your note': 'یادداشت شما را بوست کرد', 'zapped your note': 'یادداشت شما را زپ کرد', 'zapped you': 'شما را زپ کرد', 'Mark as read': 'علامت‌گذاری به عنوان خوانده شده', diff --git a/src/i18n/locales/fr.ts b/src/i18n/locales/fr.ts index 723a1199..312598b7 100644 --- a/src/i18n/locales/fr.ts +++ b/src/i18n/locales/fr.ts @@ -14,7 +14,7 @@ export default { Logout: 'Déconnexion', Following: 'Abonnements', followings: 'abonnements', - reposted: 'republié', + boosted: 'a boosté', 'just now': "à l'instant", 'n minutes ago': 'il y a {{n}} minutes', 'n m': '{{n}}m', @@ -41,7 +41,8 @@ export default { 'Failed to post': 'Publication échouée', 'Post successful': 'Publication réussie', 'Your post has been published': 'Votre publication a été publiée', - Repost: 'Reposter', + Boost: 'Boost', + 'Boost published': 'Boost publié', Quote: 'Citer', 'Copy event ID': "Copier l'ID de l'événement", 'Copy user ID': "Copier l'ID de l'utilisateur", @@ -339,9 +340,9 @@ export default { 'No reactions yet': 'Pas encore de réactions', 'No more zaps': 'Plus de zaps', 'No zaps yet': 'Pas encore de zaps', - 'No more reposts': 'Plus de reposts', - 'No reposts yet': 'Pas encore de reposts', - Reposts: 'Reposts', + 'No more boosts': 'Plus de boosts', + 'No boosts yet': 'Pas encore de boosts', + Boosts: 'Boosts', FollowListNotFoundConfirmation: 'Liste de suivi non trouvée. Voulez-vous en créer une nouvelle ? Si vous avez suivi des utilisateurs auparavant, veuillez NE PAS confirmer car cette opération vous fera perdre votre liste de suivi précédente.', MuteListNotFoundConfirmation: @@ -389,7 +390,7 @@ export default { 'quoted your note': 'a cité votre note', 'voted in your poll': 'a voté dans votre sondage', 'reacted to your note': 'a réagi à votre note', - 'reposted your note': 'a repartagé votre note', + 'boosted your note': 'a boosté votre note', 'zapped your note': 'a zappé votre note', 'zapped you': 'vous a zappé', 'Mark as read': 'Marquer comme lu', diff --git a/src/i18n/locales/hi.ts b/src/i18n/locales/hi.ts index a3de556f..1939ebbb 100644 --- a/src/i18n/locales/hi.ts +++ b/src/i18n/locales/hi.ts @@ -13,7 +13,7 @@ export default { Logout: 'लॉगआउट', Following: 'फॉलो कर रहे हैं', followings: 'फॉलोइंग', - reposted: 'रीपोस्ट किया', + boosted: 'बूस्ट किया', 'just now': 'अभी', 'n minutes ago': '{{n}} मिनट पहले', 'n m': '{{n}}मि', @@ -40,7 +40,8 @@ export default { 'Failed to post': 'पोस्ट असफल', 'Post successful': 'पोस्ट सफल', 'Your post has been published': 'आपकी पोस्ट प्रकाशित हो गई है', - Repost: 'रीपोस्ट', + Boost: 'बूस्ट', + 'Boost published': 'बूस्ट प्रकाशित', Quote: 'उद्धरण', 'Copy event ID': 'इवेंट आईडी कॉपी करें', 'Copy user ID': 'यूजर आईडी कॉपी करें', @@ -335,9 +336,9 @@ export default { 'No reactions yet': 'अभी तक कोई प्रतिक्रियाएं नहीं', 'No more zaps': 'कोई और जैप्स नहीं', 'No zaps yet': 'अभी तक कोई जैप्स नहीं', - 'No more reposts': 'कोई और रीपोस्ट नहीं', - 'No reposts yet': 'अभी तक कोई रीपोस्ट नहीं', - Reposts: 'रीपोस्ट', + 'No more boosts': 'और कोई बूस्ट नहीं', + 'No boosts yet': 'अभी तक कोई बूस्ट नहीं', + Boosts: 'बूस्ट', FollowListNotFoundConfirmation: 'फॉलो सूची नहीं मिली। क्या आप एक नई बनाना चाहते हैं? यदि आपने पहले उपयोगकर्ताओं को फॉलो किया है, तो कृपया पुष्टि न करें क्योंकि इस ऑपरेशन से आपकी पिछली फॉलो सूची नष्ट हो जाएगी।', MuteListNotFoundConfirmation: @@ -384,7 +385,7 @@ export default { 'quoted your note': 'ने आपके नोट को उद्धृत किया', 'voted in your poll': 'ने आपके पोल में वोट किया', 'reacted to your note': 'ने आपके नोट पर प्रतिक्रिया दी', - 'reposted your note': 'ने आपके नोट को रीपोस्ट किया', + 'boosted your note': 'ने आपके नोट को बूस्ट किया', 'zapped your note': 'ने आपके नोट को जैप किया', 'zapped you': 'ने आपको जैप किया', 'Mark as read': 'पढ़ा हुआ मार्क करें', diff --git a/src/i18n/locales/it.ts b/src/i18n/locales/it.ts index 431ef4f9..32138855 100644 --- a/src/i18n/locales/it.ts +++ b/src/i18n/locales/it.ts @@ -13,7 +13,7 @@ export default { Logout: 'Disconnetti', Following: 'Seguendo', followings: 'seguiti', - reposted: 'ripubblica', + boosted: 'ha boostato', 'just now': 'adesso', 'n minutes ago': '{{n}} minuti fa', 'n m': '{{n}}m', @@ -40,7 +40,8 @@ export default { 'Failed to post': 'Impossibile pubblicare', 'Post successful': 'Pubblicazione riuscita', 'Your post has been published': 'Il tuo post è stato pubblicato', - Repost: 'Ripubblica', + Boost: 'Boost', + 'Boost published': 'Boost pubblicato', Quote: 'Quota', 'Copy event ID': 'Copia ID evento', 'Copy user ID': 'Copia ID utente', @@ -337,9 +338,9 @@ export default { 'No reactions yet': 'Ancora nessuna reazione', 'No more zaps': 'Non ci sono più zaps', 'No zaps yet': 'Ancora nessuno zap', - 'No more reposts': 'Non ci sono più repost', - 'No reposts yet': 'Ancora nessun repost', - Reposts: 'Repost', + 'No more boosts': 'Non ci sono più boost', + 'No boosts yet': 'Ancora nessun boost', + Boosts: 'Boost', FollowListNotFoundConfirmation: 'Elenco seguiti non trovato. Vuoi crearne uno nuovo? Se hai già seguito degli utenti in precedenza, per favore NON confermare poiché questa operazione causerà la perdita del tuo elenco seguiti precedente.', MuteListNotFoundConfirmation: @@ -385,7 +386,7 @@ export default { 'quoted your note': 'ha citato la tua nota', 'voted in your poll': 'ha votato nel tuo sondaggio', 'reacted to your note': 'ha reagito alla tua nota', - 'reposted your note': 'ha ricondiviso la tua nota', + 'boosted your note': 'ha boostato la tua nota', 'zapped your note': 'ha zappato la tua nota', 'zapped you': 'ti ha zappato', 'Mark as read': 'Segna come letto', diff --git a/src/i18n/locales/ja.ts b/src/i18n/locales/ja.ts index f7ef559a..170f5fd5 100644 --- a/src/i18n/locales/ja.ts +++ b/src/i18n/locales/ja.ts @@ -14,7 +14,7 @@ export default { Logout: 'ログアウト', Following: 'フォロー中', followings: 'フォロー', - reposted: 'リポスト済み', + boosted: 'ブースト済み', 'just now': 'たった今', 'n minutes ago': '{{n}}分前', 'n m': '{{n}}分', @@ -41,7 +41,8 @@ export default { 'Failed to post': '投稿に失敗しました', 'Post successful': '投稿に成功しました', 'Your post has been published': '投稿が公開されました', - Repost: 'リポスト', + Boost: 'ブースト', + 'Boost published': 'ブーストを公開しました', Quote: '引用', 'Copy event ID': 'イベントIDをコピー', 'Copy user ID': 'ユーザーIDをコピー', @@ -334,9 +335,9 @@ export default { 'No reactions yet': 'まだ反応はありません', 'No more zaps': 'これ以上のZapはありません', 'No zaps yet': 'まだZapはありません', - 'No more reposts': 'これ以上のリポストはありません', - 'No reposts yet': 'まだリポストはありません', - Reposts: 'リポスト', + 'No more boosts': 'これ以上のブーストはありません', + 'No boosts yet': 'まだブーストはありません', + Boosts: 'ブースト', FollowListNotFoundConfirmation: 'フォローリストが見つかりません。新しいものを作成しますか?以前にユーザーをフォローしたことがある場合は、この操作により前のフォローリストが失われるため、確認しないでください。', MuteListNotFoundConfirmation: @@ -382,7 +383,7 @@ export default { 'quoted your note': 'あなたのノートを引用しました', 'voted in your poll': 'あなたの投票に投票しました', 'reacted to your note': 'あなたのノートにリアクションしました', - 'reposted your note': 'あなたのノートをリポストしました', + 'boosted your note': 'あなたのノートをブーストしました', 'zapped your note': 'あなたのノートにザップしました', 'zapped you': 'あなたにザップしました', 'Mark as read': '既読にする', diff --git a/src/i18n/locales/ko.ts b/src/i18n/locales/ko.ts index 9f144fe4..cfa08e95 100644 --- a/src/i18n/locales/ko.ts +++ b/src/i18n/locales/ko.ts @@ -13,7 +13,7 @@ export default { Logout: '로그아웃', Following: '팔로잉', followings: '팔로잉', - reposted: '리포스트', + boosted: '부스트함', 'just now': '방금 전', 'n minutes ago': '{{n}}분 전', 'n m': '{{n}}분', @@ -40,7 +40,8 @@ export default { 'Failed to post': '게시 실패', 'Post successful': '게시 성공', 'Your post has been published': '게시물이 게시되었습니다', - Repost: '리포스트', + Boost: '부스트', + 'Boost published': '부스트가 게시되었습니다', Quote: '인용', 'Copy event ID': '이벤트 ID 복사', 'Copy user ID': '사용자 ID 복사', @@ -334,9 +335,9 @@ export default { 'No reactions yet': '아직 반응이 없습니다', 'No more zaps': '더 이상 잽이 없습니다', 'No zaps yet': '아직 잽이 없습니다', - 'No more reposts': '더 이상 리포스트가 없습니다', - 'No reposts yet': '아직 리포스트가 없습니다', - Reposts: '리포스트', + 'No more boosts': '더 이상 부스트가 없습니다', + 'No boosts yet': '아직 부스트가 없습니다', + Boosts: '부스트', FollowListNotFoundConfirmation: '팔로우 목록을 찾을 수 없습니다. 새로 만드시겠습니까? 이전에 사용자를 팔로우한 적이 있다면 이 작업으로 인해 이전 팔로우 목록을 잃게 되므로 확인하지 마시기 바랍니다.', MuteListNotFoundConfirmation: @@ -382,7 +383,7 @@ export default { 'quoted your note': '당신의 노트를 인용했습니다', 'voted in your poll': '당신의 투표에 참여했습니다', 'reacted to your note': '당신의 노트에 반응했습니다', - 'reposted your note': '당신의 노트를 리포스트했습니다', + 'boosted your note': '당신의 노트를 부스트했습니다', 'zapped your note': '당신의 노트를 잽했습니다', 'zapped you': '당신을 잽했습니다', 'Mark as read': '읽음으로 표시', diff --git a/src/i18n/locales/pl.ts b/src/i18n/locales/pl.ts index adb0eacb..12729108 100644 --- a/src/i18n/locales/pl.ts +++ b/src/i18n/locales/pl.ts @@ -13,7 +13,7 @@ export default { Logout: 'Wyloguj', Following: 'Obserwowani', followings: 'niżej wymienionych', - reposted: 'Udostępnił', + boosted: 'zboostował', 'just now': 'teraz', 'n minutes ago': '{{n}} m', 'n m': '{{n}}m', @@ -40,7 +40,8 @@ export default { 'Failed to post': 'Nie udało się opublikować', 'Post successful': 'Twój wpis został wysłany.', 'Your post has been published': 'Publikowani są jedynie użytkownicy z białej listy', - Repost: 'Udostępnij', + Boost: 'Boost', + 'Boost published': 'Opublikowano boost', Quote: 'Zacytuj', 'Copy event ID': 'Skopiuj ID wydarzenia', 'Copy user ID': 'Skopiuj ID użytkownika', @@ -338,9 +339,9 @@ export default { 'No reactions yet': 'Brak reakcji', 'No more zaps': 'Brak kolejnych zapów', 'No zaps yet': 'Brak zapów', - 'No more reposts': 'Brak kolejnych repostów', - 'No reposts yet': 'Brak repostów', - Reposts: 'Reposty', + 'No more boosts': 'Brak kolejnych boostów', + 'No boosts yet': 'Brak boostów', + Boosts: 'Boosty', FollowListNotFoundConfirmation: 'Lista obserwowanych nie została znaleziona. Czy chcesz utworzyć nową? Jeśli wcześniej obserwowałeś użytkowników, proszę NIE potwierdzaj, ponieważ ta operacja spowoduje utratę poprzedniej listy obserwowanych.', MuteListNotFoundConfirmation: @@ -386,7 +387,7 @@ export default { 'quoted your note': 'zacytował twoją notatkę', 'voted in your poll': 'zagłosował w twojej ankiecie', 'reacted to your note': 'zareagował na twoją notatkę', - 'reposted your note': 'przepostował twoją notatkę', + 'boosted your note': 'zboostował twoją notatkę', 'zapped your note': 'zappował twoją notatkę', 'zapped you': 'zappował cię', 'Mark as read': 'Oznacz jako przeczytane', diff --git a/src/i18n/locales/pt-BR.ts b/src/i18n/locales/pt-BR.ts index 2176880d..f3c25462 100644 --- a/src/i18n/locales/pt-BR.ts +++ b/src/i18n/locales/pt-BR.ts @@ -13,7 +13,7 @@ export default { Logout: 'Sair', Following: 'Seguindo', followings: 'Seguidos', - reposted: 'Repostado', + boosted: 'deu boost', 'just now': 'agora mesmo', 'n minutes ago': '{{n}} minutos atrás', 'n m': '{{n}}m', @@ -40,7 +40,8 @@ export default { 'Failed to post': 'Falha ao postar', 'Post successful': 'Nota publicada com sucesso', 'Your post has been published': 'Sua nota foi publicada', - Repost: 'Repostar', + Boost: 'Boost', + 'Boost published': 'Boost publicado', Quote: 'Citar', 'Copy event ID': 'Copiar ID do evento', 'Copy user ID': 'Copiar ID do usuário', @@ -335,9 +336,9 @@ export default { 'No reactions yet': 'Ainda sem reações', 'No more zaps': 'Sem mais zaps', 'No zaps yet': 'Ainda sem zaps', - 'No more reposts': 'Sem mais reposts', - 'No reposts yet': 'Ainda sem reposts', - Reposts: 'Reposts', + 'No more boosts': 'Sem mais boosts', + 'No boosts yet': 'Ainda sem boosts', + Boosts: 'Boosts', FollowListNotFoundConfirmation: 'Lista de seguindo não encontrada. Deseja criar uma nova? Se você seguiu usuários antes, por favor NÃO confirme, pois esta operação fará você perder sua lista de seguindo anterior.', MuteListNotFoundConfirmation: @@ -382,7 +383,7 @@ export default { 'quoted your note': 'citou sua nota', 'voted in your poll': 'votou na sua enquete', 'reacted to your note': 'reagiu à sua nota', - 'reposted your note': 'republicou sua nota', + 'boosted your note': 'deu boost na sua nota', 'zapped your note': 'zappeou sua nota', 'zapped you': 'zappeou você', 'Mark as read': 'Marcar como lida', diff --git a/src/i18n/locales/pt-PT.ts b/src/i18n/locales/pt-PT.ts index b9a7ea61..266e8924 100644 --- a/src/i18n/locales/pt-PT.ts +++ b/src/i18n/locales/pt-PT.ts @@ -14,7 +14,7 @@ export default { Logout: 'Sair', Following: 'Seguindo', followings: 'seguidos', - reposted: 'repostado', + boosted: 'deu boost', 'just now': 'agora mesmo', 'n minutes ago': '{{n}} minutos atrás', 'n m': '{{n}}m', @@ -41,7 +41,8 @@ export default { 'Failed to post': 'Falha ao postar', 'Post successful': 'Postagem bem-sucedida', 'Your post has been published': 'Sua postagem foi publicada', - Repost: 'Repostar', + Boost: 'Boost', + 'Boost published': 'Boost publicado', Quote: 'Citar', 'Copy event ID': 'Copiar ID do evento', 'Copy user ID': 'Copiar ID do usuário', @@ -337,9 +338,9 @@ export default { 'No reactions yet': 'Ainda sem reações', 'No more zaps': 'Sem mais zaps', 'No zaps yet': 'Ainda sem zaps', - 'No more reposts': 'Sem mais reposts', - 'No reposts yet': 'Ainda sem reposts', - Reposts: 'Reposts', + 'No more boosts': 'Sem mais boosts', + 'No boosts yet': 'Ainda sem boosts', + Boosts: 'Boosts', FollowListNotFoundConfirmation: 'Lista de seguir não encontrada. Deseja criar uma nova? Se seguiu utilizadores anteriormente, por favor NÃO confirme, pois esta operação fará com que perca a sua lista de seguir anterior.', MuteListNotFoundConfirmation: @@ -385,7 +386,7 @@ export default { 'quoted your note': 'citou a sua nota', 'voted in your poll': 'votou na sua sondagem', 'reacted to your note': 'reagiu à sua nota', - 'reposted your note': 'republicou a sua nota', + 'boosted your note': 'deu boost na sua nota', 'zapped your note': 'zappeou a sua nota', 'zapped you': 'zappeou-o', 'Mark as read': 'Marcar como lida', diff --git a/src/i18n/locales/ru.ts b/src/i18n/locales/ru.ts index 9b4f1863..bca79a9d 100644 --- a/src/i18n/locales/ru.ts +++ b/src/i18n/locales/ru.ts @@ -14,7 +14,7 @@ export default { Logout: 'Выйти', Following: 'Подписки', followings: 'подписки', - reposted: 'репостнул', + boosted: 'сделал буст', 'just now': 'только что', 'n minutes ago': '{{n}} минут назад', 'n m': '{{n}}м', @@ -41,7 +41,8 @@ export default { 'Failed to post': 'Ошибка публикации', 'Post successful': 'Успешно опубликовано', 'Your post has been published': 'Ваш пост опубликован', - Repost: 'Репост', + Boost: 'Буст', + 'Boost published': 'Буст опубликован', Quote: 'Цитировать', 'Copy event ID': 'Копировать ID события', 'Copy user ID': 'Копировать ID пользователя', @@ -338,9 +339,9 @@ export default { 'No reactions yet': 'Пока нет реакций', 'No more zaps': 'Больше нет запов', 'No zaps yet': 'Пока нет запов', - 'No more reposts': 'Больше нет репостов', - 'No reposts yet': 'Пока нет репостов', - Reposts: 'Репосты', + 'No more boosts': 'Больше нет бустов', + 'No boosts yet': 'Пока нет бустов', + Boosts: 'Бусты', FollowListNotFoundConfirmation: 'Список подписок не найден. Хотите создать новый? Если вы уже подписывались на пользователей ранее, пожалуйста, НЕ подтверждайте, так как эта операция приведет к потере вашего предыдущего списка подписок.', MuteListNotFoundConfirmation: @@ -386,7 +387,7 @@ export default { 'quoted your note': 'процитировал вашу заметку', 'voted in your poll': 'проголосовал в вашем опросе', 'reacted to your note': 'отреагировал на вашу заметку', - 'reposted your note': 'репостнул вашу заметку', + 'boosted your note': 'сделал буст вашей заметки', 'zapped your note': 'заппил вашу заметку', 'zapped you': 'заппил вас', 'Mark as read': 'Отметить как прочитанное', diff --git a/src/i18n/locales/th.ts b/src/i18n/locales/th.ts index 6c3e3262..81ec6db8 100644 --- a/src/i18n/locales/th.ts +++ b/src/i18n/locales/th.ts @@ -13,7 +13,7 @@ export default { Logout: 'ออกจากระบบ', Following: 'กำลังติดตาม', followings: 'กำลังติดตาม', - reposted: 'รีโพสต์', + boosted: 'บูสต์แล้ว', 'just now': 'เมื่อสักครู่', 'n minutes ago': '{{n}} นาทีที่แล้ว', 'n m': '{{n}}น', @@ -40,7 +40,8 @@ export default { 'Failed to post': 'โพสต์ไม่สำเร็จ', 'Post successful': 'โพสต์สำเร็จ', 'Your post has been published': 'โพสต์ของคุณถูกเผยแพร่แล้ว', - Repost: 'รีโพสต์', + Boost: 'บูสต์', + 'Boost published': 'เผยแพร่บูสต์แล้ว', Quote: 'อ้างอิง', 'Copy event ID': 'คัดลอก ID เหตุการณ์', 'Copy user ID': 'คัดลอก ID ผู้ใช้', @@ -331,9 +332,9 @@ export default { 'No reactions yet': 'ยังไม่มีปฏิกิริยา', 'No more zaps': 'ไม่มีซาตส์เพิ่มเติม', 'No zaps yet': 'ยังไม่มีซาตส์', - 'No more reposts': 'ไม่มีการรีโพสต์เพิ่มเติม', - 'No reposts yet': 'ยังไม่มีการรีโพสต์', - Reposts: 'การรีโพสต์', + 'No more boosts': 'ไม่มีบูสต์เพิ่มเติม', + 'No boosts yet': 'ยังไม่มีบูสต์', + Boosts: 'บูสต์', FollowListNotFoundConfirmation: 'ไม่พบรายการติดตาม คุณต้องการสร้างรายการใหม่หรือไม่? หากคุณเคยติดตามผู้ใช้มาก่อน กรุณาอย่ายืนยัน เพราะการดำเนินการนี้จะทำให้คุณสูญเสียรายการติดตามก่อนหน้านี้', MuteListNotFoundConfirmation: @@ -378,7 +379,7 @@ export default { 'quoted your note': 'ได้ยกคำพูดจากโน้ตของคุณ', 'voted in your poll': 'ได้โหวตในการสำรวจของคุณ', 'reacted to your note': 'ได้แสดงปฏิกิริยาต่อโน้ตของคุณ', - 'reposted your note': 'ได้รีโพสต์โน้ตของคุณ', + 'boosted your note': 'ได้บูสต์โน้ตของคุณ', 'zapped your note': 'ได้แซปโน้ตของคุณ', 'zapped you': 'ได้แซปคุณ', 'Mark as read': 'ทำเครื่องหมายว่าอ่านแล้ว', diff --git a/src/i18n/locales/zh.ts b/src/i18n/locales/zh.ts index 3f94a1d6..a2e7e416 100644 --- a/src/i18n/locales/zh.ts +++ b/src/i18n/locales/zh.ts @@ -13,7 +13,7 @@ export default { Logout: '退出登录', Following: '关注', followings: '关注', - reposted: '转发', + boosted: '已助推', 'just now': '刚刚', 'n minutes ago': '{{n}} 分钟前', 'n m': '{{n}}分', @@ -40,7 +40,8 @@ export default { 'Failed to post': '发布失败', 'Post successful': '发布成功', 'Your post has been published': '您的笔记已发布', - Repost: '转发', + Boost: '助推', + 'Boost published': '助推已发布', Quote: '引用', 'Copy event ID': '复制事件 ID', 'Copy user ID': '复制用户 ID', @@ -330,9 +331,9 @@ export default { 'No reactions yet': '暂无互动', 'No more zaps': '没有更多打闪了', 'No zaps yet': '暂无打闪', - 'No more reposts': '没有更多转发了', - 'No reposts yet': '暂无转发', - Reposts: '转发', + 'No more boosts': '没有更多助推了', + 'No boosts yet': '暂无助推', + Boosts: '助推', FollowListNotFoundConfirmation: '未找到关注列表。你想创建一个新的吗?如果你之前已经关注了用户,请不要确认,因为此操作会导致你丢失之前的关注列表。', MuteListNotFoundConfirmation: @@ -376,7 +377,7 @@ export default { 'quoted your note': '引用了您的笔记', 'voted in your poll': '在您的投票中投票', 'reacted to your note': '对您的笔记做出了反应', - 'reposted your note': '转发了您的笔记', + 'boosted your note': '助推了您的笔记', 'zapped your note': '打闪了您的笔记', 'zapped you': '给您打闪', 'Mark as read': '标记为已读', diff --git a/src/pages/primary/ExplorePage/index.tsx b/src/pages/primary/ExplorePage/index.tsx index 0993f4bb..ffe4184e 100644 --- a/src/pages/primary/ExplorePage/index.tsx +++ b/src/pages/primary/ExplorePage/index.tsx @@ -109,6 +109,7 @@ const ExplorePage = forwardRef((_, ref) => { {tab === 'explore' && ( <> + )} @@ -122,6 +123,33 @@ export default ExplorePage function ExplorePageTitlebar() { const { t } = useTranslation() + + return ( +
+
+ +
{t('Explore')}
+
+ +
+ ) +} + +function ExploreRelaySearchSection() { + const { t } = useTranslation() const { navigateToRelay } = useSmartRelayNavigation() const [relayQuery, setRelayQuery] = useState('') const [monitoringRelays, setMonitoringRelays] = useState([]) @@ -175,35 +203,58 @@ function ExplorePageTitlebar() { } return ( -
-
- -
{t('Explore')}
-
-
+
+

{t('Search for Relays')}

+
- setRelayQuery(e.target.value)} - aria-label={t('Relay URL…')} - aria-autocomplete="list" - aria-expanded={suggestOpen && relaySuggestions.length > 0} - aria-controls="explore-relay-suggestions" - role="combobox" - onFocus={() => { - clearBlurTimer() - setSuggestOpen(true) - }} - onBlur={() => { - clearBlurTimer() - blurCloseTimer.current = setTimeout(() => setSuggestOpen(false), 200) - }} - /> +
+ setRelayQuery(e.target.value)} + aria-label={t('Relay URL…')} + aria-autocomplete="list" + aria-expanded={suggestOpen && relaySuggestions.length > 0} + aria-controls="explore-relay-suggestions" + role="combobox" + onFocus={() => { + clearBlurTimer() + setSuggestOpen(true) + }} + onBlur={() => { + clearBlurTimer() + blurCloseTimer.current = setTimeout(() => setSuggestOpen(false), 200) + }} + /> + {suggestOpen && relaySuggestions.length > 0 ? ( +
    e.preventDefault()} + > + {relaySuggestions.map((url) => ( +
  • + +
  • + ))} +
+ ) : null} +
- {suggestOpen && relaySuggestions.length > 0 ? ( -
    e.preventDefault()} - > - {relaySuggestions.map((url) => ( -
  • - -
  • - ))} -
- ) : null}
- -
+ ) } diff --git a/src/pages/primary/MePage/index.tsx b/src/pages/primary/MePage/index.tsx index d03d0fc2..9c91db3b 100644 --- a/src/pages/primary/MePage/index.tsx +++ b/src/pages/primary/MePage/index.tsx @@ -16,7 +16,6 @@ import { ChevronRight, LogOut, Server, - Settings, UserRound, Wallet } from 'lucide-react' diff --git a/src/pages/primary/SettingsPrimaryPage/index.tsx b/src/pages/primary/SettingsPrimaryPage/index.tsx index b88714fe..82defeeb 100644 --- a/src/pages/primary/SettingsPrimaryPage/index.tsx +++ b/src/pages/primary/SettingsPrimaryPage/index.tsx @@ -4,7 +4,7 @@ import { Settings } from 'lucide-react' import { forwardRef } from 'react' import { useTranslation } from 'react-i18next' -const SettingsPrimaryPage = forwardRef((_, ref) => { +const SettingsPrimaryPage = forwardRef((_, ref) => { const { t } = useTranslation() return ( diff --git a/src/pages/secondary/NotePage/index.tsx b/src/pages/secondary/NotePage/index.tsx index bfcbc420..413309b0 100644 --- a/src/pages/secondary/NotePage/index.tsx +++ b/src/pages/secondary/NotePage/index.tsx @@ -3,6 +3,7 @@ import { ExtendedKind } from '@/constants' import ContentPreview from '@/components/ContentPreview' import client from '@/services/client.service' import Note from '@/components/Note' +import NoteBoostBadges from '@/components/NoteBoostBadges' import NoteInteractions from '@/components/NoteInteractions' import NoteStats from '@/components/NoteStats' import UserAvatar from '@/components/UserAvatar' @@ -160,8 +161,8 @@ const NotePage = forwardRef(({ id, index, hideTitlebar = false, initialEvent }: return 'Note: Calendar Event' case 9735: // ExtendedKind.ZAP_RECEIPT return 'Note: Zap Receipt' - case 6: // kinds.Repost - return 'Note: Repost' + case 6: // kinds.Repost (Nostr boost) + return 'Note: Boost' case 7: // kinds.Reaction return 'Note: Reaction' case 1111: // ExtendedKind.COMMENT diff --git a/src/services/local-storage.service.ts b/src/services/local-storage.service.ts index b3311f4b..131dc5c8 100644 --- a/src/services/local-storage.service.ts +++ b/src/services/local-storage.service.ts @@ -3,7 +3,7 @@ import { ExtendedKind, MEDIA_AUTO_LOAD_POLICY, NOTIFICATION_LIST_STYLE, - SUPPORTED_KINDS, + PROFILE_FEED_KINDS, StorageKey } from '@/constants' import { kinds } from 'nostr-tools' @@ -223,15 +223,7 @@ class LocalStorageService { const showKindsStr = window.localStorage.getItem(StorageKey.SHOW_KINDS) if (!showKindsStr) { - // Default: show all supported kinds except reposts, publications, publication content, and NIP-89 handler kinds - this.showKinds = SUPPORTED_KINDS.filter( - kind => - kind !== kinds.Repost && - kind !== ExtendedKind.PUBLICATION && - kind !== ExtendedKind.PUBLICATION_CONTENT && - kind !== ExtendedKind.APPLICATION_HANDLER_RECOMMENDATION && - kind !== ExtendedKind.APPLICATION_HANDLER_INFO - ) + this.showKinds = [...PROFILE_FEED_KINDS] } else { const showKindsVersionStr = window.localStorage.getItem(StorageKey.SHOW_KINDS_VERSION) const showKindsVersion = showKindsVersionStr ? parseInt(showKindsVersionStr) : 0 @@ -243,7 +235,7 @@ class LocalStorageService { showKinds.push(ExtendedKind.ZAP_RECEIPT) } if (showKindsVersion < 3) { - // Remove reposts from existing users' filters + // Remove boosts (kind 6) from existing users' filters const repostIndex = showKinds.indexOf(kinds.Repost) if (repostIndex !== -1) { showKinds.splice(repostIndex, 1) @@ -290,10 +282,19 @@ class LocalStorageService { showKinds.splice(nip89InfoIndex, 1) } } + if (showKindsVersion < 8) { + // Boosts (kind 6) and publications removed from feed filter UI — strip from saved preferences + for (let i = showKinds.length - 1; i >= 0; i--) { + const k = showKinds[i] + if (k === kinds.Repost || k === ExtendedKind.PUBLICATION) { + showKinds.splice(i, 1) + } + } + } this.showKinds = showKinds } this.persistSetting(StorageKey.SHOW_KINDS, JSON.stringify(this.showKinds)) - this.persistSetting(StorageKey.SHOW_KINDS_VERSION, '7') + this.persistSetting(StorageKey.SHOW_KINDS_VERSION, '8') // Feed filter: kind 1 OPs, kind 1 replies, kind 1111 (migrate from legacy showRepliesAndComments if set) const showKind1OPsStr = window.localStorage.getItem(StorageKey.SHOW_KIND_1_OPs) diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts index c921d75e..4dea2b47 100644 --- a/src/vite-env.d.ts +++ b/src/vite-env.d.ts @@ -1,6 +1,11 @@ /// import { TNip07 } from '@/types' +declare module '*.md?raw' { + const content: string + export default content +} + declare global { interface Window { nostr?: TNip07