synchronizer

pull/41/head
Laurent Cozic 2017-05-19 19:32:49 +00:00
parent a3d2c9819e
commit c030791f07
8 changed files with 73 additions and 27 deletions

View File

@ -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 };

View File

@ -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);
});
}

View File

@ -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);

View File

@ -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(() => {

View File

@ -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);

View File

@ -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;

View File

@ -26,6 +26,8 @@ class Change extends BaseModel {
->limit($limit + 1)
->get();
$changes = $changes->all();
$hasMore = $limit < count($changes);
if ($hasMore) array_pop($changes);

View File

@ -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");
}