Browse Source

restore right-side panel

update discussion feed relay selection
imwald
Silberengel 5 months ago
parent
commit
87cec27c53
  1. 34
      src/PageManager.tsx
  2. 7
      src/constants.ts
  3. 2
      src/i18n/locales/de.ts
  4. 2
      src/i18n/locales/en.ts
  5. 5
      src/pages/primary/DiscussionsPage/index.tsx
  6. 15
      src/pages/secondary/GeneralSettingsPage/index.tsx
  7. 18
      src/providers/UserPreferencesProvider.tsx
  8. 16
      src/services/local-storage.service.ts

34
src/PageManager.tsx

@ -13,7 +13,7 @@ import GeneralSettingsPage from '@/pages/secondary/GeneralSettingsPage'
import TranslationPage from '@/pages/secondary/TranslationPage' import TranslationPage from '@/pages/secondary/TranslationPage'
import { CurrentRelaysProvider } from '@/providers/CurrentRelaysProvider' import { CurrentRelaysProvider } from '@/providers/CurrentRelaysProvider'
import { NotificationProvider } from '@/providers/NotificationProvider' import { NotificationProvider } from '@/providers/NotificationProvider'
import { UserPreferencesProvider, useUserPreferences } from '@/providers/UserPreferencesProvider' import { useUserPreferences } from '@/providers/UserPreferencesProvider'
import { TPageRef } from '@/types' import { TPageRef } from '@/types'
import { import {
cloneElement, cloneElement,
@ -118,12 +118,12 @@ export function usePrimaryNoteView() {
// Custom hook for intelligent note navigation // Custom hook for intelligent note navigation
export function useSmartNoteNavigation() { export function useSmartNoteNavigation() {
const { hideRecommendedRelaysPanel } = useUserPreferences() const { showRecommendedRelaysPanel } = useUserPreferences()
const { push: pushSecondary } = useSecondaryPage() const { push: pushSecondary } = useSecondaryPage()
const { setPrimaryNoteView } = usePrimaryNoteView() const { setPrimaryNoteView } = usePrimaryNoteView()
const navigateToNote = (url: string) => { const navigateToNote = (url: string) => {
if (hideRecommendedRelaysPanel) { if (!showRecommendedRelaysPanel) {
// 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/', '')
@ -139,12 +139,12 @@ export function useSmartNoteNavigation() {
// Custom hook for intelligent relay navigation // Custom hook for intelligent relay navigation
export function useSmartRelayNavigation() { export function useSmartRelayNavigation() {
const { hideRecommendedRelaysPanel } = useUserPreferences() const { showRecommendedRelaysPanel } = useUserPreferences()
const { push: pushSecondary } = useSecondaryPage() const { push: pushSecondary } = useSecondaryPage()
const { navigate: navigatePrimary } = usePrimaryPage() const { navigate: navigatePrimary } = usePrimaryPage()
const navigateToRelay = (url: string) => { const navigateToRelay = (url: string) => {
if (hideRecommendedRelaysPanel) { if (!showRecommendedRelaysPanel) {
// When right panel is hidden, navigate to relay page in primary area // 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://...") // Extract relay URL from the path (e.g., "/relays/wss%3A%2F%2F..." -> "wss://...")
const relayUrl = url.startsWith('/relays/') ? decodeURIComponent(url.replace('/relays/', '')) : url const relayUrl = url.startsWith('/relays/') ? decodeURIComponent(url.replace('/relays/', '')) : url
@ -160,12 +160,12 @@ export function useSmartRelayNavigation() {
// Custom hook for intelligent settings navigation // Custom hook for intelligent settings navigation
export function useSmartSettingsNavigation() { export function useSmartSettingsNavigation() {
const { hideRecommendedRelaysPanel } = useUserPreferences() const { showRecommendedRelaysPanel } = useUserPreferences()
const { push: pushSecondary } = useSecondaryPage() const { push: pushSecondary } = useSecondaryPage()
const { setPrimaryNoteView } = usePrimaryNoteView() const { setPrimaryNoteView } = usePrimaryNoteView()
const navigateToSettings = (url: string) => { const navigateToSettings = (url: string) => {
if (hideRecommendedRelaysPanel) { 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') {
setPrimaryNoteView(<SettingsPage index={0} hideTitlebar={true} />, 'settings') setPrimaryNoteView(<SettingsPage index={0} hideTitlebar={true} />, 'settings')
@ -190,9 +190,9 @@ export function useSmartSettingsNavigation() {
} }
function ConditionalHomePage() { function ConditionalHomePage() {
const { hideRecommendedRelaysPanel } = useUserPreferences() const { showRecommendedRelaysPanel } = useUserPreferences()
if (hideRecommendedRelaysPanel) { if (!showRecommendedRelaysPanel) {
return null return null
} }
@ -214,16 +214,16 @@ function MainContentArea({
primaryViewType: 'note' | 'settings' | 'settings-sub' | null primaryViewType: 'note' | 'settings' | 'settings-sub' | null
setPrimaryNoteView: (view: ReactNode | null, type?: 'note' | 'settings' | 'settings-sub') => void setPrimaryNoteView: (view: ReactNode | null, type?: 'note' | 'settings' | 'settings-sub') => void
}) { }) {
const { hideRecommendedRelaysPanel } = useUserPreferences() const { showRecommendedRelaysPanel } = useUserPreferences()
// If recommended relays panel is hidden, use single column layout // If recommended relays panel is shown, use two-column layout
// Otherwise use two-column grid layout // Otherwise use single column layout
const gridClass = hideRecommendedRelaysPanel ? "grid-cols-1" : "grid-cols-2" const gridClass = showRecommendedRelaysPanel ? "grid-cols-2" : "grid-cols-1"
return ( return (
<div className={`grid ${gridClass} gap-2 w-full pr-2 py-2`}> <div className={`grid ${gridClass} gap-2 w-full pr-2 py-2`}>
<div className="rounded-lg shadow-lg bg-background overflow-hidden"> <div className="rounded-lg shadow-lg bg-background overflow-hidden">
{hideRecommendedRelaysPanel && primaryNoteView ? ( {!showRecommendedRelaysPanel && primaryNoteView ? (
// Show note view with back button when right panel is hidden // Show note view with back button when right panel is hidden
<div className="flex flex-col h-full w-full"> <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 gap-1 p-1 items-center justify-between font-semibold border-b">
@ -262,7 +262,7 @@ function MainContentArea({
)) ))
)} )}
</div> </div>
{!hideRecommendedRelaysPanel && ( {showRecommendedRelaysPanel && (
<div className="rounded-lg shadow-lg bg-background overflow-hidden"> <div className="rounded-lg shadow-lg bg-background overflow-hidden">
{secondaryStack.map((item, index) => ( {secondaryStack.map((item, index) => (
<div <div
@ -509,7 +509,6 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
> >
<CurrentRelaysProvider> <CurrentRelaysProvider>
<NotificationProvider> <NotificationProvider>
<UserPreferencesProvider>
<PrimaryNoteViewContext.Provider value={{ setPrimaryNoteView }}> <PrimaryNoteViewContext.Provider value={{ setPrimaryNoteView }}>
{!!secondaryStack.length && {!!secondaryStack.length &&
secondaryStack.map((item, index) => ( secondaryStack.map((item, index) => (
@ -537,7 +536,6 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
<TooManyRelaysAlertDialog /> <TooManyRelaysAlertDialog />
<CreateWalletGuideToast /> <CreateWalletGuideToast />
</PrimaryNoteViewContext.Provider> </PrimaryNoteViewContext.Provider>
</UserPreferencesProvider>
</NotificationProvider> </NotificationProvider>
</CurrentRelaysProvider> </CurrentRelaysProvider>
</SecondaryPageContext.Provider> </SecondaryPageContext.Provider>
@ -562,7 +560,6 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
> >
<CurrentRelaysProvider> <CurrentRelaysProvider>
<NotificationProvider> <NotificationProvider>
<UserPreferencesProvider>
<PrimaryNoteViewContext.Provider value={{ setPrimaryNoteView }}> <PrimaryNoteViewContext.Provider value={{ setPrimaryNoteView }}>
<div className="flex flex-col items-center bg-surface-background"> <div className="flex flex-col items-center bg-surface-background">
<div <div
@ -585,7 +582,6 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
<TooManyRelaysAlertDialog /> <TooManyRelaysAlertDialog />
<CreateWalletGuideToast /> <CreateWalletGuideToast />
</PrimaryNoteViewContext.Provider> </PrimaryNoteViewContext.Provider>
</UserPreferencesProvider>
</NotificationProvider> </NotificationProvider>
</CurrentRelaysProvider> </CurrentRelaysProvider>
</SecondaryPageContext.Provider> </SecondaryPageContext.Provider>

7
src/constants.ts

@ -45,7 +45,7 @@ export const StorageKey = {
NOTIFICATION_LIST_STYLE: 'notificationListStyle', NOTIFICATION_LIST_STYLE: 'notificationListStyle',
MEDIA_AUTO_LOAD_POLICY: 'mediaAutoLoadPolicy', MEDIA_AUTO_LOAD_POLICY: 'mediaAutoLoadPolicy',
SHOWN_CREATE_WALLET_GUIDE_TOAST_PUBKEYS: 'shownCreateWalletGuideToastPubkeys', SHOWN_CREATE_WALLET_GUIDE_TOAST_PUBKEYS: 'shownCreateWalletGuideToastPubkeys',
HIDE_RECOMMENDED_RELAYS_PANEL: 'hideRecommendedRelaysPanel', SHOW_RECOMMENDED_RELAYS_PANEL: 'showRecommendedRelaysPanel',
MEDIA_UPLOAD_SERVICE: 'mediaUploadService', // deprecated MEDIA_UPLOAD_SERVICE: 'mediaUploadService', // deprecated
HIDE_UNTRUSTED_EVENTS: 'hideUntrustedEvents', // deprecated HIDE_UNTRUSTED_EVENTS: 'hideUntrustedEvents', // deprecated
ACCOUNT_RELAY_LIST_EVENT_MAP: 'accountRelayListEventMap', // deprecated ACCOUNT_RELAY_LIST_EVENT_MAP: 'accountRelayListEventMap', // deprecated
@ -65,10 +65,7 @@ export const BIG_RELAY_URLS = [
'wss://theforest.nostr1.com', 'wss://theforest.nostr1.com',
'wss://orly-relay.imwald.eu', 'wss://orly-relay.imwald.eu',
'wss://nostr.land', 'wss://nostr.land',
'wss://nostr.wine', 'wss://thecitadel.nostr1.com',
'wss://nostr.sovbit.host',
'wss://nostr21.com',
'wss://thecitadel.nostr1.com'
] ]
// Optimized relay list for read operations (includes aggregator) // Optimized relay list for read operations (includes aggregator)

2
src/i18n/locales/de.ts

@ -296,6 +296,8 @@ export default {
Article: 'Artikel', Article: 'Artikel',
Unfavorite: 'Nicht mehr favorisieren', Unfavorite: 'Nicht mehr favorisieren',
'Recommended relays': 'Empfohlene Relays', 'Recommended relays': 'Empfohlene Relays',
'Show recommended relays panel': 'Empfohlene Relays-Panel anzeigen',
'Display the right-side panel with recommended relays on desktop': 'Das rechte Panel mit empfohlenen Relays auf dem Desktop anzeigen',
'Blossom server URLs': 'Blossom-Server-URLs', 'Blossom server URLs': 'Blossom-Server-URLs',
'You need to add at least one blossom server in order to upload media files.': 'You need to add at least one blossom server in order to upload media files.':
'Du musst mindestens einen Blossom-Server hinzufügen, um Mediendateien hochladen zu können.', 'Du musst mindestens einen Blossom-Server hinzufügen, um Mediendateien hochladen zu können.',

2
src/i18n/locales/en.ts

@ -301,6 +301,8 @@ export default {
Article: 'Article', Article: 'Article',
Unfavorite: 'Unfavorite', Unfavorite: 'Unfavorite',
'Recommended relays': 'Recommended relays', 'Recommended relays': 'Recommended relays',
'Show recommended relays panel': 'Show recommended relays panel',
'Display the right-side panel with recommended relays on desktop': 'Display the right-side panel with recommended relays on desktop',
'Blossom server URLs': 'Blossom server URLs', 'Blossom server URLs': 'Blossom server URLs',
'You need to add at least one blossom server in order to upload media files.': 'You need to add at least one blossom server in order to upload media files.':
'You need to add at least one blossom server in order to upload media files.', 'You need to add at least one blossom server in order to upload media files.',

5
src/pages/primary/DiscussionsPage/index.tsx

@ -145,10 +145,11 @@ const DiscussionsPage = forwardRef((_, ref) => {
} }
} }
// Use favorite relays from provider (includes stored relay sets) + user's read relays or fast read relays // Use favorite relays from provider (includes stored relay sets) + user's read relays + fast read relays
const allRawRelays = [ const allRawRelays = [
...favoriteRelays, ...favoriteRelays,
...(userReadRelays.length > 0 ? userReadRelays : FAST_READ_RELAY_URLS) ...userReadRelays,
...FAST_READ_RELAY_URLS
] ]
// Normalize and deduplicate all relays // Normalize and deduplicate all relays

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

@ -30,7 +30,7 @@ const GeneralSettingsPage = forwardRef(({ index, hideTitlebar = false }: { index
setMediaAutoLoadPolicy setMediaAutoLoadPolicy
} = useContentPolicy() } = useContentPolicy()
const { hideUntrustedNotes, updateHideUntrustedNotes } = useUserTrust() const { hideUntrustedNotes, updateHideUntrustedNotes } = useUserTrust()
const { notificationListStyle, updateNotificationListStyle } = useUserPreferences() const { notificationListStyle, updateNotificationListStyle, showRecommendedRelaysPanel, updateShowRecommendedRelaysPanel } = useUserPreferences()
const handleLanguageChange = (value: TLanguage) => { const handleLanguageChange = (value: TLanguage) => {
i18n.changeLanguage(value) i18n.changeLanguage(value)
@ -151,6 +151,19 @@ const GeneralSettingsPage = forwardRef(({ index, hideTitlebar = false }: { index
</Label> </Label>
<Switch id="show-nsfw" checked={defaultShowNsfw} onCheckedChange={setDefaultShowNsfw} /> <Switch id="show-nsfw" checked={defaultShowNsfw} onCheckedChange={setDefaultShowNsfw} />
</SettingItem> </SettingItem>
<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>
<SettingItem> <SettingItem>
<div> <div>
<a <a

18
src/providers/UserPreferencesProvider.tsx

@ -5,8 +5,8 @@ import { createContext, useContext, useState } from 'react'
type TUserPreferencesContext = { type TUserPreferencesContext = {
notificationListStyle: TNotificationStyle notificationListStyle: TNotificationStyle
updateNotificationListStyle: (style: TNotificationStyle) => void updateNotificationListStyle: (style: TNotificationStyle) => void
hideRecommendedRelaysPanel: boolean showRecommendedRelaysPanel: boolean
updateHideRecommendedRelaysPanel: (hide: boolean) => void updateShowRecommendedRelaysPanel: (show: boolean) => void
} }
const UserPreferencesContext = createContext<TUserPreferencesContext | undefined>(undefined) const UserPreferencesContext = createContext<TUserPreferencesContext | undefined>(undefined)
@ -23,8 +23,8 @@ export function UserPreferencesProvider({ children }: { children: React.ReactNod
const [notificationListStyle, setNotificationListStyle] = useState( const [notificationListStyle, setNotificationListStyle] = useState(
storage.getNotificationListStyle() storage.getNotificationListStyle()
) )
const [hideRecommendedRelaysPanel, setHideRecommendedRelaysPanel] = useState( const [showRecommendedRelaysPanel, setShowRecommendedRelaysPanel] = useState(
storage.getHideRecommendedRelaysPanel() storage.getShowRecommendedRelaysPanel()
) )
const updateNotificationListStyle = (style: TNotificationStyle) => { const updateNotificationListStyle = (style: TNotificationStyle) => {
@ -32,9 +32,9 @@ export function UserPreferencesProvider({ children }: { children: React.ReactNod
storage.setNotificationListStyle(style) storage.setNotificationListStyle(style)
} }
const updateHideRecommendedRelaysPanel = (hide: boolean) => { const updateShowRecommendedRelaysPanel = (show: boolean) => {
setHideRecommendedRelaysPanel(hide) setShowRecommendedRelaysPanel(show)
storage.setHideRecommendedRelaysPanel(hide) storage.setShowRecommendedRelaysPanel(show)
} }
return ( return (
@ -42,8 +42,8 @@ export function UserPreferencesProvider({ children }: { children: React.ReactNod
value={{ value={{
notificationListStyle, notificationListStyle,
updateNotificationListStyle, updateNotificationListStyle,
hideRecommendedRelaysPanel, showRecommendedRelaysPanel,
updateHideRecommendedRelaysPanel updateShowRecommendedRelaysPanel
}} }}
> >
{children} {children}

16
src/services/local-storage.service.ts

@ -49,7 +49,7 @@ class LocalStorageService {
private hideContentMentioningMutedUsers: boolean = false private hideContentMentioningMutedUsers: boolean = false
private notificationListStyle: TNotificationStyle = NOTIFICATION_LIST_STYLE.DETAILED private notificationListStyle: TNotificationStyle = NOTIFICATION_LIST_STYLE.DETAILED
private mediaAutoLoadPolicy: TMediaAutoLoadPolicy = MEDIA_AUTO_LOAD_POLICY.ALWAYS private mediaAutoLoadPolicy: TMediaAutoLoadPolicy = MEDIA_AUTO_LOAD_POLICY.ALWAYS
private hideRecommendedRelaysPanel: boolean = false private showRecommendedRelaysPanel: boolean = true
private shownCreateWalletGuideToastPubkeys: Set<string> = new Set() private shownCreateWalletGuideToastPubkeys: Set<string> = new Set()
constructor() { constructor() {
@ -165,8 +165,8 @@ class LocalStorageService {
this.dismissedTooManyRelaysAlert = this.dismissedTooManyRelaysAlert =
window.localStorage.getItem(StorageKey.DISMISSED_TOO_MANY_RELAYS_ALERT) === 'true' window.localStorage.getItem(StorageKey.DISMISSED_TOO_MANY_RELAYS_ALERT) === 'true'
this.hideRecommendedRelaysPanel = const storedValue = window.localStorage.getItem(StorageKey.SHOW_RECOMMENDED_RELAYS_PANEL)
window.localStorage.getItem(StorageKey.HIDE_RECOMMENDED_RELAYS_PANEL) === 'true' this.showRecommendedRelaysPanel = storedValue !== 'false' // Default to true if not explicitly set to false
const showKindsStr = window.localStorage.getItem(StorageKey.SHOW_KINDS) const showKindsStr = window.localStorage.getItem(StorageKey.SHOW_KINDS)
if (!showKindsStr) { if (!showKindsStr) {
@ -460,13 +460,13 @@ class LocalStorageService {
window.localStorage.setItem(StorageKey.DISMISSED_TOO_MANY_RELAYS_ALERT, dismissed.toString()) window.localStorage.setItem(StorageKey.DISMISSED_TOO_MANY_RELAYS_ALERT, dismissed.toString())
} }
getHideRecommendedRelaysPanel() { getShowRecommendedRelaysPanel() {
return this.hideRecommendedRelaysPanel return this.showRecommendedRelaysPanel
} }
setHideRecommendedRelaysPanel(hide: boolean) { setShowRecommendedRelaysPanel(show: boolean) {
this.hideRecommendedRelaysPanel = hide this.showRecommendedRelaysPanel = show
window.localStorage.setItem(StorageKey.HIDE_RECOMMENDED_RELAYS_PANEL, hide.toString()) window.localStorage.setItem(StorageKey.SHOW_RECOMMENDED_RELAYS_PANEL, show.toString())
} }
getShowKinds() { getShowKinds() {

Loading…
Cancel
Save