diff --git a/ReactNativeClient/android/app/build.gradle b/ReactNativeClient/android/app/build.gradle index 59fa3186d..a39250253 100644 --- a/ReactNativeClient/android/app/build.gradle +++ b/ReactNativeClient/android/app/build.gradle @@ -90,8 +90,8 @@ android { applicationId "net.cozic.joplin" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 2097321 - versionName "1.0.143" + versionCode 2097325 + versionName "1.0.147" ndk { abiFilters "armeabi-v7a", "x86" } diff --git a/ReactNativeClient/lib/MdToHtml.js b/ReactNativeClient/lib/MdToHtml.js index d9e74e9da..0f03d1f60 100644 --- a/ReactNativeClient/lib/MdToHtml.js +++ b/ReactNativeClient/lib/MdToHtml.js @@ -89,13 +89,14 @@ class MdToHtml { if (!resource) { // Can happen for example if an image is attached to a note, but the resource hasn't // been downloaded from the sync target yet. - console.warn('Cannot load resource: ' + id); + console.info('Cannot load resource: ' + id); + delete this.loadedResources_[id]; return; } if (resource.fetch_status !== Resource.FETCH_STATUS_DONE) { delete this.loadedResources_[id]; - console.warn('Resource not yet fetched: ' + id); + console.info('Resource not yet fetched: ' + id); return; } diff --git a/ReactNativeClient/lib/components/note-body-viewer.js b/ReactNativeClient/lib/components/note-body-viewer.js index dcfaa3370..7b519d69c 100644 --- a/ReactNativeClient/lib/components/note-body-viewer.js +++ b/ReactNativeClient/lib/components/note-body-viewer.js @@ -64,6 +64,11 @@ class NoteBodyViewer extends Component { return (safeGetNoteProp(this.props, 'body') + '').length !== (safeGetNoteProp(nextProps, 'body') + '').length; } + rebuildMd() { + this.mdToHtml_.clearCache(); + this.forceUpdate(); + } + render() { const note = this.props.note; const style = this.props.style; diff --git a/ReactNativeClient/lib/components/screens/note.js b/ReactNativeClient/lib/components/screens/note.js index 0c8d208f4..43c472b17 100644 --- a/ReactNativeClient/lib/components/screens/note.js +++ b/ReactNativeClient/lib/components/screens/note.js @@ -22,6 +22,7 @@ const { Checkbox } = require('lib/components/checkbox.js'); const { _ } = require('lib/locale.js'); const { reg } = require('lib/registry.js'); const { shim } = require('lib/shim.js'); +const ResourceFetcher = require('lib/services/ResourceFetcher'); const { BaseScreenComponent } = require('lib/components/base-screen.js'); const { globalStyle, themeStyle } = require('lib/components/global-style.js'); const { dialogs } = require('lib/dialogs.js'); @@ -136,6 +137,7 @@ class NoteScreenComponent extends BaseScreenComponent { }); }, 5); } else if (item.type_ === BaseModel.TYPE_RESOURCE) { + if (!Resource.isReady(item)) throw new Error(_('This attachment is not downloaded or not decrypted yet.')); const resourcePath = Resource.fullPath(item); await FileViewer.open(resourcePath); } else { @@ -148,6 +150,14 @@ class NoteScreenComponent extends BaseScreenComponent { dialogs.error(this, error.message); } } + + this.resourceFetcher_downloadComplete = async (resource) => { + if (!this.state.note || !this.state.note.body) return; + const resourceIds = await Note.linkedResourceIds(this.state.note.body); + if (resourceIds.indexOf(resource.id) >= 0) { + this.refs.noteBodyViewer.rebuildMd(); + } + } } styles() { @@ -205,6 +215,8 @@ class NoteScreenComponent extends BaseScreenComponent { BackButtonService.addHandler(this.backHandler); NavService.addHandler(this.navHandler); + ResourceFetcher.instance().on('downloadComplete', this.resourceFetcher_downloadComplete); + await shared.initState(this); this.refreshNoteMetadata(); @@ -218,6 +230,8 @@ class NoteScreenComponent extends BaseScreenComponent { BackButtonService.removeHandler(this.backHandler); NavService.removeHandler(this.navHandler); + ResourceFetcher.instance().off('downloadComplete', this.resourceFetcher_downloadComplete); + if (Platform.OS !== 'ios' && this.state.fromShare) { ShareExtension.close(); } @@ -536,6 +550,7 @@ class NoteScreenComponent extends BaseScreenComponent { bodyComponent = { }; shim.isReactNative = () => { + if (typeof navigator === 'object' && typeof navigator.userAgent === 'string' && navigator.userAgent.indexOf('ReactNativeDebugger') >= 0) { + return true; + } + return !shim.isNode(); }; diff --git a/Tools/release-android.js b/Tools/release-android.js index 57c0ce896..eaaf9760c 100644 --- a/Tools/release-android.js +++ b/Tools/release-android.js @@ -1,5 +1,5 @@ const fs = require('fs-extra'); -const { execCommand, githubRelease, githubOauthToken } = require('./tool-utils.js'); +const { execCommand, githubRelease, githubOauthToken, isWindows } = require('./tool-utils.js'); const path = require('path'); const fetch = require('node-fetch'); const uriTemplate = require('uri-template'); @@ -60,9 +60,23 @@ async function main() { console.info('Running from: ' + process.cwd()); console.info('Building APK file...'); - const output = await execCommand('/mnt/c/Windows/System32/cmd.exe /c "cd ReactNativeClient\\android && gradlew.bat assembleRelease -PbuildDir=build --console plain"'); + + let restoreDir = null; + let apkBuildCmd = 'assembleRelease -PbuildDir=build --console plain'; + if (isWindows()) { + apkBuildCmd = '/mnt/c/Windows/System32/cmd.exe /c "cd ReactNativeClient\\android && gradlew.bat ' + apkBuildCmd + '"'; + } else { + process.chdir(rnDir + '/android'); + apkBuildCmd = './gradlew ' + apkBuildCmd; + restoreDir = rootDir; + } + + // const output = await execCommand('/mnt/c/Windows/System32/cmd.exe /c "cd ReactNativeClient\\android && gradlew.bat assembleRelease -PbuildDir=build --console plain"'); + const output = await execCommand(apkBuildCmd); console.info(output); + if (restoreDir) process.chdir(restoreDir); + await fs.mkdirp(releaseDir); console.info('Copying APK to ' + apkFilePath); diff --git a/Tools/tool-utils.js b/Tools/tool-utils.js index 1032b2318..f02703b25 100644 --- a/Tools/tool-utils.js +++ b/Tools/tool-utils.js @@ -115,4 +115,16 @@ toolUtils.githubRelease = async function(project, tagName, isDraft) { return responseJson; } +toolUtils.isLinux = () => { + return process && process.platform === 'linux'; +} + +toolUtils.isWindows = () => { + return process && process.platform === 'win32'; +} + +toolUtils.isMac = () => { + return process && process.platform === 'darwin'; +} + module.exports = toolUtils; \ No newline at end of file