From 4d61ed1dcee357e88c577761aeca1fdbc4a7928f Mon Sep 17 00:00:00 2001 From: Laurent Cozic Date: Tue, 1 Aug 2017 18:53:50 +0000 Subject: [PATCH] Various bug fixes --- CliClient/app/build-doc.js | 20 +-- CliClient/locales/en_GB.po | 48 ++------ CliClient/locales/fr_FR.po | 63 ++++------ CliClient/locales/joplin.pot | 48 ++------ README.md | 2 +- ReactNativeClient/android/app/build.gradle | 4 +- .../lib/components/global-style.js | 11 +- .../lib/components/note-body-viewer.js | 17 +-- .../lib/components/screens/note.js | 115 +++++++++++------- 9 files changed, 141 insertions(+), 187 deletions(-) diff --git a/CliClient/app/build-doc.js b/CliClient/app/build-doc.js index ea9d8329d..8e8481736 100644 --- a/CliClient/app/build-doc.js +++ b/CliClient/app/build-doc.js @@ -78,22 +78,22 @@ function getOptionColWidth(options) { function getHeader() { let output = []; - output.push(_('NAME')); + output.push('NAME'); output.push(''); - output.push(wrap(_('joplin - a note taking and todo app with synchronisation capabilities'), INDENT)); + output.push(wrap('joplin - a note taking and todo app with synchronisation capabilities'), INDENT); output.push(''); - output.push(_('DESCRIPTION')); + output.push('DESCRIPTION'); output.push(''); let description = []; - description.push(_('Joplin is a note taking and todo application, which can handle a large number of notes organised into notebooks.')); - description.push(_('The notes are searchable, can be copied, tagged and modified with your own text editor.')); + description.push('Joplin is a note taking and todo application, which can handle a large number of notes organised into notebooks.'); + description.push('The notes are searchable, can be copied, tagged and modified with your own text editor.'); description.push("\n\n"); - description.push(_('The notes can be synchronised with various target including the file system (for example with a network directory) or with Microsoft OneDrive.')); + description.push('The notes can be synchronised with various target including the file system (for example with a network directory) or with Microsoft OneDrive.'); description.push("\n\n"); - description.push(_('Notes exported from Evenotes via .enex files can be imported into Joplin, including the formatted content, resources (images, attachments, etc.) and complete metadata (geolocation, updated time, created time, etc.).')); + description.push('Notes exported from Evenotes via .enex files can be imported into Joplin, including the formatted content, resources (images, attachments, etc.) and complete metadata (geolocation, updated time, created time, etc.).'); output.push(wrap(description.join(''), INDENT)); @@ -103,13 +103,13 @@ function getHeader() { function getFooter() { let output = []; - output.push(_('WEBSITE')); + output.push('WEBSITE'); output.push(''); output.push(INDENT + 'http://joplin.cozic.net'); output.push(''); - output.push(_('LICENSE')); + output.push('LICENSE'); output.push(''); let filePath = rootDir + '/LICENSE_' + languageCode(); if (!fs.existsSync(filePath)) filePath = rootDir + '/LICENSE'; @@ -134,7 +134,7 @@ async function main() { const commandsText = commandBlocks.join("\n\n"); const footerText = getFooter(); - console.info(headerText + "\n\n" + _('USAGE') + "\n\n" + commandsText + "\n\n" + footerText); + console.info(headerText + "\n\n" + 'USAGE' + "\n\n" + commandsText + "\n\n" + footerText); } main().catch((error) => { diff --git a/CliClient/locales/en_GB.po b/CliClient/locales/en_GB.po index acd2d2d4d..705468b19 100644 --- a/CliClient/locales/en_GB.po +++ b/CliClient/locales/en_GB.po @@ -44,45 +44,6 @@ msgstr "" msgid "No notebook is defined. Create one with `mkbook `." msgstr "" -msgid "NAME" -msgstr "" - -msgid "joplin - a note taking and todo app with synchronisation capabilities" -msgstr "" - -msgid "DESCRIPTION" -msgstr "" - -msgid "" -"Joplin is a note taking and todo application, which can handle a large " -"number of notes organised into notebooks." -msgstr "" - -msgid "" -"The notes are searchable, can be copied, tagged and modified with your own " -"text editor." -msgstr "" - -msgid "" -"The notes can be synchronised with various target including the file system " -"(for example with a network directory) or with Microsoft OneDrive." -msgstr "" - -msgid "" -"Notes exported from Evenotes via .enex files can be imported into Joplin, " -"including the formatted content, resources (images, attachments, etc.) and " -"complete metadata (geolocation, updated time, created time, etc.)." -msgstr "" - -msgid "WEBSITE" -msgstr "" - -msgid "LICENSE" -msgstr "" - -msgid "USAGE" -msgstr "" - msgid "Displays the given note." msgstr "" @@ -448,6 +409,15 @@ msgstr "" msgid "%d hours" msgstr "" +msgid "Theme" +msgstr "" + +msgid "Light" +msgstr "" + +msgid "Dark" +msgstr "" + msgid "Sync status (synced items / total items)" msgstr "" diff --git a/CliClient/locales/fr_FR.po b/CliClient/locales/fr_FR.po index bb9e0e57e..88375de7a 100644 --- a/CliClient/locales/fr_FR.po +++ b/CliClient/locales/fr_FR.po @@ -46,45 +46,6 @@ msgstr "Quitter le logiciel." msgid "No notebook is defined. Create one with `mkbook `." msgstr "Aucun carnet n'est défini. Créez-en un avec `mkbook `." -msgid "NAME" -msgstr "NOM" - -msgid "joplin - a note taking and todo app with synchronisation capabilities" -msgstr "" - -msgid "DESCRIPTION" -msgstr "DESCRIPTION" - -msgid "" -"Joplin is a note taking and todo application, which can handle a large " -"number of notes organised into notebooks." -msgstr "" - -msgid "" -"The notes are searchable, can be copied, tagged and modified with your own " -"text editor." -msgstr "" - -msgid "" -"The notes can be synchronised with various target including the file system " -"(for example with a network directory) or with Microsoft OneDrive." -msgstr "" - -msgid "" -"Notes exported from Evenotes via .enex files can be imported into Joplin, " -"including the formatted content, resources (images, attachments, etc.) and " -"complete metadata (geolocation, updated time, created time, etc.)." -msgstr "" - -msgid "WEBSITE" -msgstr "SITE INTERNET" - -msgid "LICENSE" -msgstr "LISENSE" - -msgid "USAGE" -msgstr "UTILISATION" - msgid "Displays the given note." msgstr "Affiche la note." @@ -490,6 +451,15 @@ msgstr "%d heure" msgid "%d hours" msgstr "%d heures" +msgid "Theme" +msgstr "Apparence" + +msgid "Light" +msgstr "Clair" + +msgid "Dark" +msgstr "Sombre" + msgid "Sync status (synced items / total items)" msgstr "Status de la synchronisation (objets synchro. / total)" @@ -609,6 +579,21 @@ msgstr "" msgid "Welcome" msgstr "Bienvenu" +#~ msgid "NAME" +#~ msgstr "NOM" + +#~ msgid "DESCRIPTION" +#~ msgstr "DESCRIPTION" + +#~ msgid "WEBSITE" +#~ msgstr "SITE INTERNET" + +#~ msgid "LICENSE" +#~ msgstr "LISENSE" + +#~ msgid "USAGE" +#~ msgstr "UTILISATION" + #~ msgid "Folder does not exists: \"%s\". Create it?" #~ msgstr "Ce carnet n'existe pas : \"%s\". Le créer ?" diff --git a/CliClient/locales/joplin.pot b/CliClient/locales/joplin.pot index acd2d2d4d..705468b19 100644 --- a/CliClient/locales/joplin.pot +++ b/CliClient/locales/joplin.pot @@ -44,45 +44,6 @@ msgstr "" msgid "No notebook is defined. Create one with `mkbook `." msgstr "" -msgid "NAME" -msgstr "" - -msgid "joplin - a note taking and todo app with synchronisation capabilities" -msgstr "" - -msgid "DESCRIPTION" -msgstr "" - -msgid "" -"Joplin is a note taking and todo application, which can handle a large " -"number of notes organised into notebooks." -msgstr "" - -msgid "" -"The notes are searchable, can be copied, tagged and modified with your own " -"text editor." -msgstr "" - -msgid "" -"The notes can be synchronised with various target including the file system " -"(for example with a network directory) or with Microsoft OneDrive." -msgstr "" - -msgid "" -"Notes exported from Evenotes via .enex files can be imported into Joplin, " -"including the formatted content, resources (images, attachments, etc.) and " -"complete metadata (geolocation, updated time, created time, etc.)." -msgstr "" - -msgid "WEBSITE" -msgstr "" - -msgid "LICENSE" -msgstr "" - -msgid "USAGE" -msgstr "" - msgid "Displays the given note." msgstr "" @@ -448,6 +409,15 @@ msgstr "" msgid "%d hours" msgstr "" +msgid "Theme" +msgstr "" + +msgid "Light" +msgstr "" + +msgid "Dark" +msgstr "" + msgid "Sync status (synced items / total items)" msgstr "" diff --git a/README.md b/README.md index 3d05befeb..7be37a932 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ An Android app and a command line interface are currently available. Both can sy - Search functionality. - Geolocation support. - Supports multiple languages. +- Mobile: Support for dark theme / light theme. # Localisation @@ -50,7 +51,6 @@ The applications are currently available in English and French. If you would lik - All clients: End to end encryption. - All clients: Support for Dropbox synchronisation. - Mobile: Compile Windows app? -- Mobile: Support for dark theme / light theme. - Mobile: Link for non-image resources. - Mobile: Handle tags. - Mobile: Markdown edition support diff --git a/ReactNativeClient/android/app/build.gradle b/ReactNativeClient/android/app/build.gradle index 9673c360a..5902fd45f 100644 --- a/ReactNativeClient/android/app/build.gradle +++ b/ReactNativeClient/android/app/build.gradle @@ -90,8 +90,8 @@ android { applicationId "net.cozic.joplin" minSdkVersion 16 targetSdkVersion 22 - versionCode 38 - versionName "0.9.25" + versionCode 39 + versionName "0.9.26" ndk { abiFilters "armeabi-v7a", "x86" } diff --git a/ReactNativeClient/lib/components/global-style.js b/ReactNativeClient/lib/components/global-style.js index 894e15e46..3d1b243b3 100644 --- a/ReactNativeClient/lib/components/global-style.js +++ b/ReactNativeClient/lib/components/global-style.js @@ -21,8 +21,10 @@ const globalStyle = { // For WebView - must correspond to the properties above htmlFontSize: '20x', - htmlColor: 'black', // Note: CSS in WebView component only seem to work if the colour is written in full letters (so no hexadecimal) + htmlColor: 'black', // Note: CSS in WebView component only supports named colors or rgb() notation + htmlBackgroundColor: 'white', htmlDividerColor: 'Gainsboro', + htmlLinkColor: 'blue', }; globalStyle.marginRight = globalStyle.margin; @@ -50,16 +52,19 @@ function themeStyle(theme) { if (theme == Setting.THEME_LIGHT) return output; output.backgroundColor = '#1D2024'; - output.color = '#ffffff'; + output.color = '#dddddd'; output.colorFaded = '#777777'; output.dividerColor = '#555555'; output.selectedColor = '#333333'; - output.htmlColor = 'white'; output.raisedBackgroundColor = "#0F2051"; output.raisedColor = "#788BC3"; output.raisedHighlightedColor = "#ffffff"; + output.htmlColor = 'rgb(220,220,220)'; + output.htmlBackgroundColor = 'rgb(29,32,36)'; + output.htmlLinkColor = 'rgb(166,166,255)'; + themeCache_[theme] = output; return themeCache_[theme]; } diff --git a/ReactNativeClient/lib/components/note-body-viewer.js b/ReactNativeClient/lib/components/note-body-viewer.js index 9a37af10c..dca9989b8 100644 --- a/ReactNativeClient/lib/components/note-body-viewer.js +++ b/ReactNativeClient/lib/components/note-body-viewer.js @@ -1,5 +1,5 @@ import React, { Component } from 'react'; -import { WebView, View } from 'react-native'; +import { WebView, View, Linking } from 'react-native'; import { globalStyle } from 'lib/components/global-style.js'; import { Resource } from 'lib/models/resource.js'; import { shim } from 'lib/shim.js'; @@ -45,7 +45,7 @@ class NoteBodyViewer extends Component { return body; } - markdownToHtml (body, style) { + markdownToHtml(body, style) { // https://necolas.github.io/normalize.css/ const normalizeCss = ` html{line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0} @@ -59,6 +59,7 @@ class NoteBodyViewer extends Component { font-size: ` + style.htmlFontSize + `; color: ` + style.htmlColor + `; line-height: 1.5em; + background-color: ` + style.htmlBackgroundColor + `; } h1 { font-size: 1.2em; @@ -68,8 +69,8 @@ class NoteBodyViewer extends Component { font-size: 1em; font-weight: bold; } - li { - + a { + color: ` + style.htmlLinkColor + ` } ul { padding-left: 1em; @@ -134,12 +135,14 @@ class NoteBodyViewer extends Component { return '[Image: ' + htmlentities(r.title) + '(' + htmlentities(r.mime) + ')]'; } - let html = body ? '' + marked(body, { + let styleHtml = ''; + + let html = body ? styleHtml + marked(body, { gfm: true, breaks: true, renderer: renderer, sanitize: true, - }) : ''; + }) : styleHtml; let elementId = 1; while (html.indexOf('°°JOP°') >= 0) { @@ -166,7 +169,7 @@ class NoteBodyViewer extends Component { return ( { let msg = event.nativeEvent.data; diff --git a/ReactNativeClient/lib/components/screens/note.js b/ReactNativeClient/lib/components/screens/note.js index fdacaafa4..bbf93c10a 100644 --- a/ReactNativeClient/lib/components/screens/note.js +++ b/ReactNativeClient/lib/components/screens/note.js @@ -16,50 +16,10 @@ import { reg } from 'lib/registry.js'; import { shim } from 'lib/shim.js'; import { BaseScreenComponent } from 'lib/components/base-screen.js'; import { dialogs } from 'lib/dialogs.js'; -import { globalStyle } from 'lib/components/global-style.js'; +import { globalStyle, themeStyle } from 'lib/components/global-style.js'; import DialogBox from 'react-native-dialogbox'; import { NoteBodyViewer } from 'lib/components/note-body-viewer.js'; -const styleObject = { - titleTextInput: { - flex: 1, - paddingLeft: 0, - color: globalStyle.color, - backgroundColor: globalStyle.backgroundColor, - fontWeight: 'bold', - fontSize: globalStyle.fontSize, - }, - bodyTextInput: { - flex: 1, - paddingLeft: globalStyle.marginLeft, - paddingRight: globalStyle.marginRight, - textAlignVertical: 'top', - color: globalStyle.color, - backgroundColor: globalStyle.backgroundColor, - fontSize: globalStyle.fontSize, - }, - noteBodyViewer: { - flex: 1, - paddingLeft: globalStyle.marginLeft, - paddingRight: globalStyle.marginRight, - paddingTop: globalStyle.marginTop, - paddingBottom: globalStyle.marginBottom, - }, -}; - -styleObject.titleContainer = { - flex: 0, - flexDirection: 'row', - paddingLeft: globalStyle.marginLeft, - paddingRight: globalStyle.marginRight, - borderBottomColor: globalStyle.dividerColor, - borderBottomWidth: 1, -}; - -styleObject.titleContainerTodo = Object.assign({}, styleObject.titleContainer); - -const styles = StyleSheet.create(styleObject); - class NoteScreenComponent extends BaseScreenComponent { static navigationOptions(options) { @@ -82,6 +42,8 @@ class NoteScreenComponent extends BaseScreenComponent { this.saveButtonHasBeenShown_ = false; + this.styles_ = {}; + // Disabled for now because it doesn't work consistently and proabably interfer with the backHandler // on root.js. Handling of the back button should be in one single place for this to work well. @@ -102,6 +64,55 @@ class NoteScreenComponent extends BaseScreenComponent { // }; } + styles() { + const themeId = this.props.theme; + const theme = themeStyle(themeId); + + if (this.styles_[themeId]) return this.styles_[themeId]; + this.styles_ = {}; + + let styles = { + // titleTextInput: { + // flex: 1, + // paddingLeft: 0, + // color: theme.color, + // backgroundColor: theme.backgroundColor, + // fontWeight: 'bold', + // fontSize: theme.fontSize, + // }, + bodyTextInput: { + flex: 1, + paddingLeft: theme.marginLeft, + paddingRight: theme.marginRight, + textAlignVertical: 'top', + color: theme.color, + backgroundColor: theme.backgroundColor, + fontSize: theme.fontSize, + }, + noteBodyViewer: { + flex: 1, + paddingLeft: theme.marginLeft, + paddingRight: theme.marginRight, + paddingTop: theme.marginTop, + paddingBottom: theme.marginBottom, + }, + }; + + styles.titleContainer = { + flex: 0, + flexDirection: 'row', + paddingLeft: theme.marginLeft, + paddingRight: theme.marginRight, + borderBottomColor: theme.dividerColor, + borderBottomWidth: 1, + }; + + styles.titleContainerTodo = Object.assign({}, styles.titleContainer); + + this.styles_[themeId] = StyleSheet.create(styles); + return this.styles_[themeId]; + } + isModified() { if (!this.state.note || !this.state.lastSavedNote) return false; let diff = BaseModel.diffObjects(this.state.note, this.state.lastSavedNote); @@ -294,6 +305,7 @@ class NoteScreenComponent extends BaseScreenComponent { ); } + const theme = themeStyle(this.props.theme); const note = this.state.note; const isTodo = !!Number(note.is_todo); const folder = this.state.folder; @@ -305,14 +317,14 @@ class NoteScreenComponent extends BaseScreenComponent { this.saveOneProperty('body', newBody); }; - bodyComponent = { onCheckboxChange(newBody) }}/> + bodyComponent = { onCheckboxChange(newBody) }}/> } else { const focusBody = !isNew && !!note.title; bodyComponent = ( this.body_changeText(text)} @@ -352,14 +364,22 @@ class NoteScreenComponent extends BaseScreenComponent { if (showSaveButton) this.saveButtonHasBeenShown_ = true; - const titleContainerStyle = isTodo ? styles.titleContainerTodo : styles.titleContainer; + const titleContainerStyle = isTodo ? this.styles().titleContainerTodo : this.styles().titleContainer; + + let titleTextInputStyle = { + flex: 1, + paddingLeft: 0, + color: theme.color, + backgroundColor: theme.backgroundColor, + fontWeight: 'bold', + fontSize: theme.fontSize, + }; - const titleTextInputStyle = Object.assign({}, styleObject.titleTextInput); titleTextInputStyle.height = this.state.titleTextInputHeight; const titleComp = ( - { isTodo && { this.todoCheckbox_change(checked) }} /> } + { isTodo && { this.todoCheckbox_change(checked) }} /> } this.titleTextInput_contentSizeChange(event)} autoFocus={isNew} @@ -374,7 +394,7 @@ class NoteScreenComponent extends BaseScreenComponent { ); return ( - +