diff --git a/package-lock.json b/package-lock.json index 5fc5ae9..9123eba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,7 @@ "react-dom": "^18.3.1", "react-router-dom": "^6.28.0", "react-scripts": "5.0.1", + "react-snowfall": "^2.2.0", "semver": "^7.6.3", "url-join": "^5.0.0" }, @@ -15305,6 +15306,12 @@ "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" }, + "node_modules/react-fast-compare": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==", + "license": "MIT" + }, "node_modules/react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", @@ -16201,6 +16208,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/react-snowfall": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/react-snowfall/-/react-snowfall-2.2.0.tgz", + "integrity": "sha512-dRk7vEHq/ZUOG+JHk2k/hH3HmliOWGXr4rKRDeW4mjWuHeI1r5h0Lc1r2jnTtUS1im702d6tCmNGymlNTdhXYg==", + "license": "MIT", + "dependencies": { + "react-fast-compare": "^3.2.2" + }, + "peerDependencies": { + "react": "^16.8 || 17.x || 18.x", + "react-dom": "^16.8 || 17.x || 18.x" + } + }, "node_modules/react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", @@ -30070,6 +30090,11 @@ "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" }, + "react-fast-compare": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" + }, "react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", @@ -30628,6 +30653,14 @@ } } }, + "react-snowfall": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/react-snowfall/-/react-snowfall-2.2.0.tgz", + "integrity": "sha512-dRk7vEHq/ZUOG+JHk2k/hH3HmliOWGXr4rKRDeW4mjWuHeI1r5h0Lc1r2jnTtUS1im702d6tCmNGymlNTdhXYg==", + "requires": { + "react-fast-compare": "^3.2.2" + } + }, "react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", diff --git a/package.json b/package.json index 154664a..e1aa623 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "react-dom": "^18.3.1", "react-router-dom": "^6.28.0", "react-scripts": "5.0.1", + "react-snowfall": "^2.2.0", "semver": "^7.6.3", "url-join": "^5.0.0" }, diff --git a/src/App.js b/src/App.js index bd1ac03..4c0d6c4 100644 --- a/src/App.js +++ b/src/App.js @@ -34,6 +34,7 @@ import { FeatureProvider } from './feature' import { auth } from './api' import { isTokenExpired } from './util' import SnackbarWithDetails from './components/util/SnackbarWithDetails' +import Snowfall from 'react-snowfall' export let originalGetContrastText @@ -47,6 +48,7 @@ export const SearchParamContext = React.createContext() const App = () => { const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)') const [themeMode, setThemeMode] = React.useState(prefersDarkMode) + const [showSnowflakes, setShowSnowflakes] = React.useState(true) React.useEffect(() => { setThemeMode(prefersDarkMode) @@ -120,6 +122,14 @@ const App = () => { lightRed: { main: '#d32f2f', }, + snowflake: { + main: themeMode ? '#ffffff' : '#6994b7', + }, + snowflakeIcon: palette.augmentColor({ + color: { + main: '#65adff', + } + }), mode: themeMode ? 'dark' : 'light', }, bomButton: { @@ -134,6 +144,8 @@ const App = () => { prefersDarkMode: themeMode, switchThemeMode: switchThemeMode, getContrastText: theme.palette.getContrastText, + toggleSnowflakes: () => setShowSnowflakes(prev => !prev), + showSnowflakes: showSnowflakes, } const featureListenerRegistrationHandler = (state, action) => { @@ -225,6 +237,12 @@ const App = () => { + {showSnowflakes && } diff --git a/src/components/util/SettingsMenu.js b/src/components/util/SettingsMenu.js index 728450c..845592e 100644 --- a/src/components/util/SettingsMenu.js +++ b/src/components/util/SettingsMenu.js @@ -1,7 +1,7 @@ import React from 'react' import PropTypes from 'prop-types' -import { Logout, Login, Settings } from '@mui/icons-material' +import { Logout, Login, Settings, AcUnit } from '@mui/icons-material' import MenuBookIcon from '@mui/icons-material/MenuBook' import { @@ -15,7 +15,9 @@ import { ListItemButton, ListItemText, Popover, + Switch, Tooltip, + Typography, } from '@mui/material' import AutoAwesomeIcon from '@mui/icons-material/AutoAwesome' @@ -27,13 +29,14 @@ import { features, TOKEN_KEY, errorSnackbarProps } from '../../consts.js' import { auth } from '../../api.js' import DarkModeSwitch from './DarkModeSwitch.js' import FeatureDependent from './FeatureDependent.js' -import { FeatureRegistrationContext } from '../../App.js' +import { ConfigContext, FeatureRegistrationContext } from '../../App.js' import { registerCallbackHandler } from '../../feature.js' export const SettingsMenu = () => { const theme = useTheme() const featureRegistrationContext = React.useContext(FeatureRegistrationContext) + const context = React.useContext(ConfigContext) const [dashboardCreateIssueUrlFeature, setDashboardCreateIssueUrlFeature] = React.useState() const [anchorElement, setAnchorElement] = React.useState(null) @@ -97,6 +100,25 @@ export const SettingsMenu = () => { > + + Winter is coming + } + checkedIcon={} + /> +