From 1ba5a1274c7edeebaa530ee3d48d979f6833515f Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 10 Apr 2020 22:38:29 +0100 Subject: [PATCH 1/5] Started work on supporting a dark-mode - Most elements done, but still need to do editors, tables and final pass. - Toggled only by quick js check at the moment, checking via css media query. Need to make into user-preference toggle. For #1234 --- resources/js/services/code.js | 3 +- resources/sass/_blocks.scss | 2 +- resources/sass/_buttons.scss | 7 ++- resources/sass/_codemirror.scss | 71 ++++++++++++++++++++++-- resources/sass/_colors.scss | 8 +-- resources/sass/_forms.scss | 9 +-- resources/sass/_header.scss | 9 +-- resources/sass/_html.scss | 6 +- resources/sass/_lists.scss | 23 ++++---- resources/sass/_mixins.scss | 14 +++++ resources/sass/_tables.scss | 2 +- resources/sass/_text.scss | 28 ++++++---- resources/sass/_variables.scss | 1 + resources/sass/styles.scss | 5 +- resources/views/base.blade.php | 5 ++ resources/views/settings/index.blade.php | 12 ++-- 16 files changed, 149 insertions(+), 56 deletions(-) diff --git a/resources/js/services/code.js b/resources/js/services/code.js index 14801de9c..a7dfa587f 100644 --- a/resources/js/services/code.js +++ b/resources/js/services/code.js @@ -191,7 +191,8 @@ function getMode(suggestion, content) { * @returns {*|string} */ function getTheme() { - return window.codeTheme || 'default'; + const darkMode = document.documentElement.classList.contains('dark-mode'); + return window.codeTheme || (darkMode ? 'darcula' : 'default'); } /** diff --git a/resources/sass/_blocks.scss b/resources/sass/_blocks.scss index d02d25db4..9e04420a0 100644 --- a/resources/sass/_blocks.scss +++ b/resources/sass/_blocks.scss @@ -58,7 +58,7 @@ */ .card { - background-color: #FFF; + @include lightDark(background-color, #FFF, #222); box-shadow: $bs-card; border-radius: 3px; border: 1px solid transparent; diff --git a/resources/sass/_buttons.scss b/resources/sass/_buttons.scss index 7df1d61a4..8c8bac54e 100644 --- a/resources/sass/_buttons.scss +++ b/resources/sass/_buttons.scss @@ -22,17 +22,17 @@ button { box-shadow: none; background-color: var(--color-primary); color: #FFF; - fill: #FFF; text-transform: uppercase; border: 1px solid var(--color-primary); vertical-align: top; + @include lightDark(filter, none, saturate(0.8) brightness(0.8)); &:hover, &:focus, &:active { background-color: var(--color-primary); text-decoration: none; color: #FFFFFF; } &:hover { - box-shadow: $bs-light; + @include lightDark(box-shadow, $bs-light, $bs-dark); filter: brightness(110%); } &:focus { @@ -48,13 +48,14 @@ button { .button.outline { background-color: transparent; - color: #666; + @include lightDark(color, #666, #aaa); fill: currentColor; border: 1px solid #CCC; &:hover, &:focus, &:active { border: 1px solid #CCC; box-shadow: none; background-color: #F2F2F2; + @include lightDark(background-color, #f2f2f2, #555); filter: none; } &:active { diff --git a/resources/sass/_codemirror.scss b/resources/sass/_codemirror.scss index dc1aef9bb..c679e4899 100644 --- a/resources/sass/_codemirror.scss +++ b/resources/sass/_codemirror.scss @@ -390,6 +390,63 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;} /* STOP */ +/** + * Codemirror Darcula theme + */ + +/** + Name: IntelliJ IDEA darcula theme + From IntelliJ IDEA by JetBrains + */ + +.cm-s-darcula { font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif;} +.cm-s-darcula.CodeMirror { background: #2B2B2B; color: #A9B7C6; } + +.cm-s-darcula span.cm-meta { color: #BBB529; } +.cm-s-darcula span.cm-number { color: #6897BB; } +.cm-s-darcula span.cm-keyword { color: #CC7832; line-height: 1em; font-weight: bold; } +.cm-s-darcula span.cm-def { color: #A9B7C6; font-style: italic; } +.cm-s-darcula span.cm-variable { color: #A9B7C6; } +.cm-s-darcula span.cm-variable-2 { color: #A9B7C6; } +.cm-s-darcula span.cm-variable-3 { color: #9876AA; } +.cm-s-darcula span.cm-type { color: #AABBCC; font-weight: bold; } +.cm-s-darcula span.cm-property { color: #FFC66D; } +.cm-s-darcula span.cm-operator { color: #A9B7C6; } +.cm-s-darcula span.cm-string { color: #6A8759; } +.cm-s-darcula span.cm-string-2 { color: #6A8759; } +.cm-s-darcula span.cm-comment { color: #61A151; font-style: italic; } +.cm-s-darcula span.cm-link { color: #CC7832; } +.cm-s-darcula span.cm-atom { color: #CC7832; } +.cm-s-darcula span.cm-error { color: #BC3F3C; } +.cm-s-darcula span.cm-tag { color: #629755; font-weight: bold; font-style: italic; text-decoration: underline; } +.cm-s-darcula span.cm-attribute { color: #6897bb; } +.cm-s-darcula span.cm-qualifier { color: #6A8759; } +.cm-s-darcula span.cm-bracket { color: #A9B7C6; } +.cm-s-darcula span.cm-builtin { color: #FF9E59; } +.cm-s-darcula span.cm-special { color: #FF9E59; } +.cm-s-darcula span.cm-matchhighlight { color: #FFFFFF; background-color: rgba(50, 89, 48, .7); font-weight: normal;} +.cm-s-darcula span.cm-searching { color: #FFFFFF; background-color: rgba(61, 115, 59, .7); font-weight: normal;} + +.cm-s-darcula .CodeMirror-cursor { border-left: 1px solid #A9B7C6; } +.cm-s-darcula .CodeMirror-activeline-background { background: #323232; } +.cm-s-darcula .CodeMirror-gutters { background: #313335; border-right: 1px solid #313335; } +.cm-s-darcula .CodeMirror-guttermarker { color: #FFEE80; } +.cm-s-darcula .CodeMirror-guttermarker-subtle { color: #D0D0D0; } +.cm-s-darcula .CodeMirrir-linenumber { color: #606366; } +.cm-s-darcula .CodeMirror-matchingbracket { background-color: #3B514D; color: #FFEF28 !important; font-weight: bold; } + +.cm-s-darcula div.CodeMirror-selected { background: #214283; } + +.CodeMirror-hints.darcula { + font-family: Menlo, Monaco, Consolas, 'Courier New', monospace; + color: #9C9E9E; + background-color: #3B3E3F !important; +} + +.CodeMirror-hints.darcula .CodeMirror-hint-active { + background-color: #494D4E !important; + color: #9C9E9E !important; +} /** * Custom BookStack overrides @@ -401,7 +458,8 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;} font-size: 12px; height: auto; margin-bottom: $-l; - border: 1px solid #DDD;; + border: 1px solid; + @include lightDark(border-color, #DDD, #111) } .cm-s-mdn-like .CodeMirror-gutters { background: #f8f8f8; border-left: 0; color: #333; } @@ -424,24 +482,25 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;} top: -1px; right: -1px; background-color: #EEE; + border: 1px solid #DDD; + @include lightDark(background-color, #eee, #333); + @include lightDark(border-color, #ddd, #444); + @include lightDark(fill, #444, #888); padding: $-xs; line-height: 0; - border: 1px solid #DDD; cursor: pointer; - fill: #444; z-index: 5; - transition: all ease-in 240ms; user-select: none; opacity: 0; pointer-events: none; svg { - transition: transform ease-in 240ms; + transition: all ease-in 240ms; transform: translateY(0); } &.success { background-color: lighten($positive, 10%); - fill: #FFF; svg { + fill: #FFF; transform: translateY(-3px); } } diff --git a/resources/sass/_colors.scss b/resources/sass/_colors.scss index 77f51b324..e9ddd2214 100644 --- a/resources/sass/_colors.scss +++ b/resources/sass/_colors.scss @@ -36,13 +36,13 @@ } .text-muted { - color: #575757 !important; - fill: #575757 !important; + @include lightDark(color, #575757, #888888, true); + fill: currentColor !important; } .text-dark { - color: #222 !important; - fill: #222 !important; + @include lightDark(color, #222, #ccc, true); + fill: currentColor !important; } /* diff --git a/resources/sass/_forms.scss b/resources/sass/_forms.scss index f306a717b..535bc54ea 100644 --- a/resources/sass/_forms.scss +++ b/resources/sass/_forms.scss @@ -1,12 +1,13 @@ .input-base { - background-color: #FFF; border-radius: 3px; border: 1px solid #D4D4D4; + @include lightDark(background-color, #fff, #333); + @include lightDark(border-color, #d4d4d4, #111); + @include lightDark(color, #666, #AAA); display: inline-block; - font-size: $fs-s; + font-size: $fs-m; padding: $-xs*1.5; - color: #666; width: 250px; max-width: 100%; @@ -139,11 +140,11 @@ label { + @include lightDark(color, #666, #ddd); display: block; line-height: 1.4em; font-size: 0.94em; font-weight: 400; - color: #666; padding-bottom: 2px; margin-bottom: 0.2em; &.inline { diff --git a/resources/sass/_header.scss b/resources/sass/_header.scss index 5503a0895..1c4bf948f 100644 --- a/resources/sass/_header.scss +++ b/resources/sass/_header.scss @@ -18,11 +18,14 @@ header { display: block; z-index: 11; top: 0; - color: #fff; - fill: #fff; + color: rgb(250, 250, 250); border-bottom: 1px solid #DDD; box-shadow: $bs-card; padding: $-xxs 0; + @include lightDark(border-bottom-color, #DDD, #000); + @include whenDark { + filter: saturate(0.6) brightness(0.8); + } .links { display: inline-block; vertical-align: top; @@ -31,7 +34,6 @@ header { display: inline-block; padding: $-m; color: #FFF; - fill: #FFF; } .dropdown-container { padding-inline-start: $-m; @@ -94,7 +96,6 @@ header .search-box { } } button { - fill: #EEE; z-index: 1; left: 16px; @include rtl { diff --git a/resources/sass/_html.scss b/resources/sass/_html.scss index e4a8c14bb..57869d652 100644 --- a/resources/sass/_html.scss +++ b/resources/sass/_html.scss @@ -15,12 +15,14 @@ html { &.flexbox { overflow-y: hidden; } + &.dark-mode { + background-color: #111; + } } body { font-size: $fs-m; line-height: 1.6; - color: #444; + @include lightDark(color, #444, #AAA); -webkit-font-smoothing: antialiased; - background-color: #F2F2F2; } \ No newline at end of file diff --git a/resources/sass/_lists.scss b/resources/sass/_lists.scss index 7beb63d4e..2e12c2009 100644 --- a/resources/sass/_lists.scss +++ b/resources/sass/_lists.scss @@ -99,7 +99,7 @@ left: auto; right: 0; } - background-color: rgba(0, 0, 0, 0.2); + @include lightDark(background-color, rgba(0, 0, 0, 0.2), rgba(255, 255, 255, 0.2)); width: 2px; top: 5px; bottom: 5px; @@ -132,7 +132,7 @@ font-weight: bold; } li:not(.current-heading) .sidebar-page-nav-bullet { - background-color: #BBB !important; + @include lightDark(background-color, #BBB, #666, true); } .sidebar-page-nav-bullet { width: 6px; @@ -142,6 +142,7 @@ top: 30%; border-radius: 50%; box-shadow: 0 0 0 6px #F2F2F2; + @include lightDark(box-shadow, 0 0 0 6px #F2F2F2, 0 0 0 6px #111); z-index: 1; @include rtl { left: auto; @@ -438,7 +439,7 @@ ul.pagination { border-color: rgba(0, 0, 0, 0.1); } &:focus { - background-color: #eee; + @include lightDark(background-color, #eee, #222); outline: 1px dotted #666; outline-offset: -2px; } @@ -455,7 +456,7 @@ ul.pagination { } .card .entity-list-item:not(.no-hover):hover { - background-color: #F2F2F2; + @include lightDark(background-color, #F2F2F2, #2d2d2d) } .card .entity-list-item .entity-list-item:hover { background-color: #EEEEEE; @@ -554,14 +555,15 @@ ul.pagination { list-style: none; right: 0; margin: $-m 0; - background-color: #FFFFFF; + @include lightDark(background-color, #fff, #333); box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.1); border-radius: 1px; border: 1px solid #EEE; + @include lightDark(border-color, #eee, #000); min-width: 180px; padding: $-xs 0; - color: #555; - fill: #555; + @include lightDark(color, #555, #eee); + fill: currentColor; text-align: start !important; &.wide { min-width: 220px; @@ -576,7 +578,7 @@ ul.pagination { a, button { display: block; padding: $-xs $-m; - color: #555; + @include lightDark(color, #555, #eee); fill: currentColor; white-space: nowrap; &:hover, &:focus { @@ -653,11 +655,10 @@ ul.pagination { padding: $-s; } a:not(.active) { - color: #444; - fill: #444; + @include lightDark(color, #444, #666); } a:hover { - background-color: rgba(0, 0, 0, 0.05); + @include lightDark(background-color, rgba(0, 0, 0, 0.05), rgba(255, 255, 255, 0.05)); border-radius: 3px; text-decoration: none; } diff --git a/resources/sass/_mixins.scss b/resources/sass/_mixins.scss index 8a6becf6b..0a419c08a 100644 --- a/resources/sass/_mixins.scss +++ b/resources/sass/_mixins.scss @@ -31,4 +31,18 @@ html[dir=rtl] & { @content; } +} + +// Define a property for both light and dark mode +@mixin lightDark($prop, $light, $dark, $important: false) { + #{$prop}: if($important, $light !important, $light); + html.dark-mode & { + #{$prop}: if($important, $dark !important, $dark); + } +} + +@mixin whenDark { + html.dark-mode & { + @content; + } } \ No newline at end of file diff --git a/resources/sass/_tables.scss b/resources/sass/_tables.scss index 277873608..d0a920efc 100644 --- a/resources/sass/_tables.scss +++ b/resources/sass/_tables.scss @@ -33,7 +33,7 @@ table.table { font-weight: bold; } tr:hover { - background-color: #EEE; + @include lightDark(background-color, #eee, #333); } .text-right { text-align: end; diff --git a/resources/sass/_text.scss b/resources/sass/_text.scss index 8d2759b91..e62972497 100644 --- a/resources/sass/_text.scss +++ b/resources/sass/_text.scss @@ -42,7 +42,7 @@ h1, h2, h3, h4, h5, h6 { font-weight: 400; position: relative; display: block; - color: #222; + @include lightDark(color, #222, #BBB); .subheader { font-size: 0.5em; line-height: 1em; @@ -91,11 +91,14 @@ h2.list-heading { */ a { color: var(--color-primary); - fill: var(--color-primary); + fill: currentColor; cursor: pointer; text-decoration: none; transition: filter ease-in-out 80ms; line-height: 1.6; + @include whenDark { + filter: brightness(1.3) saturate(0.7); + } &:hover { text-decoration: underline; } @@ -130,7 +133,7 @@ p, ul, ol, pre, table, blockquote { hr { border: 0; height: 1px; - background: #EAEAEA; + @include lightDark(background, #eaeaea, #222); margin-bottom: $-l; &.faded { background-image: linear-gradient(to right, #FFF, #e3e0e0 20%, #e3e0e0 80%, #FFF); @@ -153,7 +156,7 @@ em, i, .italic { small, p.small, span.small, .text-small { font-size: 0.75rem; - color: lighten($text-dark, 10%); + @include lightDark(color, #5e5e5e, #999); } sup, .superscript { @@ -168,8 +171,9 @@ sub, .subscript { pre { font-size: 12px; - background-color: #f5f5f5; border: 1px solid #DDD; + @include lightDark(background-color, #f5f5f5, #2B2B2B); + @include lightDark(border-color, #DDD, #111); padding-left: 31px; position: relative; padding-top: 3px; @@ -181,9 +185,9 @@ pre { top: 0; width: 29px; left: 0; - background-color: #f5f5f5; height: 100%; - border-right: 1px solid #DDD; + @include lightDark(background-color, #f5f5f5, #313335); + @include lightDark(border-right, 1px solid #DDD, none); } } @@ -226,10 +230,11 @@ blockquote { } .code-base { - background-color: #F8F8F8; - font-size: 0.80em; - border: 1px solid #DDD; - border-radius: 3px; + font-size: 0.84em; + border: 1px solid #DDD; + border-radius: 3px; + @include lightDark(background-color, #f8f8f8f, #2b2b2b); + @include lightDark(border-color, #DDD, #444); } code { @@ -385,4 +390,5 @@ span.sep { bottom: -0.105em; margin-inline-end: $-xs; pointer-events: none; + fill: currentColor; } diff --git a/resources/sass/_variables.scss b/resources/sass/_variables.scss index 2d4d3970a..061a83746 100644 --- a/resources/sass/_variables.scss +++ b/resources/sass/_variables.scss @@ -63,6 +63,7 @@ $text-light: #EEE; // Shadows $bs-light: 0 0 4px 1px #CCC; +$bs-dark: 0 0 4px 1px rgba(0, 0, 0, 0.5); $bs-med: 0 1px 3px 1px rgba(76, 76, 76, 0.26); $bs-large: 0 1px 6px 1px rgba(22, 22, 22, 0.2); $bs-card: 0 1px 6px -1px rgba(0, 0, 0, 0.1); diff --git a/resources/sass/styles.scss b/resources/sass/styles.scss index 09d8b4100..74e4a4fde 100644 --- a/resources/sass/styles.scss +++ b/resources/sass/styles.scss @@ -161,6 +161,7 @@ $btt-size: 40px; .entity-selector { border: 1px solid #DDD; + @include lightDark(border-color, #ddd, #111); border-radius: 3px; overflow: hidden; font-size: 0.8em; @@ -176,12 +177,12 @@ $btt-size: 40px; .entity-list { overflow-y: scroll; height: 400px; - background-color: #EEEEEE; + @include lightDark(background-color, #eee, #222); margin-inline-end: 0; margin-inline-start: 0; } .entity-list-item { - background-color: #FFF; + @include lightDark(background-color, #fff, #222); } .entity-list-item p { margin-bottom: 0; diff --git a/resources/views/base.blade.php b/resources/views/base.blade.php index d362ef373..0f43532fb 100644 --- a/resources/views/base.blade.php +++ b/resources/views/base.blade.php @@ -24,6 +24,11 @@ @stack('translations') + diff --git a/resources/views/settings/index.blade.php b/resources/views/settings/index.blade.php index 07ca1fcc1..6ccb8d8f9 100644 --- a/resources/views/settings/index.blade.php +++ b/resources/views/settings/index.blade.php @@ -92,7 +92,7 @@

