// SPDX-FileCopyrightText: 2021 Nheko Contributors // // SPDX-License-Identifier: GPL-3.0-or-later #include "Utils.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "Cache.h" #include "Config.h" #include "MatrixClient.h" #include "UserSettingsPage.h" using TimelineEvent = mtx::events::collections::TimelineEvents; QHash authorColors_; template static DescInfo createDescriptionInfo(const Event &event, const QString &localUser, const QString &displayName) { const auto msg = std::get(event); const auto sender = QString::fromStdString(msg.sender); const auto username = displayName; const auto ts = QDateTime::fromMSecsSinceEpoch(msg.origin_server_ts); return DescInfo{QString::fromStdString(msg.event_id), sender, utils::messageDescription( username, utils::event_body(event).trimmed(), sender == localUser), utils::descriptiveTime(ts), msg.origin_server_ts, ts}; } QString utils::localUser() { return QString::fromStdString(http::client()->user_id().to_string()); } bool utils::codepointIsEmoji(uint code) { // TODO: Be more precise here. return (code >= 0x2600 && code <= 0x27bf) || (code >= 0x2b00 && code <= 0x2bff) || (code >= 0x1f000 && code <= 0x1faff) || code == 0x200d || code == 0xfe0f; } QString utils::replaceEmoji(const QString &body) { QString fmtBody; fmtBody.reserve(body.size()); QVector utf32_string = body.toUcs4(); bool insideFontBlock = false; for (auto &code : utf32_string) { if (utils::codepointIsEmoji(code)) { if (!insideFontBlock) { fmtBody += QStringLiteral("emojiFont() % QStringLiteral("\">"); insideFontBlock = true; } } else { if (insideFontBlock) { fmtBody += QStringLiteral(""); insideFontBlock = false; } } if (QChar::requiresSurrogates(code)) { QChar emoji[] = {static_cast(QChar::highSurrogate(code)), static_cast(QChar::lowSurrogate(code))}; fmtBody.append(emoji, 2); } else { fmtBody.append(QChar(static_cast(code))); } } if (insideFontBlock) { fmtBody += QStringLiteral(""); } return fmtBody; } void utils::setScaleFactor(float factor) { if (factor < 1 || factor > 3) return; QSettings settings; settings.setValue("settings/scale_factor", factor); } float utils::scaleFactor() { QSettings settings; return settings.value("settings/scale_factor", -1).toFloat(); } bool utils::respondsToKeyRequests(const std::string &roomId) { return respondsToKeyRequests(QString::fromStdString(roomId)); } bool utils::respondsToKeyRequests(const QString &roomId) { if (roomId.isEmpty()) return false; QSettings settings; return settings.value("rooms/respond_to_key_requests/" + roomId, false).toBool(); } void utils::setKeyRequestsPreference(QString roomId, bool value) { if (roomId.isEmpty()) return; QSettings settings; settings.setValue("rooms/respond_to_key_requests/" + roomId, value); } QString utils::descriptiveTime(const QDateTime &then) { const auto now = QDateTime::currentDateTime(); const auto days = then.daysTo(now); if (days == 0) return QLocale::system().toString(then.time(), QLocale::ShortFormat); else if (days < 2) return QString(QCoreApplication::translate("descriptiveTime", "Yesterday")); else if (days < 7) return then.toString("dddd"); return QLocale::system().toString(then.date(), QLocale::ShortFormat); } DescInfo utils::getMessageDescription(const TimelineEvent &event, const QString &localUser, const QString &displayName) { using Audio = mtx::events::RoomEvent; using Emote = mtx::events::RoomEvent; using File = mtx::events::RoomEvent; using Image = mtx::events::RoomEvent; using Notice = mtx::events::RoomEvent; using Text = mtx::events::RoomEvent; using Video = mtx::events::RoomEvent; using CallInvite = mtx::events::RoomEvent; using CallAnswer = mtx::events::RoomEvent; using CallHangUp = mtx::events::RoomEvent; using Encrypted = mtx::events::EncryptedEvent; if (std::holds_alternative