diff --git a/0001-Cherry-pick-compatability-changes-for-libquotient-0.patch b/0001-Cherry-pick-compatability-changes-for-libquotient-0.patch new file mode 100644 index 0000000..133db4c --- /dev/null +++ b/0001-Cherry-pick-compatability-changes-for-libquotient-0.patch @@ -0,0 +1,532 @@ +From eb802ff91f98204784d87db61a698b4038b7ef84 Mon Sep 17 00:00:00 2001 +From: James Graham +Date: Sat, 26 Oct 2024 07:47:15 +0000 +Subject: [PATCH] Cherry pick compatability changes for libquotient 0.9 + +Title +--- + src/actionshandler.cpp | 8 ++ + src/eventhandler.cpp | 151 +++++++++++++++++++++++------ + src/eventhandler.h | 12 ++- + src/models/messagecontentmodel.cpp | 18 +++- + src/models/messageeventmodel.cpp | 5 + + src/neochatroom.cpp | 44 ++++++++- + 6 files changed, 199 insertions(+), 39 deletions(-) + +diff --git a/src/actionshandler.cpp b/src/actionshandler.cpp +index e5ddaadbd..c47b780b1 100644 +--- a/src/actionshandler.cpp ++++ b/src/actionshandler.cpp +@@ -91,10 +91,18 @@ void ActionsHandler::handleMessage(const QString &text, QString handledText, Cha + + for (auto it = m_room->messageEvents().crbegin(); it != m_room->messageEvents().crend(); it++) { + if (const auto event = eventCast(&**it)) { ++#if Quotient_VERSION_MINOR > 8 ++ if (event->senderId() == m_room->localMember().id() && event->has()) { ++#else + if (event->senderId() == m_room->localMember().id() && event->hasTextContent()) { ++#endif + QString originalString; + if (event->content()) { ++#if Quotient_VERSION_MINOR > 8 ++ originalString = event->get()->body; ++#else + originalString = static_cast(event->content())->body; ++#endif + } else { + originalString = event->plainBody(); + } +diff --git a/src/eventhandler.cpp b/src/eventhandler.cpp +index 8cad14601..6b02ade67 100644 +--- a/src/eventhandler.cpp ++++ b/src/eventhandler.cpp +@@ -9,6 +9,8 @@ + + #include + #include ++#include ++#include + #include + #include + #include +@@ -234,10 +236,18 @@ QString EventHandler::rawMessageBody(const Quotient::RoomMessageEvent &event) + { + QString body; + ++#if Quotient_VERSION_MINOR > 8 ++ if (event.has()) { ++#else + if (event.hasFileContent()) { ++#endif + // if filename is given or body is equal to filename, + // then body is a caption ++#if Quotient_VERSION_MINOR > 8 ++ QString filename = event.get()->originalName; ++#else + QString filename = event.content()->fileInfo()->originalName; ++#endif + QString body = event.plainBody(); + if (filename.isEmpty() || filename == body) { + return QString(); +@@ -245,8 +255,13 @@ QString EventHandler::rawMessageBody(const Quotient::RoomMessageEvent &event) + return body; + } + ++#if Quotient_VERSION_MINOR > 8 ++ if (event.has() && event.content()) { ++ body = event.get()->body; ++#else + if (event.hasTextContent() && event.content()) { + body = static_cast(event.content())->body; ++#endif + } else { + body = event.plainBody(); + } +@@ -461,11 +476,16 @@ QString EventHandler::getMessageBody(const RoomMessageEvent &event, Qt::TextForm + { + TextHandler textHandler; + ++#if Quotient_VERSION_MINOR > 8 ++ if (event.has()) { ++ QString fileCaption = event.get()->originalName; ++#else + if (event.hasFileContent()) { + auto fileCaption = event.content()->fileInfo()->originalName; ++#endif + if (fileCaption.isEmpty()) { + fileCaption = event.plainBody(); +- } else if (event.content()->fileInfo()->originalName != event.plainBody()) { ++ } else if (fileCaption != event.plainBody()) { + fileCaption = event.plainBody() + " | "_ls + fileCaption; + } + textHandler.setData(fileCaption); +@@ -473,8 +493,13 @@ QString EventHandler::getMessageBody(const RoomMessageEvent &event, Qt::TextForm + } + + QString body; ++#if Quotient_VERSION_MINOR > 8 ++ if (event.has() && event.content()) { ++ body = event.get()->body; ++#else + if (event.hasTextContent() && event.content()) { + body = static_cast(event.content())->body; ++#endif + } else { + body = event.plainBody(); + } +@@ -655,39 +680,65 @@ QVariantMap EventHandler::getMediaInfoForEvent(const Quotient::RoomEvent *event) + // Get the file info for the event. + if (event->is()) { + auto roomMessageEvent = eventCast(event); ++#if Quotient_VERSION_MINOR > 8 ++ if (!roomMessageEvent->has()) { ++#else + if (!roomMessageEvent->hasFileContent()) { ++#endif + return {}; + } + +- const EventContent::FileInfo *fileInfo; +- fileInfo = roomMessageEvent->content()->fileInfo(); +- QVariantMap mediaInfo = getMediaInfoFromFileInfo(fileInfo, eventId, false, false); ++#if Quotient_VERSION_MINOR > 8 ++ const auto content = roomMessageEvent->get(); ++ QVariantMap mediaInfo = getMediaInfoFromFileInfo(content.get(), eventId, false, false); ++#else ++ const auto content = static_cast(roomMessageEvent->content()); ++ QVariantMap mediaInfo = getMediaInfoFromFileInfo(content, eventId, false, false); ++#endif + // if filename isn't specifically given, it is in body + // https://spec.matrix.org/latest/client-server-api/#mfile +- mediaInfo["filename"_ls] = (fileInfo->originalName.isEmpty()) ? roomMessageEvent->plainBody() : fileInfo->originalName; ++#if Quotient_VERSION_MINOR > 8 ++ mediaInfo["filename"_ls] = content->commonInfo().originalName.isEmpty() ? roomMessageEvent->plainBody() : content->commonInfo().originalName; ++#else ++ mediaInfo["filename"_ls] = (content->fileInfo()->originalName.isEmpty()) ? roomMessageEvent->plainBody() : content->fileInfo()->originalName; ++#endif + + return mediaInfo; + } else if (event->is()) { +- const EventContent::FileInfo *fileInfo; +- + auto stickerEvent = eventCast(event); +- fileInfo = &stickerEvent->image(); ++ auto content = &stickerEvent->image(); + +- return getMediaInfoFromFileInfo(fileInfo, eventId, false, true); ++ return getMediaInfoFromFileInfo(content, eventId, false, true); + } else { + return {}; + } + } + +-QVariantMap EventHandler::getMediaInfoFromFileInfo(const EventContent::FileInfo *fileInfo, const QString &eventId, bool isThumbnail, bool isSticker) const ++QVariantMap EventHandler::getMediaInfoFromFileInfo( ++#if Quotient_VERSION_MINOR > 8 ++ const Quotient::EventContent::FileContentBase *fileContent, ++#else ++ const Quotient::EventContent::TypedBase *fileContent, ++#endif ++ const QString &eventId, ++ bool isThumbnail, ++ bool isSticker) const + { + QVariantMap mediaInfo; + + // Get the mxc URL for the media. +- if (!fileInfo->url().isValid() || fileInfo->url().scheme() != QStringLiteral("mxc") || eventId.isEmpty()) { ++#if Quotient_VERSION_MINOR > 8 ++ if (!fileContent->url().isValid() || fileContent->url().scheme() != QStringLiteral("mxc") || eventId.isEmpty()) { ++#else ++ if (!fileContent->fileInfo()->url().isValid() || fileContent->fileInfo()->url().scheme() != QStringLiteral("mxc") || eventId.isEmpty()) { ++#endif + mediaInfo["source"_ls] = QUrl(); + } else { +- QUrl source = m_room->makeMediaUrl(eventId, fileInfo->url()); ++#if Quotient_VERSION_MINOR > 8 ++ QUrl source = m_room->makeMediaUrl(eventId, fileContent->url()); ++#else ++ QUrl source = m_room->makeMediaUrl(eventId, fileContent->fileInfo()->url()); ++#endif + + if (source.isValid()) { + mediaInfo["source"_ls] = source; +@@ -696,7 +747,7 @@ QVariantMap EventHandler::getMediaInfoFromFileInfo(const EventContent::FileInfo + } + } + +- auto mimeType = fileInfo->mimeType; ++ auto mimeType = fileContent->type(); + // Add the MIME type for the media if available. + mediaInfo["mimeType"_ls] = mimeType.name(); + +@@ -704,45 +755,53 @@ QVariantMap EventHandler::getMediaInfoFromFileInfo(const EventContent::FileInfo + mediaInfo["mimeIcon"_ls] = mimeType.iconName(); + + // Add media size if available. +- mediaInfo["size"_ls] = fileInfo->payloadSize; ++#if Quotient_VERSION_MINOR > 8 ++ mediaInfo["size"_ls] = fileContent->commonInfo().payloadSize; ++#else ++ mediaInfo["size"_ls] = static_cast(fileContent)->fileInfo()->payloadSize; ++#endif + + mediaInfo["isSticker"_ls] = isSticker; + + // Add parameter depending on media type. + if (mimeType.name().contains(QStringLiteral("image"))) { +- if (auto castInfo = static_cast(fileInfo)) { ++ if (auto castInfo = static_cast(fileContent)) { ++#if Quotient_VERSION_MINOR > 8 + mediaInfo["width"_ls] = castInfo->imageSize.width(); + mediaInfo["height"_ls] = castInfo->imageSize.height(); ++#else ++ const auto imageInfo = static_cast(castInfo->fileInfo()); ++ mediaInfo["width"_ls] = imageInfo->imageSize.width(); ++ mediaInfo["height"_ls] = imageInfo->imageSize.height(); ++#endif + + // TODO: Images in certain formats (e.g. WebP) will be erroneously marked as animated, even if they are static. + mediaInfo["animated"_ls] = QMovie::supportedFormats().contains(mimeType.preferredSuffix().toUtf8()); + +- if (!isThumbnail) { +- QVariantMap tempInfo; +- auto thumbnailInfo = getMediaInfoFromFileInfo(castInfo->thumbnailInfo(), eventId, true); +- if (thumbnailInfo["source"_ls].toUrl().scheme() == "mxc"_ls) { +- tempInfo = thumbnailInfo; ++ QVariantMap tempInfo; ++ auto thumbnailInfo = getMediaInfoFromTumbnail(castInfo->thumbnail, eventId); ++ if (thumbnailInfo["source"_ls].toUrl().scheme() == "mxc"_ls) { ++ tempInfo = thumbnailInfo; ++ } else { ++ QString blurhash = castInfo->originalInfoJson["xyz.amorgan.blurhash"_ls].toString(); ++ if (blurhash.isEmpty()) { ++ tempInfo["source"_ls] = QUrl(); + } else { +- QString blurhash = castInfo->originalInfoJson["xyz.amorgan.blurhash"_ls].toString(); +- if (blurhash.isEmpty()) { +- tempInfo["source"_ls] = QUrl(); +- } else { +- tempInfo["source"_ls] = QUrl("image://blurhash/"_ls + blurhash); +- } ++ tempInfo["source"_ls] = QUrl("image://blurhash/"_ls + blurhash); + } +- mediaInfo["tempInfo"_ls] = tempInfo; + } ++ mediaInfo["tempInfo"_ls] = tempInfo; + } + } + if (mimeType.name().contains(QStringLiteral("video"))) { +- if (auto castInfo = static_cast(fileInfo)) { ++ if (auto castInfo = static_cast(fileContent)) { + mediaInfo["width"_ls] = castInfo->imageSize.width(); + mediaInfo["height"_ls] = castInfo->imageSize.height(); + mediaInfo["duration"_ls] = castInfo->duration; + + if (!isThumbnail) { + QVariantMap tempInfo; +- auto thumbnailInfo = getMediaInfoFromFileInfo(castInfo->thumbnailInfo(), eventId, true); ++ auto thumbnailInfo = getMediaInfoFromTumbnail(castInfo->thumbnail, eventId); + if (thumbnailInfo["source"_ls].toUrl().scheme() == "mxc"_ls) { + tempInfo = thumbnailInfo; + } else { +@@ -758,7 +817,7 @@ QVariantMap EventHandler::getMediaInfoFromFileInfo(const EventContent::FileInfo + } + } + if (mimeType.name().contains(QStringLiteral("audio"))) { +- if (auto castInfo = static_cast(fileInfo)) { ++ if (auto castInfo = static_cast(fileContent)) { + mediaInfo["duration"_ls] = castInfo->duration; + } + } +@@ -766,6 +825,38 @@ QVariantMap EventHandler::getMediaInfoFromFileInfo(const EventContent::FileInfo + return mediaInfo; + } + ++QVariantMap EventHandler::getMediaInfoFromTumbnail(const Quotient::EventContent::Thumbnail &thumbnail, const QString &eventId) const ++{ ++ QVariantMap thumbnailInfo; ++ ++ if (!thumbnail.url().isValid() || thumbnail.url().scheme() != QStringLiteral("mxc") || eventId.isEmpty()) { ++ thumbnailInfo["source"_ls] = QUrl(); ++ } else { ++ QUrl source = m_room->makeMediaUrl(eventId, thumbnail.url()); ++ ++ if (source.isValid()) { ++ thumbnailInfo["source"_ls] = source; ++ } else { ++ thumbnailInfo["source"_ls] = QUrl(); ++ } ++ } ++ ++ auto mimeType = thumbnail.mimeType; ++ // Add the MIME type for the media if available. ++ thumbnailInfo["mimeType"_ls] = mimeType.name(); ++ ++ // Add the MIME type icon if available. ++ thumbnailInfo["mimeIcon"_ls] = mimeType.iconName(); ++ ++ // Add media size if available. ++ thumbnailInfo["size"_ls] = thumbnail.payloadSize; ++ ++ thumbnailInfo["width"_ls] = thumbnail.imageSize.width(); ++ thumbnailInfo["height"_ls] = thumbnail.imageSize.height(); ++ ++ return thumbnailInfo; ++} ++ + bool EventHandler::hasReply() const + { + if (m_event == nullptr) { +diff --git a/src/eventhandler.h b/src/eventhandler.h +index 277273c9e..6a3520882 100644 +--- a/src/eventhandler.h ++++ b/src/eventhandler.h +@@ -339,6 +339,14 @@ private: + QString getMessageBody(const Quotient::RoomMessageEvent &event, Qt::TextFormat format, bool stripNewlines) const; + + QVariantMap getMediaInfoForEvent(const Quotient::RoomEvent *event) const; +- QVariantMap +- getMediaInfoFromFileInfo(const Quotient::EventContent::FileInfo *fileInfo, const QString &eventId, bool isThumbnail = false, bool isSticker = false) const; ++ QVariantMap getMediaInfoFromFileInfo( ++#if Quotient_VERSION_MINOR > 8 ++ const Quotient::EventContent::FileContentBase *fileContent, ++#else ++ const Quotient::EventContent::TypedBase *fileContent, ++#endif ++ const QString &eventId, ++ bool isThumbnail = false, ++ bool isSticker = false) const; ++ QVariantMap getMediaInfoFromTumbnail(const Quotient::EventContent::Thumbnail &thumbnail, const QString &eventId) const; + }; +diff --git a/src/models/messagecontentmodel.cpp b/src/models/messagecontentmodel.cpp +index 7de11f274..ac1756f84 100644 +--- a/src/models/messagecontentmodel.cpp ++++ b/src/models/messagecontentmodel.cpp +@@ -7,6 +7,7 @@ + + #include + ++#include + #include + #include + #include +@@ -445,10 +446,19 @@ QList MessageContentModel::componentsForType(MessageComponentT + auto fileTransferInfo = m_room->cachedFileTransferInfo(m_event.get()); + + #ifndef Q_OS_ANDROID +- Q_ASSERT(event->content() != nullptr && event->content()->fileInfo() != nullptr); ++#if Quotient_VERSION_MINOR > 8 ++ Q_ASSERT(event->content() != nullptr && event->has()); ++ const QMimeType mimeType = event->get()->mimeType; ++#else ++ Q_ASSERT(event->content() != nullptr && event->hasFileContent()); + const QMimeType mimeType = event->content()->fileInfo()->mimeType; ++#endif + if (mimeType.name() == QStringLiteral("text/plain") || mimeType.parentMimeTypes().contains(QStringLiteral("text/plain"))) { ++#if Quotient_VERSION_MINOR > 8 ++ QString originalName = event->get()->originalName; ++#else + QString originalName = event->content()->fileInfo()->originalName; ++#endif + if (originalName.isEmpty()) { + originalName = event->plainBody(); + } +@@ -571,8 +581,12 @@ void MessageContentModel::updateItineraryModel() + } + + if (auto event = eventCast(m_event)) { ++#if Quotient_VERSION_MINOR > 8 ++ if (event->has()) { ++#else + if (event->hasFileContent()) { +- auto filePath = m_room->cachedFileTransferInfo(m_event.get()).localPath; ++#endif ++ auto filePath = m_room->cachedFileTransferInfo(event).localPath; + if (filePath.isEmpty() && m_itineraryModel != nullptr) { + delete m_itineraryModel; + m_itineraryModel = nullptr; +diff --git a/src/models/messageeventmodel.cpp b/src/models/messageeventmodel.cpp +index 09c738d0e..784fcd36e 100644 +--- a/src/models/messageeventmodel.cpp ++++ b/src/models/messageeventmodel.cpp +@@ -8,6 +8,7 @@ + #include "neochatconfig.h" + + #include ++#include + #include + #include + #include +@@ -498,7 +499,11 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const + + if (role == ProgressInfoRole) { + if (auto e = eventCast(&evt)) { ++#if Quotient_VERSION_MINOR > 8 ++ if (e->has()) { ++#else + if (e->hasFileContent()) { ++#endif + return QVariant::fromValue(m_currentRoom->cachedFileTransferInfo(&evt)); + } + } +diff --git a/src/neochatroom.cpp b/src/neochatroom.cpp +index f5b1eb57b..8f4201e58 100644 +--- a/src/neochatroom.cpp ++++ b/src/neochatroom.cpp +@@ -9,6 +9,7 @@ + #include + #include + ++#include + #include + #include + #include +@@ -76,11 +77,16 @@ NeoChatRoom::NeoChatRoom(Connection *connection, QString roomId, JoinState joinS + const auto m_event = evtIt->viewAs(); + QString mxcUrl; + if (auto event = eventCast(m_event)) { ++#if Quotient_VERSION_MINOR > 8 ++ if (event->has()) { ++ mxcUrl = event->get()->url().toString(); ++#else + if (event->hasFileContent()) { + mxcUrl = event->content()->fileInfo()->url().toString(); ++#endif + } + } else if (auto event = eventCast(m_event)) { +- mxcUrl = event->image().fileInfo()->url().toString(); ++ mxcUrl = event->image().url().toString(); + } + if (mxcUrl.isEmpty()) { + return; +@@ -255,7 +261,11 @@ QCoro::Task NeoChatRoom::doUploadFile(QUrl url, QString body) + auto mime = QMimeDatabase().mimeTypeForUrl(url); + url.setScheme("file"_ls); + QFileInfo fileInfo(url.isLocalFile() ? url.toLocalFile() : url.toString()); ++#if Quotient_VERSION_MINOR > 8 ++ EventContent::FileContentBase *content; ++#else + EventContent::TypedBase *content; ++#endif + if (mime.name().startsWith("image/"_ls)) { + QImage image(url.toLocalFile()); + content = new EventContent::ImageContent(url, fileInfo.size(), mime, image.size(), fileInfo.fileName()); +@@ -270,7 +280,11 @@ QCoro::Task NeoChatRoom::doUploadFile(QUrl url, QString body) + } else { + content = new EventContent::FileContent(url, fileInfo.size(), mime, fileInfo.fileName()); + } ++#if Quotient_VERSION_MINOR > 8 ++ QString txnId = postFile(body.isEmpty() ? url.fileName() : body, std::unique_ptr(content)); ++#else + QString txnId = postFile(body.isEmpty() ? url.fileName() : body, content); ++#endif + setHasFileUploading(true); + connect(this, &Room::fileTransferCompleted, [this, txnId](const QString &id, FileSourceInfo) { + if (id == txnId) { +@@ -396,8 +410,13 @@ bool NeoChatRoom::lastEventIsSpoiler() const + { + if (auto event = lastEvent()) { + if (auto e = eventCast(event)) { ++#if Quotient_VERSION_MINOR > 8 ++ if (e->has() && e->content() && e->mimeType().name() == "text/html"_ls) { ++ auto htmlBody = e->get()->body; ++#else + if (e->hasTextContent() && e->content() && e->mimeType().name() == "text/html"_ls) { + auto htmlBody = static_cast(e->content())->body; ++#endif + return htmlBody.contains("data-mx-spoiler"_ls); + } + } +@@ -1456,7 +1475,11 @@ void NeoChatRoom::openEventMediaExternally(const QString &eventId) + const auto evtIt = findInTimeline(eventId); + if (evtIt != messageEvents().rend() && is(**evtIt)) { + const auto event = evtIt->viewAs(); ++#if Quotient_VERSION_MINOR > 8 ++ if (event->has()) { ++#else + if (event->hasFileContent()) { ++#endif + const auto transferInfo = cachedFileTransferInfo(event); + if (transferInfo.completed()) { + UrlHelper helper; +@@ -1489,7 +1512,11 @@ void NeoChatRoom::copyEventMedia(const QString &eventId) + const auto evtIt = findInTimeline(eventId); + if (evtIt != messageEvents().rend() && is(**evtIt)) { + const auto event = evtIt->viewAs(); ++#if Quotient_VERSION_MINOR > 8 ++ if (event->has()) { ++#else + if (event->hasFileContent()) { ++#endif + const auto transferInfo = fileTransferInfo(eventId); + if (transferInfo.completed()) { + Clipboard clipboard; +@@ -1522,13 +1549,20 @@ FileTransferInfo NeoChatRoom::cachedFileTransferInfo(const Quotient::RoomEvent * + QString mxcUrl; + int total = 0; + if (auto evt = eventCast(event)) { ++#if Quotient_VERSION_MINOR > 8 ++ if (evt->has()) { ++ const auto fileContent = evt->get(); ++#else + if (evt->hasFileContent()) { +- mxcUrl = evt->content()->fileInfo()->url().toString(); +- total = evt->content()->fileInfo()->payloadSize; ++ const auto fileContent = evt->content()->fileInfo(); ++#endif ++ ++ mxcUrl = fileContent->url().toString(); ++ total = fileContent->payloadSize; + } + } else if (auto evt = eventCast(event)) { +- mxcUrl = evt->image().fileInfo()->url().toString(); +- total = evt->image().fileInfo()->payloadSize; ++ mxcUrl = evt->image().url().toString(); ++ total = evt->image().payloadSize; + } + + FileTransferInfo transferInfo = fileTransferInfo(event->id()); +-- +2.47.0 + diff --git a/neochat.changes b/neochat.changes index c07b559..9668cd3 100644 --- a/neochat.changes +++ b/neochat.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Mon Oct 28 07:59:23 UTC 2024 - Christophe Marin + +- Add upstream change: + * 0001-Cherry-pick-compatability-changes-for-libquotient-0.patch + ------------------------------------------------------------------- Tue Oct 8 12:02:28 UTC 2024 - Christophe Marin diff --git a/neochat.spec b/neochat.spec index 0f2b60d..87edcee 100644 --- a/neochat.spec +++ b/neochat.spec @@ -32,6 +32,8 @@ Source0: https://download.kde.org/stable/release-service/%{version}/src/% Source1: https://download.kde.org/stable/release-service/%{version}/src/%{name}-%{version}.tar.xz.sig Source2: applications.keyring %endif +# PATCH-FIX-UPSTREAM +Patch0: 0001-Cherry-pick-compatability-changes-for-libquotient-0.patch # Needed for leap 15.5 BuildRequires: cmark BuildRequires: kf6-extra-cmake-modules >= %{kf6_version}