Fix edit countdown on deleted items (#1571)

* Clarify conditions to show edit countdown

* Fix edit countdown shown for deleted items

* refactor: Minimize canEdit state

I noticed that only anonEdit requires state because it needs to use useEffect to fetch from local storage.

The other conditions can simply be checked during render.

* refactor: Use datePivot for edit countdown
This commit is contained in:
ekzyis 2024-11-11 16:23:08 +01:00 committed by GitHub
parent 406ae81693
commit fdd34b2eb3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 14 additions and 9 deletions

View File

@ -1375,7 +1375,7 @@ export const updateItem = async (parent, { sub: subName, forward, hash, hmac, ..
// prevent update if it's not explicitly allowed, not their bio, not their job and older than 10 minutes
const myBio = user.bioId === old.id
const timer = Date.now() < new Date(old.invoicePaidAt ?? old.createdAt).getTime() + 10 * 60_000
const timer = Date.now() < datePivot(new Date(old.invoicePaidAt ?? old.createdAt), { minutes: 10 })
// timer permission check
if (!adminEdit && !myBio && !timer && !isJob(item)) {

View File

@ -6,7 +6,7 @@ import Dropdown from 'react-bootstrap/Dropdown'
import Countdown from './countdown'
import { abbrNum, numWithUnits } from '@/lib/format'
import { newComments, commentsViewedAt } from '@/lib/new-comments'
import { timeSince } from '@/lib/time'
import { datePivot, timeSince } from '@/lib/time'
import { DeleteDropdownItem } from './delete'
import styles from './item.module.css'
import { useMe } from './me'
@ -34,10 +34,9 @@ export default function ItemInfo ({
onQuoteReply, extraBadges, nested, pinnable, showActionDropdown = true, showUser = true,
setDisableRetry, disableRetry
}) {
const editThreshold = new Date(item.invoice?.confirmedAt ?? item.createdAt).getTime() + 10 * 60000
const editThreshold = datePivot(new Date(item.invoice?.confirmedAt ?? item.createdAt), { minutes: 10 })
const { me } = useMe()
const router = useRouter()
const [canEdit, setCanEdit] = useState(item.mine && !item.bio && (Date.now() < editThreshold))
const [hasNewComments, setHasNewComments] = useState(false)
const root = useRoot()
const sub = item?.sub || root?.sub
@ -48,12 +47,18 @@ export default function ItemInfo ({
}
}, [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 authorEdit = item.mine && !item.bio
const invParams = window.localStorage.getItem(`item:${item.id}:hash:hmac`)
const hmacEdit = !!invParams && !me && Number(item.user.id) === USER_ID.anon
setCanEdit((authorEdit || hmacEdit) && (Date.now() < editThreshold))
}, [me, item.id, item.mine, editThreshold])
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
// and OPs can pin any root reply in their post
@ -152,7 +157,7 @@ export default function ItemInfo ({
<>
<EditInfo
item={item} edit={edit} canEdit={canEdit}
setCanEdit={setCanEdit} toggleEdit={toggleEdit} editText={editText} editThreshold={editThreshold}
setCanEdit={setAnonEdit} toggleEdit={toggleEdit} editText={editText} editThreshold={editThreshold}
/>
<PaymentInfo item={item} disableRetry={disableRetry} setDisableRetry={setDisableRetry} />
<ActionDropdown>