kopia lustrzana https://gitlab.com/soapbox-pub/soapbox
Update hook to use react query
rodzic
7357391250
commit
801bf70d6b
|
@ -32,7 +32,7 @@ const ZapsModal: React.FC<IZapsModal> = ({ onClose, statusId }) => {
|
|||
const next = useAppSelector((state) => state.user_lists.zapped_by.get(statusId)?.next);
|
||||
const nutzaps = useWalletStore().nutzappedRecord[statusId];
|
||||
const { nextZaps } = useWalletStore();
|
||||
const { getNutzappedBy, expandNutzappedBy } = useZappedByCashu();
|
||||
const { getNutzappedBy, expandNutzappedBy } = useZappedByCashu(statusId);
|
||||
|
||||
const accounts = useMemo((): ImmutableList<IAccountWithZaps> | undefined => {
|
||||
if (!zaps && !nutzaps) return;
|
||||
|
@ -51,7 +51,7 @@ const ZapsModal: React.FC<IZapsModal> = ({ onClose, statusId }) => {
|
|||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
getNutzappedBy(statusId);
|
||||
getNutzappedBy();
|
||||
}, []);
|
||||
|
||||
const onClickClose = () => {
|
||||
|
@ -63,7 +63,7 @@ const ZapsModal: React.FC<IZapsModal> = ({ onClose, statusId }) => {
|
|||
dispatch(expandZaps(statusId, next));
|
||||
}
|
||||
if (nextZaps) {
|
||||
expandNutzappedBy(statusId);
|
||||
expandNutzappedBy();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import eyeIcon from '@tabler/icons/outline/eye.svg';
|
|||
import walletIcon from '@tabler/icons/outline/wallet.svg';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import Button from 'soapbox/components/ui/button.tsx';
|
||||
import HStack from 'soapbox/components/ui/hstack.tsx';
|
||||
|
@ -23,7 +24,7 @@ const messages = defineMessages({
|
|||
|
||||
const PocketWallet = () => {
|
||||
const intl = useIntl();
|
||||
const { wallet } = useWallet();
|
||||
const { walletData } = useWallet();
|
||||
|
||||
const [expanded, setExpanded] = useState(false);
|
||||
const [eyeClosed, setEyeClosed] = useState(() => {
|
||||
|
@ -35,24 +36,26 @@ const PocketWallet = () => {
|
|||
localStorage.setItem('soapbox:wallet:eye', JSON.stringify(eyeClosed));
|
||||
}, [eyeClosed]);
|
||||
|
||||
if (!wallet) {
|
||||
if (!walletData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<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 space={1} alignItems='center'>
|
||||
<Icon src={walletIcon} size={20} className='text-gray-200' />
|
||||
<Text size='lg'>
|
||||
{intl.formatMessage(messages.wallet)}
|
||||
</Text>
|
||||
</HStack>
|
||||
<Link to={'/wallet'}>
|
||||
<HStack space={1} alignItems='center'>
|
||||
<Icon src={walletIcon} size={20} className='text-gray-200' />
|
||||
<Text size='lg'>
|
||||
{intl.formatMessage(messages.wallet)}
|
||||
</Text>
|
||||
</HStack>
|
||||
</Link>
|
||||
|
||||
<HStack alignItems='center' space={2}>
|
||||
{!expanded && <>
|
||||
{ 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>}
|
||||
|
||||
<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)}>
|
||||
|
|
|
@ -90,7 +90,7 @@ const NewMint = ({ onBack, list }: NewMintProps) => {
|
|||
const api = useApi();
|
||||
const intl = useIntl();
|
||||
const { getWallet } = useWallet();
|
||||
const { getTransactions } = useTransactions();
|
||||
const { refetch } = useTransactions();
|
||||
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
|
||||
|
@ -113,7 +113,7 @@ const NewMint = ({ onBack, list }: NewMintProps) => {
|
|||
toast.success(intl.formatMessage(messages.paidMessage));
|
||||
onBack();
|
||||
getWallet();
|
||||
getTransactions();
|
||||
refetch();
|
||||
handleClean();
|
||||
setCurrentState('default');
|
||||
}
|
||||
|
@ -233,7 +233,7 @@ const NewMint = ({ onBack, list }: NewMintProps) => {
|
|||
};
|
||||
|
||||
const Balance = () => {
|
||||
const { wallet } = useWallet();
|
||||
const { walletData } = useWallet();
|
||||
const [amount, setAmount] = useState(0);
|
||||
const [mints, setMints] = useState<string[]>([]);
|
||||
const { account } = useOwnAccount();
|
||||
|
@ -246,11 +246,11 @@ const Balance = () => {
|
|||
|
||||
useEffect(
|
||||
() => {
|
||||
if (wallet){
|
||||
setMints([...wallet.mints]);
|
||||
setAmount(wallet.balance);
|
||||
if (walletData){
|
||||
setMints([...walletData.mints]);
|
||||
setAmount(walletData.balance);
|
||||
}
|
||||
}, [wallet],
|
||||
}, [walletData],
|
||||
);
|
||||
|
||||
if (!account) {
|
||||
|
|
|
@ -12,7 +12,7 @@ import Stack from 'soapbox/components/ui/stack.tsx';
|
|||
import Text from 'soapbox/components/ui/text.tsx';
|
||||
import Tooltip from 'soapbox/components/ui/tooltip.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';
|
||||
|
||||
const messages = defineMessages({
|
||||
|
@ -28,7 +28,7 @@ const CreateWallet = () => {
|
|||
const [formActive, setFormActive] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [mints, setMints] = useState<string[]>([]);
|
||||
const { createWallet } = useWallet();
|
||||
const { mutateAsync: createWallet } = useCreateWallet();
|
||||
|
||||
const handleSubmit = async () => {
|
||||
setIsLoading(true);
|
||||
|
@ -38,8 +38,12 @@ const CreateWallet = () => {
|
|||
relays: [],
|
||||
};
|
||||
|
||||
await createWallet(walletInfo);
|
||||
setIsLoading(false);
|
||||
try {
|
||||
await createWallet(walletInfo);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
if (!account) {
|
||||
|
|
|
@ -25,7 +25,7 @@ const messages = defineMessages({
|
|||
const WalletMints = () => {
|
||||
const intl = useIntl();
|
||||
const api = useApi();
|
||||
const { wallet } = useWallet();
|
||||
const { walletData } = useWallet();
|
||||
|
||||
const [relays, setRelays] = useState<string[]>([]);
|
||||
const [initialMints, setInitialMints] = useState<string[]>([]);
|
||||
|
@ -65,11 +65,11 @@ const WalletMints = () => {
|
|||
setIsLoading(true);
|
||||
setHasError(false);
|
||||
|
||||
if (wallet) {
|
||||
if (walletData) {
|
||||
try {
|
||||
setMints(wallet.mints ?? []);
|
||||
setInitialMints(wallet.mints ?? []);
|
||||
setRelays(wallet.relays ?? []);
|
||||
setMints(walletData.mints ?? []);
|
||||
setInitialMints(walletData.mints ?? []);
|
||||
setRelays(walletData.relays ?? []);
|
||||
} catch (error) {
|
||||
console.error('Error setting wallet data:', error);
|
||||
setHasError(true);
|
||||
|
@ -80,15 +80,15 @@ const WalletMints = () => {
|
|||
} else {
|
||||
// Handle the case when wallet is null or undefined
|
||||
setIsLoading(false);
|
||||
if (wallet === undefined) { // wallet is still loading
|
||||
if (walletData === undefined) { // wallet is still loading
|
||||
// Keep loading state true
|
||||
setIsLoading(true);
|
||||
} else if (wallet === null) { // wallet failed to load
|
||||
} else if (walletData === null) { // wallet failed to load
|
||||
setHasError(true);
|
||||
toast.error(intl.formatMessage(messages.loadingError));
|
||||
}
|
||||
}
|
||||
}, [wallet, intl],
|
||||
}, [walletData, intl],
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -25,7 +25,7 @@ const messages = defineMessages({
|
|||
const WalletRelays = () => {
|
||||
const intl = useIntl();
|
||||
const api = useApi();
|
||||
const { wallet } = useWallet();
|
||||
const { walletData } = useWallet();
|
||||
|
||||
const [relays, setRelays] = useState<string[]>([]);
|
||||
const [initialRelays, setInitialRelays] = useState<string[]>([]);
|
||||
|
@ -64,11 +64,11 @@ const WalletRelays = () => {
|
|||
setIsLoading(true);
|
||||
setHasError(false);
|
||||
|
||||
if (wallet) {
|
||||
if (walletData) {
|
||||
try {
|
||||
setMints(wallet.mints ?? []);
|
||||
setInitialRelays(wallet.relays ?? []);
|
||||
setRelays(wallet.relays ?? []);
|
||||
setMints(walletData.mints ?? []);
|
||||
setInitialRelays(walletData.relays ?? []);
|
||||
setRelays(walletData.relays ?? []);
|
||||
} catch (error) {
|
||||
console.error('Error setting wallet data:', error);
|
||||
setHasError(true);
|
||||
|
@ -78,14 +78,14 @@ const WalletRelays = () => {
|
|||
}
|
||||
} else {
|
||||
setIsLoading(false);
|
||||
if (wallet === undefined) {
|
||||
if (walletData === undefined) {
|
||||
setIsLoading(true);
|
||||
} else if (wallet === null) {
|
||||
} else if (walletData === null) {
|
||||
setHasError(true);
|
||||
toast.error(intl.formatMessage(messages.loadingError));
|
||||
}
|
||||
}
|
||||
}, [wallet, intl],
|
||||
}, [walletData, intl],
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -46,7 +46,7 @@ const Wallet = () => {
|
|||
const [retryTimer, setRetryTimer] = useState<NodeJS.Timeout | null>(null);
|
||||
|
||||
const { account } = useOwnAccount();
|
||||
const { wallet: walletData, isLoading, error, getWallet } = useWallet();
|
||||
const { walletData, getWallet, isLoading, error } = useWallet();
|
||||
const { method, changeMethod } = usePaymentMethod();
|
||||
const { transactions } = useTransactions();
|
||||
const hasTransactions = transactions && transactions.length > 0;
|
||||
|
@ -60,7 +60,7 @@ const Wallet = () => {
|
|||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { debounce } from 'es-toolkit';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { create } from 'zustand';
|
||||
|
||||
import { useApi } from 'soapbox/hooks/useApi.ts';
|
||||
|
@ -10,7 +9,7 @@ import type { Account as AccountEntity, Status as StatusEntity } from 'soapbox/t
|
|||
|
||||
interface WalletState {
|
||||
wallet: WalletData | null;
|
||||
acceptsZapsCashu: boolean;
|
||||
// acceptsZapsCashu: boolean;
|
||||
transactions: Transactions | null;
|
||||
zapCashuList: string[];
|
||||
nutzappedRecord: NutzappedRecord;
|
||||
|
@ -22,7 +21,6 @@ interface WalletState {
|
|||
hasFetchedTransactions: boolean;
|
||||
|
||||
setNutzappedRecord: (statusId: string, nutzappedEntry: NutzappedEntry, prevZaps?: string | null, nextZaps?: string | null) => void;
|
||||
setAcceptsZapsCashu: (acceptsZapsCashu: boolean) => void;
|
||||
setWallet: (wallet: WalletData | null) => void;
|
||||
setHasFetchedWallet: (hasFetchedWallet: boolean) => void;
|
||||
setTransactions: (transactions: Transactions | null, prevTransaction?: string | null, nextTransaction?: string | null) => void;
|
||||
|
@ -35,6 +33,13 @@ interface IWalletInfo {
|
|||
relays: string[];
|
||||
}
|
||||
|
||||
interface IZapCashuPayload {
|
||||
account: AccountEntity;
|
||||
amount: number;
|
||||
comment: string;
|
||||
status : StatusEntity;
|
||||
}
|
||||
|
||||
const useWalletStore = create<WalletState>((set) => ({
|
||||
wallet: null,
|
||||
acceptsZapsCashu: false,
|
||||
|
@ -56,7 +61,6 @@ const useWalletStore = create<WalletState>((set) => ({
|
|||
prevZaps,
|
||||
nextZaps,
|
||||
})),
|
||||
setAcceptsZapsCashu: (acceptsZapsCashu) => set({ acceptsZapsCashu }),
|
||||
setWallet: (wallet) => set({ wallet }),
|
||||
setHasFetchedWallet: (hasFetchedWallet) => set({ hasFetchedWallet }),
|
||||
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 { wallet, setWallet, setAcceptsZapsCashu, hasFetchedWallet, setHasFetchedWallet } = useWalletStore();
|
||||
const [isLoading, setIsLoading] = useState(!hasFetchedWallet);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const queryClient = useQueryClient();
|
||||
const { setWallet } = useWalletStore();
|
||||
|
||||
const createWallet = async (walletInfo: IWalletInfo) => {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
return useMutation({
|
||||
mutationFn: async (walletInfo: IWalletInfo) => {
|
||||
const response = await api.put('/api/v1/ditto/cashu/wallet', walletInfo);
|
||||
const data = await response.json();
|
||||
if (data) {
|
||||
const normalizedData = baseWalletSchema.parse(data);
|
||||
toast.success('Wallet created successfully');
|
||||
setWallet(normalizedData);
|
||||
}
|
||||
} catch (err) {
|
||||
const messageError = err instanceof Error ? err.message : 'An error has occurred';
|
||||
setError(messageError);
|
||||
toast.error(messageError);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
return baseWalletSchema.parse(data);
|
||||
},
|
||||
onSuccess: (data) => {
|
||||
toast.success('Wallet created successfully');
|
||||
setWallet(data);
|
||||
queryClient.invalidateQueries({ queryKey: ['wallet'] });
|
||||
},
|
||||
onError: (error: any) => {
|
||||
toast.error(error?.message || 'An error occurred while creating the wallet');
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const getWallet = async (hasMessage = true) => {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const useWallet = () => {
|
||||
const api = useApi();
|
||||
const {
|
||||
setWallet,
|
||||
setHasFetchedWallet,
|
||||
} = useWalletStore();
|
||||
|
||||
const getWallet = useQuery({
|
||||
queryKey: ['wallet'],
|
||||
queryFn: async () => {
|
||||
const response = await api.get('/api/v1/ditto/cashu/wallet');
|
||||
const data = await response.json();
|
||||
if (data) {
|
||||
const normalizedData = baseWalletSchema.parse(data);
|
||||
setAcceptsZapsCashu(true);
|
||||
const normalizedData = baseWalletSchema.parse(data);
|
||||
|
||||
setWallet(normalizedData);
|
||||
}
|
||||
} catch (err) {
|
||||
const messageError = err instanceof Error ? err.message : 'Wallet not found';
|
||||
if (hasMessage) toast.error(messageError);
|
||||
setError(messageError);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
setWallet(normalizedData);
|
||||
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 api = useApi();
|
||||
const { transactions, nextTransaction, setTransactions, hasFetchedTransactions, setHasFetchedTransactions } = useWalletStore();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const { transactions, nextTransaction, setTransactions } = useWalletStore();
|
||||
|
||||
const getTransactions = async () => {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const getTransactions = useQuery({
|
||||
queryKey: ['transactions'],
|
||||
queryFn: async () => {
|
||||
const response = await api.get('/api/v1/ditto/cashu/transactions');
|
||||
const { prev, next } = response.pagination();
|
||||
const data = await response.json();
|
||||
if (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 normalizedData = transactionsSchema.parse(data);
|
||||
|
||||
setTransactions(normalizedData, prev, next);
|
||||
return normalizedData;
|
||||
},
|
||||
});
|
||||
|
||||
const expandTransactions = useMutation({
|
||||
mutationFn: async () => {
|
||||
if (!nextTransaction || !transactions) {
|
||||
return false;
|
||||
// throw new Error('No more transactions');
|
||||
}
|
||||
|
||||
const expandTransactions = async () => {
|
||||
if (!nextTransaction || !transactions) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const response = await api.get(nextTransaction);
|
||||
const { prev, next } = response.pagination();
|
||||
const data = await response.json();
|
||||
|
||||
const normalizedData = transactionsSchema.parse(data);
|
||||
const newTransactions = [...(transactions ?? []), ...normalizedData ];
|
||||
const newTransactions = [...transactions, ...normalizedData];
|
||||
|
||||
setTransactions(newTransactions, prev, next);
|
||||
return true;
|
||||
} catch (err) {
|
||||
const messageError = err instanceof Error ? err.message : 'Error expanding transactions';
|
||||
toast.error(messageError);
|
||||
setError(messageError);
|
||||
return false;
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
},
|
||||
onError: (error: any) => {
|
||||
toast.error(error?.message || 'Error expanding transactions');
|
||||
},
|
||||
});
|
||||
|
||||
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 api = useApi();
|
||||
const { zapCashuList, addZapCashu } = useWalletStore();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const { getWallet } = useWallet();
|
||||
const { getTransactions } = useTransactions();
|
||||
const { addZapCashu } = useWalletStore();
|
||||
const { refetch } = useTransactions();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const zapCashuRequest = async (account: AccountEntity, amount: number, comment: string, status?: StatusEntity) => {
|
||||
setIsLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
const zapCashuRequest = useMutation({
|
||||
mutationFn: async ({ account, amount, comment, status }: IZapCashuPayload) => {
|
||||
await api.post('/api/v1/ditto/cashu/nutzap', {
|
||||
amount,
|
||||
comment,
|
||||
|
@ -207,73 +194,66 @@ const useZapCashuRequest = () => {
|
|||
if (status) {
|
||||
addZapCashu(status.id);
|
||||
}
|
||||
|
||||
},
|
||||
onSuccess: async () =>{
|
||||
toast.success('Sats sent successfully!');
|
||||
getWallet();
|
||||
getTransactions();
|
||||
} catch (err) {
|
||||
queryClient.invalidateQueries({ queryKey: ['wallet'] });
|
||||
await refetch();
|
||||
},
|
||||
onError: (err: unknown) => {
|
||||
const messageError = err instanceof Error ? err.message : 'An unexpected error occurred';
|
||||
setError(messageError);
|
||||
toast.error('An unexpected error occurred');
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
toast.error(messageError);
|
||||
},
|
||||
});
|
||||
|
||||
return { zapCashuList, isLoading, error, zapCashuRequest };
|
||||
return { zapCashu: zapCashuRequest.mutateAsync, isLoading: zapCashuRequest.isPending };
|
||||
};
|
||||
|
||||
const useZappedByCashu = () => {
|
||||
const useZappedByCashu = (statusId: string) => {
|
||||
const api = useApi();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const { nextZaps, nutzappedRecord, setNutzappedRecord } = useWalletStore();
|
||||
|
||||
const getNutzappedBy = async (statusId: string) => {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const getNutzappedBy = useQuery({
|
||||
queryKey: ['nutzappedBy', statusId],
|
||||
queryFn: async () => {
|
||||
const response = await api.get(`/api/v1/ditto/cashu/statuses/${statusId}/nutzapped_by`);
|
||||
const { prev, next } = response.pagination();
|
||||
const data = await response.json();
|
||||
if (data) {
|
||||
const normalizedData = nutzappedEntry.parse(data);
|
||||
setNutzappedRecord(statusId, normalizedData, prev, next);
|
||||
const normalizedData = nutzappedEntry.parse(data);
|
||||
setNutzappedRecord(statusId, normalizedData, prev, next);
|
||||
return normalizedData;
|
||||
},
|
||||
enabled: !!statusId,
|
||||
retry: false,
|
||||
staleTime: 1000 * 60 * 2,
|
||||
});
|
||||
|
||||
const expandNutzappedBy = useMutation({
|
||||
mutationFn: async () => {
|
||||
if (!nextZaps || !nutzappedRecord[statusId]) {
|
||||
throw new Error('No more zaps to load');
|
||||
}
|
||||
} catch (err) {
|
||||
const messageError = err instanceof Error ? err.message : 'Zaps not found';
|
||||
toast.error('Zaps not foud');
|
||||
setError(messageError);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const expandNutzappedBy = debounce(async (id: string) => {
|
||||
if (!nextZaps || !nutzappedRecord[id]) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const response = await api.get(nextZaps);
|
||||
const { prev, next } = response.pagination();
|
||||
const data = await response.json();
|
||||
if (data) {
|
||||
const normalizedData = nutzappedEntry.parse(data);
|
||||
const newNutzappedBy = [...(nutzappedRecord[id] ?? []), ...normalizedData ];
|
||||
|
||||
setNutzappedRecord(id, newNutzappedBy, prev, next);
|
||||
}
|
||||
} catch (err) {
|
||||
const messageError = err instanceof Error ? err.message : 'Error expanding transactions';
|
||||
const normalizedData = nutzappedEntry.parse(data);
|
||||
const newNutzappedBy = [...(nutzappedRecord[statusId] ?? []), ...normalizedData];
|
||||
setNutzappedRecord(statusId, newNutzappedBy, prev, next);
|
||||
return newNutzappedBy;
|
||||
},
|
||||
onError: (err: unknown) => {
|
||||
const messageError = err instanceof Error ? err.message : 'Error expanding zaps';
|
||||
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 };
|
|
@ -9,9 +9,9 @@ import {
|
|||
CtaBanner,
|
||||
PocketWallet,
|
||||
} 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 { useFeatures } from 'soapbox/hooks/useFeatures.ts';
|
||||
import { useOwnAccount } from 'soapbox/hooks/useOwnAccount.ts';
|
||||
|
||||
interface IDefaultPage {
|
||||
children: React.ReactNode;
|
||||
|
@ -20,9 +20,9 @@ interface IDefaultPage {
|
|||
const DefaultPage: React.FC<IDefaultPage> = ({ children }) => {
|
||||
const me = useAppSelector(state => state.me);
|
||||
const features = useFeatures();
|
||||
const { wallet } = useWallet();
|
||||
const { account } = useOwnAccount();
|
||||
const path = useLocation().pathname;
|
||||
const hasPocketWallet = wallet && path !== '/wallet';
|
||||
const hasPocketWallet = account?.ditto.accepts_zaps_cashu && path !== '/wallet';
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -38,7 +38,7 @@ const DefaultPage: React.FC<IDefaultPage> = ({ children }) => {
|
|||
{!me && (
|
||||
<SignUpPanel />
|
||||
)}
|
||||
{hasPocketWallet && (
|
||||
{me && features.nostr && hasPocketWallet && (
|
||||
<PocketWallet />
|
||||
)}
|
||||
{features.trends && (
|
||||
|
|
|
@ -59,8 +59,9 @@ const HomePage: React.FC<IHomePage> = ({ children }) => {
|
|||
dispatch(uploadCompose(composeId, files, intl));
|
||||
});
|
||||
|
||||
const acct = account ? account.acct : '';
|
||||
const avatar = account ? account.avatar : '';
|
||||
const acct = account?.acct ?? '';
|
||||
const avatar = account?.avatar ?? '';
|
||||
const hasWallet = account?.ditto.accepts_zaps_cashu ?? false;
|
||||
|
||||
const renderSuggestions = () => {
|
||||
if (features.suggestionsLocal && !isGlobalPage) {
|
||||
|
@ -113,7 +114,7 @@ const HomePage: React.FC<IHomePage> = ({ children }) => {
|
|||
{!me && (
|
||||
<SignUpPanel />
|
||||
)}
|
||||
{me && features.nostr && (
|
||||
{me && features.nostr && hasWallet && (
|
||||
<PocketWallet />
|
||||
)}
|
||||
{me && features.announcements && (
|
||||
|
|
|
@ -19,7 +19,6 @@ import {
|
|||
AccountNotePanel,
|
||||
PocketWallet,
|
||||
} 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 { useFeatures } from 'soapbox/hooks/useFeatures.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 features = useFeatures();
|
||||
const { displayFqn } = useSoapboxConfig();
|
||||
const { wallet } = useWallet();
|
||||
const hasWallet = account?.ditto.accepts_zaps_cashu ?? false;
|
||||
|
||||
// Fix case of username
|
||||
if (account && account.acct !== username) {
|
||||
|
@ -121,7 +120,7 @@ const ProfilePage: React.FC<IProfilePage> = ({ params, children }) => {
|
|||
<SignUpPanel />
|
||||
)}
|
||||
|
||||
{wallet && (
|
||||
{me && features.nostr && hasWallet && (
|
||||
<PocketWallet />
|
||||
)}
|
||||
|
||||
|
|
|
@ -11,9 +11,9 @@ import {
|
|||
SuggestedGroupsPanel,
|
||||
PocketWallet,
|
||||
} 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 { useFeatures } from 'soapbox/hooks/useFeatures.ts';
|
||||
import { useOwnAccount } from 'soapbox/hooks/useOwnAccount.ts';
|
||||
|
||||
interface IExplorePage {
|
||||
children: React.ReactNode;
|
||||
|
@ -23,7 +23,8 @@ const ExplorePage: React.FC<IExplorePage> = ({ children }) => {
|
|||
const me = useAppSelector(state => state.me);
|
||||
const features = useFeatures();
|
||||
const accountsPath = useLocation().pathname === '/explore/accounts';
|
||||
const { wallet } = useWallet();
|
||||
const { account } = useOwnAccount();
|
||||
const hasWallet = account?.ditto.accepts_zaps_cashu ?? false;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -40,7 +41,7 @@ const ExplorePage: React.FC<IExplorePage> = ({ children }) => {
|
|||
<SignUpPanel />
|
||||
)}
|
||||
|
||||
{wallet && (
|
||||
{hasWallet && (
|
||||
<PocketWallet />
|
||||
)}
|
||||
|
||||
|
|
|
@ -5,9 +5,11 @@ import {
|
|||
TrendsPanel,
|
||||
SignUpPanel,
|
||||
CtaBanner,
|
||||
PocketWallet,
|
||||
} from 'soapbox/features/ui/util/async-components.ts';
|
||||
import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts';
|
||||
import { useFeatures } from 'soapbox/hooks/useFeatures.ts';
|
||||
import { useOwnAccount } from 'soapbox/hooks/useOwnAccount.ts';
|
||||
|
||||
interface IStatusPage {
|
||||
children: React.ReactNode;
|
||||
|
@ -16,6 +18,8 @@ interface IStatusPage {
|
|||
const StatusPage: React.FC<IStatusPage> = ({ children }) => {
|
||||
const me = useAppSelector(state => state.me);
|
||||
const features = useFeatures();
|
||||
const { account } = useOwnAccount();
|
||||
const hasPocketWallet = account?.ditto.accepts_zaps_cashu;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -31,6 +35,9 @@ const StatusPage: React.FC<IStatusPage> = ({ children }) => {
|
|||
{!me && (
|
||||
<SignUpPanel />
|
||||
)}
|
||||
{me && features.nostr && hasPocketWallet && (
|
||||
<PocketWallet />
|
||||
)}
|
||||
{features.trends && (
|
||||
<TrendsPanel limit={5} />
|
||||
)}
|
||||
|
|
Ładowanie…
Reference in New Issue