diff --git a/ElectronClient/app/gui/ClipperConfigScreen.jsx b/ElectronClient/app/gui/ClipperConfigScreen.jsx index 1579bd985..2da088c6d 100644 --- a/ElectronClient/app/gui/ClipperConfigScreen.jsx +++ b/ElectronClient/app/gui/ClipperConfigScreen.jsx @@ -45,15 +45,21 @@ class ClipperConfigScreenComponent extends React.Component { const style = this.props.style; const theme = themeStyle(this.props.theme); - const headerStyle = { - width: style.width, - }; + const headerStyle = Object.assign({}, theme.headerStyle, { width: style.width }); + + const containerStyle = Object.assign({}, theme.containerStyle, { + overflowY: 'scroll', + height:style.height, + }); + + const buttonStyle = Object.assign({}, theme.buttonStyle, { marginRight: 10 }); const stepBoxStyle = { border: "1px solid #ccc", padding: 15, paddingTop: 0, marginBottom: 15, + backgroundColor: theme.backgroundColor, }; let webClipperStatusComps = []; @@ -68,7 +74,7 @@ class ClipperConfigScreenComponent extends React.Component { webClipperStatusComps.push() } else { webClipperStatusComps.push(

{_('The web clipper service is not enabled.')}

) - webClipperStatusComps.push() + webClipperStatusComps.push() } const apiTokenStyle = Object.assign({}, theme.textStyle, { @@ -81,7 +87,7 @@ class ClipperConfigScreenComponent extends React.Component { return (
-
+

{_('Joplin Web Clipper allows saving web pages and screenshots from your browser to Joplin.')}

{_('In order to use the web clipper, you need to do the following:')}

@@ -106,7 +112,7 @@ class ClipperConfigScreenComponent extends React.Component {

{_('Advanced options')}

{_('Authorisation token:')}

-

{this.props.apiToken} {_('Copy token')}

+

{this.props.apiToken} {_('Copy token')}

{_('This authorisation token is only needed to allow third-party applications to access Joplin.')}

@@ -128,4 +134,4 @@ const mapStateToProps = (state) => { const ClipperConfigScreen = connect(mapStateToProps)(ClipperConfigScreenComponent); -module.exports = { ClipperConfigScreen }; \ No newline at end of file +module.exports = { ClipperConfigScreen }; diff --git a/ElectronClient/app/gui/ConfigScreen.jsx b/ElectronClient/app/gui/ConfigScreen.jsx index 8a6cfcb69..5547bc419 100644 --- a/ElectronClient/app/gui/ConfigScreen.jsx +++ b/ElectronClient/app/gui/ConfigScreen.jsx @@ -53,10 +53,13 @@ class ConfigScreenComponent extends React.Component { const labelStyle = Object.assign({}, theme.textStyle, { display: 'inline-block', marginRight: 10, + color: theme.color, }); const controlStyle = { display: 'inline-block', + color: theme.color, + backgroundColor: theme.backgroundColor, }; const descriptionStyle = Object.assign({}, theme.textStyle, { @@ -120,7 +123,10 @@ class ConfigScreenComponent extends React.Component { updateSettingValue(key, event.target.value); } - const inputStyle = Object.assign({}, controlStyle, { width: '50%', minWidth: '20em' }); + const inputStyle = Object.assign({}, controlStyle, { + width: '50%', + minWidth: '20em', + border: '1px solid' }); const inputType = md.secure === true ? 'password' : 'text'; return ( @@ -164,21 +170,19 @@ class ConfigScreenComponent extends React.Component { render() { const theme = themeStyle(this.props.theme); - const style = Object.assign({}, this.props.style, { overflow: 'auto' }); + const style = Object.assign({ + backgroundColor: theme.backgroundColor + }, this.props.style, { overflow: 'auto' }); const settings = this.state.settings; - const headerStyle = { - width: style.width, - }; + const headerStyle = Object.assign({}, theme.headerStyle, { width: style.width }); - const containerStyle = { - padding: 10, - }; + const containerStyle = Object.assign({}, theme.containerStyle, { padding: 10 }); - const buttonStyle = { + const buttonStyle = Object.assign({}, theme.buttonStyle, { display: this.state.changedSettingKeys.length ? 'inline-block' : 'none', marginRight: 10, - } + }); const settingComps = shared.settingsToComponents(this, 'desktop', settings); @@ -195,7 +199,7 @@ class ConfigScreenComponent extends React.Component { settingComps.push(
- + { statusComp }
); } @@ -228,4 +232,4 @@ const mapStateToProps = (state) => { const ConfigScreen = connect(mapStateToProps)(ConfigScreenComponent); -module.exports = { ConfigScreen }; \ No newline at end of file +module.exports = { ConfigScreen }; diff --git a/ElectronClient/app/gui/DropboxLoginScreen.jsx b/ElectronClient/app/gui/DropboxLoginScreen.jsx index 66cd6c6bb..ffad734b3 100644 --- a/ElectronClient/app/gui/DropboxLoginScreen.jsx +++ b/ElectronClient/app/gui/DropboxLoginScreen.jsx @@ -28,16 +28,18 @@ class DropboxLoginScreenComponent extends React.Component { const style = this.props.style; const theme = themeStyle(this.props.theme); - const headerStyle = { - width: style.width, - }; + const headerStyle = Object.assign({}, theme.headerStyle, { width: style.width }); + const containerStyle = Object.assign({}, theme.containerStyle, { + padding: theme.margin, + height: style.height - theme.headerHeight - theme.margin * 2, + }); const inputStyle = Object.assign({}, theme.inputStyle, { width: 500 }); return (
-
+

{_('To allow Joplin to synchronise with Dropbox, please follow the steps below:')}

{_('Step 1: Open this URL in your browser to authorise the application:')}

{this.state.loginUrl} @@ -59,4 +61,4 @@ const mapStateToProps = (state) => { const DropboxLoginScreen = connect(mapStateToProps)(DropboxLoginScreenComponent); -module.exports = { DropboxLoginScreen }; \ No newline at end of file +module.exports = { DropboxLoginScreen }; diff --git a/ElectronClient/app/gui/EncryptionConfigScreen.jsx b/ElectronClient/app/gui/EncryptionConfigScreen.jsx index 28ab352aa..2fa1ae417 100644 --- a/ElectronClient/app/gui/EncryptionConfigScreen.jsx +++ b/ElectronClient/app/gui/EncryptionConfigScreen.jsx @@ -50,6 +50,13 @@ class EncryptionConfigScreenComponent extends React.Component { renderMasterKey(mk) { const theme = themeStyle(this.props.theme); + const passwordStyle = { + color: theme.color, + backgroundColor: theme.backgroundColor, + border: '1px solid', + borderColor: theme.dividerColor, + } + const onSaveClick = () => { return shared.onSavePasswordClick(this, mk); } @@ -69,7 +76,7 @@ class EncryptionConfigScreenComponent extends React.Component { {mk.source_application} {time.formatMsToLocal(mk.created_time)} {time.formatMsToLocal(mk.updated_time)} - onPasswordChange(event)}/> + onPasswordChange(event)}/> {passwordOk} ); @@ -81,15 +88,13 @@ class EncryptionConfigScreenComponent extends React.Component { const masterKeys = this.state.masterKeys; const containerPadding = 10; - const headerStyle = { - width: style.width, - }; + const headerStyle = Object.assign({}, theme.headerStyle, { width: style.width }); - const containerStyle = { + const containerStyle = Object.assign({}, theme.containerStyle, { padding: containerPadding, overflow: 'auto', height: style.height - theme.headerHeight - containerPadding * 2, - }; + }); const mkComps = []; let nonExistingMasterKeyIds = this.props.notLoadedMasterKeys.slice(); @@ -126,7 +131,7 @@ class EncryptionConfigScreenComponent extends React.Component { } const decryptedItemsInfo =

{shared.decryptedStatText(this)}

; - const toggleButton = + const toggleButton = let masterKeySection = null; @@ -213,4 +218,4 @@ const mapStateToProps = (state) => { const EncryptionConfigScreen = connect(mapStateToProps)(EncryptionConfigScreenComponent); -module.exports = { EncryptionConfigScreen }; \ No newline at end of file +module.exports = { EncryptionConfigScreen }; diff --git a/ElectronClient/app/gui/Header.jsx b/ElectronClient/app/gui/Header.jsx index 070b6c31c..2db012ad5 100644 --- a/ElectronClient/app/gui/Header.jsx +++ b/ElectronClient/app/gui/Header.jsx @@ -108,6 +108,9 @@ class HeaderComponent extends React.Component { color: style.color, fontSize: style.fontSize, fontFamily: style.fontFamily, + backgroundColor: style.searchColor, + border: '1px solid', + borderColor: style.dividerColor, }; const searchButton = { @@ -171,6 +174,8 @@ class HeaderComponent extends React.Component { paddingLeft: theme.headerButtonHPadding, paddingRight: theme.headerButtonHPadding, color: theme.color, + searchColor: theme.backgroundColor, + dividerColor: theme.dividerColor, textDecoration: 'none', fontFamily: theme.fontFamily, fontSize: theme.fontSize, @@ -212,4 +217,4 @@ const mapStateToProps = (state) => { const Header = connect(mapStateToProps)(HeaderComponent); -module.exports = { Header }; \ No newline at end of file +module.exports = { Header }; diff --git a/ElectronClient/app/gui/IconButton.jsx b/ElectronClient/app/gui/IconButton.jsx index 1671d5a33..f1f1244f5 100644 --- a/ElectronClient/app/gui/IconButton.jsx +++ b/ElectronClient/app/gui/IconButton.jsx @@ -35,4 +35,4 @@ class IconButton extends React.Component { } -module.exports = { IconButton }; \ No newline at end of file +module.exports = { IconButton }; diff --git a/ElectronClient/app/gui/MainScreen.jsx b/ElectronClient/app/gui/MainScreen.jsx index dd08f5e9d..4f7c58109 100644 --- a/ElectronClient/app/gui/MainScreen.jsx +++ b/ElectronClient/app/gui/MainScreen.jsx @@ -336,14 +336,17 @@ class MainScreenComponent extends React.Component { } render() { - const style = this.props.style; + const theme = themeStyle(this.props.theme); + const style = Object.assign({ + color: theme.color, + backgroundColor: theme.backgroundColor, + }, this.props.style); const promptOptions = this.state.promptOptions; const folders = this.props.folders; const notes = this.props.notes; const messageBoxVisible = this.props.hasDisabledSyncItems || this.props.showMissingMasterKeyMessage; const sidebarVisibility = this.props.sidebarVisibility; const styles = this.styles(this.props.theme, style.width, style.height, messageBoxVisible, sidebarVisibility); - const theme = themeStyle(this.props.theme); const selectedFolderId = this.props.selectedFolderId; const onConflictFolder = this.props.selectedFolderId === Folder.conflictFolderId(); diff --git a/ElectronClient/app/gui/NoteText.jsx b/ElectronClient/app/gui/NoteText.jsx index 8c1ce89b4..9f64de194 100644 --- a/ElectronClient/app/gui/NoteText.jsx +++ b/ElectronClient/app/gui/NoteText.jsx @@ -37,6 +37,7 @@ require('brace/mode/markdown'); // https://ace.c9.io/build/kitchen-sink.html // https://highlightjs.org/static/demo/ require('brace/theme/chrome'); +require('brace/theme/twilight'); class NoteTextComponent extends React.Component { @@ -1401,6 +1402,10 @@ class NoteTextComponent extends React.Component { paddingLeft: 8, paddingRight: 8, marginRight: rootStyle.paddingLeft, + color: theme.color, + backgroundColor: theme.backgroundColor, + border: '1px solid', + borderColor: theme.dividerColor, }; const toolbarStyle = { @@ -1432,6 +1437,9 @@ class NoteTextComponent extends React.Component { paddingTop: paddingTop + 'px', lineHeight: theme.textAreaLineHeight + 'px', fontSize: theme.fontSize + 'px', + color: theme.color, + backgroundColor: theme.backgroundColor, + editorTheme: theme.editorTheme, }; if (visiblePanes.indexOf('viewer') < 0) { @@ -1462,7 +1470,8 @@ class NoteTextComponent extends React.Component { const htmlHasChanged = this.lastSetHtml_ !== html; if (htmlHasChanged) { - this.webview_.send('setHtml', html); + let options = {codeTheme: theme.codeThemeCss}; + this.webview_.send('setHtml', html, options); this.lastSetHtml_ = html; } @@ -1535,7 +1544,7 @@ class NoteTextComponent extends React.Component { const editor = { const NoteText = connect(mapStateToProps)(NoteTextComponent); -module.exports = { NoteText }; \ No newline at end of file +module.exports = { NoteText }; diff --git a/ElectronClient/app/gui/OneDriveLoginScreen.jsx b/ElectronClient/app/gui/OneDriveLoginScreen.jsx index 8576d661d..faf94dbc2 100644 --- a/ElectronClient/app/gui/OneDriveLoginScreen.jsx +++ b/ElectronClient/app/gui/OneDriveLoginScreen.jsx @@ -73,14 +73,14 @@ class OneDriveLoginScreenComponent extends React.Component { const style = this.props.style; const theme = themeStyle(this.props.theme); - const headerStyle = { - width: style.width, - }; + const headerStyle = Object.assign({}, theme.headerStyle, { width: style.width }); const webviewStyle = { width: this.props.style.width, height: this.props.style.height - theme.headerHeight, overflow: 'hidden', + color: theme.color, + backgroundColor: theme.backgroundColor, }; const headerButtons = [ @@ -109,4 +109,4 @@ const mapStateToProps = (state) => { const OneDriveLoginScreen = connect(mapStateToProps)(OneDriveLoginScreenComponent); -module.exports = { OneDriveLoginScreen }; \ No newline at end of file +module.exports = { OneDriveLoginScreen }; diff --git a/ElectronClient/app/gui/PromptDialog.jsx b/ElectronClient/app/gui/PromptDialog.jsx index 234b87d0f..aa887eea6 100644 --- a/ElectronClient/app/gui/PromptDialog.jsx +++ b/ElectronClient/app/gui/PromptDialog.jsx @@ -59,7 +59,7 @@ class PromptDialog extends React.Component { }; this.styles_.promptDialog = { - backgroundColor: 'white', + backgroundColor: theme.backgroundColor, padding: 16, display: 'inline-block', boxShadow: '6px 6px 20px rgba(0,0,0,0.5)', @@ -69,6 +69,10 @@ class PromptDialog extends React.Component { minWidth: theme.buttonMinWidth, minHeight: theme.buttonMinHeight, marginLeft: 5, + color: theme.color, + backgroundColor: theme.backgroundColor, + border: '1px solid', + borderColor: theme.dividerColor, }; this.styles_.label = { @@ -82,6 +86,10 @@ class PromptDialog extends React.Component { this.styles_.input = { width: 0.5 * width, maxWidth: 400, + color: theme.color, + backgroundColor: theme.backgroundColor, + border: '1px solid', + borderColor: theme.dividerColor, }; this.styles_.desc = Object.assign({}, theme.textStyle, { @@ -142,6 +150,7 @@ class PromptDialog extends React.Component { if (this.props.inputType === 'datetime') { inputComp = onDateTimeChange(momentObject)} @@ -166,7 +175,7 @@ class PromptDialog extends React.Component {
-
+
{inputComp} {descComp}
@@ -180,4 +189,4 @@ class PromptDialog extends React.Component { } -module.exports = { PromptDialog }; \ No newline at end of file +module.exports = { PromptDialog }; diff --git a/ElectronClient/app/gui/StatusScreen.jsx b/ElectronClient/app/gui/StatusScreen.jsx index 1258220de..089bf7e84 100644 --- a/ElectronClient/app/gui/StatusScreen.jsx +++ b/ElectronClient/app/gui/StatusScreen.jsx @@ -47,17 +47,14 @@ class StatusScreenComponent extends React.Component { const theme = themeStyle(this.props.theme); const style = this.props.style; - const headerStyle = { - width: style.width, - }; + const headerStyle = Object.assign({}, theme.headerStyle, { width: style.width }); const containerPadding = 10; - const containerStyle = { + const containerStyle = Object.assign({}, theme.containerStyle, { padding: containerPadding, - overflowY: 'auto', height: style.height - theme.headerHeight - containerPadding * 2, - }; + }); function renderSectionTitleHtml(key, title) { return

{title}

@@ -134,4 +131,4 @@ const mapStateToProps = (state) => { const StatusScreen = connect(mapStateToProps)(StatusScreenComponent); -module.exports = { StatusScreen }; \ No newline at end of file +module.exports = { StatusScreen }; diff --git a/ElectronClient/app/gui/dialogs.js b/ElectronClient/app/gui/dialogs.js index e2853f1a0..c30a0ea2b 100644 --- a/ElectronClient/app/gui/dialogs.js +++ b/ElectronClient/app/gui/dialogs.js @@ -30,4 +30,4 @@ class Dialogs { const dialogs = new Dialogs(); -module.exports = dialogs; \ No newline at end of file +module.exports = dialogs; diff --git a/ElectronClient/app/gui/note-viewer/index.html b/ElectronClient/app/gui/note-viewer/index.html index 791a4d4dd..6d9f359c8 100644 --- a/ElectronClient/app/gui/note-viewer/index.html +++ b/ElectronClient/app/gui/note-viewer/index.html @@ -59,7 +59,7 @@ let hljsScriptAdded = false; let hljsLoaded = false; - function loadHljs(callback) { + function loadHljs(options) { hljsScriptAdded = true; const script = document.createElement('script'); @@ -74,16 +74,16 @@ link.rel = 'stylesheet'; // https://ace.c9.io/build/kitchen-sink.html // https://highlightjs.org/static/demo/ - link.href = 'highlight/styles/atom-one-light.css'; + link.href = 'highlight/styles/' + options.codeTheme; document.getElementById('hlScriptContainer').appendChild(link); } - function loadAndApplyHljs() { + function loadAndApplyHljs(options) { var codeElements = document.getElementsByClassName('code'); if (!codeElements.length) return; if (!hljsScriptAdded) { - this.loadHljs(); + this.loadHljs(options); return; } @@ -142,7 +142,7 @@ contentElement.innerHTML = html; - loadAndApplyHljs(); + loadAndApplyHljs(event.options); // Remove the bullet from "ul" for checkbox lists and extra padding // const checkboxes = document.getElementsByClassName('checkbox'); @@ -319,4 +319,4 @@ - \ No newline at end of file + diff --git a/ElectronClient/app/gui/note-viewer/preload.js b/ElectronClient/app/gui/note-viewer/preload.js index c7be22a64..466008593 100644 --- a/ElectronClient/app/gui/note-viewer/preload.js +++ b/ElectronClient/app/gui/note-viewer/preload.js @@ -5,8 +5,8 @@ const ipcRenderer = require('electron').ipcRenderer; -ipcRenderer.on('setHtml', (event, html) => { - window.postMessage({ target: 'webview', name: 'setHtml', data: { html: html } }, '*'); +ipcRenderer.on('setHtml', (event, html, options) => { + window.postMessage({ target: 'webview', name: 'setHtml', data: { html: html, options: options } }, '*'); }); ipcRenderer.on('setPercentScroll', (event, percent) => { @@ -33,4 +33,4 @@ window.addEventListener('message', (event) => { } else { throw new Error('Unsupported number of args'); } -}); \ No newline at end of file +}); diff --git a/ElectronClient/app/style.css b/ElectronClient/app/style.css index d53975518..82d1a615d 100644 --- a/ElectronClient/app/style.css +++ b/ElectronClient/app/style.css @@ -81,4 +81,4 @@ table td, table th { .note-property-box .rdt { display: inline-block; -} \ No newline at end of file +} diff --git a/ElectronClient/app/theme.js b/ElectronClient/app/theme.js index 1209267d2..0e419394d 100644 --- a/ElectronClient/app/theme.js +++ b/ElectronClient/app/theme.js @@ -2,55 +2,30 @@ const Setting = require('lib/models/Setting.js'); const zoomRatio = Setting.value('style.zoom') / 100; +// globalStyle should be used for properties that do not change across themes +// i.e. should not be used for colors const globalStyle = { fontSize: Math.round(12 * zoomRatio), fontFamily: 'sans-serif', margin: 15, // No text and no interactive component should be within this margin itemMarginTop: 10, itemMarginBottom: 10, - backgroundColor: "#ffffff", - backgroundColorTransparent: 'rgba(255,255,255,0.9)', - oddBackgroundColor: "#dddddd", - color: "#222222", // For regular text - colorError: "red", - colorWarn: "#9A5B00", - colorFaded: "#777777", // For less important text fontSizeSmaller: 14, - dividerColor: "#dddddd", - selectedColor: '#e5e5e5', disabledOpacity: 0.3, buttonMinWidth: 50, buttonMinHeight: 30, textAreaLineHeight: 17, - //backgroundColor2: "#2B2634", - backgroundColor2: "#162B3D", - color2: "#ffffff", - //selectedColor2: "#5A4D70", - selectedColor2: "#0269C2", - colorError2: "#ff6c6c", - - warningBackgroundColor: "#FFD08D", - headerHeight: 35, headerButtonHPadding: 6, toolbarHeight: 35, - - raisedBackgroundColor: "#0080EF", - raisedColor: "#003363", - raisedHighlightedColor: "#ffffff", - tagItemPadding: 3, - tagBackgroundColor: '#e5e5e5' + tagBackgroundColor: '#e5e5e5', }; // For WebView - must correspond to the properties above globalStyle.htmlFontSize = globalStyle.fontSize + 'px'; -globalStyle.htmlColor ='black'; // Note: CSS in WebView component only supports named colors or rgb() notation -globalStyle.htmlBackgroundColor ='white'; -globalStyle.htmlDividerColor = 'rgb(150,150,150)'; -globalStyle.htmlLinkColor ='blue'; globalStyle.htmlLineHeight = Math.round(20 * zoomRatio) + 'px'; globalStyle.marginRight = globalStyle.margin; @@ -60,28 +35,22 @@ globalStyle.marginBottom = globalStyle.margin; globalStyle.htmlMarginLeft = ((globalStyle.marginLeft / 10) * 0.6).toFixed(2) + 'em'; globalStyle.icon = { - color: globalStyle.color, fontSize: 30, }; globalStyle.lineInput = { - color: globalStyle.color, - backgroundColor: globalStyle.backgroundColor, fontFamily: globalStyle.fontFamily, }; globalStyle.textStyle = { - color: globalStyle.color, fontFamily: globalStyle.fontFamily, fontSize: globalStyle.fontSize, lineHeight: '1.6em', }; -globalStyle.textStyle2 = Object.assign({}, globalStyle.textStyle, { - color: globalStyle.color2, -}); +globalStyle.textStyle2 = Object.assign({}, globalStyle.textStyle, {}); -globalStyle.urlStyle = Object.assign({}, globalStyle.textStyle, { color: "#155BDA", textDecoration: 'underline' }); +globalStyle.urlStyle = Object.assign({}, globalStyle.textStyle, { textDecoration: 'underline' }); globalStyle.h1Style = Object.assign({}, globalStyle.textStyle); globalStyle.h1Style.fontSize *= 1.5; @@ -98,7 +67,6 @@ globalStyle.toolbarStyle = { alignItems: 'center', paddingLeft: globalStyle.headerButtonHPadding, paddingRight: globalStyle.headerButtonHPadding, - color: globalStyle.color, textDecoration: 'none', fontFamily: globalStyle.fontFamily, fontSize: globalStyle.fontSize, @@ -107,6 +75,97 @@ globalStyle.toolbarStyle = { justifyContent: 'center', }; +globalStyle.headerStyle = {}; + +globalStyle.inputStyle = { + border: '1px solid', +}; + +globalStyle.containerStyle = { + overflow: 'auto', + overflowY: 'auto', +}; + +globalStyle.buttonStyle = { + marginRight: 10, + border: '1px solid', +}; + +const lightStyle = { + backgroundColor: "#ffffff", + backgroundColorTransparent: 'rgba(255,255,255,0.9)', + oddBackgroundColor: "#dddddd", + color: "#222222", // For regular text + colorError: "red", + colorWarn: "#9A5B00", + colorFaded: "#777777", // For less important text + dividerColor: "#dddddd", + selectedColor: '#e5e5e5', + urlColor: '#155BDA', + + backgroundColor2: "#162B3D", + color2: "#ffffff", + selectedColor2: "#0269C2", + colorError2: "#ff6c6c", + + raisedBackgroundColor: "#0080EF", + raisedColor: "#003363", + raisedHighlightedColor: "#ffffff", + + warningBackgroundColor: "#FFD08D", + + codeColor: "#EFF0F1", + codeBorderColor: '#CBCBCB', + + htmlColor:'black', // Note: CSS in WebView component only supports named colors or rgb() notation + htmlBackgroundColor: 'white', + htmlDividerColor: 'rgb(150,150,150)', + htmlLinkColor: 'blue', + htmlCodeColor: 'rgb(239, 240, 241)', + htmlCodeBorderColor: 'rgb(203, 203, 203)', + + editorTheme: "chrome", + codeThemeCss: "atom-one-light.css", +}; + +const darkStyle = { + backgroundColor: '#1D2024', + backgroundColorTransparent: 'rgba(255,255,255,0.9)', + oddBackgroundColor: "#dddddd", + color: '#dddddd', + colorFaded: '#777777', + colorError: "red", + colorWarn: "#9A5B00", + colorFaded: "#777777", // For less important text + dividerColor: '#555555', + selectedColor: '#333333', + urlColor: '#4E87EE', + + backgroundColor2: "#162B3D", + color2: "#ffffff", + selectedColor2: "#0269C2", + colorError2: "#ff6c6c", + + raisedBackgroundColor: "#0F2051", + raisedColor: "#788BC3", + raisedHighlightedColor: "#ffffff", + + warningBackgroundColor: "#CC6600", + + codeColor: "#2F3031", + codeBorderColor: '#464646', + + htmlColor: 'rgb(220,220,220)', // Note: CSS in WebView component only supports named colors or rgb() notation + htmlBackgroundColor: 'rgb(29,32,36)', + htmlDividerColor: 'rgb(150,150,150)', + htmlLinkColor: 'rgb(166,166,255)', + htmlCodeColor: 'rgb(47, 48, 49)', + htmlCodeBorderColor: 'rgb(70, 70, 70)', + + editorTheme: 'twilight', + codeThemeCss: "atom-one-dark-reasonable.css", +}; + globalStyle.tagStyle = { fontSize: globalStyle.fontSize, fontFamily: globalStyle.fontFamily, @@ -126,25 +185,93 @@ function themeStyle(theme) { if (!theme) throw new Error('Theme must be specified'); if (themeCache_[theme]) return themeCache_[theme]; - let output = Object.assign({}, globalStyle); - if (theme == Setting.THEME_LIGHT) return output; + let output = {}; + if (theme == Setting.THEME_LIGHT) { + output = Object.assign({}, globalStyle, lightStyle); + } + else if (theme == Setting.THEME_DARK) { + output = Object.assign({}, globalStyle, darkStyle); + } - output.backgroundColor = '#1D2024'; - output.color = '#dddddd'; - output.colorFaded = '#777777'; - output.dividerColor = '#555555'; - output.selectedColor = '#333333'; + output.textStyle = Object.assign({}, + output.textStyle, + { color: output.color } + ); - output.raisedBackgroundColor = "#0F2051"; - output.raisedColor = "#788BC3"; - output.raisedHighlightedColor = "#ffffff"; + output.icon = Object.assign({}, + output.icon, + { color: output.color } + ); - output.htmlColor = 'rgb(220,220,220)'; - output.htmlBackgroundColor = 'rgb(29,32,36)'; - output.htmlLinkColor = 'rgb(166,166,255)'; + output.lineInput = Object.assign({}, + output.lineInput, + { + color: output.color, + backgroundColor: output.backgroundColor, + } + ); + + output.textStyle2 = Object.assign({}, + output.textStyle2, + { color: output.color2, } + ); + + output.urlStyle = Object.assign({}, + output.urlStyle, + { color: output.urlColor } + ); + + output.h1Style = Object.assign({}, + output.h1Style, + { color: output.color } + ); + + output.h2Style = Object.assign({}, + output.h2Style, + { color: output.color } + ); + + output.toolbarStyle = Object.assign({}, + output.toolbarStyle, + { color: output.color } + ); + + output.headerStyle = Object.assign({}, + output.headerStyle, + { + color: output.color, + backgroundColor: output.backgroundColor, + } + ); + + output.inputStyle = Object.assign({}, + output.inputStyle, + { + color: output.color, + backgroundColor: output.backgroundColor, + borderColor: output.dividerColor, + } + ); + + output.containerStyle = Object.assign({}, + output.containerStyle, + { + color: output.color, + backgroundColor: output.backgroundColor, + } + ); + + output.buttonStyle = Object.assign({}, + output.buttonStyle, + { + color: output.color, + backgroundColor: output.backgroundColor, + borderColor: output.dividerColor, + } + ); themeCache_[theme] = output; return themeCache_[theme]; } -module.exports = { themeStyle }; \ No newline at end of file +module.exports = { themeStyle }; diff --git a/ReactNativeClient/lib/MdToHtml.js b/ReactNativeClient/lib/MdToHtml.js index 0f03d1f60..842a832bf 100644 --- a/ReactNativeClient/lib/MdToHtml.js +++ b/ReactNativeClient/lib/MdToHtml.js @@ -599,8 +599,8 @@ class MdToHtml { max-width: 100%; } .inline-code { - border: 1px solid #CBCBCB; - background-color: #eff0f1; + border: 1px solid ` + style.htmlCodeBorderColor + `; + background-color: ` + style.htmlCodeColor + `; padding-right: .2em; padding-left: .2em; } diff --git a/ReactNativeClient/lib/models/Setting.js b/ReactNativeClient/lib/models/Setting.js index 6147ec6f9..a7abaaf08 100644 --- a/ReactNativeClient/lib/models/Setting.js +++ b/ReactNativeClient/lib/models/Setting.js @@ -53,7 +53,7 @@ class Setting extends BaseModel { options[Setting.TIME_FORMAT_2] = time.formatMsToLocal(now, Setting.TIME_FORMAT_2); return options; }}, - 'theme': { value: Setting.THEME_LIGHT, type: Setting.TYPE_INT, public: true, appTypes: ['mobile'], isEnum: true, label: () => _('Theme'), options: () => { + 'theme': { value: Setting.THEME_LIGHT, type: Setting.TYPE_INT, public: true, appTypes: ['mobile', 'desktop'], isEnum: true, label: () => _('Theme'), options: () => { let output = {}; output[Setting.THEME_LIGHT] = _('Light'); output[Setting.THEME_DARK] = _('Dark'); @@ -576,4 +576,4 @@ Setting.constants_ = { Setting.autoSaveEnabled = true; -module.exports = Setting; \ No newline at end of file +module.exports = Setting;