From 79bb31540196b74f3bc0220b8c844fbd5aaaf488 Mon Sep 17 00:00:00 2001 From: Levente Kiss Date: Mon, 8 Jan 2024 22:56:31 +0100 Subject: [PATCH] feat: wait for upload sync (#649) * feat: add basic progress bar (#605) * feat: add syncing to share page (#605) * refactor: use the documentation text comp (#605) * refactor: move sync logic to new comp (#605) * refactor: optimize sync check (#605) * chore: linting (#605) --------- Co-authored-by: Levente Kiss --- src/components/ProgressBar.tsx | 22 +++++++++ src/pages/files/AssetSyncing.tsx | 85 ++++++++++++++++++++++++++++++++ src/pages/files/Share.tsx | 4 ++ src/pages/files/Upload.tsx | 11 ++++- 4 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 src/components/ProgressBar.tsx create mode 100644 src/pages/files/AssetSyncing.tsx diff --git a/src/components/ProgressBar.tsx b/src/components/ProgressBar.tsx new file mode 100644 index 00000000..78426a6b --- /dev/null +++ b/src/components/ProgressBar.tsx @@ -0,0 +1,22 @@ +import React, { ReactElement } from 'react' +import LinearProgress, { LinearProgressProps } from '@material-ui/core/LinearProgress' +import Typography from '@material-ui/core/Typography' +import Box from '@material-ui/core/Box' + +interface Props { + linearProgressProps?: LinearProgressProps + value: number +} + +export function LinearProgressWithLabel(props: Props): ReactElement { + return ( + + + + + + {`${Math.round(props.value)}%`} + + + ) +} diff --git a/src/pages/files/AssetSyncing.tsx b/src/pages/files/AssetSyncing.tsx new file mode 100644 index 00000000..736a9eb3 --- /dev/null +++ b/src/pages/files/AssetSyncing.tsx @@ -0,0 +1,85 @@ +import { Context as SettingsContext } from '../../providers/Settings' +import { Box } from '@material-ui/core' +import { ReactElement, useContext, useEffect, useRef, useState } from 'react' +import { DocumentationText } from '../../components/DocumentationText' +import { LinearProgressWithLabel } from '../../components/ProgressBar' + +interface Props { + reference: string +} + +export function AssetSyncing({ reference }: Props): ReactElement { + const { beeApi } = useContext(SettingsContext) + + const syncTimer = useRef() + const [isRetrieveChecking, setIsRetrieveChecking] = useState(false) + const [syncProgress, setSyncProgress] = useState(0) + + const syncCheck = async () => { + if (!beeApi) { + return + } + + const tags = await beeApi.getAllTags() + const tag = tags.find(t => t.address === reference) + + if (tag) { + const progress = ((tag.seen + tag.synced) / tag.split) * 100 + setSyncProgress(progress) + } + } + + useEffect(() => { + syncTimer.current = setInterval(syncCheck, 2000) + + return () => { + if (syncTimer.current) { + clearInterval(syncTimer.current) + } + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [reference]) + + useEffect(() => { + if (syncProgress === 100 && syncTimer.current) { + clearInterval(syncTimer.current) + } + }, [syncProgress]) + + useEffect(() => { + /* + There are instances when it seems that the content isn't synchronized, despite being already available. + To ensure it's not due to invalid synchronization data, + verify availability from at least 70% using one of the stewardship endpoints. + + TODO: is 70 a good number? + */ + if (beeApi && !isRetrieveChecking && syncProgress > 10 && syncProgress < 100) { + // It's a long running task make sure only one run occurs at a time. + setIsRetrieveChecking(true) + + beeApi.isReferenceRetrievable(reference).then(isRetriavable => { + if (isRetriavable) { + setSyncProgress(100) + } + + setIsRetrieveChecking(false) + }) + } + }, [syncProgress, isRetrieveChecking, beeApi, reference]) + + return ( + <> + + + Files are not immediately accessible on the Swarm network. Please wait until your upload is synced to the + network.{' '} + Learn more about syncing. + + + + + + + ) +} diff --git a/src/pages/files/Share.tsx b/src/pages/files/Share.tsx index b748c89b..c74e5864 100644 --- a/src/pages/files/Share.tsx +++ b/src/pages/files/Share.tsx @@ -16,6 +16,7 @@ import { ManifestJs } from '../../utils/manifest' import { AssetPreview } from './AssetPreview' import { AssetSummary } from './AssetSummary' import { DownloadActionBar } from './DownloadActionBar' +import { AssetSyncing } from './AssetSyncing' export function Share(): ReactElement { const { apiUrl, beeApi } = useContext(SettingsContext) @@ -152,6 +153,9 @@ export function Share(): ReactElement { + + + )} - {step === 2 && stamp && } + {step === 2 && stamp && ( + <> + + + + Please do not close the application until your file is uploaded to your local node! + + + + )}