scratch-www/src/views/preview/presentation.jsx

754 lines
38 KiB
React
Raw Normal View History

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;
const MediaQuery = require('react-responsive').default;
const React = require('react');
const Formsy = require('formsy-react').default;
const classNames = require('classnames');
const GUI = require('scratch-gui').default;
const IntlGUI = injectIntl(GUI);
const AdminPanel = require('../../components/adminpanel/adminpanel.jsx');
const decorateText = require('../../lib/decorate-text.jsx');
const FlexRow = require('../../components/flex-row/flex-row.jsx');
const Button = require('../../components/forms/button.jsx');
const Avatar = require('../../components/avatar/avatar.jsx');
const Banner = require('./banner.jsx');
const CensoredMessage = require('./censored-message.jsx');
const ModInfo = require('./mod-info.jsx');
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');
const StudioList = require('./studio-list.jsx');
2018-09-24 10:58:39 -04:00
const Subactions = require('./subactions.jsx');
const InplaceInput = require('../../components/forms/inplace-input.jsx');
const ToggleSlider = require('../../components/forms/toggle-slider.jsx');
Initial implementation for displaying comments on project page (#1997) * Create Comment component, start styling it * Restructure PreviewPresentation to better match mockup * Add padding, border to comment bubble * add padding to bottom row of comment * Tweak alignment of avatar and comment content * Add margin to lower project page container * Use border-box box sizing for comment bubble * Make user avatar a link * Add initial implementation of comment tail * Align username row properly, fix comment bubble width * Use ::before pseudoelement for comment tail * Remove unused props to Comment component * Add CommentContainer to handle comment replies * Use CommentContainer instead of Comment in PreviewPresentation * Remove debug data from CommentContainer * Fetch top level comments from the API * Force comment container to stretch to bottom of view div * Remove unused api import in CommentContainer * Long words in comments should not overflow page * Remove @ before username in comment title * Fix word wrapping on Firefox * Refactor CommentContainer into a class * Properly export CommentContainer component * Make replies column take up proper width * Pass project ID to CommentContainer * Fetch comment replies in CommentContainer * Initial implementation for loading more comments * Add "Load More" button to Presentation * Initial implementation of collapsing threads longer than 3 replies * Remove console log from preview.js redux * Tweak last comment gradient color * Only show three total replies in collapsed state * Match scratchr2 behavior for thread collapsing * Use width calc instead of margin and width 100% * Fix styling for load more button * Make comment border gray to match the wireframe * Allow clicking through comment fade gradient * Add comment compose component * style comment compose box * Style post, cancel buttons on comment compose component * Add margin to create comment container * Tweak styling for characters remaining text * Tweak placeholder text * Add more margin to comment avatar * Add icons and styling to delete, report text * Refactor px -> rem where possible in comment styles * Change comment time color to dark gray * Tweak margin and border radius * Add reply icon to preview comments * Clean up unused imports, console.log in compose-comment component * Remove console statement in preview.jsx * Add some clarifying comments to unfinished parts of comments * Remove direct passing of comment api response to CommentContainer * CommentContainer should not pass api response directly * Rename CommentContainer to TopLevelComment * First pass at getReplies for comments in redux * Move reply fetching into redux actions instead of in TopLevelComment * Refactor getReplies logic to behave better * Remove components not directly related to reading comments * Hide load more button if all comments are loaded This uses the project info returned by the API * Use same gradient as add to studio modal on comment thread
2018-08-06 11:52:18 -04:00
const TopLevelComment = require('./comment/top-level-comment.jsx');
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');
const FormsyProjectUpdater = require('./formsy-project-updater.jsx');
const projectShape = require('./projectshape.jsx').projectShape;
require('./preview.scss');
const frameless = require('../../lib/frameless');
// 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();
}
};
const PreviewPresentation = ({
addToStudioOpen,
adminModalOpen,
adminPanelOpen,
2018-07-12 10:01:27 -04:00
assetHost,
authorUsername,
backpackHost,
canAddToStudio,
2018-10-17 13:16:41 -04:00
canDeleteComments,
canRemix,
canReport,
canRestoreComments,
canSave,
canShare,
2018-12-07 12:57:50 -05:00
canToggleComments,
canUseBackpack,
cloudHost,
Initial implementation for displaying comments on project page (#1997) * Create Comment component, start styling it * Restructure PreviewPresentation to better match mockup * Add padding, border to comment bubble * add padding to bottom row of comment * Tweak alignment of avatar and comment content * Add margin to lower project page container * Use border-box box sizing for comment bubble * Make user avatar a link * Add initial implementation of comment tail * Align username row properly, fix comment bubble width * Use ::before pseudoelement for comment tail * Remove unused props to Comment component * Add CommentContainer to handle comment replies * Use CommentContainer instead of Comment in PreviewPresentation * Remove debug data from CommentContainer * Fetch top level comments from the API * Force comment container to stretch to bottom of view div * Remove unused api import in CommentContainer * Long words in comments should not overflow page * Remove @ before username in comment title * Fix word wrapping on Firefox * Refactor CommentContainer into a class * Properly export CommentContainer component * Make replies column take up proper width * Pass project ID to CommentContainer * Fetch comment replies in CommentContainer * Initial implementation for loading more comments * Add "Load More" button to Presentation * Initial implementation of collapsing threads longer than 3 replies * Remove console log from preview.js redux * Tweak last comment gradient color * Only show three total replies in collapsed state * Match scratchr2 behavior for thread collapsing * Use width calc instead of margin and width 100% * Fix styling for load more button * Make comment border gray to match the wireframe * Allow clicking through comment fade gradient * Add comment compose component * style comment compose box * Style post, cancel buttons on comment compose component * Add margin to create comment container * Tweak styling for characters remaining text * Tweak placeholder text * Add more margin to comment avatar * Add icons and styling to delete, report text * Refactor px -> rem where possible in comment styles * Change comment time color to dark gray * Tweak margin and border radius * Add reply icon to preview comments * Clean up unused imports, console.log in compose-comment component * Remove console statement in preview.jsx * Add some clarifying comments to unfinished parts of comments * Remove direct passing of comment api response to CommentContainer * CommentContainer should not pass api response directly * Rename CommentContainer to TopLevelComment * First pass at getReplies for comments in redux * Move reply fetching into redux actions instead of in TopLevelComment * Refactor getReplies logic to behave better * Remove components not directly related to reading comments * Hide load more button if all comments are loaded This uses the project info returned by the API * Use same gradient as add to studio modal on comment thread
2018-08-06 11:52:18 -04:00
comments,
editable,
extensions,
faved,
favoriteCount,
2018-09-04 14:29:59 -04:00
intl,
isAdmin,
isFullScreen,
isLoggedIn,
isNewScratcher,
isProjectLoaded,
isRemixing,
isScratcher,
isShared,
justRemixed,
2018-11-23 01:17:46 -05:00
justShared,
loveCount,
loved,
modInfo,
moreCommentsToLoad,
onAddComment,
onAddToStudioClicked,
onAddToStudioClosed,
onCloseAdminPanel,
onDeleteComment,
onFavoriteClicked,
onGreenFlag,
Initial implementation for displaying comments on project page (#1997) * Create Comment component, start styling it * Restructure PreviewPresentation to better match mockup * Add padding, border to comment bubble * add padding to bottom row of comment * Tweak alignment of avatar and comment content * Add margin to lower project page container * Use border-box box sizing for comment bubble * Make user avatar a link * Add initial implementation of comment tail * Align username row properly, fix comment bubble width * Use ::before pseudoelement for comment tail * Remove unused props to Comment component * Add CommentContainer to handle comment replies * Use CommentContainer instead of Comment in PreviewPresentation * Remove debug data from CommentContainer * Fetch top level comments from the API * Force comment container to stretch to bottom of view div * Remove unused api import in CommentContainer * Long words in comments should not overflow page * Remove @ before username in comment title * Fix word wrapping on Firefox * Refactor CommentContainer into a class * Properly export CommentContainer component * Make replies column take up proper width * Pass project ID to CommentContainer * Fetch comment replies in CommentContainer * Initial implementation for loading more comments * Add "Load More" button to Presentation * Initial implementation of collapsing threads longer than 3 replies * Remove console log from preview.js redux * Tweak last comment gradient color * Only show three total replies in collapsed state * Match scratchr2 behavior for thread collapsing * Use width calc instead of margin and width 100% * Fix styling for load more button * Make comment border gray to match the wireframe * Allow clicking through comment fade gradient * Add comment compose component * style comment compose box * Style post, cancel buttons on comment compose component * Add margin to create comment container * Tweak styling for characters remaining text * Tweak placeholder text * Add more margin to comment avatar * Add icons and styling to delete, report text * Refactor px -> rem where possible in comment styles * Change comment time color to dark gray * Tweak margin and border radius * Add reply icon to preview comments * Clean up unused imports, console.log in compose-comment component * Remove console statement in preview.jsx * Add some clarifying comments to unfinished parts of comments * Remove direct passing of comment api response to CommentContainer * CommentContainer should not pass api response directly * Rename CommentContainer to TopLevelComment * First pass at getReplies for comments in redux * Move reply fetching into redux actions instead of in TopLevelComment * Refactor getReplies logic to behave better * Remove components not directly related to reading comments * Hide load more button if all comments are loaded This uses the project info returned by the API * Use same gradient as add to studio modal on comment thread
2018-08-06 11:52:18 -04:00
onLoadMore,
2019-01-10 10:46:01 -05:00
onLoadMoreReplies,
onLoveClicked,
onOpenAdminPanel,
onProjectLoaded,
onRemix,
onRemixing,
onReportClicked,
onReportClose,
onReportComment,
onReportSubmit,
onRestoreComment,
onSeeAllComments,
onSeeInside,
onSetProjectThumbnailer,
onShare,
2019-04-26 15:50:25 -04:00
onSocialClicked,
onSocialClosed,
onToggleComments,
onToggleStudio,
onUpdateProjectId,
onUpdateProjectThumbnail,
originalInfo,
parentInfo,
showCloudDataAlert,
showUsernameBlockAlert,
projectHost,
projectId,
projectInfo,
projectStudios,
remixes,
replies,
reportOpen,
2018-12-06 17:07:28 -05:00
showAdminPanel,
showModInfo,
singleCommentId,
2019-04-26 15:50:25 -04:00
socialOpen,
userOwnsProject,
visibilityInfo
}) => {
const shareDate = ((projectInfo.history && projectInfo.history.shared)) ? projectInfo.history.shared : '';
const revisedDate = ((projectInfo.history && projectInfo.history.modified)) ? projectInfo.history.modified : '';
const showInstructions = editable || projectInfo.instructions ||
(!projectInfo.instructions && !projectInfo.description); // show if both are empty
const showNotesAndCredits = editable || projectInfo.description ||
(!projectInfo.instructions && !projectInfo.description); // show if both are empty
let banner;
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) {
const censoredMessage = (
<CensoredMessage
censoredByCommunity={visibilityInfo.censoredByCommunity}
2019-01-23 13:29:37 -05:00
messageHTML={visibilityInfo.message}
reshareable={visibilityInfo.reshareable}
/>
);
banner = (<Banner
className="banner-danger"
2019-01-22 14:51:49 -05:00
message={censoredMessage}
/>);
} else if (justRemixed) {
banner = (
<Banner
className="banner-success"
message={
<FormattedMessage
id="project.remix.justRemixed"
values={{title: projectInfo.title}}
/>
}
/>
);
} else if (canShare) {
if (isShared && justShared) { // if was shared a while ago, don't show any share banner
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" />}
/>);
}
} else if (!isShared) {
banner = (<Banner
actionMessage={<FormattedMessage id="project.share.shareButton" />}
message={<FormattedMessage id="project.share.notShared" />}
onAction={onShare}
/>);
}
}
const extensionChips = (
<FlexRow className="extension-list">
{extensions && extensions.map(extension => (
<ExtensionChip
action={extension.action}
extensionL10n={extension.l10nId}
extensionName={extension.name}
hasStatus={extension.hasStatus}
iconURI={extension.icon && `/svgs/project/${extension.icon}`}
key={extension.name || extension.l10nId}
/>
))}
</FlexRow>
);
return (
<div className="preview">
2018-12-06 17:07:28 -05:00
{showAdminPanel && (
<AdminPanel
className={classNames('project-admin-panel', {
'admin-panel-open': adminPanelOpen,
'modal-open': adminModalOpen
})}
2018-12-06 17:07:28 -05:00
isOpen={adminPanelOpen}
onClose={onCloseAdminPanel}
onOpen={onOpenAdminPanel}
>
<iframe
className={classNames('admin-iframe', {
'modal-open': adminModalOpen
})}
src={`/scratch2/${projectId}/adminpanel/`}
/>
</AdminPanel>
)}
{ projectInfo && projectInfo.author && projectInfo.author.id && (
<React.Fragment>
{banner}
<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)}
/>
</a>
<div className="title">
{editable ?
<FormsyProjectUpdater
field="title"
initialValue={projectInfo.title}
>
{(value, ref, handleUpdate) => (
<Formsy
ref={ref}
onKeyPress={onKeyPress}
>
<InplaceInput
className="project-title"
handleUpdate={handleUpdate}
name="title"
validationErrors={{
maxLength: intl.formatMessage({
id: 'project.titleMaxLength'
})
}}
validations={{
maxLength: 100
}}
value={value}
/>
</Formsy>
)}
</FormsyProjectUpdater> :
<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">
{canRemix &&
<Button
alt={intl.formatMessage({id: 'project.remixButton.altText'})}
className={classNames([
'remix-button',
{
disabled: isRemixing || !isProjectLoaded,
remixing: isRemixing
}
])}
disabled={isRemixing || !isProjectLoaded}
title={intl.formatMessage({id: 'project.remixButton.altText'})}
onClick={onRemix}
>
{isRemixing ? (
<FormattedMessage id="project.remixButton.remixing" />
) : (
<FormattedMessage id="project.remixButton" />
)}
</Button>
}
<Button
className="button see-inside-button"
onClick={onSeeInside}
>
<FormattedMessage id="project.seeInsideButton" />
</Button>
</div>
</MediaQuery>
</FlexRow>
<FlexRow className="preview-row">
<div
className={classNames(
'guiPlayer',
{fullscreen: isFullScreen}
)}
>
{showCloudDataAlert && (
<FlexRow className="project-info-alert">
<FormattedMessage id="project.cloudDataAlert" />
</FlexRow>
)}
{showUsernameBlockAlert && (
<FlexRow className="project-info-alert">
<FormattedMessage id="project.usernameBlockAlert" />
</FlexRow>
)}
<IntlGUI
isPlayerOnly
assetHost={assetHost}
backpackHost={backpackHost}
backpackVisible={canUseBackpack}
basePath="/"
canRemix={canRemix}
canSave={canSave}
className="guiPlayer"
cloudHost={cloudHost}
hasCloudPermission={isScratcher}
isFullScreen={isFullScreen}
previewInfoVisible="false"
projectHost={projectHost}
projectId={projectId}
onGreenFlag={onGreenFlag}
onProjectLoaded={onProjectLoaded}
onRemixing={onRemixing}
onSetProjectThumbnailer={onSetProjectThumbnailer}
onUpdateProjectId={onUpdateProjectId}
onUpdateProjectThumbnail={onUpdateProjectThumbnail}
/>
</div>
<MediaQuery maxWidth={frameless.tabletPortrait - 1}>
<FlexRow className="preview-row force-center">
<div className="wrappable-item">
<Stats
faved={faved}
favoriteCount={favoriteCount}
loveCount={loveCount}
loved={loved}
projectInfo={projectInfo}
onFavoriteClicked={onFavoriteClicked}
onLoveClicked={onLoveClicked}
/>
</div>
<div className="wrappable-item">
<Subactions
addToStudioOpen={addToStudioOpen}
canReport={canReport}
isAdmin={isAdmin}
projectInfo={projectInfo}
reportOpen={reportOpen}
shareDate={shareDate}
2019-04-26 15:50:25 -04:00
socialOpen={socialOpen}
userOwnsProject={userOwnsProject}
onAddToStudioClicked={onAddToStudioClicked}
onAddToStudioClosed={onAddToStudioClosed}
onReportClicked={onReportClicked}
onReportClose={onReportClose}
onReportSubmit={onReportSubmit}
2019-04-26 15:50:25 -04:00
onSocialClicked={onSocialClicked}
onSocialClosed={onSocialClosed}
onToggleStudio={onToggleStudio}
/>
</div>
</FlexRow>
</MediaQuery>
<FlexRow className="project-notes">
<RemixCredit projectInfo={parentInfo} />
<RemixCredit projectInfo={originalInfo} />
{/* eslint-disable max-len */}
<MediaQuery maxWidth={frameless.tabletPortrait - 1}>
{(extensions && extensions.length) ? (
<FlexRow className="preview-row">
{extensionChips}
</FlexRow>
) : null}
</MediaQuery>
{showInstructions && (
<div className="description-block">
<div className="project-textlabel">
<FormattedMessage id="project.instructionsLabel" />
</div>
{editable ?
<FormsyProjectUpdater
field="instructions"
initialValue={projectInfo.instructions}
>
{(value, ref, handleUpdate) => (
<Formsy
className="project-description-form"
ref={ref}
onKeyPress={onKeyPress}
>
<InplaceInput
className={classNames(
'project-description-edit',
{remixes: parentInfo && parentInfo.author}
)}
handleUpdate={handleUpdate}
name="instructions"
placeholder={intl.formatMessage({
id: 'project.descriptionPlaceholder'
})}
type="textarea"
validationErrors={{
maxLength: intl.formatMessage({
id: 'project.descriptionMaxLength'
})
}}
validations={{
maxLength: 5000
}}
value={value}
/>
</Formsy>
)}
</FormsyProjectUpdater> :
<div className="project-description">
{decorateText(projectInfo.instructions, {
usernames: true,
hashtags: true,
2019-01-15 00:34:17 -05:00
scratchLinks: true
2018-12-11 06:41:49 -05:00
})}
</div>
}
</div>
)}
{showNotesAndCredits && (
<div className="description-block">
<div className="project-textlabel">
<FormattedMessage id="project.notesAndCreditsLabel" />
</div>
{editable ?
<FormsyProjectUpdater
field="description"
initialValue={projectInfo.description}
>
{(value, ref, handleUpdate) => (
<Formsy
className="project-description-form"
ref={ref}
onKeyPress={onKeyPress}
>
<InplaceInput
className={classNames(
'project-description-edit',
'last',
{remixes: parentInfo && parentInfo.author}
)}
handleUpdate={handleUpdate}
name="description"
placeholder={intl.formatMessage({
id: 'project.notesPlaceholder'
})}
type="textarea"
validationErrors={{
maxLength: intl.formatMessage({
id: 'project.descriptionMaxLength'
})
}}
validations={{
maxLength: 5000
}}
value={value}
/>
</Formsy>
)}
</FormsyProjectUpdater> :
<div className="project-description last">
{decorateText(projectInfo.description, {
usernames: true,
hashtags: true,
2019-01-15 00:34:17 -05:00
scratchLinks: true
})}
</div>
}
</div>
)}
{/* eslint-enable max-len */}
</FlexRow>
</FlexRow>
<MediaQuery minWidth={frameless.tabletPortrait}>
<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}
canAddToStudio={canAddToStudio}
canReport={canReport}
isAdmin={isAdmin}
2018-09-25 17:16:02 -04:00
projectInfo={projectInfo}
reportOpen={reportOpen}
shareDate={shareDate}
2019-04-26 15:50:25 -04:00
socialOpen={socialOpen}
userOwnsProject={userOwnsProject}
2018-09-25 17:16:02 -04:00
onAddToStudioClicked={onAddToStudioClicked}
onAddToStudioClosed={onAddToStudioClosed}
onReportClicked={onReportClicked}
onReportClose={onReportClose}
onReportSubmit={onReportSubmit}
2019-04-26 15:50:25 -04:00
onSocialClicked={onSocialClicked}
onSocialClosed={onSocialClosed}
2018-09-25 17:16:02 -04:00
onToggleStudio={onToggleStudio}
/>
</FlexRow>
</MediaQuery>
<MediaQuery minWidth={frameless.tabletPortrait}>
{(extensions && extensions.length) ? (
<FlexRow className="preview-row">
{extensionChips}
</FlexRow>
) : null}
</MediaQuery>
{showModInfo &&
<FlexRow className="preview-row">
<ModInfo
authorUsername={authorUsername}
revisedDate={revisedDate}
scripts={modInfo.scriptCount}
sprites={modInfo.spriteCount}
/>
</FlexRow>
}
</div>
<div className="project-lower-container">
<div className="inner">
<FlexRow className="preview-row">
<div className="comments-container">
<FlexRow className="comments-header">
<h4><FormattedMessage id="project.comments.header" /></h4>
2018-12-07 12:57:50 -05:00
{canToggleComments ? (
2018-10-10 15:14:53 -04:00
<div>
{projectInfo.comments_allowed ? (
<FormattedMessage id="project.comments.toggleOn" />
) : (
<FormattedMessage id="project.comments.toggleOff" />
)}
<ToggleSlider
checked={projectInfo.comments_allowed}
className="comments-allowed-input"
onChange={onToggleComments}
/>
2018-10-10 15:14:53 -04:00
</div>
) : null}
</FlexRow>
{/* Do not show the top-level comment form in single comment mode */}
{!singleCommentId && (
<FlexRow className="comments-root-reply">
{projectInfo.comments_allowed ? (
isLoggedIn ? (
isShared && <ComposeComment
projectId={projectId}
onAddComment={onAddComment}
/>
) : (
/* TODO add box for signing in to leave a comment */
null
)
2018-10-10 15:14:53 -04:00
) : (
<div className="comments-turned-off">
<FormattedMessage id="project.comments.turnedOff" />
</div>
)}
</FlexRow>
)}
<FlexRow className="comments-list">
{comments.map(comment => (
<TopLevelComment
author={comment.author}
2018-10-17 13:16:41 -04:00
canDelete={canDeleteComments}
canReply={isLoggedIn && projectInfo.comments_allowed && isShared}
canReport={isLoggedIn}
canRestore={canRestoreComments}
content={comment.content}
datetimeCreated={comment.datetime_created}
defaultExpanded={!!singleCommentId}
highlightedCommentId={singleCommentId}
id={comment.id}
key={comment.id}
2019-01-10 10:46:01 -05:00
moreRepliesToLoad={comment.moreRepliesToLoad}
parentId={comment.parent_id}
projectId={projectId}
replies={replies && replies[comment.id] ? replies[comment.id] : []}
visibility={comment.visibility}
onAddComment={onAddComment}
onDelete={onDeleteComment}
2019-01-10 10:46:01 -05:00
onLoadMoreReplies={onLoadMoreReplies}
onReport={onReportComment}
onRestore={onRestoreComment}
/>
))}
{moreCommentsToLoad &&
2018-09-24 10:58:39 -04:00
<Button
className="button load-more-button"
onClick={onLoadMore}
>
<FormattedMessage id="general.loadMore" />
2018-09-24 10:58:39 -04:00
</Button>
}
{!!singleCommentId &&
<Button
className="button load-more-button"
onClick={onSeeAllComments}
>
<FormattedMessage id="general.seeAllComments" />
</Button>
}
</FlexRow>
</div>
<FlexRow className="column">
<RemixList
projectId={projectId}
remixes={remixes}
/>
<StudioList
projectId={projectId}
studios={projectStudios}
/>
</FlexRow>
</FlexRow>
</div>
Initial implementation for displaying comments on project page (#1997) * Create Comment component, start styling it * Restructure PreviewPresentation to better match mockup * Add padding, border to comment bubble * add padding to bottom row of comment * Tweak alignment of avatar and comment content * Add margin to lower project page container * Use border-box box sizing for comment bubble * Make user avatar a link * Add initial implementation of comment tail * Align username row properly, fix comment bubble width * Use ::before pseudoelement for comment tail * Remove unused props to Comment component * Add CommentContainer to handle comment replies * Use CommentContainer instead of Comment in PreviewPresentation * Remove debug data from CommentContainer * Fetch top level comments from the API * Force comment container to stretch to bottom of view div * Remove unused api import in CommentContainer * Long words in comments should not overflow page * Remove @ before username in comment title * Fix word wrapping on Firefox * Refactor CommentContainer into a class * Properly export CommentContainer component * Make replies column take up proper width * Pass project ID to CommentContainer * Fetch comment replies in CommentContainer * Initial implementation for loading more comments * Add "Load More" button to Presentation * Initial implementation of collapsing threads longer than 3 replies * Remove console log from preview.js redux * Tweak last comment gradient color * Only show three total replies in collapsed state * Match scratchr2 behavior for thread collapsing * Use width calc instead of margin and width 100% * Fix styling for load more button * Make comment border gray to match the wireframe * Allow clicking through comment fade gradient * Add comment compose component * style comment compose box * Style post, cancel buttons on comment compose component * Add margin to create comment container * Tweak styling for characters remaining text * Tweak placeholder text * Add more margin to comment avatar * Add icons and styling to delete, report text * Refactor px -> rem where possible in comment styles * Change comment time color to dark gray * Tweak margin and border radius * Add reply icon to preview comments * Clean up unused imports, console.log in compose-comment component * Remove console statement in preview.jsx * Add some clarifying comments to unfinished parts of comments * Remove direct passing of comment api response to CommentContainer * CommentContainer should not pass api response directly * Rename CommentContainer to TopLevelComment * First pass at getReplies for comments in redux * Move reply fetching into redux actions instead of in TopLevelComment * Refactor getReplies logic to behave better * Remove components not directly related to reading comments * Hide load more button if all comments are loaded This uses the project info returned by the API * Use same gradient as add to studio modal on comment thread
2018-08-06 11:52:18 -04:00
</div>
</React.Fragment>
)}
</div>
);
};
PreviewPresentation.propTypes = {
addToStudioOpen: PropTypes.bool,
2018-12-05 16:09:04 -05:00
adminModalOpen: PropTypes.bool,
adminPanelOpen: PropTypes.bool,
2018-07-12 10:01:27 -04:00
assetHost: PropTypes.string,
authorUsername: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
backpackHost: PropTypes.string,
canAddToStudio: PropTypes.bool,
2018-10-17 13:16:41 -04:00
canDeleteComments: PropTypes.bool,
canRemix: PropTypes.bool,
canReport: PropTypes.bool,
canRestoreComments: PropTypes.bool,
canSave: PropTypes.bool,
canShare: PropTypes.bool,
2018-12-07 12:57:50 -05:00
canToggleComments: PropTypes.bool,
canUseBackpack: PropTypes.bool,
cloudHost: PropTypes.string,
Initial implementation for displaying comments on project page (#1997) * Create Comment component, start styling it * Restructure PreviewPresentation to better match mockup * Add padding, border to comment bubble * add padding to bottom row of comment * Tweak alignment of avatar and comment content * Add margin to lower project page container * Use border-box box sizing for comment bubble * Make user avatar a link * Add initial implementation of comment tail * Align username row properly, fix comment bubble width * Use ::before pseudoelement for comment tail * Remove unused props to Comment component * Add CommentContainer to handle comment replies * Use CommentContainer instead of Comment in PreviewPresentation * Remove debug data from CommentContainer * Fetch top level comments from the API * Force comment container to stretch to bottom of view div * Remove unused api import in CommentContainer * Long words in comments should not overflow page * Remove @ before username in comment title * Fix word wrapping on Firefox * Refactor CommentContainer into a class * Properly export CommentContainer component * Make replies column take up proper width * Pass project ID to CommentContainer * Fetch comment replies in CommentContainer * Initial implementation for loading more comments * Add "Load More" button to Presentation * Initial implementation of collapsing threads longer than 3 replies * Remove console log from preview.js redux * Tweak last comment gradient color * Only show three total replies in collapsed state * Match scratchr2 behavior for thread collapsing * Use width calc instead of margin and width 100% * Fix styling for load more button * Make comment border gray to match the wireframe * Allow clicking through comment fade gradient * Add comment compose component * style comment compose box * Style post, cancel buttons on comment compose component * Add margin to create comment container * Tweak styling for characters remaining text * Tweak placeholder text * Add more margin to comment avatar * Add icons and styling to delete, report text * Refactor px -> rem where possible in comment styles * Change comment time color to dark gray * Tweak margin and border radius * Add reply icon to preview comments * Clean up unused imports, console.log in compose-comment component * Remove console statement in preview.jsx * Add some clarifying comments to unfinished parts of comments * Remove direct passing of comment api response to CommentContainer * CommentContainer should not pass api response directly * Rename CommentContainer to TopLevelComment * First pass at getReplies for comments in redux * Move reply fetching into redux actions instead of in TopLevelComment * Refactor getReplies logic to behave better * Remove components not directly related to reading comments * Hide load more button if all comments are loaded This uses the project info returned by the API * Use same gradient as add to studio modal on comment thread
2018-08-06 11:52:18 -04:00
comments: PropTypes.arrayOf(PropTypes.object),
editable: PropTypes.bool,
extensions: PropTypes.arrayOf(PropTypes.object),
faved: PropTypes.bool,
favoriteCount: PropTypes.number,
2018-09-04 14:29:59 -04:00
intl: intlShape,
isAdmin: PropTypes.bool,
isFullScreen: PropTypes.bool,
isLoggedIn: PropTypes.bool,
isNewScratcher: PropTypes.bool,
isProjectLoaded: PropTypes.bool,
isRemixing: PropTypes.bool,
isScratcher: PropTypes.bool,
isShared: PropTypes.bool,
justRemixed: PropTypes.bool,
2018-11-23 01:17:46 -05:00
justShared: PropTypes.bool,
loveCount: PropTypes.number,
loved: PropTypes.bool,
modInfo: PropTypes.shape({
2018-12-07 16:38:39 -05:00
scriptCount: PropTypes.number,
spriteCount: PropTypes.number
}),
moreCommentsToLoad: PropTypes.bool,
onAddComment: PropTypes.func,
onAddToStudioClicked: PropTypes.func,
onAddToStudioClosed: PropTypes.func,
onCloseAdminPanel: PropTypes.func,
onDeleteComment: PropTypes.func,
onFavoriteClicked: PropTypes.func,
onGreenFlag: PropTypes.func,
Initial implementation for displaying comments on project page (#1997) * Create Comment component, start styling it * Restructure PreviewPresentation to better match mockup * Add padding, border to comment bubble * add padding to bottom row of comment * Tweak alignment of avatar and comment content * Add margin to lower project page container * Use border-box box sizing for comment bubble * Make user avatar a link * Add initial implementation of comment tail * Align username row properly, fix comment bubble width * Use ::before pseudoelement for comment tail * Remove unused props to Comment component * Add CommentContainer to handle comment replies * Use CommentContainer instead of Comment in PreviewPresentation * Remove debug data from CommentContainer * Fetch top level comments from the API * Force comment container to stretch to bottom of view div * Remove unused api import in CommentContainer * Long words in comments should not overflow page * Remove @ before username in comment title * Fix word wrapping on Firefox * Refactor CommentContainer into a class * Properly export CommentContainer component * Make replies column take up proper width * Pass project ID to CommentContainer * Fetch comment replies in CommentContainer * Initial implementation for loading more comments * Add "Load More" button to Presentation * Initial implementation of collapsing threads longer than 3 replies * Remove console log from preview.js redux * Tweak last comment gradient color * Only show three total replies in collapsed state * Match scratchr2 behavior for thread collapsing * Use width calc instead of margin and width 100% * Fix styling for load more button * Make comment border gray to match the wireframe * Allow clicking through comment fade gradient * Add comment compose component * style comment compose box * Style post, cancel buttons on comment compose component * Add margin to create comment container * Tweak styling for characters remaining text * Tweak placeholder text * Add more margin to comment avatar * Add icons and styling to delete, report text * Refactor px -> rem where possible in comment styles * Change comment time color to dark gray * Tweak margin and border radius * Add reply icon to preview comments * Clean up unused imports, console.log in compose-comment component * Remove console statement in preview.jsx * Add some clarifying comments to unfinished parts of comments * Remove direct passing of comment api response to CommentContainer * CommentContainer should not pass api response directly * Rename CommentContainer to TopLevelComment * First pass at getReplies for comments in redux * Move reply fetching into redux actions instead of in TopLevelComment * Refactor getReplies logic to behave better * Remove components not directly related to reading comments * Hide load more button if all comments are loaded This uses the project info returned by the API * Use same gradient as add to studio modal on comment thread
2018-08-06 11:52:18 -04:00
onLoadMore: PropTypes.func,
2019-01-10 10:46:01 -05:00
onLoadMoreReplies: PropTypes.func,
onLoveClicked: PropTypes.func,
onOpenAdminPanel: PropTypes.func,
onProjectLoaded: PropTypes.func,
onRemix: PropTypes.func,
onRemixing: PropTypes.func,
onReportClicked: PropTypes.func.isRequired,
onReportClose: PropTypes.func.isRequired,
onReportComment: PropTypes.func.isRequired,
onReportSubmit: PropTypes.func.isRequired,
onRestoreComment: PropTypes.func,
onSeeAllComments: PropTypes.func,
onSeeInside: PropTypes.func,
onSetProjectThumbnailer: PropTypes.func,
onShare: PropTypes.func,
2019-04-26 15:50:25 -04:00
onSocialClicked: PropTypes.func,
onSocialClosed: PropTypes.func,
2018-10-10 15:14:53 -04:00
onToggleComments: PropTypes.func,
onToggleStudio: PropTypes.func,
onUpdateProjectId: PropTypes.func,
onUpdateProjectThumbnail: PropTypes.func,
originalInfo: projectShape,
parentInfo: projectShape,
2018-07-12 10:01:27 -04:00
projectHost: PropTypes.string,
projectId: PropTypes.string,
projectInfo: projectShape,
projectStudios: PropTypes.arrayOf(PropTypes.object),
remixes: PropTypes.arrayOf(PropTypes.object),
Initial implementation for displaying comments on project page (#1997) * Create Comment component, start styling it * Restructure PreviewPresentation to better match mockup * Add padding, border to comment bubble * add padding to bottom row of comment * Tweak alignment of avatar and comment content * Add margin to lower project page container * Use border-box box sizing for comment bubble * Make user avatar a link * Add initial implementation of comment tail * Align username row properly, fix comment bubble width * Use ::before pseudoelement for comment tail * Remove unused props to Comment component * Add CommentContainer to handle comment replies * Use CommentContainer instead of Comment in PreviewPresentation * Remove debug data from CommentContainer * Fetch top level comments from the API * Force comment container to stretch to bottom of view div * Remove unused api import in CommentContainer * Long words in comments should not overflow page * Remove @ before username in comment title * Fix word wrapping on Firefox * Refactor CommentContainer into a class * Properly export CommentContainer component * Make replies column take up proper width * Pass project ID to CommentContainer * Fetch comment replies in CommentContainer * Initial implementation for loading more comments * Add "Load More" button to Presentation * Initial implementation of collapsing threads longer than 3 replies * Remove console log from preview.js redux * Tweak last comment gradient color * Only show three total replies in collapsed state * Match scratchr2 behavior for thread collapsing * Use width calc instead of margin and width 100% * Fix styling for load more button * Make comment border gray to match the wireframe * Allow clicking through comment fade gradient * Add comment compose component * style comment compose box * Style post, cancel buttons on comment compose component * Add margin to create comment container * Tweak styling for characters remaining text * Tweak placeholder text * Add more margin to comment avatar * Add icons and styling to delete, report text * Refactor px -> rem where possible in comment styles * Change comment time color to dark gray * Tweak margin and border radius * Add reply icon to preview comments * Clean up unused imports, console.log in compose-comment component * Remove console statement in preview.jsx * Add some clarifying comments to unfinished parts of comments * Remove direct passing of comment api response to CommentContainer * CommentContainer should not pass api response directly * Rename CommentContainer to TopLevelComment * First pass at getReplies for comments in redux * Move reply fetching into redux actions instead of in TopLevelComment * Refactor getReplies logic to behave better * Remove components not directly related to reading comments * Hide load more button if all comments are loaded This uses the project info returned by the API * Use same gradient as add to studio modal on comment thread
2018-08-06 11:52:18 -04:00
replies: PropTypes.objectOf(PropTypes.array),
reportOpen: PropTypes.bool,
2018-12-06 17:07:28 -05:00
showAdminPanel: PropTypes.bool,
showCloudDataAlert: PropTypes.bool,
showModInfo: PropTypes.bool,
showUsernameBlockAlert: PropTypes.bool,
2018-10-24 10:43:21 -04:00
singleCommentId: PropTypes.oneOfType([PropTypes.number, PropTypes.bool]),
2019-04-26 15:50:25 -04:00
socialOpen: PropTypes.bool,
userOwnsProject: PropTypes.bool,
visibilityInfo: PropTypes.shape({
censored: PropTypes.bool,
censoredByAdmin: PropTypes.bool,
censoredByCommunity: PropTypes.bool,
message: PropTypes.string,
deleted: PropTypes.bool,
reshareable: PropTypes.bool
})
};
module.exports = injectIntl(PreviewPresentation);