diff --git a/docs/en_US/images/preferences_misc_themes.png b/docs/en_US/images/preferences_misc_themes.png index b3a3a34b1..770fbf6ce 100644 Binary files a/docs/en_US/images/preferences_misc_themes.png and b/docs/en_US/images/preferences_misc_themes.png differ diff --git a/docs/en_US/preferences.rst b/docs/en_US/preferences.rst index 8df26d56d..0a0ff3154 100644 --- a/docs/en_US/preferences.rst +++ b/docs/en_US/preferences.rst @@ -282,7 +282,8 @@ Expand the *Miscellaneous* node to specify miscellaneous display preferences. * Use the *Themes* drop-down listbox to select the theme for pgAdmin. You'll also get a preview just below the drop down. You can also submit your own themes, check `here `_ how. - Currently we support Standard, Dark and High Contrast theme. + Currently we support Standard, Dark and High Contrast and System theme. Selecting System option will follow + your computer's settings. The Paths Node ************** diff --git a/web/pgadmin/misc/__init__.py b/web/pgadmin/misc/__init__.py index b8c01a645..a9466bafa 100644 --- a/web/pgadmin/misc/__init__.py +++ b/web/pgadmin/misc/__init__.py @@ -20,7 +20,6 @@ from pgadmin.utils import PgAdminModule, replace_binary_path, \ from pgadmin.utils.csrf import pgCSRFProtect from pgadmin.utils.session import cleanup_session_files from pgadmin.misc.themes import get_all_themes -from pgadmin.utils.constants import MIMETYPE_APP_JS, UTILITIES_ARRAY from pgadmin.utils.ajax import precondition_required, make_json_response, \ internal_server_error from pgadmin.utils.heartbeat import log_server_heartbeat, \ @@ -74,20 +73,21 @@ class MiscModule(PgAdminModule): 'preview_src': url_for( 'static', filename='js/generated/img/' + theme_data['preview_img'] - ) + ) if 'preview_img' in theme_data else None }) self.preference.register( 'themes', 'theme', - gettext("Theme"), 'options', 'standard', + gettext("Theme"), 'options', 'light', category_label=gettext('Themes'), options=theme_options, control_props={ 'allowClear': False, + 'creatable': False, }, help_str=gettext( - 'A refresh is required to apply the theme. Above is the ' - 'preview of the theme' + 'Click the save button to apply the theme. Below is the ' + 'preview of the theme.' ) ) diff --git a/web/pgadmin/misc/themes/__init__.py b/web/pgadmin/misc/themes/__init__.py index 8602c1fff..4c7c2a52e 100644 --- a/web/pgadmin/misc/themes/__init__.py +++ b/web/pgadmin/misc/themes/__init__.py @@ -5,9 +5,9 @@ from pgadmin.utils.preferences import Preferences def get_all_themes(): all_themes = { - "standard": { - "disp_name": "Standard", - "preview_img": "standard_preview.png" + "light": { + "disp_name": "Light", + "preview_img": "light_preview.png" }, "dark": { "disp_name": "dark", @@ -17,5 +17,8 @@ def get_all_themes(): "disp_name": "high_contrast", "preview_img": "high_contrast_preview.png" }, + "system": { + "disp_name": "system" + }, } return all_themes diff --git a/web/pgadmin/static/img/dark_preview.png b/web/pgadmin/static/img/dark_preview.png index 301a87e43..e423d003b 100644 Binary files a/web/pgadmin/static/img/dark_preview.png and b/web/pgadmin/static/img/dark_preview.png differ diff --git a/web/pgadmin/static/img/high_contrast_preview.png b/web/pgadmin/static/img/high_contrast_preview.png index 2b9e7b964..a932e9d8f 100644 Binary files a/web/pgadmin/static/img/high_contrast_preview.png and b/web/pgadmin/static/img/high_contrast_preview.png differ diff --git a/web/pgadmin/static/img/light_preview.png b/web/pgadmin/static/img/light_preview.png new file mode 100644 index 000000000..02086dd8b Binary files /dev/null and b/web/pgadmin/static/img/light_preview.png differ diff --git a/web/pgadmin/static/img/standard_preview.png b/web/pgadmin/static/img/standard_preview.png deleted file mode 100644 index 755bdf586..000000000 Binary files a/web/pgadmin/static/img/standard_preview.png and /dev/null differ diff --git a/web/pgadmin/static/js/Theme/index.jsx b/web/pgadmin/static/js/Theme/index.jsx index 801032e80..afe113cb7 100644 --- a/web/pgadmin/static/js/Theme/index.jsx +++ b/web/pgadmin/static/js/Theme/index.jsx @@ -773,10 +773,11 @@ function getFinalTheme(baseTheme) { /* In future, this will be moved to App container */ export default function Theme({children}) { const prefStore = usePreferences(); - const [themeName, setThemeName] = useState(prefStore.getPreferencesForModule('misc')?.theme); + const [currentTheme, setCurrentTheme] = useState(prefStore.getPreferencesForModule('misc')?.theme); + const themeObj = useMemo(()=>{ let baseTheme = getStandardTheme(basicSettings); - switch(themeName) { + switch(currentTheme) { case 'dark': baseTheme = getDarkTheme(baseTheme); break; @@ -785,11 +786,20 @@ export default function Theme({children}) { break; } return getFinalTheme(baseTheme); - }, [themeName]); + }, [currentTheme]); useEffect(() => usePreferences.subscribe( state => { - setThemeName(state.getPreferencesForModule('misc').theme); + let selectdTheme = state.getPreferencesForModule('misc').theme; + if(selectdTheme === 'system'){ + const themeQuery = window.matchMedia('(prefers-color-scheme: light)'); + setCurrentTheme(themeQuery.matches ? 'light' : 'dark'); + themeQuery.addEventListener('change', ({ matches }) => { + setCurrentTheme(matches ? 'light' : 'dark'); + }); + }else{ + setCurrentTheme(selectdTheme); + } } ), []); diff --git a/web/pgadmin/static/js/components/FormComponents.jsx b/web/pgadmin/static/js/components/FormComponents.jsx index 68fc0f9f6..80e1b035b 100644 --- a/web/pgadmin/static/js/components/FormComponents.jsx +++ b/web/pgadmin/static/js/components/FormComponents.jsx @@ -1211,8 +1211,8 @@ export function FormInputSelectThemes({ hasError, label, className, helpMessage, const cid = _.uniqueId('c'); const helpid = `h${cid}`; return ( - - + + ); } diff --git a/web/pgadmin/static/js/components/SelectThemes.jsx b/web/pgadmin/static/js/components/SelectThemes.jsx index 26e9aa201..1927d0640 100644 --- a/web/pgadmin/static/js/components/SelectThemes.jsx +++ b/web/pgadmin/static/js/components/SelectThemes.jsx @@ -8,24 +8,29 @@ ////////////////////////////////////////////////////////////// import gettext from 'sources/gettext'; -import { Grid } from '@mui/material'; +import { Grid, FormHelperText } from '@mui/material'; import React, { useMemo } from 'react'; import {InputSelect } from './FormComponents'; import PropTypes from 'prop-types'; import CustomPropTypes from '../custom_prop_types'; +import HTMLReactParse from 'html-react-parser'; -export default function SelectThemes({onChange, ...props}) { +export default function SelectThemes({onChange, helpMessage, ...props}) { const previewSrc = useMemo(()=>(props.options?.find((o)=>o.value==props.value)?.preview_src), [props.value]); - + const cid = _.uniqueId('c'); + const helpid = `h${cid}`; return ( - + - {gettext('Preview + { previewSrc && <> + {HTMLReactParse(helpMessage || '')} + {gettext('Preview + } ); @@ -37,5 +42,6 @@ SelectThemes.propTypes = { controlProps: PropTypes.object, fields: PropTypes.array, options: PropTypes.array, - inputRef: CustomPropTypes.ref + inputRef: CustomPropTypes.ref, + helpMessage: PropTypes.string };