Browse Source

get rid of secondary panel completely

imwald
Silberengel 5 months ago
parent
commit
bdb6b421a9
  1. 235
      src/PageManager.tsx
  2. 17
      src/components/BottomNavigationBar/SearchButton.tsx
  3. 26
      src/components/BottomNavigationBar/WriteButton.tsx
  4. 4
      src/components/BottomNavigationBar/index.tsx
  5. 20
      src/components/ReplyNoteList/index.tsx
  6. 6
      src/components/Sidebar/SettingsButton.tsx
  7. 52
      src/pages/primary/NoteListPage/index.tsx
  8. 8
      src/pages/primary/SearchPage/index.tsx
  9. 3
      src/pages/secondary/FollowingListPage/index.tsx
  10. 18
      src/pages/secondary/GeneralSettingsPage/index.tsx
  11. 13
      src/pages/secondary/HomePage/index.tsx
  12. 3
      src/pages/secondary/MuteListPage/index.tsx
  13. 41
      src/pages/secondary/NotePage/index.tsx
  14. 3
      src/pages/secondary/OthersRelaySettingsPage/index.tsx
  15. 15
      src/pages/secondary/SearchPage/index.tsx
  16. 35
      src/providers/UserPreferencesProvider.tsx

235
src/PageManager.tsx

