@@ -3,6 +3,7 @@ import React from 'react';
33import PropTypes from 'prop-types' ;
44import { connect } from 'react-redux' ;
55import { intlShape , injectIntl } from 'react-intl' ;
6+ import JSZip from '@turbowarp/jszip' ;
67
78import {
89 openSpriteLibrary ,
@@ -18,7 +19,6 @@ import TargetPaneComponent from '../components/target-pane/target-pane.jsx';
1819import { getSpriteLibrary } from '../lib/libraries/tw-async-libraries' ;
1920import { handleFileUpload , spriteUpload } from '../lib/file-uploader.js' ;
2021import sharedMessages from '../lib/shared-messages' ;
21- import { emptySprite } from '../lib/empty-assets' ;
2222import { highlightTarget } from '../reducers/targets' ;
2323import { fetchSprite , fetchCode } from '../lib/backpack-api' ;
2424import randomizeSpritePosition from '../lib/randomize-sprite-position' ;
@@ -27,6 +27,52 @@ import log from '../lib/log';
2727import { placeInViewport } from '../lib/backpack/code-payload.js' ;
2828import { getEventXY } from '../lib/touch-utils' ;
2929
30+ const EMPTY_SPRITE_COSTUME_ASSET_ID = 'cd21514d0531fdffb22204e0ec5ed84a' ;
31+ const EMPTY_SPRITE_COSTUME_MD5 = `${ EMPTY_SPRITE_COSTUME_ASSET_ID } .svg` ;
32+ const EMPTY_SPRITE_COSTUME_SVG =
33+ '<svg version="1.1" width="2" height="2" viewBox="-1 -1 2 2" ' +
34+ 'xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">\n' +
35+ ' <!-- Exported by Scratch - http://scratch.mit.edu/ -->\n' +
36+ '</svg>\n' ;
37+
38+ const createOfflinePaintSprite = ( name , costumeName ) => {
39+ const zip = new JSZip ( ) ;
40+ zip . file ( 'sprite.json' , JSON . stringify ( {
41+ isStage : false ,
42+ name,
43+ variables : { } ,
44+ lists : { } ,
45+ broadcasts : { } ,
46+ blocks : { } ,
47+ comments : { } ,
48+ currentCostume : 0 ,
49+ costumes : [
50+ {
51+ assetId : EMPTY_SPRITE_COSTUME_ASSET_ID ,
52+ name : costumeName ,
53+ bitmapResolution : 1 ,
54+ md5ext : EMPTY_SPRITE_COSTUME_MD5 ,
55+ dataFormat : 'svg' ,
56+ rotationCenterX : 0 ,
57+ rotationCenterY : 0
58+ }
59+ ] ,
60+ sounds : [ ] ,
61+ volume : 100 ,
62+ visible : true ,
63+ x : 0 ,
64+ y : 0 ,
65+ size : 100 ,
66+ direction : 90 ,
67+ draggable : false ,
68+ rotationStyle : 'all around'
69+ } ) ) ;
70+ zip . file ( EMPTY_SPRITE_COSTUME_MD5 , EMPTY_SPRITE_COSTUME_SVG ) ;
71+ return zip . generateAsync ( {
72+ type : 'uint8array' ,
73+ compression : 'DEFLATE'
74+ } ) ;
75+ } ;
3076
3177class TargetPane extends React . Component {
3278 constructor ( props ) {
@@ -133,37 +179,20 @@ class TargetPane extends React.Component {
133179 . then ( this . handleActivateBlocksTab ) ;
134180 }
135181 handlePaintSpriteClick ( ) {
136-
137-
138- function base64ToUint8Array ( base64String ) {
139- const padding = '=' . repeat ( ( 4 - base64String . length % 4 ) % 4 ) ;
140- const base64 = ( base64String + padding )
141- . replace ( / \- / g, '+' )
142- . replace ( / _ / g, '/' ) ;
143-
144- const rawData = window . atob ( base64 ) ;
145- const outputArray = new Uint8Array ( rawData . length ) ;
146-
147- for ( let i = 0 ; i < rawData . length ; ++ i ) {
148- outputArray [ i ] = rawData . charCodeAt ( i ) ;
149- }
150- return outputArray ;
151- }
152- /*
153182 const formatMessage = this . props . intl . formatMessage ;
154- const emptyItem = emptySprite (
183+ createOfflinePaintSprite (
155184 formatMessage ( sharedMessages . sprite , { index : 1 } ) ,
156- formatMessage(sharedMessages.pop),
157185 formatMessage ( sharedMessages . costume , { index : 1 } )
158- );
159- */
160- //this.props.vm.addSprite(JSON.stringify(emptyItem)).then(() => {
161- const empt = "UEsDBAoAAAAIAPtDEFvpQGoKHgEAAMUBAAALAAAAc3ByaXRlLmpzb26NkcFKxDAQhl9F5lykbey67XVB8OpeFPEwadISTBtJ0rJrKXgVbz6AePPuOwnrWzjptog3b/NPvpl/ZjKAcluPtYSiQu1kBC02JODw8Xp4/kwggh6tQq6lg2IYI9DK+Tnk1qAo8VdrU97PcWmaRrbLS9lZS2pjnO9C+zgAU0zA7bCYfj+9f729BFOufIMPV9IZ3XllWiiSCAR6vDC2QU+s62vi0DnpLwVpxliOaZ4xZLxapZyvY5mdVVV2ngleSkFwIzK58/9gT4/NrfEYzDc0urTX09h/czeUG+8icKZrRViF4p5GDtskMeG9copuB4W3HR13BwVbRbCHIl1TlXpcOKGsLI+L5kFarGucCudvWXy3fh+ygFqfoA22MP4AUEsDBAoAAAAIAPtDEFtvxALBkgAAAMgAAAAkAAAAMzMzOWEyOTUzYTNiZjYyYmI4MGU1NGZmNTc1ZGJjZWQuc3ZnbY5NDoIwFIT3nOL59v1BVxBgQeIJPIHShjYCJe2zrbcXwaWZzWTmS2aaEEfI87SEFg3RWguRUuLpwp0fxVlKKTYCD6TOk12e/8CyqiqxtwhR+2Dd0mLJS4RkFZkWJYLRdjS022h16l3ePOzCrgBoTozBNa/Ok1bweMNt8HcaDDD4DYYj4LMlrtVLAGNd0XwPdh9QSwECFAAKAAAACAD7QxBb6UBqCh4BAADFAQAACwAAAAAAAAAAAAAAAAAAAAAAc3ByaXRlLmpzb25QSwECFAAKAAAACAD7QxBbb8QCwZIAAADIAAAAJAAAAAAAAAAAAAAAAABHAQAAMzMzOWEyOTUzYTNiZjYyYmI4MGU1NGZmNTc1ZGJjZWQuc3ZnUEsFBgAAAAACAAIAiwAAABsCAAAAAA==" ;
162- this . props . vm . addSprite ( base64ToUint8Array ( empt ) ) . then ( ( ) => {
163- setTimeout ( ( ) => { // Wait for targets update to propagate before tab switching
164- this . props . onActivateTab ( COSTUMES_TAB_INDEX ) ;
186+ )
187+ . then ( sprite3Zip => this . props . vm . addSprite ( sprite3Zip ) )
188+ . then ( ( ) => {
189+ setTimeout ( ( ) => { // Wait for targets update to propagate before tab switching
190+ this . props . onActivateTab ( COSTUMES_TAB_INDEX ) ;
191+ } ) ;
192+ } )
193+ . catch ( err => {
194+ log . error ( err ) ;
165195 } ) ;
166- } ) ;
167196 }
168197 handleActivateBlocksTab ( ) {
169198 this . props . onActivateTab ( BLOCKS_TAB_INDEX ) ;
0 commit comments