* Fix first zap when modal closed (#771) - Extract handlers - Remove unnecessary async keyword from callback - Assign a new key to force remounting of LongPressable component when modal is closed from long press - Remove hover state when closing modal, otherwise it stays colored * Replace LongPressable with custom component * Remove yarn.lock
This commit is contained in:
parent
b477f23aac
commit
a28d690f28
|
@ -0,0 +1,114 @@
|
|||
import React from 'react'
|
||||
import PropType from 'prop-types'
|
||||
|
||||
function eventToPosition (event) {
|
||||
return {
|
||||
x: event.clientX,
|
||||
y: event.clientY
|
||||
}
|
||||
}
|
||||
|
||||
function distance (pointA, pointB) {
|
||||
return Math.sqrt(
|
||||
Math.pow(pointB.x - pointA.x, 2) + Math.pow(pointB.y - pointA.y, 2)
|
||||
)
|
||||
}
|
||||
|
||||
export default class LongPressable extends React.PureComponent {
|
||||
static propTypes = {
|
||||
onLongPress: PropType.func.isRequired,
|
||||
onShortPress: PropType.func,
|
||||
longPressTime: PropType.number,
|
||||
primaryMouseButtonOnly: PropType.bool,
|
||||
// Maximum distance (pixels) user is allowed to drag before
|
||||
// click is canceled
|
||||
dragThreshold: PropType.number,
|
||||
children: PropType.node
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
longPressTime: 500,
|
||||
primaryMouseButtonOnly: true,
|
||||
dragThreshold: 100
|
||||
}
|
||||
|
||||
isLongPressing = false
|
||||
startingPosition = { x: 0, y: 0 }
|
||||
|
||||
componentWillUnmount () {
|
||||
this.clearTimeout()
|
||||
}
|
||||
|
||||
clearTimeout = () => {
|
||||
if (this.timerID) {
|
||||
clearTimeout(this.timerID)
|
||||
this.timerID = null
|
||||
}
|
||||
}
|
||||
|
||||
handlePointerUp = (e) => {
|
||||
if (this.timerID) {
|
||||
this.cancelLongPress()
|
||||
}
|
||||
|
||||
const mousePosition = eventToPosition(e)
|
||||
|
||||
if (!this.isLongPressing &&
|
||||
!this.exceedDragThreshold(mousePosition)) {
|
||||
this.props.onShortPress(e)
|
||||
} else {
|
||||
this.isLongPressing = false
|
||||
}
|
||||
}
|
||||
|
||||
handlePointerDown = (e) => {
|
||||
if (this.props.primaryMouseButtonOnly) {
|
||||
if (e.pointerType === 'mouse' && e.button !== 0) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// re-initialize long press
|
||||
this.isLongPressing = false
|
||||
this.startingPosition = eventToPosition(e)
|
||||
|
||||
this.timerID = setTimeout(() => {
|
||||
this.isLongPressing = true
|
||||
this.props.onLongPress(e)
|
||||
}, this.props.longPressTime)
|
||||
}
|
||||
|
||||
handlePointerMove = (e) => {
|
||||
const mousePosition = eventToPosition(e)
|
||||
if (this.timerID && this.exceedDragThreshold(mousePosition)) {
|
||||
this.cancelLongPress()
|
||||
}
|
||||
}
|
||||
|
||||
handlePointerLeave = () => {
|
||||
if (this.timerID) {
|
||||
this.cancelLongPress()
|
||||
}
|
||||
}
|
||||
|
||||
cancelLongPress () {
|
||||
this.clearTimeout()
|
||||
}
|
||||
|
||||
exceedDragThreshold (point) {
|
||||
return distance(this.startingPosition, point) > this.props.dragThreshold
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<div
|
||||
onPointerUp={this.handlePointerUp}
|
||||
onPointerDown={this.handlePointerDown}
|
||||
onPointerMove={this.handlePointerMove}
|
||||
onPointerLeave={this.handlePointerLeave}
|
||||
>
|
||||
{this.props.children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@ import ItemAct, { useAct, useZap } from './item-act'
|
|||
import { useMe } from './me'
|
||||
import getColor from '@/lib/rainbow'
|
||||
import { useCallback, useMemo, useRef, useState } from 'react'
|
||||
import LongPressable from 'react-longpressable'
|
||||
import LongPressable from './long-pressable'
|
||||
import Overlay from 'react-bootstrap/Overlay'
|
||||
import Popover from 'react-bootstrap/Popover'
|
||||
import { useShowModal } from './modal'
|
||||
|
@ -142,43 +142,48 @@ export default function UpVote ({ item, className }) {
|
|||
getColor(meSats), getColor(meSats + sats)]
|
||||
}, [item?.meSats, item?.meAnonSats, me?.privates?.tipDefault, me?.privates?.turboDefault])
|
||||
|
||||
const handleModalClosed = () => {
|
||||
setHover(false)
|
||||
}
|
||||
|
||||
const handleLongPress = (e) => {
|
||||
if (!item) return
|
||||
|
||||
// we can't tip ourselves
|
||||
if (disabled) {
|
||||
return
|
||||
}
|
||||
|
||||
setTipShow(false)
|
||||
showModal(onClose =>
|
||||
<ItemAct onClose={onClose} itemId={item.id} />, { onClose: handleModalClosed })
|
||||
}
|
||||
|
||||
const handleShortPress = () => {
|
||||
if (me) {
|
||||
if (!item) return
|
||||
|
||||
// we can't tip ourselves
|
||||
if (disabled) {
|
||||
return
|
||||
}
|
||||
|
||||
if (meSats) {
|
||||
setVoteShow(false)
|
||||
} else {
|
||||
setTipShow(true)
|
||||
}
|
||||
|
||||
zap({ item, me })
|
||||
} else {
|
||||
showModal(onClose => <ItemAct onClose={onClose} itemId={item.id} act={act} />, { onClose: handleModalClosed })
|
||||
}
|
||||
}
|
||||
return (
|
||||
<div ref={ref} className='upvoteParent'>
|
||||
<LongPressable
|
||||
onLongPress={
|
||||
async (e) => {
|
||||
if (!item) return
|
||||
|
||||
// we can't tip ourselves
|
||||
if (disabled) {
|
||||
return
|
||||
}
|
||||
|
||||
setTipShow(false)
|
||||
showModal(onClose =>
|
||||
<ItemAct onClose={onClose} itemId={item.id} />)
|
||||
}
|
||||
}
|
||||
onShortPress={
|
||||
me
|
||||
? async (e) => {
|
||||
if (!item) return
|
||||
|
||||
// we can't tip ourselves
|
||||
if (disabled) {
|
||||
return
|
||||
}
|
||||
|
||||
if (meSats) {
|
||||
setVoteShow(false)
|
||||
} else {
|
||||
setTipShow(true)
|
||||
}
|
||||
|
||||
zap({ item, me })
|
||||
}
|
||||
: () => showModal(onClose => <ItemAct onClose={onClose} itemId={item.id} act={act} />)
|
||||
}
|
||||
onLongPress={handleLongPress}
|
||||
onShortPress={handleShortPress}
|
||||
>
|
||||
<ActionTooltip notForm disable={disabled} overlayText={overlayText}>
|
||||
<div
|
||||
|
|
|
@ -69,7 +69,6 @@
|
|||
"react-datepicker": "^4.20.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-ios-pwa-prompt": "^1.8.4",
|
||||
"react-longpressable": "^1.1.1",
|
||||
"react-markdown": "^9.0.1",
|
||||
"react-string-replace": "^1.1.1",
|
||||
"react-syntax-highlighter": "^15.5.0",
|
||||
|
@ -16164,15 +16163,6 @@
|
|||
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
||||
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
||||
},
|
||||
"node_modules/react-longpressable": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/react-longpressable/-/react-longpressable-1.1.1.tgz",
|
||||
"integrity": "sha512-Q8S7CzZVNmP123tHrMp0U0+/fgDEZCi5CpOGkabz3a2zQ0aek5IAizetxtxBAt1hQHHaAYynPHhtcSkLIkqEzQ==",
|
||||
"peerDependencies": {
|
||||
"prop-types": "^15.6.1",
|
||||
"react": "^16.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-markdown": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-9.0.1.tgz",
|
||||
|
|
|
@ -74,7 +74,6 @@
|
|||
"react-datepicker": "^4.20.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-ios-pwa-prompt": "^1.8.4",
|
||||
"react-longpressable": "^1.1.1",
|
||||
"react-markdown": "^9.0.1",
|
||||
"react-string-replace": "^1.1.1",
|
||||
"react-syntax-highlighter": "^15.5.0",
|
||||
|
@ -121,4 +120,4 @@
|
|||
"jest": "^29.7.0",
|
||||
"standard": "^17.1.0"
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue