tip walkthrough
This commit is contained in:
		
							parent
							
								
									ed0d4f2235
								
							
						
					
					
						commit
						4d3ab603da
					
				| @ -44,6 +44,15 @@ export default { | |||||||
| 
 | 
 | ||||||
|       return true |       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 }) => { |     setTheme: async (parent, { theme }, { me, models }) => { | ||||||
|       if (!me) { |       if (!me) { | ||||||
|         throw new AuthenticationError('you must be logged in') |         throw new AuthenticationError('you must be logged in') | ||||||
|  | |||||||
| @ -13,6 +13,7 @@ export default gql` | |||||||
|     setSettings(tipDefault: Int!): Boolean |     setSettings(tipDefault: Int!): Boolean | ||||||
|     setTheme(theme: String!): Boolean |     setTheme(theme: String!): Boolean | ||||||
|     upsertBio(bio: String!): User! |     upsertBio(bio: String!): User! | ||||||
|  |     setWalkthrough(tipPopover: Boolean, upvotePopover: Boolean): Boolean | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   type User { |   type User { | ||||||
| @ -31,5 +32,7 @@ export default gql` | |||||||
|     sats: Int! |     sats: Int! | ||||||
|     msats: Int! |     msats: Int! | ||||||
|     theme: String! |     theme: String! | ||||||
|  |     upvotePopover: Boolean! | ||||||
|  |     tipPopover: Boolean! | ||||||
|   } |   } | ||||||
| ` | ` | ||||||
|  | |||||||
| @ -8,16 +8,104 @@ import ActionTooltip from './action-tooltip' | |||||||
| import { useItemAct } from './item-act' | import { useItemAct } from './item-act' | ||||||
| import Window from '../svgs/window-2-fill.svg' | import Window from '../svgs/window-2-fill.svg' | ||||||
| import { useMe } from './me' | import { useMe } from './me' | ||||||
| import { useState } from 'react' | import { useRef, useState } from 'react' | ||||||
| import LongPressable from 'react-longpressable' | import LongPressable from 'react-longpressable' | ||||||
| import Rainbow from '../lib/rainbow' | 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 }) { | export default function UpVote ({ item, className }) { | ||||||
|   const { setError } = useFundError() |   const { setError } = useFundError() | ||||||
|   const { setItem } = useItemAct() |   const { setItem } = useItemAct() | ||||||
|   const [voteLock, setVoteLock] = useState() |   const [voteLock, setVoteLock] = useState() | ||||||
|  |   const [voteShow, _setVoteShow] = useState(false) | ||||||
|  |   const [tipShow, _setTipShow] = useState(false) | ||||||
|  |   const ref = useRef() | ||||||
|   const me = useMe() |   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( |   const [act] = useMutation( | ||||||
|     gql` |     gql` | ||||||
|       mutation act($id: ID!, $act: ItemAct! $sats: Int!, $tipDefault: Boolean) { |       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 } } }) { |       update (cache, { data: { act: { act, sats } } }) { | ||||||
|         // read in the cached object so we don't use meSats prop
 |         // read in the cached object so we don't use meSats prop
 | ||||||
|         // which can be stale
 |         // which can be stale
 | ||||||
|  |         if (act === 'VOTE') { | ||||||
|  |           setVoteShow(true) | ||||||
|  |         } | ||||||
|  |         if (act === 'TIP') { | ||||||
|  |           setTipShow(true) | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         cache.modify({ |         cache.modify({ | ||||||
|           id: `Item:${item.id}`, |           id: `Item:${item.id}`, | ||||||
|           fields: { |           fields: { | ||||||
| @ -85,26 +180,6 @@ export default function UpVote ({ item, className }) { | |||||||
|     return '1 sat' |     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 |   const noSelfTips = item?.meVote && item?.mine | ||||||
|   // 12 px default height
 |   // 12 px default height
 | ||||||
|   const cover = (item?.meSats < 10 ? ((10 - item.meSats) / 10.0) : 0) * 12 |   const cover = (item?.meSats < 10 ? ((10 - item.meSats) / 10.0) : 0) * 12 | ||||||
| @ -112,8 +187,9 @@ export default function UpVote ({ item, className }) { | |||||||
|   return ( |   return ( | ||||||
|     <LightningConsumer> |     <LightningConsumer> | ||||||
|       {({ strike }) => |       {({ strike }) => | ||||||
|         <LongPressable |         <div ref={ref}> | ||||||
|           onLongPress={ |           <LongPressable | ||||||
|  |             onLongPress={ | ||||||
|               async (e) => { |               async (e) => { | ||||||
|                 e.preventDefault() |                 e.preventDefault() | ||||||
|                 e.stopPropagation() |                 e.stopPropagation() | ||||||
| @ -124,10 +200,11 @@ export default function UpVote ({ item, className }) { | |||||||
|                   return |                   return | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|  |                 setTipShow(false) | ||||||
|                 setItem({ itemId: item.id, act, strike }) |                 setItem({ itemId: item.id, act, strike }) | ||||||
|               } |               } | ||||||
|             } |             } | ||||||
|           onShortPress={ |             onShortPress={ | ||||||
|             me |             me | ||||||
|               ? async (e) => { |               ? async (e) => { | ||||||
|                   e.preventDefault() |                   e.preventDefault() | ||||||
| @ -140,6 +217,7 @@ export default function UpVote ({ item, className }) { | |||||||
|                   } |                   } | ||||||
| 
 | 
 | ||||||
|                   if (item?.meVote) { |                   if (item?.meVote) { | ||||||
|  |                     setVoteShow(false) | ||||||
|                     if (me?.tipDefault) { |                     if (me?.tipDefault) { | ||||||
|                       try { |                       try { | ||||||
|                         strike() |                         strike() | ||||||
| @ -170,21 +248,21 @@ export default function UpVote ({ item, className }) { | |||||||
|                 } |                 } | ||||||
|               : signIn |               : signIn | ||||||
|           } |           } | ||||||
|         > |           > | ||||||
|           <ActionTooltip notForm disable={noSelfTips} overlayText={overlayText()}> |             <ActionTooltip notForm disable={noSelfTips} overlayText={overlayText()}> | ||||||
|             <div className={`${noSelfTips ? styles.noSelfTips : ''} |               <div | ||||||
|               ${styles.upvoteWrapper}`}
 |                 className={`${noSelfTips ? styles.noSelfTips : ''} | ||||||
|             > |                     ${styles.upvoteWrapper}`}
 | ||||||
|               <OverlayTrigger placement='right' overlay={popover} show> |               > | ||||||
|                 <UpBolt |                 <UpBolt | ||||||
|                   width={24} |                   width={24} | ||||||
|                   height={24} |                   height={24} | ||||||
|                   className={ |                   className={ | ||||||
|                 `${styles.upvote} |                       `${styles.upvote} | ||||||
|                 ${className || ''} |                       ${className || ''} | ||||||
|                 ${noSelfTips ? styles.noSelfTips : ''} |                       ${noSelfTips ? styles.noSelfTips : ''} | ||||||
|                 ${item?.meVote ? styles.voted : ''}` |                       ${item?.meVote ? styles.voted : ''}` | ||||||
|               } |                     } | ||||||
|                   style={item?.meVote |                   style={item?.meVote | ||||||
|                     ? { |                     ? { | ||||||
|                         fill: color, |                         fill: color, | ||||||
| @ -195,11 +273,17 @@ export default function UpVote ({ item, className }) { | |||||||
|                     e.stopPropagation() |                     e.stopPropagation() | ||||||
|                   }} |                   }} | ||||||
|                 /> |                 /> | ||||||
|               </OverlayTrigger> |                 <div | ||||||
|               <div className={styles.cover} style={{ top: item?.parentId ? '9px' : '4px', height: `${cover}px` }} /> |                   className={styles.cover} onClick={e => { | ||||||
|             </div> |                     e.stopPropagation() | ||||||
|           </ActionTooltip> |                   }} style={{ top: item?.parentId ? '9px' : '4px', height: `${cover}px` }} | ||||||
|         </LongPressable>} |                 /> | ||||||
|  |               </div> | ||||||
|  |             </ActionTooltip> | ||||||
|  |           </LongPressable> | ||||||
|  |           <TipPopover target={ref.current} show={tipShow} handleClose={() => setTipShow(false)} /> | ||||||
|  |           <UpvotePopover target={ref.current} show={voteShow} handleClose={() => setVoteShow(false)} /> | ||||||
|  |         </div>} | ||||||
|     </LightningConsumer> |     </LightningConsumer> | ||||||
|   ) |   ) | ||||||
| } | } | ||||||
|  | |||||||
| @ -18,6 +18,8 @@ export const ME = gql` | |||||||
|       } |       } | ||||||
|       hasInvites |       hasInvites | ||||||
|       theme |       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 |   pubkey         String?     @unique | ||||||
|   theme          String      @default("light") |   theme          String      @default("light") | ||||||
| 
 | 
 | ||||||
|  |   upvotePopover Boolean @default(false) | ||||||
|  |   tipPopover    Boolean @default(false) | ||||||
|  | 
 | ||||||
|   @@index([createdAt]) |   @@index([createdAt]) | ||||||
|   @@map(name: "users") |   @@map(name: "users") | ||||||
| } | } | ||||||
|  | |||||||
| @ -230,6 +230,10 @@ textarea.form-control { | |||||||
|   font-family: 'lightning'; |   font-family: 'lightning'; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | .popover-header.alert-dismissible .close { | ||||||
|  |   padding: .5rem !important; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| .alert-dismissible .close::after { | .alert-dismissible .close::after { | ||||||
|   content: 'X'; |   content: 'X'; | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user