Skip to content

Commit 1031c2f

Browse files
committed
required changes
1 parent 302f5ef commit 1031c2f

File tree

4 files changed

+112
-93
lines changed

4 files changed

+112
-93
lines changed

client/modules/IDE/actions/toast.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,24 @@ export function hideToast() {
66
};
77
}
88

9-
export function showToast(time) {
9+
/**
10+
* Temporary fix until #2206 is merged.
11+
* Supports legacy two-action syntax:
12+
* dispatch(setToastText('Toast.SketchFailedSave'));
13+
* dispatch(showToast(1500));
14+
* And also supports proposed single-action syntax with message and optional timeout.
15+
* dispatch(showToast('Toast.SketchFailedSave'));
16+
* dispatch(showToast('Toast.SketchSaved', 5500));
17+
*/
18+
export function showToast(textOrTime, timeout = 1500) {
1019
return (dispatch) => {
20+
let time = timeout;
21+
if (typeof textOrTime === 'string') {
22+
// eslint-disable-next-line no-use-before-define
23+
dispatch(setToastText(textOrTime));
24+
} else {
25+
time = textOrTime;
26+
}
1127
dispatch({
1228
type: ActionTypes.SHOW_TOAST
1329
});

client/modules/IDE/components/Header/Nav.jsx

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import LogoIcon from '../../../../images/p5js-logo-small.svg';
1717
import { selectSketchPath } from '../../selectors/project';
1818
import { metaKey, metaKeyName } from '../../../../utils/metaKey';
1919
import { useSketchActions } from '../../hooks';
20-
import { getIsUserOwner } from '../../selectors/users';
20+
import { getAuthenticated, getIsUserOwner } from '../../selectors/users';
2121
import { cloneProject } from '../../actions/project';
2222
import {
2323
newFile,
@@ -63,10 +63,8 @@ LeftLayout.defaultProps = {
6363
};
6464

6565
const UserMenu = () => {
66-
const user = useSelector((state) => state.user);
67-
6866
const isLoginEnabled = getConfig('LOGIN_ENABLED');
69-
const isAuthenticated = user.authenticated;
67+
const isAuthenticated = useSelector(getAuthenticated);
7068

7169
if (isLoginEnabled && isAuthenticated) {
7270
return <AuthenticatedUserMenu />;
@@ -106,9 +104,11 @@ const DashboardMenu = () => {
106104

107105
const ProjectMenu = (props) => {
108106
const isUserOwner = useSelector(getIsUserOwner);
109-
const project = useSelector((state) => state?.project);
107+
const project = useSelector((state) => state.project);
110108
const user = useSelector((state) => state.user);
111109

110+
const isUnsaved = !project?.id;
111+
112112
// TODO: use selectRootFile selector
113113
const rootFile = useSelector(
114114
(state) => state.files.filter((file) => file.name === 'root')[0]
@@ -145,21 +145,21 @@ const ProjectMenu = (props) => {
145145
hideIf={
146146
!getConfig('LOGIN_ENABLED') || (project?.owner && !isUserOwner)
147147
}
148-
onClick={() => saveSketch(cmRef)}
148+
onClick={() => saveSketch(cmRef.current)}
149149
>
150150
{t('Common.Save')}
151151
<span className="nav__keyboard-shortcut">{metaKeyName}+S</span>
152152
</NavMenuItem>
153153
<NavMenuItem
154-
hideIf={!project?.id || !user.authenticated}
154+
hideIf={isUnsaved || !user.authenticated}
155155
onClick={() => dispatch(cloneProject())}
156156
>
157157
{t('Nav.File.Duplicate')}
158158
</NavMenuItem>
159-
<NavMenuItem hideIf={!project?.id} onClick={shareSketch}>
159+
<NavMenuItem hideIf={isUnsaved} onClick={shareSketch}>
160160
{t('Nav.File.Share')}
161161
</NavMenuItem>
162-
<NavMenuItem hideIf={!project?.id} onClick={downloadSketch}>
162+
<NavMenuItem hideIf={isUnsaved} onClick={downloadSketch}>
163163
{t('Nav.File.Download')}
164164
</NavMenuItem>
165165
<NavMenuItem
@@ -172,7 +172,7 @@ const ProjectMenu = (props) => {
172172
hideIf={
173173
!getConfig('UI_COLLECTIONS_ENABLED') ||
174174
!user.authenticated ||
175-
!project?.id
175+
isUnsaved
176176
}
177177
href={`/${user.username}/sketches/${project?.id}/add-to-collection`}
178178
>
@@ -278,7 +278,7 @@ const UnauthenticatedUserMenu = () => {
278278
};
279279

280280
const AuthenticatedUserMenu = () => {
281-
const user = useSelector((state) => state.user);
281+
const username = useSelector((state) => state.user.username);
282282

283283
const { t } = useTranslation();
284284
const dispatch = useDispatch();
@@ -290,20 +290,20 @@ const AuthenticatedUserMenu = () => {
290290
id="account"
291291
title={
292292
<span>
293-
{t('Nav.Auth.Hello')}, {user.username}!
293+
{t('Nav.Auth.Hello')}, {username}!
294294
</span>
295295
}
296296
>
297-
<NavMenuItem href={`/${user.username}/sketches`}>
297+
<NavMenuItem href={`/${username}/sketches`}>
298298
{t('Nav.Auth.MySketches')}
299299
</NavMenuItem>
300300
<NavMenuItem
301-
href={`/${user.username}/collections`}
301+
href={`/${username}/collections`}
302302
hideIf={!getConfig('UI_COLLECTIONS_ENABLED')}
303303
>
304304
{t('Nav.Auth.MyCollections')}
305305
</NavMenuItem>
306-
<NavMenuItem href={`/${user.username}/assets`}>
306+
<NavMenuItem href={`/${username}/assets`}>
307307
{t('Nav.Auth.MyAssets')}
308308
</NavMenuItem>
309309
<NavMenuItem href="/account">{t('Preferences.Settings')}</NavMenuItem>

client/modules/IDE/hooks/index.js

Lines changed: 1 addition & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1 @@
1-
import { useDispatch, useSelector } from 'react-redux';
2-
import { useTranslation } from 'react-i18next';
3-
import { useParams } from 'react-router';
4-
import {
5-
autosaveProject,
6-
exportProjectAsZip,
7-
newProject,
8-
saveProject,
9-
setProjectName
10-
} from '../actions/project';
11-
import { showToast } from '../actions/toast';
12-
import { showErrorModal, showShareModal } from '../actions/ide';
13-
14-
export const useSketchActions = () => {
15-
const unsavedChanges = useSelector((state) => state.ide.unsavedChanges);
16-
const authenticated = useSelector((state) => state.user.authenticated);
17-
const project = useSelector((state) => state.project);
18-
const currentUser = useSelector((state) => state.user.username);
19-
const dispatch = useDispatch();
20-
const { t } = useTranslation();
21-
const params = useParams();
22-
23-
function newSketch() {
24-
if (!unsavedChanges) {
25-
dispatch(showToast('Toast.OpenedNewSketch'));
26-
dispatch(newProject());
27-
} else if (window.confirm(t('Nav.WarningUnsavedChanges'))) {
28-
dispatch(showToast('Toast.OpenedNewSketch'));
29-
dispatch(newProject());
30-
}
31-
}
32-
33-
function saveSketch(cmController) {
34-
if (authenticated) {
35-
dispatch(saveProject(cmController?.getContent()));
36-
} else {
37-
dispatch(showErrorModal('forceAuthentication'));
38-
}
39-
}
40-
41-
function downloadSketch() {
42-
dispatch(autosaveProject());
43-
dispatch(exportProjectAsZip(project.id));
44-
}
45-
46-
function shareSketch() {
47-
const { username } = params;
48-
dispatch(showShareModal(project.id, project.name, username));
49-
}
50-
51-
function changeSketchName(name) {
52-
const newProjectName = name.trim();
53-
if (newProjectName.length > 0) {
54-
dispatch(setProjectName(newProjectName));
55-
if (project.id) dispatch(saveProject());
56-
}
57-
}
58-
59-
function canEditProjectName() {
60-
return (
61-
(project.owner &&
62-
project.owner.username &&
63-
project.owner.username === currentUser) ||
64-
!project.owner ||
65-
!project.owner.username
66-
);
67-
}
68-
69-
return {
70-
newSketch,
71-
saveSketch,
72-
downloadSketch,
73-
shareSketch,
74-
changeSketchName,
75-
canEditProjectName
76-
};
77-
};
1+
export { default as useSketchActions } from './useSketchActions';
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { useDispatch, useSelector } from 'react-redux';
2+
import { useTranslation } from 'react-i18next';
3+
import { useParams } from 'react-router';
4+
import {
5+
autosaveProject,
6+
exportProjectAsZip,
7+
newProject,
8+
saveProject,
9+
setProjectName
10+
} from '../actions/project';
11+
import { showToast } from '../actions/toast';
12+
import { showErrorModal, showShareModal } from '../actions/ide';
13+
14+
const useSketchActions = () => {
15+
const unsavedChanges = useSelector((state) => state.ide.unsavedChanges);
16+
const authenticated = useSelector((state) => state.user.authenticated);
17+
const project = useSelector((state) => state.project);
18+
const currentUser = useSelector((state) => state.user.username);
19+
const dispatch = useDispatch();
20+
const { t } = useTranslation();
21+
const params = useParams();
22+
23+
function newSketch() {
24+
if (!unsavedChanges) {
25+
dispatch(showToast('Toast.OpenedNewSketch'));
26+
dispatch(newProject());
27+
} else if (window.confirm(t('Nav.WarningUnsavedChanges'))) {
28+
dispatch(showToast('Toast.OpenedNewSketch'));
29+
dispatch(newProject());
30+
}
31+
}
32+
33+
function saveSketch(cmController) {
34+
if (authenticated) {
35+
dispatch(saveProject(cmController?.getContent()));
36+
} else {
37+
dispatch(showErrorModal('forceAuthentication'));
38+
}
39+
}
40+
41+
function downloadSketch() {
42+
dispatch(autosaveProject());
43+
dispatch(exportProjectAsZip(project.id));
44+
}
45+
46+
function shareSketch() {
47+
const { username } = params;
48+
dispatch(showShareModal(project.id, project.name, username));
49+
}
50+
51+
function changeSketchName(name) {
52+
const newProjectName = name.trim();
53+
if (newProjectName.length > 0) {
54+
dispatch(setProjectName(newProjectName));
55+
if (project.id) dispatch(saveProject());
56+
}
57+
}
58+
59+
function canEditProjectName() {
60+
return (
61+
(project.owner &&
62+
project.owner.username &&
63+
project.owner.username === currentUser) ||
64+
!project.owner ||
65+
!project.owner.username
66+
);
67+
}
68+
69+
return {
70+
newSketch,
71+
saveSketch,
72+
downloadSketch,
73+
shareSketch,
74+
changeSketchName,
75+
canEditProjectName
76+
};
77+
};
78+
79+
export default useSketchActions;

0 commit comments

Comments
 (0)