Improved project loading progress bar
This commit is contained in:
2 files changed
+105
-68
No files matched your search
@@ -0,0 +1,24 @@
|
||||
<script>
|
||||
export let progress = 0;
|
||||
export let text = '';
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.outer {
|
||||
width: 200px;
|
||||
height: 10px;
|
||||
border: 1px solid black;
|
||||
background: white;
|
||||
}
|
||||
.inner {
|
||||
height: 100%;
|
||||
width: 0;
|
||||
background: black;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="outer">
|
||||
<div class="inner" style={`width:${progress*100}%`}></div>
|
||||
</div>
|
||||
|
||||
{text}
|
||||
@@ -1,4 +1,5 @@
|
||||
<script>
|
||||
import Progress from './Progress.svelte';
|
||||
import writablePersistentStore from './persistent-store';
|
||||
import {error} from './stores';
|
||||
|
||||
@@ -7,80 +8,88 @@
|
||||
const projectId = writablePersistentStore('SelectProject.id', '1');
|
||||
let files = null;
|
||||
|
||||
const withErrorHandling = (fn) => () => fn().catch((e) => {
|
||||
$error = e
|
||||
});
|
||||
|
||||
const reset = () => {
|
||||
projectData = null;
|
||||
};
|
||||
|
||||
let progressVisible = false;
|
||||
let progress = 0;
|
||||
let progressText = '';
|
||||
|
||||
// Reset project whenever an input changes
|
||||
$: files, $projectId, $type, reset();
|
||||
|
||||
const load = withErrorHandling(async () => {
|
||||
reset();
|
||||
|
||||
const {
|
||||
VirtualMachine,
|
||||
Storage
|
||||
} = await import(/* webpackChunkName: "scratch" */ './large-scratch-packages');
|
||||
|
||||
let vm = new VirtualMachine();
|
||||
|
||||
vm.extensionManager.loadExtensionURL = () => Promise.resolve();
|
||||
|
||||
class StorageWithProgress extends Storage {
|
||||
constructor (...args) {
|
||||
super(...args);
|
||||
this.totalAssets = 0;
|
||||
this.loadedAssets = 0;
|
||||
}
|
||||
load (...args) {
|
||||
this.totalAssets++;
|
||||
// progress.text = `Downloading assets (${this.loadedAssets}/${this.totalAssets})`;
|
||||
// progress.visible = true
|
||||
// progress.value = this.loadedAssets / this.totalAssets;
|
||||
return super.load(...args)
|
||||
.then((r) => {
|
||||
this.loadedAssets++;
|
||||
// progress.text = `Downloading assets (${this.loadedAssets}/${this.totalAssets})`;
|
||||
// progress.value = this.loadedAssets / this.totalAssets;
|
||||
return r;
|
||||
});
|
||||
}
|
||||
}
|
||||
const storage = new StorageWithProgress();
|
||||
storage.addWebStore(
|
||||
[storage.AssetType.ImageVector, storage.AssetType.ImageBitmap, storage.AssetType.Sound],
|
||||
(asset) => `https://assets.scratch.mit.edu/internalapi/asset/${asset.assetId}.${asset.dataFormat}/get/`
|
||||
);
|
||||
vm.attachStorage(storage);
|
||||
|
||||
const readAsArrayBuffer = blob => new Promise((resolve, reject) => {
|
||||
const fr = new FileReader();
|
||||
fr.onload = () => resolve(fr.result);
|
||||
fr.onerror = () => reject(new Error('Can not read blob'));
|
||||
fr.readAsArrayBuffer(blob);
|
||||
});
|
||||
|
||||
const newProjectData = {
|
||||
vm
|
||||
};
|
||||
if ($type === 'id') {
|
||||
newProjectData.uniqueId = `#${$projectId}`;
|
||||
newProjectData.projectId = $projectId;
|
||||
const res = await fetch('https://projects.scratch.mit.edu/' + $projectId);
|
||||
const data = await res.arrayBuffer();
|
||||
await vm.loadProject(data);
|
||||
} else {
|
||||
const file = files[0];
|
||||
newProjectData.projectId = null;
|
||||
newProjectData.uniqueId = `@${file.name}`;
|
||||
const data = await readAsArrayBuffer(file);
|
||||
await vm.loadProject(data);
|
||||
}
|
||||
projectData = newProjectData
|
||||
const readAsArrayBuffer = blob => new Promise((resolve, reject) => {
|
||||
const fr = new FileReader();
|
||||
fr.onload = () => resolve(fr.result);
|
||||
fr.onerror = () => reject(new Error('Can not read blob'));
|
||||
fr.readAsArrayBuffer(blob);
|
||||
});
|
||||
|
||||
const load = async () => {
|
||||
try {
|
||||
reset();
|
||||
progressVisible = true;
|
||||
progress = 0;
|
||||
progressText = 'Loading Scratch';
|
||||
|
||||
const {
|
||||
VirtualMachine,
|
||||
Storage
|
||||
} = await import(/* webpackChunkName: "scratch" */ './large-scratch-packages');
|
||||
|
||||
progressText = 'Loading project';
|
||||
let vm = new VirtualMachine();
|
||||
vm.extensionManager.loadExtensionURL = () => Promise.resolve();
|
||||
class StorageWithProgress extends Storage {
|
||||
constructor (...args) {
|
||||
super(...args);
|
||||
this.totalAssets = 0;
|
||||
this.loadedAssets = 0;
|
||||
}
|
||||
load (...args) {
|
||||
this.totalAssets++;
|
||||
progress = this.loadedAssets / this.totalAssets;
|
||||
progressText = `Loading assets (${this.loadedAssets}/${this.totalAssets})`;
|
||||
return super.load(...args)
|
||||
.then((r) => {
|
||||
this.loadedAssets++;
|
||||
progress = this.loadedAssets / this.totalAssets;
|
||||
progressText = `Loading assets (${this.loadedAssets}/${this.totalAssets})`;
|
||||
return r;
|
||||
});
|
||||
}
|
||||
}
|
||||
const storage = new StorageWithProgress();
|
||||
storage.addWebStore(
|
||||
[storage.AssetType.ImageVector, storage.AssetType.ImageBitmap, storage.AssetType.Sound],
|
||||
(asset) => `https://assets.scratch.mit.edu/internalapi/asset/${asset.assetId}.${asset.dataFormat}/get/`
|
||||
);
|
||||
vm.attachStorage(storage);
|
||||
|
||||
const newProjectData = {
|
||||
vm
|
||||
};
|
||||
if ($type === 'id') {
|
||||
newProjectData.uniqueId = `#${$projectId}`;
|
||||
newProjectData.projectId = $projectId;
|
||||
const res = await fetch('https://projects.scratch.mit.edu/' + $projectId);
|
||||
const data = await res.arrayBuffer();
|
||||
await vm.loadProject(data);
|
||||
} else {
|
||||
const file = files[0];
|
||||
newProjectData.projectId = null;
|
||||
newProjectData.uniqueId = `@${file.name}`;
|
||||
const data = await readAsArrayBuffer(file);
|
||||
await vm.loadProject(data);
|
||||
}
|
||||
projectData = newProjectData
|
||||
} catch (e) {
|
||||
$error = e;
|
||||
}
|
||||
|
||||
progressVisible = false;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@@ -107,5 +116,9 @@
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button on:click={load}>Load Project</button>
|
||||
<button on:click={load} disabled={progressVisible}>Load Project</button>
|
||||
</div>
|
||||
|
||||
{#if progressVisible}
|
||||
<Progress progress={progress} text={progressText} />
|
||||
{/if}
|
||||
Reference in new issue
Block a user