diff --git a/Dockerfile b/Dockerfile index ac21908220..3c18288058 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,6 +14,7 @@ COPY .babelrc index.js nodemon.json ./ COPY ./webpack ./webpack COPY client ./client COPY server ./server +COPY common ./common COPY translations/locales ./translations/locales COPY public ./public CMD ["npm", "start"] diff --git a/client/modules/IDE/components/Preferences/index.jsx b/client/modules/IDE/components/Preferences/index.jsx index 2b8b8e19fd..b9f5dd2b3a 100644 --- a/client/modules/IDE/components/Preferences/index.jsx +++ b/client/modules/IDE/components/Preferences/index.jsx @@ -21,7 +21,12 @@ import { setLinewrap, setPreferencesTab } from '../../actions/preferences'; -import { p5SoundURL, p5URL, useP5Version } from '../../hooks/useP5Version'; +import { + majorVersion, + p5SoundURL, + p5URL, + useP5Version +} from '../../hooks/useP5Version'; import VersionPicker from '../VersionPicker'; import { updateFileContent } from '../../actions/files'; import { CmControllerContext } from '../../pages/IDEView'; @@ -55,7 +60,7 @@ export default function Preferences() { const timerRef = useRef(null); const pickerRef = useRef(null); const onChangeVersion = (version) => { - const shouldShowStars = version.startsWith('2.'); + const shouldShowStars = majorVersion(version) === '2'; const box = pickerRef.current?.getBoundingClientRect(); if (shouldShowStars) { setShowStars({ left: box?.left || 0, top: box?.top || 0 }); @@ -578,17 +583,7 @@ export default function Preferences() { { - if (versionInfo.lastP5SoundURL) { - // If the sketch previously used a nonstandard p5.sound - // URL, restore that URL - updateHTML( - versionInfo.setP5SoundURL(versionInfo.lastP5SoundURL) - ); - versionInfo.setLastP5SoundURL(undefined); - } else { - // Otherwise, turn on the default p5.sound URL - updateHTML(versionInfo.setP5Sound(true)); - } + updateHTML(versionInfo.setP5Sound(true)); }} aria-label={`${t('Preferences.SoundAddon')} ${t( 'Preferences.AddonOn' @@ -605,12 +600,6 @@ export default function Preferences() { { - // If the previous p5.sound.js script tag is not the - // default version that one will get via this toggle, - // record it so we can give the option to put it back - if (versionInfo.p5SoundURL !== p5SoundURL) { - versionInfo.setLastP5SoundURL(versionInfo.p5SoundURL); - } updateHTML(versionInfo.setP5Sound(false)); }} aria-label={`${t('Preferences.SoundAddon')} ${t( @@ -628,11 +617,20 @@ export default function Preferences() { > {t('Preferences.Off')} - {versionInfo.lastP5SoundURL && ( - - {t('Preferences.UndoSoundVersion')} - - )} + + + {t('Preferences.SoundReference').replace( + '$VERSION', + versionInfo.version + )} + +
diff --git a/client/modules/IDE/components/VersionPicker.jsx b/client/modules/IDE/components/VersionPicker.jsx index a42743d353..c80a35e806 100644 --- a/client/modules/IDE/components/VersionPicker.jsx +++ b/client/modules/IDE/components/VersionPicker.jsx @@ -5,7 +5,8 @@ import PropTypes from 'prop-types'; import styled from 'styled-components'; import { prop } from '../../../theme'; -import { useP5Version, p5Versions } from '../hooks/useP5Version'; +import { useP5Version } from '../hooks/useP5Version'; +import { p5Versions } from '../../../../common/p5Versions'; import MenuItem from '../../../components/Dropdown/MenuItem'; import DropdownMenu from '../../../components/Dropdown/DropdownMenu'; import { updateFileContent } from '../actions/files'; diff --git a/client/modules/IDE/hooks/useP5Version.jsx b/client/modules/IDE/hooks/useP5Version.jsx index 03ba3d0da4..643a01cf7e 100644 --- a/client/modules/IDE/hooks/useP5Version.jsx +++ b/client/modules/IDE/hooks/useP5Version.jsx @@ -1,150 +1,17 @@ /* eslint-disable func-names */ -import React, { useContext, useMemo, useState } from 'react'; +import React, { useContext, useMemo } from 'react'; import { useSelector } from 'react-redux'; import PropTypes from 'prop-types'; +import { currentP5Version, p5Versions } from '../../../../common/p5Versions'; -// Generated from https://www.npmjs.com/package/p5?activeTab=versions -// Run this in the console: -// JSON.stringify([...document.querySelectorAll('._132722c7')].map(n => n.innerText), null, 2) -// TODO: use their API for this to grab these at build time? -export const p5Versions = [ - '2.0.3', - '2.0.2', - '2.0.1', - '2.0.0', - '1.11.8', - '1.11.7', - '1.11.6', - '1.11.5', - '1.11.4', - '1.11.3', - '1.11.2', - '1.11.1', - '1.11.0', - '1.10.0', - '1.9.4', - '1.9.3', - '1.9.2', - '1.9.1', - '1.9.0', - '1.8.0', - '1.7.0', - '1.6.0', - '1.5.0', - '1.4.2', - '1.4.1', - '1.4.0', - '1.3.1', - '1.3.0', - '1.2.0', - '1.1.9', - '1.1.8', - '1.1.7', - '1.1.5', - '1.1.4', - '1.1.3', - '1.1.2', - '1.1.1', - '1.1.0', - '1.0.0', - '0.10.2', - '0.10.1', - '0.10.0', - '0.9.0', - '0.8.0', - '0.7.3', - '0.7.2', - '0.7.1', - '0.7.0', - '0.6.1', - '0.6.0', - '0.5.16', - '0.5.15', - '0.5.14', - '0.5.13', - '0.5.12', - '0.5.11', - '0.5.10', - '0.5.9', - '0.5.8', - '0.5.7', - '0.5.6', - '0.5.5', - '0.5.4', - '0.5.3', - '0.5.2', - '0.5.1', - '0.5.0', - '0.4.24', - '0.4.23', - '0.4.22', - '0.4.21', - '0.4.20', - '0.4.19', - '0.4.18', - '0.4.17', - '0.4.16', - '0.4.15', - '0.4.14', - '0.4.13', - '0.4.12', - '0.4.11', - '0.4.10', - '0.4.9', - '0.4.8', - '0.4.7', - '0.4.6', - '0.4.5', - '0.4.4', - '0.4.3', - '0.4.2', - '0.4.1', - '0.4.0', - '0.3.16', - '0.3.15', - '0.3.14', - '0.3.13', - '0.3.12', - '0.3.11', - '0.3.10', - '0.3.9', - '0.3.8', - '0.3.7', - '0.3.6', - '0.3.5', - '0.3.4', - '0.3.3', - '0.3.2', - '0.3.1', - '0.3.0', - '0.2.23', - '0.2.22', - '0.2.21', - '0.2.20', - '0.2.19', - '0.2.18', - '0.2.17', - '0.2.16', - '0.2.15', - '0.2.14', - '0.2.13', - '0.2.12', - '0.2.11', - '0.2.10', - '0.2.9', - '0.2.8', - '0.2.7', - '0.2.6', - '0.2.5', - '0.2.4', - '0.2.3', - '0.2.2', - '0.2.1' -]; +export const majorVersion = (version) => version.split('.')[0]; -export const currentP5Version = '1.11.5'; // Don't update to 2.x until 2026 - -export const p5SoundURLOld = `https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.3/addons/p5.sound.min.js`; +export const p5SoundURLOldTemplate = + 'https://cdnjs.cloudflare.com/ajax/libs/p5.js/$VERSION/addons/p5.sound.min.js'; +export const p5SoundURLOld = p5SoundURLOldTemplate.replace( + '$VERSION', + currentP5Version +); export const p5SoundURL = 'https://cdn.jsdelivr.net/npm/p5.sound@0.2.0/dist/p5.sound.min.js'; export const p5PreloadAddonURL = @@ -168,8 +35,6 @@ export function P5VersionProvider(props) { const indexSrc = indexFile?.content; const indexID = indexFile?.id; - const [lastP5SoundURL, setLastP5SoundURL] = useState(undefined); - // { version: string, minified: boolean, replaceVersion: (version: string) => string } | null const versionInfo = useMemo(() => { if (!indexSrc) return null; @@ -207,14 +72,6 @@ export function P5VersionProvider(props) { // We only know for certain which one we've got if if (usedP5Versions.length === 1) { const { version, minified, scriptNode } = usedP5Versions[0]; - const replaceVersion = function (newVersion) { - const file = minified ? 'p5.min.js' : 'p5.js'; - scriptNode.setAttribute( - 'src', - `https://cdn.jsdelivr.net/npm/p5@${newVersion}/lib/${file}` - ); - return serializeResult(); - }; const p5SoundNode = [ ...dom.documentElement.querySelectorAll('script') @@ -232,7 +89,9 @@ export function P5VersionProvider(props) { const newNode = document.createElement('script'); newNode.setAttribute( 'src', - version.startsWith('2') ? p5SoundURL : p5SoundURLOld + majorVersion(version) === '2' + ? p5SoundURL + : p5SoundURLOldTemplate.replace('$VERSION', version) ); scriptNode.parentNode.insertBefore(newNode, scriptNode.nextSibling); } @@ -250,6 +109,31 @@ export function P5VersionProvider(props) { return serializeResult(); }; + const replaceVersion = function (newVersion) { + const file = minified ? 'p5.min.js' : 'p5.js'; + scriptNode.setAttribute( + 'src', + `https://cdn.jsdelivr.net/npm/p5@${newVersion}/lib/${file}` + ); + + if (p5SoundNode) { + if (majorVersion(version) !== majorVersion(newVersion)) { + // Turn off p5.sound if the user switched from 1.x to 2.x + setP5Sound(false); + } else { + // Replace the existing p5.sound with the one compatible with + // the new version + setP5SoundURL( + majorVersion(version) === '2' + ? p5SoundURL + : p5SoundURLOldTemplate.replace('$VERSION', newVersion) + ); + } + } + + return serializeResult(); + }; + const p5PreloadAddonNode = [ ...dom.documentElement.querySelectorAll('script') ].find((s) => s.getAttribute('src') === p5PreloadAddonURL); @@ -294,14 +178,13 @@ export function P5VersionProvider(props) { return { version, + isVersion2: majorVersion(version) === '2', minified, replaceVersion, p5Sound: !!p5SoundNode, setP5Sound, setP5SoundURL, p5SoundURL: p5SoundNode?.getAttribute('src'), - lastP5SoundURL, - setLastP5SoundURL, p5PreloadAddon: !!p5PreloadAddonNode, setP5PreloadAddon, p5ShapesAddon: !!p5ShapesAddonNode, diff --git a/client/styles/components/_preferences.scss b/client/styles/components/_preferences.scss index 0ef44a9e48..b77a6e85fa 100644 --- a/client/styles/components/_preferences.scss +++ b/client/styles/components/_preferences.scss @@ -150,8 +150,12 @@ .preference__warning { @include themify() { display: contents; - font-weight: bold; - color: getThemifyVariable("preferences-warning-color"); + & a { + color: getThemifyVariable('button-background-hover-color'); + } + & a:hover { + text-decoration: underline; + } } } diff --git a/common/p5Versions.js b/common/p5Versions.js new file mode 100644 index 0000000000..c467bb7861 --- /dev/null +++ b/common/p5Versions.js @@ -0,0 +1,140 @@ +export const currentP5Version = '1.11.8'; // Don't update to 2.x until 2026 + +// Generated from https://www.npmjs.com/package/p5?activeTab=versions +// Run this in the console: +// JSON.stringify([...document.querySelectorAll('._132722c7')].map(n => n.innerText), null, 2) +// TODO: use their API for this to grab these at build time? +export const p5Versions = [ + '2.0.3', + '2.0.2', + '2.0.1', + '2.0.0', + '1.11.8', + '1.11.7', + '1.11.6', + '1.11.5', + '1.11.4', + '1.11.3', + '1.11.2', + '1.11.1', + '1.11.0', + '1.10.0', + '1.9.4', + '1.9.3', + '1.9.2', + '1.9.1', + '1.9.0', + '1.8.0', + '1.7.0', + '1.6.0', + '1.5.0', + '1.4.2', + '1.4.1', + '1.4.0', + '1.3.1', + '1.3.0', + '1.2.0', + '1.1.9', + '1.1.8', + '1.1.7', + '1.1.5', + '1.1.4', + '1.1.3', + '1.1.2', + '1.1.1', + '1.1.0', + '1.0.0', + '0.10.2', + '0.10.1', + '0.10.0', + '0.9.0', + '0.8.0', + '0.7.3', + '0.7.2', + '0.7.1', + '0.7.0', + '0.6.1', + '0.6.0', + '0.5.16', + '0.5.15', + '0.5.14', + '0.5.13', + '0.5.12', + '0.5.11', + '0.5.10', + '0.5.9', + '0.5.8', + '0.5.7', + '0.5.6', + '0.5.5', + '0.5.4', + '0.5.3', + '0.5.2', + '0.5.1', + '0.5.0', + '0.4.24', + '0.4.23', + '0.4.22', + '0.4.21', + '0.4.20', + '0.4.19', + '0.4.18', + '0.4.17', + '0.4.16', + '0.4.15', + '0.4.14', + '0.4.13', + '0.4.12', + '0.4.11', + '0.4.10', + '0.4.9', + '0.4.8', + '0.4.7', + '0.4.6', + '0.4.5', + '0.4.4', + '0.4.3', + '0.4.2', + '0.4.1', + '0.4.0', + '0.3.16', + '0.3.15', + '0.3.14', + '0.3.13', + '0.3.12', + '0.3.11', + '0.3.10', + '0.3.9', + '0.3.8', + '0.3.7', + '0.3.6', + '0.3.5', + '0.3.4', + '0.3.3', + '0.3.2', + '0.3.1', + '0.3.0', + '0.2.23', + '0.2.22', + '0.2.21', + '0.2.20', + '0.2.19', + '0.2.18', + '0.2.17', + '0.2.16', + '0.2.15', + '0.2.14', + '0.2.13', + '0.2.12', + '0.2.11', + '0.2.10', + '0.2.9', + '0.2.8', + '0.2.7', + '0.2.6', + '0.2.5', + '0.2.4', + '0.2.3', + '0.2.2', + '0.2.1' +]; diff --git a/server/domain-objects/createDefaultFiles.js b/server/domain-objects/createDefaultFiles.js index 37349dfd01..70eddee3ed 100644 --- a/server/domain-objects/createDefaultFiles.js +++ b/server/domain-objects/createDefaultFiles.js @@ -1,3 +1,5 @@ +import { currentP5Version } from '../../common/p5Versions'; + export const defaultSketch = `function setup() { createCanvas(400, 400); } @@ -9,8 +11,8 @@ function draw() { export const defaultHTML = ` - - + + diff --git a/translations/locales/en-US/translations.json b/translations/locales/en-US/translations.json index afbb6e5057..0f24da021a 100644 --- a/translations/locales/en-US/translations.json +++ b/translations/locales/en-US/translations.json @@ -228,7 +228,7 @@ "DataAddon": "p5.js 1.x Compatibility Add-on Library — Data Structures", "AddonOnARIA": "on", "AddonOffARIA": "off", - "UndoSoundVersion": "Want to use p5.sound.js again? Turning it back on will restore the version you were using before.", + "SoundReference": "View the reference for p5.sound compatible with p5.js $VERSION", "CopyToClipboardSuccess": "Copied to clipboard!", "CopyToClipboardFailure": "We weren't able to copy the text, try selecting it and copying it manually." },