diff --git a/api/typeDefs/user.js b/api/typeDefs/user.js index 086465df..800eb648 100644 --- a/api/typeDefs/user.js +++ b/api/typeDefs/user.js @@ -92,7 +92,7 @@ export default gql` nsfwMode: Boolean! tipDefault: Int! turboTipping: Boolean! - zapUndos: Boolean! + zapUndos: Int wildWestMode: Boolean! withdrawMaxFeeDefault: Int! } @@ -157,7 +157,7 @@ export default gql` nsfwMode: Boolean! tipDefault: Int! turboTipping: Boolean! - zapUndos: Boolean! + zapUndos: Int wildWestMode: Boolean! withdrawMaxFeeDefault: Int! autoWithdrawThreshold: Int diff --git a/components/dont-link-this.js b/components/dont-link-this.js index 0fa35fc4..38574d9f 100644 --- a/components/dont-link-this.js +++ b/components/dont-link-this.js @@ -1,7 +1,7 @@ import Dropdown from 'react-bootstrap/Dropdown' import { useShowModal } from './modal' import { useToast } from './toast' -import ItemAct from './item-act' +import ItemAct, { zapUndosThresholdReached } from './item-act' import AccordianItem from './accordian-item' import Flag from '@/svgs/flag-fill.svg' import { useMemo } from 'react' @@ -32,12 +32,11 @@ function DownZapper ({ id, As, children }) { try { showModal(onClose => { + onClose={(amount) => { onClose() // undo prompt was toasted before closing modal if zap undos are enabled // so an additional success toast would be confusing - const zapUndosEnabled = me && me?.privates?.zapUndos - if (!zapUndosEnabled) toaster.success('item downzapped') + if (!zapUndosThresholdReached(me, amount)) toaster.success('item downzapped') }} itemId={id} down > { window.localStorage.setItem('custom-tips', JSON.stringify(customTips)) } +export const zapUndosThresholdReached = (me, amount) => { + if (!me) return false + const enabled = me.privates.zapUndos !== null + return enabled ? amount >= me.privates.zapUndos : false +} + export default function ItemAct ({ onClose, itemId, down, children }) { const inputRef = useRef(null) const me = useMe() @@ -73,9 +79,9 @@ export default function ItemAct ({ onClose, itemId, down, children }) { }) // only strike when zap undos not enabled // due to optimistic UX on zap undos - if (!me || !me.privates.zapUndos) await strike() + if (!zapUndosThresholdReached(me, Number(amount))) await strike() addCustomTip(Number(amount)) - if (!keepOpen) onClose() + if (!keepOpen) onClose(Number(amount)) }, [me, act, down, itemId, strike]) const onSubmitWithUndos = withToastFlow(toaster)( @@ -123,7 +129,7 @@ export default function ItemAct ({ onClose, itemId, down, children }) { return onSubmit(values, { flowId, ...args, update: null }) } await strike() - onClose() + onClose(sats) return new Promise((resolve, reject) => { undoUpdate = update() setTimeout(() => { @@ -156,7 +162,12 @@ export default function ItemAct ({ onClose, itemId, down, children }) { }} schema={amountSchema} invoiceable - onSubmit={me?.privates?.zapUndos ? onSubmitWithUndos : onSubmit} + onSubmit={(values, ...args) => { + if (zapUndosThresholdReached(me, values.amount)) { + return onSubmitWithUndos(values, ...args) + } + return onSubmit(values, ...args) + }} > { + onSubmit={async ({ tipDefault, withdrawMaxFeeDefault, zapUndos, zapUndosEnabled, nostrPubkey, nostrRelays, ...values }) => { if (nostrPubkey.length === 0) { nostrPubkey = null } else { @@ -116,6 +118,7 @@ export default function Settings ({ ssrData }) { settings: { tipDefault: Number(tipDefault), withdrawMaxFeeDefault: Number(withdrawMaxFeeDefault), + zapUndos: zapUndosEnabled ? Number(zapUndos) : null, nostrPubkey, nostrRelays: nostrRelaysFiltered, ...values @@ -171,25 +174,7 @@ export default function Settings ({ ssrData }) { } groupClassName='mb-0' /> - zap undos - -
    -
  • An undo button is shown after every zap
  • -
  • The button is shown for 5 seconds
  • -
  • - The button is only shown for zaps from the custodial wallet -
  • -
  • - Use a budget or manual approval with attached wallets -
  • -
-
- - } - /> + } /> @@ -920,3 +905,36 @@ I estimate that I will call the GraphQL API this many times (rough estimate is f ) } + +const ZapUndosField = () => { + const [checkboxField] = useField({ name: 'zapUndosEnabled' }) + return ( +
+ + zap undos + +
    +
  • An undo button is shown after every zap that exceeds or is equal to the threshold
  • +
  • The button is shown for 5 seconds
  • +
  • The button is only shown for zaps from the custodial wallet
  • +
  • Use a budget or manual approval with attached wallets
  • +
+
+
+ } + /> + } + append={sats} + hint={threshold at which undo button is shown} + /> + + ) +} diff --git a/prisma/migrations/20240324192055_zap_undos_integer/migration.sql b/prisma/migrations/20240324192055_zap_undos_integer/migration.sql new file mode 100644 index 00000000..05a05eee --- /dev/null +++ b/prisma/migrations/20240324192055_zap_undos_integer/migration.sql @@ -0,0 +1,4 @@ +ALTER TABLE "users" ADD COLUMN "zapUndosTmp" INTEGER; +UPDATE "users" SET "zapUndosTmp" = CASE WHEN "zapUndos" = false THEN NULL ELSE 0::INTEGER END; +ALTER TABLE "users" DROP COLUMN "zapUndos"; +ALTER TABLE "users" RENAME COLUMN "zapUndosTmp" TO "zapUndos"; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index d9669156..0d064557 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -56,7 +56,7 @@ model User { autoDropBolt11s Boolean @default(false) hideFromTopUsers Boolean @default(false) turboTipping Boolean @default(false) - zapUndos Boolean @default(false) + zapUndos Int? imgproxyOnly Boolean @default(false) hideWalletBalance Boolean @default(false) referrerId Int?