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

572 lines
22 KiB
React
Raw Normal View History

2018-06-16 18:19:31 -04:00
// preview view can show either project page or editor page;
// idea is that we shouldn't require a page reload to switch back and forth
const bindAll = require('lodash.bindall');
2018-02-20 17:04:45 -05:00
const React = require('react');
const PropTypes = require('prop-types');
const connect = require('react-redux').connect;
const injectIntl = require('react-intl').injectIntl;
const parser = require('scratch-parser');
const Page = require('../../components/page/www/page.jsx');
2018-08-24 18:04:57 -04:00
const api = require('../../lib/api');
2018-02-20 17:04:45 -05:00
const render = require('../../lib/render.jsx');
const storage = require('../../lib/storage.js').default;
const log = require('../../lib/log');
const EXTENSION_INFO = require('../../lib/extensions.js').default;
2018-02-20 17:04:45 -05:00
const PreviewPresentation = require('./presentation.jsx');
const projectShape = require('./projectshape.jsx').projectShape;
const sessionActions = require('../../redux/session.js');
const previewActions = require('../../redux/preview.js');
const GUI = require('scratch-gui');
const IntlGUI = injectIntl(GUI.default);
2018-02-20 17:04:45 -05:00
class Preview extends React.Component {
constructor (props) {
super(props);
bindAll(this, [
'addEventListeners',
'handleToggleStudio',
'handleFavoriteToggle',
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
'handleLoadMore',
2018-08-24 18:04:57 -04:00
// temporary, to pass to GUI. Remove when nav bar components are shared between www and gui.
'handleLogout',
'handleLoveToggle',
'handlePermissions',
'handlePopState',
'handleReportClick',
'handleReportClose',
'handleReportSubmit',
'handleAddToStudioClick',
'handleAddToStudioClose',
'handleSeeInside',
'handleUpdate',
'initCounts',
'isShared',
'pushHistory',
'userOwnsProject'
]);
const pathname = window.location.pathname.toLowerCase();
const parts = pathname.split('/').filter(Boolean);
// parts[0]: 'preview'
// parts[1]: either :id or 'editor'
// parts[2]: undefined if no :id, otherwise either 'editor' or 'fullscreen'
this.state = {
editable: false,
extensions: [],
favoriteCount: 0,
loveCount: 0,
projectId: parts[1] === 'editor' ? 0 : parts[1],
addToStudioOpen: false,
reportOpen: false
};
this.getExtensions(this.state.projectId);
this.addEventListeners();
}
componentDidUpdate (prevProps) {
if (this.props.sessionStatus !== prevProps.sessionStatus &&
this.props.sessionStatus === sessionActions.Status.FETCHED &&
this.state.projectId) {
if (this.props.user) {
const username = this.props.user.username;
const token = this.props.user.token;
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
this.props.getTopLevelComments(this.state.projectId, this.props.comments.length);
this.props.getProjectInfo(this.state.projectId, token);
this.props.getRemixes(this.state.projectId, token);
this.props.getProjectStudios(this.state.projectId, token);
this.props.getCuratedStudios(username);
this.props.getFavedStatus(this.state.projectId, username, token);
this.props.getLovedStatus(this.state.projectId, username, token);
} else {
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
this.props.getTopLevelComments(this.state.projectId, this.props.comments.length);
this.props.getProjectInfo(this.state.projectId);
this.props.getRemixes(this.state.projectId);
this.props.getProjectStudios(this.state.projectId);
}
}
if (this.props.projectInfo.id !== prevProps.projectInfo.id) {
this.getExtensions(this.state.projectId);
this.initCounts(this.props.projectInfo.stats.favorites, this.props.projectInfo.stats.loves);
this.handlePermissions();
if (this.props.projectInfo.remix.parent !== null) {
this.props.getParentInfo(this.props.projectInfo.remix.parent);
}
if (this.props.projectInfo.remix.root !== null &&
this.props.projectInfo.remix.root !== this.props.projectInfo.remix.parent
) {
this.props.getOriginalInfo(this.props.projectInfo.remix.root);
}
}
if (this.props.playerMode !== prevProps.playerMode || this.props.fullScreen !== prevProps.fullScreen) {
this.pushHistory(history.state === null);
}
}
componentWillUnmount () {
this.removeEventListeners();
}
addEventListeners () {
window.addEventListener('popstate', this.handlePopState);
}
removeEventListeners () {
window.removeEventListener('popstate', this.handlePopState);
}
getExtensions (projectId) {
storage
.load(storage.AssetType.Project, projectId, storage.DataFormat.JSON)
.then(projectAsset => { // NOTE: this is turning up null, breaking the line below.
let input = projectAsset.data;
if (typeof input === 'object' && !(input instanceof ArrayBuffer) &&
!ArrayBuffer.isView(input)) { // taken from scratch-vm
// If the input is an object and not any ArrayBuffer
// or an ArrayBuffer view (this includes all typed arrays and DataViews)
// turn the object into a JSON string, because we suspect
// this is a project.json as an object
// validate expects a string or buffer as input
// TODO not sure if we need to check that it also isn't a data view
input = JSON.stringify(input);
}
parser(projectAsset.data, false, (err, projectData) => {
2018-06-20 17:04:16 -04:00
if (err) {
log.error(`Unhandled project parsing error: ${err}`);
2018-06-20 17:04:16 -04:00
return;
}
const extensionSet = new Set();
if (projectData[0].extensions) {
projectData[0].extensions.forEach(extension => {
extensionSet.add(EXTENSION_INFO[extension]);
});
}
this.setState({
extensions: Array.from(extensionSet)
});
});
});
}
2018-08-24 18:04:57 -04:00
// Temporarily duplicated this function from navigation.jsx here.
// Should move handling of login/logout into session.js, and handle them
// from here as well as navigation.jsx.
handleLogout (e) {
e.preventDefault();
api({
host: '',
method: 'post',
uri: '/accounts/logout/',
useCsrf: true
}, err => {
if (err) log.error(err);
window.location = '/';
});
}
handleReportClick () {
this.setState({reportOpen: true});
}
handleReportClose () {
this.setState({reportOpen: false});
}
handleAddToStudioClick () {
this.setState({addToStudioOpen: true});
}
handleAddToStudioClose () {
this.setState({addToStudioOpen: false});
}
handleReportSubmit (formData) {
this.props.reportProject(this.state.projectId, formData);
}
handlePopState () {
const path = window.location.pathname.toLowerCase();
const playerMode = path.indexOf('editor') === -1;
const fullScreen = path.indexOf('fullscreen') !== -1;
if (this.props.playerMode !== playerMode) {
this.props.setPlayer(playerMode);
}
if (this.props.fullScreen !== fullScreen) {
this.props.setFullScreen(fullScreen);
}
}
pushHistory (push) {
// update URI to match mode
const idPath = this.state.projectId ? `${this.state.projectId}/` : '';
let modePath = '';
if (!this.props.playerMode) modePath = 'editor/';
// fullscreen overrides editor
if (this.props.fullScreen) modePath = 'fullscreen/';
const newPath = `/preview/${idPath}${modePath}`;
if (push) {
history.pushState(
{},
document.title,
newPath
);
} else {
history.replaceState(
{},
document.title,
newPath
);
}
}
handleToggleStudio (event) {
const studioId = parseInt(event.currentTarget.dataset.id, 10);
2018-07-31 18:10:42 -04:00
if (isNaN(studioId)) { // sanity check in case event had no integer data-id
return;
}
const studio = this.props.studios.find(thisStudio => (thisStudio.id === studioId));
// only send add or leave request to server if we know current status
if ((typeof studio !== 'undefined') && ('includesProject' in studio)) {
this.props.toggleStudio(
(studio.includesProject === false),
studioId,
this.props.projectInfo.id,
this.props.user.token
);
}
}
handleFavoriteToggle () {
this.props.setFavedStatus(
!this.props.faved,
this.props.projectInfo.id,
this.props.user.username,
this.props.user.token
);
if (this.props.faved) {
this.setState(state => ({
favoriteCount: state.favoriteCount - 1
}));
} else {
this.setState(state => ({
favoriteCount: state.favoriteCount + 1
}));
}
}
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
handleLoadMore () {
this.props.getTopLevelComments(this.state.projectId, this.props.comments.length);
}
handleLoveToggle () {
this.props.setLovedStatus(
!this.props.loved,
this.props.projectInfo.id,
this.props.user.username,
this.props.user.token
);
if (this.props.loved) {
this.setState(state => ({
loveCount: state.loveCount - 1
}));
} else {
this.setState(state => ({
loveCount: state.loveCount + 1
}));
}
}
handlePermissions () {
2018-06-16 18:19:31 -04:00
// TODO: handle admins and mods
if (this.props.projectInfo.author.username === this.props.user.username) {
this.setState({editable: true});
}
}
handleSeeInside () {
this.props.setPlayer(false);
}
handleUpdate (jsonData) {
this.props.updateProject(
this.props.projectInfo.id,
jsonData,
this.props.user.username,
this.props.user.token
);
}
initCounts (favorites, loves) {
this.setState({
favoriteCount: favorites,
loveCount: loves
});
2018-02-20 17:04:45 -05:00
}
isShared () {
return (
// if we don't have projectInfo assume shared until we know otherwise
Object.keys(this.props.projectInfo).length === 0 || (
this.props.projectInfo.history &&
this.props.projectInfo.history.shared.length > 0
)
);
}
isLoggedIn () {
return (
this.props.sessionStatus === sessionActions.Status.FETCHED &&
Object.keys(this.props.user).length > 0
);
}
userOwnsProject () {
return (
this.isLoggedIn() &&
Object.keys(this.props.projectInfo).length > 0 &&
this.props.user.id === this.props.projectInfo.author.id
);
}
2018-02-20 17:04:45 -05:00
render () {
return (
this.props.playerMode ?
<Page>
<PreviewPresentation
addToStudioOpen={this.state.addToStudioOpen}
2018-07-12 10:01:27 -04:00
assetHost={this.props.assetHost}
backpackOptions={this.props.backpackOptions}
comments={this.props.comments}
editable={this.state.editable}
extensions={this.state.extensions}
faved={this.props.faved}
favoriteCount={this.state.favoriteCount}
isFullScreen={this.state.isFullScreen}
isLoggedIn={this.isLoggedIn()}
isShared={this.isShared()}
loveCount={this.state.loveCount}
loved={this.props.loved}
originalInfo={this.props.original}
parentInfo={this.props.parent}
2018-07-12 10:01:27 -04:00
projectHost={this.props.projectHost}
projectId={this.state.projectId}
projectInfo={this.props.projectInfo}
projectStudios={this.props.projectStudios}
remixes={this.props.remixes}
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={this.props.replies}
reportOpen={this.state.reportOpen}
studios={this.props.studios}
userOwnsProject={this.userOwnsProject()}
onAddToStudioClicked={this.handleAddToStudioClick}
onAddToStudioClosed={this.handleAddToStudioClose}
onFavoriteClicked={this.handleFavoriteToggle}
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={this.handleLoadMore}
onLoveClicked={this.handleLoveToggle}
onReportClicked={this.handleReportClick}
onReportClose={this.handleReportClose}
onReportSubmit={this.handleReportSubmit}
onSeeInside={this.handleSeeInside}
onToggleStudio={this.handleToggleStudio}
onUpdate={this.handleUpdate}
/>
</Page> :
<IntlGUI
enableCommunity
hideIntro
2018-07-12 10:01:27 -04:00
assetHost={this.props.assetHost}
backpackOptions={this.props.backpackOptions}
basePath="/"
className="gui"
2018-07-12 10:01:27 -04:00
projectHost={this.props.projectHost}
projectId={this.state.projectId}
2018-08-24 18:04:57 -04:00
onClickLogout={this.handleLogout}
/>
2018-02-20 17:04:45 -05:00
);
}
}
Preview.propTypes = {
2018-07-12 10:01:27 -04:00
assetHost: PropTypes.string.isRequired,
backpackOptions: PropTypes.shape({
host: PropTypes.string,
visible: PropTypes.bool
}),
comments: PropTypes.arrayOf(PropTypes.object),
faved: PropTypes.bool,
fullScreen: PropTypes.bool,
getCuratedStudios: PropTypes.func.isRequired,
getFavedStatus: PropTypes.func.isRequired,
getLovedStatus: PropTypes.func.isRequired,
getOriginalInfo: PropTypes.func.isRequired,
getParentInfo: PropTypes.func.isRequired,
getProjectInfo: PropTypes.func.isRequired,
getProjectStudios: PropTypes.func.isRequired,
getRemixes: PropTypes.func.isRequired,
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
getTopLevelComments: PropTypes.func.isRequired,
loved: PropTypes.bool,
original: projectShape,
parent: projectShape,
playerMode: PropTypes.bool,
2018-07-12 10:01:27 -04:00
projectHost: PropTypes.string.isRequired,
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),
reportProject: PropTypes.func,
sessionStatus: PropTypes.string,
setFavedStatus: PropTypes.func.isRequired,
setFullScreen: PropTypes.func.isRequired,
setLovedStatus: PropTypes.func.isRequired,
setPlayer: PropTypes.func.isRequired,
studios: PropTypes.arrayOf(PropTypes.object),
toggleStudio: PropTypes.func.isRequired,
updateProject: PropTypes.func.isRequired,
user: PropTypes.shape({
id: PropTypes.number,
banned: PropTypes.bool,
username: PropTypes.string,
token: PropTypes.string,
thumbnailUrl: PropTypes.string,
dateJoined: PropTypes.string,
email: PropTypes.string,
classroomId: PropTypes.string
})
};
Preview.defaultProps = {
2018-07-12 10:01:27 -04:00
assetHost: process.env.ASSET_HOST,
backpackOptions: {
host: process.env.BACKPACK_HOST,
visible: true
},
2018-07-12 10:01:27 -04:00
projectHost: process.env.PROJECT_HOST,
sessionStatus: sessionActions.Status.NOT_FETCHED,
user: {}
};
// Build consolidated curatedStudios object from all studio info.
// We add flags to indicate whether the project is currently in the studio,
// and the status of requests to join/leave studios.
const consolidateStudiosInfo = (curatedStudios, projectStudios, currentStudioIds, studioRequests) => {
const consolidatedStudios = [];
projectStudios.forEach(projectStudio => {
const includesProject = (currentStudioIds.indexOf(projectStudio.id) !== -1);
const consolidatedStudio =
Object.assign({}, projectStudio, {includesProject: includesProject});
consolidatedStudios.push(consolidatedStudio);
});
// copy the curated studios that project is not in
curatedStudios.forEach(curatedStudio => {
if (!projectStudios.some(projectStudio => (projectStudio.id === curatedStudio.id))) {
const includesProject = (currentStudioIds.indexOf(curatedStudio.id) !== -1);
const consolidatedStudio =
Object.assign({}, curatedStudio, {includesProject: includesProject});
consolidatedStudios.push(consolidatedStudio);
}
});
// set studio state to hasRequestOutstanding==true if it's being fetched,
// false if it's not
consolidatedStudios.forEach(consolidatedStudio => {
const id = consolidatedStudio.id;
consolidatedStudio.hasRequestOutstanding =
((id in studioRequests) &&
(studioRequests[id] === previewActions.Status.FETCHING));
});
return consolidatedStudios;
};
const mapStateToProps = state => ({
projectInfo: state.preview.projectInfo,
comments: state.preview.comments,
faved: state.preview.faved,
loved: state.preview.loved,
original: state.preview.original,
parent: state.preview.parent,
remixes: state.preview.remixes,
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: state.preview.replies,
sessionStatus: state.session.status,
projectStudios: state.preview.projectStudios,
studios: consolidateStudiosInfo(state.preview.curatedStudios,
state.preview.projectStudios, state.preview.currentStudioIds,
state.preview.status.studioRequests),
user: state.session.session.user,
playerMode: state.scratchGui.mode.isPlayerOnly,
fullScreen: state.scratchGui.mode.isFullScreen
});
const mapDispatchToProps = dispatch => ({
getOriginalInfo: id => {
dispatch(previewActions.getOriginalInfo(id));
},
getParentInfo: id => {
dispatch(previewActions.getParentInfo(id));
},
getProjectInfo: (id, token) => {
dispatch(previewActions.getProjectInfo(id, token));
},
getRemixes: id => {
dispatch(previewActions.getRemixes(id));
},
getProjectStudios: id => {
dispatch(previewActions.getProjectStudios(id));
},
getCuratedStudios: (username, token) => {
dispatch(previewActions.getCuratedStudios(username, token));
},
toggleStudio: (isAdd, studioId, id, token) => {
if (isAdd === true) {
dispatch(previewActions.addToStudio(studioId, id, token));
} else {
dispatch(previewActions.leaveStudio(studioId, id, token));
}
},
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
getTopLevelComments: (id, offset) => {
dispatch(previewActions.getTopLevelComments(id, offset));
},
getFavedStatus: (id, username, token) => {
dispatch(previewActions.getFavedStatus(id, username, token));
},
setFavedStatus: (faved, id, username, token) => {
dispatch(previewActions.setFavedStatus(faved, id, username, token));
},
getLovedStatus: (id, username, token) => {
dispatch(previewActions.getLovedStatus(id, username, token));
},
setLovedStatus: (loved, id, username, token) => {
dispatch(previewActions.setLovedStatus(loved, id, username, token));
},
refreshSession: () => {
dispatch(sessionActions.refreshSession());
},
reportProject: (id, formData) => {
dispatch(previewActions.reportProject(id, formData));
},
setOriginalInfo: info => {
dispatch(previewActions.setOriginalInfo(info));
},
setParentInfo: info => {
dispatch(previewActions.setParentInfo(info));
},
updateProject: (id, formData, username, token) => {
dispatch(previewActions.updateProject(id, formData, username, token));
},
setPlayer: player => {
dispatch(GUI.setPlayer(player));
},
setFullScreen: fullscreen => {
dispatch(GUI.setFullScreen(fullscreen));
}
});
const ConnectedPreview = connect(
mapStateToProps,
mapDispatchToProps
)(Preview);
GUI.setAppElement(document.getElementById('app'));
const initGuiState = guiInitialState => {
const pathname = window.location.pathname.toLowerCase();
const parts = pathname.split('/').filter(Boolean);
// parts[0]: 'preview'
// parts[1]: either :id or 'editor'
// parts[2]: undefined if no :id, otherwise either 'editor' or 'fullscreen'
if (parts.indexOf('editor') === -1) {
guiInitialState = GUI.initPlayer(guiInitialState);
}
if (parts.indexOf('fullscreen') !== -1) {
guiInitialState = GUI.initFullScreen(guiInitialState);
}
return guiInitialState;
};
render(
<ConnectedPreview />,
document.getElementById('app'),
{
preview: previewActions.previewReducer,
...GUI.guiReducers
},
{scratchGui: initGuiState(GUI.guiInitialState)},
GUI.guiMiddleware
);