From 6e8af5e3b386e8a098c16e9ce17f7433f2b87509 Mon Sep 17 00:00:00 2001
From: Mm2PL <miau@mail.kotmisia.pl>
Date: Sat, 2 Dec 2023 00:43:04 +0100
Subject: [PATCH] Move ImageUploader into a directory, refactor out
 UploadedImage

and all its template implementations
---
 src/Application.cpp                           |  2 +-
 src/CMakeLists.txt                            |  5 +-
 .../{ => imageuploader}/ImageUploader.cpp     | 32 +++++-
 .../{ => imageuploader}/ImageUploader.hpp     |  0
 .../imageuploader/UploadedImage.hpp           | 98 +++++++++++++++++++
 src/widgets/splits/Split.cpp                  |  2 +-
 6 files changed, 130 insertions(+), 9 deletions(-)
 rename src/singletons/{ => imageuploader}/ImageUploader.cpp (93%)
 rename src/singletons/{ => imageuploader}/ImageUploader.hpp (100%)
 create mode 100644 src/singletons/imageuploader/UploadedImage.hpp

diff --git a/src/Application.cpp b/src/Application.cpp
index 0a2f8b4de..a4e7f5d2e 100644
--- a/src/Application.cpp
+++ b/src/Application.cpp
@@ -12,7 +12,7 @@
 #include "controllers/notifications/NotificationController.hpp"
 #include "controllers/sound/ISoundController.hpp"
 #include "providers/seventv/SeventvAPI.hpp"
