kopia lustrzana https://gitlab.com/soapbox-pub/soapbox
Merge branch 'nostr-sign-load' into 'main'
Draft: Load the Nostr signer before calling verify_credentials See merge request soapbox-pub/soapbox!3010merge-requests/3010/merge
commit
daa347013e
|
@ -15,6 +15,11 @@ interface NostrConnectResponse {
|
|||
error?: string;
|
||||
}
|
||||
|
||||
let onOpen: () => void;
|
||||
const open = new Promise<void>((resolve) => {
|
||||
onOpen = resolve;
|
||||
});
|
||||
|
||||
function useSignerStream() {
|
||||
const { relay, pubkey, signer } = useNostr();
|
||||
|
||||
|
@ -143,6 +148,18 @@ function useSignerStream() {
|
|||
};
|
||||
|
||||
}, [relay, pubkey, signer]);
|
||||
|
||||
useEffect(() => {
|
||||
if (relay) {
|
||||
if (relay.socket.readyState === WebSocket.OPEN) {
|
||||
onOpen();
|
||||
} else {
|
||||
relay.socket.addEventListener('open', onOpen, { once: true });
|
||||
}
|
||||
}
|
||||
}, [relay]);
|
||||
|
||||
return { open };
|
||||
}
|
||||
|
||||
export { useSignerStream };
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
import { NRelay, NRelay1, NostrSigner } from '@soapbox/nspec';
|
||||
import { NRelay1, NostrSigner } from '@soapbox/nspec';
|
||||
import { getPublicKey, nip19 } from 'nostr-tools';
|
||||
import React, { createContext, useContext, useState, useEffect, useMemo } from 'react';
|
||||
|
||||
import { NKeys } from 'soapbox/features/nostr/keys';
|
||||
import { useOwnAccount } from 'soapbox/hooks';
|
||||
import { useAuthToken } from 'soapbox/hooks/useAuthToken';
|
||||
import { useInstance } from 'soapbox/hooks/useInstance';
|
||||
|
||||
interface NostrContextType {
|
||||
relay?: NRelay;
|
||||
relay?: NRelay1;
|
||||
pubkey?: string;
|
||||
signer?: NostrSigner;
|
||||
}
|
||||
|
@ -21,11 +22,29 @@ export const NostrProvider: React.FC<NostrProviderProps> = ({ children }) => {
|
|||
const instance = useInstance();
|
||||
const [relay, setRelay] = useState<NRelay1>();
|
||||
|
||||
const { account } = useOwnAccount();
|
||||
const token = useAuthToken();
|
||||
|
||||
const url = instance.nostr?.relay;
|
||||
const pubkey = instance.nostr?.pubkey;
|
||||
const accountPubkey = account?.nostr.pubkey;
|
||||
|
||||
let accountPubkey: string | undefined;
|
||||
|
||||
try {
|
||||
const result = nip19.decode(token!);
|
||||
switch (result.type) {
|
||||
case 'npub':
|
||||
accountPubkey = result.data;
|
||||
break;
|
||||
case 'nsec':
|
||||
accountPubkey = getPublicKey(result.data);
|
||||
break;
|
||||
case 'nprofile':
|
||||
accountPubkey = result.data.pubkey;
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
const signer = useMemo(
|
||||
() => (accountPubkey ? NKeys.get(accountPubkey) : undefined) ?? window.nostr,
|
||||
|
|
|
@ -13,7 +13,6 @@ import { fetchScheduledStatuses } from 'soapbox/actions/scheduled-statuses';
|
|||
import { fetchSuggestionsForTimeline } from 'soapbox/actions/suggestions';
|
||||
import { expandHomeTimeline } from 'soapbox/actions/timelines';
|
||||
import { useUserStream } from 'soapbox/api/hooks';
|
||||
import { useSignerStream } from 'soapbox/api/hooks/nostr/useSignerStream';
|
||||
import SidebarNavigation from 'soapbox/components/sidebar-navigation';
|
||||
import ThumbNavigation from 'soapbox/components/thumb-navigation';
|
||||
import { Layout } from 'soapbox/components/ui';
|
||||
|
@ -459,7 +458,6 @@ const UI: React.FC<IUI> = ({ children }) => {
|
|||
}, []);
|
||||
|
||||
useUserStream();
|
||||
useSignerStream();
|
||||
|
||||
// The user has logged in
|
||||
useEffect(() => {
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
import { selectAccount } from 'soapbox/selectors';
|
||||
import { RootState } from 'soapbox/store';
|
||||
import { getAuthUserId, getAuthUserUrl } from 'soapbox/utils/auth';
|
||||
|
||||
import { useAppSelector } from './useAppSelector';
|
||||
|
||||
export function useAuthToken(): string | undefined {
|
||||
const getMeId = (state: RootState) => state.me || getAuthUserId(state);
|
||||
|
||||
const getMeUrl = (state: RootState) => {
|
||||
const accountId = getMeId(state);
|
||||
if (accountId) {
|
||||
return selectAccount(state, accountId)?.url || getAuthUserUrl(state);
|
||||
}
|
||||
};
|
||||
|
||||
const getMeToken = (state: RootState) => {
|
||||
// Fallback for upgrading IDs to URLs
|
||||
const accountUrl = getMeUrl(state) || state.auth.me;
|
||||
return state.auth.users.get(accountUrl!)?.access_token;
|
||||
};
|
||||
|
||||
return useAppSelector((state) => getMeToken(state));
|
||||
}
|
|
@ -4,6 +4,7 @@ import { IntlProvider } from 'react-intl';
|
|||
import { fetchInstance } from 'soapbox/actions/instance';
|
||||
import { fetchMe } from 'soapbox/actions/me';
|
||||
import { loadSoapboxConfig } from 'soapbox/actions/soapbox';
|
||||
import { useSignerStream } from 'soapbox/api/hooks/nostr/useSignerStream';
|
||||
import LoadingScreen from 'soapbox/components/loading-screen';
|
||||
import {
|
||||
useAppSelector,
|
||||
|
@ -14,13 +15,14 @@ import {
|
|||
import MESSAGES from 'soapbox/messages';
|
||||
|
||||
/** Load initial data from the backend */
|
||||
const loadInitial = () => {
|
||||
const loadInitial = (open: Promise<void>) => {
|
||||
// @ts-ignore
|
||||
return async(dispatch, getState) => {
|
||||
// Await for authenticated fetch
|
||||
await dispatch(fetchInstance());
|
||||
await open;
|
||||
await dispatch(fetchMe());
|
||||
// Await for feature detection
|
||||
await dispatch(fetchInstance());
|
||||
// Await for configuration
|
||||
await dispatch(loadSoapboxConfig());
|
||||
};
|
||||
|
@ -43,6 +45,8 @@ const SoapboxLoad: React.FC<ISoapboxLoad> = ({ children }) => {
|
|||
const [localeLoading, setLocaleLoading] = useState(true);
|
||||
const [isLoaded, setIsLoaded] = useState(false);
|
||||
|
||||
const { open } = useSignerStream();
|
||||
|
||||
/** Whether to display a loading indicator. */
|
||||
const showLoading = [
|
||||
me === null,
|
||||
|
@ -62,7 +66,7 @@ const SoapboxLoad: React.FC<ISoapboxLoad> = ({ children }) => {
|
|||
|
||||
// Load initial data from the API
|
||||
useEffect(() => {
|
||||
dispatch(loadInitial()).then(() => {
|
||||
dispatch(loadInitial(open)).then(() => {
|
||||
setIsLoaded(true);
|
||||
}).catch(() => {
|
||||
setIsLoaded(true);
|
||||
|
|
Ładowanie…
Reference in New Issue