Skip to content

Stop button and disable caching #13

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Feb 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 55 additions & 4 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useState } from 'react';
import { Link, Route, Routes } from "react-router-dom";
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { library } from '@fortawesome/fontawesome-svg-core';
import {
Navbar,
Expand Down Expand Up @@ -60,6 +61,8 @@ export const App = () => {
maxBlock: 0,
}]);
const [currentDownloadedBlock, setCurrentDownloadedBlock] = useState(0);
const [abortController, setAbortController] = useState<{ controllerStop: AbortController, controllerPause: AbortController } | null>(null);
const [pausedStatus, setPausedStatus] = useState<string>('');
const [menuActive, setMenuActive] = useState<boolean>(false);
const [isLoading, setLoading] = useState<boolean>(false);
const [modal, setModal] = useState<Modal>({
Expand All @@ -83,12 +86,18 @@ export const App = () => {
<div className="modal">
<div
className="modal_close_panel"
onClick={() => onModal()}
onClick={() => {
onModal();
setCurrentDownloadedBlock(0);
}}
/>
<div className="modal_content">
<div
className="modal_close"
onClick={() => onModal()}
onClick={() => {
onModal();
setCurrentDownloadedBlock(0);
}}
>
<img
src="/img/close.svg"
Expand Down Expand Up @@ -126,19 +135,60 @@ export const App = () => {
<div
className="modal_close_panel"
onClick={currentDownloadedBlock < (modal.params.spanEnd - modal.params.spanStart + 1) ? () => {} : () => {
onModal();
abortController?.controllerStop.abort();
setCurrentDownloadedBlock(0);
}}
/>
<div className="modal_content">
<Heading weight="semibold" subtitle style={{ textAlign: 'center', marginBottom: 5 }}>{`Snapshot`}</Heading>
<Heading weight="semibold" size={6} subtitle style={{ textAlign: 'center' }}>{`${modal.params.spanStart} - ${modal.params.spanEnd} (${nets[modal.params.network].title})`}</Heading>
<Heading size={6} subtitle style={{ textAlign: 'center', margin: 0 }}>{currentDownloadedBlock / (modal.params.spanEnd - modal.params.spanStart + 1) === 1 ? 'Success!' : 'Writing'}</Heading>
<Heading size={6} subtitle style={{ textAlign: 'center', margin: 0 }}>{currentDownloadedBlock / (modal.params.spanEnd - modal.params.spanStart + 1) === 1 ? 'Success!' : 'Downloading'}</Heading>
<Progress
max={100}
value={roundNumber((currentDownloadedBlock / (modal.params.spanEnd - modal.params.spanStart + 1)) * 100)}
/>
<Heading size={6} subtitle style={{ textAlign: 'center', margin: 0 }}>{`${currentDownloadedBlock} / ${modal.params.spanEnd - modal.params.spanStart + 1} (${roundNumber((currentDownloadedBlock / (modal.params.spanEnd - modal.params.spanStart + 1)) * 100)}%)`}</Heading>
<Button
color="primary"
onClick={() => {
if (pausedStatus === 'continue') {
typeof modal.btn === 'function' && modal.btn(currentDownloadedBlock);
setPausedStatus('paused');
setTimeout(() => setPausedStatus(''), 500);
} else {
abortController?.controllerPause.abort();
setPausedStatus('paused');
setTimeout(() => setPausedStatus('continue'), 500);
}
}}
style={{ minWidth: 300, marginTop: 25 }}
>
<span>
{pausedStatus === 'paused' ? (
<FontAwesomeIcon
icon={['fas', 'spinner']}
spin
/>
) : pausedStatus === '' ? 'Pause': 'Continue'}
</span>
</Button>
<Button
color="secondary"
onClick={() => {
abortController?.controllerStop.abort();
setCurrentDownloadedBlock(0);
}}
style={{ minWidth: 300, marginTop: 10 }}
>
<span>
{abortController?.controllerStop.signal.aborted ? (
<FontAwesomeIcon
icon={['fas', 'spinner']}
spin
/>
) : 'Cancel'}
</span>
</Button>
</div>
</div>
)}
Expand Down Expand Up @@ -185,6 +235,7 @@ export const App = () => {
nets={nets}
setNets={setNets}
setCurrentDownloadedBlock={setCurrentDownloadedBlock}
setAbortController={setAbortController}
isLoading={isLoading}
setLoading={setLoading}
/>}
Expand Down
28 changes: 22 additions & 6 deletions src/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const Home = ({
nets,
setNets,
setCurrentDownloadedBlock,
setAbortController,
isLoading,
setLoading,
}) => {
Expand Down Expand Up @@ -80,7 +81,14 @@ const Home = ({
types: [{ accept: { 'application/octet-stream': ['.acc'] } }],
});
}
onModal('loading', formData);
onModal('loading', formData, (retryIndexTemp: number) => fetchBlocksInRange(+formData.spanStart + retryIndexTemp));

const controllerStop = new AbortController();
const controllerPause = new AbortController();
setAbortController({
controllerStop,
controllerPause,
});

const writableStream = await fileHandle?.createWritable(retryIndex === null ? {} : { keepExistingData: true });

Expand All @@ -95,6 +103,8 @@ const Home = ({
const indexFileStart = Math.floor(formData.spanStart / 128000);
const indexFileCount = Math.ceil((formData.spanEnd - formData.spanStart) / 128000) + indexFileStart;
for (let indexFile = indexFileStart; indexFile <= indexFileCount; indexFile += 1) {
if (controllerStop.signal.aborted) throw new Error('Fetching aborted');
if (controllerPause.signal.aborted) throw new Error('Paused');

const indexData: Uint8Array | string = await fetchIndexFile(currentNet, indexFile);
if (typeof indexData === 'string') {
Expand All @@ -113,12 +123,15 @@ const Home = ({

const startBlock = retryIndex !== null ? retryIndex : formData.spanStart;
for (let i = startBlock - (128000 * indexFile); i <= objectsData.length; i += 1) {
if (controllerStop.signal.aborted) throw new Error('Fetching aborted');
if (controllerPause.signal.aborted) throw new Error('Paused');

if (blockCount <= (indexFile * 128000 + i - formData.spanStart)) {
await writableStream?.close();
return
}

const objectData: Uint8Array | string = await fetchBlock(currentNet, objectsData[i]);
const objectData: Uint8Array | string = await fetchBlock(currentNet, i, objectsData[i]);
if (typeof objectData === 'string') {
await writableStream?.close();
onModal('failed', objectData, (currentDownloadedBlockTemp: number) => fetchBlocksInRange(+formData.spanStart + currentDownloadedBlockTemp));
Expand All @@ -132,11 +145,14 @@ const Home = ({
}
}
} catch (error: any) {
if (error.message.indexOf('showSaveFilePicker is not a function') !== -1) {
if (error.message.indexOf('Fetching aborted') !== -1) {
onModal('failed', 'Fetching was cancelled');
setAbortController(null);
} else if (error.message.indexOf('showSaveFilePicker is not a function') !== -1) {
onModal('failed', 'Your current browser does not support this site\'s functionality. For the best experience, please use Chrome 86+ (recommended).', 'about');
} else if (error.message.indexOf('The user aborted a request.') !== -1) {
onModal('failed', 'Aborted by user.');
} else {
} else if (error.message.indexOf('Paused') === -1) {
onModal('failed', error.message || 'Error occurred during block fetching.', (retryIndexTemp: number) => fetchBlocksInRange(+formData.spanStart + retryIndexTemp));
}
} finally {
Expand Down Expand Up @@ -166,12 +182,12 @@ const Home = ({
}
};

const fetchBlock = async (currentNet: NetItem, objectId: string): Promise<Uint8Array | string> => {
const fetchBlock = async (currentNet: NetItem, objectNumber: number, objectId: string): Promise<Uint8Array | string> => {
try {
const blockResponse = await api('GET', `/objects/${currentNet.containerId}/by_id/${objectId}?walletConnect=false`);
return blockResponse as Uint8Array;
} catch (err: any) {
return `Error occurred during object fetching ${objectId}: ${err.message}`;
return `Error occurred during object fetching #${objectNumber}: ${err.message}`;
}
};

Expand Down
8 changes: 7 additions & 1 deletion src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ type Methods = "GET" | "POST";
async function serverRequest(method: Methods, url: string, params: object, headers: any) {
const json: any = {
method,
headers,
cache: 'no-store',
headers: {
'Cache-Control': 'no-cache, no-store, must-revalidate',
'Pragma': 'no-cache',
'Expires': '0',
...headers,
},
}

if (json['headers']['Content-Type']) {
Expand Down