From 256560cf3b5b3559bd4daa97b0ef1c44d736f5a4 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Sat, 23 May 2026 12:38:19 -0500 Subject: [PATCH] chore: delete components/hooks/lib orphaned by page deletions Iteratively removed files no longer imported anywhere after the unreachable-page sweep: - Layout chrome: MainLayout, LeftSidebar, RightSidebar, WidgetSidebar, MobileDrawer, MobileBottomNav, MobileTopBar, FundraiserLayout component, FloatingComposeButton, AudioNavigationGuard, MinimizedAudioBar, DeepLinkHandler - Music subsystem: useMusic*, MusicHeroCard, MusicTrackCard, MusicPlaylistsTab, MusicTracksTab, MusicArtistsTab, MusicDiscoverTab, MusicSortFilterBar, MusicPlaylistCard - World/discovery: useWorldFeed, WorldMap, WorldDiscoveryPanel/Drawer, CountryBrowser, CountryActivityPopover, CountryPulseStrip, TagChips, HorizontalScroll, ContentCTACard - Letter system: useLetterPreferences, useStationery, useThemeStationery, LetterCard, LetterEditor, DrawingCanvas, StationeryPicker, FramePicker, FramePreviews, SendAnimation, ComposeLetterSheet, LetterPreferencesSection, useEnvelopeDimensions, svgDrawing - Bird/Constellation: useBirdSong, BirdSongPlayer, BirdexContent, BirdexTile, BirdexChorusButton, BirdDetectionContent, ConstellationContent, ConstellationStarMap, parseBirdex, starCatalog - Books: useBookFeed, useBookSearch, useBookDetails, usePopularBooks, useBookSummary, BookFeedItem - Bluesky: useBluesky*, BlueskyWidget - Wikipedia: useWikipediaSearch, useWikipediaFeatured, WikipediaWidget - AI chat: useAIChatSession, useAIChatTools, aiChatTools, tools/*, AIChatWidget - Article editor: ArticleEditor, MilkdownEditor, MilkdownToolbar, LinkDialog, usePublishedArticles, articleHelpers - Badges/community/highlights: useBadgeFeed, useCommunity*, useCreateBadge, BadgeRecoveryDialog, CreateBadgeDialog, CreateGoalDialog, CommunityCard, HighlightContent - Profile tabs: useProfileTabs, useResolveTabFilter, usePublishProfileTabs, ProfileTabEditModal, ProfileTabsManagerModal, profileTabsEvent - Webxdc/Photo/Stream/Vine: WebxdcUploadDialog, PhotoComposeModal, PhotoBottomBar, useStreamKind, vineGlobalMute - Miscellaneous: AudioPlayerContext, EditProfileForm (unused), feed widgets, FabButton, sidebar widgets, ContentSettings, FontPicker, EmbeddedPeopleListCard, PeopleListDetailContent, BitcoinContent*, exchange rate service, deduplicateEvents, feedDiversity, createZapInvoice, MuteListRecoveryDialog, EventRecoveryDialog, ZapContent, useCuratedDittoFeed, useScrollDirection, useDrafts, useUserZap, useHasUnreadNotifications, useMutedAuthorFilter, useFormatMoney, useKeyboardVisible, AgoraLogo, MailboxIcon, PlanetIcon, WhiteNoiseIcon, BarsStaggeredIcon, ScopedTheme, CommentsSheet, MobileSearchSheet, FollowAllSplitButton, FeedEditModal, KindInfoButton, WidgetCard, WidgetPickerDialog, SidebarNavItem, SidebarMoreMenu, TrendSparkline, DorkThinking, NostrEventSidebarItem, NsiteSidebarItem, ExternalContentSidebarItem, GathererCardHeader, MediaCollage, BackgroundPicker, BitcoinPrivateDisclaimer, UnknownKindContent, proxyUrl, localDrafts, flagPalette, coordinates, checkWasmSupport - Unused shadcn primitives: calendar, context-menu, input-otp, breadcrumb, menubar, toggle, table, resizable, navigation-menu, carousel, aspect-ratio, pagination, color-picker, drawer --- src/components/AgoraLogo.tsx | 53 - src/components/AudioNavigationGuard.tsx | 25 - src/components/BackgroundPicker.tsx | 174 --- src/components/BadgeRecoveryDialog.tsx | 388 ------ src/components/BirdDetectionContent.tsx | 208 --- src/components/BirdSongPlayer.tsx | 181 --- src/components/BirdexChorusButton.tsx | 279 ---- src/components/BirdexContent.tsx | 169 --- src/components/BirdexTile.tsx | 118 -- src/components/BitcoinContentHeader.tsx | 631 --------- src/components/BitcoinPrivateDisclaimer.tsx | 51 - src/components/BookFeedItem.tsx | 410 ------ src/components/CommentsSheet.tsx | 196 --- src/components/CommunityCard.tsx | 96 -- src/components/ConstellationContent.tsx | 121 -- src/components/ConstellationStarMap.tsx | 322 ----- src/components/ContentSettings.tsx | 1169 ----------------- src/components/CreateActionDialog.tsx | 355 ----- src/components/CreateBadgeDialog.tsx | 368 ------ src/components/CreateGoalDialog.tsx | 228 ---- src/components/DeepLinkHandler.tsx | 45 - src/components/DorkThinking.tsx | 12 - src/components/EditProfileForm.tsx | 619 --------- src/components/EmbeddedPeopleListCard.tsx | 128 -- src/components/EventRecoveryDialog.tsx | 278 ---- src/components/ExternalContentSidebarItem.tsx | 129 -- src/components/FabButton.tsx | 27 - src/components/FeedEditModal.tsx | 257 ---- src/components/FloatingComposeButton.tsx | 179 --- src/components/FollowAllSplitButton.tsx | 272 ---- src/components/FontPicker.tsx | 332 ----- src/components/FundraiserLayout.tsx | 128 -- src/components/GathererCardHeader.tsx | 291 ---- src/components/HighlightContent.tsx | 304 ----- src/components/KindInfoButton.tsx | 77 -- src/components/LeftSidebar.tsx | 345 ----- src/components/MainLayout.tsx | 144 -- src/components/MediaCollage.tsx | 473 ------- src/components/MinimizedAudioBar.tsx | 205 --- src/components/MobileBottomNav.tsx | 171 --- src/components/MobileDrawer.tsx | 386 ------ src/components/MobileSearchSheet.tsx | 846 ------------ src/components/MobileTopBar.tsx | 72 - src/components/MuteListRecoveryDialog.tsx | 451 ------- src/components/NostrEventSidebarItem.tsx | 209 --- src/components/NsiteSidebarItem.tsx | 154 --- src/components/PeopleListDetailContent.tsx | 705 ---------- src/components/PhotoBottomBar.tsx | 132 -- src/components/PhotoComposeModal.tsx | 491 ------- src/components/ProfileTabEditModal.tsx | 290 ---- src/components/ProfileTabsManagerModal.tsx | 217 --- src/components/RightSidebar.tsx | 266 ---- src/components/ScopedTheme.tsx | 40 - src/components/SidebarMoreMenu.tsx | 319 ----- src/components/SidebarNavItem.tsx | 242 ---- src/components/TrendSparkline.tsx | 57 - src/components/UnknownKindContent.tsx | 58 - src/components/WebxdcUploadDialog.tsx | 246 ---- src/components/WidgetCard.tsx | 133 -- src/components/WidgetPickerDialog.tsx | 100 -- src/components/WidgetSidebar.tsx | 246 ---- src/components/ZapContent.tsx | 116 -- src/components/articles/ArticleEditor.tsx | 1026 --------------- src/components/articles/LinkDialog.tsx | 99 -- src/components/articles/MilkdownEditor.tsx | 395 ------ src/components/articles/MilkdownToolbar.tsx | 233 ---- src/components/discovery/ContentCTACard.tsx | 53 - .../discovery/CountryPulseStrip.tsx | 205 --- src/components/discovery/HorizontalScroll.tsx | 23 - src/components/discovery/TagChips.tsx | 57 - src/components/icons/BarsStaggeredIcon.tsx | 24 - src/components/icons/MailboxIcon.tsx | 29 - src/components/icons/PlanetIcon.tsx | 29 - src/components/icons/WhiteNoiseIcon.tsx | 35 - src/components/letter/ComposeLetterSheet.tsx | 510 ------- src/components/letter/DrawingCanvas.tsx | 163 --- src/components/letter/FramePicker.tsx | 47 - src/components/letter/FramePreviews.tsx | 39 - src/components/letter/LetterCard.tsx | 339 ----- src/components/letter/LetterEditor.tsx | 322 ----- .../letter/LetterPreferencesSection.tsx | 202 --- src/components/letter/SendAnimation.tsx | 499 ------- src/components/letter/StationeryPicker.tsx | 308 ----- src/components/music/MusicArtistsTab.tsx | 85 -- src/components/music/MusicDiscoverTab.tsx | 297 ----- src/components/music/MusicHeroCard.tsx | 119 -- src/components/music/MusicPlaylistCard.tsx | 89 -- src/components/music/MusicPlaylistsTab.tsx | 155 --- src/components/music/MusicSortFilterBar.tsx | 88 -- src/components/music/MusicTrackCard.tsx | 110 -- src/components/music/MusicTracksTab.tsx | 138 -- src/components/ui/aspect-ratio.tsx | 5 - src/components/ui/breadcrumb.tsx | 115 -- src/components/ui/calendar.tsx | 70 - src/components/ui/carousel.tsx | 260 ---- src/components/ui/color-picker.tsx | 321 ----- src/components/ui/context-menu.tsx | 198 --- src/components/ui/drawer.tsx | 120 -- src/components/ui/input-otp.tsx | 69 - src/components/ui/menubar.tsx | 234 ---- src/components/ui/navigation-menu-variants.ts | 5 - src/components/ui/navigation-menu.tsx | 123 -- src/components/ui/pagination.tsx | 118 -- src/components/ui/resizable.tsx | 43 - src/components/ui/table.tsx | 117 -- src/components/ui/toggle.tsx | 22 - src/components/widgets/AIChatWidget.tsx | 174 --- src/components/widgets/BlueskyWidget.tsx | 128 -- src/components/widgets/FeedWidget.tsx | 129 -- src/components/widgets/HotPostsWidget.tsx | 97 -- src/components/widgets/MusicWidget.tsx | 167 --- src/components/widgets/PhotoWidget.tsx | 120 -- src/components/widgets/StatusWidget.tsx | 112 -- src/components/widgets/TrendingWidget.tsx | 66 - src/components/widgets/WikipediaWidget.tsx | 72 - .../world/CountryActivityPopover.tsx | 81 -- src/components/world/CountryBrowser.tsx | 79 -- src/components/world/WorldDiscoveryDrawer.tsx | 171 --- src/components/world/WorldDiscoveryPanel.tsx | 122 -- src/components/world/WorldMap.tsx | 567 -------- src/contexts/AudioPlayerContext.tsx | 269 ---- src/hooks/useAIChatSession.ts | 489 ------- src/hooks/useAIChatTools.ts | 87 -- src/hooks/useBadgeFeed.ts | 96 -- src/hooks/useBarcodeScanner.ts | 72 - src/hooks/useBirdSong.ts | 228 ---- src/hooks/useBitcoinAddress.ts | 30 - src/hooks/useBitcoinTx.ts | 30 - src/hooks/useBlueskyActorSearch.ts | 86 -- src/hooks/useBlueskySearch.ts | 113 -- src/hooks/useBlueskyTrending.ts | 130 -- src/hooks/useBookDetails.ts | 113 -- src/hooks/useBookFeed.ts | 76 -- src/hooks/useBookSearch.ts | 75 -- src/hooks/useBookSummary.ts | 148 --- src/hooks/useCommunityActions.ts | 37 - src/hooks/useCommunityEvents.ts | 47 - src/hooks/useCommunityGoals.ts | 32 - src/hooks/useCreateBadge.ts | 63 - src/hooks/useCuratedDittoFeed.ts | 92 -- src/hooks/useCuratedMusicArtists.ts | 62 - src/hooks/useCuratorFollowList.ts | 67 - src/hooks/useDrafts.ts | 162 --- src/hooks/useEnvelopeDimensions.ts | 30 - src/hooks/useExchangeRate.ts | 74 -- src/hooks/useFeaturedMusicTracks.ts | 81 -- src/hooks/useFormatMoney.ts | 77 -- src/hooks/useHasUnreadNotifications.ts | 88 -- src/hooks/useKeyboardVisible.ts | 37 - src/hooks/useLetterPreferences.ts | 36 - src/hooks/useMusicCuratorFollows.ts | 42 - src/hooks/useMusicData.ts | 114 -- src/hooks/useMusicFeed.ts | 114 -- src/hooks/useMusicPlaylists.ts | 59 - src/hooks/useMutedAuthorFilter.ts | 73 - src/hooks/useNostrEventSidebar.ts | 100 -- src/hooks/usePersistentNostrSession.ts | 248 ---- src/hooks/usePlaylistCoverArt.ts | 76 -- src/hooks/usePopularBooks.ts | 80 -- src/hooks/useProfileMedia.ts | 70 - src/hooks/useProfileTabs.ts | 28 - src/hooks/usePublishProfileTabs.ts | 31 - src/hooks/usePublishStatus.ts | 54 - src/hooks/usePublishedArticles.ts | 56 - src/hooks/useRemoveBadge.ts | 61 - src/hooks/useReorderBadges.ts | 46 - src/hooks/useResolveTabFilter.ts | 88 -- src/hooks/useSavedFeeds.ts | 88 -- src/hooks/useScrollDirection.ts | 67 - src/hooks/useStationery.ts | 38 - src/hooks/useStreamKind.ts | 115 -- src/hooks/useThemeStationery.ts | 61 - src/hooks/useUserZap.ts | 68 - src/hooks/useWallComments.ts | 80 -- src/hooks/useWikipediaFeatured.ts | 105 -- src/hooks/useWikipediaSearch.ts | 72 - src/hooks/useWorldFeed.ts | 250 ---- src/lib/aiChatTools.ts | 30 - src/lib/articleHelpers.ts | 33 - src/lib/checkWasmSupport.ts | 86 -- src/lib/coordinates.ts | 374 ------ src/lib/createZapInvoice.ts | 104 -- src/lib/deduplicateEvents.ts | 17 - src/lib/exchangeRateService.ts | 136 -- src/lib/feedDiversity.ts | 213 --- src/lib/flagPalette.ts | 215 --- src/lib/localDrafts.ts | 76 -- src/lib/parseBirdex.ts | 63 - src/lib/profileTabsEvent.ts | 183 --- src/lib/proxyUrl.ts | 23 - src/lib/sidebarWidgets.ts | 167 --- src/lib/starCatalog.ts | 101 -- src/lib/svgDrawing.ts | 132 -- src/lib/tools/FetchEventTool.ts | 97 -- src/lib/tools/FetchPageTool.ts | 76 -- src/lib/tools/GetFeedTool.ts | 382 ------ src/lib/tools/SearchFollowPacksTool.ts | 98 -- src/lib/tools/SearchUsersTool.ts | 109 -- src/lib/tools/Tool.ts | 53 - src/lib/tools/helpers.ts | 57 - src/lib/tools/sanitizeToolFetchUrl.ts | 145 -- src/lib/tools/toolToOpenAI.ts | 28 - src/lib/tools/truncateToolResult.ts | 44 - src/lib/vineGlobalMute.ts | 18 - 204 files changed, 33728 deletions(-) delete mode 100644 src/components/AgoraLogo.tsx delete mode 100644 src/components/AudioNavigationGuard.tsx delete mode 100644 src/components/BackgroundPicker.tsx delete mode 100644 src/components/BadgeRecoveryDialog.tsx delete mode 100644 src/components/BirdDetectionContent.tsx delete mode 100644 src/components/BirdSongPlayer.tsx delete mode 100644 src/components/BirdexChorusButton.tsx delete mode 100644 src/components/BirdexContent.tsx delete mode 100644 src/components/BirdexTile.tsx delete mode 100644 src/components/BitcoinContentHeader.tsx delete mode 100644 src/components/BitcoinPrivateDisclaimer.tsx delete mode 100644 src/components/BookFeedItem.tsx delete mode 100644 src/components/CommentsSheet.tsx delete mode 100644 src/components/CommunityCard.tsx delete mode 100644 src/components/ConstellationContent.tsx delete mode 100644 src/components/ConstellationStarMap.tsx delete mode 100644 src/components/ContentSettings.tsx delete mode 100644 src/components/CreateActionDialog.tsx delete mode 100644 src/components/CreateBadgeDialog.tsx delete mode 100644 src/components/CreateGoalDialog.tsx delete mode 100644 src/components/DeepLinkHandler.tsx delete mode 100644 src/components/DorkThinking.tsx delete mode 100644 src/components/EditProfileForm.tsx delete mode 100644 src/components/EmbeddedPeopleListCard.tsx delete mode 100644 src/components/EventRecoveryDialog.tsx delete mode 100644 src/components/ExternalContentSidebarItem.tsx delete mode 100644 src/components/FabButton.tsx delete mode 100644 src/components/FeedEditModal.tsx delete mode 100644 src/components/FloatingComposeButton.tsx delete mode 100644 src/components/FollowAllSplitButton.tsx delete mode 100644 src/components/FontPicker.tsx delete mode 100644 src/components/FundraiserLayout.tsx delete mode 100644 src/components/GathererCardHeader.tsx delete mode 100644 src/components/HighlightContent.tsx delete mode 100644 src/components/KindInfoButton.tsx delete mode 100644 src/components/LeftSidebar.tsx delete mode 100644 src/components/MainLayout.tsx delete mode 100644 src/components/MediaCollage.tsx delete mode 100644 src/components/MinimizedAudioBar.tsx delete mode 100644 src/components/MobileBottomNav.tsx delete mode 100644 src/components/MobileDrawer.tsx delete mode 100644 src/components/MobileSearchSheet.tsx delete mode 100644 src/components/MobileTopBar.tsx delete mode 100644 src/components/MuteListRecoveryDialog.tsx delete mode 100644 src/components/NostrEventSidebarItem.tsx delete mode 100644 src/components/NsiteSidebarItem.tsx delete mode 100644 src/components/PeopleListDetailContent.tsx delete mode 100644 src/components/PhotoBottomBar.tsx delete mode 100644 src/components/PhotoComposeModal.tsx delete mode 100644 src/components/ProfileTabEditModal.tsx delete mode 100644 src/components/ProfileTabsManagerModal.tsx delete mode 100644 src/components/RightSidebar.tsx delete mode 100644 src/components/ScopedTheme.tsx delete mode 100644 src/components/SidebarMoreMenu.tsx delete mode 100644 src/components/SidebarNavItem.tsx delete mode 100644 src/components/TrendSparkline.tsx delete mode 100644 src/components/UnknownKindContent.tsx delete mode 100644 src/components/WebxdcUploadDialog.tsx delete mode 100644 src/components/WidgetCard.tsx delete mode 100644 src/components/WidgetPickerDialog.tsx delete mode 100644 src/components/WidgetSidebar.tsx delete mode 100644 src/components/ZapContent.tsx delete mode 100644 src/components/articles/ArticleEditor.tsx delete mode 100644 src/components/articles/LinkDialog.tsx delete mode 100644 src/components/articles/MilkdownEditor.tsx delete mode 100644 src/components/articles/MilkdownToolbar.tsx delete mode 100644 src/components/discovery/ContentCTACard.tsx delete mode 100644 src/components/discovery/CountryPulseStrip.tsx delete mode 100644 src/components/discovery/HorizontalScroll.tsx delete mode 100644 src/components/discovery/TagChips.tsx delete mode 100644 src/components/icons/BarsStaggeredIcon.tsx delete mode 100644 src/components/icons/MailboxIcon.tsx delete mode 100644 src/components/icons/PlanetIcon.tsx delete mode 100644 src/components/icons/WhiteNoiseIcon.tsx delete mode 100644 src/components/letter/ComposeLetterSheet.tsx delete mode 100644 src/components/letter/DrawingCanvas.tsx delete mode 100644 src/components/letter/FramePicker.tsx delete mode 100644 src/components/letter/FramePreviews.tsx delete mode 100644 src/components/letter/LetterCard.tsx delete mode 100644 src/components/letter/LetterEditor.tsx delete mode 100644 src/components/letter/LetterPreferencesSection.tsx delete mode 100644 src/components/letter/SendAnimation.tsx delete mode 100644 src/components/letter/StationeryPicker.tsx delete mode 100644 src/components/music/MusicArtistsTab.tsx delete mode 100644 src/components/music/MusicDiscoverTab.tsx delete mode 100644 src/components/music/MusicHeroCard.tsx delete mode 100644 src/components/music/MusicPlaylistCard.tsx delete mode 100644 src/components/music/MusicPlaylistsTab.tsx delete mode 100644 src/components/music/MusicSortFilterBar.tsx delete mode 100644 src/components/music/MusicTrackCard.tsx delete mode 100644 src/components/music/MusicTracksTab.tsx delete mode 100644 src/components/ui/aspect-ratio.tsx delete mode 100644 src/components/ui/breadcrumb.tsx delete mode 100644 src/components/ui/calendar.tsx delete mode 100644 src/components/ui/carousel.tsx delete mode 100644 src/components/ui/color-picker.tsx delete mode 100644 src/components/ui/context-menu.tsx delete mode 100644 src/components/ui/drawer.tsx delete mode 100644 src/components/ui/input-otp.tsx delete mode 100644 src/components/ui/menubar.tsx delete mode 100644 src/components/ui/navigation-menu-variants.ts delete mode 100644 src/components/ui/navigation-menu.tsx delete mode 100644 src/components/ui/pagination.tsx delete mode 100644 src/components/ui/resizable.tsx delete mode 100644 src/components/ui/table.tsx delete mode 100644 src/components/ui/toggle.tsx delete mode 100644 src/components/widgets/AIChatWidget.tsx delete mode 100644 src/components/widgets/BlueskyWidget.tsx delete mode 100644 src/components/widgets/FeedWidget.tsx delete mode 100644 src/components/widgets/HotPostsWidget.tsx delete mode 100644 src/components/widgets/MusicWidget.tsx delete mode 100644 src/components/widgets/PhotoWidget.tsx delete mode 100644 src/components/widgets/StatusWidget.tsx delete mode 100644 src/components/widgets/TrendingWidget.tsx delete mode 100644 src/components/widgets/WikipediaWidget.tsx delete mode 100644 src/components/world/CountryActivityPopover.tsx delete mode 100644 src/components/world/CountryBrowser.tsx delete mode 100644 src/components/world/WorldDiscoveryDrawer.tsx delete mode 100644 src/components/world/WorldDiscoveryPanel.tsx delete mode 100644 src/components/world/WorldMap.tsx delete mode 100644 src/contexts/AudioPlayerContext.tsx delete mode 100644 src/hooks/useAIChatSession.ts delete mode 100644 src/hooks/useAIChatTools.ts delete mode 100644 src/hooks/useBadgeFeed.ts delete mode 100644 src/hooks/useBarcodeScanner.ts delete mode 100644 src/hooks/useBirdSong.ts delete mode 100644 src/hooks/useBitcoinAddress.ts delete mode 100644 src/hooks/useBitcoinTx.ts delete mode 100644 src/hooks/useBlueskyActorSearch.ts delete mode 100644 src/hooks/useBlueskySearch.ts delete mode 100644 src/hooks/useBlueskyTrending.ts delete mode 100644 src/hooks/useBookDetails.ts delete mode 100644 src/hooks/useBookFeed.ts delete mode 100644 src/hooks/useBookSearch.ts delete mode 100644 src/hooks/useBookSummary.ts delete mode 100644 src/hooks/useCommunityActions.ts delete mode 100644 src/hooks/useCommunityEvents.ts delete mode 100644 src/hooks/useCommunityGoals.ts delete mode 100644 src/hooks/useCreateBadge.ts delete mode 100644 src/hooks/useCuratedDittoFeed.ts delete mode 100644 src/hooks/useCuratedMusicArtists.ts delete mode 100644 src/hooks/useCuratorFollowList.ts delete mode 100644 src/hooks/useDrafts.ts delete mode 100644 src/hooks/useEnvelopeDimensions.ts delete mode 100644 src/hooks/useExchangeRate.ts delete mode 100644 src/hooks/useFeaturedMusicTracks.ts delete mode 100644 src/hooks/useFormatMoney.ts delete mode 100644 src/hooks/useHasUnreadNotifications.ts delete mode 100644 src/hooks/useKeyboardVisible.ts delete mode 100644 src/hooks/useLetterPreferences.ts delete mode 100644 src/hooks/useMusicCuratorFollows.ts delete mode 100644 src/hooks/useMusicData.ts delete mode 100644 src/hooks/useMusicFeed.ts delete mode 100644 src/hooks/useMusicPlaylists.ts delete mode 100644 src/hooks/useMutedAuthorFilter.ts delete mode 100644 src/hooks/useNostrEventSidebar.ts delete mode 100644 src/hooks/usePersistentNostrSession.ts delete mode 100644 src/hooks/usePlaylistCoverArt.ts delete mode 100644 src/hooks/usePopularBooks.ts delete mode 100644 src/hooks/useProfileMedia.ts delete mode 100644 src/hooks/useProfileTabs.ts delete mode 100644 src/hooks/usePublishProfileTabs.ts delete mode 100644 src/hooks/usePublishStatus.ts delete mode 100644 src/hooks/usePublishedArticles.ts delete mode 100644 src/hooks/useRemoveBadge.ts delete mode 100644 src/hooks/useReorderBadges.ts delete mode 100644 src/hooks/useResolveTabFilter.ts delete mode 100644 src/hooks/useSavedFeeds.ts delete mode 100644 src/hooks/useScrollDirection.ts delete mode 100644 src/hooks/useStationery.ts delete mode 100644 src/hooks/useStreamKind.ts delete mode 100644 src/hooks/useThemeStationery.ts delete mode 100644 src/hooks/useUserZap.ts delete mode 100644 src/hooks/useWallComments.ts delete mode 100644 src/hooks/useWikipediaFeatured.ts delete mode 100644 src/hooks/useWikipediaSearch.ts delete mode 100644 src/hooks/useWorldFeed.ts delete mode 100644 src/lib/aiChatTools.ts delete mode 100644 src/lib/articleHelpers.ts delete mode 100644 src/lib/checkWasmSupport.ts delete mode 100644 src/lib/coordinates.ts delete mode 100644 src/lib/createZapInvoice.ts delete mode 100644 src/lib/deduplicateEvents.ts delete mode 100644 src/lib/exchangeRateService.ts delete mode 100644 src/lib/feedDiversity.ts delete mode 100644 src/lib/flagPalette.ts delete mode 100644 src/lib/localDrafts.ts delete mode 100644 src/lib/parseBirdex.ts delete mode 100644 src/lib/profileTabsEvent.ts delete mode 100644 src/lib/proxyUrl.ts delete mode 100644 src/lib/sidebarWidgets.ts delete mode 100644 src/lib/starCatalog.ts delete mode 100644 src/lib/svgDrawing.ts delete mode 100644 src/lib/tools/FetchEventTool.ts delete mode 100644 src/lib/tools/FetchPageTool.ts delete mode 100644 src/lib/tools/GetFeedTool.ts delete mode 100644 src/lib/tools/SearchFollowPacksTool.ts delete mode 100644 src/lib/tools/SearchUsersTool.ts delete mode 100644 src/lib/tools/Tool.ts delete mode 100644 src/lib/tools/helpers.ts delete mode 100644 src/lib/tools/sanitizeToolFetchUrl.ts delete mode 100644 src/lib/tools/toolToOpenAI.ts delete mode 100644 src/lib/tools/truncateToolResult.ts delete mode 100644 src/lib/vineGlobalMute.ts diff --git a/src/components/AgoraLogo.tsx b/src/components/AgoraLogo.tsx deleted file mode 100644 index 873a8e7f..00000000 --- a/src/components/AgoraLogo.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { cn } from '@/lib/utils'; - -interface AgoraLogoProps { - className?: string; - size?: number; -} - -function LightningBolt({ size }: { size: number }) { - return ( - - - - ); -} - -/** Agora badge icon used across app chrome. */ -export function AgoraLogo({ className, size = 40 }: AgoraLogoProps) { - const boltSize = Math.max(12, Math.round(size * 0.56)); - - return ( -
-
-
- -
-
- ); -} diff --git a/src/components/AudioNavigationGuard.tsx b/src/components/AudioNavigationGuard.tsx deleted file mode 100644 index c8bc0d17..00000000 --- a/src/components/AudioNavigationGuard.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { useEffect, useRef } from 'react'; -import { useLocation } from 'react-router-dom'; -import { useAudioPlayer } from '@/contexts/audioPlayerContextDef'; - -/** - * Auto-minimizes the audio player when the user navigates to a different page. - * No dialog — audio just keeps playing in the floating mini-bar. - */ -export function AudioNavigationGuard() { - const { currentTrack, minimized, minimize } = useAudioPlayer(); - const location = useLocation(); - const prevPath = useRef(location.pathname); - - useEffect(() => { - if (location.pathname !== prevPath.current) { - // Route changed — minimize if playing and expanded - if (currentTrack && !minimized) { - minimize(); - } - prevPath.current = location.pathname; - } - }, [location.pathname, currentTrack, minimized, minimize]); - - return null; -} diff --git a/src/components/BackgroundPicker.tsx b/src/components/BackgroundPicker.tsx deleted file mode 100644 index 893946da..00000000 --- a/src/components/BackgroundPicker.tsx +++ /dev/null @@ -1,174 +0,0 @@ -import { useRef } from 'react'; -import { ImagePlus, X, Loader2 } from 'lucide-react'; - -import { useTheme } from '@/hooks/useTheme'; -import { useUploadFile } from '@/hooks/useUploadFile'; -import { useToast } from '@/hooks/useToast'; -import { Button } from '@/components/ui/button'; -import { cn } from '@/lib/utils'; -import { resizeImage } from '@/lib/resizeImage'; -import type { ThemeBackground } from '@/themes'; - -/** - * Background image picker for theme customization. - * - * Supports two modes: - * - **Uncontrolled** (default): reads/writes via `useTheme().applyCustomTheme()` - * - **Controlled**: pass `value` and `onChange` props to manage state externally - */ -export function BackgroundPicker({ value, onChange }: { - /** Controlled value — overrides useTheme() when provided. */ - value?: ThemeBackground | undefined; - /** Controlled onChange — called instead of applyCustomTheme() when provided. */ - onChange?: (bg: ThemeBackground | undefined) => void; -} = {}) { - const { theme, customTheme, applyCustomTheme } = useTheme(); - const { mutateAsync: uploadFile, isPending: isUploading } = useUploadFile(); - const { toast } = useToast(); - const inputRef = useRef(null); - const controlled = onChange !== undefined; - - const currentBg: ThemeBackground | undefined = controlled - ? value - : (theme === 'custom' ? customTheme?.background : undefined); - - const handleFileChange = async (e: React.ChangeEvent) => { - const file = e.target.files?.[0]; - if (!file) return; - e.target.value = ''; - - if (!file.type.startsWith('image/')) { - toast({ title: 'Invalid file', description: 'Please select an image file.', variant: 'destructive' }); - return; - } - - try { - // Resize & convert to JPEG before uploading for better performance. - const { file: optimized, dimensions } = await resizeImage(file); - - const tags = await uploadFile(optimized); - const url = tags[0][1]; - - const bg: ThemeBackground = { - url, - mode: 'cover', - mimeType: optimized.type, - dimensions, - }; - - if (controlled) { - onChange(bg); - } else { - const currentColors = customTheme?.colors ?? { - background: '228 20% 10%', - text: '210 40% 98%', - primary: '258 70% 60%', - }; - applyCustomTheme({ - ...customTheme, - colors: currentColors, - background: bg, - }); - } - } catch (error) { - console.error('Failed to upload background:', error); - toast({ title: 'Upload failed', description: 'Could not upload the image.', variant: 'destructive' }); - } - }; - - const handleRemove = () => { - if (controlled) { - onChange(undefined); - return; - } - if (!customTheme) return; - applyCustomTheme({ - ...customTheme, - background: undefined, - }); - }; - - const handleModeChange = (mode: 'cover' | 'tile') => { - if (controlled) { - if (!value) return; - onChange({ ...value, mode }); - return; - } - if (!customTheme?.background) return; - applyCustomTheme({ - ...customTheme, - background: { ...customTheme.background, mode }, - }); - }; - - return ( -
- - Background - - - {currentBg ? ( -
-
- Theme background - -
- - {/* Mode toggle */} -
- {(['cover', 'tile'] as const).map((mode) => ( - - ))} -
-
- ) : ( - - )} - - -
- ); -} - - diff --git a/src/components/BadgeRecoveryDialog.tsx b/src/components/BadgeRecoveryDialog.tsx deleted file mode 100644 index 2ff65468..00000000 --- a/src/components/BadgeRecoveryDialog.tsx +++ /dev/null @@ -1,388 +0,0 @@ -import { useState, useMemo } from 'react'; -import { useNostr } from '@nostrify/react'; -import { useQuery, useQueryClient } from '@tanstack/react-query'; -import type { NostrEvent, NostrFilter } from '@nostrify/nostrify'; - -import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'; -import { ScrollArea } from '@/components/ui/scroll-area'; -import { Button } from '@/components/ui/button'; -import { Skeleton } from '@/components/ui/skeleton'; -import { BadgeThumbnail } from '@/components/BadgeThumbnail'; -import { parseBadgeDefinition, type BadgeData } from '@/lib/parseBadgeDefinition'; -import { parseProfileBadges } from '@/lib/parseProfileBadges'; -import { useCurrentUser } from '@/hooks/useCurrentUser'; -import { useNostrPublish } from '@/hooks/useNostrPublish'; -import { useToast } from '@/hooks/useToast'; -import { BADGE_PROFILE_KIND, BADGE_PROFILE_KIND_LEGACY, BADGE_DEFINITION_KIND } from '@/lib/badgeUtils'; -import { cn } from '@/lib/utils'; -import { Award, Check, Loader2, RotateCcw } from 'lucide-react'; - -/** - * Query all events matching a filter using `req()` instead of `query()`. - * This bypasses NSet deduplication in NPool.query(), which discards older - * versions of replaceable events. We need all historical versions for recovery. - */ -async function queryAllEvents( - nostr: { req(filters: NostrFilter[], opts?: { signal?: AbortSignal }): AsyncIterable<['EVENT', string, NostrEvent] | ['EOSE', string] | ['CLOSED', string, string]> }, - filters: NostrFilter[], - signal: AbortSignal, -): Promise { - const events: NostrEvent[] = []; - const seen = new Set(); - - for await (const msg of nostr.req(filters, { signal })) { - if (msg[0] === 'EOSE' || msg[0] === 'CLOSED') break; - if (msg[0] === 'EVENT') { - const event = msg[2]; - if (!seen.has(event.id)) { - seen.add(event.id); - events.push(event); - } - } - } - - return events; -} - -interface BadgeRecoveryDialogProps { - open: boolean; - onOpenChange: (open: boolean) => void; -} - -/** Format a unix timestamp into a human-readable date string. */ -function formatDate(timestamp: number): string { - return new Date(timestamp * 1000).toLocaleDateString(undefined, { - year: 'numeric', - month: 'short', - day: 'numeric', - hour: '2-digit', - minute: '2-digit', - }); -} - -/** Summary of badges parsed from a snapshot. */ -interface BadgeSummary { - count: number; - /** Parsed badge refs with their a-tag and identifier. */ - refs: { aTag: string; pubkey: string; identifier: string }[]; -} - -/** Parse all badge refs from a profile badges event. */ -function parseBadgeSnapshot(event: NostrEvent): BadgeSummary { - const refs = parseProfileBadges(event); - return { - count: refs.length, - refs: refs.map((r) => ({ aTag: r.aTag, pubkey: r.pubkey, identifier: r.identifier })), - }; -} - -// ─── Badge Snapshot Card ────────────────────────────────────────────── - -function BadgeSnapshotCard({ - summary, - event, - isCurrent, - onRestore, - isRestoring, - badgeMap, -}: { - summary: BadgeSummary; - event: NostrEvent; - isCurrent: boolean; - onRestore: () => void; - isRestoring: boolean; - badgeMap: Map; -}) { - /** Show up to 5 badge thumbnails in the preview. */ - const previewRefs = summary.refs.slice(0, 5); - const remaining = Math.max(0, summary.count - previewRefs.length); - - return ( -
- {isCurrent && ( -
- - Current -
- )} - -
-
- -
- -
-
- {summary.count.toLocaleString()} {summary.count === 1 ? 'badge' : 'badges'} -
- - {/* Badge thumbnail previews */} - {previewRefs.length > 0 && ( -
- {previewRefs.map((ref) => { - const badge = badgeMap.get(ref.aTag); - return badge ? ( - - ) : ( -
- -
- ); - })} - {remaining > 0 && ( - - +{remaining} - - )} -
- )} - -
- {formatDate(event.created_at)} -
-
-
- - {!isCurrent && ( -
- -
- )} -
- ); -} - -// ─── Empty State ────────────────────────────────────────────────────── - -function EmptyState() { - return ( -
-

