From 01d5177006a6d47fa4b5ef689c944e1b6ebb633a Mon Sep 17 00:00:00 2001 From: ekzyis Date: Mon, 2 Dec 2024 15:18:35 +0100 Subject: [PATCH] Fix edit timer stuck at 00:00 (#1673) * Fix edit timer stuck at 00:00 * refactor with useCanEdit hook --- components/item-info.js | 20 ++++---------------- components/use-can-edit.js | 26 ++++++++++++++++++++++++++ pages/items/[id]/edit.js | 3 ++- 3 files changed, 32 insertions(+), 17 deletions(-) create mode 100644 components/use-can-edit.js diff --git a/components/item-info.js b/components/item-info.js index 515993f8..b0dbafaf 100644 --- a/components/item-info.js +++ b/components/item-info.js @@ -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 { datePivot, timeSince } from '@/lib/time' +import { timeSince } from '@/lib/time' import { DeleteDropdownItem } from './delete' import styles from './item.module.css' import { useMe } from './me' @@ -28,6 +28,7 @@ import { useToast } from './toast' import { useShowModal } from './modal' import classNames from 'classnames' import SubPopover from './sub-popover' +import useCanEdit from './use-can-edit' export default function ItemInfo ({ item, full, commentsText = 'comments', @@ -35,12 +36,12 @@ export default function ItemInfo ({ onQuoteReply, extraBadges, nested, pinnable, showActionDropdown = true, showUser = true, setDisableRetry, disableRetry }) { - const editThreshold = datePivot(new Date(item.invoice?.confirmedAt ?? item.createdAt), { minutes: 10 }) const { me } = useMe() const router = useRouter() const [hasNewComments, setHasNewComments] = useState(false) const root = useRoot() const sub = item?.sub || root?.sub + const [canEdit, setCanEdit, editThreshold] = useCanEdit(item) useEffect(() => { if (!full) { @@ -48,19 +49,6 @@ 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 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 // and OPs can pin any root reply in their post const isPost = !item.parentId @@ -160,7 +148,7 @@ export default function ItemInfo ({ <> diff --git a/components/use-can-edit.js b/components/use-can-edit.js new file mode 100644 index 00000000..bc31f17a --- /dev/null +++ b/components/use-can-edit.js @@ -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] +} diff --git a/pages/items/[id]/edit.js b/pages/items/[id]/edit.js index 67572ca5..707da6fd 100644 --- a/pages/items/[id]/edit.js +++ b/pages/items/[id]/edit.js @@ -12,6 +12,7 @@ import { useRouter } from 'next/router' import PageLoading from '@/components/page-loading' import { FeeButtonProvider } from '@/components/fee-button' import SubSelect from '@/components/sub-select' +import useCanEdit from '@/components/use-can-edit' export const getServerSideProps = getGetServerSideProps({ query: ITEM, @@ -26,7 +27,7 @@ export default function PostEdit ({ ssrData }) { const { item } = data || ssrData 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 itemType = 'DISCUSSION'