From e9531f0e05844161356f2fbb105c061641481774 Mon Sep 17 00:00:00 2001
From: Akira Ohgaki <akiraohgaki@gmail.com>
Date: Sat, 25 Nov 2017 19:57:13 +0900
Subject: [PATCH] UpdateHandler

---
 app/src/handlers/updatehandler.cpp | 122 ++++++++++++++++++++++++++---
 app/src/handlers/updatehandler.h   |  12 +--
 2 files changed, 119 insertions(+), 15 deletions(-)

diff --git a/app/src/handlers/updatehandler.cpp b/app/src/handlers/updatehandler.cpp
index d81a055..d752bc8 100644
--- a/app/src/handlers/updatehandler.cpp
+++ b/app/src/handlers/updatehandler.cpp
@@ -1,5 +1,11 @@
 #include "updatehandler.h"
 
+#include <QStringList>
+#include <QJsonValue>
+#include <QJsonArray>
+#include <QJsonObject>
+#include <QDateTime>
+
 #ifdef QTLIB_UNIX
 #include <thread>
 #include <chrono>
@@ -7,18 +13,84 @@
 #include "appimage/update.h"
 #endif
 
+#include "qtlib_file.h"
+
 #include "handlers/confighandler.h"
 
 UpdateHandler::UpdateHandler(ConfigHandler *configHandler, QObject *parent)
     : QObject(parent), configHandler_(configHandler)
 {}
 
-QString UpdateHandler::checkAll() const
+void UpdateHandler::checkAll()
 {
+    emit checkAllStarted();
+
+    auto application = configHandler_->getUsrConfigApplication();
+    auto installedItems = configHandler_->getUsrConfigInstalledItems();
+
+    if (installedItems.isEmpty()
+            || (application.contains("update_checked_at")
+                && application["update_checked_at"].toInt() + (1000 * 60 * 60 * 24) > QDateTime::currentMSecsSinceEpoch())) {
+        emit checkAllFinished();
+        return;
+    }
+
+    // Clear data
+    QJsonObject updateAvailable;
+    configHandler_->setUsrConfigUpdateAvailable(updateAvailable);
+
+    for (const auto &itemKey : installedItems.keys()) {
+        auto installedItem = installedItems[itemKey].toObject();
+        auto installType = installedItem["install_type"].toString();
+
+        QString destDir = "";
+#ifdef QTLIB_UNIX
+        destDir = configHandler_->getAppConfigInstallTypes()[installType].toObject()["destination"].toString();
+#else
+        destDir = configHandler_->getAppConfigInstallTypes()[installType].toObject()["generic_destination"].toString();
+#endif
+
+        if (installType == "bin") {
+            for (const auto &filenameValue : installedItem["files"].toArray()) {
+                auto filename = filenameValue.toString();
+                QString path = destDir + "/" + filename;
+                // Use file path as unique key for entry in update_available data
+                auto fileKey = path;
+                QJsonObject updateAvailableFile;
+
+#ifdef QTLIB_UNIX
+                if (filename.endsWith(".appimage", Qt::CaseInsensitive)) {
+                    if (checkAppImage(path)) {
+                        updateAvailableFile["path"] = path;
+                        updateAvailableFile["filename"] = filename;
+                        updateAvailableFile["installed_item"] = itemKey;
+                        updateAvailableFile["update_method"] = QString("appimageupdate");
+                        configHandler_->setUsrConfigUpdateAvailableFile(fileKey, updateAvailableFile);
+                    }
+                    //else if (checkAppImageWithOcsApi(itemKey, filename)) {}
+                }
+#endif
+            }
+        }
+    }
+
+    application["update_checked_at"] = QDateTime::currentMSecsSinceEpoch();
+    configHandler_->setUsrConfigApplication(application);
+
+    emit checkAllFinished();
 }
 
