1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-24 10:27:10 +02:00

Many improvements and bug fixes

This commit is contained in:
Laurent Cozic 2017-10-18 23:13:53 +01:00
parent 4db08d1a26
commit 1845a0105c
11 changed files with 69 additions and 16 deletions

View File

@ -3,6 +3,7 @@ import { Folder } from 'lib/models/folder.js';
import { Note } from 'lib/models/note.js'; import { Note } from 'lib/models/note.js';
import { cliUtils } from './cli-utils.js'; import { cliUtils } from './cli-utils.js';
import { reducer, defaultState } from 'lib/reducer.js'; import { reducer, defaultState } from 'lib/reducer.js';
import { reg } from 'lib/registry.js';
import { _ } from 'lib/locale.js'; import { _ } from 'lib/locale.js';
const chalk = require('chalk'); const chalk = require('chalk');
@ -56,15 +57,16 @@ class AppGui {
this.commandCancelCalled_ = false; this.commandCancelCalled_ = false;
this.currentShortcutKeys_ = []; this.currentShortcutKeys_ = [];
this.lastShortcutKeyTime_ = 0; this.lastShortcutKeyTime_ = 0;
cliUtils.setStdout((...object) => { cliUtils.setStdout((...object) => {
return this.stdout(...object); return this.stdout(...object);
// for (let i = 0; i < object.length; i++) {
// this.widget('console').bufferPush(object[i]);
// }
}); });
// Recurrent sync is setup only when the GUI is started. In
// a regular command it's not necessary since the process
// exits right away.
reg.setupRecurrentSync();
} }
renderer() { renderer() {

View File

@ -417,9 +417,16 @@ class Application {
}); });
} }
reducerActionToString(action) {
let o = [action.type];
if (action.noteId) o.push(action.noteId);
if (action.folderI) o.push(action.folderI);
return o.join(', ');
}
generalMiddleware() { generalMiddleware() {
const middleware = store => next => async (action) => { const middleware = store => next => async (action) => {
this.logger().info('Reducer action', action.type); this.logger().info('Reducer action', this.reducerActionToString(action));
const result = next(action); const result = next(action);
const newState = store.getState(); const newState = store.getState();
@ -429,6 +436,10 @@ class Application {
await this.refreshNotes(); await this.refreshNotes();
} }
if (this.gui() && action.type == 'SETTINGS_UPDATE_ONE' && action.key == 'sync.interval' || action.type == 'SETTINGS_UPDATE_ALL') {
reg.setupRecurrentSync();
}
return result; return result;
} }

View File

@ -86,6 +86,8 @@ class Command extends BaseCommand {
if (args.options.target) this.syncTarget_ = args.options.target; if (args.options.target) this.syncTarget_ = args.options.target;
if (this.syncTarget_ == Setting.SYNC_TARGET_ONEDRIVE && !reg.syncHasAuth(this.syncTarget_)) { if (this.syncTarget_ == Setting.SYNC_TARGET_ONEDRIVE && !reg.syncHasAuth(this.syncTarget_)) {
app().gui().showConsole();
app().gui().maximizeConsole();
const oneDriveApiUtils = new OneDriveApiNodeUtils(reg.oneDriveApi()); const oneDriveApiUtils = new OneDriveApiNodeUtils(reg.oneDriveApi());
const auth = await oneDriveApiUtils.oauthDance({ const auth = await oneDriveApiUtils.oauthDance({
log: (...s) => { return this.stdout(...s); } log: (...s) => { return this.stdout(...s); }

View File

@ -10,7 +10,7 @@ class NoteListWidget extends ListWidget {
this.updateIndexFromSelectedNoteId_ = false; this.updateIndexFromSelectedNoteId_ = false;
this.itemRenderer = (note) => { this.itemRenderer = (note) => {
let label = note.title; //+ ' ' + note.id; let label = note.title; // + ' ' + note.id;
if (note.is_todo) { if (note.is_todo) {
label = '[' + (note.todo_completed ? 'X' : ' ') + '] ' + label; label = '[' + (note.todo_completed ? 'X' : ' ') + '] ' + label;
} }

View File

@ -55,8 +55,22 @@ class StatusBarWidget extends BaseWidget {
return this.history_; return this.history_;
} }
resetCursor() {
if (!this.promptActive) return;
if (!this.inputEventEmitter_) return;
this.inputEventEmitter_.redraw();
this.inputEventEmitter_.rebase(this.absoluteInnerX + termutils.textLength(this.promptState_.promptString), this.absoluteInnerY);
this.term.moveTo(this.absoluteInnerX + termutils.textLength(this.promptState_.promptString) + this.inputEventEmitter_.getInput().length, this.absoluteInnerY);
}
render() { render() {
super.render(); super.render();
const doSaveCursor = !this.promptActive;
if (doSaveCursor) this.term.saveCursor();
this.innerClear(); this.innerClear();
const textStyle = chalk.bgBlueBright.white; const textStyle = chalk.bgBlueBright.white;
@ -70,8 +84,9 @@ class StatusBarWidget extends BaseWidget {
this.term.write(textStyle(this.promptState_.promptString)); this.term.write(textStyle(this.promptState_.promptString));
if (this.inputEventEmitter_) { if (this.inputEventEmitter_) {
this.inputEventEmitter_.redraw(); // inputField is already waiting for input so in that case just make
this.inputEventEmitter_.rebase(this.absoluteInnerX + termutils.textLength(this.promptState_.promptString), this.absoluteInnerY); // sure that the cursor is at the right position and exit.
this.resetCursor();
return; return;
} }
@ -122,6 +137,8 @@ class StatusBarWidget extends BaseWidget {
} }
} }
if (doSaveCursor) this.term.restoreCursor();
} }
} }

View File

@ -66,18 +66,27 @@ class OneDriveApiNodeUtils {
response.end(); response.end();
} }
// After the response has been received, don't destroy the server right
// away or the browser might display a connection reset error (even
// though it worked).
const waitAndDestroy = () => {
setTimeout(() => {
server.destroy();
}, 1000);
}
if (!query.code) return writeResponse(400, '"code" query parameter is missing'); if (!query.code) return writeResponse(400, '"code" query parameter is missing');
this.api().execTokenRequest(query.code, 'http://localhost:' + port.toString()).then(() => { this.api().execTokenRequest(query.code, 'http://localhost:' + port.toString()).then(() => {
writeResponse(200, _('The application has been authorised - you may now close this browser tab.')); writeResponse(200, _('The application has been authorised - you may now close this browser tab.'));
targetConsole.log(''); targetConsole.log('');
targetConsole.log(_('The application has been successfully authorised.')); targetConsole.log(_('The application has been successfully authorised.'));
server.destroy(); waitAndDestroy();
}).catch((error) => { }).catch((error) => {
writeResponse(400, error.message); writeResponse(400, error.message);
targetConsole.log(''); targetConsole.log('');
targetConsole.log(error.message); targetConsole.log(error.message);
server.destroy(); waitAndDestroy();
}); });
}); });

View File

@ -98,10 +98,12 @@ class Note extends BaseItem {
if (a[order.by] < b[order.by]) r = +1; if (a[order.by] < b[order.by]) r = +1;
if (a[order.by] > b[order.by]) r = -1; if (a[order.by] > b[order.by]) r = -1;
if (order.dir == 'ASC') r = -r; if (order.dir == 'ASC') r = -r;
if (r) break; if (r !== 0) break;
} }
return r; // Makes the sort deterministic, so that if, for example, a and b have the
// same updated_time, they aren't swapped every time a list is refreshed.
return a.title.toLowerCase() + a.id < b.title.toLowerCase() + b.id ? -1 : +1;
}); });
} }

