mirror of https://github.com/laurent22/joplin.git
synchronizer
parent
a3d2c9819e
commit
c030791f07
|
@ -33,6 +33,11 @@ class BaseModel {
|
|||
return null;
|
||||
}
|
||||
|
||||
static hasField(name) {
|
||||
let fields = this.fieldNames();
|
||||
return fields.indexOf(name) >= 0;
|
||||
}
|
||||
|
||||
static fieldNames() {
|
||||
return this.db().tableFieldNames(this.tableName());
|
||||
}
|
||||
|
@ -62,17 +67,35 @@ class BaseModel {
|
|||
return this.db().selectOne('SELECT * FROM ' + this.tableName() + ' WHERE id = ?', [id]);
|
||||
}
|
||||
|
||||
static applyPatch(model, patch) {
|
||||
model = Object.assign({}, model);
|
||||
for (let n in patch) {
|
||||
if (!patch.hasOwnProperty(n)) continue;
|
||||
model[n] = patch[n];
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
static saveQuery(o, isNew = 'auto') {
|
||||
if (isNew == 'auto') isNew = !o.id;
|
||||
let query = '';
|
||||
let itemId = o.id;
|
||||
|
||||
if (!o.updated_time && this.hasField('updated_time')) {
|
||||
o.updated_time = Math.round((new Date()).getTime() / 1000);
|
||||
}
|
||||
|
||||
if (isNew) {
|
||||
if (this.useUuid() && !o.id) {
|
||||
o = Object.assign({}, o);
|
||||
itemId = uuid.create();
|
||||
o.id = itemId;
|
||||
}
|
||||
|
||||
if (!o.created_time && this.hasField('created_time')) {
|
||||
o.created_time = Math.round((new Date()).getTime() / 1000);
|
||||
}
|
||||
|
||||
query = Database.insertQuery(this.tableName(), o);
|
||||
} else {
|
||||
let where = { id: o.id };
|
||||
|
|
|
@ -4,24 +4,29 @@ import { ListView, Text, TouchableHighlight } from 'react-native';
|
|||
import { Log } from 'src/log.js';
|
||||
import { ItemListComponent } from 'src/components/item-list.js';
|
||||
import { Note } from 'src/models/note.js';
|
||||
import { Folder } from 'src/models/folder.js';
|
||||
import { _ } from 'src/locale.js';
|
||||
|
||||
class FolderListComponent extends ItemListComponent {
|
||||
|
||||
listView_itemPress = (folderId) => {
|
||||
Note.previews(folderId).then((notes) => {
|
||||
this.props.dispatch({
|
||||
type: 'NOTES_UPDATE_ALL',
|
||||
notes: notes,
|
||||
});
|
||||
Folder.load(folderId).then((folder) => {
|
||||
Log.info('Current folder', folder);
|
||||
|
||||
this.props.dispatch({
|
||||
type: 'Navigation/NAVIGATE',
|
||||
routeName: 'Notes',
|
||||
folderId: folderId,
|
||||
Note.previews(folderId).then((notes) => {
|
||||
this.props.dispatch({
|
||||
type: 'NOTES_UPDATE_ALL',
|
||||
notes: notes,
|
||||
});
|
||||
|
||||
this.props.dispatch({
|
||||
type: 'Navigation/NAVIGATE',
|
||||
routeName: 'Notes',
|
||||
folderId: folderId,
|
||||
});
|
||||
}).catch((error) => {
|
||||
Log.warn('Cannot load notes', error);
|
||||
});
|
||||
}).catch((error) => {
|
||||
Log.warn('Cannot load notes', error);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@ class Database {
|
|||
}
|
||||
|
||||
open() {
|
||||
this.db_ = SQLite.openDatabase({ name: '/storage/emulated/0/Download/joplin-12.sqlite' }, (db) => {
|
||||
this.db_ = SQLite.openDatabase({ name: '/storage/emulated/0/Download/joplin-15.sqlite' }, (db) => {
|
||||
Log.info('Database was open successfully');
|
||||
}, (error) => {
|
||||
Log.error('Cannot open database: ', error);
|
||||
|
|
|
@ -42,12 +42,24 @@ class Synchronizer {
|
|||
let folder = Folder.fromApiResult(syncOp.item);
|
||||
// TODO: automatically handle NULL fields by checking type and default value of field
|
||||
if (!folder.parent_id) folder.parent_id = '';
|
||||
return Folder.save(folder, { isNew: true });
|
||||
return Folder.save(folder, { isNew: true, trackChanges: false });
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: update
|
||||
// TODO: delete
|
||||
if (syncOp.type == 'update') {
|
||||
chain.push(() => {
|
||||
return Folder.load(syncOp.item_id).then((folder) => {
|
||||
folder = Folder.applyPatch(folder, syncOp.item);
|
||||
return Folder.save(folder, { trackChanges: false });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (syncOp.type == 'delete') {
|
||||
chain.push(() => {
|
||||
return Folder.delete(syncOp.item_id, { trackChanges: false });
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return promiseChain(chain);
|
||||
|
@ -65,7 +77,6 @@ class Synchronizer {
|
|||
} else if (state == 'uploadingChanges') {
|
||||
Change.all().then((changes) => {
|
||||
let mergedChanges = Change.mergeChanges(changes);
|
||||
// Log.info(mergedChanges);
|
||||
let chain = [];
|
||||
let processedChangeIds = [];
|
||||
for (let i = 0; i < mergedChanges.length; i++) {
|
||||
|
@ -73,8 +84,6 @@ class Synchronizer {
|
|||
chain.push(() => {
|
||||
let p = null;
|
||||
|
||||
Log.info(this.api());
|
||||
|
||||
if (c.type == Change.TYPE_NOOP) {
|
||||
p = Promise.resolve();
|
||||
} else if (c.type == Change.TYPE_CREATE) {
|
||||
|
@ -86,9 +95,7 @@ class Synchronizer {
|
|||
return this.api().patch('folders/' + folder.id, null, folder);
|
||||
});
|
||||
} else if (c.type == Change.TYPE_DELETE) {
|
||||
p = Folder.load(c.item_id).then((folder) => {
|
||||
return this.api().delete('folders/' + folder.id);
|
||||
});
|
||||
return this.api().delete('folders/' + c.item_id);
|
||||
}
|
||||
|
||||
return p.then(() => {
|
||||
|
|
|
@ -67,10 +67,15 @@ function execRequest($method, $path, $query = array(), $data = null) {
|
|||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
if ($data) curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
||||
if ($method != 'GET' && $method != 'POST') {
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
|
||||
}
|
||||
if ($method == 'PUT' || $method == 'PATCH') {
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
|
||||
}
|
||||
if ($data) {
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $method == 'POST' ? $data : http_build_query($data));
|
||||
}
|
||||
$response = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
|
|
|
@ -147,6 +147,8 @@ class BaseModel extends \Illuminate\Database\Eloquent\Model {
|
|||
foreach ($array as $k => $v) {
|
||||
if ($k == 'rev_id') {
|
||||
$this->revId = $v;
|
||||
} else if (in_array($k, array('parent_id', 'client_id', 'item_id', 'user_id', 'owner_id'))) {
|
||||
$this->{$k} = self::unhex($v);
|
||||
} else if (in_array($k, $this->diffableFields)) {
|
||||
$this->changedDiffableFields[$k] = $v;
|
||||
} else {
|
||||
|
@ -160,7 +162,7 @@ class BaseModel extends \Illuminate\Database\Eloquent\Model {
|
|||
if ($this->useUuid) {
|
||||
$output['id'] = self::hex($output['id']);
|
||||
}
|
||||
|
||||
|
||||
if (!empty($output['parent_id'])) $output['parent_id'] = self::hex($output['parent_id']);
|
||||
if (!empty($output['owner_id'])) $output['owner_id'] = self::hex($output['owner_id']);
|
||||
if (!empty($output['client_id'])) $output['client_id'] = self::hex($output['client_id']);
|
||||
|
@ -246,7 +248,7 @@ class BaseModel extends \Illuminate\Database\Eloquent\Model {
|
|||
|
||||
static public function unhex($s) {
|
||||
if (!strlen($s)) return null;
|
||||
|
||||
|
||||
if (is_array($s)) {
|
||||
foreach ($s as $k => $v) {
|
||||
$s[$k] = self::unhex($v);
|
||||
|
@ -373,9 +375,9 @@ class BaseModel extends \Illuminate\Database\Eloquent\Model {
|
|||
unset($changedFields['updated_time']);
|
||||
}
|
||||
|
||||
$output = parent::save($options);
|
||||
//if ($this->parent_id
|
||||
|
||||
//$this->cacheClear();
|
||||
$output = parent::save($options);
|
||||
|
||||
$this->isNew = null;
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@ class Change extends BaseModel {
|
|||
->limit($limit + 1)
|
||||
->get();
|
||||
|
||||
$changes = $changes->all();
|
||||
|
||||
$hasMore = $limit < count($changes);
|
||||
if ($hasMore) array_pop($changes);
|
||||
|
||||
|
|
|
@ -37,5 +37,7 @@ try {
|
|||
header('HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
|
||||
die(json_encode($response) . "\n");
|
||||
$r = json_encode($response);
|
||||
if ($r === false) $r = serialize($response);
|
||||
die($r . "\n");
|
||||
}
|
Loading…
Reference in New Issue