From 9f7544936e9418ce99f562d6ccdd1a043adf2602 Mon Sep 17 00:00:00 2001 From: "Tom (plebeius.eth)" Date: Sun, 7 Jul 2024 20:02:58 +0200 Subject: [PATCH] feat: use red offline icon for subplebbits that are most likely offline (ipns record fails to update) --- public/assets/icons/offline-red.png | Bin 0 -> 1205 bytes .../board-header/board-header.module.css | 4 ++++ src/components/board-header/board-header.tsx | 17 +++++----------- src/components/post-form/post-form.tsx | 13 ++++-------- src/hooks/use-is-subplebbit-offline.ts | 19 ++++++++++++++++++ src/index.css | 4 ++++ src/views/board/board.tsx | 4 ++-- src/views/home/boards-box/boards-box.tsx | 11 ++++------ src/views/home/home.module.css | 4 ++++ 9 files changed, 46 insertions(+), 30 deletions(-) create mode 100644 public/assets/icons/offline-red.png create mode 100644 src/hooks/use-is-subplebbit-offline.ts diff --git a/public/assets/icons/offline-red.png b/public/assets/icons/offline-red.png new file mode 100644 index 0000000000000000000000000000000000000000..a02271059af19014cbc76b2eb05623f4e86aae7a GIT binary patch literal 1205 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ea{HEjtmSN`?>!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBC{d9b;hE;^%b*2hb1<+l z3NbJPS&Tr)z$nE4G7ZRLuw#^lv)$S=8Cam=en1)oJb)Oa4ni|8U__X*fC;WzU;#6N z4bpb|^nF(##aZAHSl5MQj7C*NCKMoj{B#7z_iZk z>Eak-AvibKny=Y_r&QbT>eQKy*#^c1EKA&aVp=;JyA2Knd%95g-xU*`Ql9T^ zpFg>yMnY@R40(m3Z?j8dwU-J0c3Wb?dRp=QM@iv3YgTz(D;4EzjNbOF^4tvm9eb>SPix)wDoh+O*$yIp(IR*wZSgx=e1^+yX+dm z-ydWgoc_+zkgXtcTE$F-mOCcC`u`lgbOM&Xwz8gDG4;+-H7&UE9F^PxOD%L$>JhWoqs@i<@Wt~$(69BD1b-w@r literal 0 HcmV?d00001 diff --git a/src/components/board-header/board-header.module.css b/src/components/board-header/board-header.module.css index 01845509..cc553a7f 100644 --- a/src/components/board-header/board-header.module.css +++ b/src/components/board-header/board-header.module.css @@ -39,6 +39,10 @@ image-rendering: pixelated; } +.redOfflineIcon { + background-image: url('/public/assets/icons/offline-red.png') !important; +} + @media (max-width: 640px) { .boardTitle { padding-top: 40px; diff --git a/src/components/board-header/board-header.tsx b/src/components/board-header/board-header.tsx index b4eb99ca..e891ac77 100644 --- a/src/components/board-header/board-header.tsx +++ b/src/components/board-header/board-header.tsx @@ -1,12 +1,11 @@ import { useState } from 'react'; import { useLocation, useParams } from 'react-router-dom'; -import { useTranslation } from 'react-i18next'; import { useAccountComment, useSubplebbit } from '@plebbit/plebbit-react-hooks'; -import { getFormattedTimeAgo } from '../../lib/utils/time-utils'; import { isAllView, isSubscriptionsView } from '../../lib/utils/view-utils'; import styles from './board-header.module.css'; import { useMultisubMetadata } from '../../hooks/use-default-subplebbits'; import useIsMobile from '../../hooks/use-is-mobile'; +import useIsSubplebbitOffline from '../../hooks/use-is-subplebbit-offline'; const totalBanners = 60; @@ -20,10 +19,8 @@ const ImageBanner = () => { }; const BoardHeader = () => { - const { t } = useTranslation(); const location = useLocation(); const params = useParams(); - const isInAllView = isAllView(location.pathname, params); const isInSubscriptionsView = isSubscriptionsView(location.pathname, useParams()); @@ -31,18 +28,14 @@ const BoardHeader = () => { const subplebbitAddress = params?.subplebbitAddress || accountComment?.subplebbitAddress; const subplebbit = useSubplebbit({ subplebbitAddress }); - const { address, shortAddress, updatedAt } = subplebbit || {}; + const { address, shortAddress } = subplebbit || {}; const multisubMetadata = useMultisubMetadata(); - const title = isInAllView ? multisubMetadata?.title || 'all' : isInSubscriptionsView ? 'Subscriptions' : subplebbit?.title; const subtitle = isInAllView ? 'p/all' : isInSubscriptionsView ? 'p/subscriptions' : `p/${address}`; - const isBoardOffline = updatedAt && updatedAt < Date.now() / 1000 - 60 * 60; - - const offlineMessage = updatedAt - ? isBoardOffline && t('posts_last_synced_info', { time: getFormattedTimeAgo(updatedAt), interpolation: { escapeValue: false } }) - : t('subplebbit_offline_info'); + const { isOffline, isDefinitelyOffline, offlineTitle } = useIsSubplebbitOffline(subplebbit); + const iconClass = `${styles.offlineIcon} ${isDefinitelyOffline ? styles.redOfflineIcon : ''}`; return (
@@ -53,7 +46,7 @@ const BoardHeader = () => { )}
{title || `p/${shortAddress || subplebbitAddress}`} - {isBoardOffline && } + {isOffline && }
{subtitle}

diff --git a/src/components/post-form/post-form.tsx b/src/components/post-form/post-form.tsx index 7d871f68..287cbbf8 100644 --- a/src/components/post-form/post-form.tsx +++ b/src/components/post-form/post-form.tsx @@ -12,7 +12,7 @@ import useReply from '../../hooks/use-reply'; import useChallengesStore from '../../stores/use-challenges-store'; import styles from './post-form.module.css'; import _ from 'lodash'; -import { getFormattedTimeAgo } from '../../lib/utils/time-utils'; +import useIsSubplebbitOffline from '../../hooks/use-is-subplebbit-offline'; type SubmitState = { subplebbitAddress: string | undefined; @@ -272,17 +272,12 @@ const PostForm = () => { const [showForm, setShowForm] = useState(false); const subplebbit = useSubplebbit({ subplebbitAddress: params?.subplebbitAddress }); - const { updatedAt } = subplebbit || {}; - const isBoardOffline = updatedAt && updatedAt < Date.now() / 1000 - 60 * 60; - - const offlineMessage = updatedAt - ? isBoardOffline && t('posts_last_synced_info', { time: getFormattedTimeAgo(updatedAt), interpolation: { escapeValue: false } }) - : t('subplebbit_offline_info'); + const { isOffline, offlineTitle } = useIsSubplebbitOffline(subplebbit); return ( <>
- {!(isInAllView || isInSubscriptionsView) && showForm && isBoardOffline &&
{offlineMessage}
} + {!(isInAllView || isInSubscriptionsView) && showForm && isOffline &&
{offlineTitle}
} {isThreadClosed ? (
{t('thread_closed')} @@ -302,7 +297,7 @@ const PostForm = () => { )}
- {!(isInAllView || isInSubscriptionsView) && showForm && isBoardOffline &&
{offlineMessage}
} + {!(isInAllView || isInSubscriptionsView) && showForm && isOffline &&
{offlineTitle}
} {isThreadClosed ? (
{t('thread_closed')} diff --git a/src/hooks/use-is-subplebbit-offline.ts b/src/hooks/use-is-subplebbit-offline.ts new file mode 100644 index 00000000..33875c20 --- /dev/null +++ b/src/hooks/use-is-subplebbit-offline.ts @@ -0,0 +1,19 @@ +import { useTranslation } from 'react-i18next'; +import { Subplebbit } from '@plebbit/plebbit-react-hooks'; +import { getFormattedTimeAgo } from '../lib/utils/time-utils'; + +const useIsSubplebbitOffline = (subplebbit: Subplebbit) => { + const { t } = useTranslation(); + const { updatedAt, updatingState } = subplebbit || {}; + const isProbablyOffline = !updatedAt || (updatedAt && updatedAt < Date.now() / 1000 - 60 * 60); + const isDefinitelyOffline = updatingState === 'failed'; + const isOffline = isProbablyOffline || isDefinitelyOffline; + + const offlineTitle = updatedAt + ? isOffline && t('posts_last_synced_info', { time: getFormattedTimeAgo(updatedAt), interpolation: { escapeValue: false } }) + : t('subplebbit_offline_info'); + + return { isOffline, isDefinitelyOffline, offlineTitle }; +}; + +export default useIsSubplebbitOffline; diff --git a/src/index.css b/src/index.css index 655e8185..ae102085 100644 --- a/src/index.css +++ b/src/index.css @@ -30,6 +30,10 @@ hr { text-transform: capitalize; } +.red { + color: red !important; +} + :root { color-scheme: dark; } diff --git a/src/views/board/board.tsx b/src/views/board/board.tsx index 3a82e812..eb1a87ad 100644 --- a/src/views/board/board.tsx +++ b/src/views/board/board.tsx @@ -72,14 +72,14 @@ const Board = () => { const loadingString = (
{state === 'failed' ? ( - state + {state} ) : isInSubscriptionsView && subscriptions?.length === 0 ? ( t('not_subscribed_to_any_board') ) : ( )} {error && ( -
+

{error.message}
diff --git a/src/views/home/boards-box/boards-box.tsx b/src/views/home/boards-box/boards-box.tsx index 7dbee2d8..6f9cda02 100644 --- a/src/views/home/boards-box/boards-box.tsx +++ b/src/views/home/boards-box/boards-box.tsx @@ -2,12 +2,12 @@ import { Link } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { Subplebbit, useAccount, useAccountSubplebbits } from '@plebbit/plebbit-react-hooks'; import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js'; -import { getFormattedTimeAgo } from '../../../lib/utils/time-utils'; import useHomeFiltersStore from '../../../stores/use-home-filters-store'; import { useMultisubMetadata } from '../../../hooks/use-default-subplebbits'; import styles from '../home.module.css'; import { nsfwTags } from '../home'; import BoxModal from '../box-modal'; +import useIsSubplebbitOffline from '../../../hooks/use-is-subplebbit-offline'; const Board = ({ subplebbit, subplebbits }: { subplebbit: Subplebbit; subplebbits: any }) => { const { t } = useTranslation(); @@ -18,15 +18,12 @@ const Board = ({ subplebbit, subplebbits }: { subplebbit: Subplebbit; subplebbit const boardLink = useCatalog ? `/p/${address}/catalog` : `/p/${address}`; const subplebbitData = subplebbits && subplebbits.find((sub: Subplebbit) => sub?.address === address); - const updatedAt = subplebbitData?.updatedAt; - const isOffline = updatedAt && updatedAt < Date.now() / 1000 - 60 * 60; - const offlineTitle = updatedAt - ? isOffline && t('posts_last_synced_info', { time: getFormattedTimeAgo(updatedAt), interpolation: { escapeValue: false } }) - : t('subplebbit_offline_info'); + const { isDefinitelyOffline, isOffline, offlineTitle } = useIsSubplebbitOffline(subplebbitData); + const iconClass = `${styles.offlineIcon} ${isDefinitelyOffline ? styles.redOfflineIcon : ''}`; return (
- {isOffline && } + {isOffline && } {title || address} {nsfwTag && ({t(nsfwTag)})}
diff --git a/src/views/home/home.module.css b/src/views/home/home.module.css index 043f746c..9e28a197 100644 --- a/src/views/home/home.module.css +++ b/src/views/home/home.module.css @@ -187,6 +187,10 @@ image-rendering: pixelated; } +.redOfflineIcon { + background-image: url('/public/assets/icons/offline-red.png') !important; +} + .boardsBoxContent { font-size: 93%; padding: 0.5em;