diff --git a/ReactNativeClient/src/base-model.js b/ReactNativeClient/src/base-model.js index c535e8421e..e38903813d 100644 --- a/ReactNativeClient/src/base-model.js +++ b/ReactNativeClient/src/base-model.js @@ -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 }; diff --git a/ReactNativeClient/src/components/folder-list.js b/ReactNativeClient/src/components/folder-list.js index 63856acedb..09322afb22 100644 --- a/ReactNativeClient/src/components/folder-list.js +++ b/ReactNativeClient/src/components/folder-list.js @@ -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); }); } diff --git a/ReactNativeClient/src/database.js b/ReactNativeClient/src/database.js index 5b874d9299..6888009002 100644 --- a/ReactNativeClient/src/database.js +++ b/ReactNativeClient/src/database.js @@ -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); diff --git a/ReactNativeClient/src/synchronizer.js b/ReactNativeClient/src/synchronizer.js index f6323b5a59..d232d89369 100644 --- a/ReactNativeClient/src/synchronizer.js +++ b/ReactNativeClient/src/synchronizer.js @@ -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(() => { diff --git a/debug_client/index.php b/debug_client/index.php index dfdf7bdac0..3c4dc8cde7 100755 --- a/debug_client/index.php +++ b/debug_client/index.php @@ -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); diff --git a/src/AppBundle/Model/BaseModel.php b/src/AppBundle/Model/BaseModel.php index b900625e02..4942d2612b 100755 --- a/src/AppBundle/Model/BaseModel.php +++ b/src/AppBundle/Model/BaseModel.php @@ -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; diff --git a/src/AppBundle/Model/Change.php b/src/AppBundle/Model/Change.php index 2b9fc2e5c2..7dd3ad8ac4 100755 --- a/src/AppBundle/Model/Change.php +++ b/src/AppBundle/Model/Change.php @@ -26,6 +26,8 @@ class Change extends BaseModel { ->limit($limit + 1) ->get(); + $changes = $changes->all(); + $hasMore = $limit < count($changes); if ($hasMore) array_pop($changes); diff --git a/web/app.php b/web/app.php index e70cb69ec0..a8170033d7 100755 --- a/web/app.php +++ b/web/app.php @@ -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"); } \ No newline at end of file