Browse Source

performance improvements

imwald
Silberengel 5 months ago
parent
commit
0a8b17a517
  1. 4
      src/components/NoteList/index.tsx
  2. 4
      src/components/NoteStats/RepostButton.tsx
  3. 1
      src/components/NoteStats/index.tsx
  4. 123
      src/components/ReplyNoteList/index.tsx
  5. 6
      src/constants.ts
  6. 2
      src/pages/primary/DiscussionsPage/ThreadCard.tsx
  7. 2
      src/pages/primary/DiscussionsPage/index.tsx
  8. 2
      src/pages/primary/NoteListPage/RelaysFeed.tsx
  9. 21
      src/providers/FeedProvider.tsx
  10. 4
      src/providers/NotificationProvider.tsx
  11. 17
      src/services/client.service.ts
  12. 4
      src/services/local-storage.service.ts
  13. 10
      vite.config.ts

4
src/components/NoteList/index.tsx

@ -177,7 +177,7 @@ const NoteList = forwardRef(
return () => {} return () => {}
} }
logger.debug('NoteList subscribing to timeline with:', subRequests.map(({ urls, filter }) => ({ console.log('[NoteList] Subscribing to timeline with:', subRequests.map(({ urls, filter }) => ({
urls, urls,
filter: { filter: {
kinds: showKinds, kinds: showKinds,
@ -269,7 +269,7 @@ const NoteList = forwardRef(
return () => { return () => {
promise.then((closer) => closer()) promise.then((closer) => closer())
} }
}, [JSON.stringify(subRequests), refreshCount, showKinds]) }, [subRequests, refreshCount, showKinds])
useEffect(() => { useEffect(() => {
const options = { const options = {

4
src/components/NoteStats/RepostButton.tsx

@ -51,8 +51,8 @@ export default function RepostButton({ event }: { event: Event }) {
const hasReposted = noteStats?.repostPubkeySet?.has(pubkey) const hasReposted = noteStats?.repostPubkeySet?.has(pubkey)
if (hasReposted) return if (hasReposted) return
if (!noteStats?.updatedAt) { if (!noteStats?.updatedAt) {
const noteStats = await noteStatsService.fetchNoteStats(event, pubkey) const fetchedNoteStats = await noteStatsService.fetchNoteStats(event, pubkey)
if (noteStats.repostPubkeySet?.has(pubkey)) { if (fetchedNoteStats?.repostPubkeySet?.has(pubkey)) {
return return
} }
} }

1
src/components/NoteStats/index.tsx

@ -2,6 +2,7 @@ import { cn } from '@/lib/utils'
import { useNostr } from '@/providers/NostrProvider' import { useNostr } from '@/providers/NostrProvider'
import { useScreenSize } from '@/providers/ScreenSizeProvider' import { useScreenSize } from '@/providers/ScreenSizeProvider'
import { useFavoriteRelays } from '@/providers/FavoriteRelaysProvider' import { useFavoriteRelays } from '@/providers/FavoriteRelaysProvider'
import { useFeed } from '@/providers/FeedProvider'
import noteStatsService from '@/services/note-stats.service' import noteStatsService from '@/services/note-stats.service'
import { ExtendedKind } from '@/constants' import { ExtendedKind } from '@/constants'
import { getRootEventHexId } from '@/lib/event' import { getRootEventHexId } from '@/lib/event'

123
src/components/ReplyNoteList/index.tsx

@ -18,6 +18,7 @@ import { useContentPolicy } from '@/providers/ContentPolicyProvider'
import { useMuteList } from '@/providers/MuteListProvider' import { useMuteList } from '@/providers/MuteListProvider'
import { useNostr } from '@/providers/NostrProvider' import { useNostr } from '@/providers/NostrProvider'
import { useReply } from '@/providers/ReplyProvider' import { useReply } from '@/providers/ReplyProvider'
import { useFeed } from '@/providers/FeedProvider'
import { useUserTrust } from '@/providers/UserTrustProvider' import { useUserTrust } from '@/providers/UserTrustProvider'
import client from '@/services/client.service' import client from '@/services/client.service'
import noteStatsService from '@/services/note-stats.service' import noteStatsService from '@/services/note-stats.service'
@ -36,6 +37,8 @@ const LIMIT = 100
const SHOW_COUNT = 10 const SHOW_COUNT = 10
function ReplyNoteList({ index, event, sort = 'oldest' }: { index?: number; event: NEvent; sort?: 'newest' | 'oldest' | 'top' | 'controversial' | 'most-zapped' }) { function ReplyNoteList({ index, event, sort = 'oldest' }: { index?: number; event: NEvent; sort?: 'newest' | 'oldest' | 'top' | 'controversial' | 'most-zapped' }) {
console.log('[ReplyNoteList] Component rendered for event:', event.id.substring(0, 8))
const { t } = useTranslation() const { t } = useTranslation()
const { navigateToNote } = useSmartNoteNavigation() const { navigateToNote } = useSmartNoteNavigation()
const { currentIndex } = useSecondaryPage() const { currentIndex } = useSecondaryPage()
@ -43,6 +46,7 @@ function ReplyNoteList({ index, event, sort = 'oldest' }: { index?: number; even
const { mutePubkeySet } = useMuteList() const { mutePubkeySet } = useMuteList()
const { hideContentMentioningMutedUsers } = useContentPolicy() const { hideContentMentioningMutedUsers } = useContentPolicy()
const { relayList: userRelayList } = useNostr() const { relayList: userRelayList } = useNostr()
const { relayUrls: currentFeedRelays } = useFeed()
const [rootInfo, setRootInfo] = useState<TRootInfo | undefined>(undefined) const [rootInfo, setRootInfo] = useState<TRootInfo | undefined>(undefined)
const { repliesMap, addReplies } = useReply() const { repliesMap, addReplies } = useReply()
@ -102,6 +106,14 @@ function ReplyNoteList({ index, event, sort = 'oldest' }: { index?: number; even
// This prevents the doom loop that was causing "too many concurrent REQS" // This prevents the doom loop that was causing "too many concurrent REQS"
const events = parentEventKeys.flatMap((id) => repliesMap.get(id)?.events || []) const events = parentEventKeys.flatMap((id) => repliesMap.get(id)?.events || [])
logger.debug('[ReplyNoteList] Processing replies:', {
eventId: event.id.substring(0, 8),
parentEventKeys,
eventsFromMap: events.length,
repliesMapSize: repliesMap.size,
repliesMapKeys: Array.from(repliesMap.keys()).map(k => k.substring(0, 8))
})
events.forEach((evt) => { events.forEach((evt) => {
if (replyIdSet.has(evt.id)) return if (replyIdSet.has(evt.id)) return
if (mutePubkeySet.has(evt.pubkey)) { if (mutePubkeySet.has(evt.pubkey)) {
@ -164,8 +176,10 @@ function ReplyNoteList({ index, event, sort = 'oldest' }: { index?: number; even
const [highlightReplyId, setHighlightReplyId] = useState<string | undefined>(undefined) const [highlightReplyId, setHighlightReplyId] = useState<string | undefined>(undefined)
const replyRefs = useRef<Record<string, HTMLDivElement | null>>({}) const replyRefs = useRef<Record<string, HTMLDivElement | null>>({})
const bottomRef = useRef<HTMLDivElement | null>(null) const bottomRef = useRef<HTMLDivElement | null>(null)
const requestTimeoutRef = useRef<NodeJS.Timeout | null>(null)
useEffect(() => { useEffect(() => {
console.log('[ReplyNoteList] fetchRootEvent useEffect triggered for event:', event.id.substring(0, 8))
const fetchRootEvent = async () => { const fetchRootEvent = async () => {
let root: TRootInfo let root: TRootInfo
@ -207,6 +221,11 @@ function ReplyNoteList({ index, event, sort = 'oldest' }: { index?: number; even
root = { type: 'I', id: rootITag[1] } root = { type: 'I', id: rootITag[1] }
} }
} }
logger.debug('[ReplyNoteList] Root info determined:', {
eventId: event.id.substring(0, 8),
rootInfo: root,
eventKind: event.kind
})
setRootInfo(root) setRootInfo(root)
} }
fetchRootEvent() fetchRootEvent()
@ -234,22 +253,79 @@ function ReplyNoteList({ index, event, sort = 'oldest' }: { index?: number; even
}, [rootInfo, onNewReply]) }, [rootInfo, onNewReply])
useEffect(() => { useEffect(() => {
if (loading || !rootInfo || currentIndex !== index) return console.log('[ReplyNoteList] Main useEffect triggered:', {
loading,
hasRootInfo: !!rootInfo,
currentIndex,
index,
shouldInit: !loading && !!rootInfo && currentIndex === index
})
if (loading || !rootInfo || currentIndex !== index) {
console.log('[ReplyNoteList] Early return - conditions not met:', {
loading,
hasRootInfo: !!rootInfo,
currentIndex,
index,
rootInfo
})
return
}
console.log('[ReplyNoteList] All conditions met, starting reply fetch...')
// Clear any existing timeout to prevent multiple simultaneous requests
if (requestTimeoutRef.current) {
clearTimeout(requestTimeoutRef.current)
}
// Debounce the request to prevent rapid successive calls
requestTimeoutRef.current = setTimeout(() => {
console.log('[ReplyNoteList] Debounced request starting...')
// Check if we're already loading to prevent duplicate requests
if (loading) {
console.log('[ReplyNoteList] Already loading, skipping request')
return
}
const init = async () => { const init = async () => {
setLoading(true) setLoading(true)
try { try {
// Privacy: Only use user's own relays + defaults, never connect to other users' relays // Use current feed's relay selection - if user selected a specific relay, use only that
const userReadRelays = userRelayList?.read || [] let finalRelayUrls: string[]
const userWriteRelays = userRelayList?.write || []
const finalRelayUrls = Array.from(new Set([
...FAST_READ_RELAY_URLS.map(url => normalizeUrl(url) || url), // Fast, well-connected relays
...userReadRelays.map(url => normalizeUrl(url) || url), // User's read relays
...userWriteRelays.map(url => normalizeUrl(url) || url) // User's write relays
]))
console.log('[ReplyNoteList] Current feed relays:', currentFeedRelays)
if (currentFeedRelays.length > 0) {
// Use the current feed's relay selection (respects user's choice of single relay)
finalRelayUrls = currentFeedRelays.map(url => normalizeUrl(url) || url).filter(Boolean)
console.log('[ReplyNoteList] Using current feed relays:', finalRelayUrls)
} else {
// Fallback: build comprehensive relay list only if no feed relays are set
const userReadRelays = userRelayList?.read || []
const userWriteRelays = userRelayList?.write || []
const eventHints = client.getEventHints(event.id)
const allRelays = [
...userReadRelays.map(url => normalizeUrl(url) || url),
...userWriteRelays.map(url => normalizeUrl(url) || url),
...eventHints.map(url => normalizeUrl(url) || url),
...FAST_READ_RELAY_URLS.map(url => normalizeUrl(url) || url),
]
finalRelayUrls = Array.from(new Set(allRelays.filter(Boolean)))
console.log('[ReplyNoteList] Using fallback relay list:', finalRelayUrls)
}
logger.debug('[ReplyNoteList] Fetching replies for event:', {
eventId: event.id.substring(0, 8),
rootInfo,
finalRelayUrls: finalRelayUrls.slice(0, 5), // Log first 5 relays
totalRelays: finalRelayUrls.length
})
const filters: (Omit<Filter, 'since' | 'until'> & { const filters: (Omit<Filter, 'since' | 'until'> & {
limit: number limit: number
@ -298,13 +374,22 @@ function ReplyNoteList({ index, event, sort = 'oldest' }: { index?: number; even
const { closer, timelineKey } = await client.subscribeTimeline( const { closer, timelineKey } = await client.subscribeTimeline(
filters.map((filter) => ({ filters.map((filter) => ({
urls: finalRelayUrls, // Use all relays, don't slice urls: finalRelayUrls, // Use current feed's relay selection
filter filter
})), })),
{ {
onEvents: (evts, eosed) => { onEvents: (evts, eosed) => {
logger.debug('[ReplyNoteList] Received events:', {
totalEvents: evts.length,
eosed,
eventIds: evts.map(e => e.id.substring(0, 8))
})
if (evts.length > 0) { if (evts.length > 0) {
const regularReplies = evts.filter((evt) => isReplyNoteEvent(evt)) const regularReplies = evts.filter((evt) => isReplyNoteEvent(evt))
logger.debug('[ReplyNoteList] Filtered replies:', {
replyCount: regularReplies.length,
replyIds: regularReplies.map(r => r.id.substring(0, 8))
})
addReplies(regularReplies) addReplies(regularReplies)
} }
if (eosed) { if (eosed) {
@ -342,6 +427,13 @@ function ReplyNoteList({ index, event, sort = 'oldest' }: { index?: number; even
return () => { return () => {
promise.then((closer) => closer?.()) promise.then((closer) => closer?.())
} }
}, 500) // 500ms debounce delay
return () => {
if (requestTimeoutRef.current) {
clearTimeout(requestTimeoutRef.current)
}
}
}, [rootInfo, currentIndex, index, onNewReply]) }, [rootInfo, currentIndex, index, onNewReply])
useEffect(() => { useEffect(() => {
@ -349,7 +441,16 @@ function ReplyNoteList({ index, event, sort = 'oldest' }: { index?: number; even
if (replies.length === 0 && !loading && timelineKey && until !== undefined) { if (replies.length === 0 && !loading && timelineKey && until !== undefined) {
loadMore() loadMore()
} }
}, [replies.length, loading, timelineKey, until]) // Added until to prevent infinite loops }, [replies.length, loading, timelineKey, until])
// Cleanup timeout on unmount
useEffect(() => {
return () => {
if (requestTimeoutRef.current) {
clearTimeout(requestTimeoutRef.current)
}
}
}, []) // Added until to prevent infinite loops
useEffect(() => { useEffect(() => {
const options = { const options = {

6
src/constants.ts

@ -81,10 +81,8 @@ export const FAST_READ_RELAY_URLS = [
export const FAST_WRITE_RELAY_URLS = [ export const FAST_WRITE_RELAY_URLS = [
'wss://relay.damus.io', 'wss://relay.damus.io',
'wss://relay.primal.net', 'wss://relay.primal.net',
'wss://freelay.sovbit.host',
'wss://thecitadel.nostr1.com', 'wss://thecitadel.nostr1.com',
'wss://nos.lol', 'wss://bevo.nostr1.com'
'wss://nostr.mom'
] ]
export const SEARCHABLE_RELAY_URLS = [ export const SEARCHABLE_RELAY_URLS = [
@ -93,13 +91,11 @@ export const SEARCHABLE_RELAY_URLS = [
'wss://nostr.wine', 'wss://nostr.wine',
'wss://orly-relay.imwald.eu', 'wss://orly-relay.imwald.eu',
'wss://aggr.nostr.land', 'wss://aggr.nostr.land',
'wss://nos.lol',
'wss://thecitadel.nostr1.com', 'wss://thecitadel.nostr1.com',
'wss://relay.primal.net', 'wss://relay.primal.net',
'wss://relay.damus.io', 'wss://relay.damus.io',
'wss://relay.lumina.rocks', 'wss://relay.lumina.rocks',
'wss://relay.snort.social', 'wss://relay.snort.social',
'wss://freelay.sovbit.host'
] ]
export const PROFILE_RELAY_URLS = [ export const PROFILE_RELAY_URLS = [

2
src/pages/primary/DiscussionsPage/ThreadCard.tsx

@ -15,7 +15,6 @@ interface ThreadCardProps {
thread: NostrEvent thread: NostrEvent
onThreadClick: () => void onThreadClick: () => void
className?: string className?: string
commentCount?: number
lastCommentTime?: number lastCommentTime?: number
lastVoteTime?: number lastVoteTime?: number
upVotes?: number upVotes?: number
@ -26,7 +25,6 @@ export default function ThreadCard({
thread, thread,
onThreadClick, onThreadClick,
className, className,
commentCount = 0,
lastCommentTime = 0, lastCommentTime = 0,
lastVoteTime = 0, lastVoteTime = 0,
upVotes = 0, upVotes = 0,

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

@ -874,7 +874,6 @@ const DiscussionsPage = forwardRef(() => {
<ThreadCard <ThreadCard
key={entry.event.id} key={entry.event.id}
thread={entry.event} thread={entry.event}
commentCount={entry.commentCount}
lastCommentTime={entry.lastCommentTime} lastCommentTime={entry.lastCommentTime}
lastVoteTime={entry.lastVoteTime} lastVoteTime={entry.lastVoteTime}
upVotes={entry.upVotes} upVotes={entry.upVotes}
@ -906,7 +905,6 @@ const DiscussionsPage = forwardRef(() => {
<ThreadCard <ThreadCard
key={entry.event.id} key={entry.event.id}
thread={entry.event} thread={entry.event}
commentCount={entry.commentCount}
lastCommentTime={entry.lastCommentTime} lastCommentTime={entry.lastCommentTime}
lastVoteTime={entry.lastVoteTime} lastVoteTime={entry.lastVoteTime}
upVotes={entry.upVotes} upVotes={entry.upVotes}

2
src/pages/primary/NoteListPage/RelaysFeed.tsx

@ -36,7 +36,7 @@ export default function RelaysFeed() {
} }
const subRequests = [{ urls: relayUrls, filter: {} }] const subRequests = [{ urls: relayUrls, filter: {} }]
logger.debug('RelaysFeed rendering NormalFeed with:', { subRequests, relayUrls, areAlgoRelays }) console.log('[RelaysFeed] Rendering NormalFeed with:', { subRequests, relayUrls, areAlgoRelays })
return ( return (
<NormalFeed <NormalFeed

21
src/providers/FeedProvider.tsx

@ -54,6 +54,11 @@ export function FeedProvider({ children }: { children: React.ReactNode }) {
feedType: 'relay', feedType: 'relay',
id: visibleRelays[0] ?? DEFAULT_FAVORITE_RELAYS[0] id: visibleRelays[0] ?? DEFAULT_FAVORITE_RELAYS[0]
} }
// Ensure we always have a valid relay ID
if (!feedInfo.id) {
feedInfo.id = DEFAULT_FAVORITE_RELAYS[0]
}
logger.debug('Initial feedInfo setup:', { visibleRelays, favoriteRelays, blockedRelays, feedInfo }) logger.debug('Initial feedInfo setup:', { visibleRelays, favoriteRelays, blockedRelays, feedInfo })
if (pubkey) { if (pubkey) {
@ -71,9 +76,10 @@ export function FeedProvider({ children }: { children: React.ReactNode }) {
if (feedInfo.feedType === 'relay') { if (feedInfo.feedType === 'relay') {
// Check if the stored relay is blocked, if so use first visible relay instead // Check if the stored relay is blocked, if so use first visible relay instead
if (feedInfo.id && blockedRelays.includes(feedInfo.id)) { if (feedInfo.id && blockedRelays.includes(feedInfo.id)) {
logger.debug('Stored relay is blocked, using first visible relay instead') console.log('[FeedProvider] Stored relay is blocked, using first visible relay instead')
feedInfo.id = visibleRelays[0] ?? DEFAULT_FAVORITE_RELAYS[0] feedInfo.id = visibleRelays[0] ?? DEFAULT_FAVORITE_RELAYS[0]
} }
console.log('[FeedProvider] Initial relay setup, calling switchFeed with:', feedInfo.id)
return await switchFeed('relay', { relay: feedInfo.id }) return await switchFeed('relay', { relay: feedInfo.id })
} }
@ -133,13 +139,14 @@ export function FeedProvider({ children }: { children: React.ReactNode }) {
} }
const newFeedInfo = { feedType, id: normalizedUrl } const newFeedInfo = { feedType, id: normalizedUrl }
logger.debug('Setting relay feed info:', newFeedInfo) console.log('[FeedProvider] Setting relay feed info:', newFeedInfo)
setFeedInfo(newFeedInfo) setFeedInfo(newFeedInfo)
feedInfoRef.current = newFeedInfo feedInfoRef.current = newFeedInfo
setRelayUrls([normalizedUrl]) setRelayUrls([normalizedUrl])
console.log('[FeedProvider] Set relayUrls to:', [normalizedUrl])
storage.setFeedInfo(newFeedInfo, pubkey) storage.setFeedInfo(newFeedInfo, pubkey)
setIsReady(true) setIsReady(true)
logger.debug('Relay feed setup complete, isReady set to true') console.log('[FeedProvider] Relay feed setup complete, isReady set to true')
return return
} }
if (feedType === 'relays') { if (feedType === 'relays') {
@ -190,11 +197,15 @@ export function FeedProvider({ children }: { children: React.ReactNode }) {
if (feedType === 'all-favorites') { if (feedType === 'all-favorites') {
// Filter out blocked relays // Filter out blocked relays
const visibleRelays = favoriteRelays.filter(relay => !blockedRelays.includes(relay)) const visibleRelays = favoriteRelays.filter(relay => !blockedRelays.includes(relay))
logger.debug('Switching to all-favorites, favoriteRelays:', visibleRelays)
// If no visible relays, fall back to default favorite relays
const finalRelays = visibleRelays.length > 0 ? visibleRelays : DEFAULT_FAVORITE_RELAYS
logger.debug('Switching to all-favorites, favoriteRelays:', visibleRelays, 'finalRelays:', finalRelays)
const newFeedInfo = { feedType } const newFeedInfo = { feedType }
setFeedInfo(newFeedInfo) setFeedInfo(newFeedInfo)
feedInfoRef.current = newFeedInfo feedInfoRef.current = newFeedInfo
setRelayUrls(visibleRelays) setRelayUrls(finalRelays)
storage.setFeedInfo(newFeedInfo, pubkey) storage.setFeedInfo(newFeedInfo, pubkey)
setIsReady(true) setIsReady(true)
return return

4
src/providers/NotificationProvider.tsx

@ -196,12 +196,14 @@ export function NotificationProvider({ children }: { children: React.ReactNode }
} }
// Only reconnect if still mounted and not a manual close // Only reconnect if still mounted and not a manual close
// Increase timeout to prevent rapid reconnection loops
if (isMountedRef.current) { if (isMountedRef.current) {
setTimeout(() => { setTimeout(() => {
if (isMountedRef.current) { if (isMountedRef.current) {
console.log('[NotificationProvider] Reconnecting after close...')
subscribe() subscribe()
} }
}, 5_000) }, 15_000) // Increased from 5s to 15s
} }
} }
} }

17
src/services/client.service.ts

@ -1,4 +1,4 @@
import { BIG_RELAY_URLS, DEFAULT_FAVORITE_RELAYS, ExtendedKind, FAST_READ_RELAY_URLS, FAST_WRITE_RELAY_URLS, PROFILE_FETCH_RELAY_URLS, SEARCHABLE_RELAY_URLS } from '@/constants' import { BIG_RELAY_URLS, DEFAULT_FAVORITE_RELAYS, ExtendedKind, FAST_READ_RELAY_URLS, FAST_WRITE_RELAY_URLS, PROFILE_FETCH_RELAY_URLS, PROFILE_RELAY_URLS, SEARCHABLE_RELAY_URLS } from '@/constants'
import { import {
compareEvents, compareEvents,
getReplaceableCoordinate, getReplaceableCoordinate,
@ -79,9 +79,6 @@ class ClientService extends EventTarget {
super() super()
this.pool = new SimplePool() this.pool = new SimplePool()
this.pool.trackRelays = true this.pool.trackRelays = true
// Pre-blacklist known problematic relays
this.blacklistRelay('wss://freelay.sovbit.host/')
} }
public static getInstance(): ClientService { public static getInstance(): ClientService {
@ -151,10 +148,16 @@ class ClientService extends EventTarget {
kinds.Contacts, kinds.Contacts,
ExtendedKind.FAVORITE_RELAYS, ExtendedKind.FAVORITE_RELAYS,
ExtendedKind.BLOSSOM_SERVER_LIST, ExtendedKind.BLOSSOM_SERVER_LIST,
ExtendedKind.RELAY_REVIEW ExtendedKind.RELAY_REVIEW,
ExtendedKind.BLOCKED_RELAYS,
kinds.Pinlist,
kinds.Mutelist,
kinds.BookmarkList,
kinds.InterestsList,
ExtendedKind.FAVORITE_RELAYS,
].includes(event.kind) ].includes(event.kind)
) { ) {
_additionalRelayUrls.push(...BIG_RELAY_URLS) _additionalRelayUrls.push(...PROFILE_RELAY_URLS, ...FAST_WRITE_RELAY_URLS)
} }
// Use current user's relay list // Use current user's relay list
@ -1950,7 +1953,7 @@ class ClientService extends EventTarget {
} }
// For other feeds: limit to 3 relays to prevent "too many concurrent REQs" errors (reduced from 5) // For other feeds: limit to 3 relays to prevent "too many concurrent REQs" errors (reduced from 5)
return validRelays.slice(0, 3) return validRelays.slice(0, 5)
} }
// ================= Utils ================= // ================= Utils =================

4
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 showRecommendedRelaysPanel: boolean = true private showRecommendedRelaysPanel: boolean = false
private shownCreateWalletGuideToastPubkeys: Set<string> = new Set() private shownCreateWalletGuideToastPubkeys: Set<string> = new Set()
constructor() { constructor() {
@ -166,7 +166,7 @@ class LocalStorageService {
window.localStorage.getItem(StorageKey.DISMISSED_TOO_MANY_RELAYS_ALERT) === 'true' window.localStorage.getItem(StorageKey.DISMISSED_TOO_MANY_RELAYS_ALERT) === 'true'
const storedValue = window.localStorage.getItem(StorageKey.SHOW_RECOMMENDED_RELAYS_PANEL) const storedValue = window.localStorage.getItem(StorageKey.SHOW_RECOMMENDED_RELAYS_PANEL)
this.showRecommendedRelaysPanel = storedValue !== 'false' // Default to true if not explicitly set to false this.showRecommendedRelaysPanel = storedValue === 'true' // Default to false if not explicitly set to true
const showKindsStr = window.localStorage.getItem(StorageKey.SHOW_KINDS) const showKindsStr = window.localStorage.getItem(StorageKey.SHOW_KINDS)
if (!showKindsStr) { if (!showKindsStr) {

10
vite.config.ts

@ -39,7 +39,7 @@ export default defineConfig({
VitePWA({ VitePWA({
registerType: 'autoUpdate', registerType: 'autoUpdate',
workbox: { workbox: {
globPatterns: ['**/*.{js,css,html,png,jpg,svg}'], globPatterns: ['**/*.{js,css,html,png,jpg,svg,ico,webmanifest}'],
globDirectory: 'dist/', globDirectory: 'dist/',
maximumFileSizeToCacheInBytes: 5 * 1024 * 1024, maximumFileSizeToCacheInBytes: 5 * 1024 * 1024,
cleanupOutdatedCaches: true, cleanupOutdatedCaches: true,
@ -47,6 +47,14 @@ export default defineConfig({
clientsClaim: true, clientsClaim: true,
navigateFallback: '/index.html', navigateFallback: '/index.html',
navigateFallbackDenylist: [/^\/api\//, /^\/_/, /^\/admin/], navigateFallbackDenylist: [/^\/api\//, /^\/_/, /^\/admin/],
// Exclude source files and development files from precaching
globIgnores: [
'**/src/**',
'**/node_modules/**',
'**/*.map',
'**/sw.js',
'**/workbox-*.js'
],
runtimeCaching: [ runtimeCaching: [
{ {
urlPattern: /^https:\/\/image\.nostr\.build\/.*/i, urlPattern: /^https:\/\/image\.nostr\.build\/.*/i,

Loading…
Cancel
Save