soiz1's picture
Update src/components/menu-bar/share-button.jsx
c4817fb verified
import classNames from 'classnames';
import { connect } from 'react-redux';
import { FormattedMessage, injectIntl } from 'react-intl';
import PropTypes from 'prop-types';
import React from 'react';
import bindAll from 'lodash.bindall';
import Button from '../button/button.jsx';
import loadingIcon from './share-loading.svg';
import styles from './share-button.css';
const getProjectThumbnail = () => new Promise(resolve => {
window.vm.renderer.requestSnapshot(uri => {
resolve(uri);
});
});
const getProjectUri = () => new Promise(resolve => {
window.vm.saveProjectSb3().then(blob => new Promise(resolve => {
const reader = new FileReader();
reader.onload = element => {
resolve(element.target.result);
};
reader.readAsDataURL(blob);
}))
.then(resolve);
});
//サーバーダウンチェック
const isUploadAvailable = async () => {
let res = null;
try {
res = await fetch('https://projects.penguinmod.com/api/v1/projects/canuploadprojects').then(res => res.json());
} catch {
// failed to fetch entirely
return false;
}
return res.canUpload;
};
class ShareButton extends React.Component {
constructor(props) {
super(props);
bindAll(this, [
'handleMessageEvent',
'wrapperEventHandler',
'onUploadProject'
]);
this.state = {
loading: false,
imageUri: ''
};
}
componentDidMount() {
window.addEventListener('message', this.wrapperEventHandler);
}
componentWillUnmount() {
window.removeEventListener('message', this.wrapperEventHandler);
}
wrapperEventHandler(e) {
this.handleMessageEvent(e);
}
async handleMessageEvent(e) {
if (!e.origin.startsWith(`https://penguinmod.com`)) {
return;
}
if (!e.data.p4) {
return;
}
const packagerData = e.data.p4;
if (packagerData.type !== 'validate') {
return;
}
const imageUri = this.state.imageUri;
e.source.postMessage({
p4: {
type: 'image',
uri: imageUri
}
}, e.origin);
const projectUri = await getProjectUri();
e.source.postMessage({
p4: {
type: 'project',
uri: projectUri
}
}, e.origin);
e.source.postMessage({
p4: {
type: 'finished'
}
}, e.origin);
}
async onUploadProject() {
if (this.state.loading) return;
if (!window.vm) return;
if (!window.vm.runtime) return;
if (!window.vm.renderer) return;
// get the project thumbnail
await new Promise((resolve) => {
getProjectThumbnail().then(dataUrl => {
this.setState({
imageUri: dataUrl
});
resolve();
});
window.vm.renderer.draw(); // force the callback to run
setTimeout(() => {
window.vm.renderer.draw(); // force the callback to run
}, 50);
setTimeout(() => {
window.vm.renderer.draw(); // force the callback to run
}, 100);
});
this.setState({
loading: true
});
isUploadAvailable().then(available => {
this.setState({
loading: false
});
if (!available) {
// error?
console.warn('Project Server did not respond. Uploading is not available.');
alert('Uploading is currently unavailable. Please wait for the server to be restored.');
return;
}
const isEdit = this.props.usernameLoggedIn
&& this.props.extraProjectInfo?.author === this.props.username;
let editPiece = '';
let remixPiece = '';
const id = location.hash.replace('#', '');
if (this.props.extraProjectInfo?.isRemix) {
remixPiece = `&remix=${id}`;
}
let targetPage = 'upload';
if (isEdit) {
targetPage = 'edit';
editPiece = `&id=${id}`;
}
const url = location.origin;
//最終的なURL
window.open(`https://penguinmod.com/${targetPage}?name=${this.props.projectTitle}${editPiece}${remixPiece}&external=${url}`, '_blank');
});
}
render() {
const isRemix = this.props.extraProjectInfo?.isRemix;
const isEdit = this.props.usernameLoggedIn
&& this.props.extraProjectInfo?.author === this.props.username;
return (
<Button
className={classNames(
this.props.className,
styles.shareButton,
{ [styles.shareButtonIsShared]: this.props.isShared },
{ [styles.disabled]: this.state.loading },
)}
onClick={this.onUploadProject}
hidden={true}
>
<div className={classNames(styles.shareContent)}>
{isEdit ? <FormattedMessage
defaultMessage="Upload Edits"
description="Text for uploading edits for projects on PenguinMod"
id="gui.menuBar.pmedit"
/> :
(isRemix ?
<FormattedMessage
defaultMessage="Remix"
description="Menu bar item for remixing"
id="gui.menuBar.remix"
/> :
<FormattedMessage
defaultMessage="Upload"
description="Label for project share button"
id="gui.menuBar.pmshare"
/>)}
{this.state.loading ? (
<img
className={classNames(styles.icon)}
draggable={false}
src={loadingIcon}
height={20}
width={20}
/>
) : null}
</div>
</Button>
);
}
}
ShareButton.propTypes = {
className: PropTypes.string,
isShared: PropTypes.bool,
projectTitle: PropTypes.string,
extraProjectInfo: PropTypes.shape({
accepted: PropTypes.bool,
isRemix: PropTypes.bool,
remixId: PropTypes.number,
tooLarge: PropTypes.bool,
author: PropTypes.string,
releaseDate: PropTypes.shape(Date),
isUpdated: PropTypes.bool
}),
username: PropTypes.string,
usernameLoggedIn: PropTypes.bool
};
const mapStateToProps = state => ({
projectTitle: state.scratchGui.projectTitle,
extraProjectInfo: state.scratchGui.tw.extraProjectInfo,
username: state.scratchGui.tw.username,
usernameLoggedIn: state.scratchGui.tw.usernameLoggedIn
});
// eslint-disable-next-line no-unused-vars
const mapDispatchToProps = dispatch => ({});
export default injectIntl(connect(
mapStateToProps,
mapDispatchToProps
)(ShareButton));