2018-03-08 15:57:19 -05:00
|
|
|
const injectIntl = require('react-intl').injectIntl;
|
|
|
|
const PropTypes = require('prop-types');
|
2018-09-04 14:29:59 -04:00
|
|
|
const intlShape = require('react-intl').intlShape;
|
2018-10-10 15:14:53 -04:00
|
|
|
const FormattedMessage = require('react-intl').FormattedMessage;
|
|
|
|
|
2018-09-14 16:39:35 -04:00
|
|
|
const MediaQuery = require('react-responsive').default;
|
2018-03-08 15:57:19 -05:00
|
|
|
const React = require('react');
|
2018-04-24 11:00:47 -04:00
|
|
|
const Formsy = require('formsy-react').default;
|
|
|
|
const classNames = require('classnames');
|
2018-03-08 15:57:19 -05:00
|
|
|
|
2018-05-02 15:27:49 -04:00
|
|
|
const GUI = require('scratch-gui').default;
|
|
|
|
const IntlGUI = injectIntl(GUI);
|
|
|
|
|
2018-04-24 11:00:47 -04:00
|
|
|
const decorateText = require('../../lib/decorate-text.jsx');
|
2018-03-08 15:57:19 -05:00
|
|
|
const FlexRow = require('../../components/flex-row/flex-row.jsx');
|
2018-05-24 09:57:06 -04:00
|
|
|
const Button = require('../../components/forms/button.jsx');
|
2018-03-08 15:57:19 -05:00
|
|
|
const Avatar = require('../../components/avatar/avatar.jsx');
|
2018-11-20 11:59:50 -05:00
|
|
|
const Banner = require('./banner.jsx');
|
2018-11-29 14:43:36 -05:00
|
|
|
const ModInfo = require('./mod-info.jsx');
|
2018-05-31 16:49:17 -04:00
|
|
|
const RemixCredit = require('./remix-credit.jsx');
|
|
|
|
const RemixList = require('./remix-list.jsx');
|
2018-09-25 17:16:02 -04:00
|
|
|
const Stats = require('./stats.jsx');
|
2018-05-31 16:49:17 -04:00
|
|
|
const StudioList = require('./studio-list.jsx');
|
2018-09-24 10:58:39 -04:00
|
|
|
const Subactions = require('./subactions.jsx');
|
2018-04-24 11:00:47 -04:00
|
|
|
const InplaceInput = require('../../components/forms/inplace-input.jsx');
|
2018-08-06 11:52:18 -04:00
|
|
|
const TopLevelComment = require('./comment/top-level-comment.jsx');
|
2018-10-04 15:02:59 -04:00
|
|
|
const ComposeComment = require('./comment/compose-comment.jsx');
|
2018-06-13 16:45:48 -04:00
|
|
|
const ExtensionChip = require('./extension-chip.jsx');
|
2018-11-15 16:44:08 -05:00
|
|
|
const thumbnailUrl = require('../../lib/user-thumbnail');
|
2018-05-24 13:47:31 -04:00
|
|
|
|
2018-05-28 15:32:23 -04:00
|
|
|
const projectShape = require('./projectshape.jsx').projectShape;
|
2018-03-08 15:57:19 -05:00
|
|
|
require('./preview.scss');
|
|
|
|
|
2018-09-14 16:39:35 -04:00
|
|
|
const frameless = require('../../lib/frameless');
|
|
|
|
|
2018-08-27 17:11:05 -04:00
|
|
|
// disable enter key submission on formsy input fields; otherwise formsy thinks
|
|
|
|
// we meant to trigger the "See inside" button. Instead, treat these keypresses
|
|
|
|
// as a blur, which will trigger a save.
|
|
|
|
const onKeyPress = e => {
|
|
|
|
if (e.target.type === 'text' && e.which === 13 /* Enter */) {
|
|
|
|
e.preventDefault();
|
|
|
|
e.target.blur();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-06-14 09:26:44 -04:00
|
|
|
const PreviewPresentation = ({
|
2018-11-17 15:13:58 -05:00
|
|
|
addToStudioOpen,
|
2018-07-12 10:01:27 -04:00
|
|
|
assetHost,
|
2018-11-08 13:19:12 -05:00
|
|
|
backpackHost,
|
2018-10-16 10:49:35 -04:00
|
|
|
canAddToStudio,
|
2018-10-17 13:16:41 -04:00
|
|
|
canDeleteComments,
|
2018-11-17 15:13:58 -05:00
|
|
|
canRemix,
|
2018-10-16 10:49:35 -04:00
|
|
|
canReport,
|
2018-10-16 14:02:40 -04:00
|
|
|
canRestoreComments,
|
2018-11-29 10:53:03 -05:00
|
|
|
canSave,
|
2018-11-01 14:19:28 -04:00
|
|
|
canShare,
|
2018-11-08 13:19:12 -05:00
|
|
|
canUseBackpack,
|
2018-10-29 01:05:36 -04:00
|
|
|
cloudHost,
|
2018-08-06 11:52:18 -04:00
|
|
|
comments,
|
2018-06-14 09:26:44 -04:00
|
|
|
editable,
|
2018-06-20 09:28:41 -04:00
|
|
|
extensions,
|
2018-06-14 09:26:44 -04:00
|
|
|
faved,
|
|
|
|
favoriteCount,
|
2018-09-04 14:29:59 -04:00
|
|
|
intl,
|
2018-06-14 09:26:44 -04:00
|
|
|
isFullScreen,
|
|
|
|
isLoggedIn,
|
2018-11-23 01:04:11 -05:00
|
|
|
isNewScratcher,
|
2018-06-14 09:26:44 -04:00
|
|
|
isShared,
|
2018-11-23 01:17:46 -05:00
|
|
|
justShared,
|
2018-06-14 09:26:44 -04:00
|
|
|
loveCount,
|
2018-11-17 15:13:58 -05:00
|
|
|
loved,
|
2018-11-29 14:43:36 -05:00
|
|
|
modInfo,
|
2018-10-24 09:18:45 -04:00
|
|
|
moreCommentsToLoad,
|
2018-10-04 15:02:59 -04:00
|
|
|
onAddComment,
|
2018-11-17 15:13:58 -05:00
|
|
|
onAddToStudioClicked,
|
|
|
|
onAddToStudioClosed,
|
2018-11-21 11:22:57 -05:00
|
|
|
onCopyProjectLink,
|
2018-10-03 13:21:36 -04:00
|
|
|
onDeleteComment,
|
2018-06-14 09:26:44 -04:00
|
|
|
onFavoriteClicked,
|
2018-08-06 11:52:18 -04:00
|
|
|
onLoadMore,
|
2018-06-14 09:26:44 -04:00
|
|
|
onLoveClicked,
|
2018-11-17 15:13:58 -05:00
|
|
|
onRemix,
|
2018-06-14 09:26:44 -04:00
|
|
|
onReportClicked,
|
|
|
|
onReportClose,
|
2018-10-09 11:38:24 -04:00
|
|
|
onReportComment,
|
2018-06-14 09:26:44 -04:00
|
|
|
onReportSubmit,
|
2018-10-16 10:00:38 -04:00
|
|
|
onRestoreComment,
|
2018-11-19 15:47:47 -05:00
|
|
|
onSeeAllComments,
|
2018-06-14 09:26:44 -04:00
|
|
|
onSeeInside,
|
2018-10-16 11:38:26 -04:00
|
|
|
onShare,
|
2018-11-17 15:13:58 -05:00
|
|
|
onToggleComments,
|
|
|
|
onToggleStudio,
|
|
|
|
onUpdate,
|
|
|
|
onUpdateProjectId,
|
|
|
|
originalInfo,
|
|
|
|
parentInfo,
|
|
|
|
projectHost,
|
|
|
|
projectId,
|
|
|
|
projectInfo,
|
|
|
|
projectStudios,
|
|
|
|
remixes,
|
|
|
|
replies,
|
|
|
|
reportOpen,
|
2018-11-29 14:43:36 -05:00
|
|
|
showModInfo,
|
2018-11-17 15:13:58 -05:00
|
|
|
singleCommentId,
|
2018-11-20 11:59:50 -05:00
|
|
|
userOwnsProject,
|
|
|
|
visibilityInfo
|
2018-10-05 09:15:09 -04:00
|
|
|
}) => {
|
|
|
|
const shareDate = ((projectInfo.history && projectInfo.history.shared)) ? projectInfo.history.shared : '';
|
2018-11-29 14:43:36 -05:00
|
|
|
const revisedDate = ((projectInfo.history && projectInfo.history.modified)) ? projectInfo.history.modified : '';
|
2018-11-07 16:32:12 -05:00
|
|
|
|
2018-11-20 11:59:50 -05:00
|
|
|
// Allow embedding html in banner messages coming from the server
|
|
|
|
const embedCensorMessage = message => (
|
|
|
|
// eslint-disable-next-line react/no-danger
|
|
|
|
<span dangerouslySetInnerHTML={{__html: message}} />
|
|
|
|
);
|
|
|
|
|
|
|
|
let banner;
|
2018-11-21 10:36:27 -05:00
|
|
|
if (visibilityInfo.deleted) { // If both censored and deleted, prioritize deleted banner
|
|
|
|
banner = (<Banner
|
|
|
|
className="banner-danger"
|
|
|
|
message={<FormattedMessage id="project.deletedBanner" />}
|
|
|
|
/>);
|
|
|
|
} else if (visibilityInfo.censored) {
|
2018-11-20 11:59:50 -05:00
|
|
|
if (visibilityInfo.reshareable) {
|
|
|
|
banner = (<Banner
|
|
|
|
actionMessage={<FormattedMessage id="project.share.shareButton" />}
|
|
|
|
className="banner-danger"
|
|
|
|
message={embedCensorMessage(visibilityInfo.censorMessage)}
|
|
|
|
onAction={onShare}
|
|
|
|
/>);
|
|
|
|
} else {
|
|
|
|
banner = (<Banner
|
|
|
|
className="banner-danger"
|
|
|
|
message={embedCensorMessage(visibilityInfo.censorMessage)}
|
|
|
|
/>);
|
|
|
|
}
|
2018-11-28 20:58:37 -05:00
|
|
|
} else if (canShare) {
|
|
|
|
if (isShared) {
|
|
|
|
if (justShared) {
|
|
|
|
if (isNewScratcher) {
|
|
|
|
banner = (<Banner
|
|
|
|
className="banner-success"
|
|
|
|
message={<FormattedMessage id="project.share.sharedLong" />}
|
|
|
|
/>);
|
|
|
|
} else {
|
|
|
|
banner = (<Banner
|
|
|
|
className="banner-success"
|
|
|
|
message={<FormattedMessage id="project.share.sharedShort" />}
|
|
|
|
/>);
|
|
|
|
}
|
|
|
|
} // if was shared a while ago, don't show any share banner
|
|
|
|
} else {
|
|
|
|
banner = (<Banner
|
|
|
|
actionMessage={<FormattedMessage id="project.share.shareButton" />}
|
|
|
|
message={<FormattedMessage id="project.share.notShared" />}
|
|
|
|
onAction={onShare}
|
|
|
|
/>);
|
|
|
|
}
|
2018-11-20 11:59:50 -05:00
|
|
|
}
|
|
|
|
|
2018-10-05 09:15:09 -04:00
|
|
|
return (
|
|
|
|
<div className="preview">
|
|
|
|
{ projectInfo && projectInfo.author && projectInfo.author.id && (
|
2018-10-25 10:27:54 -04:00
|
|
|
<React.Fragment>
|
2018-11-20 11:59:50 -05:00
|
|
|
{banner}
|
2018-10-05 09:15:09 -04:00
|
|
|
<div className="inner">
|
|
|
|
<FlexRow className="preview-row force-row">
|
|
|
|
<FlexRow className="project-header">
|
|
|
|
<a href={`/users/${projectInfo.author.username}`}>
|
|
|
|
<Avatar
|
|
|
|
alt={projectInfo.author.username}
|
2018-11-15 16:44:08 -05:00
|
|
|
src={thumbnailUrl(projectInfo.author.id, 48)}
|
2018-10-05 09:15:09 -04:00
|
|
|
/>
|
|
|
|
</a>
|
|
|
|
<div className="title">
|
|
|
|
{editable ?
|
2018-10-25 10:27:54 -04:00
|
|
|
<Formsy onKeyPress={onKeyPress}>
|
|
|
|
<InplaceInput
|
|
|
|
className="project-title"
|
|
|
|
handleUpdate={onUpdate}
|
|
|
|
name="title"
|
|
|
|
validationErrors={{
|
|
|
|
maxLength: intl.formatMessage({
|
|
|
|
id: 'project.titleMaxLength'
|
|
|
|
})
|
|
|
|
}}
|
|
|
|
validations={{
|
|
|
|
maxLength: 100
|
|
|
|
}}
|
|
|
|
value={projectInfo.title}
|
|
|
|
/>
|
|
|
|
</Formsy> :
|
2018-10-05 09:15:09 -04:00
|
|
|
<React.Fragment>
|
|
|
|
<div
|
|
|
|
className="project-title no-edit"
|
|
|
|
title={projectInfo.title}
|
|
|
|
>{projectInfo.title}</div>
|
|
|
|
{'by '}
|
|
|
|
<a href={`/users/${projectInfo.author.username}`}>
|
|
|
|
{projectInfo.author.username}
|
|
|
|
</a>
|
|
|
|
</React.Fragment>
|
|
|
|
}
|
|
|
|
</div>
|
|
|
|
</FlexRow>
|
|
|
|
<MediaQuery minWidth={frameless.mobile}>
|
|
|
|
<div className="project-buttons">
|
2018-11-17 15:13:58 -05:00
|
|
|
{canRemix &&
|
|
|
|
<Button
|
|
|
|
className="button remix-button"
|
|
|
|
onClick={onRemix}
|
|
|
|
>
|
2018-10-24 09:35:30 -04:00
|
|
|
<FormattedMessage id="project.remixButton" />
|
2018-10-05 09:15:09 -04:00
|
|
|
</Button>
|
|
|
|
}
|
|
|
|
<Button
|
|
|
|
className="button see-inside-button"
|
|
|
|
onClick={onSeeInside}
|
|
|
|
>
|
2018-10-24 09:35:30 -04:00
|
|
|
<FormattedMessage id="project.seeInsideButton" />
|
2018-10-05 09:15:09 -04:00
|
|
|
</Button>
|
|
|
|
</div>
|
|
|
|
</MediaQuery>
|
|
|
|
</FlexRow>
|
|
|
|
<FlexRow className="preview-row">
|
|
|
|
<div className="guiPlayer">
|
|
|
|
<IntlGUI
|
|
|
|
isPlayerOnly
|
|
|
|
assetHost={assetHost}
|
2018-11-08 13:19:12 -05:00
|
|
|
backpackHost={backpackHost}
|
|
|
|
backpackVisible={canUseBackpack}
|
2018-10-05 09:15:09 -04:00
|
|
|
basePath="/"
|
2018-11-17 15:13:58 -05:00
|
|
|
canRemix={canRemix}
|
2018-11-29 10:53:03 -05:00
|
|
|
canSave={canSave}
|
2018-10-05 09:15:09 -04:00
|
|
|
className="guiPlayer"
|
2018-10-29 01:05:36 -04:00
|
|
|
cloudHost={cloudHost}
|
2018-10-05 09:15:09 -04:00
|
|
|
isFullScreen={isFullScreen}
|
|
|
|
previewInfoVisible="false"
|
|
|
|
projectHost={projectHost}
|
|
|
|
projectId={projectId}
|
2018-11-17 15:13:58 -05:00
|
|
|
onUpdateProjectId={onUpdateProjectId}
|
2018-06-14 09:26:44 -04:00
|
|
|
/>
|
|
|
|
</div>
|
2018-10-05 09:15:09 -04:00
|
|
|
<MediaQuery maxWidth={frameless.tablet - 1}>
|
|
|
|
<FlexRow className="preview-row force-center">
|
|
|
|
<Stats
|
|
|
|
faved={faved}
|
|
|
|
favoriteCount={favoriteCount}
|
|
|
|
loveCount={loveCount}
|
|
|
|
loved={loved}
|
|
|
|
projectInfo={projectInfo}
|
|
|
|
onFavoriteClicked={onFavoriteClicked}
|
|
|
|
onLoveClicked={onLoveClicked}
|
|
|
|
/>
|
|
|
|
<Subactions
|
|
|
|
addToStudioOpen={addToStudioOpen}
|
2018-10-16 10:49:35 -04:00
|
|
|
canReport={canReport}
|
2018-10-05 09:15:09 -04:00
|
|
|
projectInfo={projectInfo}
|
|
|
|
reportOpen={reportOpen}
|
|
|
|
shareDate={shareDate}
|
|
|
|
onAddToStudioClicked={onAddToStudioClicked}
|
|
|
|
onAddToStudioClosed={onAddToStudioClosed}
|
2018-11-21 11:22:57 -05:00
|
|
|
onCopyProjectLink={onCopyProjectLink}
|
2018-10-05 09:15:09 -04:00
|
|
|
onReportClicked={onReportClicked}
|
|
|
|
onReportClose={onReportClose}
|
|
|
|
onReportSubmit={onReportSubmit}
|
|
|
|
onToggleStudio={onToggleStudio}
|
|
|
|
/>
|
|
|
|
</FlexRow>
|
|
|
|
</MediaQuery>
|
|
|
|
<FlexRow className="project-notes">
|
|
|
|
<RemixCredit projectInfo={parentInfo} />
|
|
|
|
<RemixCredit projectInfo={originalInfo} />
|
|
|
|
{/* eslint-disable max-len */}
|
|
|
|
<MediaQuery maxWidth={frameless.tablet - 1}>
|
|
|
|
<FlexRow className="preview-row">
|
|
|
|
<FlexRow className="extension-list">
|
|
|
|
{extensions && extensions.map(extension => (
|
|
|
|
<ExtensionChip
|
|
|
|
extensionL10n={extension.l10nId}
|
|
|
|
extensionName={extension.name}
|
|
|
|
hasStatus={extension.hasStatus}
|
|
|
|
iconURI={extension.icon && `/svgs/project/${extension.icon}`}
|
|
|
|
key={extension.name || extension.l10nId}
|
|
|
|
/>
|
|
|
|
))}
|
|
|
|
</FlexRow>
|
|
|
|
</FlexRow>
|
|
|
|
</MediaQuery>
|
|
|
|
<FlexRow className="description-block">
|
|
|
|
<div className="project-textlabel">
|
2018-10-24 09:35:30 -04:00
|
|
|
<FormattedMessage id="project.instructionsLabel" />
|
2018-10-05 09:15:09 -04:00
|
|
|
</div>
|
|
|
|
{editable ?
|
2018-10-25 11:38:27 -04:00
|
|
|
<Formsy
|
|
|
|
className="project-description-form"
|
|
|
|
onKeyPress={onKeyPress}
|
|
|
|
>
|
2018-10-25 10:27:54 -04:00
|
|
|
<InplaceInput
|
|
|
|
className={classNames(
|
|
|
|
'project-description-edit',
|
|
|
|
{remixes: parentInfo && parentInfo.author}
|
|
|
|
)}
|
|
|
|
handleUpdate={onUpdate}
|
|
|
|
name="instructions"
|
|
|
|
placeholder="Tell people how to use your project (such as which keys to press)."
|
|
|
|
type="textarea"
|
|
|
|
validationErrors={{
|
|
|
|
maxLength: 'Sorry description is too long'
|
|
|
|
// maxLength: props.intl.formatMessage({
|
|
|
|
// id: 'project.descriptionMaxLength'
|
|
|
|
// })
|
|
|
|
}}
|
|
|
|
validations={{
|
|
|
|
// TODO: actual 5000
|
|
|
|
maxLength: 1000
|
|
|
|
}}
|
|
|
|
value={projectInfo.instructions}
|
|
|
|
/>
|
|
|
|
</Formsy> :
|
2018-10-05 09:15:09 -04:00
|
|
|
<div className="project-description">
|
2018-10-24 11:25:11 -04:00
|
|
|
{decorateText(projectInfo.instructions, {
|
|
|
|
usernames: true,
|
|
|
|
hashtags: true,
|
|
|
|
scratchLinks: false
|
|
|
|
})}
|
2018-10-05 09:15:09 -04:00
|
|
|
</div>
|
|
|
|
}
|
|
|
|
</FlexRow>
|
|
|
|
<FlexRow className="description-block">
|
|
|
|
<div className="project-textlabel">
|
2018-10-24 09:35:30 -04:00
|
|
|
<FormattedMessage id="project.notesAndCreditsLabel" />
|
2018-10-05 09:15:09 -04:00
|
|
|
</div>
|
|
|
|
{editable ?
|
2018-10-25 11:38:27 -04:00
|
|
|
<Formsy
|
|
|
|
className="project-description-form"
|
|
|
|
onKeyPress={onKeyPress}
|
|
|
|
>
|
2018-10-25 10:27:54 -04:00
|
|
|
<InplaceInput
|
|
|
|
className={classNames(
|
|
|
|
'project-description-edit',
|
|
|
|
'last',
|
|
|
|
{remixes: parentInfo && parentInfo.author}
|
|
|
|
)}
|
|
|
|
handleUpdate={onUpdate}
|
|
|
|
name="description"
|
|
|
|
placeholder="How did you make this project? Did you use ideas scripts or artwork from other people? Thank them here."
|
|
|
|
type="textarea"
|
|
|
|
validationErrors={{
|
|
|
|
maxLength: 'Sorry description is too long'
|
|
|
|
// maxLength: props.intl.formatMessage({
|
|
|
|
// id: 'project.descriptionMaxLength'
|
|
|
|
// })
|
|
|
|
}}
|
|
|
|
validations={{
|
|
|
|
// TODO: actual 5000
|
|
|
|
maxLength: 1000
|
|
|
|
}}
|
|
|
|
value={projectInfo.description}
|
|
|
|
/>
|
|
|
|
</Formsy> :
|
2018-10-05 09:15:09 -04:00
|
|
|
<div className="project-description last">
|
2018-10-24 11:25:11 -04:00
|
|
|
{decorateText(projectInfo.description, {
|
|
|
|
usernames: true,
|
|
|
|
hashtags: true,
|
|
|
|
scratchLinks: false
|
|
|
|
})}
|
2018-10-05 09:15:09 -04:00
|
|
|
</div>
|
|
|
|
}
|
|
|
|
</FlexRow>
|
|
|
|
{/* eslint-enable max-len */}
|
|
|
|
</FlexRow>
|
2018-06-14 09:26:44 -04:00
|
|
|
</FlexRow>
|
2018-10-05 09:15:09 -04:00
|
|
|
<MediaQuery minWidth={frameless.tablet}>
|
|
|
|
<FlexRow className="preview-row">
|
2018-09-25 17:16:02 -04:00
|
|
|
<Stats
|
|
|
|
faved={faved}
|
|
|
|
favoriteCount={favoriteCount}
|
|
|
|
loveCount={loveCount}
|
|
|
|
loved={loved}
|
|
|
|
projectInfo={projectInfo}
|
|
|
|
onFavoriteClicked={onFavoriteClicked}
|
|
|
|
onLoveClicked={onLoveClicked}
|
|
|
|
/>
|
|
|
|
<Subactions
|
|
|
|
addToStudioOpen={addToStudioOpen}
|
2018-10-16 10:49:35 -04:00
|
|
|
canAddToStudio={canAddToStudio}
|
|
|
|
canReport={canReport}
|
2018-09-25 17:16:02 -04:00
|
|
|
projectInfo={projectInfo}
|
|
|
|
reportOpen={reportOpen}
|
2018-10-05 09:15:09 -04:00
|
|
|
shareDate={shareDate}
|
2018-09-25 17:16:02 -04:00
|
|
|
onAddToStudioClicked={onAddToStudioClicked}
|
|
|
|
onAddToStudioClosed={onAddToStudioClosed}
|
2018-11-21 11:22:57 -05:00
|
|
|
onCopyProjectLink={onCopyProjectLink}
|
2018-09-25 17:16:02 -04:00
|
|
|
onReportClicked={onReportClicked}
|
|
|
|
onReportClose={onReportClose}
|
|
|
|
onReportSubmit={onReportSubmit}
|
|
|
|
onToggleStudio={onToggleStudio}
|
|
|
|
/>
|
|
|
|
</FlexRow>
|
|
|
|
</MediaQuery>
|
2018-11-29 14:43:36 -05:00
|
|
|
{showModInfo &&
|
|
|
|
<React.Fragment>
|
|
|
|
<div className="project-textlabel">
|
|
|
|
<FormattedMessage id="project.moderationInfoLabel" />
|
|
|
|
</div>
|
|
|
|
<ModInfo
|
|
|
|
revisedDate={revisedDate}
|
|
|
|
scripts={modInfo.scripts}
|
|
|
|
sprites={modInfo.sprites}
|
|
|
|
/>
|
|
|
|
|
|
|
|
</React.Fragment>
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-10-05 09:15:09 -04:00
|
|
|
<MediaQuery minWidth={frameless.tablet}>
|
|
|
|
<FlexRow className="preview-row">
|
|
|
|
<FlexRow className="extension-list">
|
|
|
|
{extensions && extensions.map(extension => (
|
|
|
|
<ExtensionChip
|
|
|
|
extensionL10n={extension.l10nId}
|
|
|
|
extensionName={extension.name}
|
|
|
|
hasStatus={extension.hasStatus}
|
|
|
|
iconURI={extension.icon && `/svgs/project/${extension.icon}`}
|
|
|
|
key={extension.name || extension.l10nId}
|
2018-09-24 11:50:44 -04:00
|
|
|
/>
|
|
|
|
))}
|
2018-10-05 09:15:09 -04:00
|
|
|
</FlexRow>
|
|
|
|
</FlexRow>
|
|
|
|
</MediaQuery>
|
|
|
|
</div>
|
|
|
|
<div className="project-lower-container">
|
|
|
|
<div className="inner">
|
|
|
|
<FlexRow className="preview-row">
|
|
|
|
<div className="comments-container">
|
|
|
|
<FlexRow className="comments-header">
|
2018-10-24 09:35:30 -04:00
|
|
|
<h4><FormattedMessage id="project.comments.header" /></h4>
|
2018-10-10 15:14:53 -04:00
|
|
|
{userOwnsProject ? (
|
|
|
|
<div>
|
|
|
|
<label>
|
|
|
|
<input
|
|
|
|
checked={!projectInfo.comments_allowed}
|
|
|
|
className="comments-allowed-input"
|
|
|
|
type="checkbox"
|
|
|
|
onChange={onToggleComments}
|
|
|
|
/>
|
2018-10-24 09:35:30 -04:00
|
|
|
<FormattedMessage id="project.comments.turnOff" />
|
2018-10-10 15:14:53 -04:00
|
|
|
</label>
|
|
|
|
</div>
|
|
|
|
) : null}
|
2018-10-05 09:15:09 -04:00
|
|
|
</FlexRow>
|
2018-10-04 15:02:59 -04:00
|
|
|
|
2018-11-19 15:47:47 -05:00
|
|
|
{/* Do not show the top-level comment form in single comment mode */}
|
|
|
|
{!singleCommentId && (
|
|
|
|
<FlexRow className="comments-root-reply">
|
|
|
|
{projectInfo.comments_allowed ? (
|
|
|
|
isLoggedIn ? (
|
|
|
|
<ComposeComment
|
|
|
|
projectId={projectId}
|
|
|
|
onAddComment={onAddComment}
|
|
|
|
/>
|
|
|
|
) : (
|
|
|
|
/* TODO add box for signing in to leave a comment */
|
|
|
|
null
|
|
|
|
)
|
2018-10-10 15:14:53 -04:00
|
|
|
) : (
|
2018-11-19 15:47:47 -05:00
|
|
|
<div className="comments-turned-off">
|
|
|
|
<FormattedMessage id="project.comments.turnedOff" />
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
</FlexRow>
|
|
|
|
)}
|
2018-10-04 15:02:59 -04:00
|
|
|
|
2018-10-05 09:15:09 -04:00
|
|
|
<FlexRow className="comments-list">
|
|
|
|
{comments.map(comment => (
|
|
|
|
<TopLevelComment
|
|
|
|
author={comment.author}
|
2018-10-17 13:16:41 -04:00
|
|
|
canDelete={canDeleteComments}
|
2018-10-11 11:54:58 -04:00
|
|
|
canReply={isLoggedIn && projectInfo.comments_allowed}
|
2018-10-17 13:19:46 -04:00
|
|
|
canReport={isLoggedIn}
|
2018-10-16 14:02:40 -04:00
|
|
|
canRestore={canRestoreComments}
|
2018-10-05 09:15:09 -04:00
|
|
|
content={comment.content}
|
|
|
|
datetimeCreated={comment.datetime_created}
|
2018-10-24 10:23:28 -04:00
|
|
|
defaultExpanded={!!singleCommentId}
|
|
|
|
highlightedCommentId={singleCommentId}
|
2018-10-05 09:15:09 -04:00
|
|
|
id={comment.id}
|
|
|
|
key={comment.id}
|
|
|
|
parentId={comment.parent_id}
|
|
|
|
projectId={projectId}
|
|
|
|
replies={replies && replies[comment.id] ? replies[comment.id] : []}
|
2018-10-16 09:10:29 -04:00
|
|
|
visibility={comment.visibility}
|
2018-10-04 15:02:59 -04:00
|
|
|
onAddComment={onAddComment}
|
2018-10-05 09:15:09 -04:00
|
|
|
onDelete={onDeleteComment}
|
2018-10-09 11:38:24 -04:00
|
|
|
onReport={onReportComment}
|
2018-10-16 10:00:38 -04:00
|
|
|
onRestore={onRestoreComment}
|
2018-10-05 09:15:09 -04:00
|
|
|
/>
|
|
|
|
))}
|
2018-10-24 09:18:45 -04:00
|
|
|
{moreCommentsToLoad &&
|
2018-09-24 10:58:39 -04:00
|
|
|
<Button
|
|
|
|
className="button load-more-button"
|
|
|
|
onClick={onLoadMore}
|
|
|
|
>
|
2018-10-23 11:37:59 -04:00
|
|
|
<FormattedMessage id="general.loadMore" />
|
2018-09-24 10:58:39 -04:00
|
|
|
</Button>
|
2018-10-05 09:15:09 -04:00
|
|
|
}
|
2018-11-19 15:47:47 -05:00
|
|
|
{!!singleCommentId &&
|
|
|
|
<Button
|
|
|
|
className="button load-more-button"
|
|
|
|
onClick={onSeeAllComments}
|
|
|
|
>
|
|
|
|
<FormattedMessage id="general.seeAllComments" />
|
|
|
|
</Button>
|
|
|
|
}
|
2018-10-05 09:15:09 -04:00
|
|
|
</FlexRow>
|
|
|
|
</div>
|
|
|
|
<FlexRow className="column">
|
|
|
|
<RemixList remixes={remixes} />
|
|
|
|
<StudioList studios={projectStudios} />
|
2018-09-24 11:50:44 -04:00
|
|
|
</FlexRow>
|
2018-04-24 11:00:47 -04:00
|
|
|
</FlexRow>
|
2018-10-05 09:15:09 -04:00
|
|
|
</div>
|
2018-08-06 11:52:18 -04:00
|
|
|
</div>
|
2018-10-25 10:27:54 -04:00
|
|
|
</React.Fragment>
|
2018-10-05 09:15:09 -04:00
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
};
|
2018-03-08 15:57:19 -05:00
|
|
|
|
2018-03-15 17:40:16 -04:00
|
|
|
PreviewPresentation.propTypes = {
|
2018-07-25 15:08:12 -04:00
|
|
|
addToStudioOpen: PropTypes.bool,
|
2018-07-12 10:01:27 -04:00
|
|
|
assetHost: PropTypes.string,
|
2018-11-08 13:19:12 -05:00
|
|
|
backpackHost: PropTypes.string,
|
2018-10-16 10:49:35 -04:00
|
|
|
canAddToStudio: PropTypes.bool,
|
2018-10-17 13:16:41 -04:00
|
|
|
canDeleteComments: PropTypes.bool,
|
2018-11-17 15:13:58 -05:00
|
|
|
canRemix: PropTypes.bool,
|
2018-10-16 10:49:35 -04:00
|
|
|
canReport: PropTypes.bool,
|
2018-10-16 14:02:40 -04:00
|
|
|
canRestoreComments: PropTypes.bool,
|
2018-11-29 10:53:03 -05:00
|
|
|
canSave: PropTypes.bool,
|
2018-11-01 14:19:28 -04:00
|
|
|
canShare: PropTypes.bool,
|
2018-11-08 13:19:12 -05:00
|
|
|
canUseBackpack: PropTypes.bool,
|
2018-10-29 01:05:36 -04:00
|
|
|
cloudHost: PropTypes.string,
|
2018-08-06 11:52:18 -04:00
|
|
|
comments: PropTypes.arrayOf(PropTypes.object),
|
2018-05-24 09:57:06 -04:00
|
|
|
editable: PropTypes.bool,
|
2018-06-20 09:28:41 -04:00
|
|
|
extensions: PropTypes.arrayOf(PropTypes.object),
|
2018-05-24 09:57:06 -04:00
|
|
|
faved: PropTypes.bool,
|
|
|
|
favoriteCount: PropTypes.number,
|
2018-09-04 14:29:59 -04:00
|
|
|
intl: intlShape,
|
2018-05-24 09:57:06 -04:00
|
|
|
isFullScreen: PropTypes.bool,
|
2018-06-01 14:25:45 -04:00
|
|
|
isLoggedIn: PropTypes.bool,
|
2018-11-23 01:04:11 -05:00
|
|
|
isNewScratcher: PropTypes.bool,
|
2018-05-31 16:49:17 -04:00
|
|
|
isShared: PropTypes.bool,
|
2018-11-23 01:17:46 -05:00
|
|
|
justShared: PropTypes.bool,
|
2018-05-24 09:57:06 -04:00
|
|
|
loveCount: PropTypes.number,
|
|
|
|
loved: PropTypes.bool,
|
2018-11-29 14:43:36 -05:00
|
|
|
modInfo: PropTypes.shape({
|
|
|
|
scripts: PropTypes.number,
|
|
|
|
sprites: PropTypes.number
|
|
|
|
}),
|
2018-10-24 09:18:45 -04:00
|
|
|
moreCommentsToLoad: PropTypes.bool,
|
2018-10-04 15:02:59 -04:00
|
|
|
onAddComment: PropTypes.func,
|
2018-07-25 15:08:12 -04:00
|
|
|
onAddToStudioClicked: PropTypes.func,
|
|
|
|
onAddToStudioClosed: PropTypes.func,
|
2018-11-21 11:22:57 -05:00
|
|
|
onCopyProjectLink: PropTypes.func,
|
2018-10-03 13:21:36 -04:00
|
|
|
onDeleteComment: PropTypes.func,
|
2018-05-24 09:57:06 -04:00
|
|
|
onFavoriteClicked: PropTypes.func,
|
2018-08-06 11:52:18 -04:00
|
|
|
onLoadMore: PropTypes.func,
|
2018-05-24 09:57:06 -04:00
|
|
|
onLoveClicked: PropTypes.func,
|
2018-11-17 15:13:58 -05:00
|
|
|
onRemix: PropTypes.func,
|
2018-05-31 16:49:17 -04:00
|
|
|
onReportClicked: PropTypes.func.isRequired,
|
|
|
|
onReportClose: PropTypes.func.isRequired,
|
2018-10-09 11:38:24 -04:00
|
|
|
onReportComment: PropTypes.func.isRequired,
|
2018-05-31 16:49:17 -04:00
|
|
|
onReportSubmit: PropTypes.func.isRequired,
|
2018-10-16 10:00:38 -04:00
|
|
|
onRestoreComment: PropTypes.func,
|
2018-11-19 15:47:47 -05:00
|
|
|
onSeeAllComments: PropTypes.func,
|
2018-05-24 09:57:06 -04:00
|
|
|
onSeeInside: PropTypes.func,
|
2018-10-16 11:38:26 -04:00
|
|
|
onShare: PropTypes.func,
|
2018-10-10 15:14:53 -04:00
|
|
|
onToggleComments: PropTypes.func,
|
2018-07-25 15:08:12 -04:00
|
|
|
onToggleStudio: PropTypes.func,
|
2018-05-24 09:57:06 -04:00
|
|
|
onUpdate: PropTypes.func,
|
2018-11-17 15:13:58 -05:00
|
|
|
onUpdateProjectId: PropTypes.func,
|
2018-05-28 15:32:23 -04:00
|
|
|
originalInfo: projectShape,
|
|
|
|
parentInfo: projectShape,
|
2018-07-12 10:01:27 -04:00
|
|
|
projectHost: PropTypes.string,
|
2018-05-24 16:23:07 -04:00
|
|
|
projectId: PropTypes.string,
|
2018-05-28 15:32:23 -04:00
|
|
|
projectInfo: projectShape,
|
2018-07-25 15:08:12 -04:00
|
|
|
projectStudios: PropTypes.arrayOf(PropTypes.object),
|
2018-04-24 11:00:47 -04:00
|
|
|
remixes: PropTypes.arrayOf(PropTypes.object),
|
2018-08-06 11:52:18 -04:00
|
|
|
replies: PropTypes.objectOf(PropTypes.array),
|
2018-08-02 17:54:43 -04:00
|
|
|
reportOpen: PropTypes.bool,
|
2018-11-29 14:43:36 -05:00
|
|
|
showModInfo: PropTypes.bool,
|
2018-10-24 10:43:21 -04:00
|
|
|
singleCommentId: PropTypes.oneOfType([PropTypes.number, PropTypes.bool]),
|
2018-11-20 11:59:50 -05:00
|
|
|
userOwnsProject: PropTypes.bool,
|
|
|
|
visibilityInfo: PropTypes.shape({
|
|
|
|
censored: PropTypes.bool,
|
|
|
|
censorMessage: PropTypes.string,
|
|
|
|
deleted: PropTypes.bool,
|
|
|
|
reshareable: PropTypes.bool
|
|
|
|
})
|
2018-03-15 17:40:16 -04:00
|
|
|
};
|
2018-03-08 15:57:19 -05:00
|
|
|
|
2018-03-15 17:40:16 -04:00
|
|
|
module.exports = injectIntl(PreviewPresentation);
|