diff --git a/src/renderer/src/PageManager.tsx b/src/renderer/src/PageManager.tsx index d7a7fad..79f0add 100644 --- a/src/renderer/src/PageManager.tsx +++ b/src/renderer/src/PageManager.tsx @@ -142,13 +142,13 @@ export function PageManager({
- +
{children}
- + {secondaryStack.length ? ( secondaryStack.map((item, index) => (
(undefined) const [events, setEvents] = useState([]) const [newEvents, setNewEvents] = useState([]) @@ -44,7 +45,7 @@ export default function NoteList({ }, [JSON.stringify(filter), areAlgoRelays]) useEffect(() => { - if (!isReady || isFetchingRelayInfo) return + if (isFetchingRelayInfo) return async function init() { setInitialized(false) @@ -75,7 +76,13 @@ export default function NoteList({ ) } }, - { signer: signEvent, needSort: !areAlgoRelays } + { + signer: async (evt) => { + const signedEvt = await checkLogin(() => signEvent(evt)) + return signedEvt ?? null + }, + needSort: !areAlgoRelays + } ) setTimelineKey(timelineKey) return closer @@ -88,9 +95,9 @@ export default function NoteList({ }, [ JSON.stringify(relayUrls), JSON.stringify(noteFilter), - isReady, isFetchingRelayInfo, - areAlgoRelays + areAlgoRelays, + refreshCount ]) useEffect(() => { @@ -157,7 +164,17 @@ export default function NoteList({ ))}
- {hasMore ?
{t('loading...')}
: t('no more notes')} + {hasMore ? ( +
{t('loading...')}
+ ) : events.length ? ( + t('no more notes') + ) : ( +
+ +
+ )}
) diff --git a/src/renderer/src/components/ReplyNoteList/index.tsx b/src/renderer/src/components/ReplyNoteList/index.tsx index 50a5a44..5f25890 100644 --- a/src/renderer/src/components/ReplyNoteList/index.tsx +++ b/src/renderer/src/components/ReplyNoteList/index.tsx @@ -15,7 +15,7 @@ const LIMIT = 100 export default function ReplyNoteList({ event, className }: { event: NEvent; className?: string }) { const { t } = useTranslation() - const { isReady, pubkey } = useNostr() + const { pubkey } = useNostr() const [timelineKey, setTimelineKey] = useState(undefined) const [until, setUntil] = useState(() => dayjs().unix()) const [replies, setReplies] = useState([]) @@ -46,7 +46,7 @@ export default function ReplyNoteList({ event, className }: { event: NEvent; cla }, []) useEffect(() => { - if (!isReady || loading) return + if (loading) return const init = async () => { setLoading(true) @@ -87,7 +87,7 @@ export default function ReplyNoteList({ event, className }: { event: NEvent; cla return () => { promise.then((closer) => closer?.()) } - }, [isReady]) + }, []) useEffect(() => { updateNoteReplyCount(event.id, replies.length) diff --git a/src/renderer/src/i18n/en.ts b/src/renderer/src/i18n/en.ts index 821dc0e..6e7b234 100644 --- a/src/renderer/src/i18n/en.ts +++ b/src/renderer/src/i18n/en.ts @@ -87,6 +87,7 @@ export default { 'Using private key login is insecure. It is recommended to use a browser extension for login, such as alby, nostr-keyx or nos2x.', 'Login with Browser Extension': 'Login with Browser Extension', 'Login with Bunker': 'Login with Bunker', - 'Login with Private Key': 'Login with Private Key' + 'Login with Private Key': 'Login with Private Key', + 'reload notes': 'reload notes' } } diff --git a/src/renderer/src/i18n/zh.ts b/src/renderer/src/i18n/zh.ts index ac2c38b..85857fb 100644 --- a/src/renderer/src/i18n/zh.ts +++ b/src/renderer/src/i18n/zh.ts @@ -85,6 +85,7 @@ export default { '使用私钥登录是不安全的。建议使用浏览器插件进行登录,例如 alby、nostr-keyx 或 nos2x', 'Login with Browser Extension': '浏览器插件登录', 'Login with Bunker': 'Bunker 登录', - 'Login with Private Key': '私钥登录' + 'Login with Private Key': '私钥登录', + 'reload notes': '重新加载笔记' } } diff --git a/src/renderer/src/providers/NostrProvider/index.tsx b/src/renderer/src/providers/NostrProvider/index.tsx index 8ff6d96..c0d7336 100644 --- a/src/renderer/src/providers/NostrProvider/index.tsx +++ b/src/renderer/src/providers/NostrProvider/index.tsx @@ -16,7 +16,6 @@ import { Nip07Signer } from './nip-07.signer' import { NsecSigner } from './nsec.signer' type TNostrContext = { - isReady: boolean pubkey: string | null setPubkey: (pubkey: string) => void nsecLogin: (nsec: string) => Promise @@ -29,7 +28,7 @@ type TNostrContext = { publish: (draftEvent: TDraftEvent, additionalRelayUrls?: string[]) => Promise signHttpAuth: (url: string, method: string) => Promise signEvent: (draftEvent: TDraftEvent) => Promise - checkLogin: (cb?: () => void | Promise) => void + checkLogin: (cb?: () => T) => Promise } const NostrContext = createContext(undefined) @@ -44,7 +43,6 @@ export const useNostr = () => { export function NostrProvider({ children }: { children: React.ReactNode }) { const { toast } = useToast() - const [isReady, setIsReady] = useState(false) const [pubkey, setPubkey] = useState(null) const [signer, setSigner] = useState(null) const [openLoginDialog, setOpenLoginDialog] = useState(false) @@ -56,18 +54,17 @@ export function NostrProvider({ children }: { children: React.ReactNode }) { const [account] = await storage.getAccounts() if (!account) { if (isElectron(window) || !window.nostr) { - return setIsReady(true) + return } // For browser env, attempt to login with nip-07 const nip07Signer = new Nip07Signer() const pubkey = await nip07Signer.getPublicKey() if (!pubkey) { - return setIsReady(true) + return } setPubkey(pubkey) setSigner(nip07Signer) - setIsReady(true) return await storage.setAccounts([{ pubkey, signerType: 'nip-07' }]) } @@ -81,24 +78,24 @@ export function NostrProvider({ children }: { children: React.ReactNode }) { if (!pubkey) { setPubkey(null) await storage.setAccounts([]) - return setIsReady(true) + return } setPubkey(pubkey) setSigner(nsecSigner) - return setIsReady(true) + return } if (account.signerType === 'browser-nsec') { if (!account.nsec) { setPubkey(null) await storage.setAccounts([]) - return setIsReady(true) + return } const browserNsecSigner = new BrowserNsecSigner() const pubkey = browserNsecSigner.login(account.nsec) setPubkey(pubkey) setSigner(browserNsecSigner) - return setIsReady(true) + return } if (account.signerType === 'nip-07') { @@ -107,33 +104,32 @@ export function NostrProvider({ children }: { children: React.ReactNode }) { if (!pubkey) { setPubkey(null) await storage.setAccounts([]) - return setIsReady(true) + return } setPubkey(pubkey) setSigner(nip07Signer) - return setIsReady(true) + return } if (account.signerType === 'bunker') { if (!account.bunker || !account.bunkerClientSecretKey) { setPubkey(null) await storage.setAccounts([]) - return setIsReady(true) + return } const bunkerSigner = new BunkerSigner(hexToBytes(account.bunkerClientSecretKey)) const pubkey = await bunkerSigner.login(account.bunker) setPubkey(pubkey) setSigner(bunkerSigner) - return setIsReady(true) + return } await storage.setAccounts([]) - return setIsReady(true) + return } init().catch(() => { setPubkey(null) storage.setAccounts([]) - setIsReady(true) }) }, []) @@ -238,8 +234,8 @@ export function NostrProvider({ children }: { children: React.ReactNode }) { return 'Nostr ' + btoa(JSON.stringify(event)) } - const checkLogin = async (cb?: () => void) => { - if (pubkey) { + const checkLogin = async (cb?: () => T): Promise => { + if (signer) { return cb && cb() } return setOpenLoginDialog(true) @@ -248,7 +244,6 @@ export function NostrProvider({ children }: { children: React.ReactNode }) { return ( Promise + signer?: (evt: TDraftEvent) => Promise needSort?: boolean } = {} ) { @@ -221,12 +221,21 @@ class ClientService extends EventTarget { if (reason.startsWith('auth-required:')) { if (!hasAuthed && signer) { relay - .auth((authEvt: EventTemplate) => { - return signer(authEvt) as Promise + .auth(async (authEvt: EventTemplate) => { + const evt = await signer(authEvt) + if (!evt) { + throw new Error('sign event failed') + } + return evt as VerifiedEvent }) .then(() => { hasAuthed = true - startSub() + if (!eosed) { + startSub() + } + }) + .catch(() => { + // ignore }) } }