Fix edit timer stuck at 00:00 (#1673)

* Fix edit timer stuck at 00:00

* refactor with useCanEdit hook
This commit is contained in:
ekzyis 2024-12-02 15:18:35 +01:00 committed by GitHub
parent 8595a2b8b0
commit 01d5177006
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 32 additions and 17 deletions

View File

@ -6,7 +6,7 @@ import Dropdown from 'react-bootstrap/Dropdown'
import Countdown from './countdown' import Countdown from './countdown'
import { abbrNum, numWithUnits } from '@/lib/format' import { abbrNum, numWithUnits } from '@/lib/format'
import { newComments, commentsViewedAt } from '@/lib/new-comments' import { newComments, commentsViewedAt } from '@/lib/new-comments'
import { datePivot, timeSince } from '@/lib/time' import { timeSince } from '@/lib/time'
import { DeleteDropdownItem } from './delete' import { DeleteDropdownItem } from './delete'
import styles from './item.module.css' import styles from './item.module.css'
import { useMe } from './me' import { useMe } from './me'
@ -28,6 +28,7 @@ import { useToast } from './toast'
import { useShowModal } from './modal' import { useShowModal } from './modal'
import classNames from 'classnames' import classNames from 'classnames'
import SubPopover from './sub-popover' import SubPopover from './sub-popover'
import useCanEdit from './use-can-edit'
export default function ItemInfo ({ export default function ItemInfo ({
item, full, commentsText = 'comments', item, full, commentsText = 'comments',
@ -35,12 +36,12 @@ export default function ItemInfo ({
onQuoteReply, extraBadges, nested, pinnable, showActionDropdown = true, showUser = true, onQuoteReply, extraBadges, nested, pinnable, showActionDropdown = true, showUser = true,
setDisableRetry, disableRetry setDisableRetry, disableRetry
}) { }) {
const editThreshold = datePivot(new Date(item.invoice?.confirmedAt ?? item.createdAt), { minutes: 10 })
const { me } = useMe() const { me } = useMe()
const router = useRouter() const router = useRouter()
const [hasNewComments, setHasNewComments] = useState(false) const [hasNewComments, setHasNewComments] = useState(false)
const root = useRoot() const root = useRoot()
const sub = item?.sub || root?.sub const sub = item?.sub || root?.sub
const [canEdit, setCanEdit, editThreshold] = useCanEdit(item)
useEffect(() => { useEffect(() => {
if (!full) { if (!full) {
@ -48,19 +49,6 @@ export default function ItemInfo ({
} }
}, [item]) }, [item])
// allow anon edits if they have the correct hmac for the item invoice
// (the server will verify the hmac)
const [anonEdit, setAnonEdit] = useState(false)
useEffect(() => {
const invParams = window.localStorage.getItem(`item:${item.id}:hash:hmac`)
setAnonEdit(!!invParams && !me && Number(item.user.id) === USER_ID.anon)
}, [])
// deleted items can never be edited and every item has a 10 minute edit window
// except bios, they can always be edited but they should never show the countdown
const noEdit = !!item.deletedAt || (Date.now() >= editThreshold) || item.bio
const canEdit = !noEdit && ((me && item.mine) || anonEdit)
// territory founders can pin any post in their territory // territory founders can pin any post in their territory
// and OPs can pin any root reply in their post // and OPs can pin any root reply in their post
const isPost = !item.parentId const isPost = !item.parentId
@ -160,7 +148,7 @@ export default function ItemInfo ({
<> <>
<EditInfo <EditInfo
item={item} edit={edit} canEdit={canEdit} item={item} edit={edit} canEdit={canEdit}
setCanEdit={setAnonEdit} toggleEdit={toggleEdit} editText={editText} editThreshold={editThreshold} setCanEdit={setCanEdit} toggleEdit={toggleEdit} editText={editText} editThreshold={editThreshold}
/> />
<PaymentInfo item={item} disableRetry={disableRetry} setDisableRetry={setDisableRetry} /> <PaymentInfo item={item} disableRetry={disableRetry} setDisableRetry={setDisableRetry} />
<ActionDropdown> <ActionDropdown>

View File

@ -0,0 +1,26 @@
import { useEffect, useState } from 'react'
import { datePivot } from '@/lib/time'
import { useMe } from '@/components/me'
import { USER_ID } from '@/lib/constants'
export default function useCanEdit (item) {
const editThreshold = datePivot(new Date(item.invoice?.confirmedAt ?? item.createdAt), { minutes: 10 })
const { me } = useMe()
// deleted items can never be edited and every item has a 10 minute edit window
// except bios, they can always be edited but they should never show the countdown
const noEdit = !!item.deletedAt || (Date.now() >= editThreshold) || item.bio
const authorEdit = me && item.mine
const [canEdit, setCanEdit] = useState(!noEdit && authorEdit)
useEffect(() => {
// allow anon edits if they have the correct hmac for the item invoice
// (the server will verify the hmac)
const invParams = window.localStorage.getItem(`item:${item.id}:hash:hmac`)
const anonEdit = !!invParams && !me && Number(item.user.id) === USER_ID.anon
// anonEdit should not override canEdit, but only allow edits if they aren't already allowed
setCanEdit(canEdit => canEdit || anonEdit)
}, [])
return [canEdit, setCanEdit, editThreshold]
}

View File

@ -12,6 +12,7 @@ import { useRouter } from 'next/router'
import PageLoading from '@/components/page-loading' import PageLoading from '@/components/page-loading'
import { FeeButtonProvider } from '@/components/fee-button' import { FeeButtonProvider } from '@/components/fee-button'
import SubSelect from '@/components/sub-select' import SubSelect from '@/components/sub-select'
import useCanEdit from '@/components/use-can-edit'
export const getServerSideProps = getGetServerSideProps({ export const getServerSideProps = getGetServerSideProps({
query: ITEM, query: ITEM,
@ -26,7 +27,7 @@ export default function PostEdit ({ ssrData }) {
const { item } = data || ssrData const { item } = data || ssrData
const [sub, setSub] = useState(item.subName) const [sub, setSub] = useState(item.subName)
const editThreshold = new Date(item?.invoice?.confirmedAt ?? item.createdAt).getTime() + 10 * 60000 const [,, editThreshold] = useCanEdit(item)
let FormType = DiscussionForm let FormType = DiscussionForm
let itemType = 'DISCUSSION' let itemType = 'DISCUSSION'