-#include "singletons/ImageUploader.hpp"
+#include "singletons/imageuploader/ImageUploader.hpp"
 #ifdef CHATTERINO_HAVE_PLUGINS
 #    include "controllers/plugins/PluginController.hpp"
 #endif
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 86c24c15b..5d453f707 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -429,8 +429,9 @@ set(SOURCE_FILES
         singletons/Emotes.hpp
         singletons/Fonts.cpp
         singletons/Fonts.hpp
-        singletons/ImageUploader.cpp
-        singletons/ImageUploader.hpp
+        singletons/imageuploader/ImageUploader.cpp
+        singletons/imageuploader/ImageUploader.hpp
+        singletons/imageuploader/UploadedImage.hpp
         singletons/Logging.cpp
         singletons/Logging.hpp
         singletons/NativeMessaging.cpp
diff --git a/src/singletons/ImageUploader.cpp b/src/singletons/imageuploader/ImageUploader.cpp
similarity index 93%
rename from src/singletons/ImageUploader.cpp
rename to src/singletons/imageuploader/ImageUploader.cpp
index 6fd5fbaab..58955264e 100644
--- a/src/singletons/ImageUploader.cpp
+++ b/src/singletons/imageuploader/ImageUploader.cpp
@@ -1,4 +1,4 @@
-#include "singletons/ImageUploader.hpp"
+#include "singletons/imageuploader/ImageUploader.hpp"
 
 #include "common/Env.hpp"
 #include "common/NetworkRequest.hpp"
@@ -6,6 +6,7 @@
 #include "common/QLogging.hpp"
 #include "messages/MessageBuilder.hpp"
 #include "providers/twitch/TwitchMessageBuilder.hpp"
+#include "singletons/imageuploader/UploadedImageModel.hpp"
 #include "singletons/Paths.hpp"
 #include "singletons/Settings.hpp"
 #include "util/CombinePath.hpp"
@@ -16,9 +17,10 @@
 #include <QHttpMultiPart>
 #include <QJsonArray>
 #include <QJsonDocument>
-#include <qloggingcategory.h>
+#include <QLoggingCategory>
 #include <QMimeDatabase>
 #include <QMutex>
+#include <QObject>
 #include <QPointer>
 #include <QSaveFile>
 #include <rapidjson/document.h>
@@ -53,7 +55,7 @@ void ImageUploader::logToFile(const QString &originalFilePath,
                               const QString &imageLink,
                               const QString &deletionLink, ChannelPtr channel)
 {
-    this->imageLogSetting_->push_back(UploadedImage{
+    this->images_.append(UploadedImage{
         .channelName = channel->getName(),
         .deletionLink = deletionLink,
         .imageLink = imageLink,
@@ -91,9 +93,17 @@ QString getLinkFromResponse(NetworkResult response, QString pattern)
 
 void ImageUploader::save()
 {
+    this->uploadedImagesSetting_->setValue(this->images_.raw());
     this->sm_->save();
 }
 
+UploadedImageModel *ImageUploader::createModel(QObject *parent)
+{
+    auto *model = new UploadedImageModel(parent);
+    model->initialize(&this->images_);
+    return model;
+}
+
 void ImageUploader::initialize(Settings &settings, Paths &paths)
 {
     auto logPath = (getSettings()->logPath.getValue().isEmpty()
@@ -108,10 +118,19 @@ void ImageUploader::initialize(Settings &settings, Paths &paths)
     this->sm_->setBackupEnabled(true);
     this->sm_->setBackupSlots(9);
 
-    this->imageLogSetting_ = std::make_unique<
+    this->uploadedImagesSetting_ = std::make_unique<
         pajlada::Settings::Setting<std::vector<UploadedImage>>>(
         "/uploadedImages", this->sm_);
 
+    for (const auto &item : this->uploadedImagesSetting_->getValue())
+    {
+        this->images_.append(item);
+    }
+    this->signals_.addConnection(
+        this->images_.delayedItemsChanged.connect([this]() {
+            this->uploadedImagesSetting_->setValue(this->images_.raw());
+        }));
+
     // try to read old log
     QFile oldLogFile(oldLogName);
     bool isOldLogFileOkay =
@@ -139,7 +158,10 @@ void ImageUploader::initialize(Settings &settings, Paths &paths)
                 << "Unable to parse ImageUploader.json: getSafe failed";
             return;
         }
-        this->imageLogSetting_->setValue(temporary);
+        for (const auto &t : temporary)
+        {
+            this->images_.append(t);
+        }
         oldLogFile.close();
         oldLogFile.rename(combinePath(logPath, "ImageUploader.old.json"));
         this->sm_->save();
diff --git a/src/singletons/ImageUploader.hpp b/src/singletons/imageuploader/ImageUploader.hpp
similarity index 100%
rename from src/singletons/ImageUploader.hpp
rename to src/singletons/imageuploader/ImageUploader.hpp
diff --git a/src/singletons/imageuploader/UploadedImage.hpp b/src/singletons/imageuploader/UploadedImage.hpp
new file mode 100644
index 000000000..fe951c296
--- /dev/null
+++ b/src/singletons/imageuploader/UploadedImage.hpp
@@ -0,0 +1,98 @@
+#pragma once
+#include "util/RapidjsonHelpers.hpp"
+
+#include <QString>
+#include <Qt>
+
+#include <cstdint>
+
+namespace chatterino {
+struct UploadedImage {
+    QString channelName;
+    QString deletionLink;
+    QString imageLink;
+    QString localPath;
+    int64_t timestamp{};
+    bool deleted = false;
+};
+}  // namespace chatterino
+
+namespace pajlada {
+template <>
+struct Serialize<chatterino::UploadedImage> {
+    static rapidjson::Value get(const chatterino::UploadedImage &value,
+                                rapidjson::Document::AllocatorType &a)
+    {
+        rapidjson::Value ret(rapidjson::kObjectType);
+
+        chatterino::rj::set(ret, "channelName", value.channelName, a);
+        chatterino::rj::set(ret, "imageLink", value.imageLink, a);
+        chatterino::rj::set(ret, "timestamp", value.timestamp, a);
+        chatterino::rj::set(ret, "localPath", value.localPath, a);
+        chatterino::rj::set(ret, "deletionLink", value.deletionLink, a);
+        if (value.deleted)
+        {
+            chatterino::rj::set(ret, "deleted", value.deleted, a);
+        }
+
+        return ret;
+    }
+};
+
+template <>
+struct Deserialize<chatterino::UploadedImage> {
+    static chatterino::UploadedImage get(const rapidjson::Value &value,
+                                         bool *error = nullptr)
+    {
+        chatterino::UploadedImage img;
+
+        if (!value.IsObject())
+        {
+            PAJLADA_REPORT_ERROR(error);
+            return img;
+        }
+
+        if (value["localPath"].IsNull())
+        {
+            img.localPath = QString();
+        }
+        else if (!chatterino::rj::getSafe(value, "localPath", img.localPath))
+        {
+            PAJLADA_REPORT_ERROR(error);
+            return img;
+        }
+        if (!chatterino::rj::getSafe(value, "imageLink", img.imageLink))
+        {
+            PAJLADA_REPORT_ERROR(error);
+            return img;
+        }
+        if (value["deletionLink"].IsNull())
+        {
+            img.deletionLink = QString();
+        }
+        else if (!chatterino::rj::getSafe(value, "deletionLink",
+                                          img.deletionLink))
+        {
+            PAJLADA_REPORT_ERROR(error);
+            return img;
+        }
+        if (!chatterino::rj::getSafe(value, "channelName", img.channelName))
+        {
+            PAJLADA_REPORT_ERROR(error);
+            return img;
+        }
+        if (!chatterino::rj::getSafe(value, "timestamp", img.timestamp))
+        {
+            PAJLADA_REPORT_ERROR(error);
+            return img;
+        }
+        if (!chatterino::rj::getSafe(value, "deleted", img.deleted))
+        {
+            img.deleted = false;
+            return img;
+        }
+
+        return img;
+    }
+};
+}  // namespace pajlada
diff --git a/src/widgets/splits/Split.cpp b/src/widgets/splits/Split.cpp
index 7d1a2b91e..dd702f9d9 100644
--- a/src/widgets/splits/Split.cpp
+++ b/src/widgets/splits/Split.cpp
@@ -16,7 +16,7 @@
 #include "providers/twitch/TwitchIrcServer.hpp"
 #include "providers/twitch/TwitchMessageBuilder.hpp"
 #include "singletons/Fonts.hpp"
-#include "singletons/ImageUploader.hpp"
+#include "singletons/imageuploader/ImageUploader.hpp"
 #include "singletons/Settings.hpp"
 #include "singletons/Theme.hpp"
 #include "singletons/WindowManager.hpp"