1
0
mirror of https://github.com/BoostIo/Boostnote synced 2025-12-13 01:36:22 +00:00

Merge pull request #2658 from gregueiras/fixIssue2534

Fix issue2534
This commit is contained in:
Junyoung Choi
2020-04-06 17:51:45 +09:00
committed by GitHub
6 changed files with 411 additions and 14 deletions

View File

@@ -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) {

View File

@@ -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')

View File

@@ -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
}

View File

@@ -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)

View File

@@ -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 {
</div>
<div styleName='group-section-control'>
<select
value={config.ui.theme}
value={config.ui.defaultTheme}
onChange={e => this.handleUIChange(e)}
ref='uiTheme'
>
@@ -263,6 +287,101 @@ class UiTab extends React.Component {
</select>
</div>
</div>
<div styleName='group-header2'>{i18n.__('Theme Schedule')}</div>
<div styleName='group-checkBoxSection'>
<label>
<input
onChange={e => this.handleUIChange(e)}
checked={config.ui.enableScheduleTheme}
ref='enableScheduleTheme'
type='checkbox'
/>
&nbsp;
{i18n.__('Enable Scheduled Themes')}
</label>
</div>
<div styleName='group-section'>
<div styleName='group-section-label'>
{i18n.__('Scheduled Theme')}
</div>
<div styleName='group-section-control'>
<select
disabled={!config.ui.enableScheduleTheme}
value={config.ui.scheduledTheme}
onChange={e => this.handleUIChange(e)}
ref='uiScheduledTheme'
>
<optgroup label='Light Themes'>
{uiThemes
.filter(theme => !theme.isDark)
.sort((a, b) => a.label.localeCompare(b.label))
.map(theme => {
return (
<option value={theme.name} key={theme.name}>
{theme.label}
</option>
)
})}
</optgroup>
<optgroup label='Dark Themes'>
{uiThemes
.filter(theme => theme.isDark)
.sort((a, b) => a.label.localeCompare(b.label))
.map(theme => {
return (
<option value={theme.name} key={theme.name}>
{theme.label}
</option>
)
})}
</optgroup>
</select>
</div>
</div>
<div styleName='group-section'>
<div styleName='container'>
<div id='firstRow'>
<span
id='rs-bullet-1'
styleName='rs-label'
>{`End: ${this.formatTime(config.ui.scheduleEnd)}`}</span>
<input
disabled={!config.ui.enableScheduleTheme}
id='rs-range-line-1'
styleName='rs-range'
type='range'
value={config.ui.scheduleEnd}
min='0'
max='1440'
step='5'
ref='scheduleEnd'
onChange={e => this.handleUIChange(e)}
/>
</div>
<div id='secondRow'>
<span
id='rs-bullet-2'
styleName='rs-label'
>{`Start: ${this.formatTime(config.ui.scheduleStart)}`}</span>
<input
disabled={!config.ui.enableScheduleTheme}
id='rs-range-line-2'
styleName='rs-range'
type='range'
value={config.ui.scheduleStart}
min='0'
max='1440'
step='5'
ref='scheduleStart'
onChange={e => this.handleUIChange(e)}
/>
</div>
<div styleName='box-minmax'>
<span>00:00</span>
<span>24:00</span>
</div>
</div>
</div>
<div styleName='group-section'>
<div styleName='group-section-label'>{i18n.__('Language')}</div>

View File

@@ -0,0 +1,103 @@
/**
* @fileoverview Unit test for browser/main/lib/ThemeManager.js
*/
const { chooseTheme, applyTheme } = require('browser/main/lib/ThemeManager')
jest.mock('../../browser/main/lib/ConfigManager', () => {
return {
set: () => {}
}
})
const originalDate = Date
let context = {}
beforeAll(() => {
const constantDate = new Date('2017-11-27T14:33:42Z')
global.Date = class extends Date {
constructor() {
super()
return constantDate
}
}
})
beforeEach(() => {
context = {
ui: {
theme: 'white',
scheduledTheme: 'dark',
enableScheduleTheme: true,
defaultTheme: 'monokai'
}
}
})
afterAll(() => {
global.Date = originalDate
})
test("enableScheduleTheme is false, theme shouldn't change", () => {
context.ui.enableScheduleTheme = false
const beforeTheme = context.ui.theme
chooseTheme(context)
const afterTheme = context.ui.theme
expect(afterTheme).toBe(beforeTheme)
})
// NOT IN SCHEDULE
test("scheduleEnd is bigger than scheduleStart and not in schedule, theme shouldn't change", () => {
const beforeTheme = context.ui.defaultTheme
context.ui.scheduleStart = 720 // 12:00
context.ui.scheduleEnd = 870 // 14:30
chooseTheme(context)
const afterTheme = context.ui.theme
expect(afterTheme).toBe(beforeTheme)
})
test("scheduleStart is bigger than scheduleEnd and not in schedule, theme shouldn't change", () => {
const beforeTheme = context.ui.defaultTheme
context.ui.scheduleStart = 960 // 16:00
context.ui.scheduleEnd = 600 // 10:00
chooseTheme(context)
const afterTheme = context.ui.theme
expect(afterTheme).toBe(beforeTheme)
})
// IN SCHEDULE
test('scheduleEnd is bigger than scheduleStart and in schedule, theme should change', () => {
const beforeTheme = context.ui.scheduledTheme
context.ui.scheduleStart = 720 // 12:00
context.ui.scheduleEnd = 900 // 15:00
chooseTheme(context)
const afterTheme = context.ui.theme
expect(afterTheme).toBe(beforeTheme)
})
test('scheduleStart is bigger than scheduleEnd and in schedule, theme should change', () => {
const beforeTheme = context.ui.scheduledTheme
context.ui.scheduleStart = 1200 // 20:00
context.ui.scheduleEnd = 900 // 15:00
chooseTheme(context)
const afterTheme = context.ui.theme
expect(afterTheme).toBe(beforeTheme)
})
test("theme to apply is not a supported theme, theme shouldn't change", () => {
applyTheme('notATheme')
const afterTheme = document.body.dataset.theme
expect(afterTheme).toBe('default')
})
test('theme to apply is a supported theme, theme should change', () => {
applyTheme(context.ui.defaultTheme)
const afterTheme = document.body.dataset.theme
expect(afterTheme).toBe(context.ui.defaultTheme)
})