diff --git a/package-lock.json b/package-lock.json index af5ed65..e4081ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "jumble-imwald", - "version": "13.1", + "version": "13.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "jumble-imwald", - "version": "13.1", + "version": "13.2", "license": "MIT", "dependencies": { "@asciidoctor/core": "^3.0.4", diff --git a/package.json b/package.json index 569c59a..0b0f936 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jumble-imwald", - "version": "13.1", + "version": "13.2", "description": "A user-friendly Nostr client focused on relay feed browsing and relay discovery, forked from Jumble", "private": true, "type": "module", diff --git a/src/PageManager.tsx b/src/PageManager.tsx index 2009ced..05c5764 100644 --- a/src/PageManager.tsx +++ b/src/PageManager.tsx @@ -283,25 +283,25 @@ export function useSmartSettingsNavigation() { // Use primary note view to show settings since secondary panel is disabled if (url === '/settings') { window.history.pushState(null, '', url) - setPrimaryNoteView(, 'settings') + setPrimaryNoteView(, 'settings') } else if (url.startsWith('/settings/relays')) { window.history.pushState(null, '', url) - setPrimaryNoteView(, 'settings-sub') + setPrimaryNoteView(, 'settings-sub') } else if (url === '/settings/wallet') { window.history.pushState(null, '', url) - setPrimaryNoteView(, 'settings-sub') + setPrimaryNoteView(, 'settings-sub') } else if (url === '/settings/posts') { window.history.pushState(null, '', url) - setPrimaryNoteView(, 'settings-sub') + setPrimaryNoteView(, 'settings-sub') } else if (url === '/settings/general') { window.history.pushState(null, '', url) - setPrimaryNoteView(, 'settings-sub') + setPrimaryNoteView(, 'settings-sub') } else if (url === '/settings/translation') { window.history.pushState(null, '', url) - setPrimaryNoteView(, 'settings-sub') + setPrimaryNoteView(, 'settings-sub') } else if (url === '/settings/rss-feeds') { window.history.pushState(null, '', url) - setPrimaryNoteView(, 'settings-sub') + setPrimaryNoteView(, 'settings-sub') } } diff --git a/src/components/NormalFeed/index.tsx b/src/components/NormalFeed/index.tsx index 6e8c579..ce85d60 100644 --- a/src/components/NormalFeed/index.tsx +++ b/src/components/NormalFeed/index.tsx @@ -1,5 +1,5 @@ import NoteList, { TNoteListRef } from '@/components/NoteList' -import Tabs from '@/components/Tabs' +import Tabs, { TabDefinition } from '@/components/Tabs' import logger from '@/lib/logger' import { useKindFilter } from '@/providers/KindFilterProvider' import { useUserTrust } from '@/providers/UserTrustProvider' @@ -12,6 +12,7 @@ import RssFeedList from '../RssFeedList' import { useNostr } from '@/providers/NostrProvider' import rssFeedService from '@/services/rss-feed.service' import { DEFAULT_RSS_FEEDS } from '@/constants' +import { Rss } from 'lucide-react' const NormalFeed = forwardRef { + const handleSwitchToRss = () => { + if (showRssFeed) { + setActiveTab('rss') + if (noteListRef && typeof noteListRef !== 'function') { + noteListRef.current?.scrollToTop('smooth') + } + } + } + + window.addEventListener('switchToRssFeed', handleSwitchToRss) + return () => { + window.removeEventListener('switchToRssFeed', handleSwitchToRss) + } + }, [showRssFeed, noteListRef]) + const handleListModeChange = (mode: TNoteListMode | string) => { if (mode === 'rss') { setActiveTab('rss') @@ -90,14 +108,14 @@ const NormalFeed = forwardRef { - const baseTabs = [ + const tabs = useMemo((): TabDefinition[] => { + const baseTabs: TabDefinition[] = [ { value: 'posts', label: 'Notes' }, { value: 'postsAndReplies', label: 'Replies' } ] if (showRssFeed) { - baseTabs.push({ value: 'rss', label: 'RSS' }) + baseTabs.push({ value: 'rss', label: 'RSS', icon: }) } return baseTabs diff --git a/src/components/Sidebar/RssButton.tsx b/src/components/Sidebar/RssButton.tsx new file mode 100644 index 0000000..d09ac00 --- /dev/null +++ b/src/components/Sidebar/RssButton.tsx @@ -0,0 +1,35 @@ +import { usePrimaryPage, usePrimaryNoteView } from '@/PageManager' +import { Rss } from 'lucide-react' +import SidebarItem from './SidebarItem' +import storage from '@/services/local-storage.service' + +export default function RssButton() { + const { navigate, current, display } = usePrimaryPage() + const { primaryViewType } = usePrimaryNoteView() + const showRssFeed = storage.getShowRssFeed() + + // RSS is active when on home page and RSS tab would be active + // We can't directly check if RSS tab is active, so we'll just check if we're on home + const isActive = display && current === 'home' && primaryViewType === null && showRssFeed + + const handleClick = () => { + // Navigate to home if not already there + if (current !== 'home' || primaryViewType !== null) { + navigate('home') + // Wait a bit for navigation to complete, then switch to RSS + setTimeout(() => { + window.dispatchEvent(new CustomEvent('switchToRssFeed')) + }, 100) + } else { + // Already on home, just switch to RSS tab + window.dispatchEvent(new CustomEvent('switchToRssFeed')) + } + } + + return ( + + + + ) +} + diff --git a/src/components/Sidebar/index.tsx b/src/components/Sidebar/index.tsx index 760b520..122eaf6 100644 --- a/src/components/Sidebar/index.tsx +++ b/src/components/Sidebar/index.tsx @@ -8,11 +8,14 @@ import HomeButton from './HomeButton' import NotificationsButton from './NotificationButton' import PostButton from './PostButton' import ProfileButton from './ProfileButton' +import RssButton from './RssButton' import SearchButton from './SearchButton' import SettingsButton from './SettingsButton' +import storage from '@/services/local-storage.service' export default function PrimaryPageSidebar() { const { isSmallScreen } = useScreenSize() + const showRssFeed = storage.getShowRssFeed() if (isSmallScreen) return null return ( @@ -33,6 +36,7 @@ export default function PrimaryPageSidebar() { + {showRssFeed && } diff --git a/src/components/Tabs/index.tsx b/src/components/Tabs/index.tsx index b7be7e0..806732b 100644 --- a/src/components/Tabs/index.tsx +++ b/src/components/Tabs/index.tsx @@ -3,9 +3,10 @@ import { useDeepBrowsing } from '@/providers/DeepBrowsingProvider' import { ReactNode, useCallback, useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' -type TabDefinition = { +export type TabDefinition = { value: string label: string + icon?: ReactNode } export default function Tabs({ @@ -134,13 +135,14 @@ export default function Tabs({ key={tab.value} ref={(el) => (tabRefs.current[index] = el)} className={cn( - `text-center py-2 px-2 sm:px-4 md:px-6 font-semibold whitespace-nowrap clickable cursor-pointer rounded-lg text-xs sm:text-sm md:text-base shrink-0`, + `text-center py-2 px-2 sm:px-4 md:px-6 font-semibold whitespace-nowrap clickable cursor-pointer rounded-lg text-xs sm:text-sm md:text-base shrink-0 flex items-center gap-2 justify-center`, value === tab.value ? '' : 'text-muted-foreground' )} onClick={() => { onTabChange?.(tab.value) }} > + {tab.icon && {tab.icon}} {t(tab.label)} ))} diff --git a/src/pages/primary/NoteListPage/index.tsx b/src/pages/primary/NoteListPage/index.tsx index b386609..7b7fa14 100644 --- a/src/pages/primary/NoteListPage/index.tsx +++ b/src/pages/primary/NoteListPage/index.tsx @@ -1,4 +1,3 @@ -import { usePrimaryNoteView } from '@/PageManager' import BookmarkList from '@/components/BookmarkList' import RelayInfo from '@/components/RelayInfo' import VersionUpdateBanner from '@/components/VersionUpdateBanner' @@ -9,7 +8,7 @@ import { useFeed } from '@/providers/FeedProvider' import { useNostr } from '@/providers/NostrProvider' import { useScreenSize } from '@/providers/ScreenSizeProvider' import { TPageRef } from '@/types' -import { Info } from 'lucide-react' +import { Info, Rss } from 'lucide-react' import { Dispatch, forwardRef, @@ -26,6 +25,8 @@ import AccountButton from '@/components/Titlebar/AccountButton' import FollowingFeed from './FollowingFeed' import RelaysFeed from './RelaysFeed' import logger from '@/lib/logger' +import { usePrimaryPage, usePrimaryNoteView } from '@/PageManager' +import storage from '@/services/local-storage.service' const NoteListPage = forwardRef((_, ref) => { logger.debug('NoteListPage component rendering') @@ -130,6 +131,24 @@ function NoteListPageTitlebar({ }) { const { isSmallScreen } = useScreenSize() const { setPrimaryNoteView } = usePrimaryNoteView() + const { navigate, current } = usePrimaryPage() + const { primaryViewType } = usePrimaryNoteView() + const showRssFeed = storage.getShowRssFeed() + + const handleRssClick = (e: React.MouseEvent) => { + e.stopPropagation() + // Navigate to home if not already there + if (current !== 'home' || primaryViewType !== null) { + navigate('home') + // Wait a bit for navigation to complete, then switch to RSS + setTimeout(() => { + window.dispatchEvent(new CustomEvent('switchToRssFeed')) + }, 100) + } else { + // Already on home, just switch to RSS tab + window.dispatchEvent(new CustomEvent('switchToRssFeed')) + } + } return (
@@ -153,6 +172,16 @@ function NoteListPageTitlebar({
)}
+ {isSmallScreen && showRssFeed && ( + + )} {setShowRelayDetails && (