- No badge list history found. Your relay may not store historical events. -

-
- ); -} - -// ─── Loading Skeleton ───────────────────────────────────────────────── - -function SnapshotSkeleton() { - return ( -
- {[1, 2, 3].map((i) => ( -
-
- -
- - - -
-
-
- ))} -
- ); -} - -// ─── Badge History Content ──────────────────────────────────────────── - -function BadgeHistoryContent({ onClose }: { onClose: () => void }) { - const { nostr } = useNostr(); - const { user } = useCurrentUser(); - const { mutateAsync: publishEvent } = useNostrPublish(); - const { toast } = useToast(); - const queryClient = useQueryClient(); - const [restoringId, setRestoringId] = useState(null); - - const pubkey = user?.pubkey; - - // Fetch all historical kind 10008 and legacy 30008 events - const badgeHistory = useQuery({ - queryKey: ['badge-recovery', 'history', pubkey], - queryFn: async () => { - if (!pubkey) return []; - const events = await queryAllEvents( - nostr, - [ - { kinds: [BADGE_PROFILE_KIND], authors: [pubkey] }, - { kinds: [BADGE_PROFILE_KIND_LEGACY], authors: [pubkey], '#d': ['profile_badges'] }, - ], - AbortSignal.timeout(10000), - ); - return events.sort((a, b) => b.created_at - a.created_at); - }, - enabled: !!pubkey, - staleTime: 30_000, - }); - - // Parse all snapshots - const parsedSnapshots = useMemo(() => { - if (!badgeHistory.data) return new Map(); - const results = new Map(); - for (const event of badgeHistory.data) { - results.set(event.id, parseBadgeSnapshot(event)); - } - return results; - }, [badgeHistory.data]); - - // Collect all unique badge definition refs across all snapshots for thumbnail fetching - const allBadgeRefs = useMemo(() => { - const seen = new Set(); - const refs: { pubkey: string; identifier: string; aTag: string }[] = []; - for (const summary of parsedSnapshots.values()) { - for (const ref of summary.refs) { - if (!seen.has(ref.aTag)) { - seen.add(ref.aTag); - refs.push(ref); - } - } - } - return refs; - }, [parsedSnapshots]); - - // Fetch badge definitions for thumbnails - const badgeDefsQuery = useQuery({ - queryKey: ['badge-recovery', 'definitions', allBadgeRefs.map((r) => r.aTag).join(',')], - queryFn: async ({ signal }) => { - if (allBadgeRefs.length === 0) return []; - const filters = allBadgeRefs.map((ref) => ({ - kinds: [BADGE_DEFINITION_KIND as number], - authors: [ref.pubkey], - '#d': [ref.identifier], - limit: 1, - })); - return nostr.query(filters, { signal }); - }, - enabled: allBadgeRefs.length > 0, - staleTime: 5 * 60_000, - }); - - // Build badge data map for thumbnails - const badgeMap = useMemo(() => { - const map = new Map(); - if (!badgeDefsQuery.data) return map; - for (const event of badgeDefsQuery.data) { - const parsed = parseBadgeDefinition(event); - if (!parsed) continue; - const aTag = `${BADGE_DEFINITION_KIND}:${event.pubkey}:${parsed.identifier}`; - map.set(aTag, parsed); - } - return map; - }, [badgeDefsQuery.data]); - - const badgeEvents = badgeHistory.data ?? []; - const currentBadgeId = badgeEvents[0]?.id; - - const handleRestore = async (event: NostrEvent) => { - setRestoringId(event.id); - try { - // Re-publish as kind 10008 (always write to the new kind), - // stripping any legacy `d` tag from kind 30008 events. - const tags = event.tags.filter(([n, v]) => !(n === 'd' && v === 'profile_badges')); - - await publishEvent({ - kind: BADGE_PROFILE_KIND, - content: event.content, - tags, - created_at: Math.floor(Date.now() / 1000), - }); - - toast({ - title: 'Badge list restored', - description: `Successfully restored from ${formatDate(event.created_at)}.`, - }); - - queryClient.invalidateQueries({ queryKey: ['badge-recovery', 'history', pubkey] }); - queryClient.invalidateQueries({ queryKey: ['profile-badges', pubkey] }); - - onClose(); - } catch (error) { - console.error('Failed to restore badge list:', error); - toast({ - title: 'Restore failed', - description: 'Could not republish the badge list. Please try again.', - variant: 'destructive', - }); - } finally { - setRestoringId(null); - } - }; - - if (badgeHistory.isLoading) { - return ; - } - - if (badgeEvents.length === 0) { - return ; - } - - return ( - <> - {badgeEvents.map((event) => { - const summary = parsedSnapshots.get(event.id); - if (!summary) return null; - - return ( - handleRestore(event)} - isRestoring={restoringId === event.id} - badgeMap={badgeMap} - /> - ); - })} - - ); -} - -// ─── Main Dialog ────────────────────────────────────────────────────── - -export function BadgeRecoveryDialog({ open, onOpenChange }: BadgeRecoveryDialogProps) { - const close = () => onOpenChange(false); - - return ( - - - - Badge List Recovery -

