import { useEffect, useContext, createContext, useState, useCallback, useMemo } from 'react' import Table from 'react-bootstrap/Table' import ActionTooltip from './action-tooltip' import Info from './info' import styles from './fee-button.module.css' import { gql, useQuery } from '@apollo/client' import { ANON_FEE_MULTIPLIER, FAST_POLL_INTERVAL, SSR } from '@/lib/constants' import { numWithUnits } from '@/lib/format' import { useMe } from './me' import AnonIcon from '@/svgs/spy-fill.svg' import { useShowModal } from './modal' import Link from 'next/link' import { SubmitButton } from './form' const FeeButtonContext = createContext() export function postCommentBaseLineItems ({ baseCost = 1, comment = false, allowFreebies = true, me }) { const anonCharge = me ? {} : { anonCharge: { term: `x ${ANON_FEE_MULTIPLIER}`, label: 'anon mult', modifier: (cost) => cost * ANON_FEE_MULTIPLIER } } return { baseCost: { term: baseCost, label: `${comment ? 'comment' : 'post'} cost`, modifier: (cost) => cost + baseCost, allowFreebies }, ...anonCharge } } export function postCommentUseRemoteLineItems ({ parentId } = {}) { const query = parentId ? gql`{ itemRepetition(parentId: "${parentId}") }` : gql`{ itemRepetition }` return function useRemoteLineItems () { const [line, setLine] = useState({}) const { data } = useQuery(query, SSR ? {} : { pollInterval: FAST_POLL_INTERVAL, nextFetchPolicy: 'cache-and-network' }) useEffect(() => { const repetition = data?.itemRepetition if (!repetition) return setLine({}) setLine({ itemRepetition: { term: <>x 10{repetition}, label: <>{repetition} {parentId ? 'repeat or self replies' : 'posts'} in 10m, modifier: (cost) => cost * Math.pow(10, repetition) } }) }, [data?.itemRepetition]) return line } } export function FeeButtonProvider ({ baseLineItems = {}, useRemoteLineItems = () => null, children }) { const [lineItems, setLineItems] = useState({}) const [disabled, setDisabled] = useState(false) const me = useMe() const remoteLineItems = useRemoteLineItems() const mergeLineItems = useCallback((newLineItems) => { setLineItems(lineItems => ({ ...lineItems, ...newLineItems })) }, [setLineItems]) const value = useMemo(() => { const lines = { ...baseLineItems, ...lineItems, ...remoteLineItems } const total = Object.values(lines).reduce((acc, { modifier }) => modifier(acc), 0) // freebies: there's only a base cost and we don't have enough sats const free = total === lines.baseCost?.modifier(0) && lines.baseCost?.allowFreebies && me?.privates?.sats < total return { lines, merge: mergeLineItems, total, disabled, setDisabled, free } }, [me?.privates?.sats, baseLineItems, lineItems, remoteLineItems, mergeLineItems, disabled, setDisabled]) return ( {children} ) } export function useFeeButton () { const context = useContext(FeeButtonContext) return context } function FreebieDialog () { return ( <>
you don't have enough sats, so this one is on us
) } export default function FeeButton ({ ChildButton = SubmitButton, variant, text, disabled }) { const me = useMe() const { lines, total, disabled: ctxDisabled, free } = useFeeButton() const feeText = free ? 'free' : total > 1 ? numWithUnits(total, { abbreviate: false, format: true }) : undefined disabled ||= ctxDisabled return (
{text} {!me && } {(free && ) || (total > 1 && )}
) } function Receipt ({ lines, total }) { return ( {Object.entries(lines).map(([key, { term, label, omit }]) => ( !omit && ))}
{term} {label}
{numWithUnits(total, { abbreviate: false, format: true })} total fee
) } function AnonInfo () { const showModal = useShowModal() return ( showModal(onClose =>
You are posting without an account
  1. You'll pay by invoice
  2. Your content will be content-joined (get it?!) under the @anon account
  3. Any sats your content earns will go toward rewards
  4. We won't be able to notify you when you receive replies
btw if you don't need to be anonymous, posting is cheaper with an account
) } /> ) }