Merge pull request #3491 from rschamp/storage-no-cache
Use assets stored in the vm instead of storage
This commit is contained in:
15 files changed
+51
-48
No files matched your search
+1
-1
@@ -105,7 +105,7 @@
|
||||
"scratch-render": "0.1.0-prerelease.20181024220305",
|
||||
"scratch-storage": "1.1.0",
|
||||
"scratch-svg-renderer": "0.2.0-prerelease.20181024192149",
|
||||
"scratch-vm": "0.2.0-prerelease.20181023192708",
|
||||
"scratch-vm": "0.2.0-prerelease.20181025092837",
|
||||
"selenium-webdriver": "3.6.0",
|
||||
"startaudiocontext": "1.2.1",
|
||||
"style-loader": "^0.23.0",
|
||||
|
||||
@@ -64,7 +64,7 @@ const Selector = props => {
|
||||
onRemoveSortable={onRemoveSortable}
|
||||
>
|
||||
<SpriteSelectorItem
|
||||
assetId={item.assetId}
|
||||
asset={item.asset}
|
||||
className={classNames(styles.listItem, {
|
||||
[styles.placeholder]: isRelevantDrag && index === draggingIndex
|
||||
})}
|
||||
|
||||
@@ -69,7 +69,7 @@ const SpriteList = function (props) {
|
||||
onRemoveSortable={onRemoveSortable}
|
||||
>
|
||||
<SpriteSelectorItem
|
||||
assetId={sprite.costume && sprite.costume.assetId}
|
||||
asset={sprite.costume && sprite.costume.asset}
|
||||
className={classNames(styles.sprite, {
|
||||
[styles.raised]: isRaised,
|
||||
[styles.receivedBlocks]: receivedBlocks
|
||||
|
||||
@@ -79,9 +79,9 @@ const TargetPane = ({
|
||||
/>
|
||||
<div className={styles.stageSelectorWrapper}>
|
||||
{stage.id && <StageSelector
|
||||
assetId={
|
||||
asset={
|
||||
stage.costume &&
|
||||
stage.costume.assetId
|
||||
stage.costume.asset
|
||||
}
|
||||
backdropCount={stage.costumeCount}
|
||||
id={stage.id}
|
||||
|
||||
@@ -259,7 +259,7 @@ class CostumeTab extends React.Component {
|
||||
|
||||
const costumeData = target.costumes ? target.costumes.map(costume => ({
|
||||
name: costume.name,
|
||||
assetId: costume.assetId,
|
||||
asset: costume.asset,
|
||||
details: costume.size ? this.formatCostumeDetails(costume.size, costume.bitmapResolution) : null,
|
||||
dragPayload: costume
|
||||
})) : [];
|
||||
|
||||
@@ -80,17 +80,19 @@ class RecordModal extends React.Component {
|
||||
sampleCount: clippedSamples.length
|
||||
};
|
||||
|
||||
// Load the encoded .wav into the storage cache and get resulting
|
||||
// md5 from storage
|
||||
const storage = this.props.vm.runtime.storage;
|
||||
const md5 = storage.builtinHelper.cache(
|
||||
// Create an asset from the encoded .wav and get resulting md5
|
||||
const storage = this.props.vm.storage;
|
||||
vmSound.asset = storage.createAsset(
|
||||
storage.AssetType.Sound,
|
||||
storage.DataFormat.WAV,
|
||||
new Uint8Array(wavBuffer),
|
||||
null,
|
||||
true // generate md5
|
||||
);
|
||||
vmSound.assetId = vmSound.asset.assetId;
|
||||
|
||||
// update vmSound object with md5 property
|
||||
vmSound.md5 = `${md5}.${vmSound.dataFormat}`;
|
||||
vmSound.md5 = `${vmSound.assetId}.${vmSound.dataFormat}`;
|
||||
// The VM will update the sound name to a fresh name
|
||||
// if the following is already taken
|
||||
vmSound.name = 'recording1';
|
||||
|
||||
@@ -5,6 +5,7 @@ import {connect} from 'react-redux';
|
||||
|
||||
import {setHoveredSprite} from '../reducers/hovered-target';
|
||||
import {updateAssetDrag} from '../reducers/asset-drag';
|
||||
import storage from '../lib/storage';
|
||||
import {getEventXY} from '../lib/touch-utils';
|
||||
import VM from 'scratch-vm';
|
||||
import getCostumeUrl from '../lib/get-costume-url';
|
||||
@@ -44,9 +45,9 @@ class SpriteSelectorItem extends React.Component {
|
||||
}
|
||||
getCostumeData () {
|
||||
if (this.props.costumeURL) return this.props.costumeURL;
|
||||
if (!this.props.assetId) return null;
|
||||
if (!this.props.asset) return null;
|
||||
|
||||
return getCostumeUrl(this.props.assetId, this.props.vm);
|
||||
return getCostumeUrl(this.props.asset);
|
||||
}
|
||||
handleMouseUp () {
|
||||
this.initialOffset = null;
|
||||
@@ -147,7 +148,7 @@ class SpriteSelectorItem extends React.Component {
|
||||
}
|
||||
|
||||
SpriteSelectorItem.propTypes = {
|
||||
assetId: PropTypes.string,
|
||||
asset: PropTypes.instanceOf(storage.Asset),
|
||||
costumeURL: PropTypes.string,
|
||||
dispatchSetHoveredSprite: PropTypes.func.isRequired,
|
||||
dragPayload: PropTypes.shape({
|
||||
|
||||
@@ -106,7 +106,7 @@ class StageSelector extends React.Component {
|
||||
}
|
||||
render () {
|
||||
const componentProps = omit(this.props, [
|
||||
'assetId', 'dispatchSetHoveredSprite', 'id', 'intl', 'onActivateTab', 'onSelect']);
|
||||
'asset', 'dispatchSetHoveredSprite', 'id', 'intl', 'onActivateTab', 'onSelect']);
|
||||
return (
|
||||
<DroppableStage
|
||||
fileInputRef={this.setFileInput}
|
||||
@@ -130,8 +130,8 @@ StageSelector.propTypes = {
|
||||
onSelect: PropTypes.func
|
||||
};
|
||||
|
||||
const mapStateToProps = (state, {assetId, id}) => ({
|
||||
url: assetId && state.scratchGui.vm.runtime.storage.get(assetId).encodeDataURI(),
|
||||
const mapStateToProps = (state, {asset, id}) => ({
|
||||
url: asset && asset.encodeDataURI(),
|
||||
vm: state.scratchGui.vm,
|
||||
receivedBlocks: state.scratchGui.hoveredTarget.receivedBlocks &&
|
||||
state.scratchGui.hoveredTarget.sprite === id,
|
||||
|
||||
@@ -5,6 +5,7 @@ import React from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
|
||||
import VM from 'scratch-vm';
|
||||
import storage from '../lib/storage';
|
||||
import getCostumeUrl from '../lib/get-costume-url';
|
||||
|
||||
import WatermarkComponent from '../components/watermark/watermark.jsx';
|
||||
@@ -20,13 +21,13 @@ class Watermark extends React.Component {
|
||||
}
|
||||
|
||||
getCostumeData () {
|
||||
if (!this.props.assetId) return null;
|
||||
if (!this.props.asset) return null;
|
||||
|
||||
return getCostumeUrl(this.props.assetId, this.props.vm);
|
||||
return getCostumeUrl(this.props.asset);
|
||||
}
|
||||
|
||||
render () {
|
||||
const componentProps = omit(this.props, ['assetId', 'vm']);
|
||||
const componentProps = omit(this.props, ['asset', 'vm']);
|
||||
return (
|
||||
<WatermarkComponent
|
||||
costumeURL={this.getCostumeData()}
|
||||
@@ -37,7 +38,7 @@ class Watermark extends React.Component {
|
||||
}
|
||||
|
||||
Watermark.propTypes = {
|
||||
assetId: PropTypes.string,
|
||||
asset: PropTypes.instanceOf(storage.Asset),
|
||||
vm: PropTypes.instanceOf(VM).isRequired
|
||||
};
|
||||
|
||||
@@ -45,19 +46,19 @@ const mapStateToProps = state => {
|
||||
const targets = state.scratchGui.targets;
|
||||
const currentTargetId = targets.editingTarget;
|
||||
|
||||
let assetId;
|
||||
let asset;
|
||||
if (currentTargetId) {
|
||||
if (targets.stage.id === currentTargetId) {
|
||||
assetId = targets.stage.costume.assetId;
|
||||
asset = targets.stage.costume.asset;
|
||||
} else if (targets.sprites.hasOwnProperty(currentTargetId)) {
|
||||
const currentSprite = targets.sprites[currentTargetId];
|
||||
assetId = currentSprite.costume.assetId;
|
||||
asset = currentSprite.costume.asset;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
vm: state.scratchGui.vm,
|
||||
assetId: assetId
|
||||
asset: asset
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import jpegThumbnail from './jpeg-thumbnail';
|
||||
import storage from '../storage';
|
||||
|
||||
const costumePayload = costume => {
|
||||
// TODO is it ok to base64 encode SVGs? What about unicode text inside them?
|
||||
const assetDataUrl = storage.get(costume.assetId).encodeDataURI();
|
||||
const assetDataUrl = costume.asset.encodeDataURI();
|
||||
const assetDataFormat = costume.dataFormat;
|
||||
const payload = {
|
||||
type: 'costume',
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import soundThumbnail from '!base64-loader!./sound-thumbnail.jpg';
|
||||
import storage from '../storage';
|
||||
|
||||
const soundPayload = sound => {
|
||||
const assetDataUrl = storage.get(sound.assetId).encodeDataURI();
|
||||
const assetDataUrl = sound.asset.encodeDataURI();
|
||||
const assetDataFormat = sound.dataFormat;
|
||||
const payload = {
|
||||
type: 'sound',
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import jpegThumbnail from './jpeg-thumbnail';
|
||||
import storage from '../storage';
|
||||
|
||||
const spritePayload = (sprite, vm) => vm.exportSprite(
|
||||
sprite.id,
|
||||
@@ -14,7 +13,7 @@ const spritePayload = (sprite, vm) => vm.exportSprite(
|
||||
thumbnail: ''
|
||||
};
|
||||
|
||||
const costumeDataUrl = storage.get(sprite.costume.assetId).encodeDataURI();
|
||||
const costumeDataUrl = sprite.costume.asset.encodeDataURI();
|
||||
return jpegThumbnail(costumeDataUrl).then(thumbnail => {
|
||||
payload.thumbnail = thumbnail.replace('data:image/jpeg;base64,', '');
|
||||
return payload;
|
||||
|
||||
@@ -51,7 +51,7 @@ const handleFileUpload = function (fileInput, onload) {
|
||||
*/
|
||||
|
||||
/**
|
||||
* Cache an asset (costume, sound) in storage and return an object representation
|
||||
* Create an asset (costume, sound) with storage and return an object representation
|
||||
* of the asset to track in the VM.
|
||||
* @param {ScratchStorage} storage The storage to cache the asset in
|
||||
* @param {string} fileName The name of the asset
|
||||
@@ -62,18 +62,21 @@ const handleFileUpload = function (fileInput, onload) {
|
||||
* @return {VMAsset} An object representing this asset and relevant information
|
||||
* which can be used to look up the data in storage
|
||||
*/
|
||||
const cacheAsset = function (storage, fileName, assetType, dataFormat, data) {
|
||||
const md5 = storage.builtinHelper.cache(
|
||||
const createVMAsset = function (storage, fileName, assetType, dataFormat, data) {
|
||||
const asset = storage.createAsset(
|
||||
assetType,
|
||||
dataFormat,
|
||||
data
|
||||
data,
|
||||
null,
|
||||
true // generate md5
|
||||
);
|
||||
|
||||
return {
|
||||
name: fileName,
|
||||
dataFormat: dataFormat,
|
||||
md5: `${md5}.${dataFormat}`,
|
||||
assetId: md5
|
||||
asset: asset,
|
||||
md5: `${asset.assetId}.${dataFormat}`,
|
||||
assetId: asset.assetId
|
||||
};
|
||||
};
|
||||
|
||||
@@ -114,7 +117,7 @@ const costumeUpload = function (fileData, fileType, costumeName, storage, handle
|
||||
|
||||
const bitmapAdapter = new BitmapAdapter();
|
||||
const addCostumeFromBuffer = function (dataBuffer) {
|
||||
const vmCostume = cacheAsset(
|
||||
const vmCostume = createVMAsset(
|
||||
storage,
|
||||
costumeName,
|
||||
assetType,
|
||||
@@ -170,7 +173,7 @@ const soundUpload = function (fileData, fileType, soundName, storage, handleSoun
|
||||
return;
|
||||
}
|
||||
|
||||
const vmSound = cacheAsset(
|
||||
const vmSound = createVMAsset(
|
||||
storage,
|
||||
soundName,
|
||||
storage.AssetType.Sound,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import storage from './storage';
|
||||
import {SVGRenderer} from 'scratch-svg-renderer';
|
||||
|
||||
// Contains 'font-family', but doesn't only contain 'font-family="none"'
|
||||
@@ -7,30 +8,28 @@ const getCostumeUrl = (function () {
|
||||
let cachedAssetId;
|
||||
let cachedUrl;
|
||||
|
||||
return function (assetId, vm) {
|
||||
return function (asset) {
|
||||
|
||||
if (cachedAssetId === assetId) {
|
||||
if (cachedAssetId === asset.assetId) {
|
||||
return cachedUrl;
|
||||
}
|
||||
|
||||
cachedAssetId = assetId;
|
||||
cachedAssetId = asset.assetId;
|
||||
|
||||
const storage = vm.runtime.storage;
|
||||
const asset = storage.get(assetId);
|
||||
// If the SVG refers to fonts, they must be inlined in order to display correctly in the img tag.
|
||||
// Avoid parsing the SVG when possible, since it's expensive.
|
||||
if (asset.assetType === storage.AssetType.ImageVector) {
|
||||
const svgString = vm.runtime.storage.get(assetId).decodeText();
|
||||
const svgString = asset.decodeText();
|
||||
if (svgString.match(HAS_FONT_REGEXP)) {
|
||||
const svgRenderer = new SVGRenderer();
|
||||
svgRenderer.loadString(svgString);
|
||||
const svgText = svgRenderer.toString(true /* shouldInjectFonts */);
|
||||
cachedUrl = `data:image/svg+xml;utf8,${encodeURIComponent(svgText)}`;
|
||||
} else {
|
||||
cachedUrl = vm.runtime.storage.get(assetId).encodeDataURI();
|
||||
cachedUrl = asset.encodeDataURI();
|
||||
}
|
||||
} else {
|
||||
cachedUrl = vm.runtime.storage.get(assetId).encodeDataURI();
|
||||
cachedUrl = asset.encodeDataURI();
|
||||
}
|
||||
|
||||
return cachedUrl;
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ class Storage extends ScratchStorage {
|
||||
}
|
||||
cacheDefaultProject () {
|
||||
const defaultProjectAssets = defaultProject(this.translator);
|
||||
defaultProjectAssets.forEach(asset => this.cache(
|
||||
defaultProjectAssets.forEach(asset => this.builtinHelper._store(
|
||||
this.AssetType[asset.assetType],
|
||||
this.DataFormat[asset.dataFormat],
|
||||
asset.data,
|
||||
|
||||
Reference in new issue
Block a user