diff --git a/browser/main/Main.js b/browser/main/Main.js index d4484f1b..1c265206 100644 --- a/browser/main/Main.js +++ b/browser/main/Main.js @@ -16,7 +16,7 @@ import { store } from 'browser/main/store' import i18n from 'browser/lib/i18n' import { getLocales } from 'browser/lib/Languages' import applyShortcuts from 'browser/main/lib/shortcutManager' -import uiThemes from 'browser/lib/ui-themes' +import { chooseTheme, applyTheme } from 'browser/main/lib/ThemeManager' import { push } from 'connected-react-router' const path = require('path') @@ -148,11 +148,13 @@ class Main extends React.Component { componentDidMount() { const { dispatch, config } = this.props - if (uiThemes.some(theme => theme.name === config.ui.theme)) { - document.body.setAttribute('data-theme', config.ui.theme) - } else { - document.body.setAttribute('data-theme', 'default') - } + this.refreshTheme = setInterval(() => { + const conf = ConfigManager.get() + chooseTheme(conf) + }, 5 * 1000) + + chooseTheme(config) + applyTheme(config.ui.theme) if (getLocales().indexOf(config.ui.language) !== -1) { i18n.setLocale(config.ui.language) @@ -191,6 +193,7 @@ class Main extends React.Component { this.toggleMenuBarVisible.bind(this) ) eventEmitter.off('dispatch:push', this.changeRoutePush.bind(this)) + clearInterval(this.refreshTheme) } changeRoutePush(event, destination) { diff --git a/browser/main/lib/ConfigManager.js b/browser/main/lib/ConfigManager.js index 3a6546d1..8516a7fc 100644 --- a/browser/main/lib/ConfigManager.js +++ b/browser/main/lib/ConfigManager.js @@ -2,7 +2,6 @@ import _ from 'lodash' import RcParser from 'browser/lib/RcParser' import i18n from 'browser/lib/i18n' import ee from 'browser/main/lib/eventEmitter' -import uiThemes from 'browser/lib/ui-themes' const OSX = global.process.platform === 'darwin' const win = global.process.platform === 'win32' @@ -47,6 +46,11 @@ export const DEFAULT_CONFIG = { ui: { language: 'en', theme: 'default', + defaultTheme: 'default', + enableScheduleTheme: false, + scheduledTheme: 'monokai', + scheduleStart: 1200, + scheduleEnd: 360, showCopyNotification: true, disableDirectWrite: false, showScrollBar: true, @@ -200,12 +204,6 @@ function set(updates) { if (!validate(newConfig)) throw new Error('INVALID CONFIG') _save(newConfig) - if (uiThemes.some(theme => theme.name === newConfig.ui.theme)) { - document.body.setAttribute('data-theme', newConfig.ui.theme) - } else { - document.body.setAttribute('data-theme', 'default') - } - i18n.setLocale(newConfig.ui.language) let editorTheme = document.getElementById('editorTheme') diff --git a/browser/main/lib/ThemeManager.js b/browser/main/lib/ThemeManager.js new file mode 100644 index 00000000..a1b090e9 --- /dev/null +++ b/browser/main/lib/ThemeManager.js @@ -0,0 +1,65 @@ +import ConfigManager from 'browser/main/lib/ConfigManager' + +const saveChanges = newConfig => { + ConfigManager.set(newConfig) +} + +const chooseTheme = config => { + const { ui } = config + if (!ui.enableScheduleTheme) { + return + } + + const start = parseInt(ui.scheduleStart) + const end = parseInt(ui.scheduleEnd) + + const now = new Date() + const minutes = now.getHours() * 60 + now.getMinutes() + + const isEndAfterStart = end > start + const isBetweenStartAndEnd = minutes >= start && minutes < end + const isBetweenEndAndStart = minutes >= start || minutes < end + + if ( + (isEndAfterStart && isBetweenStartAndEnd) || + (!isEndAfterStart && isBetweenEndAndStart) + ) { + if (ui.theme !== ui.scheduledTheme) { + ui.defaultTheme = ui.theme + ui.theme = ui.scheduledTheme + applyTheme(ui.theme) + saveChanges(config) + } + } else { + if (ui.theme !== ui.defaultTheme) { + ui.theme = ui.defaultTheme + applyTheme(ui.theme) + saveChanges(config) + } + } +} + +const applyTheme = theme => { + const supportedThemes = [ + 'dark', + 'white', + 'solarized-dark', + 'monokai', + 'dracula' + ] + if (supportedThemes.indexOf(theme) !== -1) { + document.body.setAttribute('data-theme', theme) + if (document.body.querySelector('.MarkdownPreview')) { + document.body + .querySelector('.MarkdownPreview') + .contentDocument.body.setAttribute('data-theme', theme) + } + } else { + document.body.setAttribute('data-theme', 'default') + } +} + +module.exports = { + chooseTheme, + applyTheme +} diff --git a/browser/main/modals/PreferencesModal/ConfigTab.styl b/browser/main/modals/PreferencesModal/ConfigTab.styl index 5ae5ba77..c27bd3ac 100644 --- a/browser/main/modals/PreferencesModal/ConfigTab.styl +++ b/browser/main/modals/PreferencesModal/ConfigTab.styl @@ -1,5 +1,109 @@ @import('./Tab') +.container + display flex + flex-direction column + align-items center + justify-content center + position relative + margin-bottom 2em + margin-left 2em + +.box-minmax + width 608px + height 45px + display flex + justify-content space-between + font-size $tab--button-font-size + color $ui-text-color + span first-child + margin-top 18px + padding-right 10px + padding-left 10px + padding-top 8px + position relative + border $ui-borderColor + border-radius 5px + background $ui-backgroundColor + +div[id^="secondRow"] + position absolute + z-index 2 + left 0 + top 0 + margin-bottom -42px + .rs-label + margin-left -20px + +div[id^="firstRow"] + position absolute + z-index 2 + left 0 + top 0 + margin-bottom -25px + .rs-range + &::-webkit-slider-thumb + margin-top 0px + transform rotate(180deg) + .rs-label + margin-bottom -85px + margin-top 85px + + +.rs-range + margin-top 29px + width 600px + -webkit-appearance none + &:focus + outline black + &::-webkit-slider-runnable-track + width 100% + height 0.1px + cursor pointer + box-shadow none + background $ui-backgroundColor + border-radius 0px + border 0px solid #010101 + cursor none + + &::-webkit-slider-thumb + box-shadow none + border 1px solid $ui-borderColor + box-shadow 0px 10px 10px rgba(0, 0, 0, 0.25) + height 32px + width 32px + border-radius 22px + background white + cursor pointer + -webkit-appearance none + margin-top -20px + border-color $ui-default-button-backgroundColor + height 32px + border-top-left-radius 10% + border-top-right-radius 10% + +.rs-label + position relative + transform-origin center center + display block + background transparent + border-radius none + line-height 30px + font-weight normal + box-sizing border-box + border none + margin-bottom -5px + margin-top -10px + clear both + float left + height 17px + margin-left -25px + left attr(value) + color $ui-text-color + font-style normal + font-weight normal + line-height normal + font-size $tab--button-font-size .root padding 15px margin-bottom 30px @@ -175,6 +279,9 @@ body[data-theme="dark"] .group-section-control select, .group-section-control-input colorDarkControl() + .rs-label + color $ui-dark-text-color + apply-theme(theme) body[data-theme={theme}] @@ -205,6 +312,8 @@ apply-theme(theme) .group-section-control select, .group-section-control-input colorThemedControl(theme) + .rs-label + color get-theme-var(theme, 'text-color') for theme in 'solarized-dark' 'dracula' apply-theme(theme) diff --git a/browser/main/modals/PreferencesModal/UiTab.js b/browser/main/modals/PreferencesModal/UiTab.js index 881bcf3b..17eb5558 100644 --- a/browser/main/modals/PreferencesModal/UiTab.js +++ b/browser/main/modals/PreferencesModal/UiTab.js @@ -13,6 +13,7 @@ import i18n from 'browser/lib/i18n' import { getLanguages } from 'browser/lib/Languages' import normalizeEditorFontFamily from 'browser/lib/normalizeEditorFontFamily' import uiThemes from 'browser/lib/ui-themes' +import { chooseTheme, applyTheme } from 'browser/main/lib/ThemeManager' const OSX = global.process.platform === 'darwin' @@ -84,6 +85,11 @@ class UiTab extends React.Component { const newConfig = { ui: { theme: this.refs.uiTheme.value, + defaultTheme: this.refs.uiTheme.value, + enableScheduleTheme: this.refs.enableScheduleTheme.checked, + scheduledTheme: this.refs.uiScheduledTheme.value, + scheduleStart: this.refs.scheduleStart.value, + scheduleEnd: this.refs.scheduleEnd.value, language: this.refs.uiLanguage.value, defaultNote: this.refs.defaultNote.value, tagNewNoteWithFilteringTags: this.refs.tagNewNoteWithFilteringTags @@ -190,6 +196,9 @@ class UiTab extends React.Component { preview: this.state.config.preview } + chooseTheme(newConfig) + applyTheme(newConfig.ui.theme) + ConfigManager.set(newConfig) store.dispatch({ @@ -208,6 +217,21 @@ class UiTab extends React.Component { }, 2000)() } + formatTime(time) { + let hour = Math.floor(time / 60) + let minute = time % 60 + + if (hour < 10) { + hour = '0' + hour + } + + if (minute < 10) { + minute = '0' + minute + } + + return `${hour}:${minute}` + } + render() { const UiAlert = this.state.UiAlert const UiAlertElement = @@ -232,7 +256,7 @@ class UiTab extends React.Component {