mirror of
https://github.com/EGroupware/egroupware.git
synced 2025-02-24 14:11:29 +01:00
Introduce dark/light mode theme switch into framework
This commit is contained in:
parent
7011faba18
commit
f21ac58c87
@ -63,6 +63,9 @@ var fw_base = (function(){ "use strict"; return Class.extend(
|
|||||||
|
|
||||||
// keep track of opened popups
|
// keep track of opened popups
|
||||||
this.popups = [];
|
this.popups = [];
|
||||||
|
|
||||||
|
// initiate dark mode
|
||||||
|
this._setDarkMode(egw.preference('darkmode', 'common'));
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1299,5 +1302,10 @@ var fw_base = (function(){ "use strict"; return Class.extend(
|
|||||||
isAnInternalApp: function(_app)
|
isAnInternalApp: function(_app)
|
||||||
{
|
{
|
||||||
return _app && _app.appName != _app.internalName;
|
return _app && _app.appName != _app.internalName;
|
||||||
|
},
|
||||||
|
|
||||||
|
_setDarkMode: function(_state)
|
||||||
|
{
|
||||||
|
jQuery('html').attr('data-darkmode', _state);
|
||||||
}
|
}
|
||||||
});}).call(this);
|
});}).call(this);
|
||||||
|
@ -535,6 +535,27 @@
|
|||||||
execPushBroadcastAppStatus: function(_data)
|
execPushBroadcastAppStatus: function(_data)
|
||||||
{
|
{
|
||||||
if (app.status) app.status.mergeContent(_data, true);
|
if (app.status) app.status.mergeContent(_data, true);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param node
|
||||||
|
*/
|
||||||
|
toggle_darkmode: function(node)
|
||||||
|
{
|
||||||
|
let state = node.firstElementChild.classList.contains('darkmode_on');
|
||||||
|
egw.set_preference('common', 'darkmode',state?'0':'1');
|
||||||
|
this._setDarkMode(state?'0':'1');
|
||||||
|
if (state == 1)
|
||||||
|
{
|
||||||
|
node.firstElementChild.classList.remove('darkmode_on');
|
||||||
|
node.firstElementChild.title = egw.lang('light mode');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
node.firstElementChild.classList.add('darkmode_on');
|
||||||
|
node.firstElementChild.title = egw.lang('dark mode');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})(window);
|
})(window);
|
||||||
|
@ -117,6 +117,8 @@ var EgwApp = /** @class */ (function () {
|
|||||||
this._set_Window_title();
|
this._set_Window_title();
|
||||||
// Highlights the favorite based on initial list state
|
// Highlights the favorite based on initial list state
|
||||||
this.highlight_favorite();
|
this.highlight_favorite();
|
||||||
|
// apply theme mode
|
||||||
|
jQuery('html').attr('data-darkmode', egw.preference('darkmode', 'common'));
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* Observer method receives update notifications from all applications
|
* Observer method receives update notifications from all applications
|
||||||
|
@ -207,6 +207,8 @@ export abstract class EgwApp
|
|||||||
|
|
||||||
// Highlights the favorite based on initial list state
|
// Highlights the favorite based on initial list state
|
||||||
this.highlight_favorite();
|
this.highlight_favorite();
|
||||||
|
// apply theme mode
|
||||||
|
jQuery('html').attr('data-darkmode', <string> egw.preference('darkmode', 'common'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -534,6 +534,7 @@ abstract class Framework extends Framework\Extra
|
|||||||
'dir_code' => lang('language_direction_rtl') != 'rtl' ? '' : ' dir="rtl"',
|
'dir_code' => lang('language_direction_rtl') != 'rtl' ? '' : ' dir="rtl"',
|
||||||
'include_wz_tooltip'=> $include_wz_tooltip,
|
'include_wz_tooltip'=> $include_wz_tooltip,
|
||||||
'webserver_url' => $GLOBALS['egw_info']['server']['webserver_url'],
|
'webserver_url' => $GLOBALS['egw_info']['server']['webserver_url'],
|
||||||
|
'darkmode' => $GLOBALS['egw_info']['user']['preferences']['common']['darkmode']
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -670,6 +671,17 @@ abstract class Framework extends Framework\Extra
|
|||||||
return '<span title="'.lang("Print current view").'"</span>';
|
return '<span title="'.lang("Print current view").'"</span>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns darkmode menu
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected static function _darkmode_menu()
|
||||||
|
{
|
||||||
|
$mode = $GLOBALS['egw_info']['user']['preferences']['common']['darkmode'] == 1?'dark':'light';
|
||||||
|
return '<span title="'.lang("%1 mode", $mode).'" class="'.
|
||||||
|
($mode == 'dark'?'darkmode_on':'').'"> </span>';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare the current users
|
* Prepare the current users
|
||||||
@ -1177,7 +1189,8 @@ abstract class Framework extends Framework\Extra
|
|||||||
'update' => ($update = Framework\Updates::notification()) ? $update : null,
|
'update' => ($update = Framework\Updates::notification()) ? $update : null,
|
||||||
'notifications' => ($GLOBALS['egw_info']['user']['apps']['notifications']) ? self::_get_notification_bell() : null,
|
'notifications' => ($GLOBALS['egw_info']['user']['apps']['notifications']) ? self::_get_notification_bell() : null,
|
||||||
'quick_add' => $vars['quick_add'],
|
'quick_add' => $vars['quick_add'],
|
||||||
'print_title' => $this->_print_menu()
|
'print_title' => $this->_print_menu(),
|
||||||
|
'darkmode' => self::_darkmode_menu()
|
||||||
];
|
];
|
||||||
|
|
||||||
// array of topmenu items (orders of the items matter)
|
// array of topmenu items (orders of the items matter)
|
||||||
|
@ -43,6 +43,18 @@
|
|||||||
* Stefan Reinhardt
|
* Stefan Reinhardt
|
||||||
*/
|
*/
|
||||||
/*@import (less) "../../api/templates/default/etemplate2.css";*/
|
/*@import (less) "../../api/templates/default/etemplate2.css";*/
|
||||||
|
/**
|
||||||
|
* DARK THEME
|
||||||
|
*/
|
||||||
|
@media all {
|
||||||
|
html[data-darkmode='1'] {
|
||||||
|
background: #000;
|
||||||
|
filter: invert(1) hue-rotate(180deg);
|
||||||
|
}
|
||||||
|
html[data-darkmode='1'] img {
|
||||||
|
filter: invert(1) hue-rotate(180deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
@media all {
|
@media all {
|
||||||
/**
|
/**
|
||||||
* Top level
|
* Top level
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!-- BEGIN head --><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
<!-- BEGIN head --><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
<html xml:lang="{lang_code}" xmlns="http://www.w3.org/1999/xhtml"{dir_code}>
|
<html xml:lang="{lang_code}" xmlns="http://www.w3.org/1999/xhtml"{dir_code} data-darkmode={darkmode}>
|
||||||
<head>
|
<head>
|
||||||
<title>{website_title}</title>
|
<title>{website_title}</title>
|
||||||
<meta http-equiv="content-type" content="text/html; charset={charset}" />
|
<meta http-equiv="content-type" content="text/html; charset={charset}" />
|
||||||
|
24
pixelegg/images/darkmode_off.svg
Normal file
24
pixelegg/images/darkmode_off.svg
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="#62686A"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
|
||||||
|
>
|
||||||
|
<circle fill="#FFF49C" cx="12" cy="12" r="5"/>
|
||||||
|
<g stroke="#62686A">
|
||||||
|
<line x1="12" y1="1" x2="12" y2="3" />
|
||||||
|
<line x1="12" y1="21" x2="12" y2="23" />
|
||||||
|
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64" />
|
||||||
|
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78" />
|
||||||
|
<line x1="1" y1="12" x2="3" y2="12" />
|
||||||
|
<line x1="21" y1="12" x2="23" y2="12" />
|
||||||
|
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36" />
|
||||||
|
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 659 B |
17
pixelegg/images/darkmode_on.svg
Normal file
17
pixelegg/images/darkmode_on.svg
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="#62686A"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<mask id="mask" >
|
||||||
|
<rect x="0" y="0" width="100%" height="100%" fill="white" />
|
||||||
|
<circle cx="5" cy="16" r="9" fill="black" />
|
||||||
|
</mask>
|
||||||
|
<circle fill="#FFF49C" cx="12" cy="12" r="9" mask="url(#mask)" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 408 B |
@ -124,6 +124,7 @@
|
|||||||
window.framework = new fw_pixelegg("egw_fw_sidemenu", "egw_fw_tabs",
|
window.framework = new fw_pixelegg("egw_fw_sidemenu", "egw_fw_tabs",
|
||||||
window.egw_webserverUrl, egw_setSideboxSize,"egw_fw_splitter", 255, 245); // should be identical to jdots_framework::(DEFAULT|MIN)_SIDEBAR_WIDTH
|
window.egw_webserverUrl, egw_setSideboxSize,"egw_fw_splitter", 255, 245); // should be identical to jdots_framework::(DEFAULT|MIN)_SIDEBAR_WIDTH
|
||||||
window.callManual = window.framework.callManual;
|
window.callManual = window.framework.callManual;
|
||||||
|
jQuery('#topmenu_info_darkmode').click(function(){window.framework.toggle_darkmode(this);});
|
||||||
jQuery('#topmenu_info_user_avatar').click(function(){window.framework.toggle_avatar_menu();});
|
jQuery('#topmenu_info_user_avatar').click(function(){window.framework.toggle_avatar_menu();});
|
||||||
jQuery('#topmenu_info_print_title').click(function(){window.framework.print();});
|
jQuery('#topmenu_info_print_title').click(function(){window.framework.print();});
|
||||||
jQuery('#topmenu_info_logout').click(function(){ window.framework.redirect(this.getAttribute('data-logout-url')); });
|
jQuery('#topmenu_info_logout').click(function(){ window.framework.redirect(this.getAttribute('data-logout-url')); });
|
||||||
|
@ -10,9 +10,24 @@
|
|||||||
@import (reference) "./def_buttons.less";
|
@import (reference) "./def_buttons.less";
|
||||||
/*@import (less) "../../api/templates/default/etemplate2.css";*/
|
/*@import (less) "../../api/templates/default/etemplate2.css";*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DARK THEME
|
||||||
|
*/
|
||||||
|
@media all {
|
||||||
|
|
||||||
|
html[data-darkmode='1'] {
|
||||||
|
background: #000;
|
||||||
|
filter: invert(1) hue-rotate(180deg)
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-darkmode='1'] img {
|
||||||
|
filter: invert(1) hue-rotate(180deg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media all {
|
@media all {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Top level
|
* Top level
|
||||||
*/
|
*/
|
||||||
|
@ -108,6 +108,23 @@
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*darkmode*/
|
||||||
|
#topmenu_info_darkmode {
|
||||||
|
span {
|
||||||
|
background-image: url(../images/darkmode_off.svg);
|
||||||
|
width: 45px;
|
||||||
|
height: 45px;
|
||||||
|
display: inline-block;
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.darkmode_on {
|
||||||
|
background-image: url(../images/darkmode_on.svg);
|
||||||
|
filter:invert(1) hue-rotate(180deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*Notification*/
|
/*Notification*/
|
||||||
#topmenu_info_notifications {
|
#topmenu_info_notifications {
|
||||||
line-height: 45px;
|
line-height: 45px;
|
||||||
|
@ -178,6 +178,15 @@ class preferences_hooks
|
|||||||
'admin' => False,
|
'admin' => False,
|
||||||
'forced' => file_exists(EGW_SERVER_ROOT.'/pixelegg') ? 'pixelegg' : 'idots',
|
'forced' => file_exists(EGW_SERVER_ROOT.'/pixelegg') ? 'pixelegg' : 'idots',
|
||||||
),
|
),
|
||||||
|
'darkmode' => array(
|
||||||
|
'type' => 'select',
|
||||||
|
'label' => 'Dark mode theme',
|
||||||
|
'name' => 'darkmode',
|
||||||
|
'values' => array('0' => 'off', '1' => 'on'),
|
||||||
|
'help' => 'Dark mode theme',
|
||||||
|
'admin' => False,
|
||||||
|
'default' => '0'
|
||||||
|
),
|
||||||
'audio_effect'=> array(
|
'audio_effect'=> array(
|
||||||
'type' => 'select',
|
'type' => 'select',
|
||||||
'label' => 'Audio effect',
|
'label' => 'Audio effect',
|
||||||
|
Loading…
Reference in New Issue
Block a user