tip walkthrough

This commit is contained in:
keyan 2021-12-09 14:40:40 -06:00
parent ed0d4f2235
commit 4d3ab603da
7 changed files with 149 additions and 41 deletions

View File

@ -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')

View File

@ -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!
}
`

View File

@ -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 }) => (
<Overlay
show={show}
target={target}
placement='right'
>
<Popover id='popover-basic'>
<Popover.Title className='d-flex justify-content-between alert-dismissible' as='h3'>Tipping
<button type='button' className='close' onClick={handleClose}><span aria-hidden='true'>×</span><span className='sr-only'>Close alert</span></button>
</Popover.Title>
<Popover.Content>
Press bolt again to tip 1 sat
</Popover.Content>
</Popover>
</Overlay>
)
const TipPopover = ({ target, show, handleClose }) => (
<Overlay
show={show}
target={target}
placement='right'
>
<Popover id='popover-basic'>
<Popover.Title className='d-flex justify-content-between alert-dismissible' as='h3'>Press and hold
<button type='button' class='close' onClick={handleClose}><span aria-hidden='true'>×</span><span class='sr-only'>Close alert</span></button>
</Popover.Title>
<Popover.Content>
Press and hold bolt to tip a custom amount
</Popover.Content>
</Popover>
</Overlay>
)
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 = (
<Popover id='popover-basic'>
<Popover.Title as='h3'>Tipping</Popover.Title>
<Popover.Content>
Press bolt again to tip
</Popover.Content>
</Popover>
)
const noSelfTips = item?.meVote && item?.mine
// 12 px default height
const cover = (item?.meSats < 10 ? ((10 - item.meSats) / 10.0) : 0) * 12
@ -112,6 +187,7 @@ export default function UpVote ({ item, className }) {
return (
<LightningConsumer>
{({ strike }) =>
<div ref={ref}>
<LongPressable
onLongPress={
async (e) => {
@ -124,6 +200,7 @@ export default function UpVote ({ item, className }) {
return
}
setTipShow(false)
setItem({ itemId: item.id, act, strike })
}
}
@ -140,6 +217,7 @@ export default function UpVote ({ item, className }) {
}
if (item?.meVote) {
setVoteShow(false)
if (me?.tipDefault) {
try {
strike()
@ -172,10 +250,10 @@ export default function UpVote ({ item, className }) {
}
>
<ActionTooltip notForm disable={noSelfTips} overlayText={overlayText()}>
<div className={`${noSelfTips ? styles.noSelfTips : ''}
<div
className={`${noSelfTips ? styles.noSelfTips : ''}
${styles.upvoteWrapper}`}
>
<OverlayTrigger placement='right' overlay={popover} show>
<UpBolt
width={24}
height={24}
@ -195,11 +273,17 @@ export default function UpVote ({ item, className }) {
e.stopPropagation()
}}
/>
</OverlayTrigger>
<div className={styles.cover} style={{ top: item?.parentId ? '9px' : '4px', height: `${cover}px` }} />
<div
className={styles.cover} onClick={e => {
e.stopPropagation()
}} style={{ top: item?.parentId ? '9px' : '4px', height: `${cover}px` }}
/>
</div>
</ActionTooltip>
</LongPressable>}
</LongPressable>
<TipPopover target={ref.current} show={tipShow} handleClose={() => setTipShow(false)} />
<UpvotePopover target={ref.current} show={voteShow} handleClose={() => setVoteShow(false)} />
</div>}
</LightningConsumer>
)
}

View File

@ -18,6 +18,8 @@ export const ME = gql`
}
hasInvites
theme
upvotePopover
tipPopover
}
}`

View File

@ -0,0 +1,3 @@
-- AlterTable
ALTER TABLE "users" ADD COLUMN "tipPopover" BOOLEAN NOT NULL DEFAULT false,
ADD COLUMN "upvotePopover" BOOLEAN NOT NULL DEFAULT false;

View File

@ -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")
}

View File

@ -230,6 +230,10 @@ textarea.form-control {
font-family: 'lightning';
}
.popover-header.alert-dismissible .close {
padding: .5rem !important;
}
.alert-dismissible .close::after {
content: 'X';
}