feat: 添加暗黑模式

This commit is contained in:
kuaifan 2022-01-20 00:17:32 +08:00
parent 071ca80bae
commit 3bb0b55955
14 changed files with 572 additions and 5 deletions

View File

@ -114,7 +114,9 @@
language = 'zh'
break;
}
this.url = $A.originUrl('js/grapheditor/' + (this.readOnly ? 'viewer' : 'index') + '.html?lang=' + language);
let route = this.readOnly ? 'viewer' : 'index';
let theme = $A.dark.isDarkEnabled() ? 'dark' : 'light'
this.url = $A.originUrl('js/grapheditor/' + route + '.html?lang=' + language + '&theme=' + theme);
},
mounted() {
window.addEventListener('message', this.handleMessage)

View File

@ -159,7 +159,7 @@ export default {
"name": this.userInfo.nickname
},
"customization": {
"uiTheme": "theme-classic-light",
"uiTheme": $A.dark.isDarkEnabled() ? "theme-dark" : "theme-classic-light",
},
"callbackUrl": 'http://nginx/api/file/content/office?id=' + fileKey + '&token=' + this.userToken,
}

View File

@ -250,6 +250,7 @@
resize: !isFull,
convert_urls:false,
toolbar_mode: 'sliding',
content_css: $A.dark.isDarkEnabled() ? 'dark' : 'default',
setup: (editor) => {
editor.ui.registry.addMenuButton('uploadImages', {
text: this.$L('图片'),

View File

@ -502,5 +502,176 @@
},
});
/**
* =============================================================================
* ********************************** dark *********************************
* =============================================================================
*/
$.extend({
dark: {
utils: {
filter: '-webkit-filter: url(#dark-mode-filter) !important; filter: url(#dark-mode-filter) !important;',
reverseFilter: '-webkit-filter: url(#dark-mode-reverse-filter) !important; filter: url(#dark-mode-reverse-filter) !important;',
noneFilter: '-webkit-filter: none !important; filter: none !important;',
addExtraStyle() {
try {
return '';
} catch (e) {
return '';
}
},
addStyle(id, tag, css) {
tag = tag || 'style';
let doc = document, styleDom = doc.getElementById(id);
if (styleDom) return;
let style = doc.createElement(tag);
style.rel = 'stylesheet';
style.id = id;
tag === 'style' ? style.innerHTML = css : style.href = css;
document.head.appendChild(style);
},
getClassList(node) {
return node.classList || [];
},
addClass(node, name) {
this.getClassList(node).add(name);
return this;
},
removeClass(node, name) {
this.getClassList(node).remove(name);
return this;
},
hasClass(node, name) {
return this.getClassList(node).contains(name);
},
hasElementById(eleId) {
return document.getElementById(eleId);
},
removeElementById(eleId) {
let ele = document.getElementById(eleId);
ele && ele.parentNode.removeChild(ele);
},
},
createDarkFilter() {
if (this.utils.hasElementById('dark-mode-svg')) return;
let svgDom = '<svg id="dark-mode-svg" style="height: 0; width: 0;"><filter id="dark-mode-filter" x="0" y="0" width="99999" height="99999"><feColorMatrix type="matrix" values="0.283 -0.567 -0.567 0.000 0.925 -0.567 0.283 -0.567 0.000 0.925 -0.567 -0.567 0.283 0.000 0.925 0.000 0.000 0.000 1.000 0.000"></feColorMatrix></filter><filter id="dark-mode-reverse-filter" x="0" y="0" width="99999" height="99999"><feColorMatrix type="matrix" values="0.333 -0.667 -0.667 0.000 1.000 -0.667 0.333 -0.667 0.000 1.000 -0.667 -0.667 0.333 0.000 1.000 0.000 0.000 0.000 1.000 0.000"></feColorMatrix></filter></svg>';
let div = document.createElementNS('http://www.w3.org/1999/xhtml', 'div');
div.innerHTML = svgDom;
let frag = document.createDocumentFragment();
while (div.firstChild)
frag.appendChild(div.firstChild);
document.head.appendChild(frag);
},
createDarkStyle() {
this.utils.addStyle('dark-mode-style', 'style', `
@media screen {
html {
${this.utils.filter}
}
/* Default Reverse rule */
img,
video,
iframe,
canvas,
:not(object):not(body) > embed,
object,
svg image,
[style*="background:url"],
[style*="background-image:url"],
[style*="background: url"],
[style*="background-image: url"],
[background],
twitterwidget,
.sr-reader,
.no-dark-mode,
.sr-backdrop {
${this.utils.reverseFilter}
}
[style*="background:url"] *,
[style*="background-image:url"] *,
[style*="background: url"] *,
[style*="background-image: url"] *,
input,
[background] *,
twitterwidget .NaturalImage-image {
${this.utils.noneFilter}
}
/* Text contrast */
html {
text-shadow: 0 0 0 !important;
}
/* Full screen */
.no-filter,
:-webkit-full-screen,
:-webkit-full-screen *,
:-moz-full-screen,
:-moz-full-screen *,
:fullscreen,
:fullscreen * {
${this.utils.noneFilter}
}
/* Page background */
html {
background: #fff !important;
}
${this.utils.addExtraStyle()}
}
@media print {
.no-print {
display: none !important;
}
}`);
},
enableDarkMode() {
if (this.isDarkEnabled()) {
return
}
this.createDarkFilter();
this.createDarkStyle();
this.utils.addClass(document.body, "dark-mode-reverse")
},
disableDarkMode() {
if (!this.isDarkEnabled()) {
return
}
this.utils.removeElementById('dark-mode-svg');
this.utils.removeElementById('dark-mode-style');
this.utils.removeClass(document.body, "dark-mode-reverse")
},
autoDarkMode() {
let darkScheme = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
if (darkScheme) {
this.enableDarkMode()
} else {
this.disableDarkMode()
}
},
isDarkEnabled() {
return this.utils.hasClass(document.body, "dark-mode-reverse")
},
}
});
window.$A = $;
})(window);

