diff --git a/package-lock.json b/package-lock.json
index 16ad1fa4..33cb4d32 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "jumble-imwald",
- "version": "21.3.0",
+ "version": "21.3.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "jumble-imwald",
- "version": "21.3.0",
+ "version": "21.3.1",
"license": "MIT",
"dependencies": {
"@asciidoctor/core": "^3.0.4",
diff --git a/package.json b/package.json
index 91ba492e..2aa6a821 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "jumble-imwald",
- "version": "21.3.0",
+ "version": "21.3.1",
"description": "A user-friendly Nostr client focused on relay feed browsing and relay discovery, forked from Jumble",
"private": true,
"type": "module",
diff --git a/src/pages/secondary/BookmarkListPage/index.tsx b/src/pages/secondary/BookmarkListPage/index.tsx
index f5b56d89..14fa0726 100644
--- a/src/pages/secondary/BookmarkListPage/index.tsx
+++ b/src/pages/secondary/BookmarkListPage/index.tsx
@@ -29,6 +29,7 @@ import { fetchLatestReplaceableListEvent } from '@/lib/replaceable-list-latest'
import { normalizeUrl } from '@/lib/url'
import { PROFILE_FETCH_RELAY_URLS } from '@/constants'
import { queryService } from '@/services/client.service'
+import dayjs from 'dayjs'
import { Code, Eraser, MoreVertical } from 'lucide-react'
import { kinds } from 'nostr-tools'
import { forwardRef, useCallback, useEffect, useMemo, useState } from 'react'
@@ -108,6 +109,9 @@ const BookmarkListPage = forwardRef(
if (!pubkey || cleaning) return
setCleaning(true)
try {
+ if (dayjs().unix() === bookmarkListEvent?.created_at) {
+ await new Promise((resolve) => setTimeout(resolve, 1000))
+ }
const comprehensiveRelays = await buildAccountListRelayUrlsForMerge({
accountPubkey: pubkey,
favoriteRelays: favoriteRelays ?? [],
@@ -124,7 +128,7 @@ const BookmarkListPage = forwardRef(
setCleaning(false)
setCleanConfirmOpen(false)
}
- }, [pubkey, cleaning, favoriteRelays, blockedRelays, publish, updateBookmarkListEvent, refreshFromRelays, t])
+ }, [pubkey, cleaning, bookmarkListEvent?.created_at, favoriteRelays, blockedRelays, publish, updateBookmarkListEvent, refreshFromRelays, t])
if (!profile || !pubkey) {
return
diff --git a/src/pages/secondary/FollowingListPage/index.tsx b/src/pages/secondary/FollowingListPage/index.tsx
index 89bb4eb9..40eec860 100644
--- a/src/pages/secondary/FollowingListPage/index.tsx
+++ b/src/pages/secondary/FollowingListPage/index.tsx
@@ -26,6 +26,7 @@ import { FOLLOWS_HISTORY_RELAY_URLS } from '@/constants'
import { createFollowListDraftEvent } from '@/lib/draft-event'
import { useFavoriteRelays } from '@/providers/FavoriteRelaysProvider'
import { useNostr } from '@/providers/NostrProvider'
+import dayjs from 'dayjs'
import { Code, Eraser, MoreVertical } from 'lucide-react'
import { forwardRef, useCallback, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
@@ -70,6 +71,9 @@ const FollowingListPage = forwardRef(({ id, index, hideTitlebar = false }: { id?
if (!accountPubkey || !isOwnList || cleaning) return
setCleaning(true)
try {
+ if (dayjs().unix() === followListEvent?.created_at) {
+ await new Promise((resolve) => setTimeout(resolve, 1000))
+ }
const comprehensiveRelays = await buildAccountListRelayUrlsForMerge({
accountPubkey,
favoriteRelays: favoriteRelays ?? [],
diff --git a/src/pages/secondary/InterestListPage/index.tsx b/src/pages/secondary/InterestListPage/index.tsx
index 18dae3e9..962370e4 100644
--- a/src/pages/secondary/InterestListPage/index.tsx
+++ b/src/pages/secondary/InterestListPage/index.tsx
@@ -31,6 +31,7 @@ import { useInterestList } from '@/providers/InterestListProvider'
import { useNostr } from '@/providers/NostrProvider'
import { useFavoriteRelays } from '@/providers/FavoriteRelaysProvider'
import client from '@/services/client.service'
+import dayjs from 'dayjs'
import { Code, Eraser, MoreVertical, Trash2 } from 'lucide-react'
import { forwardRef, useCallback, useEffect, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
@@ -109,6 +110,9 @@ const InterestListPage = forwardRef(
if (!pubkey || cleaning) return
setCleaning(true)
try {
+ if (dayjs().unix() === interestListEvent?.created_at) {
+ await new Promise((resolve) => setTimeout(resolve, 1000))
+ }
const comprehensiveRelays = await buildAccountListRelayUrlsForMerge({
accountPubkey: pubkey,
favoriteRelays: favoriteRelays ?? [],
@@ -124,7 +128,7 @@ const InterestListPage = forwardRef(
setCleaning(false)
setCleanConfirmOpen(false)
}
- }, [pubkey, cleaning, favoriteRelays, blockedRelays, publish, updateInterestListEvent, t])
+ }, [pubkey, cleaning, interestListEvent?.created_at, favoriteRelays, blockedRelays, publish, updateInterestListEvent, t])
if (!profile || !pubkey) {
return
diff --git a/src/pages/secondary/MuteListPage/index.tsx b/src/pages/secondary/MuteListPage/index.tsx
index c8b23f59..efec6daa 100644
--- a/src/pages/secondary/MuteListPage/index.tsx
+++ b/src/pages/secondary/MuteListPage/index.tsx
@@ -32,6 +32,7 @@ import indexedDb from '@/services/indexed-db.service'
import { useFavoriteRelays } from '@/providers/FavoriteRelaysProvider'
import { useNostr } from '@/providers/NostrProvider'
import { Code, Eraser, Lock, MoreVertical, Unlock } from 'lucide-react'
+import dayjs from 'dayjs'
import { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { toast } from 'sonner'
@@ -45,7 +46,7 @@ const MuteListPage = forwardRef(({ index, hideTitlebar = false }: { index?: numb
const { getMutePubkeys } = useMuteList()
const [jsonOpen, setJsonOpen] = useState(false)
const [jsonPayload, setJsonPayload] = useState(null)
- const mutePubkeys = useMemo(() => getMutePubkeys(), [pubkey])
+ const mutePubkeys = useMemo(() => getMutePubkeys(), [getMutePubkeys])
const [visibleMutePubkeys, setVisibleMutePubkeys] = useState([])
const [listRefreshKey, setListRefreshKey] = useState(0)
const [cleanConfirmOpen, setCleanConfirmOpen] = useState(false)
@@ -119,6 +120,9 @@ const MuteListPage = forwardRef(({ index, hideTitlebar = false }: { index?: numb
if (!pubkey || cleaning) return
setCleaning(true)
try {
+ if (dayjs().unix() === muteListEvent?.created_at) {
+ await new Promise((resolve) => setTimeout(resolve, 1000))
+ }
const comprehensiveRelays = await buildAccountListRelayUrlsForMerge({
accountPubkey: pubkey,
favoriteRelays: favoriteRelays ?? [],
diff --git a/src/pages/secondary/PinListPage/index.tsx b/src/pages/secondary/PinListPage/index.tsx
index 45dcef4c..c235149c 100644
--- a/src/pages/secondary/PinListPage/index.tsx
+++ b/src/pages/secondary/PinListPage/index.tsx
@@ -26,6 +26,7 @@ import { fetchNewestPinListForPubkey } from '@/lib/replaceable-list-latest'
import { useNostr } from '@/providers/NostrProvider'
import { useFavoriteRelays } from '@/providers/FavoriteRelaysProvider'
import indexedDb from '@/services/indexed-db.service'
+import dayjs from 'dayjs'
import { Code, Eraser, MoreVertical } from 'lucide-react'
import type { Event } from 'nostr-tools'
import { forwardRef, useCallback, useEffect, useMemo, useState } from 'react'
@@ -112,6 +113,9 @@ const PinListPage = forwardRef(
if (!pubkey || cleaning) return
setCleaning(true)
try {
+ if (dayjs().unix() === pinListEvent?.created_at) {
+ await new Promise((resolve) => setTimeout(resolve, 1000))
+ }
const comprehensiveRelays = await buildAccountListRelayUrlsForMerge({
accountPubkey: pubkey,
favoriteRelays: favoriteRelays ?? [],
@@ -132,7 +136,7 @@ const PinListPage = forwardRef(
setCleaning(false)
setCleanConfirmOpen(false)
}
- }, [pubkey, cleaning, favoriteRelays, blockedRelays, publish, t])
+ }, [pubkey, cleaning, pinListEvent?.created_at, favoriteRelays, blockedRelays, publish, t])
if (!profile || !pubkey) {
return
diff --git a/src/providers/MuteListProvider.tsx b/src/providers/MuteListProvider.tsx
index 502a6a20..13295498 100644
--- a/src/providers/MuteListProvider.tsx
+++ b/src/providers/MuteListProvider.tsx
@@ -138,9 +138,9 @@ export function MuteListProvider({ children }: { children: ReactNode }) {
updateMuteTags()
}, [muteListEvent, isAccountSessionHydrating, account?.signerType, account?.pubkey])
- const getMutePubkeys = () => {
+ const getMutePubkeys = useCallback(() => {
return Array.from(mutePubkeySet)
- }
+ }, [mutePubkeySet])
const getMuteType = useCallback(
(pubkey: string): 'public' | 'private' | null => {
diff --git a/src/providers/NostrProvider/index.tsx b/src/providers/NostrProvider/index.tsx
index c5ebc54f..a39f6174 100644
--- a/src/providers/NostrProvider/index.tsx
+++ b/src/providers/NostrProvider/index.tsx
@@ -1353,11 +1353,10 @@ export function NostrProvider({ children }: { children: React.ReactNode }) {
}
const updateFollowListEvent = async (followListEvent: Event) => {
- const newFollowListEvent = await indexedDb.putReplaceableEvent(followListEvent)
- if (newFollowListEvent.id !== followListEvent.id) return
-
- setFollowListEvent(newFollowListEvent)
- await client.updateFollowListCache(newFollowListEvent)
+ const stored = await indexedDb.putReplaceableEvent(followListEvent)
+ /** Always sync follow list state/cache to the IndexedDB winner. */
+ setFollowListEvent(stored)
+ await client.updateFollowListCache(stored)
}
const updateMuteListEvent = async (muteListEvent: Event, privateTags: string[][]) => {
@@ -1373,17 +1372,15 @@ export function NostrProvider({ children }: { children: React.ReactNode }) {
}
const updateBookmarkListEvent = async (bookmarkListEvent: Event) => {
- const newBookmarkListEvent = await indexedDb.putReplaceableEvent(bookmarkListEvent)
- if (newBookmarkListEvent.id !== bookmarkListEvent.id) return
-
- setBookmarkListEvent(newBookmarkListEvent)
+ const stored = await indexedDb.putReplaceableEvent(bookmarkListEvent)
+ /** Keep bookmark UI aligned with replaceable winner from storage. */
+ setBookmarkListEvent(stored)
}
const updateInterestListEvent = async (interestListEvent: Event) => {
- const newInterestListEvent = await indexedDb.putReplaceableEvent(interestListEvent)
- if (newInterestListEvent.id !== interestListEvent.id) return
-
- setInterestListEvent(newInterestListEvent)
+ const stored = await indexedDb.putReplaceableEvent(interestListEvent)
+ /** Keep interests UI aligned with replaceable winner from storage. */
+ setInterestListEvent(stored)
}
const updateFavoriteRelaysEvent = async (favoriteRelaysEvent: Event) => {