diff --git a/src/actions/interactions.ts b/src/actions/interactions.ts index 60f1d686b..a8960e607 100644 --- a/src/actions/interactions.ts +++ b/src/actions/interactions.ts @@ -314,18 +314,28 @@ const undislikeFail = (status: StatusEntity, error: unknown) => ({ skipLoading: true, }); -const zap = (status: StatusEntity, amount: number) => - (dispatch: AppDispatch, getState: () => RootState) => { - if (!isLoggedIn(getState)) return; +const zap = (status: StatusEntity, amount: number, comment: string) => (dispatch: AppDispatch, getState: () => RootState) => { + if (!isLoggedIn(getState)) return; - dispatch(zapRequest(status)); + dispatch(zapRequest(status)); - api(getState).post(`/api/v1/statuses/${status.id}/zap`, { amount }).then(function(response) { + return api(getState).post(`/api/v1/statuses/${status.id}/zap`, { amount, comment: comment ?? '' }).then(async function(response) { + const invoice = response.headers['ln-invoice']; + if (!invoice) throw Error('Could not generate invoice'); + if (!window.webln) return invoice; + + try { + await window.webln?.enable(); + await window.webln?.sendPayment(invoice); dispatch(zapSuccess(status)); - }).catch(function(error) { - dispatch(zapFail(status, error)); - }); - }; + return undefined; + } catch (e) { // In case it fails we just return the invoice so the QR code can be created + return invoice; + } + }).catch(function(e) { + dispatch(zapFail(status, e)); + }); +}; const zapRequest = (status: StatusEntity) => ({ type: ZAP_REQUEST, diff --git a/src/components/status-action-bar.tsx b/src/components/status-action-bar.tsx index 61242fee0..09d599c15 100644 --- a/src/components/status-action-bar.tsx +++ b/src/components/status-action-bar.tsx @@ -6,7 +6,7 @@ import { blockAccount } from 'soapbox/actions/accounts'; import { launchChat } from 'soapbox/actions/chats'; import { directCompose, mentionCompose, quoteCompose, replyCompose } from 'soapbox/actions/compose'; import { editEvent } from 'soapbox/actions/events'; -import { pinToGroup, toggleBookmark, toggleDislike, toggleFavourite, togglePin, toggleReblog, unpinFromGroup, zap } from 'soapbox/actions/interactions'; +import { pinToGroup, toggleBookmark, toggleDislike, toggleFavourite, togglePin, toggleReblog, unpinFromGroup } from 'soapbox/actions/interactions'; import { openModal } from 'soapbox/actions/modals'; import { deleteStatusModal, toggleStatusSensitivityModal } from 'soapbox/actions/moderation'; import { initMuteModal } from 'soapbox/actions/mutes'; @@ -195,9 +195,9 @@ const StatusActionBar: React.FC = ({ const handleZapClick: React.EventHandler = (e) => { if (me) { - dispatch(zap(status, 1337)); + dispatch(openModal('ZAP_PAY_REQUEST', { status, account: status.account })); } else { - onOpenUnauthorizedModal('ZAP'); + onOpenUnauthorizedModal('ZAP_PAY_REQUEST'); } }; @@ -800,7 +800,7 @@ const StatusActionBar: React.FC = ({ /> )} - {(acceptsZaps && window.webln) && ( + {(acceptsZaps) && ( > = { 'SELECT_BOOKMARK_FOLDER': SelectBookmarkFolderModal, 'UNAUTHORIZED': UnauthorizedModal, 'VIDEO': VideoModal, + 'ZAP_INVOICE': ZapInvoiceModal, + 'ZAP_PAY_REQUEST': ZapPayRequestModal, }; export type ModalType = keyof typeof MODAL_COMPONENTS | null; diff --git a/src/features/ui/components/modals/zap-invoice.tsx b/src/features/ui/components/modals/zap-invoice.tsx new file mode 100644 index 000000000..962f0ce1c --- /dev/null +++ b/src/features/ui/components/modals/zap-invoice.tsx @@ -0,0 +1,46 @@ +import { QRCodeCanvas } from 'qrcode.react'; +import React from 'react'; +import { FormattedMessage, defineMessages, useIntl } from 'react-intl'; + +import { closeModal } from 'soapbox/actions/modals'; +import CopyableInput from 'soapbox/components/copyable-input'; +import { Modal, Button } from 'soapbox/components/ui'; +import { useAppDispatch } from 'soapbox/hooks'; + +import type { Account as AccountEntity } from 'soapbox/types/entities'; + +const messages = defineMessages({ + zap_open_wallet: { id: 'zap.open_wallet', defaultMessage: 'Open Wallet' }, +}); + +interface IZapInvoice{ + account: AccountEntity; + invoice: string; + onClose:(type?: string) => void; +} + +const ZapInvoiceModal: React.FC = ({ account, invoice, onClose }) => { + const intl = useIntl(); + const dispatch = useAppDispatch(); + + const onClickClose = () => { + onClose('ZAP_INVOICE'); + dispatch(closeModal('ZAP_PAY_REQUEST')); + }; + + const renderTitle = () => { + return ; + }; + + return ( + + + + +