Skip to content

Commit 7ab434f

Browse files
committed
add a lot of things when username is known
1 parent df64b5a commit 7ab434f

File tree

11 files changed

+244
-28
lines changed

11 files changed

+244
-28
lines changed

src/components/menu-bar/menu-bar.jsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -747,7 +747,10 @@ class MenuBar extends React.Component {
747747
</MenuItem>
748748
)}</FramerateChanger>
749749
<ChangeUsername>{changeUsername => (
750-
<MenuItem onClick={changeUsername}>
750+
<MenuItem
751+
className={classNames({ [styles.disabled]: this.props.usernameLoggedIn })}
752+
onClick={this.props.usernameLoggedIn ? () => {} : changeUsername}
753+
>
751754
<FormattedMessage
752755
defaultMessage="Change Username"
753756
description="Menu bar item for changing the username"
@@ -1005,11 +1008,13 @@ MenuBar.propTypes = {
10051008
showComingSoon: PropTypes.bool,
10061009
userOwnsProject: PropTypes.bool,
10071010
username: PropTypes.string,
1011+
usernameLoggedIn: PropTypes.bool.isRequired,
10081012
vm: PropTypes.instanceOf(VM).isRequired
10091013
};
10101014

10111015
MenuBar.defaultProps = {
10121016
logo: scratchLogo,
1017+
usernameLoggedIn: false,
10131018
onShare: () => { }
10141019
};
10151020

@@ -1036,6 +1041,7 @@ const mapStateToProps = (state, ownProps) => {
10361041
sessionExists: state.session && typeof state.session.session !== 'undefined',
10371042
errorsMenuOpen: errorsMenuOpen(state),
10381043
username: user ? user.username : null,
1044+
usernameLoggedIn: state.scratchGui.tw.usernameLoggedIn,
10391045
userOwnsProject: ownProps.authorUsername && user &&
10401046
(ownProps.authorUsername === user.username),
10411047
vm: state.scratchGui.vm

src/components/menu-bar/share-button.jsx

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -131,17 +131,30 @@ class ShareButton extends React.Component {
131131
return;
132132
}
133133

134+
const isEdit = this.props.usernameLoggedIn
135+
&& this.props.extraProjectInfo?.author === this.props.username;
136+
137+
let editPiece = '';
134138
let remixPiece = '';
135-
if (location.hash.includes('#')) {
136-
const id = location.hash.replace('#', '');
139+
const id = location.hash.replace('#', '');
140+
if (this.props.extraProjectInfo?.isRemix) {
137141
remixPiece = `&remix=${id}`;
138142
}
139143

144+
let targetPage = 'upload';
145+
if (isEdit) {
146+
targetPage = 'edit';
147+
editPiece = `&id=${id}`;
148+
}
149+
140150
const url = location.origin;
141-
window.open(`https://penguinmod.com/upload?name=${this.props.projectTitle}${remixPiece}&external=${url}`, '_blank');
151+
window.open(`https://penguinmod.com/${targetPage}?name=${this.props.projectTitle}${editPiece}${remixPiece}&external=${url}`, '_blank');
142152
});
143153
}
144154
render() {
155+
const isRemix = this.props.extraProjectInfo?.isRemix;
156+
const isEdit = this.props.usernameLoggedIn
157+
&& this.props.extraProjectInfo?.author === this.props.username;
145158
return (
146159
<Button
147160
className={classNames(
@@ -153,17 +166,22 @@ class ShareButton extends React.Component {
153166
onClick={this.onUploadProject}
154167
>
155168
<div className={classNames(styles.shareContent)}>
156-
{window.location.hash.includes('#') ?
157-
<FormattedMessage
158-
defaultMessage="Remix"
159-
description="Menu bar item for remixing"
160-
id="gui.menuBar.remix"
169+
{isEdit ? <FormattedMessage
170+
defaultMessage="Upload Edits"
171+
description="Text for uploading edits for projects on PenguinMod"
172+
id="gui.menuBar.pmedit"
161173
/> :
162-
<FormattedMessage
163-
defaultMessage="Upload"
164-
description="Label for project share button"
165-
id="gui.menuBar.pmshare"
166-
/>}
174+
(isRemix ?
175+
<FormattedMessage
176+
defaultMessage="Remix"
177+
description="Menu bar item for remixing"
178+
id="gui.menuBar.remix"
179+
/> :
180+
<FormattedMessage
181+
defaultMessage="Upload"
182+
description="Label for project share button"
183+
id="gui.menuBar.pmshare"
184+
/>)}
167185
{this.state.loading ? (
168186
<img
169187
className={classNames(styles.icon)}
@@ -182,11 +200,25 @@ class ShareButton extends React.Component {
182200
ShareButton.propTypes = {
183201
className: PropTypes.string,
184202
isShared: PropTypes.bool,
185-
projectTitle: PropTypes.string
203+
projectTitle: PropTypes.string,
204+
extraProjectInfo: PropTypes.shape({
205+
accepted: PropTypes.bool,
206+
isRemix: PropTypes.bool,
207+
remixId: PropTypes.number,
208+
tooLarge: PropTypes.bool,
209+
author: PropTypes.string,
210+
releaseDate: PropTypes.shape(Date),
211+
isUpdated: PropTypes.bool
212+
}),
213+
username: PropTypes.string,
214+
usernameLoggedIn: PropTypes.bool
186215
};
187216

188217
const mapStateToProps = state => ({
189-
projectTitle: state.scratchGui.projectTitle
218+
projectTitle: state.scratchGui.projectTitle,
219+
extraProjectInfo: state.scratchGui.tw.extraProjectInfo,
220+
username: state.scratchGui.tw.username,
221+
usernameLoggedIn: state.scratchGui.tw.usernameLoggedIn
190222
});
191223

192224
// eslint-disable-next-line no-unused-vars

src/components/tw-username-modal/username-modal.jsx

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import React from 'react';
44
import Box from '../box/box.jsx';
55
import Modal from '../../containers/modal.jsx';
66
import classNames from 'classnames';
7+
import {APP_NAME} from '../../lib/brand';
78

89
import styles from './username-modal.css';
910
import isScratchDesktop from '../../lib/isScratchDesktop.js';
@@ -24,7 +25,7 @@ const UsernameModalComponent = props => (
2425
id="usernameModal"
2526
>
2627
<Box className={styles.body}>
27-
{props.mustChangeUsername && <React.Fragment>
28+
{props.mustChangeUsername && !props.usernameLoggedIn && <React.Fragment>
2829
<p className={classNames(styles.helpText, styles.mustChange)}>
2930
<FormattedMessage
3031
// eslint-disable-next-line max-len
@@ -65,12 +66,31 @@ const UsernameModalComponent = props => (
6566
onChange={props.onChange}
6667
onFocus={props.onFocus}
6768
onKeyPress={props.onKeyPress}
68-
pattern="^[a-zA-Z0-9_-]*$"
69+
pattern="^[a-zA-Z0-9_\-]*$"
6970
maxLength="20"
7071
spellCheck="false"
72+
disabled={props.usernameLoggedIn}
7173
/>
7274
</Box>
73-
{isScratchDesktop() ? (
75+
{!props.usernameLoggedIn ? (
76+
null
77+
) : (
78+
<React.Fragment>
79+
<p className={styles.helpText}>
80+
<FormattedMessage
81+
// eslint-disable-next-line max-len
82+
defaultMessage="You are currently logged in as {USERNAME}. You cannot change your username unless you log out of {APP_NAME}."
83+
description="Text when the user is logged in, so they cant change their username"
84+
id="pm.usernameModal.loggedIn"
85+
values={{
86+
USERNAME: props.value,
87+
APP_NAME
88+
}}
89+
/>
90+
</p>
91+
</React.Fragment>
92+
)}
93+
{isScratchDesktop() || props.usernameLoggedIn ? (
7494
null
7595
) : (
7696
<React.Fragment>
@@ -96,6 +116,7 @@ const UsernameModalComponent = props => (
96116
<button
97117
className={styles.cancelButton}
98118
onClick={props.onReset}
119+
disabled={props.usernameLoggedIn}
99120
>
100121
<FormattedMessage
101122
defaultMessage="Reset"
@@ -116,7 +137,7 @@ const UsernameModalComponent = props => (
116137
<button
117138
className={styles.okButton}
118139
onClick={props.onOk}
119-
disabled={!props.valueValid}
140+
disabled={!props.valueValid || props.usernameLoggedIn}
120141
>
121142
<FormattedMessage
122143
defaultMessage="OK"
@@ -134,6 +155,7 @@ UsernameModalComponent.propTypes = {
134155
mustChangeUsername: PropTypes.bool.isRequired,
135156
value: PropTypes.string.isRequired,
136157
valueValid: PropTypes.bool.isRequired,
158+
usernameLoggedIn: PropTypes.bool.isRequired,
137159
onCancel: PropTypes.func.isRequired,
138160
onChange: PropTypes.func.isRequired,
139161
onFocus: PropTypes.func.isRequired,

src/containers/blocks.jsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@ class Blocks extends React.Component {
181181
toolboxWorkspace.registerButtonCallback('OPEN_RETURN_DOCS', () => {
182182
window.open('https://docs.turbowarp.org/return', '_blank');
183183
});
184+
toolboxWorkspace.registerButtonCallback('OPEN_USERNAME_DOCS', () => {
185+
window.open('https://docs.penguinmod.com/username', '_blank');
186+
});
184187

185188
// Store the xml of the toolbox that is actually rendered.
186189
// This is used in componentDidUpdate instead of prevProps, because

src/containers/gui.jsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import cloudManagerHOC from '../lib/cloud-manager-hoc.jsx';
4040
import TWFullScreenResizerHOC from '../lib/tw-fullscreen-resizer-hoc.jsx';
4141

4242
import GUIComponent from '../components/gui/gui.jsx';
43+
import HomeCommunication from './home-communication.jsx';
4344
import {setIsScratchDesktop} from '../lib/isScratchDesktop.js';
4445

4546
class GUI extends React.Component {
@@ -85,15 +86,20 @@ class GUI extends React.Component {
8586
isPlayground,
8687
...componentProps
8788
} = this.props;
88-
return (
89+
return (<>
8990
<GUIComponent
9091
loading={fetchingProject || isLoading || loadingStateVisible}
9192
isPlayground={isPlayground}
9293
{...componentProps}
9394
>
9495
{children}
9596
</GUIComponent>
96-
);
97+
98+
<HomeCommunication
99+
projectId={projectId}
100+
isPlayground={isPlayground}
101+
/>
102+
</>);
97103
}
98104
}
99105

src/containers/home-communication.jsx

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import bindAll from 'lodash.bindall';
2+
import PropTypes from 'prop-types';
3+
import React from 'react';
4+
import {connect} from 'react-redux';
5+
import {setUsername, setUsernameInvalid, setUsernameLoggedIn} from '../reducers/tw';
6+
7+
let origin = "https://penguinmod.com";
8+
// origin = 'http://localhost:5173';
9+
10+
class HomeCommunication extends React.Component {
11+
constructor (props) {
12+
super(props);
13+
bindAll(this, [
14+
'wrapperEventHandler'
15+
]);
16+
17+
this.state = {
18+
frame: null,
19+
canSetUsername: true,
20+
};
21+
}
22+
23+
componentDidMount() {
24+
window.addEventListener('message', this.wrapperEventHandler);
25+
const iframe = document.createElement('iframe');
26+
iframe.src = `${origin}/embed/editor?external=${encodeURIComponent(window.origin)}`;
27+
iframe.width = 100;
28+
iframe.height = 100;
29+
iframe.style.display = 'none';
30+
document.body.appendChild(iframe);
31+
32+
this.setState({
33+
frame: iframe
34+
});
35+
}
36+
componentWillUnmount() {
37+
window.removeEventListener('message', this.wrapperEventHandler);
38+
const iframe = this.state.frame;
39+
if (iframe) {
40+
iframe.remove();
41+
}
42+
this.setState({
43+
frame: null
44+
});
45+
}
46+
47+
async wrapperEventHandler(e) {
48+
const data = e.data;
49+
// Don't recursively try to run this event.
50+
if (e.origin === window.origin) {
51+
return;
52+
}
53+
if (!data.type) return;
54+
if (!data.packet) return;
55+
console.log(data);
56+
57+
switch (data.type) {
58+
case 'login': {
59+
if (data.packet.loggedIn !== true) return;
60+
if (!data.packet.username) return;
61+
if (!this.state.canSetUsername) return;
62+
this.props.onSetUsername(data.packet.username);
63+
this.setState({
64+
canSetUsername: false
65+
});
66+
}
67+
}
68+
}
69+
70+
render () {
71+
return (
72+
<div></div>
73+
);
74+
}
75+
}
76+
77+
HomeCommunication.propTypes = {
78+
projectId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
79+
isPlayground: PropTypes.bool,
80+
onSetUsername: PropTypes.func,
81+
username: PropTypes.string,
82+
usernameInvalid: PropTypes.bool,
83+
usernameLoggedIn: PropTypes.bool
84+
};
85+
86+
const mapStateToProps = state => ({
87+
username: state.scratchGui.tw.username,
88+
usernameInvalid: state.scratchGui.tw.usernameInvalid,
89+
usernameLoggedIn: state.scratchGui.tw.usernameLoggedIn
90+
});
91+
92+
const mapDispatchToProps = dispatch => ({
93+
onSetUsername: username => {
94+
dispatch(setUsername(username));
95+
dispatch(setUsernameLoggedIn(true));
96+
dispatch(setUsernameInvalid(false));
97+
}
98+
});
99+
100+
export default connect(
101+
mapStateToProps,
102+
mapDispatchToProps
103+
)(HomeCommunication);

0 commit comments

Comments
 (0)