@@ -156,10 +156,43 @@ class TargetPane extends React.Component {
156
156
}
157
157
handleBlockDragEnd ( blocks ) {
158
158
if ( this . props . hoveredTarget . sprite && this . props . hoveredTarget . sprite !== this . props . editingTarget ) {
159
- this . props . vm . shareBlocksToTarget ( blocks , this . props . hoveredTarget . sprite , this . props . editingTarget ) ;
159
+ this . shareBlocks ( blocks , this . props . hoveredTarget . sprite , this . props . editingTarget ) ;
160
160
this . props . onReceivedBlocks ( true ) ;
161
161
}
162
162
}
163
+ shareBlocks ( blocks , targetId , optFromTargetId ) {
164
+ // Position the top-level block based on the scroll position.
165
+ const topBlock = blocks . find ( block => block . topLevel ) ;
166
+ if ( topBlock ) {
167
+ let metrics ;
168
+ if ( this . props . workspaceMetrics . targets [ targetId ] ) {
169
+ metrics = this . props . workspaceMetrics . targets [ targetId ] ;
170
+ } else {
171
+ metrics = {
172
+ scrollX : 0 ,
173
+ scrollY : 0 ,
174
+ scale : 0.675 // TODO: Define this in a constant somewhere.
175
+ } ;
176
+ }
177
+
178
+ // Determine position of the top-level block based on the target's workspace metrics.
179
+ const { scrollX, scrollY, scale} = metrics ;
180
+ const { width} = this . props . workspaceMetrics . dimensions ;
181
+ const posY = - scrollY + 30 ;
182
+ let posX = - scrollX ;
183
+ if ( this . props . isRtl ) {
184
+ posX += width - 30 ;
185
+ } else {
186
+ posX += 30 ;
187
+ }
188
+
189
+ // Actually apply the position!
190
+ topBlock . x = posX / scale ;
191
+ topBlock . y = posY / scale ;
192
+ }
193
+
194
+ this . props . vm . shareBlocksToTarget ( blocks , targetId , optFromTargetId ) ;
195
+ }
163
196
handleDrop ( dragInfo ) {
164
197
const { sprite : targetId } = this . props . hoveredTarget ;
165
198
if ( dragInfo . dragType === DragConstants . SPRITE ) {
@@ -196,22 +229,25 @@ class TargetPane extends React.Component {
196
229
} else if ( dragInfo . dragType === DragConstants . BACKPACK_CODE ) {
197
230
fetchCode ( dragInfo . payload . bodyUrl )
198
231
. then ( blocks => {
199
- this . props . vm . shareBlocksToTarget ( blocks , targetId ) ;
232
+ this . shareBlocks ( blocks , targetId ) ;
200
233
this . props . vm . refreshWorkspace ( ) ;
201
234
} ) ;
202
235
}
203
236
}
204
237
}
205
238
render ( ) {
239
+ /* eslint-disable no-unused-vars */
206
240
const {
207
- onActivateTab, // eslint-disable-line no-unused-vars
208
- onReceivedBlocks, // eslint-disable-line no-unused-vars
209
- onHighlightTarget, // eslint-disable-line no-unused-vars
210
- dispatchUpdateRestore, // eslint-disable-line no-unused-vars
211
- onShowImporting, // eslint-disable-line no-unused-vars
212
- onCloseImporting, // eslint-disable-line no-unused-vars
241
+ dispatchUpdateRestore,
242
+ onActivateTab,
243
+ onCloseImporting,
244
+ onHighlightTarget,
245
+ onReceivedBlocks,
246
+ onShowImporting,
247
+ workspaceMetrics,
213
248
...componentProps
214
249
} = this . props ;
250
+ /* eslint-enable no-unused-vars */
215
251
return (
216
252
< TargetPaneComponent
217
253
{ ...componentProps }
@@ -254,10 +290,12 @@ TargetPane.propTypes = {
254
290
const mapStateToProps = state => ( {
255
291
editingTarget : state . scratchGui . targets . editingTarget ,
256
292
hoveredTarget : state . scratchGui . hoveredTarget ,
293
+ isRtl : state . locales . isRtl ,
294
+ spriteLibraryVisible : state . scratchGui . modals . spriteLibrary ,
257
295
sprites : state . scratchGui . targets . sprites ,
258
296
stage : state . scratchGui . targets . stage ,
259
297
raiseSprites : state . scratchGui . blockDrag ,
260
- spriteLibraryVisible : state . scratchGui . modals . spriteLibrary
298
+ workspaceMetrics : state . scratchGui . workspaceMetrics
261
299
} ) ;
262
300
263
301
const mapDispatchToProps = dispatch => ( {
0 commit comments