View File

@ -180,6 +180,11 @@ class OneDriveApi {
// or error code, so hopefully that message won't change and is not localized // or error code, so hopefully that message won't change and is not localized
} else if (error.code == 'ECONNRESET') { } else if (error.code == 'ECONNRESET') {
// request to https://public-ch3302....1fab24cb1bd5f.md failed, reason: socket hang up" // request to https://public-ch3302....1fab24cb1bd5f.md failed, reason: socket hang up"
} else if (error.code == 'ENOTFOUND') {
// OneDrive (or Node?) sometimes sends back a "not found" error for resources
// that definitely exist and in this case repeating the request works.
// Error is:
// request to https://graph.microsoft.com/v1.0/drive/special/approot failed, reason: getaddrinfo ENOTFOUND graph.microsoft.com graph.microsoft.com:443
} else if (error.message.indexOf('network timeout') === 0) { } else if (error.message.indexOf('network timeout') === 0) {
// network timeout at: https://public-ch3302...859f9b0e3ab.md // network timeout at: https://public-ch3302...859f9b0e3ab.md
} else { } else {

View File

@ -9,7 +9,6 @@ import { FileApiDriverOneDrive } from 'lib/file-api-driver-onedrive.js';
import { shim } from 'lib/shim.js'; import { shim } from 'lib/shim.js';
import { time } from 'lib/time-utils.js'; import { time } from 'lib/time-utils.js';
import { FileApiDriverMemory } from 'lib/file-api-driver-memory.js'; import { FileApiDriverMemory } from 'lib/file-api-driver-memory.js';
import { PoorManIntervals } from 'lib/poor-man-intervals.js';
import { _ } from 'lib/locale.js'; import { _ } from 'lib/locale.js';
const reg = {}; const reg = {};
@ -199,7 +198,7 @@ reg.syncStarted = async () => {
reg.setupRecurrentSync = () => { reg.setupRecurrentSync = () => {
if (reg.recurrentSyncId_) { if (reg.recurrentSyncId_) {
PoorManIntervals.clearInterval(reg.recurrentSyncId_); shim.clearInterval(reg.recurrentSyncId_);
reg.recurrentSyncId_ = null; reg.recurrentSyncId_ = null;
} }
@ -208,7 +207,7 @@ reg.setupRecurrentSync = () => {
} else { } else {
reg.logger().debug('Setting up recurrent sync with interval ' + Setting.value('sync.interval')); reg.logger().debug('Setting up recurrent sync with interval ' + Setting.value('sync.interval'));
reg.recurrentSyncId_ = PoorManIntervals.setInterval(() => { reg.recurrentSyncId_ = shim.setInterval(() => {
reg.logger().info('Running background sync on timer...'); reg.logger().info('Running background sync on timer...');
reg.scheduleSync(0); reg.scheduleSync(0);
}, 1000 * Setting.value('sync.interval')); }, 1000 * Setting.value('sync.interval'));

View File

@ -1,10 +1,14 @@
import { shim } from 'lib/shim.js'; import { shim } from 'lib/shim.js';
import { GeolocationReact } from 'lib/geolocation-react.js'; import { GeolocationReact } from 'lib/geolocation-react.js';
import { PoorManIntervals } from 'lib/poor-man-intervals.js';
import RNFetchBlob from 'react-native-fetch-blob'; import RNFetchBlob from 'react-native-fetch-blob';
function shimInit() { function shimInit() {
shim.Geolocation = GeolocationReact; shim.Geolocation = GeolocationReact;
shim.setInterval = PoorManIntervals.setInterval;
shim.clearInterval = PoorManIntervals.clearInterval;
shim.fetchBlob = async function(url, options) { shim.fetchBlob = async function(url, options) {
if (!options || !options.path) throw new Error('fetchBlob: target file path is missing'); if (!options || !options.path) throw new Error('fetchBlob: target file path is missing');

View File

@ -15,5 +15,7 @@ shim.fs = null;
shim.FileApiDriverLocal = null; shim.FileApiDriverLocal = null;
shim.readLocalFileBase64 = () => { throw new Error('Not implemented'); } shim.readLocalFileBase64 = () => { throw new Error('Not implemented'); }
shim.uploadBlob = () => { throw new Error('Not implemented'); } shim.uploadBlob = () => { throw new Error('Not implemented'); }
shim.setInterval = setInterval;
shim.clearInterval = clearInterval;
export { shim }; export { shim };