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 { cliUtils } from './cli-utils.js';
import { reducer, defaultState } from 'lib/reducer.js';
import { reg } from 'lib/registry.js';
import { _ } from 'lib/locale.js';
const chalk = require('chalk');
@ -56,15 +57,16 @@ class AppGui {
this.commandCancelCalled_ = false;
this.currentShortcutKeys_ = [];
this.lastShortcutKeyTime_ = 0;
this.lastShortcutKeyTime_ = 0;
cliUtils.setStdout((...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() {

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() {
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 newState = store.getState();
@ -429,6 +436,10 @@ class Application {
await this.refreshNotes();
}
if (this.gui() && action.type == 'SETTINGS_UPDATE_ONE' && action.key == 'sync.interval' || action.type == 'SETTINGS_UPDATE_ALL') {
reg.setupRecurrentSync();
}
return result;
}

View File

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

View File

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

View File

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

View File

@ -66,18 +66,27 @@ class OneDriveApiNodeUtils {
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');
this.api().execTokenRequest(query.code, 'http://localhost:' + port.toString()).then(() => {
writeResponse(200, _('The application has been authorised - you may now close this browser tab.'));
targetConsole.log('');
targetConsole.log(_('The application has been successfully authorised.'));
server.destroy();
waitAndDestroy();
}).catch((error) => {
writeResponse(400, error.message);
targetConsole.log('');
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 (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
} else if (error.code == 'ECONNRESET') {
// 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) {
// network timeout at: https://public-ch3302...859f9b0e3ab.md
} else {

View File

@ -9,7 +9,6 @@ import { FileApiDriverOneDrive } from 'lib/file-api-driver-onedrive.js';
import { shim } from 'lib/shim.js';
import { time } from 'lib/time-utils.js';
import { FileApiDriverMemory } from 'lib/file-api-driver-memory.js';
import { PoorManIntervals } from 'lib/poor-man-intervals.js';
import { _ } from 'lib/locale.js';
const reg = {};
@ -199,7 +198,7 @@ reg.syncStarted = async () => {
reg.setupRecurrentSync = () => {
if (reg.recurrentSyncId_) {
PoorManIntervals.clearInterval(reg.recurrentSyncId_);
shim.clearInterval(reg.recurrentSyncId_);
reg.recurrentSyncId_ = null;
}
@ -208,7 +207,7 @@ reg.setupRecurrentSync = () => {
} else {
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.scheduleSync(0);
}, 1000 * Setting.value('sync.interval'));

View File

@ -1,10 +1,14 @@
import { shim } from 'lib/shim.js';
import { GeolocationReact } from 'lib/geolocation-react.js';
import { PoorManIntervals } from 'lib/poor-man-intervals.js';
import RNFetchBlob from 'react-native-fetch-blob';
function shimInit() {
shim.Geolocation = GeolocationReact;
shim.setInterval = PoorManIntervals.setInterval;
shim.clearInterval = PoorManIntervals.clearInterval;
shim.fetchBlob = async function(url, options) {
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.readLocalFileBase64 = () => { throw new Error('Not implemented'); }
shim.uploadBlob = () => { throw new Error('Not implemented'); }
shim.setInterval = setInterval;
shim.clearInterval = clearInterval;
export { shim };