-QString UpdateHandler::update(const QString &path) const
+void UpdateHandler::update(const QString &fileKey)
 {
+    if (configHandler_->getUsrConfigUpdateAvailable().contains(fileKey)) {
+        auto updateAvailableFile = configHandler_->getUsrConfigUpdateAvailable()[fileKey].toObject();
+
+#ifdef QTLIB_UNIX
+        if (updateAvailableFile["update_method"].toString() == "appimageupdate") {
+            updateAppImage(fileKey);
+        }
+#endif
+    }
 }
 
 #ifdef QTLIB_UNIX
@@ -43,24 +115,56 @@ bool UpdateHandler::checkAppImage(const QString &path) const
     return false;
 }
 
-bool UpdateHandler::updateAppImage(const QString &path)
+void UpdateHandler::updateAppImage(const QString &fileKey)
 {
+    auto updateAvailableFile = configHandler_->getUsrConfigUpdateAvailable()[fileKey].toObject();
+
+    auto path = updateAvailableFile["path"].toString();
+    auto filename = updateAvailableFile["filename"].toString();
+    auto itemKey = updateAvailableFile["installed_item"].toString();
+
+    auto newFilename = filename;
+    auto updateInformation = describeAppImage(path);
+    for (const auto &info : updateInformation.split("\n")) {
+        if (info.endsWith(".zsync", Qt::CaseInsensitive)) {
+            newFilename = info.replace(".zsync", "", Qt::CaseInsensitive).split("/").last();
+            break;
+        }
+    }
+
     appimage::update::Updater appImageUpdater(path.toStdString(), false);
     if (appImageUpdater.start()) {
-        emit updateStarted(path);
+        emit updateStarted(fileKey);
+
         while (!appImageUpdater.isDone()) {
             std::this_thread::sleep_for(std::chrono::milliseconds(100));
             double progress;
             if (appImageUpdater.progress(progress)) {
-                emit updateProgress(path, progress * 100);
+                emit updateProgress(fileKey, progress * 100);
             }
         }
-        auto newPath = path; // dummy
-        emit updateFinished(path, newPath);
+
         if (!appImageUpdater.hasError()) {
-            return true;
+            if (newFilename != filename) {
+                auto installedItem = configHandler_->getUsrConfigInstalledItems()[itemKey].toObject();
+                QJsonArray files;
+                for (const auto &file : installedItem["files"].toArray()) {
+                    if (file.toString() == filename) {
+                        files.append(QJsonValue(newFilename));
+                    }
+                    else {
+                        files.append(file);
+                    }
+                }
+                installedItem["files"] = files;
+                configHandler_->setUsrConfigInstalledItemsItem(itemKey, installedItem);
+                qtlib::File(path).remove();
+            }
+
+            configHandler_->removeUsrConfigUpdateAvailableFile(fileKey);
         }
+
+        emit updateFinished(fileKey);
     }
-    return false;
 }
 #endif
diff --git a/app/src/handlers/updatehandler.h b/app/src/handlers/updatehandler.h
index 8d047eb..49dcf29 100644
--- a/app/src/handlers/updatehandler.h
+++ b/app/src/handlers/updatehandler.h
@@ -14,19 +14,19 @@ public:
 signals:
     void checkAllStarted();
     void checkAllFinished();
-    void updateStarted(QString path);
-    void updateFinished(QString path, QString newPath);
-    void updateProgress(QString path, int progress);
+    void updateStarted(QString fileKey);
+    void updateFinished(QString fileKey);
+    void updateProgress(QString fileKey, int progress);
 
 public slots:
-    bool checkAll() const;
-    bool update(const QString &path) const;
+    void checkAll();
+    void update(const QString &fileKey);
 
 private:
 #ifdef QTLIB_UNIX
     QString describeAppImage(const QString &path) const;
     bool checkAppImage(const QString &path) const;
-    bool updateAppImage(const QString &path);
+    void updateAppImage(const QString &fileKey);
 #endif
 
     ConfigHandler *configHandler_;
-- 
GitLab