{{ trans('settings.app_name_desc') }}

-
+
@include('components.toggle-switch', [ 'name' => 'setting-app-name-header', @@ -107,7 +107,7 @@

{{ trans('settings.app_editor_desc') }}

-
+
@@ -174,7 +174,7 @@

{{ trans('settings.app_homepage_desc') }}

-
+
From b0b28e7b5e5859cd676ad2e5704f244ca94422e9 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 11 Apr 2020 15:48:08 +0100 Subject: [PATCH 2/5] Rolled dark mode out to the editors - Updated editor, and other area, styles to look okay in dark mode. - Used tinyMCE theme generator to create dark mode theme. - Updated tinymce to latest 4x version. --- .../libs/tinymce/plugins/help/plugin.min.js | 2 +- .../libs/tinymce/plugins/image/plugin.min.js | 2 +- .../tinymce/plugins/imagetools/plugin.min.js | 2 +- .../libs/tinymce/plugins/lists/plugin.min.js | 2 +- .../libs/tinymce/plugins/paste/plugin.min.js | 2 +- .../libs/tinymce/plugins/print/plugin.min.js | 2 +- .../libs/tinymce/plugins/table/plugin.min.js | 2 +- .../tinymce/plugins/textpattern/plugin.min.js | 2 +- .../tinymce/plugins/visualchars/plugin.min.js | 2 +- .../tinymce/plugins/wordcount/plugin.min.js | 2 +- public/libs/tinymce/skins/dark/Variables.less | 224 ++ .../tinymce/skins/dark/content.inline.min.css | 1 + .../libs/tinymce/skins/dark/content.min.css | 1 + .../libs/tinymce/skins/dark/fonts/readme.md | 1 + .../skins/dark/fonts/tinymce-small.eot | Bin 0 -> 9492 bytes .../skins/dark/fonts/tinymce-small.json | 1277 +++++++ .../skins/dark/fonts/tinymce-small.svg | 63 + .../skins/dark/fonts/tinymce-small.ttf | Bin 0 -> 9304 bytes .../skins/dark/fonts/tinymce-small.woff | Bin 0 -> 9380 bytes .../libs/tinymce/skins/dark/fonts/tinymce.eot | Bin 0 -> 17572 bytes .../tinymce/skins/dark/fonts/tinymce.json | 3381 +++++++++++++++++ .../libs/tinymce/skins/dark/fonts/tinymce.svg | 131 + .../libs/tinymce/skins/dark/fonts/tinymce.ttf | Bin 0 -> 17408 bytes .../tinymce/skins/dark/fonts/tinymce.woff | Bin 0 -> 17484 bytes public/libs/tinymce/skins/dark/img/anchor.gif | Bin 0 -> 53 bytes public/libs/tinymce/skins/dark/img/loader.gif | Bin 0 -> 2608 bytes public/libs/tinymce/skins/dark/img/object.gif | Bin 0 -> 152 bytes public/libs/tinymce/skins/dark/img/trans.gif | Bin 0 -> 43 bytes .../libs/tinymce/skins/dark/skin.ie7.min.css | 1 + public/libs/tinymce/skins/dark/skin.json | 79 + public/libs/tinymce/skins/dark/skin.min.css | 1 + .../skins/lightgray/content.inline.min.css | 2 +- .../tinymce/skins/lightgray/content.min.css | 2 +- public/libs/tinymce/tinymce.min.js | 4 +- resources/js/components/markdown-editor.js | 8 +- resources/js/components/wysiwyg-editor.js | 20 +- resources/js/vues/components/autosuggest.js | 2 +- resources/sass/_blocks.scss | 29 +- resources/sass/_buttons.scss | 4 +- resources/sass/_colors.scss | 14 +- resources/sass/_components.scss | 29 +- resources/sass/_forms.scss | 23 +- resources/sass/_lists.scss | 6 +- resources/sass/_pages.scss | 11 +- resources/sass/_tables.scss | 2 +- resources/sass/_text.scss | 2 +- resources/sass/_tinymce.scss | 4 +- resources/sass/_variables.scss | 1 + resources/sass/styles.scss | 10 +- .../views/components/image-manager.blade.php | 2 +- 50 files changed, 5286 insertions(+), 69 deletions(-) create mode 100644 public/libs/tinymce/skins/dark/Variables.less create mode 100644 public/libs/tinymce/skins/dark/content.inline.min.css create mode 100644 public/libs/tinymce/skins/dark/content.min.css create mode 100644 public/libs/tinymce/skins/dark/fonts/readme.md create mode 100644 public/libs/tinymce/skins/dark/fonts/tinymce-small.eot create mode 100644 public/libs/tinymce/skins/dark/fonts/tinymce-small.json create mode 100644 public/libs/tinymce/skins/dark/fonts/tinymce-small.svg create mode 100644 public/libs/tinymce/skins/dark/fonts/tinymce-small.ttf create mode 100644 public/libs/tinymce/skins/dark/fonts/tinymce-small.woff create mode 100644 public/libs/tinymce/skins/dark/fonts/tinymce.eot create mode 100644 public/libs/tinymce/skins/dark/fonts/tinymce.json create mode 100644 public/libs/tinymce/skins/dark/fonts/tinymce.svg create mode 100644 public/libs/tinymce/skins/dark/fonts/tinymce.ttf create mode 100644 public/libs/tinymce/skins/dark/fonts/tinymce.woff create mode 100644 public/libs/tinymce/skins/dark/img/anchor.gif create mode 100644 public/libs/tinymce/skins/dark/img/loader.gif create mode 100644 public/libs/tinymce/skins/dark/img/object.gif create mode 100644 public/libs/tinymce/skins/dark/img/trans.gif create mode 100644 public/libs/tinymce/skins/dark/skin.ie7.min.css create mode 100644 public/libs/tinymce/skins/dark/skin.json create mode 100644 public/libs/tinymce/skins/dark/skin.min.css diff --git a/public/libs/tinymce/plugins/help/plugin.min.js b/public/libs/tinymce/plugins/help/plugin.min.js index a598b6c4a..67cde482a 100644 --- a/public/libs/tinymce/plugins/help/plugin.min.js +++ b/public/libs/tinymce/plugins/help/plugin.min.js @@ -1 +1 @@ -!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=function(e){return function(){return e}};function c(r){for(var o=[],e=1;e'+C.translate(e.action)+""+e.shortcut+"";var t}).join("");return{title:"Handy Shortcuts",type:"container",style:"overflow-y: auto; overflow-x: hidden; max-height: 250px",items:[{type:"container",html:'
"+e+"
'+C.translate("Action")+""+C.translate("Shortcut")+"
"}]}},P=Object.keys,_=[{key:"advlist",name:"Advanced List"},{key:"anchor",name:"Anchor"},{key:"autolink",name:"Autolink"},{key:"autoresize",name:"Autoresize"},{key:"autosave",name:"Autosave"},{key:"bbcode",name:"BBCode"},{key:"charmap",name:"Character Map"},{key:"code",name:"Code"},{key:"codesample",name:"Code Sample"},{key:"colorpicker",name:"Color Picker"},{key:"compat3x",name:"3.x Compatibility"},{key:"contextmenu",name:"Context Menu"},{key:"directionality",name:"Directionality"},{key:"emoticons",name:"Emoticons"},{key:"fullpage",name:"Full Page"},{key:"fullscreen",name:"Full Screen"},{key:"help",name:"Help"},{key:"hr",name:"Horizontal Rule"},{key:"image",name:"Image"},{key:"imagetools",name:"Image Tools"},{key:"importcss",name:"Import CSS"},{key:"insertdatetime",name:"Insert Date/Time"},{key:"legacyoutput",name:"Legacy Output"},{key:"link",name:"Link"},{key:"lists",name:"Lists"},{key:"media",name:"Media"},{key:"nonbreaking",name:"Nonbreaking"},{key:"noneditable",name:"Noneditable"},{key:"pagebreak",name:"Page Break"},{key:"paste",name:"Paste"},{key:"preview",name:"Preview"},{key:"print",name:"Print"},{key:"save",name:"Save"},{key:"searchreplace",name:"Search and Replace"},{key:"spellchecker",name:"Spell Checker"},{key:"tabfocus",name:"Tab Focus"},{key:"table",name:"Table"},{key:"template",name:"Template"},{key:"textcolor",name:"Text Color"},{key:"textpattern",name:"Text Pattern"},{key:"toc",name:"Table of Contents"},{key:"visualblocks",name:"Visual Blocks"},{key:"visualchars",name:"Visual Characters"},{key:"wordcount",name:"Word Count"}],H=c(function(e,o){return e.replace(/\$\{([^{}]*)\}/g,function(e,t){var n,r=o[t];return"string"==(n=typeof r)||"number"===n?r.toString():e})},'${name}'),F=function(t,n){return function(e,t){for(var n=0,r=e.length;n"+F(t,e)+""}),i=a.length,l=a.join("");return"

"+C.translate(["Plugins installed ({0}):",i])+"

    "+l+"
"},E=function(e){return{title:"Plugins",type:"container",style:"overflow-y: auto; overflow-x: hidden;",layout:"flex",padding:10,spacing:10,items:[(t=e,{type:"container",html:'
'+M(t)+"
",flex:1}),{type:"container",html:'

'+C.translate("Premium plugins:")+'

  • PowerPaste
  • Spell Checker Pro
  • Accessibility Checker
  • Advanced Code Editor
  • Enhanced Media Embed
  • Link Checker

'+C.translate("Learn more...")+"

",flex:1}]};var t},I=tinymce.util.Tools.resolve("tinymce.EditorManager"),j=function(){var e,t,n='TinyMCE '+(e=I.majorVersion,t=I.minorVersion,0===e.indexOf("@")?"X.X.X":e+"."+t)+"";return[{type:"label",html:C.translate(["You are using {0}",n])},{type:"spacer",flex:1},{text:"Close",onclick:function(){this.parent().parent().close()}}]},L=function(e,t){return function(){e.windowManager.open({title:"Help",bodyType:"tabpanel",layout:"flex",body:[T(),E(e)],buttons:j(),onPostRender:function(){this.getEl("title").innerHTML='TinyMCE Logo'}})}},B=function(e,t){e.addCommand("mceHelp",L(e,t))},N=function(e,t){e.addButton("help",{icon:"help",onclick:L(e,t)}),e.addMenuItem("help",{text:"Help",icon:"help",context:"help",onclick:L(e,t)})};e.add("help",function(e,t){N(e,t),B(e,t),e.shortcuts.add("Alt+0","Open help dialog","mceHelp")})}(); \ No newline at end of file +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=function(){},a=function(e){return function(){return e}};function l(r){for(var o=[],e=1;e'+v.translate(e.action)+""+e.shortcut+"";var t}).join("");return{title:"Handy Shortcuts",type:"container",style:"overflow-y: auto; overflow-x: hidden; max-height: 250px",items:[{type:"container",html:'
"+e+"
'+v.translate("Action")+""+v.translate("Shortcut")+"
"}]}},S=Object.keys,O=[{key:"advlist",name:"Advanced List"},{key:"anchor",name:"Anchor"},{key:"autolink",name:"Autolink"},{key:"autoresize",name:"Autoresize"},{key:"autosave",name:"Autosave"},{key:"bbcode",name:"BBCode"},{key:"charmap",name:"Character Map"},{key:"code",name:"Code"},{key:"codesample",name:"Code Sample"},{key:"colorpicker",name:"Color Picker"},{key:"compat3x",name:"3.x Compatibility"},{key:"contextmenu",name:"Context Menu"},{key:"directionality",name:"Directionality"},{key:"emoticons",name:"Emoticons"},{key:"fullpage",name:"Full Page"},{key:"fullscreen",name:"Full Screen"},{key:"help",name:"Help"},{key:"hr",name:"Horizontal Rule"},{key:"image",name:"Image"},{key:"imagetools",name:"Image Tools"},{key:"importcss",name:"Import CSS"},{key:"insertdatetime",name:"Insert Date/Time"},{key:"legacyoutput",name:"Legacy Output"},{key:"link",name:"Link"},{key:"lists",name:"Lists"},{key:"media",name:"Media"},{key:"nonbreaking",name:"Nonbreaking"},{key:"noneditable",name:"Noneditable"},{key:"pagebreak",name:"Page Break"},{key:"paste",name:"Paste"},{key:"preview",name:"Preview"},{key:"print",name:"Print"},{key:"save",name:"Save"},{key:"searchreplace",name:"Search and Replace"},{key:"spellchecker",name:"Spell Checker"},{key:"tabfocus",name:"Tab Focus"},{key:"table",name:"Table"},{key:"template",name:"Template"},{key:"textcolor",name:"Text Color"},{key:"textpattern",name:"Text Pattern"},{key:"toc",name:"Table of Contents"},{key:"visualblocks",name:"Visual Blocks"},{key:"visualchars",name:"Visual Characters"},{key:"wordcount",name:"Word Count"}],T=l(function(e,o){return e.replace(/\$\{([^{}]*)\}/g,function(e,t){var n,r=o[t];return"string"==(n=typeof r)||"number"===n?r.toString():e})},'${name}'),P=function(t,n){return function(e,t){for(var n=0,r=e.length;n"+P(t,e)+""}),i=a.length,c=a.join("");return"

