Skip to content

Commit

Permalink
When dropping scripts onto the stage selector, place them inside the …
Browse files Browse the repository at this point in the history
…viewport

as it already did when dropping into sprites
  • Loading branch information
GarboMuffin committed Jan 12, 2024
1 parent 421d3d5 commit 90eeb1b
Showing 3 changed files with 46 additions and 36 deletions.
20 changes: 16 additions & 4 deletions src/containers/stage-selector.jsx
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@ import StageSelectorComponent from '../components/stage-selector/stage-selector.

import {getBackdropLibrary} from '../lib/libraries/tw-async-libraries';
import {handleFileUpload, costumeUpload} from '../lib/file-uploader.js';
import {placeInViewport} from '../lib/backpack/code-payload.js';

const dragTypes = [
DragConstants.COSTUME,
@@ -145,8 +146,13 @@ class StageSelector extends React.Component {
}, this.props.id);
} else if (dragInfo.dragType === DragConstants.BACKPACK_CODE) {
fetchCode(dragInfo.payload.bodyUrl)
.then(blocks => {
this.props.vm.shareBlocksToTarget(blocks, this.props.id);
.then(payload => {
const centered = placeInViewport(
payload,
this.props.workspaceMetrics.targets[this.props.id],
this.props.isRtl
);
this.props.vm.shareBlocksToTarget(centered, this.props.id);
this.props.vm.refreshWorkspace();
});
}
@@ -182,17 +188,23 @@ StageSelector.propTypes = {
...StageSelectorComponent.propTypes,
id: PropTypes.string,
intl: intlShape.isRequired,
isRtl: PropTypes.bool,
onCloseImporting: PropTypes.func,
onSelect: PropTypes.func,
onShowImporting: PropTypes.func
onShowImporting: PropTypes.func,
workspaceMetrics: PropTypes.shape({
targets: PropTypes.object
})
};

const mapStateToProps = (state, {asset, id}) => ({
isRtl: state.locales.isRtl,
url: asset && asset.encodeDataURI(),
vm: state.scratchGui.vm,
receivedBlocks: state.scratchGui.hoveredTarget.receivedBlocks &&
state.scratchGui.hoveredTarget.sprite === id,
raised: state.scratchGui.blockDrag
raised: state.scratchGui.blockDrag,
workspaceMetrics: state.scratchGui.workspaceMetrics
});

const mapDispatchToProps = dispatch => ({
34 changes: 3 additions & 31 deletions src/containers/target-pane.jsx
Original file line number Diff line number Diff line change
@@ -14,7 +14,6 @@ import {showStandardAlert, closeAlertWithId} from '../reducers/alerts';
import {setRestore} from '../reducers/restore-deletion';
import DragConstants from '../lib/drag-constants';
import TargetPaneComponent from '../components/target-pane/target-pane.jsx';
import {BLOCKS_DEFAULT_SCALE} from '../lib/layout-constants';
import {getSpriteLibrary} from '../lib/libraries/tw-async-libraries';
import {handleFileUpload, spriteUpload} from '../lib/file-uploader.js';
import sharedMessages from '../lib/shared-messages';
@@ -24,7 +23,7 @@ import {fetchSprite, fetchCode} from '../lib/backpack-api';
import randomizeSpritePosition from '../lib/randomize-sprite-position';
import downloadBlob from '../lib/download-blob';
import log from '../lib/log';
import {findTopBlock} from '../lib/backpack/code-payload.js';
import {placeInViewport} from '../lib/backpack/code-payload.js';

class TargetPane extends React.Component {
constructor (props) {
@@ -169,35 +168,8 @@ class TargetPane extends React.Component {
}
shareBlocks (payload, targetId, optFromTargetId) {
// Position the top-level block based on the scroll position.
const topBlock = findTopBlock(payload);
if (topBlock) {
let metrics;
if (this.props.workspaceMetrics.targets[targetId]) {
metrics = this.props.workspaceMetrics.targets[targetId];
} else {
metrics = {
scrollX: 0,
scrollY: 0,
scale: BLOCKS_DEFAULT_SCALE
};
}

// Determine position of the top-level block based on the target's workspace metrics.
const {scrollX, scrollY, scale} = metrics;
const posY = -scrollY + 30;
let posX;
if (this.props.isRtl) {
posX = scrollX + 30;
} else {
posX = -scrollX + 30;
}

// Actually apply the position!
topBlock.x = posX / scale;
topBlock.y = posY / scale;
}

return this.props.vm.shareBlocksToTarget(payload, targetId, optFromTargetId);
const centered = placeInViewport(payload, this.props.workspaceMetrics.targets[targetId], this.props.isRtl);
return this.props.vm.shareBlocksToTarget(centered, targetId, optFromTargetId);
}
handleDrop (dragInfo) {
const {sprite: targetId} = this.props.hoveredTarget;
28 changes: 27 additions & 1 deletion src/lib/backpack/code-payload.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import blockToImage from './block-to-image';
import createThumbnail from './thumbnail';
import {BLOCKS_DEFAULT_SCALE} from '../layout-constants';
import {Base64} from 'js-base64';

const codePayload = ({blockObjects, topBlockId}) => {
@@ -25,7 +26,32 @@ const findTopBlock = payload => {
return blocks.find(i => i.topLevel);
};

const placeInViewport = (payload, workspaceMetrics, isRtl) => {
const topBlock = findTopBlock(payload);
if (topBlock) {
const {scrollX, scrollY, scale} = workspaceMetrics || {
scrollX: 0,
scrollY: 0,
scale: BLOCKS_DEFAULT_SCALE
};

const posY = -scrollY + 30;
let posX;
if (isRtl) {
posX = scrollX + 30;
} else {
posX = -scrollX + 30;
}

topBlock.x = posX / scale;
topBlock.y = posY / scale;
}

return payload;
};

export {
codePayload as default,
findTopBlock
findTopBlock,
placeInViewport
};

0 comments on commit 90eeb1b

Please sign in to comment.