diff --git a/api/resolvers/user.js b/api/resolvers/user.js index a58c4af2..f166cb0f 100644 --- a/api/resolvers/user.js +++ b/api/resolvers/user.js @@ -44,6 +44,15 @@ export default { return true }, + setWalkthrough: async (parent, { upvotePopover, tipPopover }, { me, models }) => { + if (!me) { + throw new AuthenticationError('you must be logged in') + } + + await models.user.update({ where: { id: me.id }, data: { upvotePopover, tipPopover } }) + + return true + }, setTheme: async (parent, { theme }, { me, models }) => { if (!me) { throw new AuthenticationError('you must be logged in') diff --git a/api/typeDefs/user.js b/api/typeDefs/user.js index f511dff1..ccb5f776 100644 --- a/api/typeDefs/user.js +++ b/api/typeDefs/user.js @@ -13,6 +13,7 @@ export default gql` setSettings(tipDefault: Int!): Boolean setTheme(theme: String!): Boolean upsertBio(bio: String!): User! + setWalkthrough(tipPopover: Boolean, upvotePopover: Boolean): Boolean } type User { @@ -31,5 +32,7 @@ export default gql` sats: Int! msats: Int! theme: String! + upvotePopover: Boolean! + tipPopover: Boolean! } ` diff --git a/components/upvote.js b/components/upvote.js index df4c5702..88a075b4 100644 --- a/components/upvote.js +++ b/components/upvote.js @@ -8,16 +8,104 @@ import ActionTooltip from './action-tooltip' import { useItemAct } from './item-act' import Window from '../svgs/window-2-fill.svg' import { useMe } from './me' -import { useState } from 'react' +import { useRef, useState } from 'react' import LongPressable from 'react-longpressable' import Rainbow from '../lib/rainbow' -import { OverlayTrigger, Popover } from 'react-bootstrap' +import { Overlay, Popover } from 'react-bootstrap' + +const getColor = (meSats) => { + if (!meSats || meSats <= 10) { + return 'var(--secondary)' + } + + const idx = Math.min( + Math.floor((Math.log(meSats) / Math.log(100000)) * (Rainbow.length - 1)), + Rainbow.length - 1) + return Rainbow[idx] +} + +const UpvotePopover = ({ target, show, handleClose }) => ( + + + Tipping + ×Close alert + + + Press bolt again to tip 1 sat + + + +) + +const TipPopover = ({ target, show, handleClose }) => ( + + + Press and hold + ×Close alert + + + Press and hold bolt to tip a custom amount + + + +) export default function UpVote ({ item, className }) { const { setError } = useFundError() const { setItem } = useItemAct() const [voteLock, setVoteLock] = useState() + const [voteShow, _setVoteShow] = useState(false) + const [tipShow, _setTipShow] = useState(false) + const ref = useRef() const me = useMe() + const [setWalkthrough] = useMutation( + gql` + mutation setWalkthrough($upvotePopover: Boolean, $tipPopover: Boolean) { + setWalkthrough(upvotePopover: $upvotePopover, tipPopover: $tipPopover) + }` + ) + + // TODO: 1. create functions that updates user to say that they've performed the + // actions so they don't get reprompted, 2. check that the user hasn't been prompted + // before prompting ... we can probably just create one toggle function for each + // that does these checks + + const setVoteShow = (yes) => { + if (!me) return + + if (yes && !me.upvotePopover) { + _setVoteShow(yes) + } + + if (voteShow && !yes) { + _setVoteShow(yes) + setWalkthrough({ variables: { upvotePopover: true } }) + } + } + + const setTipShow = (yes) => { + if (!me) return + + // if we want to show it, yet we still haven't shown + if (yes && !me.tipPopover) { + _setTipShow(yes) + } + + // if it's currently showing and we want to hide it + if (tipShow && !yes) { + _setTipShow(yes) + setWalkthrough({ variables: { tipPopover: true } }) + } + } + const [act] = useMutation( gql` mutation act($id: ID!, $act: ItemAct! $sats: Int!, $tipDefault: Boolean) { @@ -29,6 +117,13 @@ export default function UpVote ({ item, className }) { update (cache, { data: { act: { act, sats } } }) { // read in the cached object so we don't use meSats prop // which can be stale + if (act === 'VOTE') { + setVoteShow(true) + } + if (act === 'TIP') { + setTipShow(true) + } + cache.modify({ id: `Item:${item.id}`, fields: { @@ -85,26 +180,6 @@ export default function UpVote ({ item, className }) { return '1 sat' } - const getColor = (meSats) => { - if (!meSats || meSats <= 10) { - return 'var(--secondary)' - } - - const idx = Math.min( - Math.floor((Math.log(meSats) / Math.log(100000)) * (Rainbow.length - 1)), - Rainbow.length - 1) - return Rainbow[idx] - } - - const popover = ( - - Tipping - - Press bolt again to tip - - - ) - const noSelfTips = item?.meVote && item?.mine // 12 px default height const cover = (item?.meSats < 10 ? ((10 - item.meSats) / 10.0) : 0) * 12 @@ -112,8 +187,9 @@ export default function UpVote ({ item, className }) { return ( {({ strike }) => - + { e.preventDefault() e.stopPropagation() @@ -124,10 +200,11 @@ export default function UpVote ({ item, className }) { return } + setTipShow(false) setItem({ itemId: item.id, act, strike }) } } - onShortPress={ + onShortPress={ me ? async (e) => { e.preventDefault() @@ -140,6 +217,7 @@ export default function UpVote ({ item, className }) { } if (item?.meVote) { + setVoteShow(false) if (me?.tipDefault) { try { strike() @@ -170,21 +248,21 @@ export default function UpVote ({ item, className }) { } : signIn } - > - - - + > + + - - - - - } + { + e.stopPropagation() + }} style={{ top: item?.parentId ? '9px' : '4px', height: `${cover}px` }} + /> + + + + setTipShow(false)} /> + setVoteShow(false)} /> + } ) } diff --git a/fragments/users.js b/fragments/users.js index efbe5b8d..23a7956c 100644 --- a/fragments/users.js +++ b/fragments/users.js @@ -18,6 +18,8 @@ export const ME = gql` } hasInvites theme + upvotePopover + tipPopover } }` diff --git a/prisma/migrations/20211206213650_popovers/migration.sql b/prisma/migrations/20211206213650_popovers/migration.sql new file mode 100644 index 00000000..640dd9b2 --- /dev/null +++ b/prisma/migrations/20211206213650_popovers/migration.sql @@ -0,0 +1,3 @@ +-- AlterTable +ALTER TABLE "users" ADD COLUMN "tipPopover" BOOLEAN NOT NULL DEFAULT false, +ADD COLUMN "upvotePopover" BOOLEAN NOT NULL DEFAULT false; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 88d54488..1edbcdb5 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -37,6 +37,9 @@ model User { pubkey String? @unique theme String @default("light") + upvotePopover Boolean @default(false) + tipPopover Boolean @default(false) + @@index([createdAt]) @@map(name: "users") } diff --git a/styles/globals.scss b/styles/globals.scss index a40cf844..c25efbb7 100644 --- a/styles/globals.scss +++ b/styles/globals.scss @@ -230,6 +230,10 @@ textarea.form-control { font-family: 'lightning'; } +.popover-header.alert-dismissible .close { + padding: .5rem !important; +} + .alert-dismissible .close::after { content: 'X'; }