"+v.translate(["Plugins installed ({0}):",i])+"

    "+c+"
"},H=function(e){return{title:"Plugins",type:"container",style:"overflow-y: auto; overflow-x: hidden;",layout:"flex",padding:10,spacing:10,items:[(t=e,{type:"container",html:'
'+_(t)+"
",flex:1}),{type:"container",html:'

'+v.translate("Premium plugins:")+'

  • PowerPaste
  • Spell Checker Pro
  • Accessibility Checker
  • Advanced Code Editor
  • Enhanced Media Embed
  • Link Checker

'+v.translate("Learn more...")+"

",flex:1}]};var t},F=tinymce.util.Tools.resolve("tinymce.EditorManager"),M=function(){var e,t,n='TinyMCE '+(e=F.majorVersion,t=F.minorVersion,0===e.indexOf("@")?"X.X.X":e+"."+t)+"";return[{type:"label",html:v.translate(["You are using {0}",n])},{type:"spacer",flex:1},{text:"Close",onclick:function(){this.parent().parent().close()}}]},E=function(e,t){return function(){e.windowManager.open({title:"Help",bodyType:"tabpanel",layout:"flex",body:[w(),H(e)],buttons:M(),onPostRender:function(){this.getEl("title").innerHTML='TinyMCE Logo'}})}},I=function(e,t){e.addCommand("mceHelp",E(e,t))},j=function(e,t){e.addButton("help",{icon:"help",onclick:E(e,t)}),e.addMenuItem("help",{text:"Help",icon:"help",context:"help",onclick:E(e,t)})};e.add("help",function(e,t){j(e,t),I(e,t),e.shortcuts.add("Alt+0","Open help dialog","mceHelp")})}(); \ No newline at end of file diff --git a/public/libs/tinymce/plugins/image/plugin.min.js b/public/libs/tinymce/plugins/image/plugin.min.js index d4764ad62..23473aa76 100644 --- a/public/libs/tinymce/plugins/image/plugin.min.js +++ b/public/libs/tinymce/plugins/image/plugin.min.js @@ -1 +1 @@ -!function(l){"use strict";var i,e=tinymce.util.Tools.resolve("tinymce.PluginManager"),d=function(e){return!1!==e.settings.image_dimensions},u=function(e){return!0===e.settings.image_advtab},m=function(e){return e.getParam("image_prepend_url","")},n=function(e){return e.getParam("image_class_list")},r=function(e){return!1!==e.settings.image_description},a=function(e){return!0===e.settings.image_title},o=function(e){return!0===e.settings.image_caption},c=function(e){return e.getParam("image_list",!1)},s=function(e){return e.getParam("images_upload_url",!1)},g=function(e){return e.getParam("images_upload_handler",!1)},f=function(e){return e.getParam("images_upload_url")},p=function(e){return e.getParam("images_upload_handler")},h=function(e){return e.getParam("images_upload_base_path")},v=function(e){return e.getParam("images_upload_credentials")},b="undefined"!=typeof l.window?l.window:Function("return this;")(),y=function(e,t){return function(e,t){for(var n=t!==undefined&&null!==t?t:b,r=0;rthis.length())return null;for(var n=this.littleEndian?0:-8*(e-1),r=0,o=0;r=s.length())throw new Error("Invalid Exif data.");"ASCII"!==i?(f=s.asArray(i,c,a),l=1==a?f[0]:f,at.hasOwnProperty(o)&&"object"!=typeof l?d[o]=at[o][l]:d[o]=l):d[o]=s.STRING(c,a).replace(/\0$/,"").trim()}return d},t}(),ct=function(t){var e,n,r=[],o=0;for(e=2;e<=t.length();)if(65488<=(n=t.SHORT(e))&&n<=65495)e+=2;else{if(65498===n||65497===n)break;o=t.SHORT(e+2)+2,65505<=n&&n<=65519&&r.push({hex:n,name:"APP"+(15&n),start:e,length:o,segment:t.SEGMENT(e,o)}),e+=o}return r},lt=function(u){return L.blobToArrayBuffer(u).then(function(t){try{var e=new et(t);if(65496===e.SHORT(0)){var n=ct(e),r=n.filter(function(t){return"APP1"===t.name}),o={};if(!r.length)return g.reject("Headers did not include required information");var i=new ut(r[0].segment);return(o={tiff:i.TIFF(),exif:i.EXIF(),gps:i.GPS(),thumb:i.thumb()}).rawHeaders=n,o}return g.reject("Image was not a jpeg")}catch(a){return g.reject("Unsupported format or not an image: "+u.type+" (Exception: "+a.message+")")}})},st=function(t,e){return tt.rotate(t,e)},ft={invert:function(t){return Z.invert(t)},sharpen:function(t){return Z.sharpen(t)},emboss:function(t){return Z.emboss(t)},brightness:function(t,e){return Z.brightness(t,e)},hue:function(t,e){return Z.hue(t,e)},saturate:function(t,e){return Z.saturate(t,e)},contrast:function(t,e){return Z.contrast(t,e)},grayscale:function(t,e){return Z.grayscale(t,e)},sepia:function(t,e){return Z.sepia(t,e)},colorize:function(t,e,n,r){return Z.colorize(t,e,n,r)},gamma:function(t,e){return Z.gamma(t,e)},exposure:function(t,e){return Z.exposure(t,e)},flip:function(t,e){return tt.flip(t,e)},crop:function(t,e,n,r,o){return tt.crop(t,e,n,r,o)},resize:function(t,e,n){return tt.resize(t,e,n)},rotate:st,exifRotate:function(e){return e.toBlob().then(lt).then(function(t){switch(t.tiff.Orientation){case 6:return st(e,90);case 3:return st(e,180);case 8:return st(e,270);default:return e}},function(){return e})}},dt=function(t){return t.toBlob()},ht={blobToImageResult:function(t){return N.fromBlob(t)},fromBlobAndUrlSync:function(t,e){return N.fromBlobAndUrlSync(t,e)},imageToImageResult:function(t){return N.fromImage(t)},imageResultToBlob:function(t,e,n){return e===undefined&&n===undefined?dt(t):t.toAdjustedBlob(e,n)},imageResultToOriginalBlob:dt,imageResultToDataURL:function(t){return t.toDataURL()}},pt=function(){return O.getOrDie("URL")},gt={createObjectURL:function(t){return pt().createObjectURL(t)},revokeObjectURL:function(t){pt().revokeObjectURL(t)}},mt=tinymce.util.Tools.resolve("tinymce.util.Delay"),yt=tinymce.util.Tools.resolve("tinymce.util.Promise"),vt=tinymce.util.Tools.resolve("tinymce.util.URI"),bt=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),wt=tinymce.util.Tools.resolve("tinymce.ui.Factory"),xt=tinymce.util.Tools.resolve("tinymce.geom.Rect"),It=function(n){return new yt(function(t){var e=function(){n.removeEventListener("load",e),t(n)};n.complete?t(n):n.addEventListener("load",e)})},Tt=tinymce.util.Tools.resolve("tinymce.dom.DomQuery"),Rt=tinymce.util.Tools.resolve("tinymce.util.Observable"),St=tinymce.util.Tools.resolve("tinymce.util.VK"),Ot=0,Ft={create:function(t){return new(wt.get("Control").extend({Defaults:{classes:"imagepanel"},selection:function(t){return arguments.length?(this.state.set("rect",t),this):this.state.get("rect")},imageSize:function(){var t=this.state.get("viewRect");return{w:t.w,h:t.h}},toggleCropRect:function(t){this.state.set("cropEnabled",t)},imageSrc:function(t){var o=this,i=new s.Image;i.src=t,It(i).then(function(){var t,e,n=o.state.get("viewRect");if((e=o.$el.find("img"))[0])e.replaceWith(i);else{var r=s.document.createElement("div");r.className="mce-imagepanel-bg",o.getEl().appendChild(r),o.getEl().appendChild(i)}t={x:0,y:0,w:i.naturalWidth,h:i.naturalHeight},o.state.set("viewRect",t),o.state.set("rect",xt.inflate(t,-20,-20)),n&&n.w===t.w&&n.h===t.h||o.zoomFit(),o.repaintImage(),o.fire("load")})},zoom:function(t){return arguments.length?(this.state.set("zoom",t),this):this.state.get("zoom")},postRender:function(){return this.imageSrc(this.settings.imageSrc),this._super()},zoomFit:function(){var t,e,n,r,o,i;t=this.$el.find("img"),e=this.getEl().clientWidth,n=this.getEl().clientHeight,r=t[0].naturalWidth,o=t[0].naturalHeight,1<=(i=Math.min((e-10)/r,(n-10)/o))&&(i=1),this.zoom(i)},repaintImage:function(){var t,e,n,r,o,i,a,u,c,l,s;s=this.getEl(),c=this.zoom(),l=this.state.get("rect"),a=this.$el.find("img"),u=this.$el.find(".mce-imagepanel-bg"),o=s.offsetWidth,i=s.offsetHeight,n=a[0].naturalWidth*c,r=a[0].naturalHeight*c,t=Math.max(0,o/2-n/2),e=Math.max(0,i/2-r/2),a.css({left:t,top:e,width:n,height:r}),u.css({left:t,top:e,width:n,height:r}),this.cropRect&&(this.cropRect.setRect({x:l.x*c+t,y:l.y*c+e,w:l.w*c,h:l.h*c}),this.cropRect.setClampRect({x:t,y:e,w:n,h:r}),this.cropRect.setViewPortRect({x:0,y:0,w:o,h:i}))},bindStates:function(){var r=this;function n(t){r.cropRect=function(l,n,s,r,o){var f,a,t,i,e="mce-",u=e+"crid-"+Ot++;function d(t,e){return{x:e.x-t.x,y:e.y-t.y,w:e.w,h:e.h}}function c(t,e,n,r){var o,i,a,u,c;o=e.x,i=e.y,a=e.w,u=e.h,o+=n*t.deltaX,i+=r*t.deltaY,(a+=n*t.deltaW)<20&&(a=20),(u+=r*t.deltaH)<20&&(u=20),c=l=xt.clamp({x:o,y:i,w:a,h:u},s,"move"===t.name),c=d(s,c),f.fire("updateRect",{rect:c}),g(c)}function h(e){function t(t,e){e.h<0&&(e.h=0),e.w<0&&(e.w=0),Tt("#"+u+"-"+t,r).css({left:e.x,top:e.y,width:e.w,height:e.h})}$.each(a,function(t){Tt("#"+u+"-"+t.name,r).css({left:e.w*t.xMul+e.x,top:e.h*t.yMul+e.y})}),t("top",{x:n.x,y:n.y,w:n.w,h:e.y-n.y}),t("right",{x:e.x+e.w,y:e.y,w:n.w-e.x-e.w+n.x,h:e.h}),t("bottom",{x:n.x,y:e.y+e.h,w:n.w,h:n.h-e.y-e.h+n.y}),t("left",{x:n.x,y:e.y,w:e.x-n.x,h:e.h}),t("move",e)}function p(t){h(l=t)}function g(t){var e,n;p((e=s,{x:(n=t).x+e.x,y:n.y+e.y,w:n.w,h:n.h}))}return a=[{name:"move",xMul:0,yMul:0,deltaX:1,deltaY:1,deltaW:0,deltaH:0,label:"Crop Mask"},{name:"nw",xMul:0,yMul:0,deltaX:1,deltaY:1,deltaW:-1,deltaH:-1,label:"Top Left Crop Handle"},{name:"ne",xMul:1,yMul:0,deltaX:0,deltaY:1,deltaW:1,deltaH:-1,label:"Top Right Crop Handle"},{name:"sw",xMul:0,yMul:1,deltaX:1,deltaY:0,deltaW:-1,deltaH:1,label:"Bottom Left Crop Handle"},{name:"se",xMul:1,yMul:1,deltaX:0,deltaY:0,deltaW:1,deltaH:1,label:"Bottom Right Crop Handle"}],i=["top","right","bottom","left"],Tt('
').appendTo(r),$.each(i,function(t){Tt("#"+u,r).append('
From d4b0e4acad815d48e59eb0cde286340db8a95d30 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 11 Apr 2020 20:02:07 +0100 Subject: [PATCH 3/5] Removed throttling from web-end requests Generally seems to cause issues when secure images are in use. Was added during laravel upgrade but laravel does not use this directly for its web middleware anyway. --- app/Http/Kernel.php | 1 - resources/sass/_forms.scss | 2 +- resources/sass/_header.scss | 5 +++-- resources/sass/_lists.scss | 3 ++- resources/sass/_pages.scss | 14 ++++++++++---- resources/sass/styles.scss | 5 +++++ 6 files changed, 21 insertions(+), 9 deletions(-) diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 4517deb90..a0c45ea89 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -26,7 +26,6 @@ class Kernel extends HttpKernel \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, - \Illuminate\Routing\Middleware\ThrottleRequests::class, \BookStack\Http\Middleware\VerifyCsrfToken::class, \BookStack\Http\Middleware\Localization::class, \BookStack\Http\Middleware\GlobalViewData::class, diff --git a/resources/sass/_forms.scss b/resources/sass/_forms.scss index 824c229bd..32d873642 100644 --- a/resources/sass/_forms.scss +++ b/resources/sass/_forms.scss @@ -385,7 +385,7 @@ div[editor-type="markdown"] .title-input.page-title input[type="text"] { button { background-color: transparent; border: none; - fill: #666; + @include lightDark(color, #666, #AAA); padding: 0; cursor: pointer; position: absolute; diff --git a/resources/sass/_header.scss b/resources/sass/_header.scss index 1c4bf948f..e0a8ad1a4 100644 --- a/resources/sass/_header.scss +++ b/resources/sass/_header.scss @@ -98,6 +98,7 @@ header .search-box { button { z-index: 1; left: 16px; + @include lightDark(color, rgba(255, 255, 255, 0.8), #AAA); @include rtl { left: auto; right: 16px; @@ -264,7 +265,7 @@ header .search-box { display: none; } > span:first-child { - margin-block-end: 0; + margin-inline-end: 0; } } } @@ -280,7 +281,7 @@ header .search-box { } } .svg-icon { - margin-block-end: 0; + margin-inline-end: 0; } } diff --git a/resources/sass/_lists.scss b/resources/sass/_lists.scss index 9324bbf7b..8165d532d 100644 --- a/resources/sass/_lists.scss +++ b/resources/sass/_lists.scss @@ -358,7 +358,8 @@ ul.pagination { } } li.active span { - color: #FFF; + @include lightDark(color, #444, #eee); + @include lightDark(background-color, rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.5)); } } diff --git a/resources/sass/_pages.scss b/resources/sass/_pages.scss index 1833a0c6e..1ed02d2e7 100755 --- a/resources/sass/_pages.scss +++ b/resources/sass/_pages.scss @@ -151,15 +151,16 @@ body.mce-fullscreen, body.markdown-fullscreen { } .pointer { border: 1px solid #CCC; + @include lightDark(border-color, #ccc, #000); display: flex; align-items: center; justify-items: center; padding: $-s $-s; border-radius: 4px; - box-shadow: 0 0 12px 1px rgba(212, 209, 209, 0.3); + box-shadow: 0 0 12px 1px rgba(0, 0, 0, 0.1); position: absolute; top: -60px; - background-color:#FFF; + @include lightDark(background-color, #fff, #333); width: 275px; z-index: 55; @@ -176,12 +177,13 @@ body.mce-fullscreen, body.markdown-fullscreen { margin-inline-start: -8px; content: ''; display: block; - background-color:#FFF; transform: rotate(45deg); transform-origin: 50% 50%; - border-inline-startom: 1px solid #CCC; + border-block-end: 1px solid #CCC; border-inline-end: 1px solid #CCC; z-index: 56; + @include lightDark(background-color, #fff, #333); + @include lightDark(border-color, #ccc, #000); } input, button, a { position: relative; @@ -194,6 +196,7 @@ body.mce-fullscreen, body.markdown-fullscreen { input { background-color: #FFF; border: 1px solid #DDD; + @include lightDark(border-color, #ddd, #000); color: #666; width: 172px; z-index: 40; @@ -218,6 +221,9 @@ body.mce-fullscreen, body.markdown-fullscreen { width: 1.2em; height: 1.2em; } + .button { + @include lightDark(border-color, #ddd, #000); + } } // Attribute form diff --git a/resources/sass/styles.scss b/resources/sass/styles.scss index 1a9d793b6..8af363469 100644 --- a/resources/sass/styles.scss +++ b/resources/sass/styles.scss @@ -54,6 +54,11 @@ body.dragging, body.dragging * { &.square { border-radius: 3px; } + &[src$="user_avatar.png"] { + @include whenDark { + filter: invert(1); + } + } } // Loading icon From 573c848d510ef7f1b959b20eb8a6bf4c167a856b Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 11 Apr 2020 20:37:51 +0100 Subject: [PATCH 4/5] Added dark/light mode toggle to profile dropdown menu - Also fixed some remaining areas which needed dark mode support. --- app/Http/Controllers/UserController.php | 10 ++++++++++ resources/icons/dark-mode.svg | 1 + resources/icons/light-mode.svg | 1 + resources/sass/_lists.scss | 3 +++ resources/views/base.blade.php | 10 +++------- resources/views/common/header.blade.php | 12 ++++++++++++ routes/web.php | 1 + 7 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 resources/icons/dark-mode.svg create mode 100644 resources/icons/light-mode.svg diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 43cbad1fb..775e2a984 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -312,6 +312,16 @@ class UserController extends Controller return $this->changeListSort($id, $request, $type); } + /** + * Toggle dark mode for the current user. + */ + public function toggleDarkMode() + { + $enabled = setting()->getForCurrentUser('dark-mode-enabled', false); + setting()->putUser(user(), 'dark-mode-enabled', $enabled ? 'false' : 'true'); + return redirect()->back(); + } + /** * Update the stored section expansion preference for the given user. */ diff --git a/resources/icons/dark-mode.svg b/resources/icons/dark-mode.svg new file mode 100644 index 000000000..8b00d72a5 --- /dev/null +++ b/resources/icons/dark-mode.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/icons/light-mode.svg b/resources/icons/light-mode.svg new file mode 100644 index 000000000..cf2961d2e --- /dev/null +++ b/resources/icons/light-mode.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/sass/_lists.scss b/resources/sass/_lists.scss index 8165d532d..5eb672697 100644 --- a/resources/sass/_lists.scss +++ b/resources/sass/_lists.scss @@ -603,6 +603,9 @@ ul.pagination { li.border-bottom { border-bottom: 1px solid #DDD; } + li hr { + margin: $-xs 0; + } } // Books grid view diff --git a/resources/views/base.blade.php b/resources/views/base.blade.php index 0f43532fb..a5404a365 100644 --- a/resources/views/base.blade.php +++ b/resources/views/base.blade.php @@ -1,5 +1,7 @@ - + {{ isset($pageTitle) ? $pageTitle . ' | ' : '' }}{{ setting('app-name') }} @@ -23,12 +25,6 @@ @stack('translations') - - diff --git a/resources/views/common/header.blade.php b/resources/views/common/header.blade.php index ec90739ee..af7aaeeb0 100644 --- a/resources/views/common/header.blade.php +++ b/resources/views/common/header.blade.php @@ -70,6 +70,18 @@ @icon('logout'){{ trans('auth.logout') }} @endif +

  • +
  • +
    + {{ csrf_field() }} + {{ method_field('patch') }} + @if(setting()->getForCurrentUser('dark-mode-enabled')) + + @else + + @endif +
    +
  • @endif diff --git a/routes/web.php b/routes/web.php index 4dfccdf36..3e05e394d 100644 --- a/routes/web.php +++ b/routes/web.php @@ -183,6 +183,7 @@ Route::group(['middleware' => 'auth'], function () { Route::patch('/users/{id}/switch-shelf-view', 'UserController@switchShelfView'); Route::patch('/users/{id}/change-sort/{type}', 'UserController@changeSort'); Route::patch('/users/{id}/update-expansion-preference/{key}', 'UserController@updateExpansionPreference'); + Route::patch('/users/toggle-dark-mode', 'UserController@toggleDarkMode'); Route::post('/users/create', 'UserController@store'); Route::get('/users/{id}', 'UserController@edit'); Route::put('/users/{id}', 'UserController@update'); From 50669e3f4a32eff3523b703886e523ed84470583 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 11 Apr 2020 20:44:23 +0100 Subject: [PATCH 5/5] Added tests and translations for dark-mode components --- resources/lang/en/common.php | 2 ++ resources/views/common/header.blade.php | 4 ++-- tests/User/UserPreferencesTest.php | 17 +++++++++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/resources/lang/en/common.php b/resources/lang/en/common.php index c8b4a2b22..68c58b92b 100644 --- a/resources/lang/en/common.php +++ b/resources/lang/en/common.php @@ -66,6 +66,8 @@ return [ 'profile_menu' => 'Profile Menu', 'view_profile' => 'View Profile', 'edit_profile' => 'Edit Profile', + 'dark_mode' => 'Dark Mode', + 'light_mode' => 'Light Mode', // Layout tabs 'tab_info' => 'Info', diff --git a/resources/views/common/header.blade.php b/resources/views/common/header.blade.php index af7aaeeb0..98bd01788 100644 --- a/resources/views/common/header.blade.php +++ b/resources/views/common/header.blade.php @@ -76,9 +76,9 @@ {{ csrf_field() }} {{ method_field('patch') }} @if(setting()->getForCurrentUser('dark-mode-enabled')) - + @else - + @endif diff --git a/tests/User/UserPreferencesTest.php b/tests/User/UserPreferencesTest.php index b70d52dfa..0db4f803a 100644 --- a/tests/User/UserPreferencesTest.php +++ b/tests/User/UserPreferencesTest.php @@ -75,4 +75,21 @@ class UserPreferencesTest extends TestCase $invalidKeyRequest = $this->patch('/settings/users/' . $editor->id.'/update-expansion-preference/my-home-details', ['expand' => 'true']); $invalidKeyRequest->assertStatus(500); } + + public function test_toggle_dark_mode() + { + $home = $this->actingAs($this->getEditor())->get('/'); + $home->assertElementNotExists('.dark-mode'); + $home->assertSee('Dark Mode'); + + $this->assertEquals(false, setting()->getForCurrentUser('dark-mode-enabled', false)); + $prefChange = $this->patch('/settings/users/toggle-dark-mode'); + $prefChange->assertRedirect(); + $this->assertEquals(true, setting()->getForCurrentUser('dark-mode-enabled')); + + $home = $this->actingAs($this->getEditor())->get('/'); + $home->assertElementExists('.dark-mode'); + $home->assertDontSee('Dark Mode'); + $home->assertSee('Light Mode'); + } } \ No newline at end of file