@ -4,21 +4,22 @@ import { cn } from '@/lib/utils' @@ -4,21 +4,22 @@ import { cn } from '@/lib/utils'
import logger from '@/lib/logger'
import { ChevronLeft } from 'lucide-react'
import NoteListPage from '@/pages/primary/NoteListPage'
import HomePage from '@/pages/secondary/HomePage'
import NotePage from '@/pages/secondary/NotePage'
// Page imports needed for primary note view
import SettingsPage from '@/pages/secondary/SettingsPage'
import RelaySettingsPage from '@/pages/secondary/RelaySettingsPage'
import WalletPage from '@/pages/secondary/WalletPage'
import PostSettingsPage from '@/pages/secondary/PostSettingsPage'
import GeneralSettingsPage from '@/pages/secondary/GeneralSettingsPage'
import TranslationPage from '@/pages/secondary/TranslationPage'
import NotePage from '@/pages/secondary/NotePage'
import SecondaryProfilePage from '@/pages/secondary/ProfilePage'
import FollowingListPage from '@/pages/secondary/FollowingListPage'
import MuteListPage from '@/pages/secondary/MuteListPage'
import OthersRelaySettingsPage from '@/pages/secondary/OthersRelaySettingsPage'
import SecondaryRelayPage from '@/pages/secondary/RelayPage'
import { CurrentRelaysProvider } from '@/providers/CurrentRelaysProvider'
import { NotificationProvider } from '@/providers/NotificationProvider'
import { useUserPreferences } from '@/providers/UserPreferencesProvider'
// DEPRECATED: useUserPreferences removed - double-panel functionality disabled
import { TPageRef } from '@/types'
import {
cloneElement,
@ -94,8 +95,8 @@ const PrimaryPageContext = createContext<TPrimaryPageContext | undefined>(undefi @@ -94,8 +95,8 @@ const PrimaryPageContext = createContext<TPrimaryPageContext | undefined>(undefi
const SecondaryPageContext = createContext<TSecondaryPageContext | undefined>(undefined)
const PrimaryNoteViewContext = createContext<{
setPrimaryNoteView: (view: ReactNode | null, type?: 'note' | 'settings' | 'settings-sub' | 'profile' | 'hashtag') => void
primaryViewType: 'note' | 'settings' | 'settings-sub' | 'profile' | 'hashtag' | null
setPrimaryNoteView: (view: ReactNode | null, type?: 'note' | 'settings' | 'settings-sub' | 'profile' | 'hashtag' | 'relay') => void
primaryViewType: 'note' | 'settings' | 'settings-sub' | 'profile' | 'hashtag' | 'relay' | null
} | undefined>(undefined)
export function usePrimaryPage() {
@ -122,168 +123,110 @@ export function usePrimaryNoteView() { @@ -122,168 +123,110 @@ export function usePrimaryNoteView() {
return context
}
// Custom hook for intelligent note navigation
// Fixed: Note navigation now uses primary note view since secondary panel is disabled
export function useSmartNoteNavigation() {
const { showRecommendedRelaysPanel } = useUserPreferences()
const { push: pushSecondary } = useSecondaryPage()
const { setPrimaryNoteView } = usePrimaryNoteView()
const navigateToNote = (url: string) => {
if (!showRecommendedRelaysPanel) {
// When right panel is hidden, show note in primary area
// Use primary note view to show notes since secondary panel is disabled
// Extract note ID from URL (e.g., "/notes/note1..." -> "note1...")
const noteId = url.replace('/notes/', '')
window.history.replaceState(null, '', url)
setPrimaryNoteView(<NotePage id={noteId} index={0} hideTitlebar={true} />, 'note')
} else {
// Normal behavior - use secondary navigation
pushSecondary(url)
}
}
return { navigateToNote }
}
// Custom hook for intelligent relay navigation
// Fixed: Relay navigation now uses primary note view since secondary panel is disabled
export function useSmartRelayNavigation() {
const { showRecommendedRelaysPanel } = useUserPreferences()
const { push: pushSecondary } = useSecondaryPage()
const { navigate: navigatePrimary } = usePrimaryPage()
const { setPrimaryNoteView } = usePrimaryNoteView()
const navigateToRelay = (url: string) => {
if (!showRecommendedRelaysPanel) {
// When right panel is hidden, navigate to relay page in primary area
// Extract relay URL from the path (e.g., "/relays/wss%3A%2F%2F..." -> "wss://...")
const relayUrl = url.startsWith('/relays/') ? decodeURIComponent(url.replace('/relays/', '')) : url
navigatePrimary('relay', { url: relayUrl })
} else {
// Normal behavior - use secondary navigation
pushSecondary(url)
}
// Use primary note view to show relay pages since secondary panel is disabled
// Extract relay URL from the URL (e.g., "/relays/wss://..." -> "wss://...")
const relayUrl = url.replace('/relays/', '')
window.history.replaceState(null, '', url)
setPrimaryNoteView(<SecondaryRelayPage url={relayUrl} index={0} hideTitlebar={true} />, 'relay')
}
return { navigateToRelay }
}
// Custom hook for intelligent profile navigation
// Fixed: Profile navigation now uses primary note view since secondary panel is disabled
export function useSmartProfileNavigation() {
const { showRecommendedRelaysPanel } = useUserPreferences()
const { push: pushSecondary } = useSecondaryPage()
const { setPrimaryNoteView } = usePrimaryNoteView()
const navigateToProfile = (url: string) => {
if (showRecommendedRelaysPanel) {
// Secondary panel is available - show profile in secondary panel
pushSecondary(url)
} else {
// Secondary panel is not available - show profile in primary panel
// Use primary note view to show profiles since secondary panel is disabled
const profileId = url.replace('/users/', '')
window.history.replaceState(null, '', url)
setPrimaryNoteView(<SecondaryProfilePage id={profileId} index={0} hideTitlebar={true} />, 'profile')
}
}
return { navigateToProfile }
}
// Custom hook for intelligent hashtag navigation
// Fixed: Hashtag navigation now uses primary note view since secondary panel is disabled
export function useSmartHashtagNavigation() {
const { showRecommendedRelaysPanel } = useUserPreferences()
const { push: pushSecondary } = useSecondaryPage()
const { setPrimaryNoteView } = usePrimaryNoteView()
const navigateToHashtag = (url: string) => {
if (!showRecommendedRelaysPanel) {
// When right panel is hidden, show hashtag feed in primary area
// Extract hashtag from URL (e.g., "/notes?t=hashtag" -> "hashtag")
const urlObj = new URL(url, window.location.origin)
const hashtag = urlObj.searchParams.get('t')
if (hashtag) {
// Use primary note view to show hashtag feed since secondary panel is disabled
window.history.replaceState(null, '', url)
setPrimaryNoteView(<NoteListPage />, 'hashtag')
}
} else {
// Normal behavior - use secondary navigation
pushSecondary(url)
}
}
return { navigateToHashtag }
}
// Custom hook for intelligent following list navigation
// Fixed: Following list navigation now uses primary note view since secondary panel is disabled
export function useSmartFollowingListNavigation() {
const { showRecommendedRelaysPanel } = useUserPreferences()
const { push: pushSecondary } = useSecondaryPage()
const { setPrimaryNoteView } = usePrimaryNoteView()
const navigateToFollowingList = (url: string) => {
if (!showRecommendedRelaysPanel) {
// When right panel is hidden, show following list in primary area
// Extract profile ID from URL (e.g., "/users/npub1.../following" -> "npub1...")
// Use primary note view to show following list since secondary panel is disabled
const profileId = url.replace('/users/', '').replace('/following', '')
window.history.replaceState(null, '', url)
setPrimaryNoteView(<FollowingListPage id={profileId} index={0} />, 'profile')
} else {
// Normal behavior - use secondary navigation
pushSecondary(url)
}
setPrimaryNoteView(<FollowingListPage id={profileId} index={0} hideTitlebar={true} />, 'profile')
}
return { navigateToFollowingList }
}
// Custom hook for intelligent mute list navigation
// Fixed: Mute list navigation now uses primary note view since secondary panel is disabled
export function useSmartMuteListNavigation() {
const { showRecommendedRelaysPanel } = useUserPreferences()
const { push: pushSecondary } = useSecondaryPage()
const { setPrimaryNoteView } = usePrimaryNoteView()
const navigateToMuteList = (url: string) => {
if (!showRecommendedRelaysPanel) {
// When right panel is hidden, show mute list in primary area
// Use primary note view to show mute list since secondary panel is disabled
window.history.replaceState(null, '', url)
setPrimaryNoteView(<MuteListPage index={0} />, 'settings')
} else {
// Normal behavior - use secondary navigation
pushSecondary(url)
}
setPrimaryNoteView(<MuteListPage index={0} hideTitlebar={true} />, 'settings')
}
return { navigateToMuteList }
}
// Custom hook for intelligent others relay settings navigation
// Fixed: Others relay settings navigation now uses primary note view since secondary panel is disabled
export function useSmartOthersRelaySettingsNavigation() {
const { showRecommendedRelaysPanel } = useUserPreferences()
const { push: pushSecondary } = useSecondaryPage()
const { setPrimaryNoteView } = usePrimaryNoteView()
const navigateToOthersRelaySettings = (url: string) => {
if (!showRecommendedRelaysPanel) {
// When right panel is hidden, show others relay settings in primary area
// Extract profile ID from URL (e.g., "/users/npub1.../relays" -> "npub1...")
// Use primary note view to show others relay settings since secondary panel is disabled
const profileId = url.replace('/users/', '').replace('/relays', '')
window.history.replaceState(null, '', url)
setPrimaryNoteView(<OthersRelaySettingsPage id={profileId} index={0} />, 'profile')
} else {
// Normal behavior - use secondary navigation
pushSecondary(url)
}
setPrimaryNoteView(<OthersRelaySettingsPage id={profileId} index={0} hideTitlebar={true} />, 'profile')
}
return { navigateToOthersRelaySettings }
}
// Custom hook for intelligent settings navigation
// Fixed: Settings navigation now uses primary note view since secondary panel is disabled
export function useSmartSettingsNavigation() {
const { showRecommendedRelaysPanel } = useUserPreferences()
const { push: pushSecondary } = useSecondaryPage()
const { setPrimaryNoteView } = usePrimaryNoteView()
const navigateToSettings = (url: string) => {
if (!showRecommendedRelaysPanel) {
// When right panel is hidden, show settings page in primary area
// Use primary note view to show settings since secondary panel is disabled
if (url === '/settings') {
window.history.replaceState(null, '', url)
setPrimaryNoteView(<SettingsPage index={0} hideTitlebar={true} />, 'settings')
@ -303,58 +246,65 @@ export function useSmartSettingsNavigation() { @@ -303,58 +246,65 @@ export function useSmartSettingsNavigation() {
window.history.replaceState(null, '', url)
setPrimaryNoteView(<TranslationPage index={0} hideTitlebar={true} />, 'settings-sub')
}
} else {
// Normal behavior - use secondary navigation
pushSecondary(url)
}
}
return { navigateToSettings }
}
function ConditionalHomePage() {
const { showRecommendedRelaysPanel } = useUserPreferences()
if (!showRecommendedRelaysPanel) {
return null
}
return <HomePage />
// DEPRECATED: ConditionalHomePage removed - double-panel functionality disabled
// Helper function to get page title based on view type and URL
function getPageTitle(viewType: 'note' | 'settings' | 'settings-sub' | 'profile' | 'hashtag' | 'relay' | null, pathname: string): string {
if (viewType === 'settings') return 'Settings'
if (viewType === 'settings-sub') {
if (pathname.includes('/general')) return 'General Settings'
if (pathname.includes('/relays')) return 'Relay Settings'
if (pathname.includes('/wallet')) return 'Wallet Settings'
if (pathname.includes('/posts')) return 'Post Settings'
if (pathname.includes('/translation')) return 'Translation Settings'
return 'Settings'
}
if (viewType === 'profile') {
if (pathname.includes('/following')) return 'Following'
if (pathname.includes('/relays')) return 'Relay Settings'
return 'Profile'
}
if (viewType === 'hashtag') return 'Hashtag'
if (viewType === 'relay') return 'Relay'
if (viewType === 'note') {
// For now, return a generic "Note" - this could be enhanced to detect specific types
// by fetching the event and checking its kind
return 'Note'
}
return 'Page'
}
// DEPRECATED: Double-panel functionality removed - simplified to single column layout
function MainContentArea({
primaryPages,
currentPrimaryPage,
secondaryStack,
primaryNoteView,
primaryViewType,
setPrimaryNoteView
}: {
primaryPages: { name: TPrimaryPageName; element: ReactNode; props?: any }[]
currentPrimaryPage: TPrimaryPageName
secondaryStack: { index: number; component: ReactNode }[]
primaryNoteView: ReactNode | null
primaryViewType: 'note' | 'settings' | 'settings-sub' | 'profile' | 'hashtag' | null
setPrimaryNoteView: (view: ReactNode | null, type?: 'note' | 'settings' | 'settings-sub' | 'profile' | 'hashtag') => void
primaryViewType: 'note' | 'settings' | 'settings-sub' | 'profile' | 'hashtag' | 'relay' | null
setPrimaryNoteView: (view: ReactNode | null, type?: 'note' | 'settings' | 'settings-sub' | 'profile' | 'hashtag' | 'relay') => void
}) {
const { showRecommendedRelaysPanel } = useUserPreferences()
logger.debug('MainContentArea rendering:', {
currentPrimaryPage,
primaryPages: primaryPages.map(p => p.name),
showRecommendedRelaysPanel,
primaryNoteView: !!primaryNoteView
})
// If recommended relays panel is shown, use two-column layout
// Otherwise use single column layout
const gridClass = showRecommendedRelaysPanel ? "grid-cols-2" : "grid-cols-1"
// Always use single column layout since double-panel is disabled
return (
<div className={`grid ${gridClass} gap-2 w-full pr-2 py-2`}>
<div className="grid grid-cols-1 gap-2 w-full pr-2 py-2">
<div className="rounded-lg shadow-lg bg-background overflow-hidden">
{!showRecommendedRelaysPanel && primaryNoteView ? (
// Show note view with back button when right panel is hidden
{primaryNoteView ? (
// Show note view with back button
<div className="flex flex-col h-full w-full">
<div className="flex gap-1 p-1 items-center justify-between font-semibold border-b">
<div className="flex items-center flex-1 w-0">
@ -362,18 +312,30 @@ function MainContentArea({ @@ -362,18 +312,30 @@ function MainContentArea({
className="flex gap-1 items-center w-fit max-w-full justify-start pl-2 pr-3"
variant="ghost"
size="titlebar-icon"
title="Back to feed"
onClick={() => setPrimaryNoteView(null)}
title="Back"
onClick={() => {
if (primaryViewType === 'settings-sub') {
// For settings sub-pages, navigate back to main settings page
window.history.replaceState(null, '', '/settings')
setPrimaryNoteView(<SettingsPage index={0} hideTitlebar={true} />, 'settings')
} else {
// For other pages, go back to feed
setPrimaryNoteView(null)
}
}}
>
<ChevronLeft />
<div className="truncate text-lg font-semibold">
{primaryViewType === 'settings' ? 'Settings' :
primaryViewType === 'settings-sub' ? 'Settings' :
primaryViewType === 'profile' ? 'Back' :
primaryViewType === 'hashtag' ? 'Hashtag' : 'Note'}
Back
</div>
</Button>
</div>
<div className="flex-1 flex justify-center">
<div className="text-lg font-semibold text-green-500">
{getPageTitle(primaryViewType, window.location.pathname)}
</div>
</div>
<div className="flex-1 w-0"></div>
</div>
<div className="flex-1 overflow-auto">
{primaryNoteView}
@ -406,33 +368,14 @@ function MainContentArea({ @@ -406,33 +368,14 @@ function MainContentArea({
})
)}
</div>
{showRecommendedRelaysPanel && (
<div className="rounded-lg shadow-lg bg-background overflow-hidden">
{secondaryStack.map((item, index) => (
<div
key={item.index}
className="flex flex-col h-full w-full"
style={{ display: index === secondaryStack.length - 1 ? 'block' : 'none' }}
>
{item.component}
</div>
))}
<div
key="home"
className="w-full"
style={{ display: secondaryStack.length === 0 ? 'block' : 'none' }}
>
<ConditionalHomePage />
</div>
</div>
)}
{/* DEPRECATED: Secondary panel removed - double-panel functionality disabled */}
</div>
)
}
export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
const { isSmallScreen } = useScreenSize()
const { showRecommendedRelaysPanel } = useUserPreferences()
// DEPRECATED: showRecommendedRelaysPanel removed - double-panel functionality disabled
const [currentPrimaryPage, setCurrentPrimaryPage] = useState<TPrimaryPageName>('home')
const [primaryPages, setPrimaryPages] = useState<
{ name: TPrimaryPageName; element: ReactNode; props?: any }[]
@ -444,10 +387,10 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) { @@ -444,10 +387,10 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
])
const [secondaryStack, setSecondaryStack] = useState<TStackItem[]>([])
const [primaryNoteView, setPrimaryNoteViewState] = useState<ReactNode | null>(null)
const [primaryViewType, setPrimaryViewType] = useState<'note' | 'settings' | 'settings-sub' | 'profile' | 'hashtag' | null>(null)
const [primaryViewType, setPrimaryViewType] = useState<'note' | 'settings' | 'settings-sub' | 'profile' | 'hashtag' | 'relay' | null>(null)
const [savedPrimaryPage, setSavedPrimaryPage] = useState<TPrimaryPageName | null>(null)
const setPrimaryNoteView = (view: ReactNode | null, type?: 'note' | 'settings' | 'settings-sub' | 'profile' | 'hashtag') => {
const setPrimaryNoteView = (view: ReactNode | null, type?: 'note' | 'settings' | 'settings-sub' | 'profile' | 'hashtag' | 'relay') => {
if (view && !primaryNoteView) {
// Saving current primary page before showing overlay
setSavedPrimaryPage(currentPrimaryPage)
@ -486,11 +429,7 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) { @@ -486,11 +429,7 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
if (window.location.pathname !== '/') {
const url = window.location.pathname + window.location.search + window.location.hash
// If the side panel is off and we're on a settings page, don't add to secondary stack
// The settings navigation will handle it via primary view
if (!showRecommendedRelaysPanel && window.location.pathname.startsWith('/settings')) {
// Skip secondary stack handling for settings when side panel is off
} else {
// DEPRECATED: Double-panel logic removed - always add to secondary stack
setSecondaryStack((prevStack) => {
if (isCurrentPage(prevStack, url)) return prevStack
@ -505,7 +444,6 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) { @@ -505,7 +444,6 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
}
return newStack
})
}
} else {
const searchParams = new URLSearchParams(window.location.search)
const r = searchParams.get('r')
@ -769,7 +707,6 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) { @@ -769,7 +707,6 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
<MainContentArea
primaryPages={primaryPages}
currentPrimaryPage={currentPrimaryPage}
secondaryStack={secondaryStack}
primaryNoteView={primaryNoteView}
primaryViewType={primaryViewType}
setPrimaryNoteView={setPrimaryNoteView}

17
src/components/BottomNavigationBar/SearchButton.tsx

@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
import { usePrimaryPage, usePrimaryNoteView } from '@/PageManager'
import { Search } from 'lucide-react'
import BottomNavigationBarItem from './BottomNavigationBarItem'
export default function SearchButton() {
const { navigate, current, display } = usePrimaryPage()
const { primaryViewType } = usePrimaryNoteView()
return (
<BottomNavigationBarItem
active={current === 'search' && display && primaryViewType === null}
onClick={() => navigate('search')}
>
<Search />
</BottomNavigationBarItem>
)
}

26
src/components/BottomNavigationBar/WriteButton.tsx

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
import PostEditor from '@/components/PostEditor'
import { useNostr } from '@/providers/NostrProvider'
import { PencilLine } from 'lucide-react'
import { useState } from 'react'
import BottomNavigationBarItem from './BottomNavigationBarItem'
export default function WriteButton() {
const { checkLogin } = useNostr()
const [open, setOpen] = useState(false)
return (
<>
<BottomNavigationBarItem
onClick={(e) => {
e.stopPropagation()
checkLogin(() => {
setOpen(true)
})
}}
>
<PencilLine />
</BottomNavigationBarItem>
<PostEditor open={open} setOpen={setOpen} />
</>
)
}

4
src/components/BottomNavigationBar/index.tsx

@ -2,6 +2,8 @@ import { cn } from '@/lib/utils' @@ -2,6 +2,8 @@ import { cn } from '@/lib/utils'
import HomeButton from './HomeButton'
import NotificationsButton from './NotificationsButton'
import DiscussionsButton from './DiscussionsButton'
import SearchButton from './SearchButton'
import WriteButton from './WriteButton'
export default function BottomNavigationBar() {
return (
@ -14,8 +16,10 @@ export default function BottomNavigationBar() { @@ -14,8 +16,10 @@ export default function BottomNavigationBar() {
paddingBottom: 'env(safe-area-inset-bottom)'
}}
>
<WriteButton />
<DiscussionsButton />
<HomeButton />
<SearchButton />
<NotificationsButton />
</div>
)

20
src/components/ReplyNoteList/index.tsx

@ -20,7 +20,7 @@ import { useNostr } from '@/providers/NostrProvider' @@ -20,7 +20,7 @@ import { useNostr } from '@/providers/NostrProvider'
import { useReply } from '@/providers/ReplyProvider'
import { useFeed } from '@/providers/FeedProvider'
import { useUserTrust } from '@/providers/UserTrustProvider'
import { useUserPreferences } from '@/providers/UserPreferencesProvider'
// DEPRECATED: useUserPreferences removed - double-panel functionality disabled
import client from '@/services/client.service'
import noteStatsService from '@/services/note-stats.service'
import { Filter, Event as NEvent, kinds } from 'nostr-tools'
@ -47,7 +47,7 @@ function ReplyNoteList({ index: _index, event, sort = 'oldest' }: { index?: numb @@ -47,7 +47,7 @@ function ReplyNoteList({ index: _index, event, sort = 'oldest' }: { index?: numb
const { hideContentMentioningMutedUsers } = useContentPolicy()
const { relayList: userRelayList } = useNostr()
const { relayUrls: currentFeedRelays } = useFeed()
const { showRecommendedRelaysPanel } = useUserPreferences()
// DEPRECATED: showRecommendedRelaysPanel removed - double-panel functionality disabled
const [rootInfo, setRootInfo] = useState<TRootInfo | undefined>(undefined)
const { repliesMap, addReplies } = useReply()
@ -561,7 +561,6 @@ function ReplyNoteList({ index: _index, event, sort = 'oldest' }: { index?: numb @@ -561,7 +561,6 @@ function ReplyNoteList({ index: _index, event, sort = 'oldest' }: { index?: numb
logger.debug('[ReplyNoteList] onClickParent called:', {
parentEventHexId: parentEventHexId?.substring(0, 8),
parentEventId: parentEventId?.substring(0, 8),
showRecommendedRelaysPanel,
repliesCount: replies.length,
parentInReplies: !replies.every((r) => r.id !== parentEventHexId)
})
@ -578,13 +577,9 @@ function ReplyNoteList({ index: _index, event, sort = 'oldest' }: { index?: numb @@ -578,13 +577,9 @@ function ReplyNoteList({ index: _index, event, sort = 'oldest' }: { index?: numb
return
}
// If parent is not in current replies, we need to fetch it
// In single-panel mode, we should expand the thread to show the parent
// rather than navigating away from the current thread
if (!showRecommendedRelaysPanel) {
// Single-panel mode: fetch and add the parent to the thread
// This will expand the current thread to show the parent
logger.debug('[ReplyNoteList] Single-panel mode: fetching parent event')
// DEPRECATED: Double-panel logic removed - always expand thread to show parent
// Fetch and add the parent to the thread to expand the current thread
logger.debug('[ReplyNoteList] Fetching parent event to expand thread')
const fetchAndAddParent = async () => {
try {
logger.debug('[ReplyNoteList] Fetching parent event:', parentEventId ?? parentEventHexId)
@ -604,11 +599,6 @@ function ReplyNoteList({ index: _index, event, sort = 'oldest' }: { index?: numb @@ -604,11 +599,6 @@ function ReplyNoteList({ index: _index, event, sort = 'oldest' }: { index?: numb
}
}
fetchAndAddParent()
} else {
// Double-panel mode: navigate to parent in secondary panel
logger.debug('[ReplyNoteList] Double-panel mode: navigating to parent')
navigateToNote(toNote(parentEventId ?? parentEventHexId))
}
}}
highlight={highlightReplyId === reply.id}
/>

6
src/components/Sidebar/SettingsButton.tsx

@ -1,13 +1,13 @@ @@ -1,13 +1,13 @@
import { toSettings } from '@/lib/link'
import { useSmartSettingsNavigation, usePrimaryNoteView } from '@/PageManager'
import { useUserPreferences } from '@/providers/UserPreferencesProvider'
// DEPRECATED: useUserPreferences removed - double-panel functionality disabled
import { Settings } from 'lucide-react'
import SidebarItem from './SidebarItem'
export default function SettingsButton() {
const { navigateToSettings } = useSmartSettingsNavigation()
const { primaryViewType } = usePrimaryNoteView()
const { showRecommendedRelaysPanel } = useUserPreferences()
// DEPRECATED: showRecommendedRelaysPanel removed - double-panel functionality disabled
// Settings is active when:
// 1. primaryViewType is 'settings' or 'settings-sub' (when side panel is off)
@ -16,7 +16,7 @@ export default function SettingsButton() { @@ -16,7 +16,7 @@ export default function SettingsButton() {
const isActive =
primaryViewType === 'settings' ||
primaryViewType === 'settings-sub' ||
(showRecommendedRelaysPanel && url.startsWith('/settings'))
url.startsWith('/settings')
return (
<SidebarItem title="Settings" onClick={() => navigateToSettings(toSettings())} active={isActive}>

52
src/pages/primary/NoteListPage/index.tsx

@ -1,16 +1,14 @@ @@ -1,16 +1,14 @@
import { useSecondaryPage } from '@/PageManager'
import { usePrimaryPage } from '@/PageManager'
import BookmarkList from '@/components/BookmarkList'
import PostEditor from '@/components/PostEditor'
import RelayInfo from '@/components/RelayInfo'
import { Button } from '@/components/ui/button'
import PrimaryPageLayout from '@/layouts/PrimaryPageLayout'
import { toSearch } from '@/lib/link'
import { useCurrentRelays } from '@/providers/CurrentRelaysProvider'
import { useFeed } from '@/providers/FeedProvider'
import { useNostr } from '@/providers/NostrProvider'
import { useScreenSize } from '@/providers/ScreenSizeProvider'
import { TPageRef } from '@/types'
import { Info, PencilLine, Search } from 'lucide-react'
import { Info } from 'lucide-react'
import {
Dispatch,
forwardRef,
@ -129,6 +127,7 @@ function NoteListPageTitlebar({ @@ -129,6 +127,7 @@ function NoteListPageTitlebar({
setShowRelayDetails?: Dispatch<SetStateAction<boolean>>
}) {
const { isSmallScreen } = useScreenSize()
const { navigate } = usePrimaryPage()
return (
<div className="relative flex gap-1 items-center h-full justify-between">
@ -138,9 +137,12 @@ function NoteListPageTitlebar({ @@ -138,9 +137,12 @@ function NoteListPageTitlebar({
</div>
{isSmallScreen && (
<div className="absolute left-1/2 transform -translate-x-1/2">
<div className="text-green-600 dark:text-green-500 font-semibold text-sm">
<button
className="text-green-600 dark:text-green-500 font-semibold text-sm hover:text-green-700 dark:hover:text-green-400 transition-colors cursor-pointer"
onClick={() => navigate('home')}
>
Im Wald
</div>
</button>
</div>
)}
<div className="shrink-0 flex gap-1 items-center">
@ -161,47 +163,9 @@ function NoteListPageTitlebar({ @@ -161,47 +163,9 @@ function NoteListPageTitlebar({
<Info />
</Button>
)}
{isSmallScreen && (
<>
<SearchButton />
<PostButton />
</>
)}
<AccountButton />
</div>
</div>
)
}
function PostButton() {
const { checkLogin } = useNostr()
const [open, setOpen] = useState(false)
return (
<>
<Button
variant="ghost"
size="titlebar-icon"
onClick={(e) => {
e.stopPropagation()
checkLogin(() => {
setOpen(true)
})
}}
>
<PencilLine />
</Button>
<PostEditor open={open} setOpen={setOpen} />
</>
)
}
function SearchButton() {
const { push } = useSecondaryPage()
return (
<Button variant="ghost" size="titlebar-icon" onClick={() => push(toSearch())}>
<Search />
</Button>
)
}

8
src/pages/primary/SearchPage/index.tsx

@ -39,12 +39,14 @@ const SearchPage = forwardRef((_, ref) => { @@ -39,12 +39,14 @@ const SearchPage = forwardRef((_, ref) => {
<PrimaryPageLayout
ref={layoutRef}
pageName="search"
titlebar={
<SearchBar ref={searchBarRef} onSearch={onSearch} input={input} setInput={setInput} />
}
displayScrollToTopButton
>
<div className="px-4 pt-4">
<div className="text-2xl font-bold mb-4">Search Nostr</div>
<SearchBar ref={searchBarRef} onSearch={onSearch} input={input} setInput={setInput} />
<div className="h-4"></div>
<SearchResult searchParams={searchParams} />
</div>
</PrimaryPageLayout>
)
})

3
src/pages/secondary/FollowingListPage/index.tsx

@ -4,7 +4,7 @@ import SecondaryPageLayout from '@/layouts/SecondaryPageLayout' @@ -4,7 +4,7 @@ import SecondaryPageLayout from '@/layouts/SecondaryPageLayout'
import { forwardRef } from 'react'
import { useTranslation } from 'react-i18next'
const FollowingListPage = forwardRef(({ id, index }: { id?: string; index?: number }, ref) => {
const FollowingListPage = forwardRef(({ id, index, hideTitlebar = false }: { id?: string; index?: number; hideTitlebar?: boolean }, ref) => {
const { t } = useTranslation()
const { profile } = useFetchProfile(id)
const { followings } = useFetchFollowings(profile?.pubkey)
@ -18,6 +18,7 @@ const FollowingListPage = forwardRef(({ id, index }: { id?: string; index?: numb @@ -18,6 +18,7 @@ const FollowingListPage = forwardRef(({ id, index }: { id?: string; index?: numb
? t("username's following", { username: profile.username })
: t('Following')
}
hideBackButton={hideTitlebar}
displayScrollToTopButton
>
<ProfileList pubkeys={followings} />

18
src/pages/secondary/GeneralSettingsPage/index.tsx

@ -32,7 +32,7 @@ const GeneralSettingsPage = forwardRef(({ index, hideTitlebar = false }: { index @@ -32,7 +32,7 @@ const GeneralSettingsPage = forwardRef(({ index, hideTitlebar = false }: { index
setMediaAutoLoadPolicy
} = useContentPolicy()
const { hideUntrustedNotes, updateHideUntrustedNotes } = useUserTrust()
const { notificationListStyle, updateNotificationListStyle, showRecommendedRelaysPanel, updateShowRecommendedRelaysPanel } = useUserPreferences()
const { notificationListStyle, updateNotificationListStyle } = useUserPreferences()
const handleLanguageChange = (value: TLanguage) => {
i18n.changeLanguage(value)
@ -153,21 +153,7 @@ const GeneralSettingsPage = forwardRef(({ index, hideTitlebar = false }: { index @@ -153,21 +153,7 @@ const GeneralSettingsPage = forwardRef(({ index, hideTitlebar = false }: { index
</Label>
<Switch id="show-nsfw" checked={defaultShowNsfw} onCheckedChange={setDefaultShowNsfw} />
</SettingItem>
{!isSmallScreen && (
<SettingItem>
<Label htmlFor="show-recommended-relays" className="text-base font-normal">
<div>{t('Show recommended relays panel')}</div>
<div className="text-muted-foreground">
{t('Display the right-side panel with recommended relays on desktop')}
</div>
</Label>
<Switch
id="show-recommended-relays"
checked={showRecommendedRelaysPanel}
onCheckedChange={updateShowRecommendedRelaysPanel}
/>
</SettingItem>
)}
{/* DEPRECATED: Double-panel setting removed for technical debt reduction */}
<SettingItem>
<div>
<a

13
src/pages/secondary/HomePage/index.tsx

@ -15,7 +15,7 @@ const HomePage = forwardRef(({ index }: { index?: number }, ref) => { @@ -15,7 +15,7 @@ const HomePage = forwardRef(({ index }: { index?: number }, ref) => {
const { t } = useTranslation()
const { navigate } = usePrimaryPage()
const { navigateToRelay } = useSmartRelayNavigation()
const { updateShowRecommendedRelaysPanel } = useUserPreferences()
// DEPRECATED: updateShowRecommendedRelaysPanel removed - double-panel functionality disabled
const [recommendedRelayInfos, setRecommendedRelayInfos] = useState<TRelayInfo[]>([])
useEffect(() => {
@ -51,15 +51,8 @@ const HomePage = forwardRef(({ index }: { index?: number }, ref) => { @@ -51,15 +51,8 @@ const HomePage = forwardRef(({ index }: { index?: number }, ref) => {
</div>
}
controls={
<Button
variant="ghost"
size="icon"
className="h-6 w-6"
onClick={() => updateShowRecommendedRelaysPanel(false)}
title={t('Close')}
>
<X className="h-4 w-4" />
</Button>
// DEPRECATED: Close button removed - double-panel functionality disabled
null
}
hideBackButton
hideTitlebarBottomBorder

3
src/pages/secondary/MuteListPage/index.tsx

@ -12,7 +12,7 @@ import { forwardRef, useEffect, useMemo, useRef, useState } from 'react' @@ -12,7 +12,7 @@ import { forwardRef, useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import NotFoundPage from '../NotFoundPage'
const MuteListPage = forwardRef(({ index }: { index?: number }, ref) => {
const MuteListPage = forwardRef(({ index, hideTitlebar = false }: { index?: number; hideTitlebar?: boolean }, ref) => {
const { t } = useTranslation()
const { profile, pubkey } = useNostr()
const { getMutePubkeys } = useMuteList()
@ -61,6 +61,7 @@ const MuteListPage = forwardRef(({ index }: { index?: number }, ref) => { @@ -61,6 +61,7 @@ const MuteListPage = forwardRef(({ index }: { index?: number }, ref) => {
ref={ref}
index={index}
title={t("username's muted", { username: profile.username })}
hideBackButton={hideTitlebar}
displayScrollToTopButton
>
<div className="space-y-2 px-4 pt-2">

41
src/pages/secondary/NotePage/index.tsx

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
import { useSecondaryPage } from '@/PageManager'
import { ExtendedKind } from '@/constants'
import ContentPreview from '@/components/ContentPreview'
import Note from '@/components/Note'
import NoteInteractions from '@/components/NoteInteractions'
@ -7,7 +8,6 @@ import UserAvatar from '@/components/UserAvatar' @@ -7,7 +8,6 @@ import UserAvatar from '@/components/UserAvatar'
import { Card } from '@/components/ui/card'
import { Separator } from '@/components/ui/separator'
import { Skeleton } from '@/components/ui/skeleton'
import { ExtendedKind } from '@/constants'
import { useFetchEvent } from '@/hooks'
import SecondaryPageLayout from '@/layouts/SecondaryPageLayout'
import { getParentBech32Id, getParentETag, getRootBech32Id } from '@/lib/event'
@ -70,8 +70,45 @@ const NotePage = forwardRef(({ id, index, hideTitlebar = false }: { id?: string; @@ -70,8 +70,45 @@ const NotePage = forwardRef(({ id, index, hideTitlebar = false }: { id?: string;
)
}
const getNoteTypeTitle = (kind: number): string => {
switch (kind) {
case 1: // kinds.ShortTextNote
return 'Note: Text Post'
case 30023: // kinds.LongFormArticle
return 'Note: Longform Article'
case 20: // ExtendedKind.PICTURE
return 'Note: Picture'
case 21: // ExtendedKind.VIDEO
return 'Note: Video'
case 22: // ExtendedKind.SHORT_VIDEO
return 'Note: Short Video'
case 11: // ExtendedKind.DISCUSSION
return 'Note: Discussion Thread'
case 9802: // kinds.Highlights
return 'Note: Highlight'
case 1068: // ExtendedKind.POLL
return 'Note: Poll'
case 31987: // ExtendedKind.RELAY_REVIEW
return 'Note: Relay Review'
case 9735: // ExtendedKind.ZAP_RECEIPT
return 'Note: Zap Receipt'
case 6: // kinds.Repost
return 'Note: Repost'
case 7: // kinds.Reaction
return 'Note: Reaction'
case 1111: // ExtendedKind.COMMENT
return 'Note: Comment'
case 1222: // ExtendedKind.VOICE
return 'Note: Voice Post'
case 1244: // ExtendedKind.VOICE_COMMENT
return 'Note: Voice Comment'
default:
return 'Note'
}
}
return (
<SecondaryPageLayout ref={ref} index={index} title={hideTitlebar ? undefined : t('Note')} displayScrollToTopButton>
<SecondaryPageLayout ref={ref} index={index} title={hideTitlebar ? undefined : getNoteTypeTitle(finalEvent.kind)} displayScrollToTopButton>
<div className="px-4 pt-3">
{rootITag && <ExternalRoot value={rootITag[1]} />}
{rootEventId && rootEventId !== parentEventId && (

3
src/pages/secondary/OthersRelaySettingsPage/index.tsx

@ -4,7 +4,7 @@ import SecondaryPageLayout from '@/layouts/SecondaryPageLayout' @@ -4,7 +4,7 @@ import SecondaryPageLayout from '@/layouts/SecondaryPageLayout'
import { forwardRef } from 'react'
import { useTranslation } from 'react-i18next'
const RelaySettingsPage = forwardRef(({ id, index }: { id?: string; index?: number }, ref) => {
const RelaySettingsPage = forwardRef(({ id, index, hideTitlebar = false }: { id?: string; index?: number; hideTitlebar?: boolean }, ref) => {
const { t } = useTranslation()
const { profile } = useFetchProfile(id)
@ -17,6 +17,7 @@ const RelaySettingsPage = forwardRef(({ id, index }: { id?: string; index?: numb @@ -17,6 +17,7 @@ const RelaySettingsPage = forwardRef(({ id, index }: { id?: string; index?: numb
ref={ref}
index={index}
title={t("username's used relays", { username: profile.username })}
hideBackButton={hideTitlebar}
>
<div className="px-4 pt-3">
<OthersRelayList userId={id} />

15
src/pages/secondary/SearchPage/index.tsx

@ -50,17 +50,16 @@ const SearchPage = forwardRef(({ index, hideTitlebar = false }: { index?: number @@ -50,17 +50,16 @@ const SearchPage = forwardRef(({ index, hideTitlebar = false }: { index?: number
ref={ref}
index={index}
title={hideTitlebar ? undefined : "Search"}
titlebar={hideTitlebar ? undefined : (
<div className="flex items-center gap-1 h-full">
<Button variant="ghost" size="titlebar-icon" onClick={() => pop()}>
<ChevronLeft />
</Button>
<SearchBar ref={searchBarRef} input={input} setInput={setInput} onSearch={onSearch} />
</div>
)}
hideBackButton={hideTitlebar}
displayScrollToTopButton
>
<div className="px-4 pt-4">
<div className="text-2xl font-bold mb-4">Search Nostr</div>
<SearchBar ref={searchBarRef} input={input} setInput={setInput} onSearch={onSearch} />
<div className="h-4"></div>
<div className="text-xl font-semibold mb-4">Trending Notes</div>
<SearchResult searchParams={searchParams} />
</div>
</SecondaryPageLayout>
)
})

35
src/providers/UserPreferencesProvider.tsx

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
import storage from '@/services/local-storage.service'
import { TNotificationStyle } from '@/types'
import { createContext, useContext, useEffect, useState } from 'react'
import { createContext, useContext, useState } from 'react'
type TUserPreferencesContext = {
notificationListStyle: TNotificationStyle
@ -23,39 +23,20 @@ export function UserPreferencesProvider({ children }: { children: React.ReactNod @@ -23,39 +23,20 @@ export function UserPreferencesProvider({ children }: { children: React.ReactNod
const [notificationListStyle, setNotificationListStyle] = useState(
storage.getNotificationListStyle()
)
const [showRecommendedRelaysPanel, setShowRecommendedRelaysPanel] = useState(
storage.getShowRecommendedRelaysPanel()
)
// DEPRECATED: Double-panel functionality removed for technical debt reduction
// Keeping for backward compatibility in case we miss any references
const [showRecommendedRelaysPanel] = useState(false)
// Force showRecommendedRelaysPanel to true on mobile
useEffect(() => {
const handleResize = () => {
const isMobile = window.innerWidth <= 768
if (isMobile && !showRecommendedRelaysPanel) {
setShowRecommendedRelaysPanel(true)
storage.setShowRecommendedRelaysPanel(true)
}
}
// Check on mount and on resize
handleResize()
window.addEventListener('resize', handleResize)
return () => window.removeEventListener('resize', handleResize)
}, [showRecommendedRelaysPanel])
// DEPRECATED: Mobile panel forcing removed - double-panel functionality disabled
const updateNotificationListStyle = (style: TNotificationStyle) => {
setNotificationListStyle(style)
storage.setNotificationListStyle(style)
}
const updateShowRecommendedRelaysPanel = (show: boolean) => {
// Don't allow turning off the panel on mobile
const isMobile = window.innerWidth <= 768
if (isMobile && !show) {
return
}
setShowRecommendedRelaysPanel(show)
storage.setShowRecommendedRelaysPanel(show)
// DEPRECATED: Double-panel functionality disabled - always returns false
const updateShowRecommendedRelaysPanel = (_show: boolean) => {
// No-op: double-panel functionality has been removed
}
return (

Loading…
Cancel
Save