kopia lustrzana https://gitlab.com/soapbox-pub/soapbox
Refactor wallet logic to handle Zap Cashu data
rodzic
fc7a8c849c
commit
92aa009de9
|
@ -48,7 +48,7 @@ import DropdownMenu from 'soapbox/components/dropdown-menu/index.ts';
|
|||
import PureStatusReactionWrapper from 'soapbox/components/pure-status-reaction-wrapper.tsx';
|
||||
import StatusActionButton from 'soapbox/components/status-action-button.tsx';
|
||||
import HStack from 'soapbox/components/ui/hstack.tsx';
|
||||
import { useNutzapRequest, useWallet } from 'soapbox/features/zap/hooks/useHooks.ts';
|
||||
import { useZapCashuRequest, useWallet } from 'soapbox/features/zap/hooks/useHooks.ts';
|
||||
import { useAppDispatch } from 'soapbox/hooks/useAppDispatch.ts';
|
||||
import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts';
|
||||
import { useDislike } from 'soapbox/hooks/useDislike.ts';
|
||||
|
@ -181,8 +181,8 @@ const PureStatusActionBar: React.FC<IPureStatusActionBar> = ({
|
|||
const { boostModal, deleteModal } = useSettings();
|
||||
|
||||
const { wallet } = useWallet();
|
||||
const { nutzapsList } = useNutzapRequest();
|
||||
const isNutzapped = Object.keys(nutzapsList).some((nutzap)=> nutzap === status.id); // TODO: Remove "getWallet" after been in backend
|
||||
const { zapCashuList } = useZapCashuRequest();
|
||||
const isZappedCashu = zapCashuList.some((zapCashu)=> zapCashu === status.id);
|
||||
|
||||
const { account } = useOwnAccount();
|
||||
const isStaff = account ? account.staff : false;
|
||||
|
@ -855,9 +855,9 @@ const PureStatusActionBar: React.FC<IPureStatusActionBar> = ({
|
|||
color='accent'
|
||||
filled
|
||||
onClick={handleZapClick}
|
||||
active={status.nutzapped || status.zapped || isNutzapped}
|
||||
active={status.zapped_cashu || status.zapped || isZappedCashu}
|
||||
theme={statusActionButtonTheme}
|
||||
count={status?.zaps_amount ? status.zaps_amount / 1000 : 0}
|
||||
count={(status?.zaps_amount ?? 0) / 1000 + (status?.zaps_amount_cashu ?? 0)}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ import DropdownMenu from 'soapbox/components/dropdown-menu/index.ts';
|
|||
import StatusActionButton from 'soapbox/components/status-action-button.tsx';
|
||||
import StatusReactionWrapper from 'soapbox/components/status-reaction-wrapper.tsx';
|
||||
import HStack from 'soapbox/components/ui/hstack.tsx';
|
||||
import { useNutzapRequest, useWallet } from 'soapbox/features/zap/hooks/useHooks.ts';
|
||||
import { useZapCashuRequest, useWallet } from 'soapbox/features/zap/hooks/useHooks.ts';
|
||||
import { useAppDispatch } from 'soapbox/hooks/useAppDispatch.ts';
|
||||
import { useAppSelector } from 'soapbox/hooks/useAppSelector.ts';
|
||||
import { useFeatures } from 'soapbox/hooks/useFeatures.ts';
|
||||
|
@ -176,8 +176,8 @@ const StatusActionBar: React.FC<IStatusActionBar> = ({
|
|||
const { boostModal, deleteModal } = useSettings();
|
||||
|
||||
const { wallet } = useWallet();
|
||||
const { nutzapsList } = useNutzapRequest();
|
||||
const isNutzapped = Object.keys(nutzapsList).some((nutzap)=> nutzap === status.id);
|
||||
const { zapCashuList } = useZapCashuRequest();
|
||||
const isZappedCashu = zapCashuList.some((zapCashu)=> zapCashu === status.id);
|
||||
|
||||
const { account } = useOwnAccount();
|
||||
const isStaff = account ? account.staff : false;
|
||||
|
@ -845,9 +845,9 @@ const StatusActionBar: React.FC<IStatusActionBar> = ({
|
|||
color='accent'
|
||||
filled
|
||||
onClick={handleZapClick}
|
||||
active={status.nutzapped || status.zapped || isNutzapped}
|
||||
active={status.zapped_cashu || status.zapped || isZappedCashu}
|
||||
theme={statusActionButtonTheme}
|
||||
count={status?.zaps_amount ? status.zaps_amount / 1000 : 0}
|
||||
count={(status?.zaps_amount ?? 0) / 1000 + (status?.zaps_amount_cashu ?? 0)}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
|
|
@ -206,13 +206,13 @@ const StatusInteractionBar: React.FC<IStatusInteractionBar> = ({ status }): JSX.
|
|||
};
|
||||
|
||||
const getZaps = () => {
|
||||
if (status.zaps_amount) {
|
||||
if (status.zaps_amount || status.zaps_amount_cashu) {
|
||||
return (
|
||||
<InteractionCounter count={status.zaps_amount / 1000} onClick={handleOpenZapsModal}>
|
||||
<InteractionCounter count={(status.zaps_amount ?? 0) / 1000 + (status.zaps_amount_cashu ?? 0)} onClick={handleOpenZapsModal}>
|
||||
<FormattedMessage
|
||||
id='status.interactions.zaps'
|
||||
defaultMessage='{count, plural, one {Zap} other {Zaps}}'
|
||||
values={{ count: status.zaps_amount }}
|
||||
values={{ count: (status.zaps_amount ?? 0) + (status.zaps_amount_cashu ?? 0) }}
|
||||
/>
|
||||
</InteractionCounter>
|
||||
);
|
||||
|
|
|
@ -21,7 +21,7 @@ import Input from 'soapbox/components/ui/input.tsx';
|
|||
import Stack from 'soapbox/components/ui/stack.tsx';
|
||||
import SvgIcon from 'soapbox/components/ui/svg-icon.tsx';
|
||||
import Text from 'soapbox/components/ui/text.tsx';
|
||||
import { useNutzapRequest } from 'soapbox/features/zap/hooks/useHooks.ts';
|
||||
import { useZapCashuRequest } from 'soapbox/features/zap/hooks/useHooks.ts';
|
||||
import { usePaymentMethod } from 'soapbox/features/zap/usePaymentMethod.ts';
|
||||
import { useAppDispatch } from 'soapbox/hooks/useAppDispatch.ts';
|
||||
import { emojifyText } from 'soapbox/utils/emojify.tsx';
|
||||
|
@ -63,7 +63,7 @@ const PayRequestForm = ({ account, status, onClose }: IPayRequestForm) => {
|
|||
const { method: paymentMethod } = usePaymentMethod();
|
||||
const isCashu = paymentMethod === 'cashu';
|
||||
const hasZapSplit = zapArrays.length > 0 && !isCashu;
|
||||
const { nutzapRequest } = useNutzapRequest();
|
||||
const { zapCashuRequest } = useZapCashuRequest();
|
||||
|
||||
const handleSubmit = async (e?: React.FormEvent<Element>) => {
|
||||
e?.preventDefault();
|
||||
|
@ -71,7 +71,7 @@ const PayRequestForm = ({ account, status, onClose }: IPayRequestForm) => {
|
|||
const splitData = { hasZapSplit, zapSplitAccounts, splitValues };
|
||||
|
||||
if (isCashu) {
|
||||
await nutzapRequest(account, amount, zapComment, status);
|
||||
await zapCashuRequest(account, amount, zapComment, status);
|
||||
dispatch(closeModal('PAY_REQUEST'));
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -10,13 +10,13 @@ import type { Account as AccountEntity, Status as StatusEntity } from 'soapbox/t
|
|||
interface WalletState {
|
||||
wallet: WalletData | null;
|
||||
transactions: Transactions | null;
|
||||
nutzapsList: Record<string, { status: StatusEntity; amount: number; comment: string }>; // TODO: remove
|
||||
zapCashuList: string[];
|
||||
prevTransaction?: string | null;
|
||||
nextTransaction?: string | null;
|
||||
|
||||
setWallet: (wallet: WalletData | null) => void;
|
||||
setTransactions: (transactions: Transactions | null, prevTransaction?: string | null, nextTransaction?: string | null) => void;
|
||||
addNutzap: (statusId: string, data: { status: StatusEntity; amount: number; comment: string }) => void;
|
||||
addZapCashu: (statusId: string) => void;
|
||||
}
|
||||
|
||||
interface IWalletInfo {
|
||||
|
@ -29,16 +29,16 @@ const useWalletStore = create<WalletState>((set) => ({
|
|||
transactions: null,
|
||||
prevTransaction: null,
|
||||
nextTransaction: null,
|
||||
nutzapsList: {},
|
||||
zapCashuList: [],
|
||||
|
||||
setWallet: (wallet) => set({ wallet }),
|
||||
setTransactions: (transactions, prevTransaction, nextTransaction) => set({ transactions, prevTransaction, nextTransaction }),
|
||||
addNutzap: (statusId, data) =>
|
||||
addZapCashu: (statusId) =>
|
||||
set((state) => ({
|
||||
nutzapsList: {
|
||||
...state.nutzapsList,
|
||||
[statusId]: data,
|
||||
},
|
||||
zapCashuList: [
|
||||
...state.zapCashuList,
|
||||
statusId,
|
||||
],
|
||||
})),
|
||||
}));
|
||||
|
||||
|
@ -152,15 +152,15 @@ const useTransactions = () => {
|
|||
return { transactions, isLoading, error, getTransactions, expandTransactions };
|
||||
};
|
||||
|
||||
const useNutzapRequest = () => {
|
||||
const useZapCashuRequest = () => {
|
||||
const api = useApi();
|
||||
const { nutzapsList, addNutzap } = useWalletStore();
|
||||
const { zapCashuList, addZapCashu } = useWalletStore();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const { getWallet } = useWallet();
|
||||
const { getTransactions } = useTransactions();
|
||||
|
||||
const nutzapRequest = async (account: AccountEntity, amount: number, comment: string, status?: StatusEntity) => {
|
||||
const zapCashuRequest = async (account: AccountEntity, amount: number, comment: string, status?: StatusEntity) => {
|
||||
setIsLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
|
@ -174,7 +174,7 @@ const useNutzapRequest = () => {
|
|||
const data = await response.json();
|
||||
|
||||
if (status) {
|
||||
addNutzap(status.id, { status, amount, comment });
|
||||
addZapCashu(status.id);
|
||||
}
|
||||
|
||||
toast.success(data.message || 'Zap sent successfully!');
|
||||
|
@ -189,7 +189,7 @@ const useNutzapRequest = () => {
|
|||
}
|
||||
};
|
||||
|
||||
return { nutzapsList, isLoading, error, nutzapRequest };
|
||||
return { zapCashuList, isLoading, error, zapCashuRequest };
|
||||
};
|
||||
|
||||
export { useWallet, useTransactions, useNutzapRequest };
|
||||
export { useWallet, useTransactions, useZapCashuRequest };
|
|
@ -77,7 +77,7 @@ export const StatusRecord = ImmutableRecord({
|
|||
reblogs_count: 0,
|
||||
replies_count: 0,
|
||||
zaps_amount: 0,
|
||||
nutzaps_amount: 0,
|
||||
zaps_amount_cashu: 0,
|
||||
sensitive: false,
|
||||
spoiler_text: '',
|
||||
tags: ImmutableList<ImmutableMap<string, any>>(),
|
||||
|
@ -86,7 +86,7 @@ export const StatusRecord = ImmutableRecord({
|
|||
url: '',
|
||||
visibility: 'public' as StatusVisibility,
|
||||
zapped: false,
|
||||
nutzapped: false,
|
||||
zapped_cashu: false,
|
||||
event: null as ReturnType<typeof EventRecord> | null,
|
||||
|
||||
// Internal fields
|
||||
|
|
|
@ -222,20 +222,13 @@ const simulateDislike = (
|
|||
};
|
||||
|
||||
/** Simulate zap of status for optimistic interactions */
|
||||
const simulatePayment = (state: State, statusId: string, paid: boolean, method: 'cashu' | 'zap'): State => {
|
||||
const simulatePayment = (state: State, statusId: string, zapped: boolean): State => {
|
||||
const status = state.get(statusId);
|
||||
if (!status) return state;
|
||||
let updatedStatus;
|
||||
|
||||
if (method === 'zap') {
|
||||
updatedStatus = status.merge({
|
||||
zapped: paid,
|
||||
});
|
||||
} else {
|
||||
updatedStatus = status.merge({
|
||||
nutzapped: paid,
|
||||
});
|
||||
}
|
||||
const updatedStatus = status.merge({
|
||||
zapped,
|
||||
});
|
||||
|
||||
return state.set(statusId, updatedStatus);
|
||||
};
|
||||
|
@ -295,9 +288,9 @@ export default function statuses(state = initialState, action: AnyAction): State
|
|||
case DISLIKE_FAIL:
|
||||
return state.get(action.status.id) === undefined ? state : state.setIn([action.status.id, 'disliked'], false);
|
||||
case ZAP_REQUEST:
|
||||
return simulatePayment(state, action.status.id, true, 'zap');
|
||||
return simulatePayment(state, action.status.id, true);
|
||||
case ZAP_FAIL:
|
||||
return simulatePayment(state, action.status.id, false, 'zap');
|
||||
return simulatePayment(state, action.status.id, false);
|
||||
case REBLOG_REQUEST:
|
||||
return state.setIn([action.status.id, 'reblogged'], true);
|
||||
case REBLOG_FAIL:
|
||||
|
|
|
@ -73,8 +73,8 @@ const baseStatusSchema = z.object({
|
|||
visibility: z.string().catch('public'),
|
||||
zapped: z.coerce.boolean(),
|
||||
zaps_amount: z.number().catch(0),
|
||||
nutzapped: z.coerce.boolean(),
|
||||
nutzaps_amount: z.number().catch(0),
|
||||
zapped_cashu: z.coerce.boolean(),
|
||||
zaps_amount_cashu: z.number().catch(0),
|
||||
});
|
||||
|
||||
type BaseStatus = z.infer<typeof baseStatusSchema>;
|
||||
|
|
Ładowanie…
Reference in New Issue