diff --git a/CliClient/app/command-import-enex.js b/CliClient/app/command-import-enex.js index 5cf0d5b87..50c044357 100644 --- a/CliClient/app/command-import-enex.js +++ b/CliClient/app/command-import-enex.js @@ -39,7 +39,6 @@ class Command extends BaseCommand { } } else { folderTitle = filename(filePath); - folderTitle = _('Imported - %s', folderTitle); let inc = 0; while (true) { let t = folderTitle + (inc ? ' (' + inc + ')' : ''); diff --git a/CliClient/app/command-sync.js b/CliClient/app/command-sync.js index efe652da8..2327aa165 100644 --- a/CliClient/app/command-sync.js +++ b/CliClient/app/command-sync.js @@ -76,7 +76,7 @@ class Command extends BaseCommand { this.syncTarget_ = Setting.value('sync.target'); if (args.options.target) this.syncTarget_ = args.options.target; - if (this.syncTarget_ == Setting.SYNC_TARGET_ONEDRIVE && !await reg.syncHasAuth(this.syncTarget_)) { + if (this.syncTarget_ == Setting.SYNC_TARGET_ONEDRIVE && !reg.syncHasAuth(this.syncTarget_)) { const oneDriveApiUtils = new OneDriveApiNodeUtils(reg.oneDriveApi()); const auth = await oneDriveApiUtils.oauthDance(this); Setting.setValue('sync.3.auth', auth ? JSON.stringify(auth) : null); @@ -139,7 +139,7 @@ class Command extends BaseCommand { vorpalUtils.redrawDone(); this.log(_('Cancelling...')); - if (await reg.syncHasAuth(target)) { + if (reg.syncHasAuth(target)) { let sync = await reg.synchronizer(target); if (sync) sync.cancel(); } else { diff --git a/CliClient/app/command-todo.js b/CliClient/app/command-todo.js new file mode 100644 index 000000000..ee15ecbba --- /dev/null +++ b/CliClient/app/command-todo.js @@ -0,0 +1,50 @@ +import { BaseCommand } from './base-command.js'; +import { app } from './app.js'; +import { _ } from 'lib/locale.js'; +import { BaseModel } from 'lib/base-model.js'; +import { Folder } from 'lib/models/folder.js'; +import { Note } from 'lib/models/note.js'; +import { time } from 'lib/time-utils.js'; +import { autocompleteItems } from './autocomplete.js'; + +class Command extends BaseCommand { + + usage() { + return 'todo '; + } + + description() { + return _(' can either be "toggle" or "clear". Use "toggle" to toggle the given todo between completed and uncompleted state (If the target is not a single note it will be converted to a todo). Use "clear" to convert the todo back to a regular note.'); + } + + autocomplete() { + return { data: autocompleteItems }; + } + + async action(args) { + const action = args.action; + const pattern = args.pattern; + const notes = await app().loadItems(BaseModel.TYPE_NOTE, pattern); + if (!notes.length) throw new Error(_('Cannot find "%s".', pattern)); + + for (let i = 0; i < notes.length; i++) { + const note = notes[i]; + + let toSave = { + id: note.id, + }; + + if (action == 'toggle') { + toSave.todo_completed = note.todo_completed ? 0 : time.unixMs(); + if (!note.is_todo) toSave.is_todo = 1; + } else if (action == 'clear') { + toSave.is_todo = 0; + } + + await Note.save(toSave); + } + } + +} + +module.exports = Command; \ No newline at end of file diff --git a/CliClient/app/onedrive-api-node-utils.js b/CliClient/app/onedrive-api-node-utils.js index 85e0a05af..8607e367c 100644 --- a/CliClient/app/onedrive-api-node-utils.js +++ b/CliClient/app/onedrive-api-node-utils.js @@ -20,11 +20,25 @@ class OneDriveApiNodeUtils { return [1917, 9917, 8917]; } + makePage(message) { + const header = ` + + `; + + const footer = ` + + `; + + return header + message + footer; + } + async oauthDance(targetConsole = null) { if (targetConsole === null) targetConsole = console; this.api().setAuth(null); + + let ports = this.possibleOAuthDancePorts(); let port = null; for (let i = 0; i < ports.length; i++) { @@ -46,9 +60,9 @@ class OneDriveApiNodeUtils { server.on('request', (request, response) => { const query = urlParser.parse(request.url, true).query; - function writeResponse(code, message) { + const writeResponse = (code, message) => { response.writeHead(code, {"Content-Type": "text/html"}); - response.write(message); + response.write(this.makePage(message)); response.end(); } diff --git a/CliClient/locales/en_GB.po b/CliClient/locales/en_GB.po index 4ac79c411..33ff266d2 100644 --- a/CliClient/locales/en_GB.po +++ b/CliClient/locales/en_GB.po @@ -110,10 +110,6 @@ msgstr "" msgid "Folder does not exists: \"%s\". Create it?" msgstr "" -#, javascript-format -msgid "Imported - %s" -msgstr "" - #, javascript-format msgid "File \"%s\" will be imported into notebook \"%s\". Continue?" msgstr "" @@ -252,6 +248,13 @@ msgstr "" msgid "Invalid command: \"%s\"" msgstr "" +msgid "" +" can either be \"toggle\" or \"clear\". Use \"toggle\" to toggle the " +"given todo between completed and uncompleted state (If the target is not a " +"single note it will be converted to a todo). Use \"clear\" to convert the " +"todo back to a regular note." +msgstr "" + msgid "" "Switches to [notebook] - all further operations will happen within this " "notebook." @@ -267,10 +270,6 @@ msgstr "" msgid "Fatal error:" msgstr "" -#, javascript-format -msgid "All potential ports are in use - please report the issue at %s" -msgstr "" - msgid "" "The application has been authorised - you may now close this browser tab." msgstr "" diff --git a/CliClient/locales/fr_FR.po b/CliClient/locales/fr_FR.po index 14a3ecf2e..92990f1e5 100644 --- a/CliClient/locales/fr_FR.po +++ b/CliClient/locales/fr_FR.po @@ -121,10 +121,6 @@ msgstr "Ne pas demander de confirmation." msgid "Folder does not exists: \"%s\". Create it?" msgstr "Ce carnet n'existe pas : \"%s\". Le créer ?" -#, javascript-format -msgid "Imported - %s" -msgstr "Importé - %s" - #, javascript-format msgid "File \"%s\" will be imported into notebook \"%s\". Continue?" msgstr "Le fichier \"%s\" va être importé dans le carnet \"%s\". Continuer ?" @@ -280,6 +276,13 @@ msgstr "" msgid "Invalid command: \"%s\"" msgstr "Commande invalie : \"%s\"" +msgid "" +" can either be \"toggle\" or \"clear\". Use \"toggle\" to toggle the " +"given todo between completed and uncompleted state (If the target is not a " +"single note it will be converted to a todo). Use \"clear\" to convert the " +"todo back to a regular note." +msgstr "" + msgid "" "Switches to [notebook] - all further operations will happen within this " "notebook." @@ -296,12 +299,6 @@ msgstr "%s %s (%s)" msgid "Fatal error:" msgstr "Erreur fatale :" -#, javascript-format -msgid "All potential ports are in use - please report the issue at %s" -msgstr "" -"Tous les ports sont en cours d'utilisation. Veuillez signaler ce problème " -"sur %s" - msgid "" "The application has been authorised - you may now close this browser tab." msgstr "Le logiciel a été autorisé. Vous pouvez maintenant fermer cet onglet." @@ -556,6 +553,14 @@ msgstr "" msgid "Welcome" msgstr "" +#~ msgid "All potential ports are in use - please report the issue at %s" +#~ msgstr "" +#~ "Tous les ports sont en cours d'utilisation. Veuillez signaler ce problème " +#~ "sur %s" + +#~ msgid "Imported - %s" +#~ msgstr "Importé - %s" + #~ msgid "" #~ "There is currently no notebook. Create one by clicking on the (+) button." #~ msgstr "" diff --git a/CliClient/locales/joplin.pot b/CliClient/locales/joplin.pot index 4ac79c411..33ff266d2 100644 --- a/CliClient/locales/joplin.pot +++ b/CliClient/locales/joplin.pot @@ -110,10 +110,6 @@ msgstr "" msgid "Folder does not exists: \"%s\". Create it?" msgstr "" -#, javascript-format -msgid "Imported - %s" -msgstr "" - #, javascript-format msgid "File \"%s\" will be imported into notebook \"%s\". Continue?" msgstr "" @@ -252,6 +248,13 @@ msgstr "" msgid "Invalid command: \"%s\"" msgstr "" +msgid "" +" can either be \"toggle\" or \"clear\". Use \"toggle\" to toggle the " +"given todo between completed and uncompleted state (If the target is not a " +"single note it will be converted to a todo). Use \"clear\" to convert the " +"todo back to a regular note." +msgstr "" + msgid "" "Switches to [notebook] - all further operations will happen within this " "notebook." @@ -267,10 +270,6 @@ msgstr "" msgid "Fatal error:" msgstr "" -#, javascript-format -msgid "All potential ports are in use - please report the issue at %s" -msgstr "" - msgid "" "The application has been authorised - you may now close this browser tab." msgstr "" diff --git a/ReactNativeClient/lib/models/setting.js b/ReactNativeClient/lib/models/setting.js index 441e3becc..82c7a5f9c 100644 --- a/ReactNativeClient/lib/models/setting.js +++ b/ReactNativeClient/lib/models/setting.js @@ -134,7 +134,12 @@ class Setting extends BaseModel { const md = this.settingMetadata(key); if (md.type == Setting.TYPE_INT) return Math.floor(Number(value)); if (md.type == Setting.TYPE_BOOL) { - if (typeof value === 'string') value = Number(value); + if (typeof value === 'string') { + value = value.toLowerCase(); + if (value === 'true') return true; + if (value === 'false') return false; + value = Number(value); + } return !!value; } return value; diff --git a/ReactNativeClient/lib/onedrive-api.js b/ReactNativeClient/lib/onedrive-api.js index d1c74b8b1..a6c1dbf70 100644 --- a/ReactNativeClient/lib/onedrive-api.js +++ b/ReactNativeClient/lib/onedrive-api.js @@ -236,7 +236,10 @@ class OneDriveApi { } async refreshAccessToken() { - if (!this.auth_) throw new Error('Cannot refresh token: authentication data is missing'); + if (!this.auth_ || !this.auth_.refresh_token) { + this.setAuth(null); + throw new Error('Cannot refresh token: authentication data is missing'); + } let body = new shim.FormData(); body.append('client_id', this.clientId()); diff --git a/ReactNativeClient/lib/registry.js b/ReactNativeClient/lib/registry.js index f907770a7..b05b92e81 100644 --- a/ReactNativeClient/lib/registry.js +++ b/ReactNativeClient/lib/registry.js @@ -97,7 +97,7 @@ reg.synchronizer = async (syncTargetId) => { return sync; } -reg.syncHasAuth = async (syncTargetId) => { +reg.syncHasAuth = (syncTargetId) => { if (syncTargetId == Setting.SYNC_TARGET_ONEDRIVE && !reg.oneDriveApi().auth()) { return false; } @@ -121,7 +121,7 @@ reg.scheduleSync = async (delay = null) => { const syncTargetId = Setting.value('sync.target'); - if (!reg.syncHasAuth()) { + if (!reg.syncHasAuth(syncTargetId)) { reg.logger().info('Synchronizer is missing credentials - manual sync required to authenticate.'); return; } @@ -135,7 +135,7 @@ reg.scheduleSync = async (delay = null) => { Setting.setValue('sync.context', JSON.stringify(newContext)); } catch (error) { if (error.code == 'alreadyStarted') { - reg.logger.info(error.message); + reg.logger().info(error.message); } else { throw error; } @@ -152,8 +152,9 @@ reg.scheduleSync = async (delay = null) => { } reg.syncStarted = async () => { - if (!reg.syncHasAuth()) return false; - const sync = await reg.synchronizer(Setting.value('sync.target')); + const syncTarget = Setting.value('sync.target'); + if (!reg.syncHasAuth(syncTarget)) return false; + const sync = await reg.synchronizer(syncTarget); return sync.state() != 'idle'; }