diff --git a/app/app.pri b/app/app.pri
index 53ee440b9fd207041cdf79a18653e5b87957931a..8c1d5890f1ff52a53e3519ebf7115171a9f2e1fc 100644
--- a/app/app.pri
+++ b/app/app.pri
@@ -33,6 +33,7 @@ unix:!ios:!android {
     QT += dbus
 
     HEADERS += \
+        $${PWD}/src/updaters/appimageupdater.h \
         $${PWD}/src/desktopthemes/kdetheme.h \
         $${PWD}/src/desktopthemes/gnometheme.h \
         $${PWD}/src/desktopthemes/xfcetheme.h \
@@ -40,6 +41,7 @@ unix:!ios:!android {
         $${PWD}/src/desktopthemes/matetheme.h
 
     SOURCES += \
+        $${PWD}/src/updaters/appimageupdater.cpp \
         $${PWD}/src/desktopthemes/kdetheme.cpp \
         $${PWD}/src/desktopthemes/gnometheme.cpp \
         $${PWD}/src/desktopthemes/xfcetheme.cpp \
diff --git a/app/src/updaters/appimageupdater.cpp b/app/src/updaters/appimageupdater.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c246fb52e2e9194e82aadb741c9c5fc75382de03
--- /dev/null
+++ b/app/src/updaters/appimageupdater.cpp
@@ -0,0 +1,80 @@
+#include "appimageupdater.h"
+
+#include <QThread>
+
+#include "appimage/update.h"
+
+AppImageUpdater::AppImageUpdater(const QString &id, const QString &path, QObject *parent)
+    : QObject(parent), id_(id), path_(path)
+{
+    isFinishedWithNoError_ = false;
+    errorString_ = "";
+}
+
+QString AppImageUpdater::id() const
+{
+    return id_;
+}
+
+QString AppImageUpdater::path() const
+{
+    return path_;
+}
+
+QString AppImageUpdater::describeAppImage() const
+{
+    std::string description = "";
+    appimage::update::Updater updater(path_.toStdString());
+    updater.describeAppImage(description);
+    return QString::fromStdString(description);
+}
+
+bool AppImageUpdater::checkAppImage() const
+{
+    bool updateAvailable = false;
+    appimage::update::Updater updater(path_.toStdString());
+    updater.checkForChanges(updateAvailable);
+    return updateAvailable;
+}
+
+void AppImageUpdater::updateAppImage()
+{
+    isFinishedWithNoError_ = false;
+    errorString_ = "";
+    appimage::update::Updater updater(path_.toStdString(), false);
+
+    if (!updater.start()) {
+        emit finished(this);
+        return;
+    }
+
+    while (!updater.isDone()) {
+        QThread::msleep(100);
+        double progress;
+        if (updater.progress(progress)) {
+            emit updateProgress(id_, progress);
+        }
+    }
+
+    if (updater.hasError()) {
+        std::string message;
+        while (updater.nextStatusMessage(message)) {
+            errorString_ += QString::fromStdString(message) + "\n";
+        }
+        emit finished(this);
+        return;
+    }
+
+    isFinishedWithNoError_ = true;
+    emit finished(this);
+}
+
+bool AppImageUpdater::isFinishedWithNoError() const
+{
+    return isFinishedWithNoError_;
+}
+
+QString AppImageUpdater::errorString() const
+{
+    return errorString_;
+}
diff --git a/app/src/updaters/appimageupdater.h b/app/src/updaters/appimageupdater.h
new file mode 100644
index 0000000000000000000000000000000000000000..d83ab71c591f82f69b7232db526a995632083fb7
--- /dev/null
+++ b/app/src/updaters/appimageupdater.h
@@ -0,0 +1,30 @@
+#pragma once
+
+#include <QObject>
+
+class AppImageUpdater : public QObject
+{
+    Q_OBJECT
+
+public:
+    explicit AppImageUpdater(const QString &id, const QString &path, QObject *parent = nullptr);
+
+    QString id() const;
+    QString path() const;
+
+    QString describeAppImage() const;
+    bool checkAppImage() const;
+    void updateAppImage();
+    bool isFinishedWithNoError() const;
+    QString errorString() const;
+
+signals:
+    void finished(AppImageUpdater *updater);
+    void updateProgress(QString id, double progress);
+
+private:
+    QString id_;
+    QString path_;
+    bool isFinishedWithNoError_;
+    QString errorString_;
+};