* Avoid manual optimistic zap updates for now * Remove manual optimistic updates for pay-bounty and poll
		
			
				
	
	
		
			108 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			108 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import React, { useCallback } from 'react'
 | |
| import Button from 'react-bootstrap/Button'
 | |
| import styles from './pay-bounty.module.css'
 | |
| import ActionTooltip from './action-tooltip'
 | |
| import { useMe } from './me'
 | |
| import { numWithUnits } from '@/lib/format'
 | |
| import { useShowModal } from './modal'
 | |
| import { useRoot } from './root'
 | |
| import { useAct, actUpdate } from './item-act'
 | |
| import { InvoiceCanceledError, usePayment } from './payment'
 | |
| import { useLightning } from './lightning'
 | |
| import { useToast } from './toast'
 | |
| import { Types as ClientNotification, useClientNotifications } from './client-notifications'
 | |
| 
 | |
| export default function PayBounty ({ children, item }) {
 | |
|   const me = useMe()
 | |
|   const showModal = useShowModal()
 | |
|   const root = useRoot()
 | |
|   const payment = usePayment()
 | |
|   const strike = useLightning()
 | |
|   const toaster = useToast()
 | |
|   const { notify, unnotify } = useClientNotifications()
 | |
| 
 | |
|   const onUpdate = useCallback(onComplete => (cache, { data: { act: { id, path } } }) => {
 | |
|     // update root bounty status
 | |
|     const root = path.split('.')[0]
 | |
|     cache.modify({
 | |
|       id: `Item:${root}`,
 | |
|       fields: {
 | |
|         bountyPaidTo (existingPaidTo = []) {
 | |
|           return [...(existingPaidTo || []), Number(id)]
 | |
|         }
 | |
|       }
 | |
|     })
 | |
|     strike()
 | |
|     onComplete()
 | |
|   }, [strike])
 | |
| 
 | |
|   const act = useAct()
 | |
| 
 | |
|   const handlePayBounty = async onComplete => {
 | |
|     const sats = root.bounty
 | |
|     const variables = { id: item.id, sats, act: 'TIP', path: item.path }
 | |
|     const notifyProps = { itemId: item.id, sats }
 | |
|     const optimisticResponse = { act: { ...variables, path: item.path } }
 | |
| 
 | |
|     let cancel, nid
 | |
|     try {
 | |
|       if (me) {
 | |
|         nid = notify(ClientNotification.Bounty.PENDING, notifyProps)
 | |
|       }
 | |
| 
 | |
|       let hash, hmac;
 | |
|       [{ hash, hmac }, cancel] = await payment.request(sats)
 | |
| 
 | |
|       await act({
 | |
|         variables: { hash, hmac, ...variables },
 | |
|         optimisticResponse,
 | |
|         update: actUpdate({ me, onUpdate: onUpdate(onComplete) })
 | |
|       })
 | |
|     } catch (error) {
 | |
|       if (error instanceof InvoiceCanceledError) {
 | |
|         return
 | |
|       }
 | |
| 
 | |
|       const reason = error?.message || error?.toString?.()
 | |
|       if (me) {
 | |
|         notify(ClientNotification.Bounty.ERROR, { ...notifyProps, reason })
 | |
|       } else {
 | |
|         toaster.danger('pay bounty failed: ' + reason)
 | |
|       }
 | |
|       cancel?.()
 | |
|     } finally {
 | |
|       if (nid) unnotify(nid)
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (!me || item.mine || root.user.name !== me.name) {
 | |
|     return null
 | |
|   }
 | |
| 
 | |
|   return (
 | |
|     <ActionTooltip
 | |
|       notForm
 | |
|       overlayText={numWithUnits(root.bounty)}
 | |
|     >
 | |
|       <div
 | |
|         className={styles.pay} onClick={() => {
 | |
|           showModal(onClose => (
 | |
|             <>
 | |
|               <div className='text-center fw-bold text-muted'>
 | |
|                 Pay this bounty to {item.user.name}?
 | |
|               </div>
 | |
|               <div className='text-center'>
 | |
|                 <Button className='mt-4' variant='primary' onClick={() => handlePayBounty(onClose)}>
 | |
|                   pay <small>{numWithUnits(root.bounty)}</small>
 | |
|                 </Button>
 | |
|               </div>
 | |
|             </>
 | |
|           ))
 | |
|         }}
 | |
|       >
 | |
|         pay bounty
 | |
|       </div>
 | |
|     </ActionTooltip>
 | |
|   )
 | |
| }
 |