Update hook to use react query

merge-requests/3367/head
danidfra 2025-04-24 20:58:02 -03:00
rodzic 7357391250
commit 801bf70d6b
13 zmienionych plików z 198 dodań i 203 usunięć

Wyświetl plik

@ -32,7 +32,7 @@ const ZapsModal: React.FC<IZapsModal> = ({ onClose, statusId }) => {
const next = useAppSelector((state) => state.user_lists.zapped_by.get(statusId)?.next); const next = useAppSelector((state) => state.user_lists.zapped_by.get(statusId)?.next);
const nutzaps = useWalletStore().nutzappedRecord[statusId]; const nutzaps = useWalletStore().nutzappedRecord[statusId];
const { nextZaps } = useWalletStore(); const { nextZaps } = useWalletStore();
const { getNutzappedBy, expandNutzappedBy } = useZappedByCashu(); const { getNutzappedBy, expandNutzappedBy } = useZappedByCashu(statusId);
const accounts = useMemo((): ImmutableList<IAccountWithZaps> | undefined => { const accounts = useMemo((): ImmutableList<IAccountWithZaps> | undefined => {
if (!zaps && !nutzaps) return; if (!zaps && !nutzaps) return;
@ -51,7 +51,7 @@ const ZapsModal: React.FC<IZapsModal> = ({ onClose, statusId }) => {
useEffect(() => { useEffect(() => {
fetchData(); fetchData();
getNutzappedBy(statusId); getNutzappedBy();
}, []); }, []);
const onClickClose = () => { const onClickClose = () => {
@ -63,7 +63,7 @@ const ZapsModal: React.FC<IZapsModal> = ({ onClose, statusId }) => {
dispatch(expandZaps(statusId, next)); dispatch(expandZaps(statusId, next));
} }
if (nextZaps) { if (nextZaps) {
expandNutzappedBy(statusId); expandNutzappedBy();
} }
}; };

Wyświetl plik

@ -5,6 +5,7 @@ import eyeIcon from '@tabler/icons/outline/eye.svg';
import walletIcon from '@tabler/icons/outline/wallet.svg'; import walletIcon from '@tabler/icons/outline/wallet.svg';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { defineMessages, useIntl } from 'react-intl'; import { defineMessages, useIntl } from 'react-intl';
import { Link } from 'react-router-dom';
import Button from 'soapbox/components/ui/button.tsx'; import Button from 'soapbox/components/ui/button.tsx';
import HStack from 'soapbox/components/ui/hstack.tsx'; import HStack from 'soapbox/components/ui/hstack.tsx';
@ -23,7 +24,7 @@ const messages = defineMessages({
const PocketWallet = () => { const PocketWallet = () => {
const intl = useIntl(); const intl = useIntl();
const { wallet } = useWallet(); const { walletData } = useWallet();
const [expanded, setExpanded] = useState(false); const [expanded, setExpanded] = useState(false);
const [eyeClosed, setEyeClosed] = useState(() => { const [eyeClosed, setEyeClosed] = useState(() => {
@ -35,24 +36,26 @@ const PocketWallet = () => {
localStorage.setItem('soapbox:wallet:eye', JSON.stringify(eyeClosed)); localStorage.setItem('soapbox:wallet:eye', JSON.stringify(eyeClosed));
}, [eyeClosed]); }, [eyeClosed]);
if (!wallet) { if (!walletData) {
return null; return null;
} }
return ( return (
<Stack className='rounded-lg border p-2 px-4 black:border-gray-500 dark:border-gray-500' alignItems='center' space={4}> <Stack className='rounded-lg border p-2 px-4 black:border-gray-500 dark:border-gray-500' alignItems='center' space={4}>
<HStack className='w-full' justifyContent='between' alignItems='center' > <HStack className='w-full' justifyContent='between' alignItems='center' >
<Link to={'/wallet'}>
<HStack space={1} alignItems='center'> <HStack space={1} alignItems='center'>
<Icon src={walletIcon} size={20} className='text-gray-200' /> <Icon src={walletIcon} size={20} className='text-gray-200' />
<Text size='lg'> <Text size='lg'>
{intl.formatMessage(messages.wallet)} {intl.formatMessage(messages.wallet)}
</Text> </Text>
</HStack> </HStack>
</Link>
<HStack alignItems='center' space={2}> <HStack alignItems='center' space={2}>
{!expanded && <> {!expanded && <>
{ eyeClosed ? <Text className='text-sm !text-gray-500'>{intl.formatMessage({ id: 'wallet.hidden.balance', defaultMessage: '••••••' })}</Text> : <Text> { eyeClosed ? <Text className='text-sm !text-gray-500'>{intl.formatMessage({ id: 'wallet.hidden.balance', defaultMessage: '••••••' })}</Text> : <Text>
{intl.formatMessage(messages.balance, { amount: wallet.balance })} {intl.formatMessage(messages.balance, { amount: walletData?.balance })}
</Text>} </Text>}
<Button className='!ml-1 space-x-2 !border-none !p-0 !text-gray-500 focus:!ring-transparent focus:ring-offset-transparent rtl:ml-0 rtl:mr-1 rtl:space-x-reverse' theme='transparent' onClick={() => setEyeClosed(!eyeClosed)}> <Button className='!ml-1 space-x-2 !border-none !p-0 !text-gray-500 focus:!ring-transparent focus:ring-offset-transparent rtl:ml-0 rtl:mr-1 rtl:space-x-reverse' theme='transparent' onClick={() => setEyeClosed(!eyeClosed)}>

Wyświetl plik

@ -90,7 +90,7 @@ const NewMint = ({ onBack, list }: NewMintProps) => {
const api = useApi(); const api = useApi();
const intl = useIntl(); const intl = useIntl();
const { getWallet } = useWallet(); const { getWallet } = useWallet();
const { getTransactions } = useTransactions(); const { refetch } = useTransactions();
const now = Math.floor(Date.now() / 1000); const now = Math.floor(Date.now() / 1000);
@ -113,7 +113,7 @@ const NewMint = ({ onBack, list }: NewMintProps) => {
toast.success(intl.formatMessage(messages.paidMessage)); toast.success(intl.formatMessage(messages.paidMessage));
onBack(); onBack();
getWallet(); getWallet();
getTransactions(); refetch();
handleClean(); handleClean();
setCurrentState('default'); setCurrentState('default');
} }
@ -233,7 +233,7 @@ const NewMint = ({ onBack, list }: NewMintProps) => {
}; };
const Balance = () => { const Balance = () => {
const { wallet } = useWallet(); const { walletData } = useWallet();
const [amount, setAmount] = useState(0); const [amount, setAmount] = useState(0);
const [mints, setMints] = useState<string[]>([]); const [mints, setMints] = useState<string[]>([]);
const { account } = useOwnAccount(); const { account } = useOwnAccount();
@ -246,11 +246,11 @@ const Balance = () => {
useEffect( useEffect(
() => { () => {
if (wallet){ if (walletData){
setMints([...wallet.mints]); setMints([...walletData.mints]);
setAmount(wallet.balance); setAmount(walletData.balance);
} }
}, [wallet], }, [walletData],
); );
if (!account) { if (!account) {

Wyświetl plik

@ -12,7 +12,7 @@ import Stack from 'soapbox/components/ui/stack.tsx';
import Text from 'soapbox/components/ui/text.tsx'; import Text from 'soapbox/components/ui/text.tsx';
import Tooltip from 'soapbox/components/ui/tooltip.tsx'; import Tooltip from 'soapbox/components/ui/tooltip.tsx';
import { MintEditor } from 'soapbox/features/wallet/components/editable-lists.tsx'; import { MintEditor } from 'soapbox/features/wallet/components/editable-lists.tsx';
import { useWallet } from 'soapbox/features/zap/hooks/useHooks.ts'; import { useCreateWallet } from 'soapbox/features/zap/hooks/useHooks.ts';
import { useOwnAccount } from 'soapbox/hooks/useOwnAccount.ts'; import { useOwnAccount } from 'soapbox/hooks/useOwnAccount.ts';
const messages = defineMessages({ const messages = defineMessages({
@ -28,7 +28,7 @@ const CreateWallet = () => {
const [formActive, setFormActive] = useState(false); const [formActive, setFormActive] = useState(false);
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [mints, setMints] = useState<string[]>([]); const [mints, setMints] = useState<string[]>([]);
const { createWallet } = useWallet(); const { mutateAsync: createWallet } = useCreateWallet();
const handleSubmit = async () => { const handleSubmit = async () => {
setIsLoading(true); setIsLoading(true);
@ -38,8 +38,12 @@ const CreateWallet = () => {
relays: [], relays: [],
}; };
try {
await createWallet(walletInfo); await createWallet(walletInfo);
} finally {
setIsLoading(false); setIsLoading(false);
}
}; };
if (!account) { if (!account) {

Wyświetl plik

@ -25,7 +25,7 @@ const messages = defineMessages({
const WalletMints = () => { const WalletMints = () => {
const intl = useIntl(); const intl = useIntl();
const api = useApi(); const api = useApi();
const { wallet } = useWallet(); const { walletData } = useWallet();
const [relays, setRelays] = useState<string[]>([]); const [relays, setRelays] = useState<string[]>([]);
const [initialMints, setInitialMints] = useState<string[]>([]); const [initialMints, setInitialMints] = useState<string[]>([]);
@ -65,11 +65,11 @@ const WalletMints = () => {
setIsLoading(true); setIsLoading(true);
setHasError(false); setHasError(false);
if (wallet) { if (walletData) {
try { try {
setMints(wallet.mints ?? []); setMints(walletData.mints ?? []);
setInitialMints(wallet.mints ?? []); setInitialMints(walletData.mints ?? []);
setRelays(wallet.relays ?? []); setRelays(walletData.relays ?? []);
} catch (error) { } catch (error) {
console.error('Error setting wallet data:', error); console.error('Error setting wallet data:', error);
setHasError(true); setHasError(true);
@ -80,15 +80,15 @@ const WalletMints = () => {
} else { } else {
// Handle the case when wallet is null or undefined // Handle the case when wallet is null or undefined
setIsLoading(false); setIsLoading(false);
if (wallet === undefined) { // wallet is still loading if (walletData === undefined) { // wallet is still loading
// Keep loading state true // Keep loading state true
setIsLoading(true); setIsLoading(true);
} else if (wallet === null) { // wallet failed to load } else if (walletData === null) { // wallet failed to load
setHasError(true); setHasError(true);
toast.error(intl.formatMessage(messages.loadingError)); toast.error(intl.formatMessage(messages.loadingError));
} }
} }
}, [wallet, intl], }, [walletData, intl],
); );
return ( return (

Wyświetl plik

@ -25,7 +25,7 @@ const messages = defineMessages({
const WalletRelays = () => { const WalletRelays = () => {
const intl = useIntl(); const intl = useIntl();
const api = useApi(); const api = useApi();
const { wallet } = useWallet(); const { walletData } = useWallet();
const [relays, setRelays] = useState<string[]>([]); const [relays, setRelays] = useState<string[]>([]);
const [initialRelays, setInitialRelays] = useState<string[]>([]); const [initialRelays, setInitialRelays] = useState<string[]>([]);
@ -64,11 +64,11 @@ const WalletRelays = () => {
setIsLoading(true); setIsLoading(true);
setHasError(false); setHasError(false);
if (wallet) { if (walletData) {
try { try {
setMints(wallet.mints ?? []); setMints(walletData.mints ?? []);
setInitialRelays(wallet.relays ?? []); setInitialRelays(walletData.relays ?? []);
setRelays(wallet.relays ?? []); setRelays(walletData.relays ?? []);
} catch (error) { } catch (error) {
console.error('Error setting wallet data:', error); console.error('Error setting wallet data:', error);
setHasError(true); setHasError(true);
@ -78,14 +78,14 @@ const WalletRelays = () => {
} }
} else { } else {
setIsLoading(false); setIsLoading(false);
if (wallet === undefined) { if (walletData === undefined) {
setIsLoading(true); setIsLoading(true);
} else if (wallet === null) { } else if (walletData === null) {
setHasError(true); setHasError(true);
toast.error(intl.formatMessage(messages.loadingError)); toast.error(intl.formatMessage(messages.loadingError));
} }
} }
}, [wallet, intl], }, [walletData, intl],
); );
return ( return (

Wyświetl plik

@ -46,7 +46,7 @@ const Wallet = () => {
const [retryTimer, setRetryTimer] = useState<NodeJS.Timeout | null>(null); const [retryTimer, setRetryTimer] = useState<NodeJS.Timeout | null>(null);
const { account } = useOwnAccount(); const { account } = useOwnAccount();
const { wallet: walletData, isLoading, error, getWallet } = useWallet(); const { walletData, getWallet, isLoading, error } = useWallet();
const { method, changeMethod } = usePaymentMethod(); const { method, changeMethod } = usePaymentMethod();
const { transactions } = useTransactions(); const { transactions } = useTransactions();
const hasTransactions = transactions && transactions.length > 0; const hasTransactions = transactions && transactions.length > 0;
@ -60,7 +60,7 @@ const Wallet = () => {
} }
setIsRetrying(false); setIsRetrying(false);
getWallet(true); // Trigger wallet reload with error messages getWallet(); // Trigger wallet reload with error messages
}; };
// Setup automatic retry when there's an error // Setup automatic retry when there's an error

Wyświetl plik

@ -1,5 +1,4 @@
import { debounce } from 'es-toolkit'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useEffect, useState } from 'react';
import { create } from 'zustand'; import { create } from 'zustand';
import { useApi } from 'soapbox/hooks/useApi.ts'; import { useApi } from 'soapbox/hooks/useApi.ts';
@ -10,7 +9,7 @@ import type { Account as AccountEntity, Status as StatusEntity } from 'soapbox/t
interface WalletState { interface WalletState {
wallet: WalletData | null; wallet: WalletData | null;
acceptsZapsCashu: boolean; // acceptsZapsCashu: boolean;
transactions: Transactions | null; transactions: Transactions | null;
zapCashuList: string[]; zapCashuList: string[];
nutzappedRecord: NutzappedRecord; nutzappedRecord: NutzappedRecord;
@ -22,7 +21,6 @@ interface WalletState {
hasFetchedTransactions: boolean; hasFetchedTransactions: boolean;
setNutzappedRecord: (statusId: string, nutzappedEntry: NutzappedEntry, prevZaps?: string | null, nextZaps?: string | null) => void; setNutzappedRecord: (statusId: string, nutzappedEntry: NutzappedEntry, prevZaps?: string | null, nextZaps?: string | null) => void;
setAcceptsZapsCashu: (acceptsZapsCashu: boolean) => void;
setWallet: (wallet: WalletData | null) => void; setWallet: (wallet: WalletData | null) => void;
setHasFetchedWallet: (hasFetchedWallet: boolean) => void; setHasFetchedWallet: (hasFetchedWallet: boolean) => void;
setTransactions: (transactions: Transactions | null, prevTransaction?: string | null, nextTransaction?: string | null) => void; setTransactions: (transactions: Transactions | null, prevTransaction?: string | null, nextTransaction?: string | null) => void;
@ -35,6 +33,13 @@ interface IWalletInfo {
relays: string[]; relays: string[];
} }
interface IZapCashuPayload {
account: AccountEntity;
amount: number;
comment: string;
status : StatusEntity;
}
const useWalletStore = create<WalletState>((set) => ({ const useWalletStore = create<WalletState>((set) => ({
wallet: null, wallet: null,
acceptsZapsCashu: false, acceptsZapsCashu: false,
@ -56,7 +61,6 @@ const useWalletStore = create<WalletState>((set) => ({
prevZaps, prevZaps,
nextZaps, nextZaps,
})), })),
setAcceptsZapsCashu: (acceptsZapsCashu) => set({ acceptsZapsCashu }),
setWallet: (wallet) => set({ wallet }), setWallet: (wallet) => set({ wallet }),
setHasFetchedWallet: (hasFetchedWallet) => set({ hasFetchedWallet }), setHasFetchedWallet: (hasFetchedWallet) => set({ hasFetchedWallet }),
setTransactions: (transactions, prevTransaction, nextTransaction) => set({ transactions, prevTransaction, nextTransaction }), setTransactions: (transactions, prevTransaction, nextTransaction) => set({ transactions, prevTransaction, nextTransaction }),
@ -70,133 +74,116 @@ const useWalletStore = create<WalletState>((set) => ({
})), })),
})); }));
const useWallet = () => { const useCreateWallet = () => {
const api = useApi(); const api = useApi();
const { wallet, setWallet, setAcceptsZapsCashu, hasFetchedWallet, setHasFetchedWallet } = useWalletStore(); const queryClient = useQueryClient();
const [isLoading, setIsLoading] = useState(!hasFetchedWallet); const { setWallet } = useWalletStore();
const [error, setError] = useState<string | null>(null);
const createWallet = async (walletInfo: IWalletInfo) => { return useMutation({
setIsLoading(true); mutationFn: async (walletInfo: IWalletInfo) => {
try {
const response = await api.put('/api/v1/ditto/cashu/wallet', walletInfo); const response = await api.put('/api/v1/ditto/cashu/wallet', walletInfo);
const data = await response.json(); const data = await response.json();
if (data) { return baseWalletSchema.parse(data);
const normalizedData = baseWalletSchema.parse(data); },
onSuccess: (data) => {
toast.success('Wallet created successfully'); toast.success('Wallet created successfully');
setWallet(normalizedData); setWallet(data);
} queryClient.invalidateQueries({ queryKey: ['wallet'] });
} catch (err) { },
const messageError = err instanceof Error ? err.message : 'An error has occurred'; onError: (error: any) => {
setError(messageError); toast.error(error?.message || 'An error occurred while creating the wallet');
toast.error(messageError); },
} finally { });
setIsLoading(false); };
}
};
const getWallet = async (hasMessage = true) => { const useWallet = () => {
setIsLoading(true); const api = useApi();
try { const {
setWallet,
setHasFetchedWallet,
} = useWalletStore();
const getWallet = useQuery({
queryKey: ['wallet'],
queryFn: async () => {
const response = await api.get('/api/v1/ditto/cashu/wallet'); const response = await api.get('/api/v1/ditto/cashu/wallet');
const data = await response.json(); const data = await response.json();
if (data) {
const normalizedData = baseWalletSchema.parse(data); const normalizedData = baseWalletSchema.parse(data);
setAcceptsZapsCashu(true);
setWallet(normalizedData); setWallet(normalizedData);
}
} catch (err) {
const messageError = err instanceof Error ? err.message : 'Wallet not found';
if (hasMessage) toast.error(messageError);
setError(messageError);
} finally {
setIsLoading(false);
setHasFetchedWallet(true); setHasFetchedWallet(true);
}
return normalizedData;
},
staleTime: 1000 * 60 * 2,
retry: false,
});
return {
walletData: getWallet.data,
error: getWallet.error?.message,
isLoading: getWallet.isLoading,
getWallet: getWallet.refetch,
}; };
useEffect(() => {
if (!hasFetchedWallet) {
getWallet(false);
}
}, []);
return { wallet, isLoading, error, createWallet, getWallet };
}; };
const useTransactions = () => { const useTransactions = () => {
const api = useApi(); const api = useApi();
const { transactions, nextTransaction, setTransactions, hasFetchedTransactions, setHasFetchedTransactions } = useWalletStore(); const { transactions, nextTransaction, setTransactions } = useWalletStore();
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const getTransactions = async () => { const getTransactions = useQuery({
setIsLoading(true); queryKey: ['transactions'],
try { queryFn: async () => {
const response = await api.get('/api/v1/ditto/cashu/transactions'); const response = await api.get('/api/v1/ditto/cashu/transactions');
const { prev, next } = response.pagination(); const { prev, next } = response.pagination();
const data = await response.json(); const data = await response.json();
if (data) {
const normalizedData = transactionsSchema.parse(data); const normalizedData = transactionsSchema.parse(data);
setTransactions(normalizedData, prev, next);
}
} catch (err) {
const messageError = err instanceof Error ? err.message : 'Transactions not found';
toast.error(messageError);
setError(messageError);
} finally {
setIsLoading(false);
}
};
const expandTransactions = async () => { setTransactions(normalizedData, prev, next);
return normalizedData;
},
});
const expandTransactions = useMutation({
mutationFn: async () => {
if (!nextTransaction || !transactions) { if (!nextTransaction || !transactions) {
return false; return false;
// throw new Error('No more transactions');
} }
try {
setIsLoading(true);
const response = await api.get(nextTransaction); const response = await api.get(nextTransaction);
const { prev, next } = response.pagination(); const { prev, next } = response.pagination();
const data = await response.json(); const data = await response.json();
const normalizedData = transactionsSchema.parse(data); const normalizedData = transactionsSchema.parse(data);
const newTransactions = [...(transactions ?? []), ...normalizedData ]; const newTransactions = [...transactions, ...normalizedData];
setTransactions(newTransactions, prev, next); setTransactions(newTransactions, prev, next);
return true; return true;
} catch (err) { },
const messageError = err instanceof Error ? err.message : 'Error expanding transactions'; onError: (error: any) => {
toast.error(messageError); toast.error(error?.message || 'Error expanding transactions');
setError(messageError); },
return false; });
} finally {
setIsLoading(false); return {
} transactions: getTransactions.data,
isLoading: getTransactions.isLoading,
error: getTransactions.error,
refetch: getTransactions.refetch,
expandTransactions: expandTransactions.mutateAsync,
isExpanding: expandTransactions.isPending,
}; };
useEffect(() => {
if (!hasFetchedTransactions) {
setHasFetchedTransactions(true);
getTransactions();
}
}, []);
return { transactions, isLoading, error, getTransactions, expandTransactions };
}; };
const useZapCashuRequest = () => { const useZapCashuRequest = () => {
const api = useApi(); const api = useApi();
const { zapCashuList, addZapCashu } = useWalletStore(); const { addZapCashu } = useWalletStore();
const [isLoading, setIsLoading] = useState(false); const { refetch } = useTransactions();
const [error, setError] = useState<string | null>(null); const queryClient = useQueryClient();
const { getWallet } = useWallet();
const { getTransactions } = useTransactions();
const zapCashuRequest = async (account: AccountEntity, amount: number, comment: string, status?: StatusEntity) => { const zapCashuRequest = useMutation({
setIsLoading(true); mutationFn: async ({ account, amount, comment, status }: IZapCashuPayload) => {
setError(null);
try {
await api.post('/api/v1/ditto/cashu/nutzap', { await api.post('/api/v1/ditto/cashu/nutzap', {
amount, amount,
comment, comment,
@ -207,73 +194,66 @@ const useZapCashuRequest = () => {
if (status) { if (status) {
addZapCashu(status.id); addZapCashu(status.id);
} }
},
onSuccess: async () =>{
toast.success('Sats sent successfully!'); toast.success('Sats sent successfully!');
getWallet(); queryClient.invalidateQueries({ queryKey: ['wallet'] });
getTransactions(); await refetch();
} catch (err) { },
onError: (err: unknown) => {
const messageError = err instanceof Error ? err.message : 'An unexpected error occurred'; const messageError = err instanceof Error ? err.message : 'An unexpected error occurred';
setError(messageError); toast.error(messageError);
toast.error('An unexpected error occurred'); },
} finally { });
setIsLoading(false);
}
};
return { zapCashuList, isLoading, error, zapCashuRequest }; return { zapCashu: zapCashuRequest.mutateAsync, isLoading: zapCashuRequest.isPending };
}; };
const useZappedByCashu = () => { const useZappedByCashu = (statusId: string) => {
const api = useApi(); const api = useApi();
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const { nextZaps, nutzappedRecord, setNutzappedRecord } = useWalletStore(); const { nextZaps, nutzappedRecord, setNutzappedRecord } = useWalletStore();
const getNutzappedBy = async (statusId: string) => { const getNutzappedBy = useQuery({
setIsLoading(true); queryKey: ['nutzappedBy', statusId],
try { queryFn: async () => {
const response = await api.get(`/api/v1/ditto/cashu/statuses/${statusId}/nutzapped_by`); const response = await api.get(`/api/v1/ditto/cashu/statuses/${statusId}/nutzapped_by`);
const { prev, next } = response.pagination(); const { prev, next } = response.pagination();
const data = await response.json(); const data = await response.json();
if (data) {
const normalizedData = nutzappedEntry.parse(data); const normalizedData = nutzappedEntry.parse(data);
setNutzappedRecord(statusId, normalizedData, prev, next); setNutzappedRecord(statusId, normalizedData, prev, next);
} return normalizedData;
} catch (err) { },
const messageError = err instanceof Error ? err.message : 'Zaps not found'; enabled: !!statusId,
toast.error('Zaps not foud'); retry: false,
setError(messageError); staleTime: 1000 * 60 * 2,
} finally { });
setIsLoading(false);
}
};
const expandNutzappedBy = debounce(async (id: string) => { const expandNutzappedBy = useMutation({
if (!nextZaps || !nutzappedRecord[id]) { mutationFn: async () => {
return; if (!nextZaps || !nutzappedRecord[statusId]) {
throw new Error('No more zaps to load');
} }
try {
setIsLoading(true);
const response = await api.get(nextZaps); const response = await api.get(nextZaps);
const { prev, next } = response.pagination(); const { prev, next } = response.pagination();
const data = await response.json(); const data = await response.json();
if (data) {
const normalizedData = nutzappedEntry.parse(data); const normalizedData = nutzappedEntry.parse(data);
const newNutzappedBy = [...(nutzappedRecord[id] ?? []), ...normalizedData ]; const newNutzappedBy = [...(nutzappedRecord[statusId] ?? []), ...normalizedData];
setNutzappedRecord(statusId, newNutzappedBy, prev, next);
setNutzappedRecord(id, newNutzappedBy, prev, next); return newNutzappedBy;
} },
} catch (err) { onError: (err: unknown) => {
const messageError = err instanceof Error ? err.message : 'Error expanding transactions'; const messageError = err instanceof Error ? err.message : 'Error expanding zaps';
toast.error(messageError); toast.error(messageError);
setError(messageError); },
} finally { });
setIsLoading(false);
}
}, 700);
return { error, isLoading, getNutzappedBy, expandNutzappedBy }; return {
error: getNutzappedBy.error,
isLoading: getNutzappedBy.isLoading || expandNutzappedBy.isPending,
getNutzappedBy: getNutzappedBy.refetch,
expandNutzappedBy: expandNutzappedBy.mutateAsync,
};
}; };
export { useWalletStore, useWallet, useTransactions, useZapCashuRequest, useZappedByCashu }; export { useWalletStore, useWallet, useCreateWallet, useTransactions, useZapCashuRequest, useZappedByCashu };

Wyświetl plik

@ -9,9 +9,9 @@ import {
CtaBanner, CtaBanner,
PocketWallet, PocketWallet,
} from 'soapbox/features/ui/util/async-components.ts'; } from 'soapbox/features/ui/util/async-components.ts';
import { useWallet } from 'soapbox/features/zap/hooks/useHooks.ts';
import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts'; import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts';
import { useFeatures } from 'soapbox/hooks/useFeatures.ts'; import { useFeatures } from 'soapbox/hooks/useFeatures.ts';
import { useOwnAccount } from 'soapbox/hooks/useOwnAccount.ts';
interface IDefaultPage { interface IDefaultPage {
children: React.ReactNode; children: React.ReactNode;
@ -20,9 +20,9 @@ interface IDefaultPage {
const DefaultPage: React.FC<IDefaultPage> = ({ children }) => { const DefaultPage: React.FC<IDefaultPage> = ({ children }) => {
const me = useAppSelector(state => state.me); const me = useAppSelector(state => state.me);
const features = useFeatures(); const features = useFeatures();
const { wallet } = useWallet(); const { account } = useOwnAccount();
const path = useLocation().pathname; const path = useLocation().pathname;
const hasPocketWallet = wallet && path !== '/wallet'; const hasPocketWallet = account?.ditto.accepts_zaps_cashu && path !== '/wallet';
return ( return (
<> <>
@ -38,7 +38,7 @@ const DefaultPage: React.FC<IDefaultPage> = ({ children }) => {
{!me && ( {!me && (
<SignUpPanel /> <SignUpPanel />
)} )}
{hasPocketWallet && ( {me && features.nostr && hasPocketWallet && (
<PocketWallet /> <PocketWallet />
)} )}
{features.trends && ( {features.trends && (

Wyświetl plik

@ -59,8 +59,9 @@ const HomePage: React.FC<IHomePage> = ({ children }) => {
dispatch(uploadCompose(composeId, files, intl)); dispatch(uploadCompose(composeId, files, intl));
}); });
const acct = account ? account.acct : ''; const acct = account?.acct ?? '';
const avatar = account ? account.avatar : ''; const avatar = account?.avatar ?? '';
const hasWallet = account?.ditto.accepts_zaps_cashu ?? false;
const renderSuggestions = () => { const renderSuggestions = () => {
if (features.suggestionsLocal && !isGlobalPage) { if (features.suggestionsLocal && !isGlobalPage) {
@ -113,7 +114,7 @@ const HomePage: React.FC<IHomePage> = ({ children }) => {
{!me && ( {!me && (
<SignUpPanel /> <SignUpPanel />
)} )}
{me && features.nostr && ( {me && features.nostr && hasWallet && (
<PocketWallet /> <PocketWallet />
)} )}
{me && features.announcements && ( {me && features.announcements && (

Wyświetl plik

@ -19,7 +19,6 @@ import {
AccountNotePanel, AccountNotePanel,
PocketWallet, PocketWallet,
} from 'soapbox/features/ui/util/async-components.ts'; } from 'soapbox/features/ui/util/async-components.ts';
import { useWallet } from 'soapbox/features/zap/hooks/useHooks.ts';
import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts'; import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts';
import { useFeatures } from 'soapbox/hooks/useFeatures.ts'; import { useFeatures } from 'soapbox/hooks/useFeatures.ts';
import { useSoapboxConfig } from 'soapbox/hooks/useSoapboxConfig.ts'; import { useSoapboxConfig } from 'soapbox/hooks/useSoapboxConfig.ts';
@ -42,7 +41,7 @@ const ProfilePage: React.FC<IProfilePage> = ({ params, children }) => {
const me = useAppSelector(state => state.me); const me = useAppSelector(state => state.me);
const features = useFeatures(); const features = useFeatures();
const { displayFqn } = useSoapboxConfig(); const { displayFqn } = useSoapboxConfig();
const { wallet } = useWallet(); const hasWallet = account?.ditto.accepts_zaps_cashu ?? false;
// Fix case of username // Fix case of username
if (account && account.acct !== username) { if (account && account.acct !== username) {
@ -121,7 +120,7 @@ const ProfilePage: React.FC<IProfilePage> = ({ params, children }) => {
<SignUpPanel /> <SignUpPanel />
)} )}
{wallet && ( {me && features.nostr && hasWallet && (
<PocketWallet /> <PocketWallet />
)} )}

Wyświetl plik

@ -11,9 +11,9 @@ import {
SuggestedGroupsPanel, SuggestedGroupsPanel,
PocketWallet, PocketWallet,
} from 'soapbox/features/ui/util/async-components.ts'; } from 'soapbox/features/ui/util/async-components.ts';
import { useWallet } from 'soapbox/features/zap/hooks/useHooks.ts';
import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts'; import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts';
import { useFeatures } from 'soapbox/hooks/useFeatures.ts'; import { useFeatures } from 'soapbox/hooks/useFeatures.ts';
import { useOwnAccount } from 'soapbox/hooks/useOwnAccount.ts';
interface IExplorePage { interface IExplorePage {
children: React.ReactNode; children: React.ReactNode;
@ -23,7 +23,8 @@ const ExplorePage: React.FC<IExplorePage> = ({ children }) => {
const me = useAppSelector(state => state.me); const me = useAppSelector(state => state.me);
const features = useFeatures(); const features = useFeatures();
const accountsPath = useLocation().pathname === '/explore/accounts'; const accountsPath = useLocation().pathname === '/explore/accounts';
const { wallet } = useWallet(); const { account } = useOwnAccount();
const hasWallet = account?.ditto.accepts_zaps_cashu ?? false;
return ( return (
<> <>
@ -40,7 +41,7 @@ const ExplorePage: React.FC<IExplorePage> = ({ children }) => {
<SignUpPanel /> <SignUpPanel />
)} )}
{wallet && ( {hasWallet && (
<PocketWallet /> <PocketWallet />
)} )}

Wyświetl plik

@ -5,9 +5,11 @@ import {
TrendsPanel, TrendsPanel,
SignUpPanel, SignUpPanel,
CtaBanner, CtaBanner,
PocketWallet,
} from 'soapbox/features/ui/util/async-components.ts'; } from 'soapbox/features/ui/util/async-components.ts';
import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts'; import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts';
import { useFeatures } from 'soapbox/hooks/useFeatures.ts'; import { useFeatures } from 'soapbox/hooks/useFeatures.ts';
import { useOwnAccount } from 'soapbox/hooks/useOwnAccount.ts';
interface IStatusPage { interface IStatusPage {
children: React.ReactNode; children: React.ReactNode;
@ -16,6 +18,8 @@ interface IStatusPage {
const StatusPage: React.FC<IStatusPage> = ({ children }) => { const StatusPage: React.FC<IStatusPage> = ({ children }) => {
const me = useAppSelector(state => state.me); const me = useAppSelector(state => state.me);
const features = useFeatures(); const features = useFeatures();
const { account } = useOwnAccount();
const hasPocketWallet = account?.ditto.accepts_zaps_cashu;
return ( return (
<> <>
@ -31,6 +35,9 @@ const StatusPage: React.FC<IStatusPage> = ({ children }) => {
{!me && ( {!me && (
<SignUpPanel /> <SignUpPanel />
)} )}
{me && features.nostr && hasPocketWallet && (
<PocketWallet />
)}
{features.trends && ( {features.trends && (
<TrendsPanel limit={5} /> <TrendsPanel limit={5} />
)} )}