summary refs log tree commit diff
path: root/src/Utils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Utils.cpp')
-rw-r--r--src/Utils.cpp188
1 files changed, 188 insertions, 0 deletions
diff --git a/src/Utils.cpp b/src/Utils.cpp
new file mode 100644
index 00000000..2247c2b7
--- /dev/null
+++ b/src/Utils.cpp
@@ -0,0 +1,188 @@
+#include "Utils.h"
+
+#include <QApplication>
+#include <QDesktopWidget>
+
+#include <variant.hpp>
+
+using TimelineEvent = mtx::events::collections::TimelineEvents;
+
+QString
+utils::descriptiveTime(const QDateTime &then)
+{
+        const auto now  = QDateTime::currentDateTime();
+        const auto days = then.daysTo(now);
+
+        if (days == 0)
+                return then.toString("HH:mm");
+        else if (days < 2)
+                return QString("Yesterday");
+        else if (days < 365)
+                return then.toString("dd/MM");
+
+        return then.toString("dd/MM/yy");
+}
+
+DescInfo
+utils::getMessageDescription(const TimelineEvent &event,
+                             const QString &localUser,
+                             const QString &room_id)
+{
+        using Audio     = mtx::events::RoomEvent<mtx::events::msg::Audio>;
+        using Emote     = mtx::events::RoomEvent<mtx::events::msg::Emote>;
+        using File      = mtx::events::RoomEvent<mtx::events::msg::File>;
+        using Image     = mtx::events::RoomEvent<mtx::events::msg::Image>;
+        using Notice    = mtx::events::RoomEvent<mtx::events::msg::Notice>;
+        using Text      = mtx::events::RoomEvent<mtx::events::msg::Text>;
+        using Video     = mtx::events::RoomEvent<mtx::events::msg::Video>;
+        using Encrypted = mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>;
+
+        if (mpark::holds_alternative<Audio>(event)) {
+                return createDescriptionInfo<Audio>(event, localUser, room_id);
+        } else if (mpark::holds_alternative<Emote>(event)) {
+                return createDescriptionInfo<Emote>(event, localUser, room_id);
+        } else if (mpark::holds_alternative<File>(event)) {
+                return createDescriptionInfo<File>(event, localUser, room_id);
+        } else if (mpark::holds_alternative<Image>(event)) {
+                return createDescriptionInfo<Image>(event, localUser, room_id);
+        } else if (mpark::holds_alternative<Notice>(event)) {
+                return createDescriptionInfo<Notice>(event, localUser, room_id);
+        } else if (mpark::holds_alternative<Text>(event)) {
+                return createDescriptionInfo<Text>(event, localUser, room_id);
+        } else if (mpark::holds_alternative<Video>(event)) {
+                return createDescriptionInfo<Video>(event, localUser, room_id);
+        } else if (mpark::holds_alternative<mtx::events::Sticker>(event)) {
+                return createDescriptionInfo<mtx::events::Sticker>(event, localUser, room_id);
+        } else if (mpark::holds_alternative<Encrypted>(event)) {
+                const auto msg    = mpark::get<Encrypted>(event);
+                const auto sender = QString::fromStdString(msg.sender);
+
+                const auto username = Cache::displayName(room_id, sender);
+                const auto ts       = QDateTime::fromMSecsSinceEpoch(msg.origin_server_ts);
+
+                DescInfo info;
+                if (sender == localUser)
+                        info.username = "You";
+                else
+                        info.username = username;
+
+                info.userid    = sender;
+                info.body      = QString(" %1").arg(messageDescription<Encrypted>());
+                info.timestamp = utils::descriptiveTime(ts);
+                info.datetime  = ts;
+
+                return info;
+        } else {
+                std::cout << "type not found: " << serialize_event(event).dump(2) << '\n';
+        }
+
+        return DescInfo{};
+}
+
+QString
+utils::firstChar(const QString &input)
+{
+        if (input.isEmpty())
+                return input;
+
+        for (auto const &c : input.toUcs4()) {
+                if (QString::fromUcs4(&c, 1) != QString("#"))
+                        return QString::fromUcs4(&c, 1).toUpper();
+        }
+
+        return QString::fromUcs4(&input.toUcs4().at(0), 1).toUpper();
+}
+
+QString
+utils::humanReadableFileSize(uint64_t bytes)
+{
+        constexpr static const char *units[] = {"B", "KiB", "MiB", "GiB", "TiB"};
+        constexpr static const int length    = sizeof(units) / sizeof(units[0]);
+
+        int u       = 0;
+        double size = static_cast<double>(bytes);
+        while (size >= 1024.0 && u < length) {
+                ++u;
+                size /= 1024.0;
+        }
+
+        return QString::number(size, 'g', 4) + ' ' + units[u];
+}
+
+int
+utils::levenshtein_distance(const std::string &s1, const std::string &s2)
+{
+        const int nlen = s1.size();
+        const int hlen = s2.size();
+
+        if (hlen == 0)
+                return -1;
+        if (nlen == 1)
+                return s2.find(s1);
+
+        std::vector<int> row1(hlen + 1, 0);
+
+        for (int i = 0; i < nlen; ++i) {
+                std::vector<int> row2(1, i + 1);
+
+                for (int j = 0; j < hlen; ++j) {
+                        const int cost = s1[i] != s2[j];
+                        row2.push_back(
+                          std::min(row1[j + 1] + 1, std::min(row2[j] + 1, row1[j] + cost)));
+                }
+
+                row1.swap(row2);
+        }
+
+        return *std::min_element(row1.begin(), row1.end());
+}
+
+QString
+utils::event_body(const mtx::events::collections::TimelineEvents &event)
+{
+        using namespace mtx::events;
+        using namespace mtx::events::msg;
+
+        if (mpark::holds_alternative<RoomEvent<Audio>>(event)) {
+                return message_body<RoomEvent<Audio>>(event);
+        } else if (mpark::holds_alternative<RoomEvent<Emote>>(event)) {
+                return message_body<RoomEvent<Emote>>(event);
+        } else if (mpark::holds_alternative<RoomEvent<File>>(event)) {
+                return message_body<RoomEvent<File>>(event);
+        } else if (mpark::holds_alternative<RoomEvent<Image>>(event)) {
+                return message_body<RoomEvent<Image>>(event);
+        } else if (mpark::holds_alternative<RoomEvent<Notice>>(event)) {
+                return message_body<RoomEvent<Notice>>(event);
+        } else if (mpark::holds_alternative<Sticker>(event)) {
+                return message_body<Sticker>(event);
+        } else if (mpark::holds_alternative<RoomEvent<Text>>(event)) {
+                return message_body<RoomEvent<Text>>(event);
+        } else if (mpark::holds_alternative<RoomEvent<Video>>(event)) {
+                return message_body<RoomEvent<Video>>(event);
+        }
+
+        return QString();
+}
+
+QPixmap
+utils::scaleImageToPixmap(const QImage &img, int size)
+{
+        if (img.isNull())
+                return QPixmap();
+
+        const int sz = QApplication::desktop()->screen()->devicePixelRatio() * size;
+        return QPixmap::fromImage(
+          img.scaled(sz, sz, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
+}
+
+QString
+utils::mxcToHttp(const QUrl &url, const QString &server, int port)
+{
+        auto mxcParts = mtx::client::utils::parse_mxc_url(url.toString().toStdString());
+
+        return QString("https://%1:%2/_matrix/media/r0/download/%3/%4")
+          .arg(server)
+          .arg(port)
+          .arg(QString::fromStdString(mxcParts.server))
+          .arg(QString::fromStdString(mxcParts.media_id));
+}