View File

@ -22,6 +22,17 @@
:key="key"
:divided="!!item.divided"
:name="item.path">{{$L(item.name)}}</DropdownItem>
<Dropdown placement="right-start" @on-click="setTheme">
<DropdownItem divided>
<div class="manage-menu-language">
{{$L('主题皮肤')}}
<Icon type="ios-arrow-forward"></Icon>
</div>
</DropdownItem>
<DropdownMenu slot="list">
<Dropdown-item v-for="(item, key) in themeList" :key="key" :name="item.value" :selected="themeMode === item.value">{{$L(item.name)}}</Dropdown-item>
</DropdownMenu>
</Dropdown>
<Dropdown placement="right-start" @on-click="setLanguage">
<DropdownItem divided>
<div class="manage-menu-language">
@ -302,7 +313,10 @@ export default {
'cacheProjects',
'projectTotal',
'taskId',
'wsOpenNum'
'wsOpenNum',
'themeMode',
'themeList'
]),
...mapGetters(['taskData', 'dashboardTask']),
@ -454,6 +468,22 @@ export default {
}
},
setTheme(mode) {
switch (mode) {
case 'dark':
$A.dark.enableDarkMode()
break;
case 'light':
$A.dark.disableDarkMode()
break;
default:
$A.dark.autoDarkMode()
break;
}
this.$store.state.themeMode = mode;
$A.setStorage("cacheThemeMode", mode);
},
toggleRoute(path) {
this.show768Menu = false;
this.goForward({path: '/manage/' + path});

View File

@ -386,6 +386,7 @@ export default {
return new Promise(function (resolve) {
try {
const cacheLoginEmail = $A.getStorageString("cacheLoginEmail");
const cacheThemeMode = $A.getStorageString("cacheThemeMode");
//
window.localStorage.clear();
//
@ -398,6 +399,7 @@ export default {
$A.setStorage("cacheProjectParameter", state.cacheProjectParameter);
$A.setStorage("cacheServerUrl", state.cacheServerUrl);
$A.setStorage("cacheLoginEmail", cacheLoginEmail);
$A.setStorage("cacheThemeMode", cacheThemeMode);
dispatch("saveUserInfo", $A.isJson(userInfo) ? userInfo : state.userInfo);
//
resolve()

View File

@ -107,4 +107,23 @@ state.taskColorList = [
{name: '灰色', color: '#f3f3f3'},
];
// 主题皮肤
state.themeMode = $A.getStorageString("cacheThemeMode", "auto");
state.themeList = [
{name: '跟随系统', value: 'auto'},
{name: '明亮', value: 'light'},
{name: '暗黑', value: 'dark'},
];
switch (state.themeMode) {
case 'dark':
$A.dark.enableDarkMode()
break;
case 'light':
$A.dark.disableDarkMode()
break;
default:
$A.dark.autoDarkMode()
break;
}
export default state

View File

@ -8,3 +8,5 @@
@import "components/_";
@import "pages/_";
@import "dark";

157
resources/assets/sass/dark.scss vendored Normal file
View File

@ -0,0 +1,157 @@
body.dark-mode-reverse {
.ivu-btn-primary,
.ivu-badge-count,
.common-app-down-link {
color: #000;
}
.ivu-select-dropdown {
box-shadow: rgba(255, 255, 255, 0.2) 0 1px 6px;
}
.ivu-modal-mask {
background-color: rgba(230, 230, 230, 0.6);
}
.ivu-modal-content {
box-shadow: 0 4px 12px rgba(255, 255, 255, 0.15);
}
.ivu-tooltip-inner,
.ivu-poptip-inner {
border: 1px solid #e3e8ed;
box-shadow: none;
}
.el-dropdown-menu {
border-color: #e3e8ed;
box-shadow: 0 2px 12px 0 rgba(255, 255, 255, 0.1);
}
.el-tooltip__popper {
&.is-light {
border: 1px solid #e3e8ed;
box-shadow: 0 1px 6px rgba(255, 255, 255, 0.2);
}
}
.drawer-overlay {
background: rgba(240, 240, 240, 0.76);
.overlay-body {
.overlay-close {
> a {
color: #323232;
}
}
}
}
.file-content,
.file-preview {
.content-body {
.tox {
.tox-edit-area__iframe {
background-color: #000;
}
}
.teditor-loadedstyle {
.tox-sidebar-wrap {
box-shadow: none
}
}
}
}
.minder-editor-container {
.quickbar {
border: 1px solid #e3e8ed !important;
box-shadow: 3px 3px 10px rgba(255, 255, 255, .2) !important;
}
}
.project-list {
.project-head {
.project-titbox {
.project-icons {
> li {
&.project-icon {
&.active {
color: #000000;
}
}
}
}
}
}
}
.page-manage {
.manage-box-menu {
.manage-box-dropdown {
.manage-box-title {
&.menu-visible {
box-shadow: 0 1px 6px rgba(255, 255, 255, 0.2);
}
}
}
}
}
.page-dashboard {
.dashboard-wrapper {
.dashboard-block {
> li {
.block-title {
color: rgba(0, 0, 0, 0.6);
font-size: 12px;
}
.block-data {
.block-num {
color: #000;
}
.taskfont {
color: rgba(0, 0, 0, 0.7);
}
}
}
}
}
}
.page-messenger {
.messenger-wrapper {
.messenger-select {
.messenger-list {
> ul {
&.dialog {
> li {
.icon-avatar {
color: #1c1917;
}
}
}
}
}
}
}
}
.page-file {
.file-wrapper {
.file-list {
> ul {
> li {
.file-icon {
.share-icon,
.share-avatar {
.taskfont {
color: #3a3a3a;
}
}
}
}
}
}
}
}
}

View File

@ -44,6 +44,7 @@
<script type="text/javascript" src="js/Dialogs.js"></script>
</head>
<body class="geEditor">
<script type="text/javascript" src="js/Dark.js"></script>
<script type="text/javascript">
(function () {
var editorUiInit = EditorUi.prototype.init;

View File

@ -0,0 +1,165 @@
var Dark = {
utils: {
filter: '-webkit-filter: url(#dark-mode-filter) !important; filter: url(#dark-mode-filter) !important;',
reverseFilter: '-webkit-filter: url(#dark-mode-reverse-filter) !important; filter: url(#dark-mode-reverse-filter) !important;',
noneFilter: '-webkit-filter: none !important; filter: none !important;',
addExtraStyle() {
try {
return '';
} catch (e) {
return '';
}
},
addStyle(id, tag, css) {
tag = tag || 'style';
let doc = document, styleDom = doc.getElementById(id);
if (styleDom) return;
let style = doc.createElement(tag);
style.rel = 'stylesheet';
style.id = id;
tag === 'style' ? style.innerHTML = css : style.href = css;
document.head.appendChild(style);
},
getClassList(node) {
return node.classList || [];
},
addClass(node, name) {
this.getClassList(node).add(name);
return this;
},
removeClass(node, name) {
this.getClassList(node).remove(name);
return this;
},
hasClass(node, name) {
return this.getClassList(node).contains(name);
},
hasElementById(eleId) {
return document.getElementById(eleId);
},
removeElementById(eleId) {
let ele = document.getElementById(eleId);
ele && ele.parentNode.removeChild(ele);
},
},
createDarkFilter() {
if (this.utils.hasElementById('dark-mode-svg')) return;
let svgDom = '<svg id="dark-mode-svg" style="height: 0; width: 0;"><filter id="dark-mode-filter" x="0" y="0" width="99999" height="99999"><feColorMatrix type="matrix" values="0.283 -0.567 -0.567 0.000 0.925 -0.567 0.283 -0.567 0.000 0.925 -0.567 -0.567 0.283 0.000 0.925 0.000 0.000 0.000 1.000 0.000"></feColorMatrix></filter><filter id="dark-mode-reverse-filter" x="0" y="0" width="99999" height="99999"><feColorMatrix type="matrix" values="0.333 -0.667 -0.667 0.000 1.000 -0.667 0.333 -0.667 0.000 1.000 -0.667 -0.667 0.333 0.000 1.000 0.000 0.000 0.000 1.000 0.000"></feColorMatrix></filter></svg>';
let div = document.createElementNS('http://www.w3.org/1999/xhtml', 'div');
div.innerHTML = svgDom;
let frag = document.createDocumentFragment();
while (div.firstChild)
frag.appendChild(div.firstChild);
document.head.appendChild(frag);
},
createDarkStyle() {
this.utils.addStyle('dark-mode-style', 'style', `
@media screen {
html {
${this.utils.filter}
}
/* Default Reverse rule */
img,
video,
iframe,
canvas,
:not(object):not(body) > embed,
object,
svg image {
${this.utils.reverseFilter}
}
[style*="background:url"] *,
[style*="background-image:url"] *,
[style*="background: url"] *,
[style*="background-image: url"] *,
input,
[background] *,
twitterwidget .NaturalImage-image {
${this.utils.noneFilter}
}
/* Text contrast */
html {
text-shadow: 0 0 0 !important;
}
/* Full screen */
.no-filter,
:-webkit-full-screen,
:-webkit-full-screen *,
:-moz-full-screen,
:-moz-full-screen *,
:fullscreen,
:fullscreen * {
${this.utils.noneFilter}
}
/* Page background */
html {
background: #fff !important;
}
${this.utils.addExtraStyle()}
}
@media print {
.no-print {
display: none !important;
}
}`);
},
enableDarkMode() {
if (this.isDarkEnabled()) {
return
}
this.createDarkFilter();
this.createDarkStyle();
this.utils.addClass(document.body, "dark-mode-reverse")
},
disableDarkMode() {
if (!this.isDarkEnabled()) {
return
}
this.utils.removeElementById('dark-mode-svg');
this.utils.removeElementById('dark-mode-style');
this.utils.removeClass(document.body, "dark-mode-reverse")
},
autoDarkMode() {
let darkScheme = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
if (darkScheme) {
this.enableDarkMode()
} else {
this.disableDarkMode()
}
},
isDarkEnabled() {
return this.utils.hasClass(document.body, "dark-mode-reverse")
},
};
switch (window.mxTheme) {
case 'dark':
Dark.enableDarkMode();
break;
case 'light':
Dark.disableDarkMode();
break;
default:
Dark.autoDarkMode();
break;
}

View File

@ -27,3 +27,4 @@ window.OPEN_FORM = window.OPEN_FORM || 'open.html';
window.mxBasePath = window.mxBasePath || '../../../src';
window.mxLanguage = window.mxLanguage || urlParams['lang'] || 'zh';
window.mxLanguages = window.mxLanguages || ['zh'];
window.mxTheme = window.mxTheme || urlParams['theme'] || 'light';

View File

@ -5,12 +5,28 @@
* For commercial licenses see https://www.tiny.cloud/
*/
body {
background-color: #2f3742;
background-color: #131313;
color: #dfe0e4;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
line-height: 1.4;
margin: 1rem;
}
::-webkit-scrollbar {
background-color: #202324;
color: #aba499;
}
::-webkit-scrollbar-thumb {
background-color: #454a4d;
}
::-webkit-scrollbar-thumb:hover {
background-color: #575e62;
}
::-webkit-scrollbar-thumb:active {
background-color: #484e51;
}
::-webkit-scrollbar-corner {
background-color: #181a1b;
}
a {
color: #4099ff;
}

View File

@ -4,4 +4,4 @@
* For LGPL see License.txt in the project root for license information.
* For commercial licenses see https://www.tiny.cloud/
*/
body{background-color:#2f3742;color:#dfe0e4;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif;line-height:1.4;margin:1rem}a{color:#4099ff}table{border-collapse:collapse}table:not([cellpadding]) td,table:not([cellpadding]) th{padding:.4rem}table[border]:not([border="0"]):not([style*=border-width]) td,table[border]:not([border="0"]):not([style*=border-width]) th{border-width:1px}table[border]:not([border="0"]):not([style*=border-style]) td,table[border]:not([border="0"]):not([style*=border-style]) th{border-style:solid}table[border]:not([border="0"]):not([style*=border-color]) td,table[border]:not([border="0"]):not([style*=border-color]) th{border-color:#6d737b}figure{display:table;margin:1rem auto}figure figcaption{color:#8a8f97;display:block;margin-top:.25rem;text-align:center}hr{border-color:#6d737b;border-style:solid;border-width:1px 0 0 0}code{background-color:#6d737b;border-radius:3px;padding:.1rem .2rem}.mce-content-body:not([dir=rtl]) blockquote{border-left:2px solid #6d737b;margin-left:1.5rem;padding-left:1rem}.mce-content-body[dir=rtl] blockquote{border-right:2px solid #6d737b;margin-right:1.5rem;padding-right:1rem}
body{background-color:#131313;color:#dfe0e4;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif;line-height:1.4;margin:1rem}::-webkit-scrollbar{background-color:#202324;color:#aba499}::-webkit-scrollbar-thumb{background-color:#454a4d}::-webkit-scrollbar-thumb:hover{background-color:#575e62}::-webkit-scrollbar-thumb:active{background-color:#484e51}::-webkit-scrollbar-corner{background-color:#181a1b}a{color:#4099ff}table{border-collapse:collapse}table:not([cellpadding]) td,table:not([cellpadding]) th{padding:.4rem}table[border]:not([border="0"]):not([style*=border-width]) td,table[border]:not([border="0"]):not([style*=border-width]) th{border-width:1px}table[border]:not([border="0"]):not([style*=border-style]) td,table[border]:not([border="0"]):not([style*=border-style]) th{border-style:solid}table[border]:not([border="0"]):not([style*=border-color]) td,table[border]:not([border="0"]):not([style*=border-color]) th{border-color:#6d737b}figure{display:table;margin:1rem auto}figure figcaption{color:#8a8f97;display:block;margin-top:.25rem;text-align:center}hr{border-color:#6d737b;border-style:solid;border-width:1px 0 0 0}code{background-color:#6d737b;border-radius:3px;padding:.1rem .2rem}.mce-content-body:not([dir=rtl]) blockquote{border-left:2px solid #6d737b;margin-left:1.5rem;padding-left:1rem}.mce-content-body[dir=rtl] blockquote{border-right:2px solid #6d737b;margin-right:1.5rem;padding-right:1rem}