tip walkthrough
This commit is contained in:
parent
ed0d4f2235
commit
4d3ab603da
@ -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')
|
||||
|
@ -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!
|
||||
}
|
||||
`
|
||||
|
@ -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,8 +187,9 @@ export default function UpVote ({ item, className }) {
|
||||
return (
|
||||
<LightningConsumer>
|
||||
{({ strike }) =>
|
||||
<LongPressable
|
||||
onLongPress={
|
||||
<div ref={ref}>
|
||||
<LongPressable
|
||||
onLongPress={
|
||||
async (e) => {
|
||||
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
|
||||
}
|
||||
>
|
||||
<ActionTooltip notForm disable={noSelfTips} overlayText={overlayText()}>
|
||||
<div className={`${noSelfTips ? styles.noSelfTips : ''}
|
||||
${styles.upvoteWrapper}`}
|
||||
>
|
||||
<OverlayTrigger placement='right' overlay={popover} show>
|
||||
>
|
||||
<ActionTooltip notForm disable={noSelfTips} overlayText={overlayText()}>
|
||||
<div
|
||||
className={`${noSelfTips ? styles.noSelfTips : ''}
|
||||
${styles.upvoteWrapper}`}
|
||||
>
|
||||
<UpBolt
|
||||
width={24}
|
||||
height={24}
|
||||
className={
|
||||
`${styles.upvote}
|
||||
${className || ''}
|
||||
${noSelfTips ? styles.noSelfTips : ''}
|
||||
${item?.meVote ? styles.voted : ''}`
|
||||
}
|
||||
`${styles.upvote}
|
||||
${className || ''}
|
||||
${noSelfTips ? styles.noSelfTips : ''}
|
||||
${item?.meVote ? styles.voted : ''}`
|
||||
}
|
||||
style={item?.meVote
|
||||
? {
|
||||
fill: color,
|
||||
@ -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>
|
||||
</ActionTooltip>
|
||||
</LongPressable>}
|
||||
<div
|
||||
className={styles.cover} onClick={e => {
|
||||
e.stopPropagation()
|
||||
}} style={{ top: item?.parentId ? '9px' : '4px', height: `${cover}px` }}
|
||||
/>
|
||||
</div>
|
||||
</ActionTooltip>
|
||||
</LongPressable>
|
||||
<TipPopover target={ref.current} show={tipShow} handleClose={() => setTipShow(false)} />
|
||||
<UpvotePopover target={ref.current} show={voteShow} handleClose={() => setVoteShow(false)} />
|
||||
</div>}
|
||||
</LightningConsumer>
|
||||
)
|
||||
}
|
||||
|
@ -18,6 +18,8 @@ export const ME = gql`
|
||||
}
|
||||
hasInvites
|
||||
theme
|
||||
upvotePopover
|
||||
tipPopover
|
||||
}
|
||||
}`
|
||||
|
||||
|
3
prisma/migrations/20211206213650_popovers/migration.sql
Normal file
3
prisma/migrations/20211206213650_popovers/migration.sql
Normal 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;
|
@ -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")
|
||||
}
|
||||
|
@ -230,6 +230,10 @@ textarea.form-control {
|
||||
font-family: 'lightning';
|
||||
}
|
||||
|
||||
.popover-header.alert-dismissible .close {
|
||||
padding: .5rem !important;
|
||||
}
|
||||
|
||||
.alert-dismissible .close::after {
|
||||
content: 'X';
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user