From c84fc204199fd776befef56969bb8744218883d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Tue, 25 Aug 2020 19:00:21 +0200 Subject: [PATCH 1/7] Reset last time opened when setting a comic as unread --- YACReaderLibrary/db/comic_model.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/YACReaderLibrary/db/comic_model.cpp b/YACReaderLibrary/db/comic_model.cpp index 982f051a..a50cc7b1 100644 --- a/YACReaderLibrary/db/comic_model.cpp +++ b/YACReaderLibrary/db/comic_model.cpp @@ -798,6 +798,7 @@ QVector ComicModel::setComicsRead(QList l c.info.read = false; c.info.currentPage = 1; c.info.hasBeenOpened = false; + c.info.lastTimeOpened.setValue(nullptr); DBHelper::update(&(c.info), db); } } From fe15bc2ba8b3c114ed74975d610968d7e340a8bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Tue, 25 Aug 2020 19:01:03 +0200 Subject: [PATCH 2/7] Include "last_time_opened" in JSON serialization --- YACReaderLibrary/server/yacreader_server_data_helper.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/YACReaderLibrary/server/yacreader_server_data_helper.cpp b/YACReaderLibrary/server/yacreader_server_data_helper.cpp index ab16a427..722df335 100644 --- a/YACReaderLibrary/server/yacreader_server_data_helper.cpp +++ b/YACReaderLibrary/server/yacreader_server_data_helper.cpp @@ -53,6 +53,7 @@ QJsonObject YACReaderServerDataHelper::comicToJSON(const qulonglong libraryId, c json["cover_size_ratio"] = comic.info.coverSizeRatio.toFloat(); json["title"] = comic.info.title.toString(); json["number"] = comic.info.number.toInt(); + json["last_time_opened"] = comic.info.lastTimeOpened.toLongLong(); return json; } @@ -103,4 +104,4 @@ QJsonObject YACReaderServerDataHelper::labelToJSON(const qulonglong libraryId, c return json; } -YACReaderServerDataHelper::YACReaderServerDataHelper() { } +YACReaderServerDataHelper::YACReaderServerDataHelper() {} From 2b780e23a4ba49d260a0b989f3368eacedd643b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Tue, 25 Aug 2020 19:01:43 +0200 Subject: [PATCH 3/7] Make `updateFromRemoteClient` return more updated comics So they can be sent back to the client. --- YACReaderLibrary/db_helper.cpp | 48 ++++++++++++++++++++++++++-------- YACReaderLibrary/db_helper.h | 2 +- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/YACReaderLibrary/db_helper.cpp b/YACReaderLibrary/db_helper.cpp index a81bd916..47fdc68c 100644 --- a/YACReaderLibrary/db_helper.cpp +++ b/YACReaderLibrary/db_helper.cpp @@ -827,10 +827,15 @@ void DBHelper::updateFromRemoteClientWithHash(const ComicInfo &comicInfo) } } -void DBHelper::updateFromRemoteClient(const QMap> &comics) +QMap> DBHelper::updateFromRemoteClient(const QMap> &comics) { + QMap> moreRecentComics; + foreach (qulonglong libraryId, comics.keys()) { + QList libraryMoreRecentComics; + QString libraryPath = DBHelper::getLibraries().getPath(libraryId); + QString connectionName = ""; { QSqlDatabase db = DataBaseManagement::loadDatabase(libraryPath + "/.yacreaderlibrary"); @@ -850,37 +855,58 @@ void DBHelper::updateFromRemoteClient(const QMap> & ComicDB comic = DBHelper::loadComic(comicInfo.id, db); if (comic.info.hash == comicInfo.hash) { - if (comicInfo.currentPage > 0) { - comic.info.currentPage = comicInfo.currentPage; + bool isMoreRecent = false; - if (comic.info.currentPage == comic.info.numPages) - comic.info.read = true; - - comic.info.hasBeenOpened = true; - - if (comic.info.lastTimeOpened.toULongLong() < comicInfo.lastTimeOpened.toULongLong()) - comic.info.lastTimeOpened = comicInfo.lastTimeOpened; + //completion takes precedence over lastTimeOpened, if we just want to synchronize the lastest status we should use only lastTimeOpened + if ((comic.info.currentPage > 1 && comic.info.currentPage > comicInfo.currentPage) || comic.info.hasBeenOpened || (comic.info.read && !comicInfo.read)) { + isMoreRecent = true; } + if (comic.info.lastTimeOpened.toULongLong() > 0 && comicInfo.lastTimeOpened.toULongLong() == 0) { + isMoreRecent = true; + } + + comic.info.currentPage = qMax(comic.info.currentPage, comicInfo.currentPage); + + if (comic.info.currentPage == comic.info.numPages) + comic.info.read = true; + + comic.info.read = comic.info.read || comicInfo.read; + + comic.info.hasBeenOpened = comic.info.hasBeenOpened || comicInfo.currentPage > 0; + + if (comic.info.lastTimeOpened.toULongLong() < comicInfo.lastTimeOpened.toULongLong() && comicInfo.lastTimeOpened.toULongLong() > 0) + comic.info.lastTimeOpened = comicInfo.lastTimeOpened; + if (comicInfo.rating > 0) comic.info.rating = comicInfo.rating; updateComicInfo.bindValue(":read", comic.info.read ? 1 : 0); updateComicInfo.bindValue(":currentPage", comic.info.currentPage); updateComicInfo.bindValue(":hasBeenOpened", comic.info.hasBeenOpened ? 1 : 0); - updateComicInfo.bindValue(":lastTimeOpened", QDateTime::currentMSecsSinceEpoch() / 1000); + updateComicInfo.bindValue(":lastTimeOpened", comic.info.lastTimeOpened); updateComicInfo.bindValue(":id", comic.info.id); updateComicInfo.bindValue(":rating", comic.info.rating); updateComicInfo.exec(); + + if (isMoreRecent) { + libraryMoreRecentComics.append(comic); + } } } + if (!libraryMoreRecentComics.isEmpty()) { + moreRecentComics[libraryId] = libraryMoreRecentComics; + } + db.commit(); connectionName = db.connectionName(); } QSqlDatabase::removeDatabase(connectionName); } + + return moreRecentComics; } void DBHelper::updateFromRemoteClientWithHash(const QList &comics) diff --git a/YACReaderLibrary/db_helper.h b/YACReaderLibrary/db_helper.h index fb61b854..3b11f41f 100644 --- a/YACReaderLibrary/db_helper.h +++ b/YACReaderLibrary/db_helper.h @@ -72,7 +72,7 @@ public: static void updateFromRemoteClient(qulonglong libraryId, const ComicInfo &comicInfo); static void updateFromRemoteClientWithHash(const ComicInfo &comicInfo); static void updateReadingRemoteProgress(const ComicInfo &comicInfo, QSqlDatabase &db); - static void updateFromRemoteClient(const QMap> &comics); + static QMap> updateFromRemoteClient(const QMap> &comics); static void updateFromRemoteClientWithHash(const QList &comics); static void renameLabel(qulonglong id, const QString &name, QSqlDatabase &db); static void renameList(qulonglong id, const QString &name, QSqlDatabase &db); From 5bc3ad5014558cb3871a6c361980ba8c780ac997 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Tue, 25 Aug 2020 19:03:00 +0200 Subject: [PATCH 4/7] Send back more recent comic status to the client on sync --- .../controllers/v2/synccontroller_v2.cpp | 31 ++++++++++++++++--- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/YACReaderLibrary/server/controllers/v2/synccontroller_v2.cpp b/YACReaderLibrary/server/controllers/v2/synccontroller_v2.cpp index 8883a8ce..8adef636 100644 --- a/YACReaderLibrary/server/controllers/v2/synccontroller_v2.cpp +++ b/YACReaderLibrary/server/controllers/v2/synccontroller_v2.cpp @@ -5,6 +5,7 @@ #include "comic_db.h" #include "db_helper.h" +#include "yacreader_server_data_helper.h" using stefanfrings::HttpRequest; using stefanfrings::HttpResponse; @@ -15,13 +16,13 @@ SyncControllerV2::SyncControllerV2() void SyncControllerV2::service(HttpRequest &request, HttpResponse &response) { + response.setHeader("Content-Type", "text/plain; charset=utf-8"); + QString postData = QString::fromUtf8(request.getBody()); QLOG_TRACE() << "POST DATA: " << postData; if (postData.length() > 0) { - response.write("OK", true); - QList data = postData.split("\n"); qulonglong libraryId; @@ -35,7 +36,7 @@ void SyncControllerV2::service(HttpRequest &request, HttpResponse &response) foreach (QString comicInfo, data) { QList comicInfoProgress = comicInfo.split("\t"); - if (comicInfoProgress.length() == 6) { + if (comicInfoProgress.length() >= 6) { if (comicInfoProgress.at(0) != "unknown") { libraryId = comicInfoProgress.at(0).toULongLong(); comicId = comicInfoProgress.at(1).toULongLong(); @@ -52,6 +53,11 @@ void SyncControllerV2::service(HttpRequest &request, HttpResponse &response) lastTimeOpened = comicInfoProgress.at(5).toULong(); info.lastTimeOpened = lastTimeOpened; + + if (comicInfoProgress.length() >= 7) { + info.read = comicInfoProgress.at(6).toInt(); + } + if (!comics.contains(libraryId)) { comics[libraryId] = QList(); } @@ -75,11 +81,26 @@ void SyncControllerV2::service(HttpRequest &request, HttpResponse &response) } } - DBHelper::updateFromRemoteClient(comics); + auto moreRecentComicsFound = DBHelper::updateFromRemoteClient(comics); + + QJsonArray items; + + foreach (qulonglong libraryId, moreRecentComicsFound.keys()) { + foreach (ComicDB comic, moreRecentComicsFound[libraryId]) { + items.append(YACReaderServerDataHelper::comicToJSON(libraryId, comic)); + } + } + + QJsonDocument output(items); + + response.write(output.toJson(QJsonDocument::Compact), true); + + //TODO does it make sense to send these back? The source is not YACReaderLibrary... DBHelper::updateFromRemoteClientWithHash(comicsWithNoLibrary); + } else { response.setStatus(412, "No comic info received"); - response.write("", true); + response.write("[]", true); return; } } From 8a99e35cf6dc9bbe2c79825550c44178c28f177e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Tue, 25 Aug 2020 19:04:43 +0200 Subject: [PATCH 5/7] Update CHANGELOG --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d6311664..56e34450 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,12 @@ spanish only. Sorry for the mess. Version counting is based on semantic versioning (Major.Feature.Patch) -## 9.6.7 (unreleased) +## 9.7.0 (unreleased) ### YACReaderLibrary * update QsLog logger to version 2.1, snapshot 46b643d5bcbc * fix object leaks in database code +* add bidirectional sync support ## 9.6.0 ### Reader and Library From f11a7571413e67e51b2f5858b8bfc6f2f7703a6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Tue, 25 Aug 2020 19:13:43 +0200 Subject: [PATCH 6/7] Code format I had to update clang-format --- YACReaderLibrary/server/yacreader_server_data_helper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/YACReaderLibrary/server/yacreader_server_data_helper.cpp b/YACReaderLibrary/server/yacreader_server_data_helper.cpp index 722df335..5af2389d 100644 --- a/YACReaderLibrary/server/yacreader_server_data_helper.cpp +++ b/YACReaderLibrary/server/yacreader_server_data_helper.cpp @@ -104,4 +104,4 @@ QJsonObject YACReaderServerDataHelper::labelToJSON(const qulonglong libraryId, c return json; } -YACReaderServerDataHelper::YACReaderServerDataHelper() {} +YACReaderServerDataHelper::YACReaderServerDataHelper() { } From b64ea19e8b680462303fdea22641afb71f3c3be5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Tue, 25 Aug 2020 19:45:05 +0200 Subject: [PATCH 7/7] Use an invalid QVariant to set to NULL a value in the DB nullptr causes troubles in some platforms/compiles --- YACReaderLibrary/db/comic_model.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/YACReaderLibrary/db/comic_model.cpp b/YACReaderLibrary/db/comic_model.cpp index a50cc7b1..7fee8000 100644 --- a/YACReaderLibrary/db/comic_model.cpp +++ b/YACReaderLibrary/db/comic_model.cpp @@ -798,7 +798,7 @@ QVector ComicModel::setComicsRead(QList l c.info.read = false; c.info.currentPage = 1; c.info.hasBeenOpened = false; - c.info.lastTimeOpened.setValue(nullptr); + c.info.lastTimeOpened.setValue(QVariant()); DBHelper::update(&(c.info), db); } }