From 53513db5b5317b4427d9346bf6962224ea4e24b9 Mon Sep 17 00:00:00 2001 From: Laurent Cozic Date: Fri, 28 Dec 2018 21:40:29 +0100 Subject: [PATCH] Mobile: Fixes #1066: Disable use of FTS when not present on device --- ReactNativeClient/lib/BaseApplication.js | 2 +- .../lib/components/screens/config.js | 17 +++++++- .../lib/components/screens/folder.js | 2 +- .../lib/components/screens/note.js | 4 +- .../lib/components/screens/search.js | 29 ++++++------- ReactNativeClient/lib/joplin-database.js | 41 +++++++++++++++++-- ReactNativeClient/lib/models/Setting.js | 1 + ReactNativeClient/root.js | 9 +++- 8 files changed, 81 insertions(+), 24 deletions(-) diff --git a/ReactNativeClient/lib/BaseApplication.js b/ReactNativeClient/lib/BaseApplication.js index 90587b876..8b9b9a526 100644 --- a/ReactNativeClient/lib/BaseApplication.js +++ b/ReactNativeClient/lib/BaseApplication.js @@ -477,7 +477,7 @@ class BaseApplication { this.dbLogger_.setLevel(initArgs.logLevel); if (Setting.value('env') === 'dev') { - this.dbLogger_.setLevel(Logger.LEVEL_WARN); + this.dbLogger_.setLevel(Logger.LEVEL_INFO); } this.logger_.info('Profile directory: ' + profileDir); diff --git a/ReactNativeClient/lib/components/screens/config.js b/ReactNativeClient/lib/components/screens/config.js index 516ed5045..df7c9a12b 100644 --- a/ReactNativeClient/lib/components/screens/config.js +++ b/ReactNativeClient/lib/components/screens/config.js @@ -9,6 +9,7 @@ const { themeStyle } = require('lib/components/global-style.js'); const Setting = require('lib/models/Setting.js'); const shared = require('lib/components/shared/config-shared.js'); const SyncTargetRegistry = require('lib/SyncTargetRegistry'); +const { reg } = require('lib/registry.js'); import VersionInfo from 'react-native-version-info'; class ConfigScreenComponent extends BaseScreenComponent { @@ -248,8 +249,20 @@ class ConfigScreenComponent extends BaseScreenComponent { ); settingComps.push( - - Version {VersionInfo.appVersion} + + {_('Joplin v%s', VersionInfo.appVersion)} + + ); + + settingComps.push( + + {_('Database v%s', reg.db().version())} + + ); + + settingComps.push( + + {_('FTS enabled: %d', this.props.settings['db.ftsEnabled'])} ); diff --git a/ReactNativeClient/lib/components/screens/folder.js b/ReactNativeClient/lib/components/screens/folder.js index a64443567..4aa1d7d4f 100644 --- a/ReactNativeClient/lib/components/screens/folder.js +++ b/ReactNativeClient/lib/components/screens/folder.js @@ -113,7 +113,7 @@ class FolderScreenComponent extends BaseScreenComponent { saveButtonDisabled={saveButtonDisabled} onSaveButtonPress={() => this.saveFolderButton_press()} /> - this.title_changeText(text)} /> + this.title_changeText(text)} /> { this.dialogbox = dialogbox }}/> ); diff --git a/ReactNativeClient/lib/components/screens/note.js b/ReactNativeClient/lib/components/screens/note.js index b9382e29f..81f5312c8 100644 --- a/ReactNativeClient/lib/components/screens/note.js +++ b/ReactNativeClient/lib/components/screens/note.js @@ -597,8 +597,9 @@ class NoteScreenComponent extends BaseScreenComponent { this.saveOneProperty('body', newBody); }; + // Currently keyword highlighting is supported only when FTS is available. let keywords = []; - if (this.props.searchQuery) { + if (this.props.searchQuery && !!this.props.ftsEnabled) { const parsedQuery = SearchEngine.instance().parseQuery(this.props.searchQuery); keywords = SearchEngine.instance().allParsedQueryTerms(parsedQuery); } @@ -769,6 +770,7 @@ const NoteScreen = connect( folders: state.folders, searchQuery: state.searchQuery, theme: state.settings.theme, + ftsEnabled: state.settings['db.ftsEnabled'], sharedData: state.sharedData, showAdvancedOptions: state.settings.showAdvancedOptions, }; diff --git a/ReactNativeClient/lib/components/screens/search.js b/ReactNativeClient/lib/components/screens/search.js index dc8e604cc..dcd60db10 100644 --- a/ReactNativeClient/lib/components/screens/search.js +++ b/ReactNativeClient/lib/components/screens/search.js @@ -106,22 +106,22 @@ class SearchScreenComponent extends BaseScreenComponent { let notes = [] if (query) { - notes = await SearchEngineUtils.notesForQuery(query); - // Keeping the code below in case of compatibility issue with old versions - // of Android and SQLite FTS. + if (!!this.props.settings['db.ftsEnabled']) { + notes = await SearchEngineUtils.notesForQuery(query); + } else { + let p = query.split(' '); + let temp = []; + for (let i = 0; i < p.length; i++) { + let t = p[i].trim(); + if (!t) continue; + temp.push(t); + } - // let p = query.split(' '); - // let temp = []; - // for (let i = 0; i < p.length; i++) { - // let t = p[i].trim(); - // if (!t) continue; - // temp.push(t); - // } - - // notes = await Note.previews(null, { - // anywherePattern: '*' + temp.join('*') + '*', - // }); + notes = await Note.previews(null, { + anywherePattern: '*' + temp.join('*') + '*', + }); + } } if (!this.isMounted_) return; @@ -193,6 +193,7 @@ const SearchScreen = connect( return { query: state.searchQuery, theme: state.settings.theme, + settings: state.settings, noteSelectionEnabled: state.noteSelectionEnabled, }; } diff --git a/ReactNativeClient/lib/joplin-database.js b/ReactNativeClient/lib/joplin-database.js index 660d2987e..c339c0a73 100644 --- a/ReactNativeClient/lib/joplin-database.js +++ b/ReactNativeClient/lib/joplin-database.js @@ -125,6 +125,7 @@ class JoplinDatabase extends Database { super(driver); this.initialized_ = false; this.tableFields_ = null; + this.version_ = null; } initialized() { @@ -270,7 +271,9 @@ class JoplinDatabase extends Database { // version of the database, so that migration is not run in this case. if (currentVersionIndex < 0) throw new Error('Unknown profile version. Most likely this is an old version of Joplin, while the profile was created by a newer version. Please upgrade Joplin at https://joplin.cozic.net and try again.'); - if (currentVersionIndex == existingDatabaseVersions.length - 1) return false; + if (currentVersionIndex == existingDatabaseVersions.length - 1) return fromVersion; + + let latestVersion = fromVersion; while (currentVersionIndex < existingDatabaseVersions.length - 1) { const targetVersion = existingDatabaseVersions[currentVersionIndex + 1]; @@ -472,14 +475,42 @@ class JoplinDatabase extends Database { } queries.push({ sql: 'UPDATE version SET version = ?', params: [targetVersion] }); - await this.transactionExecBatch(queries); + try { + await this.transactionExecBatch(queries); + } catch (error) { + if (targetVersion === 15) { + this.logger().warn('Could not upgrade to database v15 - FTS feature will not be used', error); + } else { + throw error; + } + } + + latestVersion = targetVersion; + currentVersionIndex++; } + return latestVersion; + } + + async ftsEnabled() { + try { + await this.selectOne('SELECT count(*) FROM notes_fts'); + } catch (error) { + this.logger().warn('FTS check failed', error); + return false; + } + + this.logger().info('FTS check succeeded'); + return true; } + version() { + return this.version_; + } + async initialize() { this.logger().info('Checking for database schema update...'); @@ -496,10 +527,12 @@ class JoplinDatabase extends Database { } const version = !versionRow ? 0 : versionRow.version; + this.version_ = version; this.logger().info('Current database version', version); - const upgraded = await this.upgradeDatabase(version); - if (upgraded) await this.refreshTableFields(); + const newVersion = await this.upgradeDatabase(version); + this.version_ = newVersion; + if (newVersion !== version) await this.refreshTableFields(); this.tableFields_ = {}; diff --git a/ReactNativeClient/lib/models/Setting.js b/ReactNativeClient/lib/models/Setting.js index 1dd366bff..9853f5a92 100644 --- a/ReactNativeClient/lib/models/Setting.js +++ b/ReactNativeClient/lib/models/Setting.js @@ -97,6 +97,7 @@ class Setting extends BaseModel { 'collapsedFolderIds': { value: [], type: Setting.TYPE_ARRAY, public: false }, + 'db.ftsEnabled': { value: -1, type: Setting.TYPE_INT, public: false }, 'encryption.enabled': { value: false, type: Setting.TYPE_BOOL, public: false }, 'encryption.activeMasterKeyId': { value: '', type: Setting.TYPE_STRING, public: false }, 'encryption.passwordCache': { value: {}, type: Setting.TYPE_OBJECT, public: false, secure: true }, diff --git a/ReactNativeClient/root.js b/ReactNativeClient/root.js index c27f65ac5..7a4d4e78a 100644 --- a/ReactNativeClient/root.js +++ b/ReactNativeClient/root.js @@ -417,7 +417,13 @@ async function initialize(dispatch) { if (!locale) locale = defaultLocale(); Setting.setValue('locale', closestSupportedLocale(locale)); if (Setting.value('env') === 'dev') Setting.setValue('sync.target', SyncTargetRegistry.nameToId('onedrive_dev')); - Setting.setValue('firstStart', 0) + Setting.setValue('firstStart', 0); + } + + if (Setting.value('db.ftsEnabled') === -1) { + const ftsEnabled = await db.ftsEnabled(); + Setting.setValue('db.ftsEnabled', ftsEnabled ? 1 : 0); + reg.logger().info('db.ftsEnabled = ', Setting.value('db.ftsEnabled')); } reg.logger().info('Sync target: ' + Setting.value('sync.target')); @@ -481,6 +487,7 @@ async function initialize(dispatch) { }); } } catch (error) { + alert('Initialization error: ' + error.message); reg.logger().error('Initialization error:', error); }