Browse Source

fix settings button and emoji picker

imwald
Silberengel 5 months ago
parent
commit
1820d47577
  1. 66
      src/PageManager.tsx
  2. 3
      src/components/EmojiPicker/index.tsx
  3. 7
      src/components/Sidebar/DiscussionsButton.tsx
  4. 7
      src/components/Sidebar/ExploreButton.tsx
  5. 11
      src/components/Sidebar/HomeButton.tsx
  6. 7
      src/components/Sidebar/NotificationButton.tsx
  7. 7
      src/components/Sidebar/ProfileButton.tsx
  8. 5
      src/components/Sidebar/SearchButton.tsx
  9. 16
      src/components/Sidebar/SettingsButton.tsx

66
src/PageManager.tsx

@ -91,6 +91,7 @@ const SecondaryPageContext = createContext<TSecondaryPageContext | undefined>(un
const PrimaryNoteViewContext = createContext<{ const PrimaryNoteViewContext = createContext<{
setPrimaryNoteView: (view: ReactNode | null, type?: 'note' | 'settings' | 'settings-sub' | 'profile') => void setPrimaryNoteView: (view: ReactNode | null, type?: 'note' | 'settings' | 'settings-sub' | 'profile') => void
primaryViewType: 'note' | 'settings' | 'settings-sub' | 'profile' | null
} | undefined>(undefined) } | undefined>(undefined)
export function usePrimaryPage() { export function usePrimaryPage() {
@ -128,7 +129,8 @@ export function useSmartNoteNavigation() {
// When right panel is hidden, show note in primary area // When right panel is hidden, show note in primary area
// Extract note ID from URL (e.g., "/notes/note1..." -> "note1...") // Extract note ID from URL (e.g., "/notes/note1..." -> "note1...")
const noteId = url.replace('/notes/', '') const noteId = url.replace('/notes/', '')
setPrimaryNoteView(<NotePage id={noteId} index={0} hideTitlebar={true} />, 'note') window.history.replaceState(null, '', url)
setPrimaryNoteView(<NotePage id={noteId} index={0} hideTitlebar={true} />, 'note')
} else { } else {
// Normal behavior - use secondary navigation // Normal behavior - use secondary navigation
pushSecondary(url) pushSecondary(url)
@ -170,6 +172,7 @@ export function useSmartProfileNavigation() {
// When right panel is hidden, show profile in primary area // When right panel is hidden, show profile in primary area
// Extract profile ID from URL (e.g., "/users/npub1..." -> "npub1...") // Extract profile ID from URL (e.g., "/users/npub1..." -> "npub1...")
const profileId = url.replace('/users/', '') const profileId = url.replace('/users/', '')
window.history.replaceState(null, '', url)
setPrimaryNoteView(<SecondaryProfilePage id={profileId} index={0} hideTitlebar={true} />, 'profile') setPrimaryNoteView(<SecondaryProfilePage id={profileId} index={0} hideTitlebar={true} />, 'profile')
} else { } else {
// Normal behavior - use secondary navigation // Normal behavior - use secondary navigation
@ -190,16 +193,22 @@ export function useSmartSettingsNavigation() {
if (!showRecommendedRelaysPanel) { if (!showRecommendedRelaysPanel) {
// When right panel is hidden, show settings page in primary area // When right panel is hidden, show settings page in primary area
if (url === '/settings') { if (url === '/settings') {
window.history.replaceState(null, '', url)
setPrimaryNoteView(<SettingsPage index={0} hideTitlebar={true} />, 'settings') setPrimaryNoteView(<SettingsPage index={0} hideTitlebar={true} />, 'settings')
} else if (url === '/settings/relays') { } else if (url === '/settings/relays') {
window.history.replaceState(null, '', url)
setPrimaryNoteView(<RelaySettingsPage index={0} hideTitlebar={true} />, 'settings-sub') setPrimaryNoteView(<RelaySettingsPage index={0} hideTitlebar={true} />, 'settings-sub')
} else if (url === '/settings/wallet') { } else if (url === '/settings/wallet') {
window.history.replaceState(null, '', url)
setPrimaryNoteView(<WalletPage index={0} hideTitlebar={true} />, 'settings-sub') setPrimaryNoteView(<WalletPage index={0} hideTitlebar={true} />, 'settings-sub')
} else if (url === '/settings/posts') { } else if (url === '/settings/posts') {
window.history.replaceState(null, '', url)
setPrimaryNoteView(<PostSettingsPage index={0} hideTitlebar={true} />, 'settings-sub') setPrimaryNoteView(<PostSettingsPage index={0} hideTitlebar={true} />, 'settings-sub')
} else if (url === '/settings/general') { } else if (url === '/settings/general') {
window.history.replaceState(null, '', url)
setPrimaryNoteView(<GeneralSettingsPage index={0} hideTitlebar={true} />, 'settings-sub') setPrimaryNoteView(<GeneralSettingsPage index={0} hideTitlebar={true} />, 'settings-sub')
} else if (url === '/settings/translation') { } else if (url === '/settings/translation') {
window.history.replaceState(null, '', url)
setPrimaryNoteView(<TranslationPage index={0} hideTitlebar={true} />, 'settings-sub') setPrimaryNoteView(<TranslationPage index={0} hideTitlebar={true} />, 'settings-sub')
} }
} else { } else {
@ -311,6 +320,7 @@ function MainContentArea({
export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) { export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
const { isSmallScreen } = useScreenSize() const { isSmallScreen } = useScreenSize()
const { showRecommendedRelaysPanel } = useUserPreferences()
const [currentPrimaryPage, setCurrentPrimaryPage] = useState<TPrimaryPageName>('home') const [currentPrimaryPage, setCurrentPrimaryPage] = useState<TPrimaryPageName>('home')
const [primaryPages, setPrimaryPages] = useState< const [primaryPages, setPrimaryPages] = useState<
{ name: TPrimaryPageName; element: ReactNode; props?: any }[] { name: TPrimaryPageName; element: ReactNode; props?: any }[]
@ -323,10 +333,22 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
const [secondaryStack, setSecondaryStack] = useState<TStackItem[]>([]) const [secondaryStack, setSecondaryStack] = useState<TStackItem[]>([])
const [primaryNoteView, setPrimaryNoteViewState] = useState<ReactNode | null>(null) const [primaryNoteView, setPrimaryNoteViewState] = useState<ReactNode | null>(null)
const [primaryViewType, setPrimaryViewType] = useState<'note' | 'settings' | 'settings-sub' | 'profile' | null>(null) const [primaryViewType, setPrimaryViewType] = useState<'note' | 'settings' | 'settings-sub' | 'profile' | null>(null)
const [savedPrimaryPage, setSavedPrimaryPage] = useState<TPrimaryPageName | null>(null)
const setPrimaryNoteView = (view: ReactNode | null, type?: 'note' | 'settings' | 'settings-sub' | 'profile') => { const setPrimaryNoteView = (view: ReactNode | null, type?: 'note' | 'settings' | 'settings-sub' | 'profile') => {
if (view && !primaryNoteView) {
// Saving current primary page before showing overlay
setSavedPrimaryPage(currentPrimaryPage)
}
setPrimaryNoteViewState(view) setPrimaryNoteViewState(view)
setPrimaryViewType(type || null) setPrimaryViewType(type || null)
// If clearing the view, restore to the saved primary page
if (!view && savedPrimaryPage) {
const newUrl = savedPrimaryPage === 'home' ? '/' : `/?page=${savedPrimaryPage}`
window.history.replaceState(null, '', newUrl)
}
} }
const ignorePopStateRef = useRef(false) const ignorePopStateRef = useRef(false)
@ -351,20 +373,27 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
window.history.pushState(null, '', window.location.href) window.history.pushState(null, '', window.location.href)
if (window.location.pathname !== '/') { if (window.location.pathname !== '/') {
const url = window.location.pathname + window.location.search + window.location.hash const url = window.location.pathname + window.location.search + window.location.hash
setSecondaryStack((prevStack) => {
if (isCurrentPage(prevStack, url)) return prevStack // 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
const { newStack, newItem } = pushNewPageToStack( if (!showRecommendedRelaysPanel && window.location.pathname.startsWith('/settings')) {
prevStack, // Skip secondary stack handling for settings when side panel is off
url, } else {
maxStackSize, setSecondaryStack((prevStack) => {
window.history.state?.index if (isCurrentPage(prevStack, url)) return prevStack
)
if (newItem) { const { newStack, newItem } = pushNewPageToStack(
window.history.replaceState({ index: newItem.index, url }, '', url) prevStack,
} url,
return newStack maxStackSize,
}) window.history.state?.index
)
if (newItem) {
window.history.replaceState({ index: newItem.index, url }, '', url)
}
return newStack
})
}
} else { } else {
const searchParams = new URLSearchParams(window.location.search) const searchParams = new URLSearchParams(window.location.search)
const r = searchParams.get('r') const r = searchParams.get('r')
@ -467,6 +496,9 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
}) })
setCurrentPrimaryPage(page) setCurrentPrimaryPage(page)
// Clear any primary note view when navigating to a new primary page
setPrimaryNoteView(null)
// Update URL for primary pages (except home) // Update URL for primary pages (except home)
const newUrl = page === 'home' ? '/' : `/?page=${page}` const newUrl = page === 'home' ? '/' : `/?page=${page}`
window.history.pushState(null, '', newUrl) window.history.pushState(null, '', newUrl)
@ -532,7 +564,7 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
> >
<CurrentRelaysProvider> <CurrentRelaysProvider>
<NotificationProvider> <NotificationProvider>
<PrimaryNoteViewContext.Provider value={{ setPrimaryNoteView }}> <PrimaryNoteViewContext.Provider value={{ setPrimaryNoteView, primaryViewType }}>
{!!secondaryStack.length && {!!secondaryStack.length &&
secondaryStack.map((item, index) => ( secondaryStack.map((item, index) => (
<div <div
@ -583,7 +615,7 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
> >
<CurrentRelaysProvider> <CurrentRelaysProvider>
<NotificationProvider> <NotificationProvider>
<PrimaryNoteViewContext.Provider value={{ setPrimaryNoteView }}> <PrimaryNoteViewContext.Provider value={{ setPrimaryNoteView, primaryViewType }}>
<div className="flex flex-col items-center bg-surface-background"> <div className="flex flex-col items-center bg-surface-background">
<div <div
className="flex h-[var(--vh)] w-full bg-surface-background" className="flex h-[var(--vh)] w-full bg-surface-background"

3
src/components/EmojiPicker/index.tsx

@ -33,7 +33,8 @@ export default function EmojiPicker({
'--epr-category-label-bg-color': 'hsl(var(--background))', '--epr-category-label-bg-color': 'hsl(var(--background))',
'--epr-text-color': 'hsl(var(--foreground))', '--epr-text-color': 'hsl(var(--foreground))',
'--epr-hover-bg-color': 'hsl(var(--muted) / 0.5)', '--epr-hover-bg-color': 'hsl(var(--muted) / 0.5)',
'--epr-picker-border-color': 'transparent' '--epr-picker-border-color': 'transparent',
'--epr-search-input-bg-color': 'hsl(var(--muted) / 0.5)'
} as React.CSSProperties } as React.CSSProperties
} }
suggestedEmojisMode={SuggestionMode.FREQUENT} suggestedEmojisMode={SuggestionMode.FREQUENT}

7
src/components/Sidebar/DiscussionsButton.tsx

@ -1,17 +1,18 @@
import { usePrimaryPage } from '@/PageManager' import { usePrimaryPage, usePrimaryNoteView } from '@/PageManager'
import { MessageCircle } from 'lucide-react' import { MessageCircle } from 'lucide-react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import SidebarItem from './SidebarItem' import SidebarItem from './SidebarItem'
export default function DiscussionsButton() { export default function DiscussionsButton() {
const { t } = useTranslation() const { t } = useTranslation()
const { navigate, current } = usePrimaryPage() const { navigate, current, display } = usePrimaryPage()
const { primaryViewType } = usePrimaryNoteView()
return ( return (
<SidebarItem <SidebarItem
title={t('Discussions')} title={t('Discussions')}
onClick={() => navigate('discussions')} onClick={() => navigate('discussions')}
active={current === 'discussions'} active={display && current === 'discussions' && primaryViewType === null}
> >
<MessageCircle strokeWidth={3} /> <MessageCircle strokeWidth={3} />
</SidebarItem> </SidebarItem>

7
src/components/Sidebar/ExploreButton.tsx

@ -1,17 +1,18 @@
import { usePrimaryPage } from '@/PageManager' import { usePrimaryPage, usePrimaryNoteView } from '@/PageManager'
import { Compass } from 'lucide-react' import { Compass } from 'lucide-react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import SidebarItem from './SidebarItem' import SidebarItem from './SidebarItem'
export default function RelaysButton() { export default function RelaysButton() {
const { t } = useTranslation() const { t } = useTranslation()
const { navigate, current } = usePrimaryPage() const { navigate, current, display } = usePrimaryPage()
const { primaryViewType } = usePrimaryNoteView()
return ( return (
<SidebarItem <SidebarItem
title={t('Explore')} title={t('Explore')}
onClick={() => navigate('explore')} onClick={() => navigate('explore')}
active={current === 'explore'} active={display && current === 'explore' && primaryViewType === null}
> >
<Compass strokeWidth={3} /> <Compass strokeWidth={3} />
</SidebarItem> </SidebarItem>

11
src/components/Sidebar/HomeButton.tsx

@ -1,12 +1,17 @@
import { usePrimaryPage } from '@/PageManager' import { usePrimaryPage, usePrimaryNoteView } from '@/PageManager'
import { Home } from 'lucide-react' import { Home } from 'lucide-react'
import SidebarItem from './SidebarItem' import SidebarItem from './SidebarItem'
export default function HomeButton() { export default function HomeButton() {
const { navigate, current } = usePrimaryPage() const { navigate, current, display } = usePrimaryPage()
const { primaryViewType } = usePrimaryNoteView()
return ( return (
<SidebarItem title="Home" onClick={() => navigate('home')} active={current === 'home'}> <SidebarItem
title="Home"
onClick={() => navigate('home')}
active={display && current === 'home' && primaryViewType === null}
>
<Home strokeWidth={3} /> <Home strokeWidth={3} />
</SidebarItem> </SidebarItem>
) )

7
src/components/Sidebar/NotificationButton.tsx

@ -1,4 +1,4 @@
import { usePrimaryPage } from '@/PageManager' import { usePrimaryPage, usePrimaryNoteView } from '@/PageManager'
import { useNostr } from '@/providers/NostrProvider' import { useNostr } from '@/providers/NostrProvider'
import { useNotification } from '@/providers/NotificationProvider' import { useNotification } from '@/providers/NotificationProvider'
import { Bell } from 'lucide-react' import { Bell } from 'lucide-react'
@ -6,14 +6,15 @@ import SidebarItem from './SidebarItem'
export default function NotificationsButton() { export default function NotificationsButton() {
const { checkLogin } = useNostr() const { checkLogin } = useNostr()
const { navigate, current } = usePrimaryPage() const { navigate, current, display } = usePrimaryPage()
const { primaryViewType } = usePrimaryNoteView()
const { hasNewNotification } = useNotification() const { hasNewNotification } = useNotification()
return ( return (
<SidebarItem <SidebarItem
title="Notifications" title="Notifications"
onClick={() => checkLogin(() => navigate('notifications'))} onClick={() => checkLogin(() => navigate('notifications'))}
active={current === 'notifications'} active={display && current === 'notifications' && primaryViewType === null}
> >
<div className="relative"> <div className="relative">
<Bell strokeWidth={3} /> <Bell strokeWidth={3} />

7
src/components/Sidebar/ProfileButton.tsx

@ -1,17 +1,18 @@
import { usePrimaryPage } from '@/PageManager' import { usePrimaryPage, usePrimaryNoteView } from '@/PageManager'
import { useNostr } from '@/providers/NostrProvider' import { useNostr } from '@/providers/NostrProvider'
import { UserRound } from 'lucide-react' import { UserRound } from 'lucide-react'
import SidebarItem from './SidebarItem' import SidebarItem from './SidebarItem'
export default function ProfileButton() { export default function ProfileButton() {
const { navigate, current } = usePrimaryPage() const { navigate, current, display } = usePrimaryPage()
const { primaryViewType } = usePrimaryNoteView()
const { checkLogin } = useNostr() const { checkLogin } = useNostr()
return ( return (
<SidebarItem <SidebarItem
title="Profile" title="Profile"
onClick={() => checkLogin(() => navigate('profile'))} onClick={() => checkLogin(() => navigate('profile'))}
active={current === 'profile'} active={display && current === 'profile' && primaryViewType === 'profile'}
> >
<UserRound strokeWidth={3} /> <UserRound strokeWidth={3} />
</SidebarItem> </SidebarItem>

5
src/components/Sidebar/SearchButton.tsx

@ -1,15 +1,16 @@
import { usePrimaryPage } from '@/PageManager' import { usePrimaryPage, usePrimaryNoteView } from '@/PageManager'
import { Search } from 'lucide-react' import { Search } from 'lucide-react'
import SidebarItem from './SidebarItem' import SidebarItem from './SidebarItem'
export default function SearchButton() { export default function SearchButton() {
const { navigate, current, display } = usePrimaryPage() const { navigate, current, display } = usePrimaryPage()
const { primaryViewType } = usePrimaryNoteView()
return ( return (
<SidebarItem <SidebarItem
title="Search" title="Search"
onClick={() => navigate('search')} onClick={() => navigate('search')}
active={current === 'search' && display} active={current === 'search' && display && primaryViewType === null}
> >
<Search strokeWidth={3} /> <Search strokeWidth={3} />
</SidebarItem> </SidebarItem>

16
src/components/Sidebar/SettingsButton.tsx

@ -1,13 +1,25 @@
import { toSettings } from '@/lib/link' import { toSettings } from '@/lib/link'
import { useSmartSettingsNavigation } from '@/PageManager' import { useSmartSettingsNavigation, usePrimaryNoteView } from '@/PageManager'
import { useUserPreferences } from '@/providers/UserPreferencesProvider'
import { Settings } from 'lucide-react' import { Settings } from 'lucide-react'
import SidebarItem from './SidebarItem' import SidebarItem from './SidebarItem'
export default function SettingsButton() { export default function SettingsButton() {
const { navigateToSettings } = useSmartSettingsNavigation() const { navigateToSettings } = useSmartSettingsNavigation()
const { primaryViewType } = usePrimaryNoteView()
const { showRecommendedRelaysPanel } = useUserPreferences()
// Settings is active when:
// 1. primaryViewType is 'settings' or 'settings-sub' (when side panel is off)
// 2. OR we're on a /settings URL (when side panel is on)
const url = window.location.pathname
const isActive =
primaryViewType === 'settings' ||
primaryViewType === 'settings-sub' ||
(showRecommendedRelaysPanel && url.startsWith('/settings'))
return ( return (
<SidebarItem title="Settings" onClick={() => navigateToSettings(toSettings())}> <SidebarItem title="Settings" onClick={() => navigateToSettings(toSettings())} active={isActive}>
<Settings strokeWidth={3} /> <Settings strokeWidth={3} />
</SidebarItem> </SidebarItem>
) )

Loading…
Cancel
Save