diff --git a/README.md b/README.md
index aa18076069..cdd7a447d0 100644
--- a/README.md
+++ b/README.md
@@ -31,17 +31,6 @@ If you have found a bug in the p5.js Web Editor, you can file it under the ["iss
To see which pull requests and issues are currently being reviewed, check the [PR Review Board](https://github.com/processing/p5.js-web-editor/projects/9) or the following Milestones: [MINOR Release](https://github.com/processing/p5.js-web-editor/milestone/8).
-Issues and Pull Requests categorized under the PATCH or MINOR Release Milestones will be prioritized since they are planned to be merged for the next release to Production. Please feel free to [comment on this pinned issue](https://github.com/processing/p5.js-web-editor/issues/2534) if you would like your issue to be considered for the next release!
-
-
-### When Will the Next Production Release Be?
-
-We will aim to deploy on a 1-2 month basis. Here are some dates we’re working towards:
-
-2.12.0 MINOR Release: By February 27, 2024
-
-[You can read more about Semantic Versioning and the differences between a MINOR and PATCH release](https://semver.org/).
-
## References for Contributing to the p5.js Web Editor
diff --git a/client/common/icons.jsx b/client/common/icons.jsx
index 5fe685be9b..13d2e18092 100644
--- a/client/common/icons.jsx
+++ b/client/common/icons.jsx
@@ -25,8 +25,6 @@ import CircleInfo from '../images/circle-info.svg';
import Add from '../images/add.svg';
import Filter from '../images/filter.svg';
import Cross from '../images/cross.svg';
-import Lock from '../images/lock.svg';
-import UnLock from '../images/unlock.svg';
// HOC that adds the right web accessibility props
// https://www.scottohara.me/blog/2019/05/22/contextual-images-svgs-and-a11y.html
@@ -104,5 +102,3 @@ export const CircleFolderIcon = withLabel(CircleFolder);
export const CircleInfoIcon = withLabel(CircleInfo);
export const AddIcon = withLabel(Add);
export const FilterIcon = withLabel(Filter);
-export const LockIcon = withLabel(Lock);
-export const UnlockIcon = withLabel(UnLock);
diff --git a/client/components/Dropdown/TableDropdown.jsx b/client/components/Dropdown/TableDropdown.jsx
index d4db78f963..44f4f27fd6 100644
--- a/client/components/Dropdown/TableDropdown.jsx
+++ b/client/components/Dropdown/TableDropdown.jsx
@@ -1,20 +1,18 @@
import React from 'react';
-import { useMediaQuery } from 'react-responsive';
import styled from 'styled-components';
import { prop, remSize } from '../../theme';
import DropdownMenu from './DropdownMenu';
import DownFilledTriangleIcon from '../../images/down-filled-triangle.svg';
import MoreIconSvg from '../../images/more.svg';
+import useIsMobile from '../../modules/IDE/hooks/useIsMobile';
const DotsHorizontal = styled(MoreIconSvg)`
transform: rotate(90deg);
`;
const TableDropdownIcon = () => {
- // TODO: centralize breakpoints
- const isMobile = useMediaQuery({ maxWidth: 770 });
-
+ const isMobile = useIsMobile();
return isMobile ? (
) : (
diff --git a/client/constants.js b/client/constants.js
index bc27fadaba..d2b1007b90 100644
--- a/client/constants.js
+++ b/client/constants.js
@@ -138,9 +138,6 @@ export const SET_SORT_PARAMS = 'SET_SORT_PARAMS';
export const SET_SEARCH_TERM = 'SET_SEARCH_TERM';
export const CLOSE_SKETCHLIST_MODAL = 'CLOSE_SKETCHLIST_MODAL';
-export const START_LOADING = 'START_LOADING';
-export const STOP_LOADING = 'STOP_LOADING';
-
export const START_SAVING_PROJECT = 'START_SAVING_PROJECT';
export const END_SAVING_PROJECT = 'END_SAVING_PROJECT';
diff --git a/client/images/lock.svg b/client/images/lock.svg
deleted file mode 100644
index 6f4d4af4c8..0000000000
--- a/client/images/lock.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-
\ No newline at end of file
diff --git a/client/images/lockgif.gif b/client/images/lockgif.gif
deleted file mode 100644
index b0a08e2cca..0000000000
Binary files a/client/images/lockgif.gif and /dev/null differ
diff --git a/client/images/unlock.svg b/client/images/unlock.svg
deleted file mode 100644
index fc20a1fdeb..0000000000
--- a/client/images/unlock.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-
diff --git a/client/modules/App/components/ThemeProvider.jsx b/client/modules/App/components/ThemeProvider.jsx
index a168d856d9..8bbef6931e 100644
--- a/client/modules/App/components/ThemeProvider.jsx
+++ b/client/modules/App/components/ThemeProvider.jsx
@@ -1,23 +1,18 @@
import React from 'react';
import PropTypes from 'prop-types';
-import { connect } from 'react-redux';
+import { useSelector } from 'react-redux';
import { ThemeProvider } from 'styled-components';
+import theme from '../../../theme';
-import theme, { Theme } from '../../../theme';
-
-const Provider = ({ children, currentTheme }) => (
- {children}
-);
+const Provider = ({ children }) => {
+ const currentTheme = useSelector((state) => state.preferences.theme);
+ return (
+ {children}
+ );
+};
Provider.propTypes = {
- children: PropTypes.node.isRequired,
- currentTheme: PropTypes.oneOf(Object.keys(Theme)).isRequired
+ children: PropTypes.node.isRequired
};
-function mapStateToProps(state) {
- return {
- currentTheme: state.preferences.theme
- };
-}
-
-export default connect(mapStateToProps)(Provider);
+export default Provider;
diff --git a/client/modules/IDE/actions/assets.js b/client/modules/IDE/actions/assets.js
index 333dfd0ab2..ecd16fb7c6 100644
--- a/client/modules/IDE/actions/assets.js
+++ b/client/modules/IDE/actions/assets.js
@@ -1,6 +1,6 @@
import apiClient from '../../../utils/apiClient';
import * as ActionTypes from '../../../constants';
-import { startLoader, stopLoader } from './loader';
+import { startLoader, stopLoader } from '../reducers/loading';
import { assetsActions } from '../reducers/assets';
const { setAssets, deleteAsset } = assetsActions;
diff --git a/client/modules/IDE/actions/collections.js b/client/modules/IDE/actions/collections.js
index e8bda9623f..32790e681e 100644
--- a/client/modules/IDE/actions/collections.js
+++ b/client/modules/IDE/actions/collections.js
@@ -1,7 +1,7 @@
import browserHistory from '../../../browserHistory';
import apiClient from '../../../utils/apiClient';
import * as ActionTypes from '../../../constants';
-import { startLoader, stopLoader } from './loader';
+import { startLoader, stopLoader } from '../reducers/loading';
import { setToastText, showToast } from './toast';
const TOAST_DISPLAY_TIME_MS = 1500;
@@ -80,7 +80,7 @@ export function addToCollection(collectionId, projectId) {
const collectionName = response.data.name;
- dispatch(setToastText(`Added to "${collectionName}`));
+ dispatch(setToastText(`Added to "${collectionName}"`));
dispatch(showToast(TOAST_DISPLAY_TIME_MS));
return response.data;
@@ -110,7 +110,7 @@ export function removeFromCollection(collectionId, projectId) {
const collectionName = response.data.name;
- dispatch(setToastText(`Removed from "${collectionName}`));
+ dispatch(setToastText(`Removed from "${collectionName}"`));
dispatch(showToast(TOAST_DISPLAY_TIME_MS));
return response.data;
diff --git a/client/modules/IDE/actions/loader.js b/client/modules/IDE/actions/loader.js
deleted file mode 100644
index f331094c02..0000000000
--- a/client/modules/IDE/actions/loader.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import * as ActionTypes from '../../../constants';
-
-export function startLoader() {
- return { type: ActionTypes.START_LOADING };
-}
-
-export function stopLoader() {
- return { type: ActionTypes.STOP_LOADING };
-}
diff --git a/client/modules/IDE/actions/project.js b/client/modules/IDE/actions/project.js
index 4516fa669d..e55bac1a6a 100644
--- a/client/modules/IDE/actions/project.js
+++ b/client/modules/IDE/actions/project.js
@@ -411,7 +411,7 @@ export function deleteProject(id) {
};
}
-export function changeVisibility(projectId, visibility) {
+export function changeVisibility(projectId, projectName, visibility) {
return (dispatch) =>
apiClient
.patch('/project/visibility', { projectId, visibility })
@@ -423,7 +423,7 @@ export function changeVisibility(projectId, visibility) {
payload: { visibility: response.data.visibility }
});
- dispatch(setToastText(`Sketch is ${newVisibility}`));
+ dispatch(setToastText(`The ${projectName} is now ${newVisibility}!`));
dispatch(showToast(2000));
})
.catch((error) => {
diff --git a/client/modules/IDE/actions/projects.js b/client/modules/IDE/actions/projects.js
index eb9984cf54..34ca2a35bf 100644
--- a/client/modules/IDE/actions/projects.js
+++ b/client/modules/IDE/actions/projects.js
@@ -1,6 +1,6 @@
import apiClient from '../../../utils/apiClient';
import * as ActionTypes from '../../../constants';
-import { startLoader, stopLoader } from './loader';
+import { startLoader, stopLoader } from '../reducers/loading';
// eslint-disable-next-line
export function getProjects(username) {
diff --git a/client/modules/IDE/actions/projects.unit.test.js b/client/modules/IDE/actions/projects.unit.test.js
index 6fce08c796..95a6205520 100644
--- a/client/modules/IDE/actions/projects.unit.test.js
+++ b/client/modules/IDE/actions/projects.unit.test.js
@@ -5,6 +5,7 @@ import { rest } from 'msw';
import * as ProjectActions from './projects';
import * as ActionTypes from '../../../constants';
+import { startLoader, stopLoader } from '../reducers/loading';
import {
initialTestState,
mockProjects
@@ -33,9 +34,9 @@ describe('projects action creator tests', () => {
store = mockStore(initialTestState);
const expectedActions = [
- { type: ActionTypes.START_LOADING },
+ { type: startLoader.type },
{ type: ActionTypes.SET_PROJECTS, projects: mockProjects },
- { type: ActionTypes.STOP_LOADING }
+ { type: stopLoader.type }
];
return store
diff --git a/client/modules/IDE/components/About.jsx b/client/modules/IDE/components/About.jsx
index d22ec2c631..67c259c571 100644
--- a/client/modules/IDE/components/About.jsx
+++ b/client/modules/IDE/components/About.jsx
@@ -162,6 +162,20 @@ function About(props) {
{t('About.Discord')}
+
+
+
+ Donate
+
+
section {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 5px;
+ }
+
> h5 {
font-size: ${remSize(13)};
font-weight: normal;
@@ -203,6 +211,7 @@ const LanguageSelect = styled.div`
const MobileNav = () => {
const project = useSelector((state) => state.project);
const user = useSelector((state) => state.user);
+ const dispatch = useDispatch();
const { t } = useTranslation();
@@ -228,19 +237,53 @@ const MobileNav = () => {
}
const title = useMemo(resolveTitle, [pageName, project.name]);
+ const userIsOwner = user?.username === project.owner?.username;
const Logo = AsteriskIcon;
+
+ const toggleVisibility = (e) => {
+ try {
+ const isChecked = e.target.checked;
+
+ dispatch(
+ changeVisibility(
+ project.id,
+ project.name,
+ isChecked ? 'Private' : 'Public'
+ )
+ );
+ } catch (error) {
+ console.log(error);
+ }
+ };
return (