- Browse and restore previous versions of your accepted badges. -

-
- - -
- -
-
-
-
- ); -} diff --git a/src/components/BirdDetectionContent.tsx b/src/components/BirdDetectionContent.tsx deleted file mode 100644 index 6946471e..00000000 --- a/src/components/BirdDetectionContent.tsx +++ /dev/null @@ -1,208 +0,0 @@ -import { useMemo } from 'react'; -import { Bird } from 'lucide-react'; -import { Link } from 'react-router-dom'; -import type { NostrEvent } from '@nostrify/nostrify'; - -import { BirdSongPlayer } from '@/components/BirdSongPlayer'; -import { Skeleton } from '@/components/ui/skeleton'; -import { useWikidataEntity } from '@/hooks/useWikidataEntity'; -import { useWikipediaSummary } from '@/hooks/useWikipediaSummary'; -import { sanitizeUrl } from '@/lib/sanitizeUrl'; -import { cn } from '@/lib/utils'; - -/** - * Birdstar kind 2473 — Bird Detection. - * - * The species is identified by a NIP-73 `i`/`k` pair pointing at a Wikidata - * entity URI (e.g. `https://www.wikidata.org/entity/Q26825`). We resolve it - * through Wikidata → English Wikipedia to get a display name, a short - * summary, and a thumbnail image. - * - * Structured data lives in tags; `content` is an optional freeform note. - */ - -const WIKIDATA_URL_RE = /^https:\/\/www\.wikidata\.org\/entity\/(Q\d+)$/; - -interface BirdDetectionContentProps { - event: NostrEvent; - className?: string; -} - -function extractWikidata(tags: string[][]): { id: string; url: string } | null { - // A valid detection pairs an `i` tag with `k: web`. There may be multiple - // i/k pairs in principle; we take the first `i` whose URL matches. - for (const tag of tags) { - if (tag[0] !== 'i') continue; - const value = tag[1]; - if (typeof value !== 'string') continue; - const m = value.match(WIKIDATA_URL_RE); - if (m) return { id: m[1], url: value }; - } - return null; -} - -/** Pull a species label from the `alt` tag: "Bird detection: American Robin (Turdus migratorius)". */ -function extractAltSpecies(tags: string[][]): { common?: string; scientific?: string } | null { - const alt = tags.find(([n]) => n === 'alt')?.[1]; - if (!alt) return null; - // Match "Bird detection: ()" — keep the parser loose - // so subtly different NIP-31 prefixes still yield a usable label. - const m = alt.match(/^[^:]*:\s*([^()]+?)\s*(?:\(([^)]+)\))?\s*$/); - if (!m) return { common: alt }; - return { common: m[1]?.trim(), scientific: m[2]?.trim() }; -} - -/** Extract the scientific name from the `n` tag (Birdstar NIP §"Kind 2473" — the - * authoritative scientific-name field, added so clients can label a detection - * without round-tripping Wikidata). Falls through to parsing the `alt` tag for - * older events authored before `n` was part of the NIP. */ -function extractScientificName( - tags: string[][], - altScientific: string | undefined, -): string | undefined { - const n = tags.find(([name]) => name === 'n')?.[1]; - if (typeof n === 'string' && n.trim()) return n.trim(); - return altScientific; -} - -export function BirdDetectionContent({ event, className }: BirdDetectionContentProps) { - const wikidata = useMemo(() => extractWikidata(event.tags), [event.tags]); - const altSpecies = useMemo(() => extractAltSpecies(event.tags), [event.tags]); - const scientificName = useMemo( - () => extractScientificName(event.tags, altSpecies?.scientific), - [event.tags, altSpecies?.scientific], - ); - const note = event.content.trim(); - - // Resolve Wikidata → English Wikipedia title, then fetch the Wikipedia - // summary (extract + thumbnail) for the title. - const { data: entity, isLoading: entityLoading } = useWikidataEntity(wikidata?.id ?? null); - const wikipediaTitle = entity?.wikipediaTitle ?? null; - const { data: summary, isLoading: summaryLoading } = useWikipediaSummary(wikipediaTitle); - - const isLoading = entityLoading || summaryLoading; - - // Prefer the Wikipedia page title for the display name when available, - // but fall back to the species parsed from the `alt` tag so the card is - // still meaningful while the Wikipedia fetch is in flight (or has failed). - const commonName = summary?.title ?? altSpecies?.common ?? 'Unknown species'; - const extract = summary?.extract; - const thumbnail = sanitizeUrl(summary?.thumbnail?.source); - - // The whole card routes to Ditto's external-content page for this - // species' Wikidata URL. Other users' kind 2473 detections and - // NIP-22 comments both attach to the same `i`-tag identifier, so - // the discussion thread aggregates naturally across clients. - const discussPath = wikidata ? `/i/${encodeURIComponent(wikidata.url)}` : undefined; - - // When the user's own freeform note exists we show it above the - // Wikipedia-derived summary. `content` can be empty per the NIP. - const timeStr = new Date(event.created_at * 1000).toLocaleTimeString([], { - hour: '2-digit', - minute: '2-digit', - }); - - if (!wikidata) { - // Shouldn't happen for a valid kind 2473 (the NIP requires the i tag), - // but render something useful rather than silently dropping the event. - return ( -
- Bird detection with no species reference. -
- ); - } - - return ( -
- e.stopPropagation()} - className="block overflow-hidden rounded-2xl border border-border bg-card shadow-sm transition-shadow hover:shadow-md focus:outline-none focus-visible:ring-2 focus-visible:ring-ring" - > -
- {/* Thumbnail panel */} -
- {isLoading ? ( - - ) : thumbnail ? ( - {commonName} - ) : ( -
- -
- )} -
-
- {timeStr} -
-
- - {/* Text panel */} -
-
-
-

