feat(submit page): alert user if selected subplebbit might be offline

This commit is contained in:
Tom (plebeius.eth)
2024-10-08 21:14:09 +02:00
parent c9217cda62
commit 7e565ab9fc
4 changed files with 147 additions and 18 deletions

View File

@@ -0,0 +1,51 @@
import { useTranslation } from 'react-i18next';
import { useEffect } from 'react';
import { Subplebbit } from '@plebbit/plebbit-react-hooks';
import { getFormattedTimeAgo } from '../lib/utils/time-utils';
import useSubplebbitOfflineStore from '../stores/use-subplebbit-offline-store';
import useSubplebbitsLoadingStartTimestamps from '../stores/use-subplebbits-loading-start-timestamps-store';
const useIsSubplebbitOffline = (subplebbit: Subplebbit) => {
const { t } = useTranslation();
const { address, state, updatedAt, updatingState } = subplebbit || {};
const { subplebbitOfflineState, setSubplebbitOfflineState, initializesubplebbitOfflineState } = useSubplebbitOfflineStore();
const subplebbitsLoadingStartTimestamps = useSubplebbitsLoadingStartTimestamps([address]);
useEffect(() => {
if (address && !subplebbitOfflineState[address]) {
initializesubplebbitOfflineState(address);
}
}, [address, subplebbitOfflineState, initializesubplebbitOfflineState]);
useEffect(() => {
if (address) {
setSubplebbitOfflineState(address, { state, updatedAt, updatingState });
}
}, [address, state, updatedAt, updatingState, setSubplebbitOfflineState]);
const subplebbitOfflineStore = subplebbitOfflineState[address] || { initialLoad: true };
const loadingStartTimestamp = subplebbitsLoadingStartTimestamps[0] || 0;
const isLoading = subplebbitOfflineStore.initialLoad && (!updatedAt || Date.now() / 1000 - updatedAt >= 60 * 60) && Date.now() / 1000 - loadingStartTimestamp < 30;
const isOffline = !isLoading && ((updatedAt && updatedAt < Date.now() / 1000 - 60 * 60) || (!updatedAt && Date.now() / 1000 - loadingStartTimestamp >= 30));
const isOnline = updatedAt && Date.now() / 1000 - updatedAt < 60 * 60;
const offlineTitle = isLoading
? t('loading')
: updatedAt
? isOffline && t('posts_last_synced_info', { time: getFormattedTimeAgo(updatedAt), interpolation: { escapeValue: false } })
: t('subplebbit_offline_info');
// ensure isOffline is false until we have enough information
const hasEnoughInfo = subplebbitOfflineStore.initialLoad === false || updatedAt !== undefined;
return {
isOffline: hasEnoughInfo && !isOnline && isOffline,
isOnlineStatusLoading: !isOnline && isLoading,
offlineTitle,
};
};
export default useIsSubplebbitOffline;

View File

@@ -0,0 +1,51 @@
import { create } from 'zustand';
interface SubplebbitOfflineState {
state?: string;
updatedAt?: number;
updatingState?: string;
initialLoad: boolean;
}
interface SubplebbitOfflineStore {
subplebbitOfflineState: Record<string, SubplebbitOfflineState>;
setSubplebbitOfflineState: (address: string, state: Partial<SubplebbitOfflineState>) => void;
initializesubplebbitOfflineState: (address: string) => void;
}
const useSubplebbitOfflineStore = create<SubplebbitOfflineStore>((set) => ({
subplebbitOfflineState: {},
setSubplebbitOfflineState: (address, newState) =>
set((state) => ({
subplebbitOfflineState: {
...state.subplebbitOfflineState,
[address]: {
...state.subplebbitOfflineState[address],
...newState,
},
},
})),
initializesubplebbitOfflineState: (address) => {
set((state) => ({
subplebbitOfflineState: {
...state.subplebbitOfflineState,
[address]: {
initialLoad: true,
},
},
}));
setTimeout(() => {
set((state) => ({
subplebbitOfflineState: {
...state.subplebbitOfflineState,
[address]: {
...state.subplebbitOfflineState[address],
initialLoad: false,
},
},
}));
}, 30000);
},
}));
export default useSubplebbitOfflineStore;

View File

@@ -0,0 +1,42 @@
import { useEffect, useMemo } from 'react';
import { create } from 'zustand';
interface SubplebbitsLoadingStartTimestampsState {
timestamps: Record<string, number>;
addSubplebbits: (subplebbitAddresses: string[]) => void;
}
const useSubplebbitsLoadingStartTimestampsStore = create<SubplebbitsLoadingStartTimestampsState>((set, get) => ({
timestamps: {},
addSubplebbits: (subplebbitAddresses) => {
const { timestamps } = get();
const newTimestamps: Record<string, number> = {};
subplebbitAddresses.forEach((subplebbitAddress) => {
if (!timestamps[subplebbitAddress]) {
newTimestamps[subplebbitAddress] = Math.round(Date.now() / 1000);
}
});
if (Object.keys(newTimestamps).length) {
set((state) => ({ timestamps: { ...state.timestamps, ...newTimestamps } }));
}
},
}));
const useSubplebbitsLoadingStartTimestamps = (subplebbitAddresses?: string[]) => {
const timestampsStore = useSubplebbitsLoadingStartTimestampsStore((state) => state.timestamps);
const addSubplebbits = useSubplebbitsLoadingStartTimestampsStore((state) => state.addSubplebbits);
useEffect(() => {
if (subplebbitAddresses) {
addSubplebbits(subplebbitAddresses);
}
}, [subplebbitAddresses, addSubplebbits]);
const subplebbitsLoadingStartTimestamps = useMemo(() => {
return subplebbitAddresses?.map((subplebbitAddress) => timestampsStore[subplebbitAddress]) || [];
}, [timestampsStore, subplebbitAddresses]);
return subplebbitsLoadingStartTimestamps;
};
export default useSubplebbitsLoadingStartTimestamps;

View File

@@ -11,6 +11,7 @@ import { isSubmitView } from '../../lib/utils/view-utils';
import Embed from '../../components/post/embed';
import Markdown from '../../components/markdown';
import styles from './submit-page.module.css';
import useIsSubplebbitOffline from '../../hooks/use-is-subplebbit-offline';
const UrlField = () => {
const { t } = useTranslation();
@@ -87,23 +88,7 @@ const Submit = () => {
const { subscriptions } = account || {};
const defaultSubplebbitAddresses = useDefaultSubplebbitAddresses();
const [isOffline, setIsOffline] = useState(false);
useEffect(() => {
const checkOfflineStatus = () => {
if (subplebbit?.updatedAt !== undefined) {
setIsOffline(subplebbit.updatedAt < Date.now() / 1000 - 60 * 60);
} else {
setTimeout(() => {
setIsOffline(subplebbit?.updatedAt === undefined || subplebbit.updatedAt < Date.now() / 1000 - 60 * 60);
}, 5000);
}
};
if (subplebbitAddress) {
checkOfflineStatus();
}
}, [subplebbit?.updatedAt, subplebbitAddress]);
const { isOffline, offlineTitle } = useIsSubplebbitOffline(subplebbit);
const onPublish = () => {
if (!title) {
@@ -235,7 +220,7 @@ const Submit = () => {
return (
<div className={styles.content}>
{isOffline && <div className={styles.infobar}>test</div>}
{isOffline && selectedSubplebbit && <div className={styles.infobar}>{offlineTitle}</div>}
<h1>
<Trans
i18nKey='submit_to'