mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
Clean up
This commit is contained in:
parent
fdeb797750
commit
f3d8c34499
@ -29,6 +29,7 @@ import { reg } from 'lib/registry.js';
|
||||
import { FsDriverNode } from './fs-driver-node.js';
|
||||
import { filename, basename } from 'lib/path-utils.js';
|
||||
import { shim } from 'lib/shim.js';
|
||||
import { shimInit } from 'lib/shim-init-node.js';
|
||||
import { _ } from 'lib/locale.js';
|
||||
import os from 'os';
|
||||
import fs from 'fs-extra';
|
||||
@ -104,7 +105,8 @@ commands.push({
|
||||
};
|
||||
|
||||
try {
|
||||
await Note.save(note);
|
||||
note = await Note.save(note);
|
||||
Note.updateGeolocation(note.id);
|
||||
} catch (error) {
|
||||
this.log(error);
|
||||
}
|
||||
@ -512,42 +514,54 @@ commands.push({
|
||||
description: 'Synchronizes with remote storage.',
|
||||
options: [
|
||||
['--random-failures', 'For debugging purposes. Do not use.'],
|
||||
['--stats', 'Displays stats about synchronization.'],
|
||||
],
|
||||
action: async function(args, end) {
|
||||
|
||||
let options = {
|
||||
onProgress: (report) => {
|
||||
let line = [];
|
||||
if (report.remotesToUpdate) line.push(_('Items to upload: %d/%d.', report.createRemote + report.updateRemote, report.remotesToUpdate));
|
||||
if (report.remotesToDelete) line.push(_('Remote items to delete: %d/%d.', report.deleteRemote, report.remotesToDelete));
|
||||
if (report.localsToUdpate) line.push(_('Items to download: %d/%d.', report.createLocal + report.updateLocal, report.localsToUdpate));
|
||||
if (report.localsToDelete) line.push(_('Local items to delete: %d/%d.', report.deleteLocal, report.localsToDelete));
|
||||
if (line.length) vorpalUtils.redraw(line.join(' '));
|
||||
},
|
||||
onMessage: (msg) => {
|
||||
vorpalUtils.redrawDone();
|
||||
this.log(msg);
|
||||
},
|
||||
randomFailures: args.options['random-failures'] === true,
|
||||
};
|
||||
if (args.options.stats) {
|
||||
const report = await BaseItem.stats();
|
||||
for (let n in report.items) {
|
||||
if (!report.items.hasOwnProperty(n)) continue;
|
||||
const r = report.items[n];
|
||||
this.log(_('%s: %d/%d', n, r.synced, r.total))
|
||||
}
|
||||
this.log(_('Total: %d/%d', report.total.synced, report.total.total));
|
||||
} else {
|
||||
let options = {
|
||||
onProgress: (report) => {
|
||||
let line = [];
|
||||
if (report.remotesToUpdate) line.push(_('Items to upload: %d/%d.', report.createRemote + report.updateRemote, report.remotesToUpdate));
|
||||
if (report.remotesToDelete) line.push(_('Remote items to delete: %d/%d.', report.deleteRemote, report.remotesToDelete));
|
||||
if (report.localsToUdpate) line.push(_('Items to download: %d/%d.', report.createLocal + report.updateLocal, report.localsToUdpate));
|
||||
if (report.localsToDelete) line.push(_('Local items to delete: %d/%d.', report.deleteLocal, report.localsToDelete));
|
||||
if (line.length) vorpalUtils.redraw(line.join(' '));
|
||||
},
|
||||
onMessage: (msg) => {
|
||||
vorpalUtils.redrawDone();
|
||||
this.log(msg);
|
||||
},
|
||||
randomFailures: args.options['random-failures'] === true,
|
||||
};
|
||||
|
||||
this.log(_('Synchronization target: %s', Setting.value('sync.target')));
|
||||
this.log(_('Synchronization target: %s', Setting.value('sync.target')));
|
||||
|
||||
let sync = await synchronizer(Setting.value('sync.target'));
|
||||
if (!sync) {
|
||||
end();
|
||||
return;
|
||||
let sync = await synchronizer(Setting.value('sync.target'));
|
||||
if (!sync) {
|
||||
end();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.log(_('Starting synchronization...'));
|
||||
await sync.start(options);
|
||||
} catch (error) {
|
||||
this.log(error);
|
||||
}
|
||||
|
||||
vorpalUtils.redrawDone();
|
||||
this.log(_('Done.'));
|
||||
}
|
||||
|
||||
try {
|
||||
this.log(_('Starting synchronization...'));
|
||||
await sync.start(options);
|
||||
} catch (error) {
|
||||
this.log(error);
|
||||
}
|
||||
|
||||
vorpalUtils.redrawDone();
|
||||
this.log(_('Done.'));
|
||||
end();
|
||||
},
|
||||
cancel: async function() {
|
||||
@ -904,64 +918,7 @@ vorpalUtils.initialize(vorpal);
|
||||
|
||||
async function main() {
|
||||
|
||||
shim.fetchBlob = async function(url, options) {
|
||||
if (!options || !options.path) throw new Error('fetchBlob: target file path is missing');
|
||||
if (!options.method) options.method = 'GET';
|
||||
|
||||
const urlParse = require('url').parse;
|
||||
|
||||
url = urlParse(url.trim());
|
||||
const http = url.protocol.toLowerCase() == 'http:' ? require('follow-redirects').http : require('follow-redirects').https;
|
||||
const headers = options.headers ? options.headers : {};
|
||||
const method = options.method ? options.method : 'GET';
|
||||
if (method != 'GET') throw new Error('Only GET is supported');
|
||||
const filePath = options.path;
|
||||
|
||||
function makeResponse(response) {
|
||||
return {
|
||||
ok: response.statusCode < 400,
|
||||
path: filePath,
|
||||
text: () => { return response.statusMessage; },
|
||||
json: () => { return { message: response.statusCode + ': ' + response.statusMessage }; },
|
||||
status: response.statusCode,
|
||||
headers: response.headers,
|
||||
};
|
||||
}
|
||||
|
||||
const requestOptions = {
|
||||
protocol: url.protocol,
|
||||
host: url.host,
|
||||
port: url.port,
|
||||
method: method,
|
||||
path: url.path + (url.query ? '?' + url.query : ''),
|
||||
headers: headers,
|
||||
};
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
// Note: relative paths aren't supported
|
||||
const file = fs.createWriteStream(filePath);
|
||||
|
||||
const request = http.get(requestOptions, function(response) {
|
||||
response.pipe(file);
|
||||
|
||||
file.on('finish', function() {
|
||||
file.close(() => {
|
||||
resolve(makeResponse(response));
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
request.on('error', function(error) {
|
||||
fs.unlink(filePath);
|
||||
reject(error);
|
||||
});
|
||||
} catch(error) {
|
||||
fs.unlink(filePath);
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
shimInit();
|
||||
|
||||
for (let commandIndex = 0; commandIndex < commands.length; commandIndex++) {
|
||||
let c = commands[commandIndex];
|
||||
@ -1046,9 +1003,6 @@ async function main() {
|
||||
|
||||
// If we still have arguments, pass it to Vorpal and exit
|
||||
if (argv.length) {
|
||||
//vorpal.delimiter(' AAAAAAAAAAAAAAAAAAAAA');
|
||||
//console.info(vorpal.ui.inquirer);
|
||||
//vorpal.show();
|
||||
let cmd = shellArgsToString(argv);
|
||||
await vorpal.exec(cmd);
|
||||
await vorpal.exec('exit');
|
||||
|
@ -7,7 +7,7 @@
|
||||
"url": "https://github.com/laurent22/joplin"
|
||||
},
|
||||
"url": "git://github.com/laurent22/joplin.git",
|
||||
"version": "0.8.30",
|
||||
"version": "0.8.31",
|
||||
"bin": {
|
||||
"joplin": "./main_launcher.js"
|
||||
},
|
||||
|
28
ReactNativeClient/lib/geolocation-node.js
Normal file
28
ReactNativeClient/lib/geolocation-node.js
Normal file
@ -0,0 +1,28 @@
|
||||
import { shim } from 'lib/shim.js'
|
||||
import { netUtils } from 'lib/net-utils.js';
|
||||
|
||||
class GeolocationNode {
|
||||
|
||||
static async currentPosition(options = null) {
|
||||
if (!options) options = {};
|
||||
|
||||
const ip = await netUtils.ip();
|
||||
|
||||
let response = await shim.fetch('https://freegeoip.net/json/' + ip);
|
||||
if (!response.ok) throw new Error('Could not get geolocation: ' + await response.text());
|
||||
|
||||
response = await response.json();
|
||||
|
||||
return {
|
||||
timestamp: (new Date()).getTime(),
|
||||
coords: {
|
||||
longitude: response.longitude,
|
||||
altitude: 0,
|
||||
latitude: response.latitude
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { GeolocationNode };
|
@ -29,13 +29,40 @@ class BaseItem extends BaseModel {
|
||||
}
|
||||
|
||||
throw new Error('Invalid class name: ' + name);
|
||||
}
|
||||
|
||||
// if (!this.classes_) this.classes_ = {};
|
||||
// if (this.classes_[name]) return this.classes_[name];
|
||||
// let filename = name.toLowerCase();
|
||||
// if (name == 'NoteTag') filename = 'note-tag';
|
||||
// this.classes_[name] = require('lib/models/' + filename + '.js')[name];
|
||||
// return this.classes_[name];
|
||||
static async stats() {
|
||||
let output = {
|
||||
items: {},
|
||||
total: {},
|
||||
};
|
||||
|
||||
let itemCount = 0;
|
||||
let syncedCount = 0;
|
||||
for (let i = 0; i < BaseItem.syncItemDefinitions_.length; i++) {
|
||||
let d = BaseItem.syncItemDefinitions_[i];
|
||||
let ItemClass = this.getClass(d.className);
|
||||
let o = {
|
||||
total: await ItemClass.count(),
|
||||
synced: await ItemClass.syncedCount(),
|
||||
};
|
||||
output.items[d.className] = o;
|
||||
itemCount += o.total;
|
||||
syncedCount += o.synced;
|
||||
}
|
||||
|
||||
output.total = {
|
||||
total: itemCount,
|
||||
synced: syncedCount,
|
||||
};
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
static async syncedCount() {
|
||||
const ItemClass = this.itemClass(this.modelType());
|
||||
const r = await this.db().selectOne('SELECT count(*) as total FROM `' + ItemClass.tableName() + '` WHERE updated_time > sync_time');
|
||||
return r.total;
|
||||
}
|
||||
|
||||
static systemPath(itemOrId) {
|
||||
@ -248,12 +275,6 @@ class BaseItem extends BaseModel {
|
||||
|
||||
}
|
||||
|
||||
// import { Note } from 'lib/models/note.js';
|
||||
// import { Folder } from 'lib/models/folder.js';
|
||||
// import { Resource } from 'lib/models/resource.js';
|
||||
// import { Tag } from 'lib/models/tag.js';
|
||||
// import { NoteTag } from 'lib/models/note-tag.js';
|
||||
|
||||
// Also update:
|
||||
// - itemsThatNeedSync()
|
||||
// - syncedItems()
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { BaseModel } from 'lib/base-model.js';
|
||||
import { Log } from 'lib/log.js';
|
||||
import { Folder } from 'lib/models/folder.js';
|
||||
import { GeolocationReact } from 'lib/geolocation-react.js';
|
||||
import { BaseItem } from 'lib/models/base-item.js';
|
||||
import { Setting } from 'lib/models/setting.js';
|
||||
import { shim } from 'lib/shim.js';
|
||||
import moment from 'moment';
|
||||
import lodash from 'lodash';
|
||||
|
||||
@ -96,11 +96,11 @@ class Note extends BaseItem {
|
||||
}
|
||||
|
||||
static updateGeolocation(noteId) {
|
||||
Log.info('Updating lat/long of note ' + noteId);
|
||||
this.logger().info('Updating lat/long of note ' + noteId);
|
||||
|
||||
let geoData = null;
|
||||
return GeolocationReact.currentPosition().then((data) => {
|
||||
Log.info('Got lat/long');
|
||||
return shim.Geolocation.currentPosition().then((data) => {
|
||||
this.logger().info('Got lat/long');
|
||||
geoData = data;
|
||||
return Note.load(noteId);
|
||||
}).then((note) => {
|
||||
@ -110,7 +110,7 @@ class Note extends BaseItem {
|
||||
note.altitude = geoData.coords.altitude;
|
||||
return Note.save(note);
|
||||
}).catch((error) => {
|
||||
Log.info('Cannot get location:', error);
|
||||
this.logger().warn('Cannot get location:', error);
|
||||
});
|
||||
}
|
||||
|
||||
|
15
ReactNativeClient/lib/net-utils.js
Normal file
15
ReactNativeClient/lib/net-utils.js
Normal file
@ -0,0 +1,15 @@
|
||||
import { shim } from 'lib/shim.js'
|
||||
|
||||
const netUtils = {};
|
||||
|
||||
netUtils.ip = async () => {
|
||||
let response = await shim.fetch('https://api.ipify.org/?format=json');
|
||||
if (!response.ok) {
|
||||
throw new Error('Could not retrieve IP: ' + await response.text());
|
||||
}
|
||||
|
||||
let ip = await response.json();
|
||||
return ip.ip;
|
||||
}
|
||||
|
||||
export { netUtils };
|
67
ReactNativeClient/lib/shim-init-node.js
Normal file
67
ReactNativeClient/lib/shim-init-node.js
Normal file
@ -0,0 +1,67 @@
|
||||
import { shim } from 'lib/shim.js';
|
||||
import { GeolocationNode } from 'lib/geolocation-node.js';
|
||||
|
||||
function shimInit() {
|
||||
shim.Geolocation = GeolocationNode;
|
||||
|
||||
shim.fetchBlob = async function(url, options) {
|
||||
if (!options || !options.path) throw new Error('fetchBlob: target file path is missing');
|
||||
if (!options.method) options.method = 'GET';
|
||||
|
||||
const urlParse = require('url').parse;
|
||||
|
||||
url = urlParse(url.trim());
|
||||
const http = url.protocol.toLowerCase() == 'http:' ? require('follow-redirects').http : require('follow-redirects').https;
|
||||
const headers = options.headers ? options.headers : {};
|
||||
const method = options.method ? options.method : 'GET';
|
||||
if (method != 'GET') throw new Error('Only GET is supported');
|
||||
const filePath = options.path;
|
||||
|
||||
function makeResponse(response) {
|
||||
return {
|
||||
ok: response.statusCode < 400,
|
||||
path: filePath,
|
||||
text: () => { return response.statusMessage; },
|
||||
json: () => { return { message: response.statusCode + ': ' + response.statusMessage }; },
|
||||
status: response.statusCode,
|
||||
headers: response.headers,
|
||||
};
|
||||
}
|
||||
|
||||
const requestOptions = {
|
||||
protocol: url.protocol,
|
||||
host: url.host,
|
||||
port: url.port,
|
||||
method: method,
|
||||
path: url.path + (url.query ? '?' + url.query : ''),
|
||||
headers: headers,
|
||||
};
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
// Note: relative paths aren't supported
|
||||
const file = fs.createWriteStream(filePath);
|
||||
|
||||
const request = http.get(requestOptions, function(response) {
|
||||
response.pipe(file);
|
||||
|
||||
file.on('finish', function() {
|
||||
file.close(() => {
|
||||
resolve(makeResponse(response));
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
request.on('error', function(error) {
|
||||
fs.unlink(filePath);
|
||||
reject(error);
|
||||
});
|
||||
} catch(error) {
|
||||
fs.unlink(filePath);
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export { shimInit }
|
42
ReactNativeClient/lib/shim-init-react.js
Normal file
42
ReactNativeClient/lib/shim-init-react.js
Normal file
@ -0,0 +1,42 @@
|
||||
import { shim } from 'lib/shim.js';
|
||||
import { GeolocationReact } from 'lib/geolocation-react.js';
|
||||
|
||||
function shimInit() {
|
||||
shim.Geolocation = GeolocationReact;
|
||||
|
||||
shim.fetchBlob = async function(url, options) {
|
||||
if (!options || !options.path) throw new Error('fetchBlob: target file path is missing');
|
||||
if (!options.method) options.method = 'GET';
|
||||
|
||||
let headers = options.headers ? options.headers : {};
|
||||
let method = options.method ? options.method : 'GET';
|
||||
|
||||
let dirs = RNFetchBlob.fs.dirs;
|
||||
let localFilePath = options.path;
|
||||
if (localFilePath.indexOf('/') !== 0) localFilePath = dirs.DocumentDir + '/' + localFilePath;
|
||||
|
||||
delete options.path;
|
||||
|
||||
try {
|
||||
let response = await RNFetchBlob.config({
|
||||
path: localFilePath
|
||||
}).fetch(method, url, headers);
|
||||
|
||||
// Returns an object that's roughtly compatible with a standard Response object
|
||||
let output = {
|
||||
ok: response.respInfo.status < 400,
|
||||
path: response.data,
|
||||
text: response.text,
|
||||
json: response.json,
|
||||
status: response.respInfo.status,
|
||||
headers: response.respInfo.headers,
|
||||
};
|
||||
|
||||
return output;
|
||||
} catch (error) {
|
||||
throw new Error('fetchBlob: ' + method + ' ' + url + ': ' + error.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { shimInit }
|
@ -1,5 +1,14 @@
|
||||
let shim = {};
|
||||
|
||||
shim.isNode = () => {
|
||||
if (typeof process === 'undefined') return false;
|
||||
return process.title = 'node';
|
||||
};
|
||||
|
||||
shim.isReactNative = () => {
|
||||
return !shim.isNode();
|
||||
};
|
||||
|
||||
shim.fetch = typeof fetch !== 'undefined' ? fetch : null;
|
||||
shim.FormData = typeof FormData !== 'undefined' ? FormData : null;
|
||||
|
||||
|
@ -6,7 +6,7 @@ import { createStore } from 'redux';
|
||||
import { combineReducers } from 'redux';
|
||||
import { StackNavigator } from 'react-navigation';
|
||||
import { addNavigationHelpers } from 'react-navigation';
|
||||
import { shim } from 'lib/shim.js';
|
||||
import { shimInit } from 'lib/shim-init-react.js';
|
||||
import { Log } from 'lib/log.js'
|
||||
import { Logger } from 'lib/logger.js'
|
||||
import { Note } from 'lib/models/note.js'
|
||||
@ -225,42 +225,10 @@ let initializationState_ = 'waiting';
|
||||
async function initialize(dispatch) {
|
||||
if (initializationState_ != 'waiting') return;
|
||||
|
||||
shimInit();
|
||||
|
||||
initializationState_ = 'in_progress';
|
||||
|
||||
shim.fetchBlob = async function(url, options) {
|
||||
if (!options || !options.path) throw new Error('fetchBlob: target file path is missing');
|
||||
if (!options.method) options.method = 'GET';
|
||||
|
||||
let headers = options.headers ? options.headers : {};
|
||||
let method = options.method ? options.method : 'GET';
|
||||
|
||||
let dirs = RNFetchBlob.fs.dirs;
|
||||
let localFilePath = options.path;
|
||||
if (localFilePath.indexOf('/') !== 0) localFilePath = dirs.DocumentDir + '/' + localFilePath;
|
||||
|
||||
delete options.path;
|
||||
|
||||
try {
|
||||
let response = await RNFetchBlob.config({
|
||||
path: localFilePath
|
||||
}).fetch(method, url, headers);
|
||||
|
||||
// Returns an object that's roughtly compatible with a standard Response object
|
||||
let output = {
|
||||
ok: response.respInfo.status < 400,
|
||||
path: response.data,
|
||||
text: response.text,
|
||||
json: response.json,
|
||||
status: response.respInfo.status,
|
||||
headers: response.respInfo.headers,
|
||||
};
|
||||
|
||||
return output;
|
||||
} catch (error) {
|
||||
throw new Error('fetchBlob: ' + method + ' ' + url + ': ' + error.toString());
|
||||
}
|
||||
}
|
||||
|
||||
Setting.setConstant('env', __DEV__ ? 'dev' : 'prod');
|
||||
Setting.setConstant('appId', 'net.cozic.joplin');
|
||||
Setting.setConstant('appType', 'mobile');
|
||||
|
Loading…
Reference in New Issue
Block a user