- {commonName} -

- {scientificName && ( -

- {scientificName} -

- )} -
- - {isLoading ? ( -
- - - -
- ) : extract ? ( -

- {extract} -

- ) : ( -

- Heard at {new Date(event.created_at * 1000).toLocaleString()}. -

- )} -
- - {/* Reference recording from Wikipedia/Commons, when available. - * `BirdSongPlayer` returns null when the article has no - * usable audio, so the right-hand column collapses - * cleanly and the text reflows across the full card. - * The click handler stops propagation so toggling - * playback doesn't also navigate to `/i/...`. */} - {wikipediaTitle && ( -
{ - e.stopPropagation(); - e.preventDefault(); - }} - className="shrink-0" - > - -
- )} -
-
- - - {note && ( -

- {note} -

- )} -
- ); -} diff --git a/src/components/BirdSongPlayer.tsx b/src/components/BirdSongPlayer.tsx deleted file mode 100644 index 19e131e9..00000000 --- a/src/components/BirdSongPlayer.tsx +++ /dev/null @@ -1,181 +0,0 @@ -import { useEffect, useRef, useState } from 'react'; -import { Play } from 'lucide-react'; - -import { Skeleton } from '@/components/ui/skeleton'; -import { useBirdSong, type BirdSong } from '@/hooks/useBirdSong'; -import { cn } from '@/lib/utils'; - -/** - * Inline bird-song play button for Wikipedia species pages. - * - * Looks up a reference recording from the article (via - * `useBirdSong` → Wikipedia/Commons) and renders a circular - * toggle. Clicking plays the song on loop; the play triangle is - * replaced by an animated equaliser so the single control both - * triggers and indicates playback. The `