From 073e756364009286beeef250494f6b03c05aaffb Mon Sep 17 00:00:00 2001 From: Tobias Fella Date: Sat, 22 Mar 2025 17:10:33 +0100 Subject: [PATCH] Port to Integral --- CMakeLists.txt | 10 +- src/CMakeLists.txt | 284 +-- src/chatbar/ChatBar.qml | 48 +- src/chatbarcache.cpp | 209 +-- src/chatbarcache.h | 12 +- src/chatdocumenthandler.cpp | 102 +- src/controller.cpp | 245 +-- src/controller.h | 30 +- src/enums/neochatroomtype.h | 22 +- src/enums/roomsortparameter.cpp | 100 +- src/enums/roomsortparameter.h | 24 +- src/foreigntypes.h | 44 +- src/login/Login.qml | 21 +- src/login/Password.qml | 7 +- src/login/WelcomePage.qml | 143 +- src/main.cpp | 130 +- src/models/completionmodel.cpp | 211 +-- src/models/completionmodel.h | 4 +- src/models/pushrulemodel.cpp | 264 +-- src/models/pushrulemodel.h | 6 +- src/models/roomtreeitem.cpp | 14 +- src/models/roomtreeitem.h | 25 +- src/models/roomtreemodel.cpp | 435 +++-- src/models/roomtreemodel.h | 29 +- src/models/sortfilterroomtreemodel.cpp | 78 +- src/models/sortfilterroomtreemodel.h | 4 +- src/models/userlistmodel.cpp | 200 +-- src/models/userlistmodel.h | 10 +- src/neochatconnection.cpp | 763 ++++---- src/neochatconnection.h | 26 +- src/neochatroom.cpp | 2258 ++++++++++++------------ src/neochatroom.h | 80 +- src/qml/AccountSwitchDialog.qml | 2 +- src/qml/Main.qml | 252 +-- src/qml/RoomDelegate.qml | 19 +- src/qml/RoomListPage.qml | 349 +--- src/qml/RoomMedia.qml | 56 +- src/qml/RoomPage.qml | 142 +- src/qml/RoomTreeSection.qml | 2 +- src/qml/UserInfo.qml | 8 +- src/roommanager.h | 6 +- src/settings/CMakeLists.txt | 46 +- src/utils.cpp | 12 +- src/utils.h | 6 +- 44 files changed, 3212 insertions(+), 3526 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6afbc135c..d66643e70 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,8 +49,6 @@ if(NEOCHAT_FLATPAK) include(cmake/Flatpak.cmake) endif() -set(QUOTIENT_FORCE_NAMESPACED_INCLUDES TRUE) - ecm_setup_version(${PROJECT_VERSION} VARIABLE_PREFIX NEOCHAT VERSION_HEADER ${CMAKE_CURRENT_BINARY_DIR}/neochat-version.h @@ -107,13 +105,7 @@ if (NOT ANDROID AND NOT WIN32 AND NOT APPLE AND NOT HAIKU) find_package(KF6DBusAddons ${KF_MIN_VERSION} REQUIRED) endif() -find_package(QuotientQt6 0.9) -set_package_properties(QuotientQt6 PROPERTIES - TYPE REQUIRED - DESCRIPTION "Qt wrapper around Matrix API" - URL "https://github.com/quotient-im/libQuotient/" - PURPOSE "Talk with matrix server" -) +find_package(Integral 0.1 REQUIRED) find_package(cmark) set_package_properties(cmark PROPERTIES diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f7432bdad..8d20be57c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,192 +10,192 @@ endif() add_library(neochat STATIC controller.cpp controller.h - models/emojimodel.cpp - models/emojimodel.h - emojitones.cpp - emojitones.h - models/customemojimodel.cpp - models/customemojimodel.h - clipboard.cpp - clipboard.h - models/timelinemessagemodel.cpp - models/timelinemessagemodel.h - models/messagefiltermodel.cpp - models/messagefiltermodel.h - models/roomlistmodel.cpp - models/roomlistmodel.h - models/sortfilterspacelistmodel.cpp - models/sortfilterspacelistmodel.h - models/accountemoticonmodel.cpp - models/accountemoticonmodel.h - spacehierarchycache.cpp - spacehierarchycache.h - roommanager.cpp - roommanager.h + # models/emojimodel.cpp + # models/emojimodel.h + # emojitones.cpp + # emojitones.h + # models/customemojimodel.cpp + # models/customemojimodel.h + # clipboard.cpp + # clipboard.h + # models/timelinemessagemodel.cpp + # models/timelinemessagemodel.h + # models/messagefiltermodel.cpp + # models/messagefiltermodel.h + # models/roomlistmodel.cpp + # models/roomlistmodel.h + # models/sortfilterspacelistmodel.cpp + # models/sortfilterspacelistmodel.h + # models/accountemoticonmodel.cpp + # models/accountemoticonmodel.h + # spacehierarchycache.cpp + # spacehierarchycache.h + # roommanager.cpp + # roommanager.h neochatroom.cpp neochatroom.h models/userlistmodel.cpp models/userlistmodel.h models/userfiltermodel.cpp models/userfiltermodel.h - models/publicroomlistmodel.cpp - models/publicroomlistmodel.h - models/spacechildrenmodel.cpp - models/spacechildrenmodel.h - models/spacechildsortfiltermodel.cpp - models/spacechildsortfiltermodel.h - models/spacetreeitem.cpp - models/spacetreeitem.h - models/userdirectorylistmodel.cpp - models/userdirectorylistmodel.h + # models/publicroomlistmodel.cpp + # models/publicroomlistmodel.h + # models/spacechildrenmodel.cpp + # models/spacechildrenmodel.h + # models/spacechildsortfiltermodel.cpp + # models/spacechildsortfiltermodel.h + # models/spacetreeitem.cpp + # models/spacetreeitem.h + # models/userdirectorylistmodel.cpp + # models/userdirectorylistmodel.h models/pushrulemodel.cpp models/pushrulemodel.h - models/emoticonfiltermodel.cpp - models/emoticonfiltermodel.h - notificationsmanager.cpp - notificationsmanager.h - models/sortfilterroomlistmodel.cpp - models/sortfilterroomlistmodel.h + # models/emoticonfiltermodel.cpp + # models/emoticonfiltermodel.h + # notificationsmanager.cpp + # notificationsmanager.h + # models/sortfilterroomlistmodel.cpp + # models/sortfilterroomlistmodel.h models/roomtreemodel.cpp models/roomtreemodel.h chatdocumenthandler.cpp chatdocumenthandler.h - models/devicesmodel.cpp - models/devicesmodel.h - models/devicesproxymodel.cpp - filetype.cpp - filetype.h - login.cpp - login.h - models/webshortcutmodel.cpp - models/webshortcutmodel.h + # models/devicesmodel.cpp + # models/devicesmodel.h + # models/devicesproxymodel.cpp + # filetype.cpp + # filetype.h + # login.cpp + # login.h + # models/webshortcutmodel.cpp + # models/webshortcutmodel.h blurhash.cpp blurhash.h blurhashimageprovider.cpp blurhashimageprovider.h - models/mediamessagefiltermodel.cpp - models/mediamessagefiltermodel.h - urlhelper.cpp - urlhelper.h + # models/mediamessagefiltermodel.cpp + # models/mediamessagefiltermodel.h + # urlhelper.cpp + # urlhelper.h windowcontroller.cpp windowcontroller.h - linkpreviewer.cpp - linkpreviewer.h + # linkpreviewer.cpp + # linkpreviewer.h models/completionmodel.cpp models/completionmodel.h - models/completionproxymodel.cpp - models/completionproxymodel.h - models/actionsmodel.cpp - models/actionsmodel.h - models/serverlistmodel.cpp - models/serverlistmodel.h - models/statemodel.cpp - models/statemodel.h - models/statefiltermodel.cpp - models/statefiltermodel.h - filetransferpseudojob.cpp - filetransferpseudojob.h - models/searchmodel.cpp - models/searchmodel.h - texthandler.cpp - texthandler.h + # models/completionproxymodel.cpp + # models/completionproxymodel.h + # models/actionsmodel.cpp + # models/actionsmodel.h + # models/serverlistmodel.cpp + # models/serverlistmodel.h + # models/statemodel.cpp + # models/statemodel.h + # models/statefiltermodel.cpp + # models/statefiltermodel.h + # filetransferpseudojob.cpp + # filetransferpseudojob.h + # models/searchmodel.cpp + # models/searchmodel.h + # texthandler.cpp + # texthandler.h logger.cpp logger.h - models/stickermodel.cpp - models/stickermodel.h - models/imagepacksmodel.cpp - models/imagepacksmodel.h - events/imagepackevent.cpp - events/imagepackevent.h - models/reactionmodel.cpp - models/reactionmodel.h + # models/stickermodel.cpp + # models/stickermodel.h + # models/imagepacksmodel.cpp + # models/imagepacksmodel.h + # events/imagepackevent.cpp + # events/imagepackevent.h + # models/reactionmodel.cpp + # models/reactionmodel.h delegatesizehelper.cpp delegatesizehelper.h - models/livelocationsmodel.cpp - models/livelocationsmodel.h - models/locationsmodel.cpp - models/locationsmodel.h - locationhelper.cpp - locationhelper.h - events/pollevent.cpp - pollhandler.cpp + # models/livelocationsmodel.cpp + # models/livelocationsmodel.h + # models/locationsmodel.cpp + # models/locationsmodel.h + # locationhelper.cpp + # locationhelper.h + # events/pollevent.cpp + # pollhandler.cpp utils.h utils.cpp - registration.cpp + # registration.cpp neochatconnection.cpp neochatconnection.h - jobs/neochatgetcommonroomsjob.cpp - jobs/neochatgetcommonroomsjob.h + # jobs/neochatgetcommonroomsjob.cpp + # jobs/neochatgetcommonroomsjob.h mediasizehelper.cpp mediasizehelper.h - eventhandler.cpp - enums/delegatetype.h - roomlastmessageprovider.cpp - roomlastmessageprovider.h + # eventhandler.cpp + # enums/delegatetype.h + # roomlastmessageprovider.cpp + # roomlastmessageprovider.h chatbarcache.cpp chatbarcache.h colorschemer.cpp colorschemer.h - models/notificationsmodel.cpp - models/notificationsmodel.h - models/timelinemodel.cpp - models/timelinemodel.h + # models/notificationsmodel.cpp + # models/notificationsmodel.h + # models/timelinemodel.cpp + # models/timelinemodel.h enums/pushrule.h - models/itinerarymodel.cpp - models/itinerarymodel.h + # models/itinerarymodel.cpp + # models/itinerarymodel.h proxycontroller.cpp proxycontroller.h models/linemodel.cpp models/linemodel.h - events/locationbeaconevent.h - events/widgetevent.h - enums/messagecomponenttype.h - models/messagecontentmodel.cpp - models/messagecontentmodel.h + # events/locationbeaconevent.h + # events/widgetevent.h + # enums/messagecomponenttype.h + # models/messagecontentmodel.cpp + # models/messagecontentmodel.h enums/neochatroomtype.h models/sortfilterroomtreemodel.cpp models/sortfilterroomtreemodel.h mediamanager.cpp mediamanager.h - models/statekeysmodel.cpp - models/statekeysmodel.h - sharehandler.cpp - sharehandler.h + # models/statekeysmodel.cpp + # models/statekeysmodel.h + # sharehandler.cpp + # sharehandler.h models/roomtreeitem.cpp models/roomtreeitem.h foreigntypes.h - models/threepidmodel.cpp - models/threepidmodel.h - threepidaddhelper.cpp - threepidaddhelper.h - identityserverhelper.cpp - identityserverhelper.h - enums/powerlevel.cpp - enums/powerlevel.h - models/permissionsmodel.cpp - models/permissionsmodel.h - threepidbindhelper.cpp - threepidbindhelper.h - models/readmarkermodel.cpp - models/readmarkermodel.h - neochatroommember.cpp - neochatroommember.h - models/threadmodel.cpp - models/threadmodel.h - enums/messagetype.h - messagecomponent.h + # models/threepidmodel.cpp + # models/threepidmodel.h + # threepidaddhelper.cpp + # threepidaddhelper.h + # identityserverhelper.cpp + # identityserverhelper.h + # enums/powerlevel.cpp + # enums/powerlevel.h + # models/permissionsmodel.cpp + # models/permissionsmodel.h + # threepidbindhelper.cpp + # threepidbindhelper.h + # models/readmarkermodel.cpp + # models/readmarkermodel.h + # neochatroommember.cpp + # neochatroommember.h + # models/threadmodel.cpp + # models/threadmodel.h + # enums/messagetype.h + # messagecomponent.h enums/roomsortparameter.cpp enums/roomsortparameter.h - models/roomsortparametermodel.cpp - models/roomsortparametermodel.h - models/messagemodel.cpp - models/messagemodel.h - models/messagecontentfiltermodel.cpp - models/messagecontentfiltermodel.h - models/pinnedmessagemodel.cpp - models/pinnedmessagemodel.h - models/commonroomsmodel.cpp - models/commonroomsmodel.h + # models/roomsortparametermodel.cpp + # models/roomsortparametermodel.h + # models/messagemodel.cpp + # models/messagemodel.h + # models/messagecontentfiltermodel.cpp + # models/messagecontentfiltermodel.h + # models/pinnedmessagemodel.cpp + # models/pinnedmessagemodel.h + # models/commonroomsmodel.cpp + # models/commonroomsmodel.h ) set_source_files_properties(qml/OsmLocationPlugin.qml PROPERTIES @@ -297,8 +297,8 @@ ecm_add_qml_module(neochat URI org.kde.neochat GENERATE_PLUGIN_SOURCE qml/AvatarNotification.qml qml/ReasonDialog.qml SOURCES - messageattached.cpp - messageattached.h + # messageattached.cpp + # messageattached.h DEPENDENCIES QtCore QtQuick @@ -398,10 +398,10 @@ endif() if (NOT ANDROID AND NOT WIN32 AND NOT APPLE AND NOT HAIKU) target_compile_definitions(neochat PUBLIC -DHAVE_RUNNER) target_compile_definitions(neochat PUBLIC -DHAVE_X11=1) - target_sources(neochat PRIVATE runner.cpp) + # target_sources(neochat PRIVATE runner.cpp) if (TARGET KUnifiedPush) - target_sources(neochat PRIVATE fakerunner.cpp) + # target_sources(neochat PRIVATE fakerunner.cpp) endif() else() target_compile_definitions(neochat PUBLIC -DHAVE_X11=0) @@ -427,7 +427,7 @@ target_link_libraries(neochat PUBLIC KF6::IconThemes KF6::ColorScheme KF6::ItemModels - QuotientQt6 + Integral cmark::cmark QCoro::Core QCoro::Network diff --git a/src/chatbar/ChatBar.qml b/src/chatbar/ChatBar.qml index 3dfd841a4..c8d5a8e1c 100644 --- a/src/chatbar/ChatBar.qml +++ b/src/chatbar/ChatBar.qml @@ -344,13 +344,13 @@ QQC2.Control { Item { implicitWidth: replyComponent.implicitWidth implicitHeight: replyComponent.implicitHeight - ReplyComponent { - id: replyComponent - replyEventId: _private.chatBarCache.replyId - replyAuthor: _private.chatBarCache.relationAuthor - replyContentModel: _private.chatBarCache.relationEventContentModel - Message.maxContentWidth: paneLoader.item.width - } + // ReplyComponent { + // id: replyComponent + // replyEventId: _private.chatBarCache.replyId + // replyAuthor: _private.chatBarCache.relationAuthor + // replyContentModel: _private.chatBarCache.relationEventContentModel + // Message.maxContentWidth: paneLoader.item.width + // } QQC2.Button { id: cancelButton @@ -498,23 +498,23 @@ QQC2.Control { } } - EmojiDialog { - id: emojiDialog - - x: root.width - width - y: -implicitHeight - - modal: false - includeCustom: true - closeOnChosen: false - - currentRoom: root.currentRoom - - onChosen: emoji => insertText(emoji) - onClosed: if (emojiAction.checked) { - emojiAction.checked = false; - } - } + // EmojiDialog { + // id: emojiDialog + // + // x: root.width - width + // y: -implicitHeight + // + // modal: false + // includeCustom: true + // closeOnChosen: false + // + // currentRoom: root.currentRoom + // + // onChosen: emoji => insertText(emoji) + // onClosed: if (emojiAction.checked) { + // emojiAction.checked = false; + // } + // } function insertText(text) { let initialCursorPosition = textField.cursorPosition; diff --git a/src/chatbarcache.cpp b/src/chatbarcache.cpp index c1f90a53f..7dd887179 100644 --- a/src/chatbarcache.cpp +++ b/src/chatbarcache.cpp @@ -2,14 +2,15 @@ // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL #include "chatbarcache.h" +#include "chatdocumenthandler.h" #include -#include "chatdocumenthandler.h" -#include "eventhandler.h" -#include "models/actionsmodel.h" +// #include "chatdocumenthandler.h" +// #include "eventhandler.h" +// #include "models/actionsmodel.h" #include "neochatroom.h" -#include "texthandler.h" +// #include "texthandler.h" using namespace Qt::StringLiterals; @@ -88,7 +89,7 @@ void ChatBarCache::setReplyId(const QString &replyId) m_relationType = Reply; } m_attachmentPath = QString(); - delete m_relationContentModel; + // delete m_relationContentModel; Q_EMIT relationIdChanged(oldEventId, m_relationId); Q_EMIT attachmentPathChanged(); } @@ -118,27 +119,27 @@ void ChatBarCache::setEditId(const QString &editId) m_relationType = Edit; } m_attachmentPath = QString(); - delete m_relationContentModel; + // delete m_relationContentModel; Q_EMIT relationIdChanged(oldEventId, m_relationId); Q_EMIT attachmentPathChanged(); } -Quotient::RoomMember ChatBarCache::relationAuthor() const -{ - if (parent() == nullptr) { - qWarning() << "ChatBarCache created with no parent, a NeoChatRoom must be set as the parent on creation."; - return {}; - } - auto room = dynamic_cast(parent()); - if (room == nullptr) { - qWarning() << "ChatBarCache created with incorrect parent, a NeoChatRoom must be set as the parent on creation."; - return {}; - } - if (m_relationId.isEmpty()) { - return room->member(QString()); - } - return room->member((*room->findInTimeline(m_relationId))->senderId()); -} +// Quotient::RoomMember ChatBarCache::relationAuthor() const +// { +// if (parent() == nullptr) { +// qWarning() << "ChatBarCache created with no parent, a NeoChatRoom must be set as the parent on creation."; +// return {}; +// } +// auto room = dynamic_cast(parent()); +// if (room == nullptr) { +// qWarning() << "ChatBarCache created with incorrect parent, a NeoChatRoom must be set as the parent on creation."; +// return {}; +// } +// if (m_relationId.isEmpty()) { +// return room->member(QString()); +// } +// return room->member((*room->findInTimeline(m_relationId))->senderId()); +// } QString ChatBarCache::relationMessage() const { @@ -155,33 +156,33 @@ QString ChatBarCache::relationMessage() const return {}; } - if (auto event = room->findInTimeline(m_relationId); event != room->historyEdge()) { - return EventHandler::markdownBody(&**event); - } + // if (auto event = room->findInTimeline(m_relationId); event != room->historyEdge()) { + // return EventHandler::markdownBody(&**event); + // } return {}; } -MessageContentModel *ChatBarCache::relationEventContentModel() -{ - if (parent() == nullptr) { - qWarning() << "ChatBarCache created with no parent, a NeoChatRoom must be set as the parent on creation."; - return nullptr; - } - if (m_relationId.isEmpty()) { - return nullptr; - } - if (m_relationContentModel != nullptr) { - return m_relationContentModel; - } - - auto room = dynamic_cast(parent()); - if (room == nullptr) { - qWarning() << "ChatBarCache created with incorrect parent, a NeoChatRoom must be set as the parent on creation."; - return nullptr; - } - m_relationContentModel = new MessageContentModel(room, m_relationId, true); - return m_relationContentModel; -} +// MessageContentModel *ChatBarCache::relationEventContentModel() +// { +// if (parent() == nullptr) { +// qWarning() << "ChatBarCache created with no parent, a NeoChatRoom must be set as the parent on creation."; +// return nullptr; +// } +// if (m_relationId.isEmpty()) { +// return nullptr; +// } +// if (m_relationContentModel != nullptr) { +// return m_relationContentModel; +// } +// +// auto room = dynamic_cast(parent()); +// if (room == nullptr) { +// qWarning() << "ChatBarCache created with incorrect parent, a NeoChatRoom must be set as the parent on creation."; +// return nullptr; +// } +// m_relationContentModel = new MessageContentModel(room, m_relationId, true); +// return m_relationContentModel; +// } bool ChatBarCache::isThreaded() const { @@ -215,7 +216,7 @@ void ChatBarCache::setAttachmentPath(const QString &attachmentPath) m_attachmentPath = attachmentPath; m_relationType = None; const auto oldEventId = std::exchange(m_relationId, QString()); - delete m_relationContentModel; + // delete m_relationContentModel; Q_EMIT attachmentPathChanged(); Q_EMIT relationIdChanged(oldEventId, m_relationId); } @@ -225,7 +226,7 @@ void ChatBarCache::clearRelations() const auto oldEventId = std::exchange(m_relationId, QString()); const auto oldThreadId = std::exchange(m_threadId, QString()); m_attachmentPath = QString(); - delete m_relationContentModel; + // delete m_relationContentModel; Q_EMIT relationIdChanged(oldEventId, m_relationId); Q_EMIT threadIdChanged(oldThreadId, m_threadId); Q_EMIT attachmentPathChanged(); @@ -238,7 +239,7 @@ QList *ChatBarCache::mentions() void ChatBarCache::updateMentions(QQuickTextDocument *document, ChatDocumentHandler *documentHandler) { - documentHandler->setDocument(document); + // documentHandler->setDocument(document); if (parent() == nullptr) { qWarning() << "ChatBarCache created with no parent, a NeoChatRoom must be set as the parent on creation."; @@ -253,35 +254,35 @@ void ChatBarCache::updateMentions(QQuickTextDocument *document, ChatDocumentHand return; } - if (auto event = room->findInTimeline(m_relationId); event != room->historyEdge()) { - if (const auto &roomMessageEvent = &*event->viewAs()) { - // Replaces the mentions that are baked into the HTML but plaintext in the original markdown - const QRegularExpression re(uR"lit(([\S]*)<\/a>)lit"_s); - - m_mentions.clear(); - - int linkSize = 0; - auto matches = re.globalMatch(EventHandler::rawMessageBody(*roomMessageEvent)); - while (matches.hasNext()) { - const QRegularExpressionMatch match = matches.next(); - if (match.hasMatch()) { - const QString id = match.captured(1); - const QString name = match.captured(2); - - const int position = match.capturedStart(0) - linkSize; - const int end = position + name.length(); - linkSize += match.capturedLength(0) - name.length(); - - QTextCursor cursor(documentHandler->document()->textDocument()); - cursor.setPosition(position); - cursor.setPosition(end, QTextCursor::KeepAnchor); - cursor.setKeepPositionOnInsert(true); - - m_mentions.push_back(Mention{.cursor = cursor, .text = name, .start = position, .position = end, .id = id}); - } - } - } - } + // if (auto event = room->findInTimeline(m_relationId); event != room->historyEdge()) { + // if (const auto &roomMessageEvent = &*event->viewAs()) { + // // Replaces the mentions that are baked into the HTML but plaintext in the original markdown + // const QRegularExpression re(uR"lit(([\S]*)<\/a>)lit"_s); + // + // m_mentions.clear(); + // + // int linkSize = 0; + // auto matches = re.globalMatch(EventHandler::rawMessageBody(*roomMessageEvent)); + // while (matches.hasNext()) { + // const QRegularExpressionMatch match = matches.next(); + // if (match.hasMatch()) { + // const QString id = match.captured(1); + // const QString name = match.captured(2); + // + // const int position = match.capturedStart(0) - linkSize; + // const int end = position + name.length(); + // linkSize += match.capturedLength(0) - name.length(); + // + // QTextCursor cursor(documentHandler->document()->textDocument()); + // cursor.setPosition(position); + // cursor.setPosition(end, QTextCursor::KeepAnchor); + // cursor.setKeepPositionOnInsert(true); + // + // m_mentions.push_back(Mention{.cursor = cursor, .text = name, .start = position, .position = end, .id = id}); + // } + // } + // } + // } } QString ChatBarCache::savedText() const @@ -308,37 +309,37 @@ void ChatBarCache::postMessage() return; } - const auto result = ActionsModel::handleAction(room, this); - if (!result.second.has_value()) { - return; - } + // const auto result = ActionsModel::handleAction(room, this); + // if (!result.second.has_value()) { + // return; + // } - TextHandler textHandler; - textHandler.setData(*std::get>(result)); - const auto sendText = textHandler.handleSendText(); - - if (sendText.length() == 0) { - return; - } + // TextHandler textHandler; + // textHandler.setData(*std::get>(result)); + // const auto sendText = textHandler.handleSendText(); + // + // if (sendText.length() == 0) { + // return; + // } bool isReply = !replyId().isEmpty(); - const auto replyIt = room->findInTimeline(replyId()); - if (replyIt == room->historyEdge()) { - isReply = false; - } + // const auto replyIt = room->findInTimeline(replyId()); + // if (replyIt == room->historyEdge()) { + // isReply = false; + // } - auto content = std::make_unique(sendText, u"text/html"_s); - std::optional relatesTo = std::nullopt; + // auto content = std::make_unique(sendText, u"text/html"_s); + // std::optional relatesTo = std::nullopt; + // + // if (!threadId().isEmpty()) { + // relatesTo = Quotient::EventRelation::replyInThread(threadId(), !isReply, isReply ? replyId() : threadId()); + // } else if (!editId().isEmpty()) { + // relatesTo = Quotient::EventRelation::replace(editId()); + // } else if (isReply) { + // relatesTo = Quotient::EventRelation::replyTo(replyId()); + // } - if (!threadId().isEmpty()) { - relatesTo = Quotient::EventRelation::replyInThread(threadId(), !isReply, isReply ? replyId() : threadId()); - } else if (!editId().isEmpty()) { - relatesTo = Quotient::EventRelation::replace(editId()); - } else if (isReply) { - relatesTo = Quotient::EventRelation::replyTo(replyId()); - } - - room->post(text(), *std::get>(result), std::move(content), relatesTo); + // room->post(text(), *std::get>(result), std::move(content), relatesTo); clearCache(); } diff --git a/src/chatbarcache.h b/src/chatbarcache.h index 0924c11ed..e1f3b89ca 100644 --- a/src/chatbarcache.h +++ b/src/chatbarcache.h @@ -8,7 +8,7 @@ #include #include -#include "models/messagecontentmodel.h" +// #include "models/messagecontentmodel.h" class ChatDocumentHandler; @@ -102,7 +102,7 @@ class ChatBarCache : public QObject * * @sa Quotient::RoomMember */ - Q_PROPERTY(Quotient::RoomMember relationAuthor READ relationAuthor NOTIFY relationIdChanged) + // Q_PROPERTY(Quotient::RoomMember relationAuthor READ relationAuthor NOTIFY relationIdChanged) /** * @brief The content of the related message. @@ -116,7 +116,7 @@ class ChatBarCache : public QObject * * Will be nullptr if no related message. */ - Q_PROPERTY(MessageContentModel *relationEventContentModel READ relationEventContentModel NOTIFY relationIdChanged) + // Q_PROPERTY(MessageContentModel *relationEventContentModel READ relationEventContentModel NOTIFY relationIdChanged) /** * @brief Whether the chat bar is replying in a thread. @@ -164,10 +164,10 @@ public: QString editId() const; void setEditId(const QString &editId); - Quotient::RoomMember relationAuthor() const; + // Quotient::RoomMember relationAuthor() const; QString relationMessage() const; - MessageContentModel *relationEventContentModel(); + // MessageContentModel *relationEventContentModel(); bool isThreaded() const; QString threadId() const; @@ -225,7 +225,7 @@ private: QList m_mentions; QString m_savedText; - QPointer m_relationContentModel; + // QPointer m_relationContentModel; void clearCache(); }; diff --git a/src/chatdocumenthandler.cpp b/src/chatdocumenthandler.cpp index 5ff6ab6bf..01546db84 100644 --- a/src/chatdocumenthandler.cpp +++ b/src/chatdocumenthandler.cpp @@ -105,7 +105,7 @@ ChatDocumentHandler::ChatDocumentHandler(QObject *parent) , m_completionModel(new CompletionModel(this)) { connect(this, &ChatDocumentHandler::roomChanged, this, [this]() { - m_completionModel->setRoom(m_room); + // m_completionModel->setRoom(m_room); static QPointer previousRoom = nullptr; if (previousRoom) { disconnect(m_chatBarCache, &ChatBarCache::textChanged, this, nullptr); @@ -113,7 +113,7 @@ ChatDocumentHandler::ChatDocumentHandler(QObject *parent) previousRoom = m_room; connect(m_chatBarCache, &ChatBarCache::textChanged, this, [this]() { int start = completionStartIndex(); - m_completionModel->setText(getText().mid(start, cursorPosition() - start), getText().mid(start)); + // m_completionModel->setText(getText().mid(start, cursorPosition() - start), getText().mid(start)); }); }); connect(this, &ChatDocumentHandler::documentChanged, this, [this]() { @@ -124,7 +124,7 @@ ChatDocumentHandler::ChatDocumentHandler(QObject *parent) return; } int start = completionStartIndex(); - m_completionModel->setText(getText().mid(start, cursorPosition() - start), getText().mid(start)); + // m_completionModel->setText(getText().mid(start, cursorPosition() - start), getText().mid(start)); }); } @@ -217,58 +217,58 @@ void ChatDocumentHandler::complete(int index) qCWarning(ChatDocumentHandling) << "complete called with m_document set to nullptr."; return; } - if (m_completionModel->autoCompletionType() == CompletionModel::None) { - qCWarning(ChatDocumentHandling) << "complete called with m_completionModel->autoCompletionType() == CompletionModel::None."; - return; - } + // if (m_completionModel->autoCompletionType() == CompletionModel::None) { + // qCWarning(ChatDocumentHandling) << "complete called with m_completionModel->autoCompletionType() == CompletionModel::None."; + // return; + // } // Ensure we only search for the beginning of the current completion identifier const auto fromIndex = qMax(completionStartIndex(), 0); - if (m_completionModel->autoCompletionType() == CompletionModel::User) { - auto name = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::DisplayNameRole).toString(); - auto id = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::SubtitleRole).toString(); - auto text = getText(); - auto at = text.indexOf(QLatin1Char('@'), fromIndex); - QTextCursor cursor(document()->textDocument()); - cursor.setPosition(at); - cursor.setPosition(cursorPosition(), QTextCursor::KeepAnchor); - cursor.insertText(name + u" "_s); - cursor.setPosition(at); - cursor.setPosition(cursor.position() + name.size(), QTextCursor::KeepAnchor); - cursor.setKeepPositionOnInsert(true); - pushMention({cursor, name, 0, 0, id}); - m_highlighter->rehighlight(); - } else if (m_completionModel->autoCompletionType() == CompletionModel::Command) { - auto command = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::ReplacedTextRole).toString(); - auto text = getText(); - auto at = text.indexOf(QLatin1Char('/'), fromIndex); - QTextCursor cursor(document()->textDocument()); - cursor.setPosition(at); - cursor.setPosition(cursorPosition(), QTextCursor::KeepAnchor); - cursor.insertText(u"/%1 "_s.arg(command)); - } else if (m_completionModel->autoCompletionType() == CompletionModel::Room) { - auto alias = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::SubtitleRole).toString(); - auto text = getText(); - auto at = text.indexOf(QLatin1Char('#'), fromIndex); - QTextCursor cursor(document()->textDocument()); - cursor.setPosition(at); - cursor.setPosition(cursorPosition(), QTextCursor::KeepAnchor); - cursor.insertText(alias + u" "_s); - cursor.setPosition(at); - cursor.setPosition(cursor.position() + alias.size(), QTextCursor::KeepAnchor); - cursor.setKeepPositionOnInsert(true); - pushMention({cursor, alias, 0, 0, alias}); - m_highlighter->rehighlight(); - } else if (m_completionModel->autoCompletionType() == CompletionModel::Emoji) { - auto shortcode = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::ReplacedTextRole).toString(); - auto text = getText(); - auto at = text.indexOf(QLatin1Char(':'), fromIndex); - QTextCursor cursor(document()->textDocument()); - cursor.setPosition(at); - cursor.setPosition(cursorPosition(), QTextCursor::KeepAnchor); - cursor.insertText(shortcode); - } + // if (m_completionModel->autoCompletionType() == CompletionModel::User) { + // auto name = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::DisplayNameRole).toString(); + // auto id = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::SubtitleRole).toString(); + // auto text = getText(); + // auto at = text.indexOf(QLatin1Char('@'), fromIndex); + // QTextCursor cursor(document()->textDocument()); + // cursor.setPosition(at); + // cursor.setPosition(cursorPosition(), QTextCursor::KeepAnchor); + // cursor.insertText(name + u" "_s); + // cursor.setPosition(at); + // cursor.setPosition(cursor.position() + name.size(), QTextCursor::KeepAnchor); + // cursor.setKeepPositionOnInsert(true); + // pushMention({cursor, name, 0, 0, id}); + // m_highlighter->rehighlight(); + // } else if (m_completionModel->autoCompletionType() == CompletionModel::Command) { + // auto command = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::ReplacedTextRole).toString(); + // auto text = getText(); + // auto at = text.indexOf(QLatin1Char('/'), fromIndex); + // QTextCursor cursor(document()->textDocument()); + // cursor.setPosition(at); + // cursor.setPosition(cursorPosition(), QTextCursor::KeepAnchor); + // cursor.insertText(u"/%1 "_s.arg(command)); + // } else if (m_completionModel->autoCompletionType() == CompletionModel::Room) { + // auto alias = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::SubtitleRole).toString(); + // auto text = getText(); + // auto at = text.indexOf(QLatin1Char('#'), fromIndex); + // QTextCursor cursor(document()->textDocument()); + // cursor.setPosition(at); + // cursor.setPosition(cursorPosition(), QTextCursor::KeepAnchor); + // cursor.insertText(alias + u" "_s); + // cursor.setPosition(at); + // cursor.setPosition(cursor.position() + alias.size(), QTextCursor::KeepAnchor); + // cursor.setKeepPositionOnInsert(true); + // pushMention({cursor, alias, 0, 0, alias}); + // m_highlighter->rehighlight(); + // } else if (m_completionModel->autoCompletionType() == CompletionModel::Emoji) { + // auto shortcode = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::ReplacedTextRole).toString(); + // auto text = getText(); + // auto at = text.indexOf(QLatin1Char(':'), fromIndex); + // QTextCursor cursor(document()->textDocument()); + // cursor.setPosition(at); + // cursor.setPosition(cursorPosition(), QTextCursor::KeepAnchor); + // cursor.insertText(shortcode); + // } } CompletionModel *ChatDocumentHandler::completionModel() const diff --git a/src/controller.cpp b/src/controller.cpp index 2a4dd5058..73ae68326 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -8,19 +8,16 @@ #include +#include #include #include #include -#include -#include -#include - #include "neochatconfig.h" #include "neochatconnection.h" -#include "neochatroom.h" -#include "notificationsmanager.h" +// #include "neochatroom.h" +// #include "notificationsmanager.h" #include "proxycontroller.h" #if defined(Q_OS_WIN) || defined(Q_OS_MAC) @@ -43,12 +40,13 @@ bool testMode = false; -using namespace Quotient; +using namespace Integral; +using namespace Qt::Literals::StringLiterals; Controller::Controller(QObject *parent) : QObject(parent) { - Connection::setRoomType(); + // Connection::setRoomType(); ProxyController::instance().setApplicationProxy(); @@ -57,18 +55,18 @@ Controller::Controller(QObject *parent) connect(NeoChatConfig::self(), &NeoChatConfig::SystemTrayChanged, this, &Controller::setQuitOnLastWindowClosed); #endif - if (!testMode) { - QTimer::singleShot(0, this, [this] { - invokeLogin(); - }); - } else { - auto c = new NeoChatConnection(this); - c->assumeIdentity(u"@user:localhost:1234"_s, u"device_1234"_s, u"token_1234"_s); - connect(c, &Connection::connected, this, [c, this]() { - m_accountRegistry.add(c); - c->syncLoop(); - }); - } + // if (!testMode) { + // QTimer::singleShot(0, this, [this] { + // invokeLogin(); + // }); + // } else { + // auto c = new NeoChatConnection(this); + // c->assumeIdentity(u"@user:localhost:1234"_s, u"device_1234"_s, u"token_1234"_s); + // connect(c, &Connection::connected, this, [c, this]() { + // m_accountRegistry.add(c); + // c->syncLoop(); + // }); + // } QObject::connect(QGuiApplication::instance(), &QCoreApplication::aboutToQuit, QGuiApplication::instance(), [this] { delete m_trayIcon; @@ -99,31 +97,31 @@ Controller::Controller(QObject *parent) #endif static int oldAccountCount = 0; - connect(&m_accountRegistry, &AccountRegistry::accountCountChanged, this, [this]() { - if (m_accountRegistry.size() > oldAccountCount) { - auto connection = dynamic_cast(m_accountRegistry.accounts()[m_accountRegistry.size() - 1]); - connect( - connection, - &NeoChatConnection::syncDone, - this, - [this, connection] { - if (!m_endpoint.isEmpty()) { - connection->setupPushNotifications(m_endpoint); - } - }, - Qt::SingleShotConnection); - } - oldAccountCount = m_accountRegistry.size(); - }); + // connect(&m_accountRegistry, &AccountRegistry::accountCountChanged, this, [this]() { + // if (m_accountRegistry.size() > oldAccountCount) { + // auto connection = dynamic_cast(m_accountRegistry.accounts()[m_accountRegistry.size() - 1]); + // connect( + // connection, + // &NeoChatConnection::syncDone, + // this, + // [this, connection] { + // if (!m_endpoint.isEmpty()) { + // connection->setupPushNotifications(m_endpoint); + // } + // }, + // Qt::SingleShotConnection); + // } + // oldAccountCount = m_accountRegistry.size(); + // }); #ifdef HAVE_KUNIFIEDPUSH auto connector = new KUnifiedPush::Connector(u"org.kde.neochat"_s); connect(connector, &KUnifiedPush::Connector::endpointChanged, this, [this](const QString &endpoint) { m_endpoint = endpoint; - for (auto "ientConnection : m_accountRegistry) { - auto connection = dynamic_cast(quotientConnection); - connection->setupPushNotifications(endpoint); - } + // for (auto "ientConnection : m_accountRegistry) { + // auto connection = dynamic_cast(quotientConnection); + // connection->setupPushNotifications(endpoint); + // } }); connector->registerClient( @@ -140,147 +138,6 @@ Controller &Controller::instance() return _instance; } -void Controller::addConnection(NeoChatConnection *c) -{ - Q_ASSERT_X(c, __FUNCTION__, "Attempt to add a null connection"); - - m_accountRegistry.add(c); - - c->setLazyLoading(true); - - connect(c, &NeoChatConnection::syncDone, this, [c] { - c->sync(30000); - c->saveState(); - }); - connect(c, &NeoChatConnection::loggedOut, this, [this, c] { - if (accounts().count() > 1) { - // Only set the connection if the account being logged out is currently active - if (c == activeConnection()) { - setActiveConnection(dynamic_cast(accounts().accounts()[0])); - } - } else { - setActiveConnection(nullptr); - } - - dropConnection(c); - }); - connect(c, &NeoChatConnection::badgeNotificationCountChanged, this, &Controller::updateBadgeNotificationCount); - connect(c, &NeoChatConnection::syncDone, this, [this, c]() { - m_notificationsManager.handleNotifications(c); - }); - - c->sync(); - - Q_EMIT connectionAdded(c); -} - -void Controller::dropConnection(NeoChatConnection *c) -{ - Q_ASSERT_X(c, __FUNCTION__, "Attempt to drop a null connection"); - - c->disconnect(this); - c->disconnect(&m_notificationsManager); - m_accountRegistry.drop(c); - Q_EMIT connectionDropped(c); -} - -void Controller::invokeLogin() -{ - const auto accounts = SettingsGroup("Accounts"_L1).childGroups(); - for (const auto &accountId : accounts) { - AccountSettings account{accountId}; - m_accountsLoading += accountId; - Q_EMIT accountsLoadingChanged(); - if (!account.homeserver().isEmpty()) { - auto accessTokenLoadingJob = loadAccessTokenFromKeyChain(account.userId()); - connect(accessTokenLoadingJob, &QKeychain::Job::finished, this, [accountId, this, accessTokenLoadingJob](QKeychain::Job *) { - AccountSettings account{accountId}; - QString accessToken; - if (accessTokenLoadingJob->error() == QKeychain::Error::NoError) { - accessToken = QString::fromLatin1(accessTokenLoadingJob->binaryData()); - } else { - return; - } - - auto connection = new NeoChatConnection(account.homeserver()); - m_connectionsLoading[accountId] = connection; - connect(connection, &NeoChatConnection::connected, this, [this, connection, accountId] { - connection->loadState(); - if (connection->allRooms().size() == 0 || connection->allRooms()[0]->currentState().get()) { - addConnection(connection); - m_accountsLoading.removeAll(connection->userId()); - m_connectionsLoading.remove(accountId); - Q_EMIT accountsLoadingChanged(); - } else { - connect( - connection->allRooms()[0], - &Room::baseStateLoaded, - this, - [this, connection, accountId]() { - addConnection(connection); - m_accountsLoading.removeAll(connection->userId()); - m_connectionsLoading.remove(accountId); - Q_EMIT accountsLoadingChanged(); - }, - Qt::SingleShotConnection); - } - }); - connection->assumeIdentity(account.userId(), account.deviceId(), accessToken); - }); - } - } -} - -QKeychain::ReadPasswordJob *Controller::loadAccessTokenFromKeyChain(const QString &userId) -{ - qDebug() << "Reading access token from the keychain for" << userId; - auto job = new QKeychain::ReadPasswordJob(qAppName(), this); - job->setKey(userId); - - // Handling of errors - connect(job, &QKeychain::Job::finished, this, [this, job]() { - if (job->error() == QKeychain::Error::NoError) { - return; - } - - switch (job->error()) { - case QKeychain::EntryNotFound: - Q_EMIT errorOccured(i18n("Access token wasn't found: Maybe it was deleted?")); - break; - case QKeychain::AccessDeniedByUser: - case QKeychain::AccessDenied: - Q_EMIT errorOccured(i18n("Access to keychain was denied: Please allow NeoChat to read the access token")); - break; - case QKeychain::NoBackendAvailable: - Q_EMIT errorOccured(i18n("No keychain available: Please install a keychain, e.g. KWallet or GNOME keyring on Linux")); - break; - case QKeychain::OtherError: - Q_EMIT errorOccured(i18n("Unable to read access token: %1", job->errorString())); - break; - default: - break; - } - }); - job->start(); - - return job; -} - -void Controller::saveAccessTokenToKeyChain(const QString &userId, const QByteArray &accessToken) -{ - qDebug() << "Save the access token to the keychain for " << userId; - auto job = new QKeychain::WritePasswordJob(qAppName()); - job->setAutoDelete(true); - job->setKey(userId); - job->setBinaryData(accessToken); - connect(job, &QKeychain::WritePasswordJob::finished, this, [job]() { - if (job->error()) { - qWarning() << "Could not save access token to the keychain: " << qPrintable(job->errorString()); - } - }); - job->start(); -} - bool Controller::supportSystemTray() const { #ifdef Q_OS_ANDROID @@ -322,7 +179,7 @@ void Controller::setActiveConnection(NeoChatConnection *connection) if (m_connection != nullptr) { m_connection->disconnect(this); - m_connection->disconnect(&m_notificationsManager); + // m_connection->disconnect(&m_notificationsManager); } m_connection = connection; @@ -331,7 +188,7 @@ void Controller::setActiveConnection(NeoChatConnection *connection) m_connection->refreshBadgeNotificationCount(); updateBadgeNotificationCount(m_connection, m_connection->badgeNotificationCount()); - connect(m_connection, &NeoChatConnection::errorOccured, this, &Controller::errorOccured); + // connect(m_connection, &NeoChatConnection::errorOccured, this, &Controller::errorOccured); } Q_EMIT activeConnectionChanged(m_connection); @@ -346,7 +203,7 @@ void Controller::listenForNotifications() connect(timer, &QTimer::timeout, qGuiApp, &QGuiApplication::quit); connect(connector, &KUnifiedPush::Connector::messageReceived, [timer](const QByteArray &data) { - instance().m_notificationsManager.postPushNotification(data); + // instance().m_notificationsManager.postPushNotification(data); timer->stop(); }); @@ -360,7 +217,7 @@ void Controller::listenForNotifications() void Controller::clearInvitationNotification(const QString &roomId) { - m_notificationsManager.clearInvitationNotification(roomId); + // m_notificationsManager.clearInvitationNotification(roomId); } void Controller::updateBadgeNotificationCount(NeoChatConnection *connection, int count) @@ -402,9 +259,9 @@ bool Controller::isFlatpak() const #endif } -AccountRegistry &Controller::accounts() +Accounts &Controller::accounts() { - return m_accountRegistry; + return m_accounts; } QString Controller::loadFileContent(const QString &path) const @@ -420,20 +277,6 @@ void Controller::setTestMode(bool test) testMode = test; } -void Controller::removeConnection(const QString &userId) -{ - // When loadAccessTokenFromKeyChain() fails m_connectionsLoading won't have an - // entry for it so we need to check both separately. - if (m_accountsLoading.contains(userId)) { - m_accountsLoading.removeAll(userId); - Q_EMIT accountsLoadingChanged(); - } - if (m_connectionsLoading.contains(userId) && m_connectionsLoading[userId]) { - auto connection = m_connectionsLoading[userId]; - SettingsGroup("Accounts"_L1).remove(userId); - } -} - bool Controller::csSupported() const { return true; diff --git a/src/controller.h b/src/controller.h index 21e7b1d27..db4eeb15e 100644 --- a/src/controller.h +++ b/src/controller.h @@ -7,8 +7,8 @@ #include #include "neochatconnection.h" -#include "notificationsmanager.h" -#include +// #include "notificationsmanager.h" +#include class TrayIcon; @@ -63,21 +63,6 @@ public: void setActiveConnection(NeoChatConnection *connection); [[nodiscard]] NeoChatConnection *activeConnection() const; - /** - * @brief Add a new connection to the account registry. - */ - void addConnection(NeoChatConnection *c); - - /** - * @brief Drop a connection from the account registry. - */ - void dropConnection(NeoChatConnection *c); - - /** - * @brief Save an access token to the keychain for the given account. - */ - void saveAccessTokenToKeyChain(const QString &userId, const QByteArray &accessToken); - [[nodiscard]] bool supportSystemTray() const; bool isFlatpak() const; @@ -97,12 +82,10 @@ public: Q_INVOKABLE QString loadFileContent(const QString &path) const; - Quotient::AccountRegistry &accounts(); + Integral::Accounts &accounts(); static void setTestMode(bool testMode); - Q_INVOKABLE void removeConnection(const QString &userId); - bool csSupported() const; /** @@ -122,18 +105,15 @@ private: QPointer m_connection; TrayIcon *m_trayIcon = nullptr; - QKeychain::ReadPasswordJob *loadAccessTokenFromKeyChain(const QString &account); - - Quotient::AccountRegistry m_accountRegistry; + Integral::Accounts m_accounts; QStringList m_accountsLoading; QMap> m_connectionsLoading; QString m_endpoint; QStringList m_shownImages; - NotificationsManager m_notificationsManager; + // NotificationsManager m_notificationsManager; private Q_SLOTS: - void invokeLogin(); void setQuitOnLastWindowClosed(); void updateBadgeNotificationCount(NeoChatConnection *connection, int count); diff --git a/src/enums/neochatroomtype.h b/src/enums/neochatroomtype.h index c96320376..a3ea8d10c 100644 --- a/src/enums/neochatroomtype.h +++ b/src/enums/neochatroomtype.h @@ -4,12 +4,12 @@ #pragma once #include - -#include "neochatroom.h" -#include +#include #include +#include + using namespace Qt::StringLiterals; class NeoChatRoomType : public QObject @@ -22,7 +22,7 @@ public: /** * @brief Defines the room list categories a room can be assigned. */ - enum Types { + enum Type { Invited, /**< The user has been invited to the room. */ Favorite, /**< The room is set as a favourite. */ Direct, /**< The room is a direct chat. */ @@ -32,23 +32,23 @@ public: AddDirect, /**< So we can show the add friend delegate. */ TypesCount, /**< Number of different types (this should always be last). */ }; - Q_ENUM(Types); + Q_ENUM(Type); - static NeoChatRoomType::Types typeForRoom(const NeoChatRoom *room) + static NeoChatRoomType::Type typeForRoom(rust::Box room) { - if (room->isSpace()) { + if (room->is_space()) { return NeoChatRoomType::Space; } - if (room->joinState() == Quotient::JoinState::Invite) { + if (room->state() == 2) { return NeoChatRoomType::Invited; } - if (room->isFavourite()) { + if (room->is_favourite()) { return NeoChatRoomType::Favorite; } - if (room->isLowPriority()) { + if (room->is_low_priority()) { return NeoChatRoomType::Deprioritized; } - if (room->isDirectChat()) { + if (false /*room->isDirectChat()*/) { return NeoChatRoomType::Direct; } return NeoChatRoomType::Normal; diff --git a/src/enums/roomsortparameter.cpp b/src/enums/roomsortparameter.cpp index 609c02e23..daab80c7a 100644 --- a/src/enums/roomsortparameter.cpp +++ b/src/enums/roomsortparameter.cpp @@ -1,3 +1,4 @@ + // SPDX-FileCopyrightText: 2024 James Graham // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL @@ -5,8 +6,8 @@ #include -#include "neochatconfig.h" -#include "neochatroom.h" +// #include "neochatconfig.h" +#include namespace { @@ -56,27 +57,27 @@ QList RoomSortParameter::allParameterList() QList RoomSortParameter::currentParameterList() { - QList configParamList; - switch (static_cast(NeoChatConfig::sortOrder())) { - case NeoChatConfig::EnumSortOrder::Activity: - configParamList = activitySortPriorities; - break; - case NeoChatConfig::EnumSortOrder::Alphabetical: - configParamList = alphabeticalSortPriorities; - break; - case NeoChatConfig::EnumSortOrder::LastMessage: - configParamList = lastMessageSortPriorities; - break; - case NeoChatConfig::EnumSortOrder::Custom: { - const auto intList = NeoChatConfig::customSortOrder(); - std::transform(intList.constBegin(), intList.constEnd(), std::back_inserter(configParamList), [](int param) { - return static_cast(param); - }); - break; - } - default: - break; - } + QList configParamList = activitySortPriorities; + // switch (static_cast(NeoChatConfig::sortOrder())) { + // case NeoChatConfig::EnumSortOrder::Activity: + // configParamList = activitySortPriorities; + // break; + // case NeoChatConfig::EnumSortOrder::Alphabetical: + // configParamList = alphabeticalSortPriorities; + // break; + // case NeoChatConfig::EnumSortOrder::LastMessage: + // configParamList = lastMessageSortPriorities; + // break; + // case NeoChatConfig::EnumSortOrder::Custom: { + // const auto intList = NeoChatConfig::customSortOrder(); + // std::transform(intList.constBegin(), intList.constEnd(), std::back_inserter(configParamList), [](int param) { + // return static_cast(param); + // }); + // break; + // } + // default: + // break; + // } if (configParamList.isEmpty()) { return activitySortPriorities; @@ -90,73 +91,74 @@ void RoomSortParameter::saveNewParameterList(const QList &newList) std::transform(newList.constBegin(), newList.constEnd(), std::back_inserter(intList), [](Parameter param) { return static_cast(param); }); - NeoChatConfig::setCustomSortOrder(intList); - NeoChatConfig::setSortOrder(NeoChatConfig::EnumSortOrder::Custom); - NeoChatConfig::self()->save(); + // NeoChatConfig::setCustomSortOrder(intList); + // NeoChatConfig::setSortOrder(NeoChatConfig::EnumSortOrder::Custom); + // NeoChatConfig::self()->save(); } -int RoomSortParameter::compareParameter(Parameter parameter, NeoChatRoom *leftRoom, NeoChatRoom *rightRoom) +int RoomSortParameter::compareParameter(Parameter parameter, rust::Box leftRoom, rust::Box rightRoom) { switch (parameter) { case AlphabeticalAscending: - return compareParameter(leftRoom, rightRoom); + return compareParameter(leftRoom->box_me(), rightRoom->box_me()); case AlphabeticalDescending: - return compareParameter(leftRoom, rightRoom); + return compareParameter(leftRoom->box_me(), rightRoom->box_me()); case HasUnread: - return compareParameter(leftRoom, rightRoom); + return compareParameter(leftRoom->box_me(), rightRoom->box_me()); case MostUnread: - return compareParameter(leftRoom, rightRoom); + return compareParameter(leftRoom->box_me(), rightRoom->box_me()); case HasHighlight: - return compareParameter(leftRoom, rightRoom); + return compareParameter(leftRoom->box_me(), rightRoom->box_me()); case MostHighlights: - return compareParameter(leftRoom, rightRoom); + return compareParameter(leftRoom->box_me(), rightRoom->box_me()); case LastActive: - return compareParameter(leftRoom, rightRoom); + return compareParameter(leftRoom->box_me(), rightRoom->box_me()); default: return 0; } } template<> -int RoomSortParameter::compareParameter(NeoChatRoom *leftRoom, NeoChatRoom *rightRoom) +int RoomSortParameter::compareParameter(rust::Box leftRoom, rust::Box rightRoom) { - return -typeCompare(leftRoom->displayName(), rightRoom->displayName()); + return -typeCompare(stringFromRust(leftRoom->display_name()), stringFromRust(rightRoom->display_name())); } template<> -int RoomSortParameter::compareParameter(NeoChatRoom *leftRoom, NeoChatRoom *rightRoom) +int RoomSortParameter::compareParameter(rust::Box leftRoom, + rust::Box rightRoom) { - return typeCompare(leftRoom->displayName(), rightRoom->displayName()); + return typeCompare(stringFromRust(leftRoom->display_name()), stringFromRust(rightRoom->display_name())); } template<> -int RoomSortParameter::compareParameter(NeoChatRoom *leftRoom, NeoChatRoom *rightRoom) +int RoomSortParameter::compareParameter(rust::Box leftRoom, rust::Box rightRoom) { - return typeCompare(leftRoom->contextAwareNotificationCount() > 0, rightRoom->contextAwareNotificationCount() > 0); + return typeCompare(leftRoom->num_unread_messages() > 0, rightRoom->num_unread_messages() > 0); } template<> -int RoomSortParameter::compareParameter(NeoChatRoom *leftRoom, NeoChatRoom *rightRoom) +int RoomSortParameter::compareParameter(rust::Box leftRoom, rust::Box rightRoom) { - return typeCompare(leftRoom->contextAwareNotificationCount(), rightRoom->contextAwareNotificationCount()); + return typeCompare(leftRoom->num_unread_messages(), rightRoom->num_unread_messages()); } template<> -int RoomSortParameter::compareParameter(NeoChatRoom *leftRoom, NeoChatRoom *rightRoom) +int RoomSortParameter::compareParameter(rust::Box leftRoom, rust::Box rightRoom) { - const auto leftHighlight = leftRoom->highlightCount() > 0 && leftRoom->contextAwareNotificationCount() > 0; - const auto rightHighlight = rightRoom->highlightCount() > 0 && rightRoom->contextAwareNotificationCount() > 0; + const auto leftHighlight = leftRoom->num_unread_mentions() > 0 && leftRoom->num_unread_messages() > 0; + const auto rightHighlight = rightRoom->num_unread_mentions() > 0 && rightRoom->num_unread_messages() > 0; return typeCompare(leftHighlight, rightHighlight); } template<> -int RoomSortParameter::compareParameter(NeoChatRoom *leftRoom, NeoChatRoom *rightRoom) +int RoomSortParameter::compareParameter(rust::Box leftRoom, rust::Box rightRoom) { - return typeCompare(int(leftRoom->highlightCount()), int(rightRoom->highlightCount())); + return typeCompare(int(leftRoom->num_unread_mentions()), int(rightRoom->num_unread_mentions())); } template<> -int RoomSortParameter::compareParameter(NeoChatRoom *leftRoom, NeoChatRoom *rightRoom) +int RoomSortParameter::compareParameter(rust::Box leftRoom, rust::Box rightRoom) { - return typeCompare(leftRoom->lastActiveTime(), rightRoom->lastActiveTime()); + return 1; } diff --git a/src/enums/roomsortparameter.h b/src/enums/roomsortparameter.h index b60ab75fc..344ab76d3 100644 --- a/src/enums/roomsortparameter.h +++ b/src/enums/roomsortparameter.h @@ -8,7 +8,9 @@ #include -class NeoChatRoom; +#include + +class Room; /** * @class RoomSortParameter @@ -116,27 +118,29 @@ public: * * @sa Parameter */ - static int compareParameter(Parameter parameter, NeoChatRoom *leftRoom, NeoChatRoom *rightRoom); + static int compareParameter(Parameter parameter, rust::Box leftRoom, rust::Box rightRoom); private: template - static int compareParameter(NeoChatRoom *, NeoChatRoom *) + static int compareParameter(rust::Box, rust::Box) { return false; } }; template<> -int RoomSortParameter::compareParameter(NeoChatRoom *leftRoom, NeoChatRoom *rightRoom); +int RoomSortParameter::compareParameter(rust::Box leftRoom, + rust::Box rightRoom); template<> -int RoomSortParameter::compareParameter(NeoChatRoom *leftRoom, NeoChatRoom *rightRoom); +int RoomSortParameter::compareParameter(rust::Box leftRoom, + rust::Box rightRoom); template<> -int RoomSortParameter::compareParameter(NeoChatRoom *leftRoom, NeoChatRoom *rightRoom); +int RoomSortParameter::compareParameter(rust::Box leftRoom, rust::Box rightRoom); template<> -int RoomSortParameter::compareParameter(NeoChatRoom *leftRoom, NeoChatRoom *rightRoom); +int RoomSortParameter::compareParameter(rust::Box leftRoom, rust::Box rightRoom); template<> -int RoomSortParameter::compareParameter(NeoChatRoom *leftRoom, NeoChatRoom *rightRoom); +int RoomSortParameter::compareParameter(rust::Box leftRoom, rust::Box rightRoom); template<> -int RoomSortParameter::compareParameter(NeoChatRoom *leftRoom, NeoChatRoom *rightRoom); +int RoomSortParameter::compareParameter(rust::Box leftRoom, rust::Box rightRoom); template<> -int RoomSortParameter::compareParameter(NeoChatRoom *leftRoom, NeoChatRoom *rightRoom); +int RoomSortParameter::compareParameter(rust::Box leftRoom, rust::Box rightRoom); diff --git a/src/foreigntypes.h b/src/foreigntypes.h index ecc625795..2119eb5d2 100644 --- a/src/foreigntypes.h +++ b/src/foreigntypes.h @@ -5,44 +5,36 @@ #include -#include -#include -#include -#include -#include +#include +#include #include "controller.h" #include "neochatconfig.h" -struct ForeignAccountRegistry { +struct ForeignAccounts { Q_GADGET - QML_FOREIGN(Quotient::AccountRegistry) - QML_NAMED_ELEMENT(AccountRegistry) + QML_ELEMENT QML_SINGLETON -public: - static Quotient::AccountRegistry *create(QQmlEngine *, QJSEngine *) + QML_FOREIGN(Integral::Accounts) + QML_NAMED_ELEMENT(Accounts) + static Integral::Accounts *create(QQmlEngine *, QJSEngine *) { - QQmlEngine::setObjectOwnership(&Controller::instance().accounts(), QQmlEngine::CppOwnership); - return &Controller::instance().accounts(); + auto &accounts = Controller::instance().accounts(); + QQmlEngine::setObjectOwnership(&accounts, QQmlEngine::CppOwnership); + return &accounts; } }; -struct ForeignKeyVerificationSession { +struct ForeignHomeserver { Q_GADGET - QML_FOREIGN(Quotient::KeyVerificationSession) - QML_NAMED_ELEMENT(KeyVerificationSession) - QML_UNCREATABLE("") + QML_ELEMENT + QML_FOREIGN(Integral::Homeserver) + QML_NAMED_ELEMENT(Homeserver) }; -struct ForeignSSSSHandler { +struct ForeignConnection { Q_GADGET - QML_FOREIGN(Quotient::SSSSHandler) - QML_NAMED_ELEMENT(SSSSHandler) -}; - -struct ForeignKeyImport { - Q_GADGET - QML_SINGLETON - QML_FOREIGN(Quotient::KeyImport) - QML_NAMED_ELEMENT(KeyImport) + QML_ELEMENT + QML_FOREIGN(Integral::Connection) + QML_NAMED_ELEMENT(Connection) }; diff --git a/src/login/Login.qml b/src/login/Login.qml index 081c03f35..2f2c42ed6 100644 --- a/src/login/Login.qml +++ b/src/login/Login.qml @@ -16,8 +16,15 @@ LoginStep { onActiveFocusChanged: if (activeFocus) matrixIdField.forceActiveFocus() - Component.onCompleted: { - LoginHelper.matrixId = ""; + property Homeserver homeserver + + Timer { + id: timer + interval: 500 + repeat: false + onTriggered: if (matrixIdField.text.length > 0) { + root.homeserver.resolveFromMatrixId(matrixIdField.text) + } } FormCard.FormTextFieldDelegate { @@ -26,7 +33,7 @@ LoginStep { placeholderText: "@user:example.org" Accessible.name: i18n("Matrix ID") onTextChanged: { - LoginHelper.matrixId = text; + timer.restart() } Keys.onReturnPressed: { @@ -35,17 +42,17 @@ LoginStep { } nextAction: Kirigami.Action { - text: LoginHelper.isLoggedIn ? i18n("Already logged in") : (LoginHelper.testing && matrixIdField.acceptableInput) ? i18n("Loading…") : i18nc("@action:button", "Continue") + // text: LoginHelper.isLoggedIn ? i18n("Already logged in") : (LoginHelper.testing && matrixIdField.acceptableInput) ? i18n("Loading…") : i18nc("@action:button", "Continue") onTriggered: { - if (LoginHelper.supportsSso && LoginHelper.supportsPassword) { + if (root.homeserver.ssoLoginSupported && root.homeserver.passwordLoginSupported) { processed("LoginMethod"); - } else if (LoginHelper.supportsSso) { + } else if (root.homeserver.ssoLoginSupported) { processed("Sso"); } else { processed("Password"); } } - enabled: LoginHelper.homeserverReachable + enabled: root.homeserver.loginFlowsLoaded } previousAction: Kirigami.Action { onTriggered: { diff --git a/src/login/Password.qml b/src/login/Password.qml index 9bc9262ab..b1acccf1b 100644 --- a/src/login/Password.qml +++ b/src/login/Password.qml @@ -12,6 +12,8 @@ import org.kde.neochat LoginStep { id: root + property Homeserver homeserver + Connections { target: LoginHelper function onConnected() { @@ -26,7 +28,6 @@ LoginStep { id: passwordField label: i18n("Password:") - onTextChanged: LoginHelper.password = text enabled: !LoginHelper.isLoggingIn echoMode: TextInput.Password Accessible.name: i18n("Password") @@ -39,10 +40,10 @@ LoginStep { nextAction: Kirigami.Action { text: i18nc("@action:button", "Login") - enabled: passwordField.text.length > 0 && !LoginHelper.isLoggingIn + // enabled: passwordField.text.length > 0 && !LoginHelper.isLoggingIn onTriggered: { root.clearError(); - LoginHelper.login(); + let pending = Accounts.loginWithPassword(root.homeserver.matrixId, passwordField.text) } } previousAction: Kirigami.Action { diff --git a/src/login/WelcomePage.qml b/src/login/WelcomePage.qml index 2d3481a09..4dd4b7de3 100644 --- a/src/login/WelcomePage.qml +++ b/src/login/WelcomePage.qml @@ -27,6 +27,10 @@ Kirigami.Page { title: i18n("Welcome") globalToolBarStyle: Kirigami.ApplicationHeaderStyle.None + Homeserver { + id: homeserver + } + header: QQC2.Control { topPadding: 0 bottomPadding: 0 @@ -81,7 +85,7 @@ Kirigami.Page { FormCard.FormHeader { id: existingAccountsHeader title: i18nc("@title", "Continue with an existing account") - visible: (loadedAccounts.count > 0 || loadingAccounts.count > 0) && root._showExisting + // visible: (loadedAccounts.count > 0 || loadingAccounts.count > 0) && root._showExisting maximumWidth: Kirigami.Units.gridUnit * 20 } @@ -90,15 +94,21 @@ Kirigami.Page { maximumWidth: Kirigami.Units.gridUnit * 20 Repeater { id: loadedAccounts - model: AccountRegistry + model: Accounts delegate: FormCard.FormButtonDelegate { id: delegate - required property string userId - required property NeoChatConnection connection + required property string matrixId + required property string displayName + required property string avatarUrl + required property int index + required property bool ready + required property Connection connection - text: QmlUtils.escapeString(connection.localUser.displayName) - description: connection.localUser.id + enabled: ready + + text: QmlUtils.escapeString(delegate.displayName) + description: delegate.matrixId leadingPadding: Kirigami.Units.largeSpacing onClicked: { @@ -109,62 +119,12 @@ Kirigami.Page { id: avatar name: delegate.text // Note: User::avatarUrl does not set user_id, and thus cannot be used directly here. Hence the makeMediaUrl. - source: delegate.connection.localUser.avatarUrl.toString().length > 0 ? delegate.connection.makeMediaUrl(delegate.connection.localUser.avatarUrl) : "" + source: delegate.avatarUrl implicitWidth: Kirigami.Units.iconSizes.medium implicitHeight: Kirigami.Units.iconSizes.medium } } } - Repeater { - id: loadingAccounts - model: Controller.accountsLoading - delegate: FormCard.AbstractFormDelegate { - id: loadingDelegate - - topPadding: Kirigami.Units.smallSpacing - bottomPadding: Kirigami.Units.smallSpacing - - background: null - contentItem: RowLayout { - spacing: 0 - - QQC2.Label { - Layout.fillWidth: true - text: i18nc("As in 'this account is still loading'", "%1 (loading)", modelData) - elide: Text.ElideRight - wrapMode: Text.Wrap - maximumLineCount: 2 - color: Kirigami.Theme.disabledTextColor - Accessible.ignored: true // base class sets this text on root already - } - - QQC2.ToolButton { - text: i18nc("@action:button", "Log out of this account") - icon.name: "im-kick-user" - onClicked: Controller.removeConnection(modelData) - display: QQC2.Button.IconOnly - QQC2.ToolTip.text: text - QQC2.ToolTip.visible: hovered - QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay - enabled: true - Layout.preferredHeight: Kirigami.Units.gridUnit * 2 - } - - FormCard.FormArrow { - Layout.leftMargin: Kirigami.Units.smallSpacing - Layout.alignment: Qt.AlignRight | Qt.AlignVCenter - direction: Qt.RightArrow - visible: root.background.visible - } - } - } - onCountChanged: { - if (loadingAccounts.count === 0 && loadedAccounts.count === 1 && showExisting) { - Controller.activeConnection = AccountRegistry.data(AccountRegistry.index(0, 0), 257); - root.connectionChosen(); - } - } - } } FormCard.FormHeader { @@ -188,6 +148,7 @@ Kirigami.Page { root.currentStepString = nextStep; headerMessage.text = ""; headerMessage.visible = false; + module.item.homeserver = homeserver if (!module.item.noControls) { module.item.forceActiveFocus(); } else { @@ -211,33 +172,33 @@ Kirigami.Page { } } - Connections { - target: Registration - - function onNextStepChanged() { - if (Registration.nextStep === "m.login.recaptcha") { - stepConnections.onProcessed("Captcha"); - } - if (Registration.nextStep === "m.login.terms") { - stepConnections.onProcessed("Terms"); - } - if (Registration.nextStep === "m.login.email.identity") { - stepConnections.onProcessed("Email"); - } - if (Registration.nextStep === "loading") { - stepConnections.onProcessed("Loading"); - } - } - } - Connections { - target: LoginHelper - - function onLoginErrorOccured(message) { - headerMessage.text = message; - headerMessage.visible = message.length > 0; - headerMessage.type = Kirigami.MessageType.Error; - } - } + // Connections { + // target: Registration + // + // function onNextStepChanged() { + // if (Registration.nextStep === "m.login.recaptcha") { + // stepConnections.onProcessed("Captcha"); + // } + // if (Registration.nextStep === "m.login.terms") { + // stepConnections.onProcessed("Terms"); + // } + // if (Registration.nextStep === "m.login.email.identity") { + // stepConnections.onProcessed("Email"); + // } + // if (Registration.nextStep === "loading") { + // stepConnections.onProcessed("Loading"); + // } + // } + // } + // Connections { + // target: LoginHelper + // + // function onLoginErrorOccured(message) { + // headerMessage.text = message; + // headerMessage.visible = message.length > 0; + // headerMessage.type = Kirigami.MessageType.Error; + // } + // } } FormCard.FormDelegateSeparator { @@ -276,11 +237,11 @@ Kirigami.Page { } } - Component.onCompleted: { - LoginHelper.init(); - module.item.forceActiveFocus(); - Registration.username = ""; - Registration.password = ""; - Registration.email = ""; - } + // Component.onCompleted: { + // LoginHelper.init(); + // module.item.forceActiveFocus(); + // Registration.username = ""; + // Registration.password = ""; + // Registration.email = ""; + // } } diff --git a/src/main.cpp b/src/main.cpp index d40e16f94..30fc25d49 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,7 +13,12 @@ #include #include #include -#include + +#include +#include +#include + +// #include #ifdef Q_OS_ANDROID #include @@ -43,31 +48,35 @@ #include "neochat-version.h" -#include +// #include #include "blurhashimageprovider.h" #include "colorschemer.h" -#include "controller.h" +// #include "controller.h" #include "logger.h" -#include "roommanager.h" -#include "sharehandler.h" +// #include "roommanager.h" +// #include "sharehandler.h" +#include "neochatconnection.h" +#include "neochatroom.h" #include "windowcontroller.h" #ifdef HAVE_RUNNER -#include "runner.h" +// #include "runner.h" #include #include #endif #if defined(HAVE_RUNNER) && defined(HAVE_KUNIFIEDPUSH) -#include "fakerunner.h" +// #include "fakerunner.h" #endif #ifdef Q_OS_WINDOWS #include #endif -using namespace Quotient; +using namespace Qt::Literals::StringLiterals; + +using namespace Integral; void qml_register_types_org_kde_neochat(); @@ -158,14 +167,14 @@ int main(int argc, char *argv[]) about.setTranslator(i18nc("NAME OF TRANSLATORS", "Your names"), i18nc("EMAIL OF TRANSLATORS", "Your emails")); about.setOrganizationDomain("kde.org"); - about.addComponent(u"libQuotient"_s, - i18n("A Qt library to write cross-platform clients for Matrix"), - i18nc(" (built against )", - "%1 (built against %2)", - Quotient::versionString(), - QStringLiteral(Quotient_VERSION_STRING)), - u"https://github.com/quotient-im/libquotient"_s, - KAboutLicense::LGPL_V2_1); + // about.addComponent(u"libQuotient"_s, + // i18n("A Qt library to write cross-platform clients for Matrix"), + // i18nc(" (built against )", + // "%1 (built against %2)", + // Quotient::versionString(), + // QStringLiteral(Quotient_VERSION_STRING)), + // u"https://github.com/quotient-im/libquotient"_s, + // KAboutLicense::LGPL_V2_1); KAboutData::setApplicationData(about); QGuiApplication::setWindowIcon(QIcon::fromTheme(u"org.kde.neochat"_s)); @@ -174,10 +183,13 @@ int main(int argc, char *argv[]) KCrash::initialize(); #endif + PendingConnection::setConnectionType(); + Connection::setRoomType(); + initLogging(); - Connection::setEncryptionDefault(true); - Connection::setDirectChatEncryptionDefault(true); + // Connection::setEncryptionDefault(true); + // Connection::setDirectChatEncryptionDefault(true); #ifdef NEOCHAT_FLATPAK // Copy over the included FontConfig configuration to the @@ -185,7 +197,7 @@ int main(int argc, char *argv[]) QFile::copy(u"/app/etc/fonts/conf.d/99-noto-mono-color-emoji.conf"_s, u"/var/config/fontconfig/conf.d/99-noto-mono-color-emoji.conf"_s); #endif - ColorSchemer colorScheme; + // ColorSchemer colorScheme; QCommandLineParser parser; parser.setApplicationDescription(i18n("Client for the matrix communication protocol")); @@ -208,7 +220,7 @@ int main(int argc, char *argv[]) about.setupCommandLine(&parser); parser.process(app); about.processCommandLine(&parser); - Controller::setTestMode(parser.isSet("test"_L1)); + // Controller::setTestMode(parser.isSet("test"_L1)); #ifdef HAVE_KUNIFIEDPUSH if (parser.isSet(dbusActivatedOption)) { @@ -220,10 +232,10 @@ int main(int argc, char *argv[]) // Because KRunner may call us on the D-Bus (under the same service name org.kde.neochat) then it may // accidentally activate us for push notifications instead. If this happens, then immediately quit if the fake // runner is called. - QDBusConnection::sessionBus().registerObject("/RoomRunner"_L1, new FakeRunner(), QDBusConnection::ExportScriptableContents); + // QDBusConnection::sessionBus().registerObject("/RoomRunner"_L1, new FakeRunner(), QDBusConnection::ExportScriptableContents); #endif - Controller::listenForNotifications(); + // Controller::listenForNotifications(); return QCoreApplication::exec(); } #endif @@ -239,51 +251,51 @@ int main(int argc, char *argv[]) Q_IMPORT_QML_PLUGIN(org_kde_neochat_chatbarPlugin) qml_register_types_org_kde_neochat(); - qmlRegisterUncreatableMetaObject(Quotient::staticMetaObject, "Quotient", 1, 0, "JoinRule", u"Access to JoinRule enum only"_s); + // qmlRegisterUncreatableMetaObject(Quotient::staticMetaObject, "Quotient", 1, 0, "JoinRule", u"Access to JoinRule enum only"_s); QQmlApplicationEngine engine; -#ifdef HAVE_KDBUSADDONS - service.connect(&service, - &KDBusService::activateRequested, - &RoomManager::instance(), - [&engine](const QStringList &arguments, const QString &workingDirectory) { - Q_UNUSED(workingDirectory); - - QWindow *window = windowFromEngine(&engine); - KWindowSystem::updateStartupId(window); - - WindowController::instance().showAndRaiseWindow(QString()); - - // Open matrix uri - if (arguments.isEmpty()) { - return; - } - - auto args = arguments; - args.removeFirst(); - if (args.length() == 2 && args[0] == "--share"_L1) { - ShareHandler::instance().setText(args[1]); - return; - } - - for (const auto &arg : args) { - RoomManager::instance().resolveResource(arg); - } - }); -#endif + // #ifdef HAVE_KDBUSADDONS + // service.connect(&service, + // &KDBusService::activateRequested, + // &RoomManager::instance(), + // [&engine](const QStringList &arguments, const QString &workingDirectory) { + // Q_UNUSED(workingDirectory); + // + // QWindow *window = windowFromEngine(&engine); + // KWindowSystem::updateStartupId(window); + // + // // WindowController::instance().showAndRaiseWindow(QString()); + // + // // Open matrix uri + // if (arguments.isEmpty()) { + // return; + // } + // + // auto args = arguments; + // args.removeFirst(); + // if (args.length() == 2 && args[0] == "--share"_L1) { + // // ShareHandler::instance().setText(args[1]); + // return; + // } + // + // for (const auto &arg : args) { + // // RoomManager::instance().resolveResource(arg); + // } + // }); + // #endif engine.rootContext()->setContextObject(new KLocalizedContext(&engine)); engine.setNetworkAccessManagerFactory(new NetworkAccessManagerFactory()); if (parser.isSet("ignore-ssl-errors"_L1)) { - QObject::connect(NetworkAccessManager::instance(), &QNetworkAccessManager::sslErrors, NetworkAccessManager::instance(), [](QNetworkReply *reply) { - reply->ignoreSslErrors(); - }); + // QObject::connect(NetworkAccessManager::instance(), &QNetworkAccessManager::sslErrors, NetworkAccessManager::instance(), [](QNetworkReply *reply) { + // reply->ignoreSslErrors(); + // }); } if (parser.isSet("share"_L1)) { - ShareHandler::instance().setText(parser.value(shareOption)); + // ShareHandler::instance().setText(parser.value(shareOption)); } engine.addImageProvider(u"blurhash"_s, new BlurhashImageProvider); @@ -294,12 +306,12 @@ int main(int argc, char *argv[]) } if (!parser.positionalArguments().isEmpty() && !parser.isSet("share"_L1)) { - RoomManager::instance().setUrlArgument(parser.positionalArguments()[0]); + // RoomManager::instance().setUrlArgument(parser.positionalArguments()[0]); } #ifdef HAVE_RUNNER - auto runner = Runner::create(&engine, &engine); - QDBusConnection::sessionBus().registerObject("/RoomRunner"_L1, runner, QDBusConnection::ExportScriptableContents); + // auto runner = Runner::create(&engine, &engine); + // QDBusConnection::sessionBus().registerObject("/RoomRunner"_L1, runner, QDBusConnection::ExportScriptableContents); #endif QWindow *window = windowFromEngine(&engine); diff --git a/src/models/completionmodel.cpp b/src/models/completionmodel.cpp index f03edb704..e5ce212c4 100644 --- a/src/models/completionmodel.cpp +++ b/src/models/completionmodel.cpp @@ -4,23 +4,23 @@ #include "completionmodel.h" #include -#include "actionsmodel.h" -#include "completionproxymodel.h" -#include "customemojimodel.h" -#include "emojimodel.h" +// #include "actionsmodel.h" +// #include "completionproxymodel.h" +// #include "customemojimodel.h" +// #include "emojimodel.h" #include "neochatroom.h" -#include "roommanager.h" -#include "userlistmodel.h" +// #include "roommanager.h" +// #include "userlistmodel.h" CompletionModel::CompletionModel(QObject *parent) : QAbstractListModel(parent) - , m_filterModel(new CompletionProxyModel()) - , m_userListModel(RoomManager::instance().userListModel()) + // , m_filterModel(new CompletionProxyModel()) + // , m_userListModel(RoomManager::instance().userListModel()) , m_emojiModel(new QConcatenateTablesProxyModel(this)) { connect(this, &CompletionModel::textChanged, this, &CompletionModel::updateCompletion); - m_emojiModel->addSourceModel(&CustomEmojiModel::instance()); - m_emojiModel->addSourceModel(&EmojiModel::instance()); + // m_emojiModel->addSourceModel(&CustomEmojiModel::instance()); + // m_emojiModel->addSourceModel(&EmojiModel::instance()); } QString CompletionModel::text() const @@ -41,67 +41,68 @@ int CompletionModel::rowCount(const QModelIndex &parent) const if (m_autoCompletionType == None) { return 0; } - return m_filterModel->rowCount(); + // return m_filterModel->rowCount(); + return {}; } QVariant CompletionModel::data(const QModelIndex &index, int role) const { - if (index.row() < 0 || index.row() >= m_filterModel->rowCount()) { - return {}; - } - auto filterIndex = m_filterModel->index(index.row(), 0); - if (m_autoCompletionType == User) { - if (role == DisplayNameRole) { - return m_filterModel->data(filterIndex, UserListModel::DisplayNameRole); - } - if (role == SubtitleRole) { - return m_filterModel->data(filterIndex, UserListModel::UserIdRole); - } - if (role == IconNameRole) { - return m_filterModel->data(filterIndex, UserListModel::AvatarRole); - } - } - - if (m_autoCompletionType == Command) { - if (role == DisplayNameRole) { - return u"%1 %2"_s.arg(m_filterModel->data(filterIndex, ActionsModel::Prefix).toString(), - m_filterModel->data(filterIndex, ActionsModel::Parameters).toString()); - } - if (role == SubtitleRole) { - return m_filterModel->data(filterIndex, ActionsModel::Description); - } - if (role == IconNameRole) { - return u"invalid"_s; - } - if (role == ReplacedTextRole) { - return m_filterModel->data(filterIndex, ActionsModel::Prefix); - } - } - if (m_autoCompletionType == Room) { - if (role == DisplayNameRole) { - return m_filterModel->data(filterIndex, RoomListModel::DisplayNameRole); - } - if (role == SubtitleRole) { - return m_filterModel->data(filterIndex, RoomListModel::CanonicalAliasRole); - } - if (role == IconNameRole) { - return m_filterModel->data(filterIndex, RoomListModel::AvatarRole).toString(); - } - } - if (m_autoCompletionType == Emoji) { - if (role == DisplayNameRole) { - return m_filterModel->data(filterIndex, CustomEmojiModel::DisplayRole); - } - if (role == IconNameRole) { - return m_filterModel->data(filterIndex, CustomEmojiModel::MxcUrl); - } - if (role == ReplacedTextRole) { - return m_filterModel->data(filterIndex, CustomEmojiModel::ReplacedTextRole); - } - if (role == SubtitleRole) { - return m_filterModel->data(filterIndex, EmojiModel::DescriptionRole); - } - } + // if (index.row() < 0 || index.row() >= m_filterModel->rowCount()) { + // return {}; + // } + // auto filterIndex = m_filterModel->index(index.row(), 0); + // if (m_autoCompletionType == User) { + // if (role == DisplayNameRole) { + // return m_filterModel->data(filterIndex, UserListModel::DisplayNameRole); + // } + // if (role == SubtitleRole) { + // return m_filterModel->data(filterIndex, UserListModel::UserIdRole); + // } + // if (role == IconNameRole) { + // return m_filterModel->data(filterIndex, UserListModel::AvatarRole); + // } + // } + // + // if (m_autoCompletionType == Command) { + // if (role == DisplayNameRole) { + // return u"%1 %2"_s.arg(m_filterModel->data(filterIndex, ActionsModel::Prefix).toString(), + // m_filterModel->data(filterIndex, ActionsModel::Parameters).toString()); + // } + // if (role == SubtitleRole) { + // return m_filterModel->data(filterIndex, ActionsModel::Description); + // } + // if (role == IconNameRole) { + // return u"invalid"_s; + // } + // if (role == ReplacedTextRole) { + // return m_filterModel->data(filterIndex, ActionsModel::Prefix); + // } + // } + // if (m_autoCompletionType == Room) { + // if (role == DisplayNameRole) { + // return m_filterModel->data(filterIndex, RoomListModel::DisplayNameRole); + // } + // if (role == SubtitleRole) { + // return m_filterModel->data(filterIndex, RoomListModel::CanonicalAliasRole); + // } + // if (role == IconNameRole) { + // return m_filterModel->data(filterIndex, RoomListModel::AvatarRole).toString(); + // } + // } + // if (m_autoCompletionType == Emoji) { + // if (role == DisplayNameRole) { + // return m_filterModel->data(filterIndex, CustomEmojiModel::DisplayRole); + // } + // if (role == IconNameRole) { + // return m_filterModel->data(filterIndex, CustomEmojiModel::MxcUrl); + // } + // if (role == ReplacedTextRole) { + // return m_filterModel->data(filterIndex, CustomEmojiModel::ReplacedTextRole); + // } + // if (role == SubtitleRole) { + // return m_filterModel->data(filterIndex, EmojiModel::DescriptionRole); + // } + // } return {}; } @@ -118,50 +119,50 @@ QHash CompletionModel::roleNames() const void CompletionModel::updateCompletion() { - if (text().startsWith(QLatin1Char('@'))) { - m_filterModel->setSourceModel(m_userListModel); - m_filterModel->setFilterRole(UserListModel::UserIdRole); - m_filterModel->setSecondaryFilterRole(UserListModel::DisplayNameRole); - m_filterModel->setFullText(m_fullText); - m_filterModel->setFilterText(m_text); - m_autoCompletionType = User; - m_filterModel->invalidate(); - } else if (text().startsWith(QLatin1Char('/'))) { - m_filterModel->setSourceModel(&ActionsModel::instance()); - m_filterModel->setFilterRole(ActionsModel::Prefix); - m_filterModel->setSecondaryFilterRole(-1); - m_filterModel->setFullText(m_fullText); - m_filterModel->setFilterText(m_text.mid(1)); - m_autoCompletionType = Command; - m_filterModel->invalidate(); - } else if (text().startsWith(QLatin1Char('#'))) { - m_autoCompletionType = Room; - m_filterModel->setSourceModel(m_roomListModel); - m_filterModel->setFilterRole(RoomListModel::CanonicalAliasRole); - m_filterModel->setSecondaryFilterRole(RoomListModel::DisplayNameRole); - m_filterModel->setFullText(m_fullText); - m_filterModel->setFilterText(m_text); - m_filterModel->invalidate(); - } else if (text().startsWith(QLatin1Char(':')) && text().size() > 1 && !text()[1].isUpper() - && (m_fullText.indexOf(QLatin1Char(':'), 1) == -1 - || (m_fullText.indexOf(QLatin1Char(' ')) != -1 && m_fullText.indexOf(QLatin1Char(':'), 1) > m_fullText.indexOf(QLatin1Char(' '), 1)))) { - m_filterModel->setSourceModel(m_emojiModel); - m_autoCompletionType = Emoji; - m_filterModel->setFilterRole(CustomEmojiModel::Name); - m_filterModel->setSecondaryFilterRole(EmojiModel::DescriptionRole); - m_filterModel->setFullText(m_fullText); - m_filterModel->setFilterText(m_text); - m_filterModel->invalidate(); - } else { - m_autoCompletionType = None; - } + // if (text().startsWith(QLatin1Char('@'))) { + // m_filterModel->setSourceModel(m_userListModel); + // m_filterModel->setFilterRole(UserListModel::UserIdRole); + // m_filterModel->setSecondaryFilterRole(UserListModel::DisplayNameRole); + // m_filterModel->setFullText(m_fullText); + // m_filterModel->setFilterText(m_text); + // m_autoCompletionType = User; + // m_filterModel->invalidate(); + // } else if (text().startsWith(QLatin1Char('/'))) { + // m_filterModel->setSourceModel(&ActionsModel::instance()); + // m_filterModel->setFilterRole(ActionsModel::Prefix); + // m_filterModel->setSecondaryFilterRole(-1); + // m_filterModel->setFullText(m_fullText); + // m_filterModel->setFilterText(m_text.mid(1)); + // m_autoCompletionType = Command; + // m_filterModel->invalidate(); + // } else if (text().startsWith(QLatin1Char('#'))) { + // m_autoCompletionType = Room; + // m_filterModel->setSourceModel(m_roomListModel); + // m_filterModel->setFilterRole(RoomListModel::CanonicalAliasRole); + // m_filterModel->setSecondaryFilterRole(RoomListModel::DisplayNameRole); + // m_filterModel->setFullText(m_fullText); + // m_filterModel->setFilterText(m_text); + // m_filterModel->invalidate(); + // } else if (text().startsWith(QLatin1Char(':')) && text().size() > 1 && !text()[1].isUpper() + // && (m_fullText.indexOf(QLatin1Char(':'), 1) == -1 + // || (m_fullText.indexOf(QLatin1Char(' ')) != -1 && m_fullText.indexOf(QLatin1Char(':'), 1) > m_fullText.indexOf(QLatin1Char(' '), 1)))) { + // m_filterModel->setSourceModel(m_emojiModel); + // m_autoCompletionType = Emoji; + // m_filterModel->setFilterRole(CustomEmojiModel::Name); + // m_filterModel->setSecondaryFilterRole(EmojiModel::DescriptionRole); + // m_filterModel->setFullText(m_fullText); + // m_filterModel->setFilterText(m_text); + // m_filterModel->invalidate(); + // } else { + // m_autoCompletionType = None; + // } beginResetModel(); endResetModel(); } NeoChatRoom *CompletionModel::room() const { - return m_room; + return m_room.get(); } void CompletionModel::setRoom(NeoChatRoom *room) diff --git a/src/models/completionmodel.h b/src/models/completionmodel.h index 6f52f1c30..fe72412c2 100644 --- a/src/models/completionmodel.h +++ b/src/models/completionmodel.h @@ -7,7 +7,7 @@ #include #include -#include "roomlistmodel.h" +// #include "roomlistmodel.h" class CompletionProxyModel; class UserListModel; @@ -47,7 +47,7 @@ class CompletionModel : public QAbstractListModel /** * @brief The RoomListModel to be used for room completions. */ - Q_PROPERTY(RoomListModel *roomListModel READ roomListModel WRITE setRoomListModel NOTIFY roomListModelChanged) + // Q_PROPERTY(RoomListModel *roomListModel READ roomListModel WRITE setRoomListModel NOTIFY roomListModelChanged) public: /** diff --git a/src/models/pushrulemodel.cpp b/src/models/pushrulemodel.cpp index 3b66b499d..d8b6b5a2d 100644 --- a/src/models/pushrulemodel.cpp +++ b/src/models/pushrulemodel.cpp @@ -5,10 +5,10 @@ #include -#include -#include -#include -#include +// #include +// #include +// #include +// #include #include "neochatconfig.h" @@ -74,18 +74,18 @@ void PushRuleModel::updateNotificationRules(const QString &type) return; } - const QJsonObject ruleDataJson = m_connection->accountDataJson(u"m.push_rules"_s); - const Quotient::PushRuleset ruleData = Quotient::fromJson(ruleDataJson["global"_L1].toObject()); + // const QJsonObject ruleDataJson = m_connection->accountDataJson(u"m.push_rules"_s); + // const Quotient::PushRuleset ruleData = Quotient::fromJson(ruleDataJson["global"_L1].toObject()); beginResetModel(); m_rules.clear(); // Doing this 5 times because PushRuleset is a struct. - setRules(ruleData.override, PushRuleKind::Override); - setRules(ruleData.content, PushRuleKind::Content); - setRules(ruleData.room, PushRuleKind::Room); - setRules(ruleData.sender, PushRuleKind::Sender); - setRules(ruleData.underride, PushRuleKind::Underride); + // setRules(ruleData.override, PushRuleKind::Override); + // setRules(ruleData.content, PushRuleKind::Content); + // setRules(ruleData.room, PushRuleKind::Room); + // setRules(ruleData.sender, PushRuleKind::Sender); + // setRules(ruleData.underride, PushRuleKind::Underride); Q_EMIT globalNotificationsEnabledChanged(); Q_EMIT globalNotificationsSetChanged(); @@ -93,28 +93,28 @@ void PushRuleModel::updateNotificationRules(const QString &type) endResetModel(); } -void PushRuleModel::setRules(QList rules, PushRuleKind::Kind kind) -{ - for (const auto &rule : rules) { - QString roomId; - if (rule.conditions.size() > 0) { - for (const auto &condition : std::as_const(rule.conditions)) { - if (condition.key == u"room_id"_s) { - roomId = condition.pattern; - } - } - } - - m_rules.append(Rule{ - rule.ruleId, - kind, - variantToAction(rule.actions, rule.enabled), - getSection(rule), - rule.enabled, - roomId, - }); - } -} +// void PushRuleModel::setRules(QList rules, PushRuleKind::Kind kind) +// { +// for (const auto &rule : rules) { +// QString roomId; +// if (rule.conditions.size() > 0) { +// for (const auto &condition : std::as_const(rule.conditions)) { +// if (condition.key == u"room_id"_s) { +// roomId = condition.pattern; +// } +// } +// } +// +// m_rules.append(Rule{ +// rule.ruleId, +// kind, +// variantToAction(rule.actions, rule.enabled), +// getSection(rule), +// rule.enabled, +// roomId, +// }); +// } +// } int PushRuleModel::getRuleIndex(const QString &ruleId) const { @@ -126,51 +126,51 @@ int PushRuleModel::getRuleIndex(const QString &ruleId) const return -1; } -PushRuleSection::Section PushRuleModel::getSection(Quotient::PushRule rule) -{ - auto ruleId = rule.ruleId; - - if (defaultSections.contains(ruleId)) { - return defaultSections.value(ruleId); - } else { - if (rule.ruleId.startsWith(u'.')) { - return PushRuleSection::Unknown; - } - /** - * If the rule name resolves to a matrix id for a room that the user is part - * of it shouldn't appear in the global list as it's overriding the global - * state for that room. - * - * Rooms that the user hasn't joined shouldn't have a rule. - */ - if (m_connection->room(ruleId) != nullptr) { - return PushRuleSection::Undefined; - } - /** - * If the rule name resolves to a matrix id for a user it shouldn't appear - * in the global list as it's a rule to block notifications from a user and - * is handled elsewhere. - */ - auto testUserId = ruleId; - // Rules for user matrix IDs often don't have the @ on the beginning so add - // if not there to avoid malformed ID. - if (!testUserId.startsWith(u'@')) { - testUserId.prepend(u'@'); - } - if (testUserId.startsWith(u'@') && !Quotient::serverPart(testUserId).isEmpty() && m_connection->user(testUserId) != nullptr) { - return PushRuleSection::Undefined; - } - // If the rule has push conditions and one is a room ID it is a room only keyword. - if (!rule.conditions.isEmpty()) { - for (const auto &condition : std::as_const(rule.conditions)) { - if (condition.key == u"room_id"_s) { - return PushRuleSection::RoomKeywords; - } - } - } - return PushRuleSection::Keywords; - } -} +// PushRuleSection::Section PushRuleModel::getSection(Quotient::PushRule rule) +// { +// auto ruleId = rule.ruleId; +// +// if (defaultSections.contains(ruleId)) { +// return defaultSections.value(ruleId); +// } else { +// if (rule.ruleId.startsWith(u'.')) { +// return PushRuleSection::Unknown; +// } +// /** +// * If the rule name resolves to a matrix id for a room that the user is part +// * of it shouldn't appear in the global list as it's overriding the global +// * state for that room. +// * +// * Rooms that the user hasn't joined shouldn't have a rule. +// */ +// if (m_connection->room(ruleId) != nullptr) { +// return PushRuleSection::Undefined; +// } +// /** +// * If the rule name resolves to a matrix id for a user it shouldn't appear +// * in the global list as it's a rule to block notifications from a user and +// * is handled elsewhere. +// */ +// auto testUserId = ruleId; +// // Rules for user matrix IDs often don't have the @ on the beginning so add +// // if not there to avoid malformed ID. +// if (!testUserId.startsWith(u'@')) { +// testUserId.prepend(u'@'); +// } +// if (testUserId.startsWith(u'@') && !Quotient::serverPart(testUserId).isEmpty() && m_connection->user(testUserId) != nullptr) { +// return PushRuleSection::Undefined; +// } +// // If the rule has push conditions and one is a room ID it is a room only keyword. +// if (!rule.conditions.isEmpty()) { +// for (const auto &condition : std::as_const(rule.conditions)) { +// if (condition.key == u"room_id"_s) { +// return PushRuleSection::RoomKeywords; +// } +// } +// } +// return PushRuleSection::Keywords; +// } +// } PushRuleAction::Action PushRuleModel::defaultState() const { @@ -294,33 +294,33 @@ void PushRuleModel::addKeyword(const QString &keyword, const QString &roomId) { PushRuleKind::Kind kind = PushRuleKind::Content; const QList actions = actionToVariant(m_defaultKeywordAction); - QList pushConditions; - if (!roomId.isEmpty()) { - kind = PushRuleKind::Override; - - Quotient::PushCondition roomCondition; - roomCondition.kind = u"event_match"_s; - roomCondition.key = u"room_id"_s; - roomCondition.pattern = roomId; - pushConditions.append(roomCondition); - - Quotient::PushCondition keywordCondition; - keywordCondition.kind = u"event_match"_s; - keywordCondition.key = u"content.body"_s; - keywordCondition.pattern = keyword; - pushConditions.append(keywordCondition); - } - - auto job = m_connection->callApi(PushRuleKind::kindString(kind), - keyword, - actions, - QString(), - QString(), - pushConditions, - roomId.isEmpty() ? keyword : QString()); - connect(job, &Quotient::BaseJob::failure, this, [job, keyword]() { - qWarning() << "Unable to set push rule for keyword %1: "_L1.arg(keyword) << job->errorString(); - }); + // QList pushConditions; + // if (!roomId.isEmpty()) { + // kind = PushRuleKind::Override; + // + // Quotient::PushCondition roomCondition; + // roomCondition.kind = u"event_match"_s; + // roomCondition.key = u"room_id"_s; + // roomCondition.pattern = roomId; + // pushConditions.append(roomCondition); + // + // Quotient::PushCondition keywordCondition; + // keywordCondition.kind = u"event_match"_s; + // keywordCondition.key = u"content.body"_s; + // keywordCondition.pattern = keyword; + // pushConditions.append(keywordCondition); + // } + // + // auto job = m_connection->callApi(PushRuleKind::kindString(kind), + // keyword, + // actions, + // QString(), + // QString(), + // pushConditions, + // roomId.isEmpty() ? keyword : QString()); + // connect(job, &Quotient::BaseJob::failure, this, [job, keyword]() { + // qWarning() << "Unable to set push rule for keyword %1: "_L1.arg(keyword) << job->errorString(); + // }); } /** @@ -336,20 +336,20 @@ void PushRuleModel::removeKeyword(const QString &keyword) } auto kind = PushRuleKind::kindString(m_rules[index].kind); - auto job = m_connection->callApi(kind, m_rules[index].id); - connect(job, &Quotient::BaseJob::failure, this, [this, job, index]() { - qWarning() << "Unable to remove push rule for keyword %1: "_L1.arg(m_rules[index].id) << job->errorString(); - }); + // auto job = m_connection->callApi(kind, m_rules[index].id); + // connect(job, &Quotient::BaseJob::failure, this, [this, job, index]() { + // qWarning() << "Unable to remove push rule for keyword %1: "_L1.arg(m_rules[index].id) << job->errorString(); + // }); } void PushRuleModel::setNotificationRuleEnabled(const QString &kind, const QString &ruleId, bool enabled) { - auto job = m_connection->callApi(kind, ruleId); - connect(job, &Quotient::BaseJob::success, this, [job, kind, ruleId, enabled, this]() { - if (job->enabled() != enabled) { - m_connection->callApi(kind, ruleId, enabled); - } - }); + // auto job = m_connection->callApi(kind, ruleId); + // connect(job, &Quotient::BaseJob::success, this, [job, kind, ruleId, enabled, this]() { + // if (job->enabled() != enabled) { + // m_connection->callApi(kind, ruleId, enabled); + // } + // }); } void PushRuleModel::setNotificationRuleActions(const QString &kind, const QString &ruleId, PushRuleAction::Action action) @@ -361,7 +361,7 @@ void PushRuleModel::setNotificationRuleActions(const QString &kind, const QStrin actions = actionToVariant(action); } - m_connection->callApi(kind, ruleId, actions); + // m_connection->callApi(kind, ruleId, actions); } PushRuleAction::Action PushRuleModel::variantToAction(const QList &actions, bool enabled) @@ -378,14 +378,14 @@ PushRuleAction::Action PushRuleModel::variantToAction(const QList &act continue; } - QJsonObject action = i.toJsonObject(); - if (action["set_tweak"_L1].toString() == u"sound"_s) { - isNoisy = true; - } else if (action["set_tweak"_L1].toString() == u"highlight"_s) { - if (action["value"_L1].toString() != u"false"_s) { - highlightEnabled = true; - } - } + // QJsonObject action = i.toJsonObject(); + // if (action["set_tweak"_L1].toString() == u"sound"_s) { + // isNoisy = true; + // } else if (action["set_tweak"_L1].toString() == u"highlight"_s) { + // if (action["value"_L1].toString() != u"false"_s) { + // highlightEnabled = true; + // } + // } } if (!enabled) { @@ -424,15 +424,15 @@ QList PushRuleModel::actionToVariant(PushRuleAction::Action action, co actions.append(u"dont_notify"_s); } if (action == PushRuleAction::Noisy || action == PushRuleAction::NoisyHighlight) { - QJsonObject soundTweak; - soundTweak.insert("set_tweak"_L1, u"sound"_s); - soundTweak.insert("value"_L1, sound); - actions.append(soundTweak); + // QJsonObject soundTweak; + // soundTweak.insert("set_tweak"_L1, u"sound"_s); + // soundTweak.insert("value"_L1, sound); + // actions.append(soundTweak); } if (action == PushRuleAction::Highlight || action == PushRuleAction::NoisyHighlight) { - QJsonObject highlightTweak; - highlightTweak.insert("set_tweak"_L1, u"highlight"_s); - actions.append(highlightTweak); + // QJsonObject highlightTweak; + // highlightTweak.insert("set_tweak"_L1, u"highlight"_s); + // actions.append(highlightTweak); } return actions; @@ -452,7 +452,7 @@ void PushRuleModel::setConnection(NeoChatConnection *connection) Q_EMIT connectionChanged(); if (m_connection) { - connect(m_connection, &NeoChatConnection::accountDataChanged, this, &PushRuleModel::updateNotificationRules); + // connect(m_connection, &NeoChatConnection::accountDataChanged, this, &PushRuleModel::updateNotificationRules); updateNotificationRules(u"m.push_rules"_s); } } diff --git a/src/models/pushrulemodel.h b/src/models/pushrulemodel.h index 7ec684e4e..dd95b1c81 100644 --- a/src/models/pushrulemodel.h +++ b/src/models/pushrulemodel.h @@ -6,7 +6,7 @@ #include #include -#include +// #include #include "enums/pushrule.h" #include "neochatconnection.h" @@ -130,10 +130,10 @@ private: QList m_rules; QPointer m_connection; - void setRules(QList rules, PushRuleKind::Kind kind); + // void setRules(QList rules, PushRuleKind::Kind kind); int getRuleIndex(const QString &ruleId) const; - PushRuleSection::Section getSection(Quotient::PushRule rule); + // PushRuleSection::Section getSection(Quotient::PushRule rule); void setNotificationRuleEnabled(const QString &kind, const QString &ruleId, bool enabled); void setNotificationRuleActions(const QString &kind, const QString &ruleId, PushRuleAction::Action action); diff --git a/src/models/roomtreeitem.cpp b/src/models/roomtreeitem.cpp index 0a48c667b..0890c2423 100644 --- a/src/models/roomtreeitem.cpp +++ b/src/models/roomtreeitem.cpp @@ -12,11 +12,11 @@ RoomTreeItem::RoomTreeItem(TreeData data, RoomTreeItem *parent) bool RoomTreeItem::operator==(const RoomTreeItem &other) const { - if (std::holds_alternative(m_data) && std::holds_alternative(other.data())) { - return std::get(m_data) == std::get(m_data); + if (std::holds_alternative(m_data) && std::holds_alternative(other.data())) { + return std::get(m_data) == std::get(m_data); } - if (std::holds_alternative(m_data) && std::holds_alternative(other.data())) { - return std::get(m_data)->id() == std::get(m_data)->id(); + if (std::holds_alternative(m_data) && std::holds_alternative(other.data())) { + return (*std::get(m_data)->item)->id() == (*std::get(other.data())->item)->id(); } return false; } @@ -84,13 +84,13 @@ RoomTreeItem::TreeData RoomTreeItem::data() const return m_data; } -std::optional RoomTreeItem::rowForRoom(Quotient::Room *room) const +std::optional RoomTreeItem::rowForRoom(rust::Box room) const { - Q_ASSERT_X(std::holds_alternative(m_data), __FUNCTION__, "rowForRoom only works items for rooms not categories"); + Q_ASSERT_X(std::holds_alternative(m_data), __FUNCTION__, "rowForRoom only works items for rooms not categories"); int i = 0; for (const auto &child : m_children) { - if (std::get(child->data()) == room) { + if ((*std::get(child->data())->item)->id() == room->id()) { return i; } i++; diff --git a/src/models/roomtreeitem.h b/src/models/roomtreeitem.h index 6eaa8aebf..e3f3cbe37 100644 --- a/src/models/roomtreeitem.h +++ b/src/models/roomtreeitem.h @@ -1,27 +1,28 @@ + // SPDX-FileCopyrightText: 2024 Carl Schwan // SPDX-FileCopyrightText: 2024 James Graham // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL -#include "enums/neochatroomtype.h" +#include "neochatroomtype.h" -class NeoChatRoom; +namespace sdk +{ +struct RoomListRoom; +} + +struct RoomWrapper { + std::optional> item; +}; /** * @class RoomTreeItem * - * This class defines an item in the space tree hierarchy model. - * - * @note This is separate from Quotient::Room and NeoChatRoom because we don't have - * full room information for any room/space the user hasn't joined and we - * don't want to create one for ever possible child in a space as that would - * be expensive. - * - * @sa Quotient::Room, NeoChatRoom + * This class defines an item in a room tree. */ class RoomTreeItem { public: - using TreeData = std::variant; + using TreeData = std::variant; explicit RoomTreeItem(TreeData data, RoomTreeItem *parent = nullptr); @@ -68,7 +69,7 @@ public: */ TreeData data() const; - std::optional rowForRoom(Quotient::Room *room) const; + std::optional rowForRoom(rust::Box room) const; private: std::vector> m_children; diff --git a/src/models/roomtreemodel.cpp b/src/models/roomtreemodel.cpp index c605de7a9..780583ff4 100644 --- a/src/models/roomtreemodel.cpp +++ b/src/models/roomtreemodel.cpp @@ -1,23 +1,45 @@ + // SPDX-FileCopyrightText: 2023 Tobias Fella // SPDX-License-Identifier: LGPL-2.0-or-later #include "roomtreemodel.h" -#include - -#include "eventhandler.h" #include "neochatconnection.h" +// #include "eventhandler.h" #include "neochatroomtype.h" -#include "spacehierarchycache.h" +#include "rust/cxx.h" +#include +// #include "spacehierarchycache.h" +#include +#include -using namespace Quotient; +using namespace Integral; + +class RoomTreeModel::Private +{ +public: + QPointer connection; + std::unique_ptr roomStream = nullptr; + std::unique_ptr rootItem; + // Since the rooms are streamed as vector diffs we need to keep track of them + // for things like the index value of insert to make sense. + QList roomIndexes; + + void roomsUpdate(); + void resetTree(); + + RoomTreeModel *q = nullptr; +}; RoomTreeModel::RoomTreeModel(QObject *parent) : QAbstractItemModel(parent) - , m_rootItem(new RoomTreeItem(nullptr)) + , d(std::make_unique()) { + d->q = this; } +RoomTreeModel::~RoomTreeModel() = default; + RoomTreeItem *RoomTreeModel::getItem(const QModelIndex &index) const { if (index.isValid()) { @@ -26,179 +48,226 @@ RoomTreeItem *RoomTreeModel::getItem(const QModelIndex &index) const return item; } } - return m_rootItem.get(); + return d->rootItem.get(); } void RoomTreeModel::resetModel() { - if (m_connection == nullptr) { + if (d->connection == nullptr) { beginResetModel(); - m_rootItem.reset(); + d->rootItem.reset(); + d->roomStream.reset(); endResetModel(); return; } beginResetModel(); - m_rootItem.reset(new RoomTreeItem(nullptr)); + d->resetTree(); - for (int i = 0; i < NeoChatRoomType::TypesCount; i++) { - m_rootItem->insertChild(std::make_unique(NeoChatRoomType::Types(i), m_rootItem.get())); - } + d->roomStream = d->connection->roomStream(); + connect(d->roomStream.get(), &RoomStream::roomsUpdate, this, [this]() { + d->roomsUpdate(); + }); - for (const auto &r : m_connection->allRooms()) { - const auto room = dynamic_cast(r); - const auto type = NeoChatRoomType::typeForRoom(room); - const auto categoryItem = m_rootItem->child(type); - if (categoryItem->insertChild(std::make_unique(room, categoryItem))) { - connectRoomSignals(room); - } - } + d->roomStream->startStream(); endResetModel(); } -void RoomTreeModel::setConnection(NeoChatConnection *connection) +void RoomTreeModel::Private::resetTree() { - if (m_connection == connection) { + rootItem.reset(new RoomTreeItem(nullptr)); + for (int i = 0; i < NeoChatRoomType::TypesCount; i++) { + rootItem->insertChild(std::make_unique(NeoChatRoomType::Type(i), rootItem.get())); + } +} + +void RoomTreeModel::setConnection(Connection *connection) +{ + if (d->connection == connection) { return; } - if (m_connection) { - disconnect(m_connection.get(), nullptr, this, nullptr); + if (d->connection) { + d->connection->disconnect(this); } - m_connection = connection; + d->connection = connection; resetModel(); - - connect(connection, &Connection::newRoom, this, &RoomTreeModel::newRoom); - connect(connection, &Connection::leftRoom, this, &RoomTreeModel::leftRoom); - connect(connection, &Connection::aboutToDeleteRoom, this, &RoomTreeModel::leftRoom); - Q_EMIT connectionChanged(); } -void RoomTreeModel::newRoom(Room *r) +void RoomTreeModel::Private::roomsUpdate() { - const auto room = dynamic_cast(r); - const auto type = NeoChatRoomType::typeForRoom(room); - // Check if the room is already in the model. - const auto checkRoomIndex = indexForRoom(room); - if (checkRoomIndex.isValid()) { - // If the room is in the wrong type category for whatever reason, move it. - if (checkRoomIndex.parent().row() != type) { - moveRoom(room); + const auto diff = roomStream->next(); + + switch (diff->op()) { + case 0: { // Append + for (const auto &it : diff->items_vec()) { + const auto type = NeoChatRoomType::typeForRoom(it.box_me()); + const auto parentItem = rootItem->child(type); + q->beginInsertRows(q->index(parentItem->row(), 0), parentItem->childCount(), parentItem->childCount()); + if (parentItem->insertChild(std::make_unique(new RoomWrapper{it.box_me()}, parentItem))) { + // connectRoomSignals(room); + } + q->endInsertRows(); + roomIndexes.append(q->indexForRoom(it.box_me())); } - return; + break; } - - const auto parentItem = m_rootItem->child(type); - beginInsertRows(index(parentItem->row(), 0), parentItem->childCount(), parentItem->childCount()); - parentItem->insertChild(std::make_unique(room, parentItem)); - connectRoomSignals(room); - endInsertRows(); -} - -void RoomTreeModel::leftRoom(Room *r) -{ - const auto room = dynamic_cast(r); - auto index = indexForRoom(room); - if (!index.isValid()) { - return; + case 1: { // Clear + q->beginResetModel(); + resetTree(); + roomIndexes.clear(); + q->endResetModel(); + break; } - - const auto parentItem = getItem(index.parent()); - Q_ASSERT(parentItem); - - beginRemoveRows(index.parent(), index.row(), index.row()); - parentItem->removeChild(index.row()); - room->disconnect(this); - endRemoveRows(); -} - -void RoomTreeModel::moveRoom(Quotient::Room *room) -{ - // We can't assume the type as it has changed so currently the return of - // NeoChatRoomType::typeForRoom doesn't match it's current location. So find the room. - NeoChatRoomType::Types oldType; - int oldRow = -1; - for (int i = 0; i < NeoChatRoomType::TypesCount; i++) { - const auto categoryItem = m_rootItem->child(i); - const auto row = categoryItem->rowForRoom(room); - if (row) { - oldType = static_cast(i); - oldRow = *row; + case 2: { // Push Front + const auto type = NeoChatRoomType::typeForRoom(diff->item()); + const auto parentItem = rootItem->child(type); + q->beginInsertRows(q->index(parentItem->row(), 0), 0, 0); + if (parentItem->insertChild(std::make_unique(new RoomWrapper{diff->item()}, parentItem))) { + // connectRoomSignals(room); } + q->endInsertRows(); + roomIndexes.prepend(q->indexForRoom(diff->item())); + break; } - - if (oldRow == -1) { - return; + case 3: { // Push Back + const auto type = NeoChatRoomType::typeForRoom(diff->item()); + const auto parentItem = rootItem->child(type); + q->beginInsertRows(q->index(parentItem->row(), 0), parentItem->childCount(), parentItem->childCount()); + if (parentItem->insertChild(std::make_unique(new RoomWrapper{diff->item()}, parentItem))) { + // connectRoomSignals(room); + } + q->endInsertRows(); + roomIndexes.append(q->indexForRoom(diff->item())); + break; } - auto neochatRoom = dynamic_cast(room); - const auto newType = NeoChatRoomType::typeForRoom(neochatRoom); - if (newType == oldType) { - return; + case 4: { // Pop Front + const auto index = roomIndexes.front(); + q->beginRemoveRows(index.parent(), index.row(), index.row()); + const auto parentItem = q->getItem(index.parent()); + parentItem->removeChild(index.row()); + roomIndexes.removeFirst(); + q->endRemoveRows(); + break; } + case 5: { // Pop Back + const auto index = roomIndexes.back(); + q->beginRemoveRows(index.parent(), index.row(), index.row()); + const auto parentItem = q->getItem(index.parent()); + parentItem->removeChild(index.row()); + roomIndexes.removeLast(); + q->endRemoveRows(); + break; + } + case 6: { // Insert + const auto type = NeoChatRoomType::typeForRoom(diff->item()); + const auto parentItem = rootItem->child(type); + q->beginInsertRows(q->index(parentItem->row(), 0), parentItem->childCount(), parentItem->childCount()); + if (parentItem->insertChild(std::make_unique(new RoomWrapper{diff->item()}, parentItem))) { + // connectRoomSignals(room); + } + q->endInsertRows(); + roomIndexes.insert(diff->index(), q->indexForRoom(diff->item())); + break; + } + case 7: { // Set + const auto index = roomIndexes.at(diff->index()); + q->beginRemoveRows(index.parent(), index.row(), index.row()); + q->getItem(index.parent())->removeChild(index.row()); + q->endRemoveRows(); - const auto oldParent = index(oldType, 0, {}); - auto oldParentItem = getItem(oldParent); - Q_ASSERT(oldParentItem); + const auto type = NeoChatRoomType::typeForRoom(diff->item()); + const auto parentItem = rootItem->child(type); + q->beginInsertRows(q->index(parentItem->row(), 0), parentItem->childCount(), parentItem->childCount()); + if (parentItem->insertChild(std::make_unique(new RoomWrapper{diff->item()}, parentItem))) { + // connectRoomSignals(room); + } + q->endInsertRows(); + roomIndexes[diff->index()] = q->indexForRoom(diff->item()); + break; + } + case 8: { // Remove + const auto index = roomIndexes.at(diff->index()); + q->beginRemoveRows(index.parent(), index.row(), index.row()); + q->getItem(index.parent())->removeChild(index.row()); + q->endRemoveRows(); + roomIndexes.removeAt(diff->index()); + break; + } + case 9: { // Truncate + for (int i = q->rowCount({}) - 1; i >= int(diff->index()); i--) { + const auto index = roomIndexes.at(i); + q->beginRemoveRows(index.parent(), index.row(), index.row()); + q->getItem(index.parent())->removeChild(index.row()); + q->endRemoveRows(); + roomIndexes.removeAt(i); + } + break; + } + case 10: { // Reset + q->beginResetModel(); + resetTree(); + roomIndexes.clear(); + q->endResetModel(); - const auto newParent = index(newType, 0, {}); - auto newParentItem = getItem(newParent); - Q_ASSERT(newParentItem); - - // HACK: We're doing this as a remove then insert because moving doesn't work - // properly with DelegateChooser for whatever reason. - Q_ASSERT(checkIndex(index(oldRow, 0, oldParent), QAbstractItemModel::CheckIndexOption::IndexIsValid)); - beginRemoveRows(oldParent, oldRow, oldRow); - const bool success = oldParentItem->removeChild(oldRow); - Q_ASSERT(success); - endRemoveRows(); - beginInsertRows(newParent, newParentItem->childCount(), newParentItem->childCount()); - newParentItem->insertChild(std::make_unique(neochatRoom, newParentItem)); - endInsertRows(); + for (const auto &it : diff->items_vec()) { + const auto type = NeoChatRoomType::typeForRoom(it.box_me()); + const auto parentItem = rootItem->child(type); + q->beginInsertRows(q->index(parentItem->row(), 0), parentItem->childCount(), parentItem->childCount()); + if (parentItem->insertChild(std::make_unique(new RoomWrapper{it.box_me()}, parentItem))) { + // connectRoomSignals(room); + } + q->endInsertRows(); + roomIndexes.append(q->indexForRoom(it.box_me())); + } + break; + } + } } -void RoomTreeModel::connectRoomSignals(NeoChatRoom *room) -{ - connect(room, &Room::displaynameChanged, this, [this, room] { - refreshRoomRoles(room, {DisplayNameRole}); - }); - connect(room, &Room::unreadStatsChanged, this, [this, room] { - refreshRoomRoles(room, {ContextNotificationCountRole, HasHighlightNotificationsRole}); - }); - connect(room, &Room::avatarChanged, this, [this, room] { - refreshRoomRoles(room, {AvatarRole}); - }); - connect(room, &Room::tagsChanged, this, [this, room] { - moveRoom(room); - }); - connect(room, &Room::joinStateChanged, this, [this, room] { - refreshRoomRoles(room); - }); - connect(room, &Room::addedMessages, this, [this, room] { - refreshRoomRoles(room, {SubtitleTextRole}); - }); - connect(room, &Room::pendingEventMerged, this, [this, room] { - refreshRoomRoles(room, {SubtitleTextRole}); - }); - connect(room, &NeoChatRoom::pushNotificationStateChanged, this, [this, room] { - refreshRoomRoles(room, {ContextNotificationCountRole, HasHighlightNotificationsRole}); - }); -} +// void RoomTreeModel::connectRoomSignals(NeoChatRoom *room) +// { +// connect(room, &Room::displaynameChanged, this, [this, room] { +// refreshRoomRoles(room, {DisplayNameRole}); +// }); +// connect(room, &Room::unreadStatsChanged, this, [this, room] { +// refreshRoomRoles(room, {ContextNotificationCountRole, HasHighlightNotificationsRole}); +// }); +// connect(room, &Room::avatarChanged, this, [this, room] { +// refreshRoomRoles(room, {AvatarRole}); +// }); +// connect(room, &Room::tagsChanged, this, [this, room] { +// moveRoom(room); +// }); +// connect(room, &Room::joinStateChanged, this, [this, room] { +// refreshRoomRoles(room); +// }); +// connect(room, &Room::addedMessages, this, [this, room] { +// refreshRoomRoles(room, {SubtitleTextRole}); +// }); +// connect(room, &Room::pendingEventMerged, this, [this, room] { +// refreshRoomRoles(room, {SubtitleTextRole}); +// }); +// connect(room, &NeoChatRoom::pushNotificationStateChanged, this, [this, room] { +// refreshRoomRoles(room, {ContextNotificationCountRole, HasHighlightNotificationsRole}); +// }); +// } -void RoomTreeModel::refreshRoomRoles(NeoChatRoom *room, const QList &roles) -{ - const auto index = indexForRoom(room); - if (!index.isValid()) { - qCritical() << "Room" << room->id() << "not found in the room list"; - return; - } - Q_EMIT dataChanged(index, index, roles); -} +// void RoomTreeModel::refreshRoomRoles(NeoChatRoom *room, const QList &roles) +// { +// const auto index = indexForRoom(room); +// if (!index.isValid()) { +// qCritical() << "Room" << room->id() << "not found in the room list"; +// return; +// } +// Q_EMIT dataChanged(index, index, roles); +// } -NeoChatConnection *RoomTreeModel::connection() const +Connection *RoomTreeModel::connection() const { - return m_connection; + return d->connection; } int RoomTreeModel::columnCount(const QModelIndex &parent) const @@ -215,7 +284,7 @@ int RoomTreeModel::rowCount(const QModelIndex &parent) const } if (!parent.isValid()) { - parentItem = m_rootItem.get(); + parentItem = d->rootItem.get(); } else { parentItem = static_cast(parent.internalPointer()); } @@ -239,7 +308,7 @@ QModelIndex RoomTreeModel::parent(const QModelIndex &index) const } RoomTreeItem *parentItem = childItem->parentItem(); - if (parentItem == m_rootItem.get()) { + if (parentItem == d->rootItem.get()) { return QModelIndex(); } @@ -295,7 +364,7 @@ QVariant RoomTreeModel::data(const QModelIndex &index, int role) const } RoomTreeItem *child = getItem(index); - if (std::holds_alternative(child->data())) { + if (std::holds_alternative(child->data())) { if (role == DisplayNameRole) { return NeoChatRoomType::typeName(index.row()); } @@ -314,98 +383,91 @@ QVariant RoomTreeModel::data(const QModelIndex &index, int role) const return {}; } - const auto room = std::get(child->data()); + const auto room = std::get(child->data()); Q_ASSERT(room); if (role == DisplayNameRole) { - return room->displayName(); + return stringFromRust((*room->item)->display_name()).toHtmlEscaped(); } if (role == AvatarRole) { - return room->avatarMediaUrl(); + return u"%1?user_id=%2"_s.arg(stringFromRust((*room->item)->avatar_url()), d->connection->matrixId()); } if (role == CanonicalAliasRole) { - return room->canonicalAlias(); + return stringFromRust((*room->item)->canonical_alias()).toHtmlEscaped(); } if (role == TopicRole) { - return room->topic(); + return stringFromRust((*room->item)->topic()).toHtmlEscaped(); } if (role == CategoryRole) { - return NeoChatRoomType::typeForRoom(room); + return NeoChatRoomType::typeForRoom((*room->item)->box_me()); } if (role == ContextNotificationCountRole) { - return int(room->contextAwareNotificationCount()); + return int((*room->item)->num_unread_messages()); } if (role == HasHighlightNotificationsRole) { - return room->highlightCount() > 0 && room->contextAwareNotificationCount() > 0; + return (*room->item)->num_unread_mentions() > 0 && (*room->item)->num_unread_messages() > 0; } if (role == JoinStateRole) { - if (!room->successorId().isEmpty()) { + if (!(*room->item)->tombstone()->replacement_room().empty()) { return u"upgraded"_s; } - return QVariant::fromValue(room->joinState()); + return QVariant::fromValue((*room->item)->state()); } if (role == CurrentRoomRole) { - return QVariant::fromValue(room); + return {}; + // return QVariant::fromValue(room); } if (role == SubtitleTextRole) { - if (room->isInvite()) { - if (room->isDirectChat()) { - return i18nc("@info:label", "Invited you to chat"); - } - return i18nc("@info:label", "%1 invited you", room->member(room->invitingUserId()).displayName()); - } - if (room->lastEvent() == nullptr || room->lastEventIsSpoiler()) { - return QString(); - } - return EventHandler::subtitleText(room, room->lastEvent()); + return {}; + // if (room->lastEvent() == nullptr || room->lastEventIsSpoiler()) { + // return QString(); + // } + // return EventHandler::subtitleText(room, room->lastEvent()); } if (role == AvatarImageRole) { - return room->avatar(128); + return {}; + // return room->avatar(128); } if (role == RoomIdRole) { - return room->id(); + return stringFromRust((*room->item)->id()).toHtmlEscaped(); } if (role == IsSpaceRole) { - return room->isSpace(); + return (*room->item)->is_space(); } if (role == IsChildSpaceRole) { - return SpaceHierarchyCache::instance().isChild(room->id()); + return false; + // return SpaceHierarchyCache::instance().isChild(room->id()); } if (role == ReplacementIdRole) { - return room->successorId(); + return stringFromRust((*room->item)->tombstone()->replacement_room()).toHtmlEscaped(); } if (role == IsDirectChat) { - return room->isDirectChat(); + return false; + // return room->isDirectChat(); } if (role == DelegateTypeRole) { return u"normal"_s; } if (role == RoomTypeRole) { - if (room->creation()) { - return room->creation()->contentPart("type"_L1); - } + return stringFromRust((*room->item)->room_type()).toHtmlEscaped(); } return {}; } -QModelIndex RoomTreeModel::indexForRoom(NeoChatRoom *room) const +QModelIndex RoomTreeModel::indexForRoom(rust::Box room) const { - if (room == nullptr) { - return {}; - } - // Try and find by checking type. - const auto type = NeoChatRoomType::typeForRoom(room); - const auto parentItem = m_rootItem->child(type); - const auto row = parentItem->rowForRoom(room); + const auto type = NeoChatRoomType::typeForRoom(room->box_me()); + const auto parentItem = d->rootItem->child(type); + const auto row = parentItem->rowForRoom(room->box_me()); if (row) { return index(*row, 0, index(type, 0)); } // Double check that the room isn't in the wrong category. for (int i = 0; i < NeoChatRoomType::TypesCount; i++) { - const auto parentItem = m_rootItem->child(i); - const auto row = parentItem->rowForRoom(room); + const auto parentItem = d->rootItem->child(i); + const auto row = parentItem->rowForRoom(room->box_me()); if (row) { return index(*row, 0, index(i, 0)); } @@ -414,4 +476,13 @@ QModelIndex RoomTreeModel::indexForRoom(NeoChatRoom *room) const return {}; } +std::optional> RoomTreeModel::roomForIndex(QModelIndex index) const +{ + RoomTreeItem *child = getItem(index); + if (std::holds_alternative(child->data())) { + return std::nullopt; + } + return (*std::get(child->data())->item)->box_me(); +} + #include "moc_roomtreemodel.cpp" diff --git a/src/models/roomtreemodel.h b/src/models/roomtreemodel.h index 0644db11e..fc6a82053 100644 --- a/src/models/roomtreemodel.h +++ b/src/models/roomtreemodel.h @@ -1,3 +1,4 @@ + // SPDX-FileCopyrightText: 2023 Tobias Fella // SPDX-License-Identifier: LGPL-2.0-or-later @@ -6,23 +7,20 @@ #include #include -#include "enums/neochatroomtype.h" #include "roomtreeitem.h" -namespace Quotient +namespace Integral { +class Connection; class Room; } -class NeoChatConnection; -class NeoChatRoom; - class RoomTreeModel : public QAbstractItemModel { Q_OBJECT QML_ELEMENT - Q_PROPERTY(NeoChatConnection *connection READ connection WRITE setConnection NOTIFY connectionChanged) + Q_PROPERTY(Integral::Connection *connection READ connection WRITE setConnection NOTIFY connectionChanged) public: /** @@ -51,9 +49,10 @@ public: }; Q_ENUM(EventRoles) explicit RoomTreeModel(QObject *parent = nullptr); + ~RoomTreeModel(); - void setConnection(NeoChatConnection *connection); - NeoChatConnection *connection() const; + void setConnection(Integral::Connection *connection); + Integral::Connection *connection() const; /** * @brief Get the given role value at the given index. @@ -75,23 +74,21 @@ public: int columnCount(const QModelIndex &parent = QModelIndex()) const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override; - Q_INVOKABLE QModelIndex indexForRoom(NeoChatRoom *room) const; + QModelIndex indexForRoom(rust::Box room) const; + std::optional> roomForIndex(QModelIndex index) const; Q_SIGNALS: void connectionChanged(); private: - QPointer m_connection; - std::unique_ptr m_rootItem; + class Private; + std::unique_ptr d; RoomTreeItem *getItem(const QModelIndex &index) const; void resetModel(); - void connectRoomSignals(NeoChatRoom *room); - void newRoom(Quotient::Room *room); - void leftRoom(Quotient::Room *room); - void moveRoom(Quotient::Room *room); + // void connectRoomSignals(NeoChatRoom *room); - void refreshRoomRoles(NeoChatRoom *room, const QList &roles = {}); + // void refreshRoomRoles(NeoChatRoom *room, const QList &roles = {}); }; diff --git a/src/models/sortfilterroomtreemodel.cpp b/src/models/sortfilterroomtreemodel.cpp index 260c1d54c..4fab3aab2 100644 --- a/src/models/sortfilterroomtreemodel.cpp +++ b/src/models/sortfilterroomtreemodel.cpp @@ -4,26 +4,26 @@ #include "sortfilterroomtreemodel.h" -#include "enums/roomsortparameter.h" -#include "neochatconfig.h" +#include "roomsortparameter.h" +// #include "neochatconfig.h" #include "neochatconnection.h" -#include "neochatroom.h" #include "neochatroomtype.h" -#include "roommanager.h" +#include +// #include "roommanager.h" #include "roomtreemodel.h" -#include "spacehierarchycache.h" +// #include "spacehierarchycache.h" -SortFilterRoomTreeModel::SortFilterRoomTreeModel(RoomTreeModel *sourceModel, QObject *parent) +SortFilterRoomTreeModel::SortFilterRoomTreeModel(QObject *parent) : QSortFilterProxyModel(parent) { - Q_ASSERT(sourceModel); - setSourceModel(sourceModel); + // Q_ASSERT(sourceModel); + // setSourceModel(sourceModel); - setRoomSortOrder(static_cast(NeoChatConfig::sortOrder())); - connect(NeoChatConfig::self(), &NeoChatConfig::SortOrderChanged, this, [this]() { - setRoomSortOrder(static_cast(NeoChatConfig::sortOrder())); - invalidateFilter(); - }); + // setRoomSortOrder(static_cast(NeoChatConfig::sortOrder())); + // connect(NeoChatConfig::self(), &NeoChatConfig::SortOrderChanged, this, [this]() { + // setRoomSortOrder(static_cast(NeoChatConfig::sortOrder())); + // invalidateFilter(); + // }); setRecursiveFilteringEnabled(true); sort(0); @@ -34,13 +34,13 @@ SortFilterRoomTreeModel::SortFilterRoomTreeModel(RoomTreeModel *sourceModel, QOb connect(this->sourceModel(), &QAbstractItemModel::rowsRemoved, this, &SortFilterRoomTreeModel::invalidateFilter); }); - connect(NeoChatConfig::self(), &NeoChatConfig::CollapsedChanged, this, &SortFilterRoomTreeModel::invalidateFilter); - connect(NeoChatConfig::self(), &NeoChatConfig::AllRoomsInHomeChanged, this, [this]() { - invalidateFilter(); - if (NeoChatConfig::self()->allRoomsInHome()) { - RoomManager::instance().resetState(); - } - }); + // connect(NeoChatConfig::self(), &NeoChatConfig::CollapsedChanged, this, &SortFilterRoomTreeModel::invalidateFilter); + // connect(NeoChatConfig::self(), &NeoChatConfig::AllRoomsInHomeChanged, this, [this]() { + // invalidateFilter(); + // if (NeoChatConfig::self()->allRoomsInHome()) { + // RoomManager::instance().resetState(); + // } + // }); } void SortFilterRoomTreeModel::setRoomSortOrder(SortFilterRoomTreeModel::RoomSortOrder sortOrder) @@ -78,14 +78,14 @@ bool SortFilterRoomTreeModel::lessThan(const QModelIndex &source_left, const QMo return false; } - const auto leftRoom = dynamic_cast(treeModel->connection()->room(source_left.data(RoomTreeModel::RoomIdRole).toString())); - const auto rightRoom = dynamic_cast(treeModel->connection()->room(source_right.data(RoomTreeModel::RoomIdRole).toString())); - if (leftRoom == nullptr || rightRoom == nullptr) { + const auto leftRoom = treeModel->roomForIndex(source_left); + const auto rightRoom = treeModel->roomForIndex(source_right); + if (!leftRoom.has_value() || !rightRoom.has_value()) { return false; } for (auto sortRole : RoomSortParameter::currentParameterList()) { - auto result = RoomSortParameter::compareParameter(sortRole, leftRoom, rightRoom); + auto result = RoomSortParameter::compareParameter(sortRole, leftRoom.value()->box_me(), rightRoom.value()->box_me()); if (result != 0) { return result > 0; @@ -141,20 +141,22 @@ bool SortFilterRoomTreeModel::filterAcceptsRow(int source_row, const QModelIndex return false; } - static auto config = NeoChatConfig::self(); - if (config->allRoomsInHome() && RoomManager::instance().currentSpace().isEmpty()) { - return acceptRoom; - } + return acceptRoom; - if (m_activeSpaceId.isEmpty()) { - if (!SpaceHierarchyCache::instance().isChild(sourceModel()->data(index, RoomTreeModel::RoomIdRole).toString())) { - return acceptRoom; - } - return false; - } else { - const auto &rooms = SpaceHierarchyCache::instance().getRoomListForSpace(m_activeSpaceId, false); - return std::find(rooms.begin(), rooms.end(), sourceModel()->data(index, RoomTreeModel::RoomIdRole).toString()) != rooms.end() && acceptRoom; - } + // static auto config = NeoChatConfig::self(); + // if (config->allRoomsInHome() && RoomManager::instance().currentSpace().isEmpty()) { + // return acceptRoom; + // } + // + // if (m_activeSpaceId.isEmpty()) { + // if (!SpaceHierarchyCache::instance().isChild(sourceModel()->data(index, RoomTreeModel::RoomIdRole).toString())) { + // return acceptRoom; + // } + // return false; + // } else { + // const auto &rooms = SpaceHierarchyCache::instance().getRoomListForSpace(m_activeSpaceId, false); + // return std::find(rooms.begin(), rooms.end(), sourceModel()->data(index, RoomTreeModel::RoomIdRole).toString()) != rooms.end() && acceptRoom; + // } } QString SortFilterRoomTreeModel::activeSpaceId() const @@ -192,7 +194,7 @@ QModelIndex SortFilterRoomTreeModel::currentRoomIndex() const return {}; } - return mapFromSource(roomModel->indexForRoom(RoomManager::instance().currentRoom())); + return {}; // mapFromSource(roomModel->indexForRoom(RoomManager::instance().currentRoom())); } #include "moc_sortfilterroomtreemodel.cpp" diff --git a/src/models/sortfilterroomtreemodel.h b/src/models/sortfilterroomtreemodel.h index eaac032dd..8bbfd68cc 100644 --- a/src/models/sortfilterroomtreemodel.h +++ b/src/models/sortfilterroomtreemodel.h @@ -32,7 +32,7 @@ class SortFilterRoomTreeModel : public QSortFilterProxyModel { Q_OBJECT QML_ELEMENT - QML_UNCREATABLE("") + // QML_UNCREATABLE("") /** * @brief The text to use to filter room names. @@ -64,7 +64,7 @@ public: }; Q_ENUM(Mode) - explicit SortFilterRoomTreeModel(RoomTreeModel *sourceModel, QObject *parent = nullptr); + explicit SortFilterRoomTreeModel(QObject *parent = nullptr); void setRoomSortOrder(RoomSortOrder sortOrder); diff --git a/src/models/userlistmodel.cpp b/src/models/userlistmodel.cpp index 63caf072c..3c308e62b 100644 --- a/src/models/userlistmodel.cpp +++ b/src/models/userlistmodel.cpp @@ -5,8 +5,8 @@ #include -#include -#include +// #include +// #include #include "enums/powerlevel.h" #include "neochatroom.h" @@ -30,7 +30,7 @@ void UserListModel::setRoom(NeoChatRoom *room) // last room's objects before the room is actually changed beginResetModel(); m_currentRoom->disconnect(this); - m_currentRoom->connection()->disconnect(this); + // m_currentRoom->connection()->disconnect(this); m_currentRoom = nullptr; m_members.clear(); endResetModel(); @@ -39,21 +39,21 @@ void UserListModel::setRoom(NeoChatRoom *room) m_currentRoom = room; if (m_currentRoom) { - connect(m_currentRoom, &Room::memberJoined, this, &UserListModel::memberJoined); - connect(m_currentRoom, &Room::memberLeft, this, &UserListModel::memberLeft); - connect(m_currentRoom, &Room::memberNameUpdated, this, [this](RoomMember member) { - refreshMember(member, {DisplayNameRole}); - }); - connect(m_currentRoom, &Room::memberAvatarUpdated, this, [this](RoomMember member) { - refreshMember(member, {AvatarRole}); - }); - connect(m_currentRoom, &Room::memberListChanged, this, [this]() { - // this is slow - UserListModel::refreshAllMembers(); - }); - connect(m_currentRoom->connection(), &Connection::loggedOut, this, [this]() { - setRoom(nullptr); - }); + // connect(m_currentRoom, &Room::memberJoined, this, &UserListModel::memberJoined); + // connect(m_currentRoom, &Room::memberLeft, this, &UserListModel::memberLeft); + // connect(m_currentRoom, &Room::memberNameUpdated, this, [this](RoomMember member) { + // refreshMember(member, {DisplayNameRole}); + // }); + // connect(m_currentRoom, &Room::memberAvatarUpdated, this, [this](RoomMember member) { + // refreshMember(member, {AvatarRole}); + // }); + // connect(m_currentRoom, &Room::memberListChanged, this, [this]() { + // // this is slow + // UserListModel::refreshAllMembers(); + // }); + // connect(m_currentRoom->connection(), &Connection::loggedOut, this, [this]() { + // setRoom(nullptr); + // }); } m_active = false; @@ -80,40 +80,40 @@ QVariant UserListModel::data(const QModelIndex &index, int role) const return {}; } auto memberId = m_members.at(index.row()); - if (role == DisplayNameRole) { - return m_currentRoom->member(memberId).disambiguatedName(); - } - if (role == UserIdRole) { - return memberId; - } - if (role == AvatarRole) { - return m_currentRoom->member(memberId).avatarUrl(); - } - if (role == ObjectRole) { - return QVariant::fromValue(memberId); - } - if (role == PowerLevelRole) { - auto plEvent = m_currentRoom->currentState().get(); - if (!plEvent) { - return 0; - } - return plEvent->powerLevelForUser(memberId); - } - if (role == PowerLevelStringRole) { - auto pl = m_currentRoom->currentState().get(); - // User might not in the room yet, in this case pl can be nullptr. - // e.g. When invited but user not accepted or denied the invitation. - if (!pl) { - return u"Not Available"_s; - } - - auto userPl = pl->powerLevelForUser(memberId); - - return i18nc("%1 is the name of the power level, e.g. admin and %2 is the value that represents.", - "%1 (%2)", - PowerLevel::nameForLevel(PowerLevel::levelForValue(userPl)), - userPl); - } + // if (role == DisplayNameRole) { + // return m_currentRoom->member(memberId).disambiguatedName(); + // } + // if (role == UserIdRole) { + // return memberId; + // } + // if (role == AvatarRole) { + // return m_currentRoom->member(memberId).avatarUrl(); + // } + // if (role == ObjectRole) { + // return QVariant::fromValue(memberId); + // } + // if (role == PowerLevelRole) { + // auto plEvent = m_currentRoom->currentState().get(); + // if (!plEvent) { + // return 0; + // } + // return plEvent->powerLevelForUser(memberId); + // } + // if (role == PowerLevelStringRole) { + // auto pl = m_currentRoom->currentState().get(); + // // User might not in the room yet, in this case pl can be nullptr. + // // e.g. When invited but user not accepted or denied the invitation. + // if (!pl) { + // return u"Not Available"_s; + // } + // + // auto userPl = pl->powerLevelForUser(memberId); + // + // return i18nc("%1 is the name of the power level, e.g. admin and %2 is the value that represents.", + // "%1 (%2)", + // PowerLevel::nameForLevel(PowerLevel::levelForValue(userPl)), + // userPl); + // } return {}; } @@ -134,65 +134,65 @@ bool UserListModel::event(QEvent *event) return QObject::event(event); } -void UserListModel::memberJoined(const Quotient::RoomMember &member) -{ - auto pos = findUserPos(member); - beginInsertRows(QModelIndex(), pos, pos); - m_members.insert(pos, member.id()); - endInsertRows(); -} - -void UserListModel::memberLeft(const Quotient::RoomMember &member) -{ - auto pos = findUserPos(member); - if (pos != m_members.size()) { - beginRemoveRows(QModelIndex(), pos, pos); - m_members.removeAt(pos); - endRemoveRows(); - } else { - qWarning() << "Trying to remove a room member not in the user list"; - } -} - -void UserListModel::refreshMember(const Quotient::RoomMember &member, const QList &roles) -{ - auto pos = findUserPos(member); - if (pos != m_members.size()) { - // The update will have changed the state event so we need to insert the updated member object. - m_members.insert(pos, member.id()); - Q_EMIT dataChanged(index(pos), index(pos), roles); - } else { - qWarning() << "Trying to access a room member not in the user list"; - } -} +// void UserListModel::memberJoined(const Quotient::RoomMember &member) +// { +// auto pos = findUserPos(member); +// beginInsertRows(QModelIndex(), pos, pos); +// m_members.insert(pos, member.id()); +// endInsertRows(); +// } +// +// void UserListModel::memberLeft(const Quotient::RoomMember &member) +// { +// auto pos = findUserPos(member); +// if (pos != m_members.size()) { +// beginRemoveRows(QModelIndex(), pos, pos); +// m_members.removeAt(pos); +// endRemoveRows(); +// } else { +// qWarning() << "Trying to remove a room member not in the user list"; +// } +// } +// +// void UserListModel::refreshMember(const Quotient::RoomMember &member, const QList &roles) +// { +// auto pos = findUserPos(member); +// if (pos != m_members.size()) { +// // The update will have changed the state event so we need to insert the updated member object. +// m_members.insert(pos, member.id()); +// Q_EMIT dataChanged(index(pos), index(pos), roles); +// } else { +// qWarning() << "Trying to access a room member not in the user list"; +// } +// } void UserListModel::refreshAllMembers() { beginResetModel(); if (m_currentRoom != nullptr) { - m_members = m_currentRoom->joinedMemberIds(); - MemberSorter sorter; - std::sort(m_members.begin(), m_members.end(), [&sorter, this](const auto &left, const auto &right) { - const auto leftPl = m_currentRoom->memberEffectivePowerLevel(left); - const auto rightPl = m_currentRoom->memberEffectivePowerLevel(right); - if (leftPl > rightPl) { - return true; - } else if (rightPl > leftPl) { - return false; - } - - return sorter(m_currentRoom->member(left), m_currentRoom->member(right)); - }); + // m_members = m_currentRoom->joinedMemberIds(); + // MemberSorter sorter; + // std::sort(m_members.begin(), m_members.end(), [&sorter, this](const auto &left, const auto &right) { + // const auto leftPl = m_currentRoom->memberEffectivePowerLevel(left); + // const auto rightPl = m_currentRoom->memberEffectivePowerLevel(right); + // if (leftPl > rightPl) { + // return true; + // } else if (rightPl > leftPl) { + // return false; + // } + // + // return sorter(m_currentRoom->member(left), m_currentRoom->member(right)); + // }); } endResetModel(); Q_EMIT usersRefreshed(); } -int UserListModel::findUserPos(const RoomMember &member) const -{ - return findUserPos(member.id()); -} +// int UserListModel::findUserPos(const RoomMember &member) const +// { +// return findUserPos(member.id()); +// } int UserListModel::findUserPos(const QString &userId) const { diff --git a/src/models/userlistmodel.h b/src/models/userlistmodel.h index 39acd22e3..1fc56f027 100644 --- a/src/models/userlistmodel.h +++ b/src/models/userlistmodel.h @@ -3,7 +3,7 @@ #pragma once -#include +#include #include #include @@ -87,9 +87,9 @@ protected: bool event(QEvent *event) override; private Q_SLOTS: - void memberJoined(const Quotient::RoomMember &member); - void memberLeft(const Quotient::RoomMember &member); - void refreshMember(const Quotient::RoomMember &member, const QList &roles = {}); + // void memberJoined(const Quotient::RoomMember &member); + // void memberLeft(const Quotient::RoomMember &member); + // void refreshMember(const Quotient::RoomMember &member, const QList &roles = {}); void refreshAllMembers(); private: @@ -98,6 +98,6 @@ private: bool m_active = false; - int findUserPos(const Quotient::RoomMember &member) const; + // int findUserPos(const Quotient::RoomMember &member) const; [[nodiscard]] int findUserPos(const QString &username) const; }; diff --git a/src/neochatconnection.cpp b/src/neochatconnection.cpp index da1ec8a36..92ebecf1b 100644 --- a/src/neochatconnection.cpp +++ b/src/neochatconnection.cpp @@ -6,147 +6,142 @@ #include #include -#include "neochatconfig.h" -#include "neochatroom.h" -#include "spacehierarchycache.h" +// #include "neochatconfig.h" +// #include "neochatroom.h" +// #include "spacehierarchycache.h" -#include -#include +// #include +// #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include -#ifdef HAVE_KUNIFIEDPUSH -#include -#include -#include -#endif +// #ifdef HAVE_KUNIFIEDPUSH +// #include +// #include +// #include +// #endif -using namespace Quotient; +#include + +using namespace Integral; using namespace Qt::StringLiterals; -NeoChatConnection::NeoChatConnection(QObject *parent) - : Connection(parent) +NeoChatConnection::NeoChatConnection(std::unique_ptr d) + : Connection(std::move(d)) { - m_linkPreviewers.setMaxCost(20); - connectSignals(); -} - -NeoChatConnection::NeoChatConnection(const QUrl &server, QObject *parent) - : Connection(server, parent) -{ - m_linkPreviewers.setMaxCost(20); + // m_linkPreviewers.setMaxCost(20); connectSignals(); } void NeoChatConnection::connectSignals() { - connect(this, &NeoChatConnection::accountDataChanged, this, [this](const QString &type) { - if (type == u"org.kde.neochat.account_label"_s) { - Q_EMIT labelChanged(); - } - if (type == u"m.identity_server"_s) { - Q_EMIT identityServerChanged(); - } - }); - connect(this, &NeoChatConnection::syncDone, this, [this] { - setIsOnline(true); - }); - connect(this, &NeoChatConnection::networkError, this, [this]() { - setIsOnline(false); - }); - connect(this, &NeoChatConnection::requestFailed, this, [this](BaseJob *job) { - if (job->error() == BaseJob::UserConsentRequired) { - Q_EMIT userConsentRequired(job->errorUrl()); - } - }); - connect(this, &NeoChatConnection::requestFailed, this, [this](BaseJob *job) { - if (dynamic_cast(job) && job->jsonData()["errcode"_L1].toString() == "M_TOO_LARGE"_L1) { - Q_EMIT showMessage(MessageType::Warning, i18n("File too large to download.
Contact your matrix server administrator for support.")); - } - }); - connect(this, &NeoChatConnection::directChatsListChanged, this, [this](DirectChatsMap additions, DirectChatsMap removals) { - Q_EMIT directChatInvitesChanged(); - for (const auto &chatId : additions) { - if (const auto chat = room(chatId)) { - connect(chat, &Room::unreadStatsChanged, this, [this]() { - refreshBadgeNotificationCount(); - Q_EMIT directChatNotificationsChanged(); - Q_EMIT directChatsHaveHighlightNotificationsChanged(); - }); - } - } - for (const auto &chatId : removals) { - if (const auto chat = room(chatId)) { - disconnect(chat, &Room::unreadStatsChanged, this, nullptr); - } - } - }); - connect(this, &NeoChatConnection::joinedRoom, this, [this](Room *room) { - if (room->isDirectChat()) { - connect(room, &Room::unreadStatsChanged, this, [this]() { - Q_EMIT directChatNotificationsChanged(); - Q_EMIT directChatsHaveHighlightNotificationsChanged(); - }); - } - connect(room, &Room::unreadStatsChanged, this, [this]() { - refreshBadgeNotificationCount(); - Q_EMIT homeNotificationsChanged(); - Q_EMIT homeHaveHighlightNotificationsChanged(); - }); - }); - connect(this, &NeoChatConnection::leftRoom, this, [this](Room *room, Room *prev) { - Q_UNUSED(room) - if (prev && prev->isDirectChat()) { - Q_EMIT directChatInvitesChanged(); - Q_EMIT directChatNotificationsChanged(); - Q_EMIT directChatsHaveHighlightNotificationsChanged(); - } - refreshBadgeNotificationCount(); - Q_EMIT homeNotificationsChanged(); - Q_EMIT homeHaveHighlightNotificationsChanged(); - }); - - connect(&SpaceHierarchyCache::instance(), &SpaceHierarchyCache::spaceHierarchyChanged, this, [this]() { - refreshBadgeNotificationCount(); - Q_EMIT homeNotificationsChanged(); - Q_EMIT homeHaveHighlightNotificationsChanged(); - }); - - // Fetch unstable features - // TODO: Expose unstableFeatures() in libQuotient - connect( - this, - &Connection::connected, - this, - [this] { - auto job = callApi(BackgroundRequest); - connect(job, &GetVersionsJob::success, this, [this, job] { - m_canCheckMutualRooms = job->unstableFeatures().contains("uk.half-shot.msc2666.query_mutual_rooms"_L1); - Q_EMIT canCheckMutualRoomsChanged(); - m_canEraseData = job->unstableFeatures().contains("org.matrix.msc4025"_L1) || job->versions().count("v1.10"_L1); - Q_EMIT canEraseDataChanged(); - }); - }, - Qt::SingleShotConnection); - setDirectChatEncryptionDefault(NeoChatConfig::preferUsingEncryption()); - connect(NeoChatConfig::self(), &NeoChatConfig::PreferUsingEncryptionChanged, this, [] { - setDirectChatEncryptionDefault(NeoChatConfig::preferUsingEncryption()); - }); - setGlobalUrlPreviewEnabled(NeoChatConfig::showLinkPreview()); - connect(NeoChatConfig::self(), &NeoChatConfig::ShowLinkPreviewChanged, this, [this]() { - setGlobalUrlPreviewEnabled(NeoChatConfig::showLinkPreview()); - }); + // connect(this, &NeoChatConnection::accountDataChanged, this, [this](const QString &type) { + // if (type == u"org.kde.neochat.account_label"_s) { + // Q_EMIT labelChanged(); + // } + // if (type == u"m.identity_server"_s) { + // Q_EMIT identityServerChanged(); + // } + // }); + // connect(this, &NeoChatConnection::syncDone, this, [this] { + // setIsOnline(true); + // }); + // connect(this, &NeoChatConnection::networkError, this, [this]() { + // setIsOnline(false); + // }); + // connect(this, &NeoChatConnection::requestFailed, this, [this](BaseJob *job) { + // if (job->error() == BaseJob::UserConsentRequired) { + // Q_EMIT userConsentRequired(job->errorUrl()); + // } + // }); + // connect(this, &NeoChatConnection::requestFailed, this, [this](BaseJob *job) { + // if (dynamic_cast(job) && job->jsonData()["errcode"_L1].toString() == "M_TOO_LARGE"_L1) { + // Q_EMIT showMessage(MessageType::Warning, i18n("File too large to download.
Contact your matrix server administrator for support.")); + // } + // }); + // connect(this, &NeoChatConnection::directChatsListChanged, this, [this](DirectChatsMap additions, DirectChatsMap removals) { + // Q_EMIT directChatInvitesChanged(); + // for (const auto &chatId : additions) { + // if (const auto chat = room(chatId)) { + // connect(chat, &Room::unreadStatsChanged, this, [this]() { + // refreshBadgeNotificationCount(); + // Q_EMIT directChatNotificationsChanged(); + // Q_EMIT directChatsHaveHighlightNotificationsChanged(); + // }); + // } + // } + // for (const auto &chatId : removals) { + // if (const auto chat = room(chatId)) { + // disconnect(chat, &Room::unreadStatsChanged, this, nullptr); + // } + // } + // }); + // connect(this, &NeoChatConnection::joinedRoom, this, [this](Room *room) { + // if (room->isDirectChat()) { + // connect(room, &Room::unreadStatsChanged, this, [this]() { + // Q_EMIT directChatNotificationsChanged(); + // Q_EMIT directChatsHaveHighlightNotificationsChanged(); + // }); + // } + // connect(room, &Room::unreadStatsChanged, this, [this]() { + // refreshBadgeNotificationCount(); + // Q_EMIT homeNotificationsChanged(); + // Q_EMIT homeHaveHighlightNotificationsChanged(); + // }); + // }); + // connect(this, &NeoChatConnection::leftRoom, this, [this](Room *room, Room *prev) { + // Q_UNUSED(room) + // if (prev && prev->isDirectChat()) { + // Q_EMIT directChatInvitesChanged(); + // Q_EMIT directChatNotificationsChanged(); + // Q_EMIT directChatsHaveHighlightNotificationsChanged(); + // } + // refreshBadgeNotificationCount(); + // Q_EMIT homeNotificationsChanged(); + // Q_EMIT homeHaveHighlightNotificationsChanged(); + // }); + // + // connect(&SpaceHierarchyCache::instance(), &SpaceHierarchyCache::spaceHierarchyChanged, this, [this]() { + // refreshBadgeNotificationCount(); + // Q_EMIT homeNotificationsChanged(); + // Q_EMIT homeHaveHighlightNotificationsChanged(); + // }); + // + // // Fetch unstable features + // // TODO: Expose unstableFeatures() in libQuotient + // connect( + // this, + // &Connection::connected, + // this, + // [this] { + // auto job = callApi(BackgroundRequest); + // connect(job, &GetVersionsJob::success, this, [this, job] { + // m_canCheckMutualRooms = job->unstableFeatures().contains("uk.half-shot.msc2666.query_mutual_rooms"_L1); + // Q_EMIT canCheckMutualRoomsChanged(); + // m_canEraseData = job->unstableFeatures().contains("org.matrix.msc4025"_L1) || job->versions().count("v1.10"_L1); + // Q_EMIT canEraseDataChanged(); + // }); + // }, + // Qt::SingleShotConnection); + // setDirectChatEncryptionDefault(NeoChatConfig::preferUsingEncryption()); + // connect(NeoChatConfig::self(), &NeoChatConfig::PreferUsingEncryptionChanged, this, [] { + // setDirectChatEncryptionDefault(NeoChatConfig::preferUsingEncryption()); + // }); + // setGlobalUrlPreviewEnabled(NeoChatConfig::showLinkPreview()); + // connect(NeoChatConfig::self(), &NeoChatConfig::ShowLinkPreviewChanged, this, [this]() { + // setGlobalUrlPreviewEnabled(NeoChatConfig::showLinkPreview()); + // }); } int NeoChatConnection::badgeNotificationCount() const @@ -157,11 +152,11 @@ int NeoChatConnection::badgeNotificationCount() const void NeoChatConnection::refreshBadgeNotificationCount() { int count = 0; - for (const auto &r : allRooms()) { - if (const auto room = static_cast(r)) { - count += room->contextAwareNotificationCount(); - } - } + // for (const auto &r : allRooms()) { + // if (const auto room = static_cast(r)) { + // count += room->contextAwareNotificationCount(); + // } + // } if (count != m_badgeNotificationCount) { m_badgeNotificationCount = count; @@ -182,56 +177,58 @@ void NeoChatConnection::setGlobalUrlPreviewEnabled(bool newState) m_globalUrlPreviewEnabled = newState; if (!m_globalUrlPreviewEnabled) { - m_linkPreviewers.clear(); + // m_linkPreviewers.clear(); } - NeoChatConfig::setShowLinkPreview(m_globalUrlPreviewEnabled); + // NeoChatConfig::setShowLinkPreview(m_globalUrlPreviewEnabled); Q_EMIT globalUrlPreviewEnabledChanged(); } void NeoChatConnection::logout(bool serverSideLogout) { - SettingsGroup(u"Accounts"_s).remove(userId()); - - QKeychain::DeletePasswordJob job(qAppName()); - job.setAutoDelete(true); - job.setKey(userId()); - QEventLoop loop; - QKeychain::DeletePasswordJob::connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); - job.start(); - loop.exec(); - - if (!serverSideLogout) { - return; - } - Connection::logout(); + // SettingsGroup(u"Accounts"_s).remove(userId()); + // + // QKeychain::DeletePasswordJob job(qAppName()); + // job.setAutoDelete(true); + // job.setKey(userId()); + // QEventLoop loop; + // QKeychain::DeletePasswordJob::connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); + // job.start(); + // loop.exec(); + // + // if (!serverSideLogout) { + // return; + // } + // Connection::logout(); } bool NeoChatConnection::setAvatar(const QUrl &avatarSource) { - QString decoded = avatarSource.path(); - if (decoded.isEmpty()) { - callApi(user()->id(), avatarSource); - return true; - } - if (QImageReader(decoded).read().isNull()) { - return false; - } else { - return user()->setAvatar(decoded); - } + // QString decoded = avatarSource.path(); + // if (decoded.isEmpty()) { + // callApi(user()->id(), avatarSource); + // return true; + // } + // if (QImageReader(decoded).read().isNull()) { + // return false; + // } else { + // return user()->setAvatar(decoded); + // } + return {}; } QVariantList NeoChatConnection::getSupportedRoomVersions() const { - const auto &roomVersions = availableRoomVersions(); - QVariantList supportedRoomVersions; - for (const auto &v : roomVersions) { - QVariantMap roomVersionMap; - roomVersionMap.insert("id"_L1, v.id); - roomVersionMap.insert("status"_L1, v.status); - roomVersionMap.insert("isStable"_L1, v.isStable()); - supportedRoomVersions.append(roomVersionMap); - } - return supportedRoomVersions; + // const auto &roomVersions = availableRoomVersions(); + // QVariantList supportedRoomVersions; + // for (const auto &v : roomVersions) { + // QVariantMap roomVersionMap; + // roomVersionMap.insert("id"_L1, v.id); + // roomVersionMap.insert("status"_L1, v.status); + // roomVersionMap.insert("isStable"_L1, v.isStable()); + // supportedRoomVersions.append(roomVersionMap); + // } + // return supportedRoomVersions; + return {}; } bool NeoChatConnection::canCheckMutualRooms() const @@ -241,85 +238,86 @@ bool NeoChatConnection::canCheckMutualRooms() const void NeoChatConnection::changePassword(const QString ¤tPassword, const QString &newPassword) { - auto job = callApi(newPassword, false); - connect(job, &BaseJob::result, this, [this, job, currentPassword, newPassword] { - if (job->error() == 103) { - QJsonObject replyData = job->jsonData(); - AuthenticationData authData; - authData.session = replyData["session"_L1].toString(); - authData.type = "m.login.password"_L1; - authData.authInfo["password"_L1] = currentPassword; - authData.authInfo["user"_L1] = user()->id(); - authData.authInfo["identifier"_L1] = QJsonObject{{"type"_L1, "m.id.user"_L1}, {"user"_L1, user()->id()}}; - auto innerJob = callApi(newPassword, false, authData); - connect(innerJob, &BaseJob::success, this, [this]() { - Q_EMIT passwordStatus(PasswordStatus::Success); - }); - connect(innerJob, &BaseJob::failure, this, [innerJob, this]() { - Q_EMIT passwordStatus(innerJob->jsonData()["errcode"_L1] == "M_FORBIDDEN"_L1 ? PasswordStatus::Wrong : PasswordStatus::Other); - }); - } - }); + // auto job = callApi(newPassword, false); + // connect(job, &BaseJob::result, this, [this, job, currentPassword, newPassword] { + // if (job->error() == 103) { + // QJsonObject replyData = job->jsonData(); + // AuthenticationData authData; + // authData.session = replyData["session"_L1].toString(); + // authData.type = "m.login.password"_L1; + // authData.authInfo["password"_L1] = currentPassword; + // authData.authInfo["user"_L1] = user()->id(); + // authData.authInfo["identifier"_L1] = QJsonObject{{"type"_L1, "m.id.user"_L1}, {"user"_L1, user()->id()}}; + // auto innerJob = callApi(newPassword, false, authData); + // connect(innerJob, &BaseJob::success, this, [this]() { + // Q_EMIT passwordStatus(PasswordStatus::Success); + // }); + // connect(innerJob, &BaseJob::failure, this, [innerJob, this]() { + // Q_EMIT passwordStatus(innerJob->jsonData()["errcode"_L1] == "M_FORBIDDEN"_L1 ? PasswordStatus::Wrong : PasswordStatus::Other); + // }); + // } + // }); } void NeoChatConnection::setLabel(const QString &label) { - QJsonObject json{ - {"account_label"_L1, label}, - }; - setAccountData("org.kde.neochat.account_label"_L1, json); - Q_EMIT labelChanged(); + // QJsonObject json{ + // {"account_label"_L1, label}, + // }; + // setAccountData("org.kde.neochat.account_label"_L1, json); + // Q_EMIT labelChanged(); } QString NeoChatConnection::label() const { - return accountDataJson("org.kde.neochat.account_label"_L1)["account_label"_L1].toString(); + // return accountDataJson("org.kde.neochat.account_label"_L1)["account_label"_L1].toString(); + return {}; } void NeoChatConnection::deactivateAccount(const QString &password, const bool erase) { - auto job = callApi(); - connect(job, &BaseJob::result, this, [this, job, password, erase] { - if (job->error() == 103) { - QJsonObject replyData = job->jsonData(); - AuthenticationData authData; - authData.session = replyData["session"_L1].toString(); - authData.authInfo["password"_L1] = password; - authData.type = "m.login.password"_L1; - authData.authInfo["user"_L1] = user()->id(); - QJsonObject identifier = {{"type"_L1, "m.id.user"_L1}, {"user"_L1, user()->id()}}; - authData.authInfo["identifier"_L1] = identifier; - auto innerJob = callApi(authData, QString{}, erase); - connect(innerJob, &BaseJob::success, this, [this]() { - logout(false); - }); - } - }); + // auto job = callApi(); + // connect(job, &BaseJob::result, this, [this, job, password, erase] { + // if (job->error() == 103) { + // QJsonObject replyData = job->jsonData(); + // AuthenticationData authData; + // authData.session = replyData["session"_L1].toString(); + // authData.authInfo["password"_L1] = password; + // authData.type = "m.login.password"_L1; + // authData.authInfo["user"_L1] = user()->id(); + // QJsonObject identifier = {{"type"_L1, "m.id.user"_L1}, {"user"_L1, user()->id()}}; + // authData.authInfo["identifier"_L1] = identifier; + // auto innerJob = callApi(authData, QString{}, erase); + // connect(innerJob, &BaseJob::success, this, [this]() { + // logout(false); + // }); + // } + // }); } bool NeoChatConnection::hasIdentityServer() const { - if (!hasAccountData(u"m.identity_server"_s)) { - return false; - } + // if (!hasAccountData(u"m.identity_server"_s)) { + // return false; + // } - const auto url = accountData(u"m.identity_server"_s)->contentPart("base_url"_L1); - if (!url.isEmpty()) { - return true; - } + // const auto url = accountData(u"m.identity_server"_s)->contentPart("base_url"_L1); + // if (!url.isEmpty()) { + // return true; + // } return false; } QUrl NeoChatConnection::identityServer() const { - if (!hasAccountData(u"m.identity_server"_s)) { - return {}; - } + // if (!hasAccountData(u"m.identity_server"_s)) { + // return {}; + // } - const auto url = accountData(u"m.identity_server"_s)->contentPart("base_url"_L1); - if (!url.isEmpty()) { - return url; - } + // const auto url = accountData(u"m.identity_server"_s)->contentPart("base_url"_L1); + // if (!url.isEmpty()) { + // return url; + // } return {}; } @@ -334,92 +332,93 @@ QString NeoChatConnection::identityServerUIString() const void NeoChatConnection::createRoom(const QString &name, const QString &topic, const QString &parent, bool setChildParent) { - QList initialStateEvents; - if (!parent.isEmpty()) { - initialStateEvents.append(CreateRoomJob::StateEvent{ - "m.space.parent"_L1, - QJsonObject{ - {"canonical"_L1, true}, - {"via"_L1, QJsonArray{domain()}}, - }, - parent, - }); - } - - const auto job = Connection::createRoom(Connection::PublishRoom, QString(), name, topic, QStringList(), {}, {}, {}, initialStateEvents); - if (!parent.isEmpty()) { - connect(job, &Quotient::CreateRoomJob::success, this, [this, parent, setChildParent, job]() { - if (setChildParent) { - if (auto parentRoom = room(parent)) { - parentRoom->setState(u"m.space.child"_s, job->roomId(), QJsonObject{{"via"_L1, QJsonArray{domain()}}}); - } - } - }); - } - connect(job, &CreateRoomJob::failure, this, [this, job] { - Q_EMIT errorOccured(i18n("Room creation failed: %1", job->errorString())); - }); + // QList initialStateEvents; + // if (!parent.isEmpty()) { + // initialStateEvents.append(CreateRoomJob::StateEvent{ + // "m.space.parent"_L1, + // QJsonObject{ + // {"canonical"_L1, true}, + // {"via"_L1, QJsonArray{domain()}}, + // }, + // parent, + // }); + // } + // + // const auto job = Connection::createRoom(Connection::PublishRoom, QString(), name, topic, QStringList(), {}, {}, {}, initialStateEvents); + // if (!parent.isEmpty()) { + // connect(job, &Quotient::CreateRoomJob::success, this, [this, parent, setChildParent, job]() { + // if (setChildParent) { + // if (auto parentRoom = room(parent)) { + // parentRoom->setState(u"m.space.child"_s, job->roomId(), QJsonObject{{"via"_L1, QJsonArray{domain()}}}); + // } + // } + // }); + // } + // connect(job, &CreateRoomJob::failure, this, [this, job] { + // Q_EMIT errorOccured(i18n("Room creation failed: %1", job->errorString())); + // }); } void NeoChatConnection::createSpace(const QString &name, const QString &topic, const QString &parent, bool setChildParent) { - QList initialStateEvents; - if (!parent.isEmpty()) { - initialStateEvents.append(CreateRoomJob::StateEvent{ - "m.space.parent"_L1, - QJsonObject{ - {"canonical"_L1, true}, - {"via"_L1, QJsonArray{domain()}}, - }, - parent, - }); - } - - const auto job = - Connection::createRoom(Connection::UnpublishRoom, {}, name, topic, {}, {}, {}, false, initialStateEvents, {}, QJsonObject{{"type"_L1, "m.space"_L1}}); - if (!parent.isEmpty()) { - connect(job, &Quotient::CreateRoomJob::success, this, [this, parent, setChildParent, job]() { - if (setChildParent) { - if (auto parentRoom = room(parent)) { - parentRoom->setState(u"m.space.child"_s, job->roomId(), QJsonObject{{"via"_L1, QJsonArray{domain()}}}); - } - } - }); - } - connect(job, &CreateRoomJob::failure, this, [this, job] { - Q_EMIT errorOccured(i18n("Space creation failed: %1", job->errorString())); - }); + // QList initialStateEvents; + // if (!parent.isEmpty()) { + // initialStateEvents.append(CreateRoomJob::StateEvent{ + // "m.space.parent"_L1, + // QJsonObject{ + // {"canonical"_L1, true}, + // {"via"_L1, QJsonArray{domain()}}, + // }, + // parent, + // }); + // } + // + // const auto job = + // Connection::createRoom(Connection::UnpublishRoom, {}, name, topic, {}, {}, {}, false, initialStateEvents, {}, QJsonObject{{"type"_L1, + // "m.space"_L1}}); + // if (!parent.isEmpty()) { + // connect(job, &Quotient::CreateRoomJob::success, this, [this, parent, setChildParent, job]() { + // if (setChildParent) { + // if (auto parentRoom = room(parent)) { + // parentRoom->setState(u"m.space.child"_s, job->roomId(), QJsonObject{{"via"_L1, QJsonArray{domain()}}}); + // } + // } + // }); + // } + // connect(job, &CreateRoomJob::failure, this, [this, job] { + // Q_EMIT errorOccured(i18n("Space creation failed: %1", job->errorString())); + // }); } -bool NeoChatConnection::directChatExists(Quotient::User *user) -{ - return directChats().contains(user); -} +// bool NeoChatConnection::directChatExists(Quotient::User *user) +// { +// return directChats().contains(user); +// } qsizetype NeoChatConnection::directChatNotifications() const { qsizetype notifications = 0; QStringList added; // The same ID can be in the list multiple times. - for (const auto &chatId : directChats()) { - if (!added.contains(chatId)) { - if (const auto chat = room(chatId)) { - notifications += dynamic_cast(chat)->contextAwareNotificationCount(); - added += chatId; - } - } - } + // for (const auto &chatId : directChats()) { + // if (!added.contains(chatId)) { + // if (const auto chat = room(chatId)) { + // notifications += dynamic_cast(chat)->contextAwareNotificationCount(); + // added += chatId; + // } + // } + // } return notifications; } bool NeoChatConnection::directChatsHaveHighlightNotifications() const { - for (const auto &childId : directChats()) { - if (const auto child = static_cast(room(childId))) { - if (child->highlightCount() > 0) { - return true; - } - } - } + // for (const auto &childId : directChats()) { + // if (const auto child = static_cast(room(childId))) { + // if (child->highlightCount() > 0) { + // return true; + // } + // } + // } return false; } @@ -427,78 +426,78 @@ qsizetype NeoChatConnection::homeNotifications() const { qsizetype notifications = 0; QStringList added; - const auto &spaceHierarchyCache = SpaceHierarchyCache::instance(); - for (const auto &r : allRooms()) { - if (const auto room = static_cast(r)) { - if (!added.contains(room->id()) && !room->isDirectChat() && !spaceHierarchyCache.isChild(room->id())) { - notifications += dynamic_cast(room)->contextAwareNotificationCount(); - added += room->id(); - } - } - } + // const auto &spaceHierarchyCache = SpaceHierarchyCache::instance(); + // for (const auto &r : allRooms()) { + // if (const auto room = static_cast(r)) { + // if (!added.contains(room->id()) && !room->isDirectChat() && !spaceHierarchyCache.isChild(room->id())) { + // notifications += dynamic_cast(room)->contextAwareNotificationCount(); + // added += room->id(); + // } + // } + // } return notifications; } bool NeoChatConnection::homeHaveHighlightNotifications() const { - const auto &spaceHierarchyCache = SpaceHierarchyCache::instance(); - for (const auto &r : allRooms()) { - if (const auto room = static_cast(r)) { - if (!room->isDirectChat() && !spaceHierarchyCache.isChild(room->id()) && room->highlightCount() > 0) { - return true; - } - } - } + // const auto &spaceHierarchyCache = SpaceHierarchyCache::instance(); + // for (const auto &r : allRooms()) { + // if (const auto room = static_cast(r)) { + // if (!room->isDirectChat() && !spaceHierarchyCache.isChild(room->id()) && room->highlightCount() > 0) { + // return true; + // } + // } + // } return false; } bool NeoChatConnection::directChatInvites() const { - auto inviteRooms = rooms(JoinState::Invite); - for (const auto inviteRoom : inviteRooms) { - if (inviteRoom->isDirectChat()) { - return true; - } - } + // auto inviteRooms = rooms(JoinState::Invite); + // for (const auto inviteRoom : inviteRooms) { + // if (inviteRoom->isDirectChat()) { + // return true; + // } + // } return false; } -QCoro::Task NeoChatConnection::setupPushNotifications(QString endpoint) -{ -#ifdef HAVE_KUNIFIEDPUSH - QUrl gatewayEndpoint(endpoint); - gatewayEndpoint.setPath(u"/_matrix/push/v1/notify"_s); - - QNetworkRequest checkGateway(gatewayEndpoint); - auto reply = co_await NetworkAccessManager::instance()->get(checkGateway); - - // We want to check if this UnifiedPush server has a Matrix gateway - // This is because Matrix does not natively support UnifiedPush - const auto &replyJson = QJsonDocument::fromJson(reply->readAll()).object(); - - if (replyJson["unifiedpush"_L1]["gateway"_L1].toString() == u"matrix"_s) { - callApi(endpoint, - u"http"_s, - u"org.kde.neochat"_s, - u"NeoChat"_s, - deviceId(), - QString(), // profileTag is intentionally left empty for now, it's optional - u"en-US"_s, - PostPusherJob::PusherData{QUrl::fromUserInput(gatewayEndpoint.toString()), u" "_s}, - false); - - qInfo() << "Registered for push notifications"; - m_pushNotificationsEnabled = true; - } else { - qWarning() << "There's no gateway, not setting up push notifications."; - m_pushNotificationsEnabled = false; - } - Q_EMIT enablePushNotificationsChanged(); -#else - Q_UNUSED(endpoint) - co_return; -#endif -} +// QCoro::Task NeoChatConnection::setupPushNotifications(QString endpoint) +// { +// #ifdef HAVE_KUNIFIEDPUSH +// QUrl gatewayEndpoint(endpoint); +// gatewayEndpoint.setPath(u"/_matrix/push/v1/notify"_s); +// +// QNetworkRequest checkGateway(gatewayEndpoint); +// auto reply = co_await NetworkAccessManager::instance()->get(checkGateway); +// +// // We want to check if this UnifiedPush server has a Matrix gateway +// // This is because Matrix does not natively support UnifiedPush +// const auto &replyJson = QJsonDocument::fromJson(reply->readAll()).object(); +// +// if (replyJson["unifiedpush"_L1]["gateway"_L1].toString() == u"matrix"_s) { +// callApi(endpoint, +// u"http"_s, +// u"org.kde.neochat"_s, +// u"NeoChat"_s, +// deviceId(), +// QString(), // profileTag is intentionally left empty for now, it's optional +// u"en-US"_s, +// PostPusherJob::PusherData{QUrl::fromUserInput(gatewayEndpoint.toString()), u" "_s}, +// false); +// +// qInfo() << "Registered for push notifications"; +// m_pushNotificationsEnabled = true; +// } else { +// qWarning() << "There's no gateway, not setting up push notifications."; +// m_pushNotificationsEnabled = false; +// } +// Q_EMIT enablePushNotificationsChanged(); +// #else +// Q_UNUSED(endpoint) +// co_return; +// #endif +// } bool NeoChatConnection::isOnline() const { @@ -516,39 +515,39 @@ void NeoChatConnection::setIsOnline(bool isOnline) QString NeoChatConnection::accountDataJsonString(const QString &type) const { - return QString::fromUtf8(QJsonDocument(accountDataJson(type)).toJson()); + return {}; // QString::fromUtf8(QJsonDocument(accountDataJson(type)).toJson()); } -LinkPreviewer *NeoChatConnection::previewerForLink(const QUrl &link) -{ - if (!m_globalUrlPreviewEnabled) { - return nullptr; - } +// LinkPreviewer *NeoChatConnection::previewerForLink(const QUrl &link) +// { +// if (!m_globalUrlPreviewEnabled) { +// return nullptr; +// } +// +// auto previewer = m_linkPreviewers.object(link); +// if (previewer != nullptr) { +// return previewer; +// } +// +// previewer = new LinkPreviewer(link, this); +// m_linkPreviewers.insert(link, previewer); +// return previewer; +// } - auto previewer = m_linkPreviewers.object(link); - if (previewer != nullptr) { - return previewer; - } - - previewer = new LinkPreviewer(link, this); - m_linkPreviewers.insert(link, previewer); - return previewer; -} - -KeyImport::Error NeoChatConnection::exportMegolmSessions(const QString &passphrase, const QString &path) -{ - KeyImport keyImport; - auto result = keyImport.exportKeys(passphrase, this); - if (!result.has_value()) { - return result.error(); - } - QUrl url(path); - QFile file(url.toLocalFile()); - file.open(QFile::WriteOnly); - file.write(result.value()); - file.close(); - return KeyImport::Success; -} +// KeyImport::Error NeoChatConnection::exportMegolmSessions(const QString &passphrase, const QString &path) +// { +// KeyImport keyImport; +// auto result = keyImport.exportKeys(passphrase, this); +// if (!result.has_value()) { +// return result.error(); +// } +// QUrl url(path); +// QFile file(url.toLocalFile()); +// file.open(QFile::WriteOnly); +// file.write(result.value()); +// file.close(); +// return KeyImport::Success; +// } bool NeoChatConnection::canEraseData() const { diff --git a/src/neochatconnection.h b/src/neochatconnection.h index e3ea388ae..1688b4db7 100644 --- a/src/neochatconnection.h +++ b/src/neochatconnection.h @@ -7,15 +7,16 @@ #include #include +#include #include -#include -#include +// #include -#include "enums/messagetype.h" -#include "linkpreviewer.h" +// #include "enums/messagetype.h" +// #include "linkpreviewer.h" +// #include "models/threepidmodel.h" -class NeoChatConnection : public Quotient::Connection +class NeoChatConnection : public Integral::Connection { Q_OBJECT QML_ELEMENT @@ -110,8 +111,7 @@ public: }; Q_ENUM(PasswordStatus) - NeoChatConnection(QObject *parent = nullptr); - NeoChatConnection(const QUrl &server, QObject *parent = nullptr); + NeoChatConnection(std::unique_ptr d); Q_INVOKABLE void logout(bool serverSideLogout); Q_INVOKABLE QVariantList getSupportedRoomVersions() const; @@ -162,14 +162,14 @@ public: /** * @brief Whether a direct chat with the user exists. */ - Q_INVOKABLE bool directChatExists(Quotient::User *user); + // Q_INVOKABLE bool directChatExists(Quotient::User *user); /** * @brief Get the account data with \param type as a formatted JSON string. */ Q_INVOKABLE QString accountDataJsonString(const QString &type) const; - Q_INVOKABLE Quotient::KeyImport::Error exportMegolmSessions(const QString &passphrase, const QString &path); + // Q_INVOKABLE Quotient::KeyImport::Error exportMegolmSessions(const QString &passphrase, const QString &path); qsizetype directChatNotifications() const; bool directChatsHaveHighlightNotifications() const; @@ -186,14 +186,14 @@ public: // note: this is intentionally a copied QString because // the reference could be destroyed before the task is finished - QCoro::Task setupPushNotifications(QString endpoint); + // QCoro::Task setupPushNotifications(QString endpoint); bool pushNotificationsAvailable() const; bool enablePushNotifications() const; bool isOnline() const; - LinkPreviewer *previewerForLink(const QUrl &link); + // LinkPreviewer *previewerForLink(const QUrl &link); Q_SIGNALS: void globalUrlPreviewEnabledChanged(); @@ -215,7 +215,7 @@ Q_SIGNALS: /** * @brief Request a message be shown to the user of the given type. */ - void showMessage(MessageType::Type messageType, const QString &message); + // void showMessage(MessageType::Type messageType, const QString &message); /** * @brief Request a error message be shown to the user. @@ -231,7 +231,7 @@ private: int m_badgeNotificationCount = 0; bool m_globalUrlPreviewEnabled = true; - QCache m_linkPreviewers; + // QCache m_linkPreviewers; bool m_canCheckMutualRooms = false; bool m_canEraseData = false; diff --git a/src/neochatroom.cpp b/src/neochatroom.cpp index c2ed653d0..78f09a70e 100644 --- a/src/neochatroom.cpp +++ b/src/neochatroom.cpp @@ -4,51 +4,52 @@ #include "neochatroom.h" #include +#include #include #include #include #include -#include -#include -#include -#include -#include -#include +// #include +// #include +// #include +// #include +// #include +// #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include -#include "chatbarcache.h" -#include "clipboard.h" -#include "eventhandler.h" -#include "events/pollevent.h" -#include "filetransferpseudojob.h" +// #include "chatbarcache.h" +// #include "clipboard.h" +// #include "eventhandler.h" +// #include "events/pollevent.h" +// #include "filetransferpseudojob.h" #include "neochatconfig.h" #include "neochatconnection.h" -#include "neochatroommember.h" -#include "roomlastmessageprovider.h" -#include "spacehierarchycache.h" -#include "texthandler.h" -#include "urlhelper.h" +// #include "neochatroommember.h" +// #include "roomlastmessageprovider.h" +// #include "spacehierarchycache.h" +// #include "texthandler.h" +// #include "urlhelper.h" #ifndef Q_OS_ANDROID #include @@ -59,107 +60,107 @@ using namespace Quotient; -NeoChatRoom::NeoChatRoom(Connection *connection, QString roomId, JoinState joinState) - : Room(connection, std::move(roomId), joinState) +NeoChatRoom::NeoChatRoom(std::unique_ptr d, QObject *parent) + : Room(std::move(d), parent) { - m_mainCache = new ChatBarCache(this); - m_editCache = new ChatBarCache(this); - m_threadCache = new ChatBarCache(this); + // m_mainCache = new ChatBarCache(this); + // m_editCache = new ChatBarCache(this); + // m_threadCache = new ChatBarCache(this); - connect(connection, &Connection::accountDataChanged, this, &NeoChatRoom::updatePushNotificationState); - connect(this, &Room::fileTransferCompleted, this, [this] { - setFileUploadingProgress(0); - setHasFileUploading(false); - }); - connect(this, &Room::fileTransferCompleted, this, [this](QString eventId) { - const auto evtIt = findInTimeline(eventId); - if (evtIt != messageEvents().rend()) { - const auto m_event = evtIt->viewAs(); - QString mxcUrl; - if (auto event = eventCast(m_event)) { - if (event->has()) { - mxcUrl = event->get()->url().toString(); - } - } else if (auto event = eventCast(m_event)) { - mxcUrl = event->image().url().toString(); - } - if (mxcUrl.isEmpty()) { - return; - } - auto localPath = this->fileTransferInfo(eventId).localPath.toLocalFile(); - auto config = KSharedConfig::openStateConfig(u"neochatdownloads"_s)->group(u"downloads"_s); - config.writePathEntry(mxcUrl.mid(6), localPath); - } - }); + // connect(connection, &Connection::accountDataChanged, this, &NeoChatRoom::updatePushNotificationState); + // connect(this, &Room::fileTransferCompleted, this, [this] { + // setFileUploadingProgress(0); + // setHasFileUploading(false); + // }); + // connect(this, &Room::fileTransferCompleted, this, [this](QString eventId) { + // const auto evtIt = findInTimeline(eventId); + // if (evtIt != messageEvents().rend()) { + // const auto m_event = evtIt->viewAs(); + // QString mxcUrl; + // if (auto event = eventCast(m_event)) { + // if (event->has()) { + // mxcUrl = event->get()->url().toString(); + // } + // } else if (auto event = eventCast(m_event)) { + // mxcUrl = event->image().url().toString(); + // } + // if (mxcUrl.isEmpty()) { + // return; + // } + // auto localPath = this->fileTransferInfo(eventId).localPath.toLocalFile(); + // auto config = KSharedConfig::openStateConfig(u"neochatdownloads"_s)->group(u"downloads"_s); + // config.writePathEntry(mxcUrl.mid(6), localPath); + // } + // }); - connect(this, &Room::addedMessages, this, &NeoChatRoom::readMarkerLoadedChanged); - connect(this, &Room::aboutToAddHistoricalMessages, this, &NeoChatRoom::cleanupExtraEventRange); - connect(this, &Room::aboutToAddNewMessages, this, &NeoChatRoom::cleanupExtraEventRange); + // connect(this, &Room::addedMessages, this, &NeoChatRoom::readMarkerLoadedChanged); + // connect(this, &Room::aboutToAddHistoricalMessages, this, &NeoChatRoom::cleanupExtraEventRange); + // connect(this, &Room::aboutToAddNewMessages, this, &NeoChatRoom::cleanupExtraEventRange); - const auto &roomLastMessageProvider = RoomLastMessageProvider::self(); + // const auto &roomLastMessageProvider = RoomLastMessageProvider::self(); + // + // if (roomLastMessageProvider.hasKey(id())) { + // auto eventJson = QJsonDocument::fromJson(roomLastMessageProvider.read(id())).object(); + // if (!eventJson.isEmpty()) { + // auto event = loadEvent(eventJson); + // + // if (event != nullptr) { + // // m_cachedEvent = std::move(event); + // } + // } + // } + // connect(this, &Room::addedMessages, this, &NeoChatRoom::cacheLastEvent); - if (roomLastMessageProvider.hasKey(id())) { - auto eventJson = QJsonDocument::fromJson(roomLastMessageProvider.read(id())).object(); - if (!eventJson.isEmpty()) { - auto event = loadEvent(eventJson); + // connect(this, &Quotient::Room::eventsHistoryJobChanged, this, &NeoChatRoom::lastActiveTimeChanged); - if (event != nullptr) { - m_cachedEvent = std::move(event); - } - } - } - connect(this, &Room::addedMessages, this, &NeoChatRoom::cacheLastEvent); + // connect(this, &Room::joinStateChanged, this, [this](JoinState oldState, JoinState newState) { + // if (oldState == JoinState::Invite && newState != JoinState::Invite) { + // Q_EMIT isInviteChanged(); + // } + // }); + // connect(this, &Room::displaynameChanged, this, &NeoChatRoom::displayNameChanged); - connect(this, &Quotient::Room::eventsHistoryJobChanged, this, &NeoChatRoom::lastActiveTimeChanged); + // connect( + // this, + // &Room::baseStateLoaded, + // this, + // [this]() { + // updatePushNotificationState(u"m.push_rules"_s); + // + // Q_EMIT canEncryptRoomChanged(); + // }, + // Qt::SingleShotConnection); + // connect(this, &Room::changed, this, [this] { + // Q_EMIT canEncryptRoomChanged(); + // Q_EMIT parentIdsChanged(); + // Q_EMIT canonicalParentChanged(); + // Q_EMIT readOnlyChanged(); + // }); + // connect(connection, &Connection::capabilitiesLoaded, this, &NeoChatRoom::maxRoomVersionChanged); + // connect(this, &Room::changed, this, [this]() { + // Q_EMIT defaultUrlPreviewStateChanged(); + // }); + // connect(this, &Room::accountDataChanged, this, [this](QString type) { + // if (type == "org.matrix.room.preview_urls"_L1) { + // Q_EMIT urlPreviewEnabledChanged(); + // } + // }); + // connect(&SpaceHierarchyCache::instance(), &SpaceHierarchyCache::spaceHierarchyChanged, this, [this]() { + // if (isSpace()) { + // Q_EMIT childrenNotificationCountChanged(); + // Q_EMIT childrenHaveHighlightNotificationsChanged(); + // } + // }); + // connect(&SpaceHierarchyCache::instance(), &SpaceHierarchyCache::spaceNotifcationCountChanged, this, [this](const QStringList &spaces) { + // if (spaces.contains(id())) { + // Q_EMIT childrenNotificationCountChanged(); + // Q_EMIT childrenHaveHighlightNotificationsChanged(); + // } + // }); - connect(this, &Room::joinStateChanged, this, [this](JoinState oldState, JoinState newState) { - if (oldState == JoinState::Invite && newState != JoinState::Invite) { - Q_EMIT isInviteChanged(); - } - }); - connect(this, &Room::displaynameChanged, this, &NeoChatRoom::displayNameChanged); - - connect( - this, - &Room::baseStateLoaded, - this, - [this]() { - updatePushNotificationState(u"m.push_rules"_s); - - Q_EMIT canEncryptRoomChanged(); - }, - Qt::SingleShotConnection); - connect(this, &Room::changed, this, [this] { - Q_EMIT canEncryptRoomChanged(); - Q_EMIT parentIdsChanged(); - Q_EMIT canonicalParentChanged(); - Q_EMIT readOnlyChanged(); - }); - connect(connection, &Connection::capabilitiesLoaded, this, &NeoChatRoom::maxRoomVersionChanged); - connect(this, &Room::changed, this, [this]() { - Q_EMIT defaultUrlPreviewStateChanged(); - }); - connect(this, &Room::accountDataChanged, this, [this](QString type) { - if (type == "org.matrix.room.preview_urls"_L1) { - Q_EMIT urlPreviewEnabledChanged(); - } - }); - connect(&SpaceHierarchyCache::instance(), &SpaceHierarchyCache::spaceHierarchyChanged, this, [this]() { - if (isSpace()) { - Q_EMIT childrenNotificationCountChanged(); - Q_EMIT childrenHaveHighlightNotificationsChanged(); - } - }); - connect(&SpaceHierarchyCache::instance(), &SpaceHierarchyCache::spaceNotifcationCountChanged, this, [this](const QStringList &spaces) { - if (spaces.contains(id())) { - Q_EMIT childrenNotificationCountChanged(); - Q_EMIT childrenHaveHighlightNotificationsChanged(); - } - }); - - const auto neochatconnection = static_cast(connection); - Q_ASSERT(neochatconnection); - connect(neochatconnection, &NeoChatConnection::globalUrlPreviewEnabledChanged, this, &NeoChatRoom::urlPreviewEnabledChanged); + // const auto neochatconnection = static_cast(connection); + // Q_ASSERT(neochatconnection); + // connect(neochatconnection, &NeoChatConnection::globalUrlPreviewEnabledChanged, this, &NeoChatRoom::urlPreviewEnabledChanged); } bool NeoChatRoom::visible() const @@ -172,25 +173,26 @@ void NeoChatRoom::setVisible(bool visible) m_visible = visible; if (!visible) { - m_memberObjects.clear(); - m_eventContentModels.clear(); - m_threadModels.clear(); + // m_memberObjects.clear(); + // m_eventContentModels.clear(); + // m_threadModels.clear(); } } int NeoChatRoom::contextAwareNotificationCount() const { // DOn't include spaces, rooms that the user hasn't joined and rooms where the user has joined the successor. - if (isSpace() || joinState() != JoinState::Join || successor(JoinState::Join) != nullptr) { - return 0; - } - if (m_currentPushNotificationState == PushNotificationState::Mute) { - return 0; - } - if (m_currentPushNotificationState == PushNotificationState::MentionKeyword || isLowPriority()) { - return int(highlightCount()); - } - return int(notificationCount()); + // if (isSpace() || joinState() != JoinState::Join || successor(JoinState::Join) != nullptr) { + // return 0; + // } + // if (m_currentPushNotificationState == PushNotificationState::Mute) { + // return 0; + // } + // if (m_currentPushNotificationState == PushNotificationState::MentionKeyword || isLowPriority()) { + // return int(highlightCount()); + // } + // return int(notificationCount()); + return {}; // TODO } bool NeoChatRoom::hasFileUploading() const @@ -232,64 +234,64 @@ QCoro::Task NeoChatRoom::doUploadFile(QUrl url, QString body) co_return; } - auto mime = QMimeDatabase().mimeTypeForUrl(url); - url.setScheme("file"_L1); - QFileInfo fileInfo(url.isLocalFile() ? url.toLocalFile() : url.toString()); - EventContent::FileContentBase *content; - if (mime.name().startsWith("image/"_L1)) { - QImage image(url.toLocalFile()); - content = new EventContent::ImageContent(url, fileInfo.size(), mime, image.size(), fileInfo.fileName()); - } else if (mime.name().startsWith("audio/"_L1)) { - content = new EventContent::AudioContent(url, fileInfo.size(), mime, fileInfo.fileName()); - } else if (mime.name().startsWith("video/"_L1)) { - QMediaPlayer player; - player.setSource(url); - co_await qCoro(&player, &QMediaPlayer::mediaStatusChanged); - auto resolution = player.metaData().value(QMediaMetaData::Resolution).toSize(); - content = new EventContent::VideoContent(url, fileInfo.size(), mime, resolution, fileInfo.fileName()); - } else { - content = new EventContent::FileContent(url, fileInfo.size(), mime, fileInfo.fileName()); - } - QString txnId = postFile(body.isEmpty() ? url.fileName() : body, std::unique_ptr(content)); - setHasFileUploading(true); - connect(this, &Room::fileTransferCompleted, [this, txnId](const QString &id, FileSourceInfo) { - if (id == txnId) { - setFileUploadingProgress(0); - setHasFileUploading(false); - } - }); - connect(this, &Room::fileTransferFailed, [this, txnId](const QString &id, const QString & /*error*/) { - if (id == txnId) { - setFileUploadingProgress(0); - setHasFileUploading(false); - } - }); - connect(this, &Room::fileTransferProgress, [this, txnId](const QString &id, qint64 progress, qint64 total) { - if (id == txnId) { - setFileUploadingProgress(int(float(progress) / float(total) * 100)); - } - }); -#ifndef Q_OS_ANDROID - auto job = new FileTransferPseudoJob(FileTransferPseudoJob::Upload, url.toLocalFile(), txnId); - connect(this, &Room::fileTransferProgress, job, &FileTransferPseudoJob::fileTransferProgress); - connect(this, &Room::fileTransferCompleted, job, &FileTransferPseudoJob::fileTransferCompleted); - connect(this, &Room::fileTransferFailed, job, [this, job, txnId] { - auto info = fileTransferInfo(txnId); - if (info.status == FileTransferInfo::Cancelled) { - job->fileTransferCanceled(txnId); - } else { - job->fileTransferFailed(txnId); - } - }); - connect(job, &FileTransferPseudoJob::cancelRequested, this, &Room::cancelFileTransfer); - KIO::getJobTracker()->registerJob(job); - job->start(); -#endif + // auto mime = QMimeDatabase().mimeTypeForUrl(url); + // url.setScheme("file"_L1); + // QFileInfo fileInfo(url.isLocalFile() ? url.toLocalFile() : url.toString()); + // EventContent::FileContentBase *content; + // if (mime.name().startsWith("image/"_L1)) { + // QImage image(url.toLocalFile()); + // content = new EventContent::ImageContent(url, fileInfo.size(), mime, image.size(), fileInfo.fileName()); + // } else if (mime.name().startsWith("audio/"_L1)) { + // content = new EventContent::AudioContent(url, fileInfo.size(), mime, fileInfo.fileName()); + // } else if (mime.name().startsWith("video/"_L1)) { + // QMediaPlayer player; + // player.setSource(url); + // co_await qCoro(&player, &QMediaPlayer::mediaStatusChanged); + // auto resolution = player.metaData().value(QMediaMetaData::Resolution).toSize(); + // content = new EventContent::VideoContent(url, fileInfo.size(), mime, resolution, fileInfo.fileName()); + // } else { + // content = new EventContent::FileContent(url, fileInfo.size(), mime, fileInfo.fileName()); + // } + // QString txnId = postFile(body.isEmpty() ? url.fileName() : body, std::unique_ptr(content)); + // setHasFileUploading(true); + // connect(this, &Room::fileTransferCompleted, [this, txnId](const QString &id, FileSourceInfo) { + // if (id == txnId) { + // setFileUploadingProgress(0); + // setHasFileUploading(false); + // } + // }); + // connect(this, &Room::fileTransferFailed, [this, txnId](const QString &id, const QString & /*error*/) { + // if (id == txnId) { + // setFileUploadingProgress(0); + // setHasFileUploading(false); + // } + // }); + // connect(this, &Room::fileTransferProgress, [this, txnId](const QString &id, qint64 progress, qint64 total) { + // if (id == txnId) { + // setFileUploadingProgress(int(float(progress) / float(total) * 100)); + // } + // }); + // #ifndef Q_OS_ANDROID + // auto job = new FileTransferPseudoJob(FileTransferPseudoJob::Upload, url.toLocalFile(), txnId); + // connect(this, &Room::fileTransferProgress, job, &FileTransferPseudoJob::fileTransferProgress); + // connect(this, &Room::fileTransferCompleted, job, &FileTransferPseudoJob::fileTransferCompleted); + // connect(this, &Room::fileTransferFailed, job, [this, job, txnId] { + // auto info = fileTransferInfo(txnId); + // if (info.status == FileTransferInfo::Cancelled) { + // job->fileTransferCanceled(txnId); + // } else { + // job->fileTransferFailed(txnId); + // } + // }); + // connect(job, &FileTransferPseudoJob::cancelRequested, this, &Room::cancelFileTransfer); + // KIO::getJobTracker()->registerJob(job); + // job->start(); + // #endif } void NeoChatRoom::acceptInvitation() { - connection()->joinRoom(id()); + // connection()->joinRoom(id()); } void NeoChatRoom::forget() @@ -297,217 +299,220 @@ void NeoChatRoom::forget() QStringList roomIds{id()}; NeoChatRoom *predecessor = this; - while (predecessor = dynamic_cast(predecessor->predecessor(JoinState::Join)), predecessor && !roomIds.contains(predecessor->id())) { - roomIds += predecessor->id(); - } - - for (const auto &id : roomIds) { - connection()->forgetRoom(id); - } + // while (predecessor = dynamic_cast(predecessor->predecessor(JoinState::Join)), predecessor && !roomIds.contains(predecessor->id())) { + // roomIds += predecessor->id(); + // } + // + // for (const auto &id : roomIds) { + // connection()->forgetRoom(id); + // } } void NeoChatRoom::sendTypingNotification(bool isTyping) { - connection()->callApi(BackgroundRequest, localMember().id(), id(), isTyping, 10000); + // connection()->callApi(BackgroundRequest, localMember().id(), id(), isTyping, 10000); } -const RoomEvent *NeoChatRoom::lastEvent() const -{ - for (auto timelineItem = messageEvents().rbegin(); timelineItem < messageEvents().rend(); timelineItem++) { - const RoomEvent *event = timelineItem->get(); - - if (is(*event) || is(*event)) { - continue; - } - if (event->isRedacted()) { - continue; - } - - if (event->isStateEvent() && !NeoChatConfig::showStateEvent()) { - continue; - } - - if (auto roomMemberEvent = eventCast(event)) { - if ((roomMemberEvent->isJoin() || roomMemberEvent->isLeave()) && !NeoChatConfig::showLeaveJoinEvent()) { - continue; - } else if (roomMemberEvent->isRename() && !roomMemberEvent->isJoin() && !roomMemberEvent->isLeave() && !NeoChatConfig::showRename()) { - continue; - } else if (roomMemberEvent->isAvatarUpdate() && !roomMemberEvent->isJoin() && !roomMemberEvent->isLeave() && !NeoChatConfig::showAvatarUpdate()) { - continue; - } - } - if (event->isStateEvent() && static_cast(*event).repeatsState()) { - continue; - } - - if (auto roomEvent = eventCast(event)) { - if (!roomEvent->replacedEvent().isEmpty() && roomEvent->replacedEvent() != roomEvent->id()) { - continue; - } - } - - if (connection()->isIgnored(event->senderId())) { - continue; - } - - if (auto lastEvent = eventCast(event)) { - return lastEvent; - } - - if (auto lastEvent = eventCast(event)) { - return lastEvent; - } - if (auto lastEvent = eventCast(event)) { - return lastEvent; - } - } - - if (m_cachedEvent != nullptr) { - return std::to_address(m_cachedEvent); - } - - return nullptr; -} +// const RoomEvent *NeoChatRoom::lastEvent() const +// { +// for (auto timelineItem = messageEvents().rbegin(); timelineItem < messageEvents().rend(); timelineItem++) { +// const RoomEvent *event = timelineItem->get(); +// +// if (is(*event) || is(*event)) { +// continue; +// } +// if (event->isRedacted()) { +// continue; +// } +// +// if (event->isStateEvent() && !NeoChatConfig::showStateEvent()) { +// continue; +// } +// +// if (auto roomMemberEvent = eventCast(event)) { +// if ((roomMemberEvent->isJoin() || roomMemberEvent->isLeave()) && !NeoChatConfig::showLeaveJoinEvent()) { +// continue; +// } else if (roomMemberEvent->isRename() && !roomMemberEvent->isJoin() && !roomMemberEvent->isLeave() && !NeoChatConfig::showRename()) { +// continue; +// } else if (roomMemberEvent->isAvatarUpdate() && !roomMemberEvent->isJoin() && !roomMemberEvent->isLeave() && !NeoChatConfig::showAvatarUpdate()) +// { +// continue; +// } +// } +// if (event->isStateEvent() && static_cast(*event).repeatsState()) { +// continue; +// } +// +// if (auto roomEvent = eventCast(event)) { +// if (!roomEvent->replacedEvent().isEmpty() && roomEvent->replacedEvent() != roomEvent->id()) { +// continue; +// } +// } +// +// if (connection()->isIgnored(event->senderId())) { +// continue; +// } +// +// if (auto lastEvent = eventCast(event)) { +// return lastEvent; +// } +// +// if (auto lastEvent = eventCast(event)) { +// return lastEvent; +// } +// if (auto lastEvent = eventCast(event)) { +// return lastEvent; +// } +// } +// +// if (m_cachedEvent != nullptr) { +// return std::to_address(m_cachedEvent); +// } +// +// return nullptr; +// } void NeoChatRoom::cacheLastEvent() { - auto event = lastEvent(); - if (event != nullptr) { - auto &roomLastMessageProvider = RoomLastMessageProvider::self(); - - auto eventJson = QJsonDocument(event->fullJson()).toJson(QJsonDocument::Compact); - roomLastMessageProvider.write(id(), eventJson); - - auto uniqueEvent = loadEvent(event->fullJson()); - - if (event != nullptr) { - m_cachedEvent = std::move(uniqueEvent); - } - } + // auto event = lastEvent(); + // if (event != nullptr) { + // auto &roomLastMessageProvider = RoomLastMessageProvider::self(); + // + // auto eventJson = QJsonDocument(event->fullJson()).toJson(QJsonDocument::Compact); + // roomLastMessageProvider.write(id(), eventJson); + // + // auto uniqueEvent = loadEvent(event->fullJson()); + // + // if (event != nullptr) { + // m_cachedEvent = std::move(uniqueEvent); + // } + // } } bool NeoChatRoom::lastEventIsSpoiler() const { - if (auto event = lastEvent()) { - if (auto e = eventCast(event)) { - if (e->has() && e->content() && e->mimeType().name() == "text/html"_L1) { - auto htmlBody = e->get()->body; - return htmlBody.contains("data-mx-spoiler"_L1); - } - } - } + // if (auto event = lastEvent()) { + // if (auto e = eventCast(event)) { + // if (e->has() && e->content() && e->mimeType().name() == "text/html"_L1) { + // auto htmlBody = e->get()->body; + // return htmlBody.contains("data-mx-spoiler"_L1); + // } + // } + // } return false; } -bool NeoChatRoom::isEventHighlighted(const RoomEvent *e) const -{ - return highlights.contains(e); -} +// bool NeoChatRoom::isEventHighlighted(const RoomEvent *e) const +// { +// return highlights.contains(e); +// } -void NeoChatRoom::checkForHighlights(const Quotient::TimelineItem &ti) -{ - auto localMember = this->localMember(); - if (ti->senderId() == localMember.id()) { - return; - } - if (auto *e = ti.viewAs()) { - const auto &text = e->plainBody(); - if (text.contains(localMember.id()) || text.contains(localMember.disambiguatedName())) { - highlights.insert(e); - } - } -} +// void NeoChatRoom::checkForHighlights(const Quotient::TimelineItem &ti) +// { +// auto localMember = this->localMember(); +// if (ti->senderId() == localMember.id()) { +// return; +// } +// if (auto *e = ti.viewAs()) { +// const auto &text = e->plainBody(); +// if (text.contains(localMember.id()) || text.contains(localMember.disambiguatedName())) { +// highlights.insert(e); +// } +// } +// } -void NeoChatRoom::onAddNewTimelineEvents(timeline_iter_t from) -{ - std::for_each(from, messageEvents().cend(), [this](const TimelineItem &ti) { - checkForHighlights(ti); - }); -} +// void NeoChatRoom::onAddNewTimelineEvents(timeline_iter_t from) +// { +// std::for_each(from, messageEvents().cend(), [this](const TimelineItem &ti) { +// checkForHighlights(ti); +// }); +// } -void NeoChatRoom::onAddHistoricalTimelineEvents(rev_iter_t from) -{ - std::for_each(from, messageEvents().crend(), [this](const TimelineItem &ti) { - checkForHighlights(ti); - }); -} +// void NeoChatRoom::onAddHistoricalTimelineEvents(rev_iter_t from) +// { +// std::for_each(from, messageEvents().crend(), [this](const TimelineItem &ti) { +// checkForHighlights(ti); +// }); +// } -void NeoChatRoom::onRedaction(const RoomEvent &prevEvent, const RoomEvent & /*after*/) -{ - if (const auto &e = eventCast(&prevEvent)) { - if (auto relatedEventId = e->eventId(); !relatedEventId.isEmpty()) { - Q_EMIT updatedEvent(relatedEventId); - } - } -} +// void NeoChatRoom::onRedaction(const RoomEvent &prevEvent, const RoomEvent & /*after*/) +// { +// if (const auto &e = eventCast(&prevEvent)) { +// if (auto relatedEventId = e->eventId(); !relatedEventId.isEmpty()) { +// Q_EMIT updatedEvent(relatedEventId); +// } +// } +// } QDateTime NeoChatRoom::lastActiveTime() { - if (timelineSize() == 0) { - if (m_cachedEvent != nullptr) { - return m_cachedEvent->originTimestamp(); - } - return QDateTime(); - } - - if (auto event = lastEvent()) { - return event->originTimestamp(); - } - - // no message found, take last event - return messageEvents().rbegin()->get()->originTimestamp(); + return {}; + // if (timelineSize() == 0) { + // if (m_cachedEvent != nullptr) { + // return m_cachedEvent->originTimestamp(); + // } + // return QDateTime(); + // } + // + // if (auto event = lastEvent()) { + // return event->originTimestamp(); + // } + // + // // no message found, take last event + // return messageEvents().rbegin()->get()->originTimestamp(); } QUrl NeoChatRoom::avatarMediaUrl() const { - if (const auto avatar = Room::avatarUrl(); !avatar.isEmpty()) { - return avatar; - } - - // Use the first (excluding self) user's avatar for direct chats - const auto directChatMembers = this->directChatMembers(); - for (const auto member : directChatMembers) { - if (member != localMember()) { - return member.avatarUrl(); - } - } - return {}; + // if (const auto avatar = Room::avatarUrl(); !avatar.isEmpty()) { + // return avatar; + // } + // + // // Use the first (excluding self) user's avatar for direct chats + // const auto directChatMembers = this->directChatMembers(); + // for (const auto member : directChatMembers) { + // if (member != localMember()) { + // return member.avatarUrl(); + // } + // } + // + // return {}; } void NeoChatRoom::changeAvatar(const QUrl &localFile) { - const auto job = connection()->uploadFile(localFile.toLocalFile()); - if (isJobPending(job)) { - connect(job, &BaseJob::success, this, [this, job] { - connection()->callApi(id(), "m.room.avatar"_L1, QString(), QJsonObject{{"url"_L1, job->contentUri().toString()}}); - }); - } + // const auto job = connection()->uploadFile(localFile.toLocalFile()); + // if (isJobPending(job)) { + // connect(job, &BaseJob::success, this, [this, job] { + // connection()->callApi(id(), "m.room.avatar"_L1, QString(), QJsonObject{{"url"_L1, job->contentUri().toString()}}); + // }); + // } } -QString msgTypeToString(MessageEventType msgType) -{ - switch (msgType) { - case MessageEventType::Text: - return "m.text"_L1; - case MessageEventType::File: - return "m.file"_L1; - case MessageEventType::Audio: - return "m.audio"_L1; - case MessageEventType::Emote: - return "m.emote"_L1; - case MessageEventType::Image: - return "m.image"_L1; - case MessageEventType::Video: - return "m.video"_L1; - case MessageEventType::Notice: - return "m.notice"_L1; - case MessageEventType::Location: - return "m.location"_L1; - default: - return "m.text"_L1; - } -} +// QString msgTypeToString(MessageEventType msgType) +// { +// switch (msgType) { +// case MessageEventType::Text: +// return "m.text"_L1; +// case MessageEventType::File: +// return "m.file"_L1; +// case MessageEventType::Audio: +// return "m.audio"_L1; +// case MessageEventType::Emote: +// return "m.emote"_L1; +// case MessageEventType::Image: +// return "m.image"_L1; +// case MessageEventType::Video: +// return "m.video"_L1; +// case MessageEventType::Notice: +// return "m.notice"_L1; +// case MessageEventType::Location: +// return "m.location"_L1; +// default: +// return "m.text"_L1; +// } +// } void NeoChatRoom::toggleReaction(const QString &eventId, const QString &reaction) { @@ -515,78 +520,83 @@ void NeoChatRoom::toggleReaction(const QString &eventId, const QString &reaction return; } - const auto eventIt = findInTimeline(eventId); - if (eventIt == historyEdge()) { - return; - } - - const auto &evt = **eventIt; - - QStringList redactEventIds; // What if there are multiple reaction events? - - const auto &annotations = relatedEvents(evt, EventRelation::AnnotationType); - if (!annotations.isEmpty()) { - for (const auto &a : annotations) { - if (auto e = eventCast(a)) { - if (e->key() != reaction) { - continue; - } - - if (e->senderId() == localMember().id()) { - redactEventIds.push_back(e->id()); - break; - } - } - } - } - - if (!redactEventIds.isEmpty()) { - for (const auto &redactEventId : redactEventIds) { - redactEvent(redactEventId); - } - } else { - postReaction(eventId, reaction); - } + // const auto eventIt = findInTimeline(eventId); + // if (eventIt == historyEdge()) { + // return; + // } + // + // const auto &evt = **eventIt; + // + // QStringList redactEventIds; // What if there are multiple reaction events? + // + // const auto &annotations = relatedEvents(evt, EventRelation::AnnotationType); + // if (!annotations.isEmpty()) { + // for (const auto &a : annotations) { + // if (auto e = eventCast(a)) { + // if (e->key() != reaction) { + // continue; + // } + // + // if (e->senderId() == localMember().id()) { + // redactEventIds.push_back(e->id()); + // break; + // } + // } + // } + // } + // + // if (!redactEventIds.isEmpty()) { + // for (const auto &redactEventId : redactEventIds) { + // redactEvent(redactEventId); + // } + // } else { + // postReaction(eventId, reaction); + // } } bool NeoChatRoom::containsUser(const QString &userID) const { - return memberState(userID) != Membership::Leave; + return false; + // return memberState(userID) != Membership::Leave; } bool NeoChatRoom::canSendEvent(const QString &eventType) const { - auto plEvent = currentState().get(); - if (!plEvent) { - return false; - } - auto pl = plEvent->powerLevelForEvent(eventType); - auto currentPl = plEvent->powerLevelForUser(localMember().id()); - - return currentPl >= pl; + // auto plEvent = currentState().get(); + // if (!plEvent) { + // return false; + // } + // auto pl = plEvent->powerLevelForEvent(eventType); + // auto currentPl = plEvent->powerLevelForUser(localMember().id()); + // + // return currentPl >= pl; + return false; } bool NeoChatRoom::canSendState(const QString &eventType) const { - auto plEvent = currentState().get(); - if (!plEvent) { - return false; - } - auto pl = plEvent->powerLevelForState(eventType); - auto currentPl = plEvent->powerLevelForUser(localMember().id()); - - return currentPl >= pl; + // auto plEvent = currentState().get(); + // if (!plEvent) { + // return false; + // } + // auto pl = plEvent->powerLevelForState(eventType); + // auto currentPl = plEvent->powerLevelForUser(localMember().id()); + // + // return currentPl >= pl; + return false; } bool NeoChatRoom::readMarkerLoaded() const { - const auto it = findInTimeline(lastFullyReadEventId()); - return it != historyEdge(); + // const auto it = findInTimeline(lastFullyReadEventId()); + // return it != historyEdge(); + return false; } bool NeoChatRoom::isInvite() const { - return joinState() == JoinState::Invite; + // return joinState() == JoinState::Invite; + return false; } bool NeoChatRoom::readOnly() const @@ -596,23 +606,24 @@ bool NeoChatRoom::readOnly() const bool NeoChatRoom::isUserBanned(const QString &user) const { - auto roomMemberEvent = currentState().get(user); - if (!roomMemberEvent) { - return false; - } - return roomMemberEvent->membership() == Membership::Ban; + // auto roomMemberEvent = currentState().get(user); + // if (!roomMemberEvent) { + // return false; + // } + // return roomMemberEvent->membership() == Membership::Ban; + return false; } void NeoChatRoom::deleteMessagesByUser(const QString &user, const QString &reason) { - doDeleteMessagesByUser(user, reason); + // doDeleteMessagesByUser(user, reason); } QString NeoChatRoom::historyVisibility() const { - if (auto stateEvent = currentState().get("m.room.history_visibility"_L1)) { - return stateEvent->contentJson()["history_visibility"_L1].toString(); - } + // if (auto stateEvent = currentState().get("m.room.history_visibility"_L1)) { + // return stateEvent->contentJson()["history_visibility"_L1].toString(); + // } return {}; } @@ -623,20 +634,21 @@ void NeoChatRoom::setHistoryVisibility(const QString &historyVisibilityRule) return; } - setState("m.room.history_visibility"_L1, {}, QJsonObject{{"history_visibility"_L1, historyVisibilityRule}}); + // setState("m.room.history_visibility"_L1, {}, QJsonObject{{"history_visibility"_L1, historyVisibilityRule}}); // Not emitting historyVisibilityChanged() here, since that would override the change in the UI with the *current* value, which is not the *new* value. } bool NeoChatRoom::defaultUrlPreviewState() const { - auto urlPreviewsDisabled = currentState().get("org.matrix.room.preview_urls"_L1); + // auto urlPreviewsDisabled = currentState().get("org.matrix.room.preview_urls"_L1); - // Some rooms will not have this state event set so check for a nullptr return. - if (urlPreviewsDisabled != nullptr) { - return !urlPreviewsDisabled->contentJson()["disable"_L1].toBool(); - } else { - return false; - } + // // Some rooms will not have this state event set so check for a nullptr return. + // if (urlPreviewsDisabled != nullptr) { + // return !urlPreviewsDisabled->contentJson()["disable"_L1].toBool(); + // } else { + // return false; + // } + return false; } void NeoChatRoom::setDefaultUrlPreviewState(const bool &defaultUrlPreviewState) @@ -675,19 +687,20 @@ void NeoChatRoom::setDefaultUrlPreviewState(const bool &defaultUrlPreviewState) * * You just have to set disable to true to disable URL previews by default. */ - setState("org.matrix.room.preview_urls"_L1, {}, QJsonObject{{"disable"_L1, !defaultUrlPreviewState}}); + // setState("org.matrix.room.preview_urls"_L1, {}, QJsonObject{{"disable"_L1, !defaultUrlPreviewState}}); } bool NeoChatRoom::urlPreviewEnabled() const { - if (!static_cast(connection())->globalUrlPreviewEnabled()) { - return false; - } - if (hasAccountData("org.matrix.room.preview_urls"_L1)) { - return !accountData("org.matrix.room.preview_urls"_L1)->contentJson()["disable"_L1].toBool(); - } else { - return defaultUrlPreviewState(); - } + // if (!static_cast(connection())->globalUrlPreviewEnabled()) { + // return false; + // } + // if (hasAccountData("org.matrix.room.preview_urls"_L1)) { + // return !accountData("org.matrix.room.preview_urls"_L1)->contentJson()["disable"_L1].toBool(); + // } else { + // return defaultUrlPreviewState(); + // } + return false; } void NeoChatRoom::setUrlPreviewEnabled(const bool &urlPreviewEnabled) @@ -703,71 +716,72 @@ void NeoChatRoom::setUrlPreviewEnabled(const bool &urlPreviewEnabled) * "type": "org.matrix.room.preview_urls", * } */ - connection()->callApi(localMember().id(), - id(), - "org.matrix.room.preview_urls"_L1, - QJsonObject{{"disable"_L1, !urlPreviewEnabled}}); + // connection()->callApi(localMember().id(), + // id(), + // "org.matrix.room.preview_urls"_L1, + // QJsonObject{{"disable"_L1, !urlPreviewEnabled}}); } void NeoChatRoom::setUserPowerLevel(const QString &userID, const int &powerLevel) { - if (joinedCount() <= 1) { - qWarning() << "Cannot modify the power level of the only user"; - return; - } + // if (joinedCount() <= 1) { + // qWarning() << "Cannot modify the power level of the only user"; + // return; + // } if (!canSendState("m.room.power_levels"_L1)) { qWarning() << "Power level too low to set user power levels"; return; } - if (!isMember(userID)) { - qWarning() << "User is not a member of this room so power level cannot be set"; - return; - } + // if (!isMember(userID)) { + // qWarning() << "User is not a member of this room so power level cannot be set"; + // return; + // } int clampPowerLevel = std::clamp(powerLevel, -1, 100); - auto powerLevelContent = currentState().get("m.room.power_levels"_L1)->contentJson(); - auto powerLevelUserOverrides = powerLevelContent["users"_L1].toObject(); + // auto powerLevelContent = currentState().get("m.room.power_levels"_L1)->contentJson(); + // auto powerLevelUserOverrides = powerLevelContent["users"_L1].toObject(); - if (powerLevelUserOverrides[userID] != clampPowerLevel) { - powerLevelUserOverrides[userID] = clampPowerLevel; - powerLevelContent["users"_L1] = powerLevelUserOverrides; - - setState("m.room.power_levels"_L1, {}, powerLevelContent); - } + // if (powerLevelUserOverrides[userID] != clampPowerLevel) { + // powerLevelUserOverrides[userID] = clampPowerLevel; + // powerLevelContent["users"_L1] = powerLevelUserOverrides; + // + // setState("m.room.power_levels"_L1, {}, powerLevelContent); + // } } -QCoro::Task NeoChatRoom::doDeleteMessagesByUser(const QString &user, QString reason) -{ - QStringList events; - for (const auto &event : messageEvents()) { - if (event->senderId() == user && !event->isRedacted() && !event.viewAs() && !event->isStateEvent()) { - events += event->id(); - } - } - for (const auto &e : events) { - auto job = connection()->callApi(id(), QString::fromLatin1(QUrl::toPercentEncoding(e)), connection()->generateTxnId(), reason); - co_await qCoro(job.get(), &BaseJob::finished); - if (job->error() != BaseJob::Success) { - qWarning() << "Error: \"" << job->error() << "\" while deleting messages. Aborting"; - break; - } - } -} +// QCoro::Task NeoChatRoom::doDeleteMessagesByUser(const QString &user, QString reason) +// { +// QStringList events; +// for (const auto &event : messageEvents()) { +// if (event->senderId() == user && !event->isRedacted() && !event.viewAs() && !event->isStateEvent()) { +// events += event->id(); +// } +// } +// for (const auto &e : events) { +// auto job = connection()->callApi(id(), QString::fromLatin1(QUrl::toPercentEncoding(e)), connection()->generateTxnId(), reason); +// co_await qCoro(job.get(), &BaseJob::finished); +// if (job->error() != BaseJob::Success) { +// qWarning() << "Error: \"" << job->error() << "\" while deleting messages. Aborting"; +// break; +// } +// } +// } bool NeoChatRoom::hasParent() const { - return currentState().eventsOfType("m.space.parent"_L1).size() > 0; + // return currentState().eventsOfType("m.space.parent"_L1).size() > 0; + return false; } QList NeoChatRoom::parentIds() const { - auto parentEvents = currentState().eventsOfType("m.space.parent"_L1); + // auto parentEvents = currentState().eventsOfType("m.space.parent"_L1); QList parentIds; - for (const auto &parentEvent : parentEvents) { - if (parentEvent->contentJson().contains("via"_L1) && !parentEvent->contentPart("via"_L1).isEmpty()) { - parentIds += parentEvent->stateKey(); - } - } + // for (const auto &parentEvent : parentEvents) { + // if (parentEvent->contentJson().contains("via"_L1) && !parentEvent->contentPart("via"_L1).isEmpty()) { + // parentIds += parentEvent->stateKey(); + // } + // } return parentIds; } @@ -776,26 +790,26 @@ QList NeoChatRoom::parentObjects(bool multiLevel) const QList parentObjects; QList parentIds = this->parentIds(); for (const auto &parentId : parentIds) { - if (auto parentObject = static_cast(connection()->room(parentId))) { - parentObjects += parentObject; - if (multiLevel) { - parentObjects += parentObject->parentObjects(true); - } - } + // if (auto parentObject = static_cast(connection()->room(parentId))) { + // parentObjects += parentObject; + // if (multiLevel) { + // parentObjects += parentObject->parentObjects(true); + // } + // } } return parentObjects; } QString NeoChatRoom::canonicalParent() const { - auto parentEvents = currentState().eventsOfType("m.space.parent"_L1); - for (const auto &parentEvent : parentEvents) { - if (parentEvent->contentJson().contains("via"_L1) && !parentEvent->contentPart("via"_L1).isEmpty()) { - if (parentEvent->contentPart("canonical"_L1)) { - return parentEvent->stateKey(); - } - } - } + // auto parentEvents = currentState().eventsOfType("m.space.parent"_L1); + // for (const auto &parentEvent : parentEvents) { + // if (parentEvent->contentJson().contains("via"_L1) && !parentEvent->contentPart("via"_L1).isEmpty()) { + // if (parentEvent->contentPart("canonical"_L1)) { + // return parentEvent->stateKey(); + // } + // } + // } return {}; } @@ -804,23 +818,23 @@ void NeoChatRoom::setCanonicalParent(const QString &parentId) if (!canModifyParent(parentId)) { return; } - if (const auto &parent = currentState().get("m.space.parent"_L1, parentId)) { - auto content = parent->contentJson(); - content.insert("canonical"_L1, true); - setState("m.space.parent"_L1, parentId, content); - } else { - return; - } + // if (const auto &parent = currentState().get("m.space.parent"_L1, parentId)) { + // auto content = parent->contentJson(); + // content.insert("canonical"_L1, true); + // setState("m.space.parent"_L1, parentId, content); + // } else { + // return; + // } // Only one canonical parent can exist so make sure others are set false. - auto parentEvents = currentState().eventsOfType("m.space.parent"_L1); - for (const auto &parentEvent : parentEvents) { - if (parentEvent->contentPart("canonical"_L1) && parentEvent->stateKey() != parentId) { - auto content = parentEvent->contentJson(); - content.insert("canonical"_L1, false); - setState("m.space.parent"_L1, parentEvent->stateKey(), content); - } - } + // auto parentEvents = currentState().eventsOfType("m.space.parent"_L1); + // for (const auto &parentEvent : parentEvents) { + // if (parentEvent->contentPart("canonical"_L1) && parentEvent->stateKey() != parentId) { + // auto content = parentEvent->contentJson(); + // content.insert("canonical"_L1, false); + // setState("m.space.parent"_L1, parentEvent->stateKey(), content); + // } + // } } bool NeoChatRoom::canModifyParent(const QString &parentId) const @@ -830,22 +844,22 @@ bool NeoChatRoom::canModifyParent(const QString &parentId) const } // If we can't peek the parent we assume that we neither have permission nor is // there an existing space child event for this room. - if (auto parent = static_cast(connection()->room(parentId))) { - if (!parent->isSpace()) { - return false; - } - // If the user is allowed to set space child events in the parent they are - // allowed to set the space as a parent (even if a space child event doesn't - // exist). - if (parent->canSendState("m.space.child"_L1)) { - return true; - } - // If the parent has a space child event the user can set as a parent (even - // if they don't have permission to set space child events in that parent). - if (parent->currentState().contains("m.space.child"_L1, id())) { - return true; - } - } + // if (auto parent = static_cast(connection()->room(parentId))) { + // if (!parent->isSpace()) { + // return false; + // } + // // If the user is allowed to set space child events in the parent they are + // // allowed to set the space as a parent (even if a space child event doesn't + // // exist). + // if (parent->canSendState("m.space.child"_L1)) { + // return true; + // } + // // If the parent has a space child event the user can set as a parent (even + // // if they don't have permission to set space child events in that parent). + // if (parent->currentState().contains("m.space.child"_L1, id())) { + // return true; + // } + // } return false; } @@ -856,22 +870,22 @@ void NeoChatRoom::addParent(const QString &parentId, bool canonical, bool setPar } if (canonical) { // Only one canonical parent can exist so make sure others are set false. - auto parentEvents = currentState().eventsOfType("m.space.parent"_L1); - for (const auto &parentEvent : parentEvents) { - if (parentEvent->contentPart("canonical"_L1)) { - auto content = parentEvent->contentJson(); - content.insert("canonical"_L1, false); - setState("m.space.parent"_L1, parentEvent->stateKey(), content); - } - } + // auto parentEvents = currentState().eventsOfType("m.space.parent"_L1); + // for (const auto &parentEvent : parentEvents) { + // if (parentEvent->contentPart("canonical"_L1)) { + // auto content = parentEvent->contentJson(); + // content.insert("canonical"_L1, false); + // setState("m.space.parent"_L1, parentEvent->stateKey(), content); + // } + // } } - setState("m.space.parent"_L1, parentId, QJsonObject{{"canonical"_L1, canonical}, {"via"_L1, QJsonArray{connection()->domain()}}}); + // setState("m.space.parent"_L1, parentId, QJsonObject{{"canonical"_L1, canonical}, {"via"_L1, QJsonArray{connection()->domain()}}}); if (setParentChild) { - if (auto parent = static_cast(connection()->room(parentId))) { - parent->setState("m.space.child"_L1, id(), QJsonObject{{"via"_L1, QJsonArray{connection()->domain()}}}); - } + // if (auto parent = static_cast(connection()->room(parentId))) { + // parent->setState("m.space.child"_L1, id(), QJsonObject{{"via"_L1, QJsonArray{connection()->domain()}}}); + // } } } @@ -880,20 +894,21 @@ void NeoChatRoom::removeParent(const QString &parentId) if (!canModifyParent(parentId)) { return; } - if (!currentState().contains("m.space.parent"_L1, parentId)) { - return; - } - setState("m.space.parent"_L1, parentId, {}); + // if (!currentState().contains("m.space.parent"_L1, parentId)) { + // return; + // } + // setState("m.space.parent"_L1, parentId, {}); } bool NeoChatRoom::isSpace() const { - const auto creationEvent = this->creation(); - if (!creationEvent) { - return false; - } + // const auto creationEvent = this->creation(); + // if (!creationEvent) { + // return false; + // } - return creationEvent->roomType() == RoomType::Space; + // return creationEvent->roomType() == RoomType::Space; + return false; } qsizetype NeoChatRoom::childrenNotificationCount() @@ -901,7 +916,7 @@ qsizetype NeoChatRoom::childrenNotificationCount() if (!isSpace()) { return 0; } - return SpaceHierarchyCache::instance().notificationCountForSpace(id()); + return {}; // SpaceHierarchyCache::instance().notificationCountForSpace(id()); } bool NeoChatRoom::childrenHaveHighlightNotifications() const @@ -909,7 +924,7 @@ bool NeoChatRoom::childrenHaveHighlightNotifications() const if (!isSpace()) { return false; } - return SpaceHierarchyCache::instance().spaceHasHighlightNotifications(id()); + return {}; // SpaceHierarchyCache::instance().spaceHasHighlightNotifications(id()); } void NeoChatRoom::addChild(const QString &childId, bool setChildParent, bool canonical, bool suggested, const QString &order) @@ -920,26 +935,26 @@ void NeoChatRoom::addChild(const QString &childId, bool setChildParent, bool can if (!canSendEvent("m.space.child"_L1)) { return; } - setState("m.space.child"_L1, childId, QJsonObject{{"via"_L1, QJsonArray{connection()->domain()}}, {"suggested"_L1, suggested}, {"order"_L1, order}}); + // setState("m.space.child"_L1, childId, QJsonObject{{"via"_L1, QJsonArray{connection()->domain()}}, {"suggested"_L1, suggested}, {"order"_L1, order}}); if (setChildParent) { - if (auto child = static_cast(connection()->room(childId))) { - if (child->canSendState("m.space.parent"_L1)) { - child->setState("m.space.parent"_L1, id(), QJsonObject{{"canonical"_L1, canonical}, {"via"_L1, QJsonArray{connection()->domain()}}}); - - if (canonical) { - // Only one canonical parent can exist so make sure others are set to false. - auto parentEvents = child->currentState().eventsOfType("m.space.parent"_L1); - for (const auto &parentEvent : parentEvents) { - if (parentEvent->contentPart("canonical"_L1)) { - auto content = parentEvent->contentJson(); - content.insert("canonical"_L1, false); - setState("m.space.parent"_L1, parentEvent->stateKey(), content); - } - } - } - } - } + // if (auto child = static_cast(connection()->room(childId))) { + // if (child->canSendState("m.space.parent"_L1)) { + // child->setState("m.space.parent"_L1, id(), QJsonObject{{"canonical"_L1, canonical}, {"via"_L1, QJsonArray{connection()->domain()}}}); + // + // if (canonical) { + // // Only one canonical parent can exist so make sure others are set to false. + // auto parentEvents = child->currentState().eventsOfType("m.space.parent"_L1); + // for (const auto &parentEvent : parentEvents) { + // if (parentEvent->contentPart("canonical"_L1)) { + // auto content = parentEvent->contentJson(); + // content.insert("canonical"_L1, false); + // setState("m.space.parent"_L1, parentEvent->stateKey(), content); + // } + // } + // } + // } + // } } } @@ -951,24 +966,25 @@ void NeoChatRoom::removeChild(const QString &childId, bool unsetChildParent) if (!canSendEvent("m.space.child"_L1)) { return; } - setState("m.space.child"_L1, childId, {}); + // setState("m.space.child"_L1, childId, {}); if (unsetChildParent) { - if (auto child = static_cast(connection()->room(childId))) { - if (child->canSendState("m.space.parent"_L1) && child->currentState().contains("m.space.parent"_L1, id())) { - child->setState("m.space.parent"_L1, id(), {}); - } - } + // if (auto child = static_cast(connection()->room(childId))) { + // if (child->canSendState("m.space.parent"_L1) && child->currentState().contains("m.space.parent"_L1, id())) { + // child->setState("m.space.parent"_L1, id(), {}); + // } + // } } } bool NeoChatRoom::isSuggested(const QString &childId) { - if (!currentState().contains("m.space.child"_L1, childId)) { - return false; - } - const auto childEvent = currentState().get("m.space.child"_L1, childId); - return childEvent->contentPart("suggested"_L1); + // if (!currentState().contains("m.space.child"_L1, childId)) { + // return false; + // } + // const auto childEvent = currentState().get("m.space.child"_L1, childId); + // return childEvent->contentPart("suggested"_L1); + return false; } void NeoChatRoom::toggleChildSuggested(const QString &childId) @@ -979,11 +995,11 @@ void NeoChatRoom::toggleChildSuggested(const QString &childId) if (!canSendEvent("m.space.child"_L1)) { return; } - if (const auto childEvent = currentState().get("m.space.child"_L1, childId)) { - auto content = childEvent->contentJson(); - content.insert("suggested"_L1, !childEvent->contentPart("suggested"_L1)); - setState("m.space.child"_L1, childId, content); - } + // if (const auto childEvent = currentState().get("m.space.child"_L1, childId)) { + // auto content = childEvent->contentJson(); + // content.insert("suggested"_L1, !childEvent->contentPart("suggested"_L1)); + // setState("m.space.child"_L1, childId, content); + // } } void NeoChatRoom::setChildOrder(const QString &childId, const QString &order) @@ -994,18 +1010,18 @@ void NeoChatRoom::setChildOrder(const QString &childId, const QString &order) if (!canSendEvent("m.space.child"_L1)) { return; } - if (const auto childEvent = currentState().get("m.space.child"_L1, childId)) { - auto content = childEvent->contentJson(); - if (!content.contains("via"_L1)) { - return; - } - if (content.value("order"_L1).toString() == order) { - return; - } - - content.insert("order"_L1, order); - setState("m.space.child"_L1, childId, content); - } + // if (const auto childEvent = currentState().get("m.space.child"_L1, childId)) { + // auto content = childEvent->contentJson(); + // if (!content.contains("via"_L1)) { + // return; + // } + // if (content.value("order"_L1).toString() == order) { + // return; + // } + // + // content.insert("order"_L1, order); + // setState("m.space.child"_L1, childId, content); + // } } PushNotificationState::State NeoChatRoom::pushNotificationState() const @@ -1035,28 +1051,28 @@ void NeoChatRoom::setPushNotificationState(PushNotificationState::State state) * Note to prevent race conditions any rule that is going ot be overridden later is not removed. * If the default push notification state is chosen any existing rule needs to be removed. */ - QJsonObject accountData = connection()->accountDataJson("m.push_rules"_L1); + // QJsonObject accountData = connection()->accountDataJson("m.push_rules"_L1); // For default and mute check for a room rule and remove if found. if (state == PushNotificationState::Default || state == PushNotificationState::Mute) { - QJsonArray roomRuleArray = accountData["global"_L1].toObject()["room"_L1].toArray(); - for (const auto &i : roomRuleArray) { - QJsonObject roomRule = i.toObject(); - if (roomRule["rule_id"_L1] == id()) { - connection()->callApi("room"_L1, id()); - } - } + // QJsonArray roomRuleArray = accountData["global"_L1].toObject()["room"_L1].toArray(); + // for (const auto &i : roomRuleArray) { + // QJsonObject roomRule = i.toObject(); + // if (roomRule["rule_id"_L1] == id()) { + // connection()->callApi("room"_L1, id()); + // } + // } } // For default, all and @mentions and keywords check for an override rule and remove if found. if (state == PushNotificationState::Default || state == PushNotificationState::All || state == PushNotificationState::MentionKeyword) { - QJsonArray overrideRuleArray = accountData["global"_L1].toObject()["override"_L1].toArray(); - for (const auto &i : overrideRuleArray) { - QJsonObject overrideRule = i.toObject(); - if (overrideRule["rule_id"_L1] == id()) { - connection()->callApi("override"_L1, id()); - } - } + // QJsonArray overrideRuleArray = accountData["global"_L1].toObject()["override"_L1].toArray(); + // for (const auto &i : overrideRuleArray) { + // QJsonObject overrideRule = i.toObject(); + // if (overrideRule["rule_id"_L1] == id()) { + // connection()->callApi("override"_L1, id()); + // } + // } } if (state == PushNotificationState::Mute) { @@ -1083,20 +1099,20 @@ void NeoChatRoom::setPushNotificationState(PushNotificationState::State state) * } * ] */ - PushCondition pushCondition; - pushCondition.kind = "event_match"_L1; - pushCondition.key = "room_id"_L1; - pushCondition.pattern = id(); - const QList conditions = {pushCondition}; - - // Add new override rule and make sure it's enabled - auto job = connection()->callApi("override"_L1, id(), actions, QString(), QString(), conditions, QString()); - connect(job, &BaseJob::success, this, [this]() { - auto enableJob = connection()->callApi("override"_L1, id(), true); - connect(enableJob, &BaseJob::success, this, [this]() { - m_pushNotificationStateUpdating = false; - }); - }); + // PushCondition pushCondition; + // pushCondition.kind = "event_match"_L1; + // pushCondition.key = "room_id"_L1; + // pushCondition.pattern = id(); + // const QList conditions = {pushCondition}; + // + // // Add new override rule and make sure it's enabled + // auto job = connection()->callApi("override"_L1, id(), actions, QString(), QString(), conditions, QString()); + // connect(job, &BaseJob::success, this, [this]() { + // auto enableJob = connection()->callApi("override"_L1, id(), true); + // connect(enableJob, &BaseJob::success, this, [this]() { + // m_pushNotificationStateUpdating = false; + // }); + // }); } else if (state == PushNotificationState::MentionKeyword) { /** * To only get notifcations for @ mentions and keywords a room rule with "don't_notify" is set. @@ -1114,15 +1130,15 @@ void NeoChatRoom::setPushNotificationState(PushNotificationState::State state) */ const QList actions = {"dont_notify"_L1}; // No conditions for a room rule - const QList conditions; - - auto setJob = connection()->callApi("room"_L1, id(), actions, QString(), QString(), conditions, QString()); - connect(setJob, &BaseJob::success, this, [this]() { - auto enableJob = connection()->callApi("room"_L1, id(), true); - connect(enableJob, &BaseJob::success, this, [this]() { - m_pushNotificationStateUpdating = false; - }); - }); + // const QList conditions; + // + // auto setJob = connection()->callApi("room"_L1, id(), actions, QString(), QString(), conditions, QString()); + // connect(setJob, &BaseJob::success, this, [this]() { + // auto enableJob = connection()->callApi("room"_L1, id(), true); + // connect(enableJob, &BaseJob::success, this, [this]() { + // m_pushNotificationStateUpdating = false; + // }); + // }); } else if (state == PushNotificationState::All) { /** * To send a notification for all room messages a room rule with "notify" is set. @@ -1144,16 +1160,16 @@ void NeoChatRoom::setPushNotificationState(PushNotificationState::State state) tweaks.insert("value"_L1, "default"_L1); const QList actions = {"notify"_L1, tweaks}; // No conditions for a room rule - const QList conditions; - - // Add new room rule and make sure enabled - auto setJob = connection()->callApi("room"_L1, id(), actions, QString(), QString(), conditions, QString()); - connect(setJob, &BaseJob::success, this, [this]() { - auto enableJob = connection()->callApi("room"_L1, id(), true); - connect(enableJob, &BaseJob::success, this, [this]() { - m_pushNotificationStateUpdating = false; - }); - }); + // const QList conditions; + // + // // Add new room rule and make sure enabled + // auto setJob = connection()->callApi("room"_L1, id(), actions, QString(), QString(), conditions, QString()); + // connect(setJob, &BaseJob::success, this, [this]() { + // auto enableJob = connection()->callApi("room"_L1, id(), true); + // connect(enableJob, &BaseJob::success, this, [this]() { + // m_pushNotificationStateUpdating = false; + // }); + // }); } m_currentPushNotificationState = state; @@ -1166,49 +1182,49 @@ void NeoChatRoom::updatePushNotificationState(QString type) return; } - QJsonObject accountData = connection()->accountDataJson("m.push_rules"_L1); - - // First look for a room rule with the room id - QJsonArray roomRuleArray = accountData["global"_L1].toObject()["room"_L1].toArray(); - for (const auto &i : roomRuleArray) { - QJsonObject roomRule = i.toObject(); - if (roomRule["rule_id"_L1] == id()) { - if (roomRule["actions"_L1].toArray().size() == 0) { - m_currentPushNotificationState = PushNotificationState::MentionKeyword; - Q_EMIT pushNotificationStateChanged(m_currentPushNotificationState); - return; - } - QString notifyAction = roomRule["actions"_L1].toArray()[0].toString(); - if (notifyAction == "notify"_L1) { - m_currentPushNotificationState = PushNotificationState::All; - Q_EMIT pushNotificationStateChanged(m_currentPushNotificationState); - return; - } else if (notifyAction == "dont_notify"_L1) { - m_currentPushNotificationState = PushNotificationState::MentionKeyword; - Q_EMIT pushNotificationStateChanged(m_currentPushNotificationState); - return; - } - } - } - - // Check for an override rule with the room id - QJsonArray overrideRuleArray = accountData["global"_L1].toObject()["override"_L1].toArray(); - for (const auto &i : overrideRuleArray) { - QJsonObject overrideRule = i.toObject(); - if (overrideRule["rule_id"_L1] == id()) { - if (overrideRule["actions"_L1].toArray().isEmpty()) { - m_currentPushNotificationState = PushNotificationState::Mute; - Q_EMIT pushNotificationStateChanged(m_currentPushNotificationState); - return; - } - QString notifyAction = overrideRule["actions"_L1].toArray()[0].toString(); - if (notifyAction == "dont_notify"_L1) { - m_currentPushNotificationState = PushNotificationState::Mute; - Q_EMIT pushNotificationStateChanged(m_currentPushNotificationState); - return; - } - } - } + // QJsonObject accountData = connection()->accountDataJson("m.push_rules"_L1); + // + // // First look for a room rule with the room id + // QJsonArray roomRuleArray = accountData["global"_L1].toObject()["room"_L1].toArray(); + // for (const auto &i : roomRuleArray) { + // QJsonObject roomRule = i.toObject(); + // if (roomRule["rule_id"_L1] == id()) { + // if (roomRule["actions"_L1].toArray().size() == 0) { + // m_currentPushNotificationState = PushNotificationState::MentionKeyword; + // Q_EMIT pushNotificationStateChanged(m_currentPushNotificationState); + // return; + // } + // QString notifyAction = roomRule["actions"_L1].toArray()[0].toString(); + // if (notifyAction == "notify"_L1) { + // m_currentPushNotificationState = PushNotificationState::All; + // Q_EMIT pushNotificationStateChanged(m_currentPushNotificationState); + // return; + // } else if (notifyAction == "dont_notify"_L1) { + // m_currentPushNotificationState = PushNotificationState::MentionKeyword; + // Q_EMIT pushNotificationStateChanged(m_currentPushNotificationState); + // return; + // } + // } + // } + // + // // Check for an override rule with the room id + // QJsonArray overrideRuleArray = accountData["global"_L1].toObject()["override"_L1].toArray(); + // for (const auto &i : overrideRuleArray) { + // QJsonObject overrideRule = i.toObject(); + // if (overrideRule["rule_id"_L1] == id()) { + // if (overrideRule["actions"_L1].toArray().isEmpty()) { + // m_currentPushNotificationState = PushNotificationState::Mute; + // Q_EMIT pushNotificationStateChanged(m_currentPushNotificationState); + // return; + // } + // QString notifyAction = overrideRule["actions"_L1].toArray()[0].toString(); + // if (notifyAction == "dont_notify"_L1) { + // m_currentPushNotificationState = PushNotificationState::Mute; + // Q_EMIT pushNotificationStateChanged(m_currentPushNotificationState); + // return; + // } + // } + // } // If neither a room or override rule exist for the room then the setting must be default m_currentPushNotificationState = PushNotificationState::Default; @@ -1217,132 +1233,132 @@ void NeoChatRoom::updatePushNotificationState(QString type) void NeoChatRoom::reportEvent(const QString &eventId, const QString &reason) { - auto job = connection()->callApi(id(), eventId, -50, reason); - connect(job, &BaseJob::finished, this, [this, job]() { - if (job->error() == BaseJob::Success) { - Q_EMIT showMessage(MessageType::Positive, i18n("Report sent successfully.")); - } - }); + // auto job = connection()->callApi(id(), eventId, -50, reason); + // connect(job, &BaseJob::finished, this, [this, job]() { + // if (job->error() == BaseJob::Success) { + // Q_EMIT showMessage(MessageType::Positive, i18n("Report sent successfully.")); + // } + // }); } QByteArray NeoChatRoom::getEventJsonSource(const QString &eventId) { - auto evtIt = findInTimeline(eventId); - if (evtIt != messageEvents().rend() && is(**evtIt)) { - const auto event = evtIt->viewAs(); - return QJsonDocument(event->fullJson()).toJson(); - } + // auto evtIt = findInTimeline(eventId); + // if (evtIt != messageEvents().rend() && is(**evtIt)) { + // const auto event = evtIt->viewAs(); + // return QJsonDocument(event->fullJson()).toJson(); + // } return {}; } void NeoChatRoom::openEventMediaExternally(const QString &eventId) { - const auto evtIt = findInTimeline(eventId); - if (evtIt != messageEvents().rend() && is(**evtIt)) { - const auto event = evtIt->viewAs(); - if (event->has()) { - const auto transferInfo = cachedFileTransferInfo(event); - if (transferInfo.completed()) { - UrlHelper helper; - helper.openUrl(transferInfo.localPath); - } else { - downloadFile(eventId, - QUrl(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + u'/' - + event->id().replace(u':', u'_').replace(u'/', u'_').replace(u'+', u'_') + fileNameToDownload(eventId))); - connect( - this, - &Room::fileTransferCompleted, - this, - [this, eventId](QString id, QUrl localFile, FileSourceInfo fileMetadata) { - Q_UNUSED(localFile); - Q_UNUSED(fileMetadata); - if (id == eventId) { - auto transferInfo = fileTransferInfo(eventId); - UrlHelper helper; - helper.openUrl(transferInfo.localPath); - } - }, - static_cast(Qt::SingleShotConnection)); - } - } - } + // const auto evtIt = findInTimeline(eventId); + // if (evtIt != messageEvents().rend() && is(**evtIt)) { + // const auto event = evtIt->viewAs(); + // if (event->has()) { + // const auto transferInfo = cachedFileTransferInfo(event); + // if (transferInfo.completed()) { + // UrlHelper helper; + // helper.openUrl(transferInfo.localPath); + // } else { + // downloadFile(eventId, + // QUrl(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + u'/' + // + event->id().replace(u':', u'_').replace(u'/', u'_').replace(u'+', u'_') + fileNameToDownload(eventId))); + // connect( + // this, + // &Room::fileTransferCompleted, + // this, + // [this, eventId](QString id, QUrl localFile, FileSourceInfo fileMetadata) { + // Q_UNUSED(localFile); + // Q_UNUSED(fileMetadata); + // if (id == eventId) { + // auto transferInfo = fileTransferInfo(eventId); + // UrlHelper helper; + // helper.openUrl(transferInfo.localPath); + // } + // }, + // static_cast(Qt::SingleShotConnection)); + // } + // } + // } } void NeoChatRoom::copyEventMedia(const QString &eventId) { - const auto evtIt = findInTimeline(eventId); - if (evtIt != messageEvents().rend() && is(**evtIt)) { - const auto event = evtIt->viewAs(); - if (event->has()) { - const auto transferInfo = fileTransferInfo(eventId); - if (transferInfo.completed()) { - Clipboard clipboard; - clipboard.setImage(transferInfo.localPath); - } else { - downloadFile(eventId, - QUrl(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + u'/' - + event->id().replace(u':', u'_').replace(u'/', u'_').replace(u'+', u'_') + fileNameToDownload(eventId))); - connect( - this, - &Room::fileTransferCompleted, - this, - [this, eventId](QString id, QUrl localFile, FileSourceInfo fileMetadata) { - Q_UNUSED(localFile); - Q_UNUSED(fileMetadata); - if (id == eventId) { - auto transferInfo = fileTransferInfo(eventId); - Clipboard clipboard; - clipboard.setImage(transferInfo.localPath); - } - }, - static_cast(Qt::SingleShotConnection)); - } - } - } + // const auto evtIt = findInTimeline(eventId); + // if (evtIt != messageEvents().rend() && is(**evtIt)) { + // const auto event = evtIt->viewAs(); + // if (event->has()) { + // const auto transferInfo = fileTransferInfo(eventId); + // if (transferInfo.completed()) { + // Clipboard clipboard; + // clipboard.setImage(transferInfo.localPath); + // } else { + // downloadFile(eventId, + // QUrl(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + u'/' + // + event->id().replace(u':', u'_').replace(u'/', u'_').replace(u'+', u'_') + fileNameToDownload(eventId))); + // connect( + // this, + // &Room::fileTransferCompleted, + // this, + // [this, eventId](QString id, QUrl localFile, FileSourceInfo fileMetadata) { + // Q_UNUSED(localFile); + // Q_UNUSED(fileMetadata); + // if (id == eventId) { + // auto transferInfo = fileTransferInfo(eventId); + // Clipboard clipboard; + // clipboard.setImage(transferInfo.localPath); + // } + // }, + // static_cast(Qt::SingleShotConnection)); + // } + // } + // } } -FileTransferInfo NeoChatRoom::cachedFileTransferInfo(const Quotient::RoomEvent *event) const -{ - QString mxcUrl; - int total = 0; - if (auto evt = eventCast(event)) { - if (evt->has()) { - const auto fileContent = evt->get(); - - mxcUrl = fileContent->url().toString(); - total = fileContent->payloadSize; - } - } else if (auto evt = eventCast(event)) { - mxcUrl = evt->image().url().toString(); - total = evt->image().payloadSize; - } - - FileTransferInfo transferInfo = fileTransferInfo(event->id()); - if (transferInfo.active()) { - return transferInfo; - } - - auto config = KSharedConfig::openStateConfig(u"neochatdownloads"_s)->group(u"downloads"_s); - if (!config.hasKey(mxcUrl.mid(6))) { - return transferInfo; - } - - const auto path = config.readPathEntry(mxcUrl.mid(6), QString()); - QFileInfo info(path); - if (!info.isFile()) { - config.deleteEntry(mxcUrl); - return transferInfo; - } - // TODO: we could check the hash here - return FileTransferInfo{ - .status = FileTransferInfo::Completed, - .isUpload = false, - .progress = total, - .total = total, - .localDir = QUrl(info.dir().path()), - .localPath = QUrl::fromLocalFile(path), - }; -} +// FileTransferInfo NeoChatRoom::cachedFileTransferInfo(const Quotient::RoomEvent *event) const +// { +// QString mxcUrl; +// int total = 0; +// if (auto evt = eventCast(event)) { +// if (evt->has()) { +// const auto fileContent = evt->get(); +// +// mxcUrl = fileContent->url().toString(); +// total = fileContent->payloadSize; +// } +// } else if (auto evt = eventCast(event)) { +// mxcUrl = evt->image().url().toString(); +// total = evt->image().payloadSize; +// } +// +// FileTransferInfo transferInfo = fileTransferInfo(event->id()); +// if (transferInfo.active()) { +// return transferInfo; +// } +// +// auto config = KSharedConfig::openStateConfig(u"neochatdownloads"_s)->group(u"downloads"_s); +// if (!config.hasKey(mxcUrl.mid(6))) { +// return transferInfo; +// } +// +// const auto path = config.readPathEntry(mxcUrl.mid(6), QString()); +// QFileInfo info(path); +// if (!info.isFile()) { +// config.deleteEntry(mxcUrl); +// return transferInfo; +// } +// // TODO: we could check the hash here +// return FileTransferInfo{ +// .status = FileTransferInfo::Completed, +// .isUpload = false, +// .progress = total, +// .total = total, +// .localDir = QUrl(info.dir().path()), +// .localPath = QUrl::fromLocalFile(path), +// }; +// } ChatBarCache *NeoChatRoom::mainCache() const { @@ -1361,97 +1377,98 @@ ChatBarCache *NeoChatRoom::threadCache() const void NeoChatRoom::replyLastMessage() { - const auto &timelineBottom = messageEvents().rbegin(); - - // set a cap limit of startRow + 35 messages, to prevent loading a lot of messages - // in rooms where the user has not sent many messages - const auto limit = timelineBottom + std::min(35, timelineSize()); - - for (auto it = timelineBottom; it != limit; ++it) { - auto evt = it->event(); - auto e = eventCast(evt); - if (!e) { - continue; - } - - auto content = (*it)->contentJson(); - - if (e->msgtype() != MessageEventType::Unknown) { - QString eventId; - if (content.contains("m.new_content"_L1)) { - // The message has been edited so we have to return the id of the original message instead of the replacement - eventId = content["m.relates_to"_L1].toObject()["event_id"_L1].toString(); - } else { - // For any message that isn't an edit return the id of the current message - eventId = (*it)->id(); - } - mainCache()->setReplyId(eventId); - return; - } - } + // const auto &timelineBottom = messageEvents().rbegin(); + // + // // set a cap limit of startRow + 35 messages, to prevent loading a lot of messages + // // in rooms where the user has not sent many messages + // const auto limit = timelineBottom + std::min(35, timelineSize()); + // + // for (auto it = timelineBottom; it != limit; ++it) { + // auto evt = it->event(); + // auto e = eventCast(evt); + // if (!e) { + // continue; + // } + // + // auto content = (*it)->contentJson(); + // + // if (e->msgtype() != MessageEventType::Unknown) { + // QString eventId; + // if (content.contains("m.new_content"_L1)) { + // // The message has been edited so we have to return the id of the original message instead of the replacement + // eventId = content["m.relates_to"_L1].toObject()["event_id"_L1].toString(); + // } else { + // // For any message that isn't an edit return the id of the current message + // eventId = (*it)->id(); + // } + // mainCache()->setReplyId(eventId); + // return; + // } + // } } void NeoChatRoom::editLastMessage() { - const auto &timelineBottom = messageEvents().rbegin(); - - // set a cap limit of 35 messages, to prevent loading a lot of messages - // in rooms where the user has not sent many messages - const auto limit = timelineBottom + std::min(35, timelineSize()); - - for (auto it = timelineBottom; it != limit; ++it) { - auto evt = it->event(); - auto e = eventCast(evt); - if (!e) { - continue; - } - - // check if the current message's sender's id is same as the user's id - if ((*it)->senderId() == localMember().id()) { - auto content = (*it)->contentJson(); - - if (e->msgtype() != MessageEventType::Unknown) { - QString eventId; - if (content.contains("m.new_content"_L1)) { - // The message has been edited so we have to return the id of the original message instead of the replacement - eventId = content["m.relates_to"_L1].toObject()["event_id"_L1].toString(); - } else { - // For any message that isn't an edit return the id of the current message - eventId = (*it)->id(); - } - editCache()->setEditId(eventId); - return; - } - } - } + // const auto &timelineBottom = messageEvents().rbegin(); + // + // // set a cap limit of 35 messages, to prevent loading a lot of messages + // // in rooms where the user has not sent many messages + // const auto limit = timelineBottom + std::min(35, timelineSize()); + // + // for (auto it = timelineBottom; it != limit; ++it) { + // auto evt = it->event(); + // auto e = eventCast(evt); + // if (!e) { + // continue; + // } + // + // // check if the current message's sender's id is same as the user's id + // if ((*it)->senderId() == localMember().id()) { + // auto content = (*it)->contentJson(); + // + // if (e->msgtype() != MessageEventType::Unknown) { + // QString eventId; + // if (content.contains("m.new_content"_L1)) { + // // The message has been edited so we have to return the id of the original message instead of the replacement + // eventId = content["m.relates_to"_L1].toObject()["event_id"_L1].toString(); + // } else { + // // For any message that isn't an edit return the id of the current message + // eventId = (*it)->id(); + // } + // editCache()->setEditId(eventId); + // return; + // } + // } + // } } bool NeoChatRoom::canEncryptRoom() const { - return !usesEncryption() && canSendState("m.room.encryption"_L1); + // return !usesEncryption() && canSendState("m.room.encryption"_L1); + return false; } -static PollHandler *emptyPollHandler = new PollHandler; +// static PollHandler *emptyPollHandler = new PollHandler; -PollHandler *NeoChatRoom::poll(const QString &eventId) const -{ - if (auto pollHandler = m_polls[eventId]) { - return pollHandler; - } - return emptyPollHandler; -} +// PollHandler *NeoChatRoom::poll(const QString &eventId) const +// { +// if (auto pollHandler = m_polls[eventId]) { +// return pollHandler; +// } +// return emptyPollHandler; +// } -void NeoChatRoom::createPollHandler(const Quotient::PollStartEvent *event) -{ - if (event == nullptr) { - return; - } - auto eventId = event->id(); - if (!m_polls.contains(eventId)) { - auto handler = new PollHandler(this, event); - m_polls.insert(eventId, handler); - } -} +// void NeoChatRoom::createPollHandler(const Quotient::PollStartEvent *event) +// { +// if (event == nullptr) { +// return; +// } +// auto eventId = event->id(); +// if (!m_polls.contains(eventId)) { +// auto handler = new PollHandler(this, event); +// m_polls.insert(eventId, handler); +// } +// } bool NeoChatRoom::downloadTempFile(const QString &eventId) { @@ -1467,87 +1484,87 @@ bool NeoChatRoom::downloadTempFile(const QString &eventId) void NeoChatRoom::download(const QString &eventId, const QUrl &localFilename) { - downloadFile(eventId, localFilename); -#ifndef Q_OS_ANDROID - auto job = new FileTransferPseudoJob(FileTransferPseudoJob::Download, localFilename.toLocalFile(), eventId); - connect(this, &Room::fileTransferProgress, job, &FileTransferPseudoJob::fileTransferProgress); - connect(this, &Room::fileTransferCompleted, job, &FileTransferPseudoJob::fileTransferCompleted); - connect(this, &Room::fileTransferFailed, job, [this, job, eventId] { - auto info = fileTransferInfo(eventId); - if (info.status == FileTransferInfo::Cancelled) { - job->fileTransferCanceled(eventId); - } else { - job->fileTransferFailed(eventId); - } - }); - connect(job, &FileTransferPseudoJob::cancelRequested, this, &Room::cancelFileTransfer); - KIO::getJobTracker()->registerJob(job); - job->start(); -#endif + // downloadFile(eventId, localFilename); + // #ifndef Q_OS_ANDROID + // auto job = new FileTransferPseudoJob(FileTransferPseudoJob::Download, localFilename.toLocalFile(), eventId); + // connect(this, &Room::fileTransferProgress, job, &FileTransferPseudoJob::fileTransferProgress); + // connect(this, &Room::fileTransferCompleted, job, &FileTransferPseudoJob::fileTransferCompleted); + // connect(this, &Room::fileTransferFailed, job, [this, job, eventId] { + // auto info = fileTransferInfo(eventId); + // if (info.status == FileTransferInfo::Cancelled) { + // job->fileTransferCanceled(eventId); + // } else { + // job->fileTransferFailed(eventId); + // } + // }); + // connect(job, &FileTransferPseudoJob::cancelRequested, this, &Room::cancelFileTransfer); + // KIO::getJobTracker()->registerJob(job); + // job->start(); + // #endif } void NeoChatRoom::mapAlias(const QString &alias) { - auto getLocalAliasesJob = connection()->callApi(id()); - connect(getLocalAliasesJob, &BaseJob::success, this, [this, getLocalAliasesJob, alias] { - if (getLocalAliasesJob->aliases().contains(alias)) { - return; - } else { - auto setRoomAliasJob = connection()->callApi(alias, id()); - connect(setRoomAliasJob, &BaseJob::success, this, [this, alias] { - auto newAltAliases = altAliases(); - newAltAliases.append(alias); - setLocalAliases(newAltAliases); - }); - } - }); + // auto getLocalAliasesJob = connection()->callApi(id()); + // connect(getLocalAliasesJob, &BaseJob::success, this, [this, getLocalAliasesJob, alias] { + // if (getLocalAliasesJob->aliases().contains(alias)) { + // return; + // } else { + // auto setRoomAliasJob = connection()->callApi(alias, id()); + // connect(setRoomAliasJob, &BaseJob::success, this, [this, alias] { + // auto newAltAliases = altAliases(); + // newAltAliases.append(alias); + // setLocalAliases(newAltAliases); + // }); + // } + // }); } void NeoChatRoom::unmapAlias(const QString &alias) { - connection()->callApi(alias); + // connection()->callApi(alias); } void NeoChatRoom::setCanonicalAlias(const QString &newAlias) { - QString oldCanonicalAlias = canonicalAlias(); - Room::setCanonicalAlias(newAlias); - - connect(this, &Room::namesChanged, this, [this, newAlias, oldCanonicalAlias] { - if (canonicalAlias() == newAlias) { - // If the new canonical alias is already a published alt alias remove it otherwise it will be in both lists. - // The server doesn't prevent this so we need to handle it. - auto newAltAliases = altAliases(); - if (!oldCanonicalAlias.isEmpty()) { - newAltAliases.append(oldCanonicalAlias); - } - if (newAltAliases.contains(newAlias)) { - newAltAliases.removeAll(newAlias); - Room::setLocalAliases(newAltAliases); - } - } - }); + // QString oldCanonicalAlias = canonicalAlias(); + // Room::setCanonicalAlias(newAlias); + // + // connect(this, &Room::namesChanged, this, [this, newAlias, oldCanonicalAlias] { + // if (canonicalAlias() == newAlias) { + // // If the new canonical alias is already a published alt alias remove it otherwise it will be in both lists. + // // The server doesn't prevent this so we need to handle it. + // auto newAltAliases = altAliases(); + // if (!oldCanonicalAlias.isEmpty()) { + // newAltAliases.append(oldCanonicalAlias); + // } + // if (newAltAliases.contains(newAlias)) { + // newAltAliases.removeAll(newAlias); + // Room::setLocalAliases(newAltAliases); + // } + // } + // }); } int NeoChatRoom::maxRoomVersion() const { int maxVersion = 0; - for (auto roomVersion : connection()->availableRoomVersions()) { - if (roomVersion.id.toInt() > maxVersion) { - maxVersion = roomVersion.id.toInt(); - } - } + // for (auto roomVersion : connection()->availableRoomVersions()) { + // if (roomVersion.id.toInt() > maxVersion) { + // maxVersion = roomVersion.id.toInt(); + // } + // } return maxVersion; } -NeochatRoomMember *NeoChatRoom::directChatRemoteMember() -{ - if (directChatMembers().size() == 0) { - qWarning() << "No other member available in this room"; - return {}; - } - return new NeochatRoomMember(this, directChatMembers()[0].id()); -} +// NeochatRoomMember *NeoChatRoom::directChatRemoteMember() +// { +// if (directChatMembers().size() == 0) { +// qWarning() << "No other member available in this room"; +// return {}; +// } +// return new NeochatRoomMember(this, directChatMembers()[0].id()); +// } void NeoChatRoom::sendLocation(float lat, float lon, const QString &description) { @@ -1570,212 +1587,215 @@ void NeoChatRoom::sendLocation(float lat, float lon, const QString &description) }}, {"org.matrix.msc1767.text"_L1, i18nc("'Lat' and 'Lon' as in Latitude and Longitude", "Lat: %1, Lon: %2", lat, lon)}, }; - postJson("m.room.message"_L1, content); + // postJson("m.room.message"_L1, content); } QByteArray NeoChatRoom::roomAcountDataJson(const QString &eventType) { - return QJsonDocument(accountData(eventType)->fullJson()).toJson(); + // return QJsonDocument(accountData(eventType)->fullJson()).toJson(); + return {}; } void NeoChatRoom::downloadEventFromServer(const QString &eventId) { - if (findInTimeline(eventId) != historyEdge()) { - // For whatever reason the event has now appeared so the function that called - // this need to whatever it wanted to do with the event. - Q_EMIT extraEventLoaded(eventId); - return; - } - auto job = connection()->callApi(id(), eventId); - connect(job, &BaseJob::success, this, [this, job, eventId] { - // The event may have arrived in the meantime so check it's not in the timeline. - if (findInTimeline(eventId) != historyEdge()) { - Q_EMIT extraEventLoaded(eventId); - return; - } - - event_ptr_tt event = fromJson>(job->jsonData()); - m_extraEvents.push_back(std::move(event)); - Q_EMIT extraEventLoaded(eventId); - }); - connect(job, &BaseJob::failure, this, [this, job, eventId] { - if (job->error() == BaseJob::NotFound) { - Q_EMIT extraEventNotFound(eventId); - } - }); + // if (findInTimeline(eventId) != historyEdge()) { + // // For whatever reason the event has now appeared so the function that called + // // this need to whatever it wanted to do with the event. + // Q_EMIT extraEventLoaded(eventId); + // return; + // } + // auto job = connection()->callApi(id(), eventId); + // connect(job, &BaseJob::success, this, [this, job, eventId] { + // // The event may have arrived in the meantime so check it's not in the timeline. + // if (findInTimeline(eventId) != historyEdge()) { + // Q_EMIT extraEventLoaded(eventId); + // return; + // } + // + // event_ptr_tt event = fromJson>(job->jsonData()); + // m_extraEvents.push_back(std::move(event)); + // Q_EMIT extraEventLoaded(eventId); + // }); + // connect(job, &BaseJob::failure, this, [this, job, eventId] { + // if (job->error() == BaseJob::NotFound) { + // Q_EMIT extraEventNotFound(eventId); + // } + // }); } -std::pair NeoChatRoom::getEvent(const QString &eventId) const -{ - if (eventId.isEmpty()) { - return {}; - } - const auto timelineIt = findInTimeline(eventId); - if (timelineIt != historyEdge()) { - return std::make_pair(timelineIt->get(), false); - } +// std::pair NeoChatRoom::getEvent(const QString &eventId) const +// { +// if (eventId.isEmpty()) { +// return {}; +// } +// const auto timelineIt = findInTimeline(eventId); +// if (timelineIt != historyEdge()) { +// return std::make_pair(timelineIt->get(), false); +// } +// +// auto pendingIt = findPendingEvent(eventId); +// if (pendingIt != pendingEvents().end()) { +// return std::make_pair(pendingIt->event(), true); +// } +// // findPendingEvent() searches by transaction ID, we also need to check event ID. +// for (const auto &event : pendingEvents()) { +// if (event->id() == eventId || event->transactionId() == eventId) { +// return std::make_pair(event.event(), true); +// } +// } +// +// auto extraIt = std::find_if(m_extraEvents.begin(), m_extraEvents.end(), [eventId](const Quotient::event_ptr_tt &event) { +// return event->id() == eventId; +// }); +// return std::make_pair(extraIt != m_extraEvents.end() ? extraIt->get() : nullptr, false); +// } - auto pendingIt = findPendingEvent(eventId); - if (pendingIt != pendingEvents().end()) { - return std::make_pair(pendingIt->event(), true); - } - // findPendingEvent() searches by transaction ID, we also need to check event ID. - for (const auto &event : pendingEvents()) { - if (event->id() == eventId || event->transactionId() == eventId) { - return std::make_pair(event.event(), true); - } - } +// const RoomEvent *NeoChatRoom::getReplyForEvent(const RoomEvent &event) const +// { +// const QString &replyEventId = event.contentJson()["m.relates_to"_L1].toObject()["m.in_reply_to"_L1].toObject()["event_id"_L1].toString(); +// if (replyEventId.isEmpty()) { +// return {}; +// }; +// +// const auto replyIt = findInTimeline(replyEventId); +// const RoomEvent *replyPtr = replyIt != historyEdge() ? &**replyIt : nullptr; +// if (!replyPtr) { +// for (const auto &e : m_extraEvents) { +// if (e->id() == replyEventId) { +// replyPtr = e.get(); +// break; +// } +// } +// } +// return replyPtr; +// } - auto extraIt = std::find_if(m_extraEvents.begin(), m_extraEvents.end(), [eventId](const Quotient::event_ptr_tt &event) { - return event->id() == eventId; - }); - return std::make_pair(extraIt != m_extraEvents.end() ? extraIt->get() : nullptr, false); -} - -const RoomEvent *NeoChatRoom::getReplyForEvent(const RoomEvent &event) const -{ - const QString &replyEventId = event.contentJson()["m.relates_to"_L1].toObject()["m.in_reply_to"_L1].toObject()["event_id"_L1].toString(); - if (replyEventId.isEmpty()) { - return {}; - }; - - const auto replyIt = findInTimeline(replyEventId); - const RoomEvent *replyPtr = replyIt != historyEdge() ? &**replyIt : nullptr; - if (!replyPtr) { - for (const auto &e : m_extraEvents) { - if (e->id() == replyEventId) { - replyPtr = e.get(); - break; - } - } - } - return replyPtr; -} - -void NeoChatRoom::cleanupExtraEventRange(Quotient::RoomEventsRange events) -{ - for (auto &&event : events) { - cleanupExtraEvent(event->id()); - } -} +// void NeoChatRoom::cleanupExtraEventRange(Quotient::RoomEventsRange events) +// { +// for (auto &&event : events) { +// cleanupExtraEvent(event->id()); +// } +// } void NeoChatRoom::cleanupExtraEvent(const QString &eventId) { - auto it = std::find_if(m_extraEvents.begin(), m_extraEvents.end(), [eventId](Quotient::event_ptr_tt &event) { - return event->id() == eventId; - }); - - if (it != m_extraEvents.end()) { - m_extraEvents.erase(it); - } + // auto it = std::find_if(m_extraEvents.begin(), m_extraEvents.end(), [eventId](Quotient::event_ptr_tt &event) { + // return event->id() == eventId; + // }); + // + // if (it != m_extraEvents.end()) { + // m_extraEvents.erase(it); + // } } QString NeoChatRoom::invitingUserId() const { - return currentState().get(connection()->userId())->senderId(); + // return currentState().get(connection()->userId())->senderId(); + return {}; } void NeoChatRoom::setRoomState(const QString &type, const QString &stateKey, const QByteArray &content) { - setState(type, stateKey, QJsonDocument::fromJson(content).object()); + // setState(type, stateKey, QJsonDocument::fromJson(content).object()); } -NeochatRoomMember *NeoChatRoom::qmlSafeMember(const QString &memberId) -{ - if (!m_memberObjects.contains(memberId)) { - return m_memberObjects.emplace(memberId, std::make_unique(this, memberId)).first->second.get(); - } +// NeochatRoomMember *NeoChatRoom::qmlSafeMember(const QString &memberId) +// { +// if (!m_memberObjects.contains(memberId)) { +// return m_memberObjects.emplace(memberId, std::make_unique(this, memberId)).first->second.get(); +// } +// +// return m_memberObjects[memberId].get(); +// } - return m_memberObjects[memberId].get(); -} +// MessageContentModel *NeoChatRoom::contentModelForEvent(const QString &eventId) +// { +// if (eventId.isEmpty()) { +// return nullptr; +// } +// +// if (!m_eventContentModels.contains(eventId)) { +// return m_eventContentModels.emplace(eventId, std::make_unique(this, eventId)).first->second.get(); +// } +// +// return m_eventContentModels[eventId].get(); +// } -MessageContentModel *NeoChatRoom::contentModelForEvent(const QString &eventId) -{ - if (eventId.isEmpty()) { - return nullptr; - } +// MessageContentModel *NeoChatRoom::contentModelForEvent(const Quotient::RoomEvent *event) +// { +// const auto roomMessageEvent = eventCast(event); +// if (roomMessageEvent == nullptr) { +// // If for some reason a model is there remove. +// if (m_eventContentModels.contains(event->id())) { +// m_eventContentModels.erase(event->id()); +// } +// if (m_eventContentModels.contains(event->transactionId())) { +// m_eventContentModels.erase(event->transactionId()); +// } +// return nullptr; +// } +// +// if (event->isStateEvent() || event->matrixType() == u"org.matrix.msc3672.beacon_info"_s) { +// return nullptr; +// } +// +// auto eventId = event->id(); +// const auto txnId = event->transactionId(); +// if (!m_eventContentModels.contains(eventId) && !m_eventContentModels.contains(txnId)) { +// return m_eventContentModels +// .emplace(eventId.isEmpty() ? txnId : eventId, +// std::make_unique(this, eventId.isEmpty() ? txnId : eventId, false, eventId.isEmpty())) +// .first->second.get(); +// } +// +// if (!eventId.isEmpty() && m_eventContentModels.contains(eventId)) { +// return m_eventContentModels[eventId].get(); +// } +// +// if (!txnId.isEmpty() && m_eventContentModels.contains(txnId)) { +// if (eventId.isEmpty()) { +// return m_eventContentModels[txnId].get(); +// } +// +// // If we now have an event ID use that as the map key instead of transaction ID. +// auto txnModel = std::move(m_eventContentModels[txnId]); +// m_eventContentModels.erase(txnId); +// return m_eventContentModels.emplace(eventId, std::move(txnModel)).first->second.get(); +// } +// +// return nullptr; +// } - if (!m_eventContentModels.contains(eventId)) { - return m_eventContentModels.emplace(eventId, std::make_unique(this, eventId)).first->second.get(); - } - - return m_eventContentModels[eventId].get(); -} - -MessageContentModel *NeoChatRoom::contentModelForEvent(const Quotient::RoomEvent *event) -{ - const auto roomMessageEvent = eventCast(event); - if (roomMessageEvent == nullptr) { - // If for some reason a model is there remove. - if (m_eventContentModels.contains(event->id())) { - m_eventContentModels.erase(event->id()); - } - if (m_eventContentModels.contains(event->transactionId())) { - m_eventContentModels.erase(event->transactionId()); - } - return nullptr; - } - - if (event->isStateEvent() || event->matrixType() == u"org.matrix.msc3672.beacon_info"_s) { - return nullptr; - } - - auto eventId = event->id(); - const auto txnId = event->transactionId(); - if (!m_eventContentModels.contains(eventId) && !m_eventContentModels.contains(txnId)) { - return m_eventContentModels - .emplace(eventId.isEmpty() ? txnId : eventId, - std::make_unique(this, eventId.isEmpty() ? txnId : eventId, false, eventId.isEmpty())) - .first->second.get(); - } - - if (!eventId.isEmpty() && m_eventContentModels.contains(eventId)) { - return m_eventContentModels[eventId].get(); - } - - if (!txnId.isEmpty() && m_eventContentModels.contains(txnId)) { - if (eventId.isEmpty()) { - return m_eventContentModels[txnId].get(); - } - - // If we now have an event ID use that as the map key instead of transaction ID. - auto txnModel = std::move(m_eventContentModels[txnId]); - m_eventContentModels.erase(txnId); - return m_eventContentModels.emplace(eventId, std::move(txnModel)).first->second.get(); - } - - return nullptr; -} - -ThreadModel *NeoChatRoom::modelForThread(const QString &threadRootId) -{ - if (threadRootId.isEmpty()) { - return nullptr; - } - - if (!m_threadModels.contains(threadRootId)) { - return m_threadModels.emplace(threadRootId, std::make_unique(threadRootId, this)).first->second.get(); - } - - return m_threadModels[threadRootId].get(); -} +// ThreadModel *NeoChatRoom::modelForThread(const QString &threadRootId) +// { +// if (threadRootId.isEmpty()) { +// return nullptr; +// } +// +// if (!m_threadModels.contains(threadRootId)) { +// return m_threadModels.emplace(threadRootId, std::make_unique(threadRootId, this)).first->second.get(); +// } +// +// return m_threadModels[threadRootId].get(); +// } void NeoChatRoom::pinEvent(const QString &eventId) { - auto eventIds = pinnedEventIds(); - eventIds.push_back(eventId); - setPinnedEvents(eventIds); + // auto eventIds = pinnedEventIds(); + // eventIds.push_back(eventId); + // setPinnedEvents(eventIds); } void NeoChatRoom::unpinEvent(const QString &eventId) { - auto eventIds = pinnedEventIds(); - eventIds.removeAll(eventId); - setPinnedEvents(eventIds); + // auto eventIds = pinnedEventIds(); + // eventIds.removeAll(eventId); + // setPinnedEvents(eventIds); } bool NeoChatRoom::isEventPinned(const QString &eventId) const { - return pinnedEventIds().contains(eventId); + // return pinnedEventIds().contains(eventId); + return {}; } #include "moc_neochatroom.cpp" diff --git a/src/neochatroom.h b/src/neochatroom.h index 20a1e3769..826eb48e9 100644 --- a/src/neochatroom.h +++ b/src/neochatroom.h @@ -3,8 +3,9 @@ #pragma once -#include -#include +// #include +// #include +#include #include #include @@ -13,12 +14,12 @@ #include #include -#include "enums/messagetype.h" #include "enums/pushrule.h" -#include "models/messagecontentmodel.h" -#include "models/threadmodel.h" -#include "neochatroommember.h" -#include "pollhandler.h" +// #include "enums/messagetype.h" +// #include "models/messagecontentmodel.h" +// #include "models/threadmodel.h" +// #include "neochatroommember.h" +// #include "pollhandler.h" namespace Quotient { @@ -39,7 +40,7 @@ class ChatBarCache; * * @sa Quotient::Room */ -class NeoChatRoom : public Quotient::Room +class NeoChatRoom : public Integral::Room { Q_OBJECT QML_ELEMENT @@ -79,7 +80,7 @@ class NeoChatRoom : public Quotient::Room /** * @brief Get a RoomMember object for the other person in a direct chat. */ - Q_PROPERTY(NeochatRoomMember *directChatRemoteMember READ directChatRemoteMember CONSTANT) + // Q_PROPERTY(NeochatRoomMember *directChatRemoteMember READ directChatRemoteMember CONSTANT) /** * @brief The Matrix IDs of this room's parents. @@ -183,20 +184,20 @@ class NeoChatRoom : public Quotient::Room /** * @brief The cache for the main chat bar in the room. */ - Q_PROPERTY(ChatBarCache *mainCache READ mainCache CONSTANT) + // Q_PROPERTY(ChatBarCache *mainCache READ mainCache CONSTANT) /** * @brief The cache for the edit chat bar in the room. */ - Q_PROPERTY(ChatBarCache *editCache READ editCache CONSTANT) + // Q_PROPERTY(ChatBarCache *editCache READ editCache CONSTANT) /** * @brief The cache for the thread chat bar in the room. */ - Q_PROPERTY(ChatBarCache *threadCache READ threadCache CONSTANT) + // Q_PROPERTY(ChatBarCache *threadCache READ threadCache CONSTANT) public: - explicit NeoChatRoom(Quotient::Connection *connection, QString roomId, Quotient::JoinState joinState = {}); + explicit NeoChatRoom(std::unique_ptr d, QObject *parent = nullptr); bool visible() const; void setVisible(bool visible); @@ -212,7 +213,7 @@ public: * @warning This function can return an empty pointer if the room does not have * any RoomMessageEvents loaded. */ - [[nodiscard]] const Quotient::RoomEvent *lastEvent() const; + // [[nodiscard]] const Quotient::RoomEvent *lastEvent() const; /** * @brief Convenient way to check if the last event looks like it has spoilers. @@ -259,7 +260,7 @@ public: * An event is highlighted if it contains the local user's id but was not sent by the * local user. */ - bool isEventHighlighted(const Quotient::RoomEvent *e) const; + // bool isEventHighlighted(const Quotient::RoomEvent *e) const; /** * @brief Convenience function to find out if the room contains the given user. @@ -312,7 +313,7 @@ public: [[nodiscard]] QUrl avatarMediaUrl() const; - NeochatRoomMember *directChatRemoteMember(); + // NeochatRoomMember *directChatRemoteMember(); /** * @brief Whether this room has one or more parent spaces set. @@ -501,14 +502,14 @@ public: * * @sa PollHandler */ - PollHandler *poll(const QString &eventId) const; + // PollHandler *poll(const QString &eventId) const; /** * @brief Create a PollHandler object for the given event. * * @sa PollHandler */ - void createPollHandler(const Quotient::PollStartEvent *event); + // void createPollHandler(const Quotient::PollStartEvent *event); /** * @brief Get the full Json data for a given room account data event. @@ -533,12 +534,12 @@ public: * * The result will be nullptr if not found so needs to be managed. */ - std::pair getEvent(const QString &eventId) const; + // std::pair getEvent(const QString &eventId) const; /** * @brief Returns the event that is being replied to. This includes events that were manually loaded using NeoChatRoom::loadReply. */ - const Quotient::RoomEvent *getReplyForEvent(const Quotient::RoomEvent &event) const; + // const Quotient::RoomEvent *getReplyForEvent(const Quotient::RoomEvent &event) const; /** * If we're invited to this room, the user that invited us. Undefined in other cases. @@ -551,7 +552,7 @@ public: * If we downloaded the file previously, return a struct with Completed status * and the local file path stored in KSharedCOnfig */ - Quotient::FileTransferInfo cachedFileTransferInfo(const Quotient::RoomEvent *event) const; + // Quotient::FileTransferInfo cachedFileTransferInfo(const Quotient::RoomEvent *event) const; /** * @brief Return a NeochatRoomMember object for the given user ID. @@ -562,7 +563,7 @@ public: * responsibility of the caller to ensure that they only ask for objects * for real senders. */ - NeochatRoomMember *qmlSafeMember(const QString &memberId); + // NeochatRoomMember *qmlSafeMember(const QString &memberId); /** * @brief Returns the content model for the given event ID. @@ -576,7 +577,7 @@ public: * * @warning Do NOT use for pending events as this function has no way to differentiate. */ - MessageContentModel *contentModelForEvent(const QString &evtOrTxnId); + // MessageContentModel *contentModelForEvent(const QString &evtOrTxnId); /** * @brief Returns the content model for the given event. @@ -591,7 +592,7 @@ public: * * @note This version must be used for pending events as it can differentiate. */ - MessageContentModel *contentModelForEvent(const Quotient::RoomEvent *event); + // MessageContentModel *contentModelForEvent(const Quotient::RoomEvent *event); /** * @brief Returns the thread model for the given thread root event ID. @@ -599,7 +600,7 @@ public: * A model is created is one doesn't exist. Will return nullptr if threadRootId * is empty. */ - Q_INVOKABLE ThreadModel *modelForThread(const QString &threadRootId); + // Q_INVOKABLE ThreadModel *modelForThread(const QString &threadRootId); /** * @brief Pin a message in the room. @@ -621,7 +622,7 @@ public: private: bool m_visible = false; - QSet highlights; + // QSet highlights; bool m_hasFileUploading = false; int m_fileUploadingProgress = 0; @@ -629,29 +630,29 @@ private: PushNotificationState::State m_currentPushNotificationState = PushNotificationState::Unknown; bool m_pushNotificationStateUpdating = false; - void checkForHighlights(const Quotient::TimelineItem &ti); + // void checkForHighlights(const Quotient::TimelineItem &ti); - void onAddNewTimelineEvents(timeline_iter_t from) override; - void onAddHistoricalTimelineEvents(rev_iter_t from) override; - void onRedaction(const Quotient::RoomEvent &prevEvent, const Quotient::RoomEvent &after) override; + // void onAddNewTimelineEvents(timeline_iter_t from) override; + // void onAddHistoricalTimelineEvents(rev_iter_t from) override; + // void onRedaction(const Quotient::RoomEvent &prevEvent, const Quotient::RoomEvent &after) override; - QCoro::Task doDeleteMessagesByUser(const QString &user, QString reason); + // QCoro::Task doDeleteMessagesByUser(const QString &user, QString reason); QCoro::Task doUploadFile(QUrl url, QString body = QString()); - std::unique_ptr m_cachedEvent; + // std::unique_ptr m_cachedEvent; ChatBarCache *m_mainCache; ChatBarCache *m_editCache; ChatBarCache *m_threadCache; - QCache m_polls; - std::vector> m_extraEvents; - void cleanupExtraEventRange(Quotient::RoomEventsRange events); + // QCache m_polls; + // std::vector> m_extraEvents; + // void cleanupExtraEventRange(Quotient::RoomEventsRange events); void cleanupExtraEvent(const QString &eventId); - std::unordered_map> m_memberObjects; - std::unordered_map> m_eventContentModels; - std::unordered_map> m_threadModels; + // std::unordered_map> m_memberObjects; + // std::unordered_map> m_eventContentModels; + // std::unordered_map> m_threadModels; private Q_SLOTS: void updatePushNotificationState(QString type); @@ -681,11 +682,12 @@ Q_SIGNALS: void maxRoomVersionChanged(); void extraEventLoaded(const QString &eventId); void extraEventNotFound(const QString &eventId); + void avatarChanged(); /** * @brief Request a message be shown to the user of the given type. */ - void showMessage(MessageType::Type messageType, const QString &message); + // void showMessage(MessageType::Type messageType, const QString &message); public Q_SLOTS: /** diff --git a/src/qml/AccountSwitchDialog.qml b/src/qml/AccountSwitchDialog.qml index 13a65da35..d1ed077ad 100644 --- a/src/qml/AccountSwitchDialog.qml +++ b/src/qml/AccountSwitchDialog.qml @@ -75,7 +75,7 @@ Kirigami.Dialog { } } clip: true - model: AccountRegistry + model: Accounts keyNavigationEnabled: false Keys.onDownPressed: { diff --git a/src/qml/Main.qml b/src/qml/Main.qml index 92f8dcae3..ede8673c5 100644 --- a/src/qml/Main.qml +++ b/src/qml/Main.qml @@ -23,8 +23,8 @@ Kirigami.ApplicationWindow { title: { if (NeoChatConfig.windowTitleFocus) { return activeFocusItem + " " + (activeFocusItem ? activeFocusItem.Accessible.name : ""); - } else if (RoomManager.currentRoom) { - return RoomManager.currentRoom.displayName; + // } else if (RoomManager.currentRoom) { + // return RoomManager.currentRoom.displayName; } else { return Application.displayName; } @@ -49,20 +49,20 @@ Kirigami.ApplicationWindow { } onConnectionChanged: { - CustomEmojiModel.connection = root.connection; - SpaceHierarchyCache.connection = root.connection; + // CustomEmojiModel.connection = root.connection; + // SpaceHierarchyCache.connection = root.connection; NeoChatSettingsView.connection = root.connection; - if (ShareHandler.text && root.connection) { - root.handleShare(); - } + // if (ShareHandler.text && root.connection) { + // root.handleShare(); + // } } - Connections { - target: LoginHelper - function onLoaded() { - root.load(); - } - } + // Connections { + // target: LoginHelper + // function onLoaded() { + // root.load(); + // } + // } Connections { target: root.quitAction @@ -83,64 +83,64 @@ Kirigami.ApplicationWindow { configGroupName: "MainWindow" } - QuickSwitcher { - id: quickSwitcher - connection: root.connection - } - - Connections { - target: RoomManager - - function onCurrentRoomChanged() { - if (RoomManager.currentRoom && pageStack.depth <= 1 && root.initialized && Kirigami.Settings.isMobile) { - let roomPage = pageStack.layers.push(Qt.createComponent('org.kde.neochat', 'RoomPage'), { - connection: root.connection - }); - roomPage.backRequested.connect(event => { - RoomManager.clearCurrentRoom(); - }); - } - } - - function onAskJoinRoom(room) { - Qt.createComponent("org.kde.neochat", "JoinRoomDialog").createObject(root, { - room: room, - connection: root.connection - }).open(); - } - - function onShowUserDetail(user, room) { - root.showUserDetail(user, room); - } - - function goToEvent(event) { - if (event.length > 0) { - roomItem.goToEvent(event); - } - roomItem.forceActiveFocus(); - } - - function onAskDirectChatConfirmation(user) { - Qt.createComponent("org.kde.neochat", "AskDirectChatConfirmation").createObject(this, { - user: user - }).open(); - } - - function onExternalUrl(url) { - let dialog = Qt.createComponent("org.kde.neochat", "ConfirmUrlDialog").createObject(this); - dialog.link = url; - dialog.open(); - } - } - - function pushReplaceLayer(page, args) { - if (pageStack.layers.depth === 2) { - pageStack.layers.replace(page, args); - } else { - pageStack.layers.push(page, args); - } - } + // QuickSwitcher { + // id: quickSwitcher + // connection: root.connection + // } + // Connections { + // target: RoomManager + // + // function onCurrentRoomChanged() { + // if (RoomManager.currentRoom && pageStack.depth <= 1 && root.initialized && Kirigami.Settings.isMobile) { + // let roomPage = pageStack.layers.push(Qt.createComponent('org.kde.neochat', 'RoomPage'), { + // connection: root.connection + // }); + // roomPage.backRequested.connect(event => { + // RoomManager.clearCurrentRoom(); + // }); + // } + // } + // + // function onAskJoinRoom(room) { + // Qt.createComponent("org.kde.neochat", "JoinRoomDialog").createObject(root, { + // room: room, + // connection: root.connection + // }).open(); + // } + // + // function onShowUserDetail(user, room) { + // root.showUserDetail(user, room); + // } + // + // function goToEvent(event) { + // if (event.length > 0) { + // roomItem.goToEvent(event); + // } + // roomItem.forceActiveFocus(); + // } + // + // function onAskDirectChatConfirmation(user) { + // Qt.createComponent("org.kde.neochat", "AskDirectChatConfirmation").createObject(this, { + // user: user + // }).open(); + // } + // + // function onExternalUrl(url) { + // let dialog = Qt.createComponent("org.kde.neochat", "ConfirmUrlDialog").createObject(this); + // dialog.link = url; + // dialog.open(); + // } + // } + // + // function pushReplaceLayer(page, args) { + // if (pageStack.layers.depth === 2) { + // pageStack.layers.replace(page, args); + // } else { + // pageStack.layers.push(page, args); + // } + // } + // function openRoomDrawer() { pageStack.push(Qt.createComponent('org.kde.neochat', 'RoomDrawerPage'), { connection: root.connection @@ -183,15 +183,15 @@ Kirigami.ApplicationWindow { } Component.onCompleted: { - CustomEmojiModel.connection = root.connection; - SpaceHierarchyCache.connection = root.connection; - RoomSettingsView.window = root; + // CustomEmojiModel.connection = root.connection; + // SpaceHierarchyCache.connection = root.connection; + // RoomSettingsView.window = root; NeoChatSettingsView.window = root; NeoChatSettingsView.connection = root.connection; WindowController.setBlur(pageStack, NeoChatConfig.blur && !NeoChatConfig.compactLayout); - if (ShareHandler.text && root.connection) { - root.handleShare() - } + // if (ShareHandler.text && root.connection) { + // root.handleShare() + // } const hasSystemTray = Controller.supportSystemTray && NeoChatConfig.systemTray; if (Kirigami.Settings.isMobile || !(hasSystemTray && NeoChatConfig.minimizeToSystemTrayOnStartup)) { visible = true; @@ -210,7 +210,7 @@ Kirigami.ApplicationWindow { // blur effect color: NeoChatConfig.blur && !NeoChatConfig.compactLayout ? "transparent" : Kirigami.Theme.backgroundColor - // we need to apply the translucency effect separately on top of the color + // // we need to apply the translucency effect separately on top of the color background: Rectangle { color: NeoChatConfig.blur && !NeoChatConfig.compactLayout ? Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 1 - NeoChatConfig.transparency) : "transparent" } @@ -220,7 +220,7 @@ Kirigami.ApplicationWindow { RoomListPage { id: roomList - onSearch: quickSwitcher.open() + // onSearch: quickSwitcher.open() connection: root.connection @@ -255,9 +255,9 @@ Kirigami.ApplicationWindow { } Connections { - target: AccountRegistry + target: Accounts function onRowsRemoved() { - if (AccountRegistry.rowCount() === 0) { + if (Accounts.rowCount() === 0) { pageStack.clear(); pageStack.push(Qt.createComponent('org.kde.neochat.login', 'WelcomePage')); } @@ -272,22 +272,22 @@ Kirigami.ApplicationWindow { } } - Connections { - target: root.connection - - function onNewKeyVerificationSession(session) { - root.pageStack.pushDialogLayer(Qt.createComponent("org.kde.neochat", "KeyVerificationDialog"), { - session: session - }, { - title: i18nc("@title:window", "Session Verification") - }); - } - function onUserConsentRequired(url) { - Qt.createComponent("org.kde.neochat", "ConsentDialog").createObject(this, { - url: url - }).open(); - } - } + // Connections { + // target: root.connection + // + // function onNewKeyVerificationSession(session) { + // root.pageStack.pushDialogLayer(Qt.createComponent("org.kde.neochat", "KeyVerificationDialog"), { + // session: session + // }, { + // title: i18nc("@title:window", "Session Verification") + // }); + // } + // function onUserConsentRequired(url) { + // Qt.createComponent("org.kde.neochat", "ConsentDialog").createObject(this, { + // url: url + // }).open(); + // } + // } HoverLinkIndicator { id: linkIndicator @@ -303,36 +303,36 @@ Kirigami.ApplicationWindow { } } - Connections { - target: ShareHandler - function onTextChanged(): void { - if (root.connection && ShareHandler.text.length > 0) { - root.handleShare(); - } - } - } - function handleShare(): void { - const dialog = applicationWindow().pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'ChooseRoomDialog'), { - connection: root.connection - }, { - title: i18nc("@title", "Share"), - width: Kirigami.Units.gridUnit * 25 - }) - dialog.chosen.connect(function(targetRoomId) { - RoomManager.resolveResource(targetRoomId) - ShareHandler.room = targetRoomId - dialog.closeDialog() - }) - } - function showUserDetail(user, room) { - const dialog = Qt.createComponent("org.kde.neochat", "UserDetailDialog").createObject(root, { - room: room, - user: user, - connection: root.connection, - }); - dialog.parent = QmlUtils.focusedWindowItem(); // Kirigami Dialogs overwrite the parent, so we need to set it again - dialog.open(); - } + // Connections { + // target: ShareHandler + // function onTextChanged(): void { + // if (root.connection && ShareHandler.text.length > 0) { + // root.handleShare(); + // } + // } + // } + // function handleShare(): void { + // const dialog = applicationWindow().pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'ChooseRoomDialog'), { + // connection: root.connection + // }, { + // title: i18nc("@title", "Share"), + // width: Kirigami.Units.gridUnit * 25 + // }) + // dialog.chosen.connect(function(targetRoomId) { + // RoomManager.resolveResource(targetRoomId) + // ShareHandler.room = targetRoomId + // dialog.closeDialog() + // }) + // } + // function showUserDetail(user, room) { + // const dialog = Qt.createComponent("org.kde.neochat", "UserDetailDialog").createObject(root, { + // room: room, + // user: user, + // connection: root.connection, + // }); + // dialog.parent = QmlUtils.focusedWindowItem(); // Kirigami Dialogs overwrite the parent, so we need to set it again + // dialog.open(); + // } function load() { pageStack.replace(roomListComponent); diff --git a/src/qml/RoomDelegate.qml b/src/qml/RoomDelegate.qml index 932551857..816416df9 100644 --- a/src/qml/RoomDelegate.qml +++ b/src/qml/RoomDelegate.qml @@ -19,7 +19,7 @@ Delegates.RoundedItemDelegate { required property int index required property int contextNotificationCount required property bool hasHighlightNotifications - required property NeoChatRoom currentRoom + required property string roomId required property NeoChatConnection connection required property url avatar required property string subtitleText @@ -37,11 +37,13 @@ Delegates.RoundedItemDelegate { onClicked: { if (root.openOnClick) { - RoomManager.resolveResource(currentRoom.id); + root.connection.open(root.roomId) pageStack.currentIndex = 1; } } + onPressAndHold: createRoomListContextMenu() + Keys.onSpacePressed: clicked() Keys.onEnterPressed: clicked() Keys.onReturnPressed: clicked() @@ -52,19 +54,14 @@ Delegates.RoundedItemDelegate { onTapped: (eventPoint, button) => root.createRoomListContextMenu() } - TapHandler { - acceptedDevices: PointerDevice.TouchScreen - onLongPressed: root.createRoomListContextMenu() - } - contentItem: RowLayout { spacing: Kirigami.Units.largeSpacing AvatarNotification { source: root.avatar name: root.displayName - visible: NeoChatConfig.showAvatarInRoomDrawer - implicitHeight: Kirigami.Units.gridUnit + (NeoChatConfig.compactRoomList ? 0 : Kirigami.Units.largeSpacing * 2) + // visible: NeoChatConfig.showAvatarInRoomDrawer + implicitHeight: Kirigami.Units.gridUnit + Kirigami.Units.largeSpacing * 2 // (NeoChatConfig.compactRoomList ? 0 : Kirigami.Units.largeSpacing * 2) implicitWidth: visible ? implicitHeight : 0 notificationCount: root.contextNotificationCount @@ -101,7 +98,7 @@ Delegates.RoundedItemDelegate { elide: Text.ElideRight font: Kirigami.Theme.smallFont opacity: root.hasNotifications ? 0.9 : 0.7 - visible: !NeoChatConfig.compactRoomList && text.length > 0 + // visible: !NeoChatConfig.compactRoomList && text.length > 0 textFormat: Text.PlainText Layout.fillWidth: true @@ -147,7 +144,7 @@ Delegates.RoundedItemDelegate { QQC2.Button { id: configButton - visible: root.hovered && !Kirigami.Settings.isMobile && !NeoChatConfig.compactRoomList && !root.collapsed && root.showConfigure + visible: root.hovered && !Kirigami.Settings.isMobile /*&& !NeoChatConfig.compactRoomList*/ && !root.collapsed && root.showConfigure text: i18n("Configure room") display: QQC2.Button.IconOnly diff --git a/src/qml/RoomListPage.qml b/src/qml/RoomListPage.qml index ffb0b1cb5..43485410d 100644 --- a/src/qml/RoomListPage.qml +++ b/src/qml/RoomListPage.qml @@ -1,295 +1,117 @@ -// SPDX-FileCopyrightText: 2019 Black Hat -// SPDX-FileCopyrightText: 2020 Carl Schwan -// SPDX-License-Identifier: GPL-3.0-only +// SPDX-FileCopyrightText: 2025 Tobias Fella +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma ComponentBehavior: Bound import QtQuick import QtQuick.Controls as QQC2 import QtQuick.Layouts -import QtQml.Models import Qt.labs.qmlmodels import org.kde.kirigami as Kirigami -import org.kde.kirigamiaddons.components as KirigamiComponents +import org.kde.kirigamiaddons.formcard as FormCard import org.kde.kirigamiaddons.delegates as Delegates import org.kde.neochat - -Kirigami.Page { +Kirigami.ScrollablePage { id: root - /** - * @brief The current width of the room list. - * - * @note Other objects can access the value but the private function makes sure - * that only the internal members can modify it. - */ - readonly property int currentWidth: _private.currentWidth + spaceDrawer.width + 1 + title: i18nc("@title", "Rooms") required property NeoChatConnection connection - readonly property bool collapsed: NeoChatConfig.collapsed - - signal search - - onCurrentWidthChanged: pageStack.defaultColumnWidth = root.currentWidth - Component.onCompleted: pageStack.defaultColumnWidth = root.currentWidth - - - onCollapsedChanged: { - if (collapsed) { - RoomManager.sortFilterRoomTreeModel.filterText = ""; + actions: [ + Kirigami.Action { + text: i18nc("@action:button", "Log out") + onTriggered: root.connection.logout() + }, + Kirigami.Action { + text: i18nc("@action:button", "Create Room") + onTriggered: root.connection.createRoom("Hello", "World", "") } - } + ] - function goToNextRoomFiltered(condition) { - let index = treeView.rowAtIndex(RoomManager.sortFilterRoomTreeModel.currentRoomIndex()); - while (index++ < treeView.rows) { - let item = treeView.itemAtIndex(treeView.index(index, 0)) - if (condition(item)) { - RoomManager.resolveResource(item.currentRoom.id) - return; - } + Connections { + target: root.connection + function onOpenRoom(): void { + room => pageStack.push(Qt.createComponent("org.kde.neochat", "RoomPage"), { + room: room, + connection: connection, + }); } } - function goToPreviousRoomFiltered(condition) { - let index = treeView.rowAtIndex(RoomManager.sortFilterRoomTreeModel.currentRoomIndex()); - while (index-- > 0) { - let item = treeView.itemAtIndex(treeView.index(index, 0)) - if (condition(item)) { - RoomManager.resolveResource(item.currentRoom.id) - return; - } - } - } - - function goToNextRoom() { - goToNextRoomFiltered(item => (item && item instanceof RoomDelegate)); - } - - function goToPreviousRoom() { - goToPreviousRoomFiltered(item => (item && item instanceof RoomDelegate)); - } - - function goToNextUnreadRoom() { - goToNextRoomFiltered(item => (item && item instanceof RoomDelegate && item.hasUnread)); - } - - function goToPreviousUnreadRoom() { - goToPreviousRoomFiltered(item => (item && item instanceof RoomDelegate && item.hasUnread)); - } - titleDelegate: Loader { Layout.fillWidth: true sourceComponent: Kirigami.Settings.isMobile ? userInfo : exploreComponent } - padding: 0 - - Connections { - target: RoomManager - function onCurrentSpaceChanged() { - treeView.expandRecursively(); - } - - function onCurrentRoomChanged() { - treeView.positionViewAtIndex(RoomManager.sortFilterRoomTreeModel.currentRoomIndex(), TableView.AlignVCenter) - } - } - - RowLayout { - anchors.fill: parent - spacing: 0 - - SpaceDrawer { - id: spaceDrawer - Layout.preferredWidth: Kirigami.Units.gridUnit * 3 - Layout.fillHeight: true - - connection: root.connection - } - - Kirigami.Separator { - Layout.fillHeight: true - Layout.preferredWidth: 1 - } - - QQC2.ScrollView { - id: scrollView - Layout.fillWidth: true - Layout.fillHeight: true - - background: Rectangle { - color: Kirigami.Theme.backgroundColor - Kirigami.Theme.colorSet: Kirigami.Theme.View - } - - Keys.onDownPressed: ; // Do not delete 🫠 - Keys.onUpPressed: ; // These make sure the scrollview doesn't also scroll while going through the roomlist using the arrow keys - - contentItem: TreeView { - id: treeView - topMargin: Math.round(Kirigami.Units.smallSpacing / 2) - - clip: true - reuseItems: false - - model: RoomManager.sortFilterRoomTreeModel - - selectionModel: ItemSelectionModel {} - - delegate: DelegateChooser { - role: "delegateType" - - DelegateChoice { - roleValue: "section" - delegate: RoomTreeSection { - collapsed: root.collapsed - } - } - - DelegateChoice { - roleValue: "normal" - delegate: RoomDelegate { - id: roomDelegate - required property int row - required property TreeView treeView - required property bool current - onCurrentChanged: if (current) { - forceActiveFocus(Qt.TabFocusReason); - } - - implicitWidth: treeView.width - connection: root.connection - collapsed: root.collapsed - highlighted: RoomManager.currentRoom === currentRoom - } - } - - DelegateChoice { - roleValue: "addDirect" - delegate: Delegates.RoundedItemDelegate { - text: i18n("Find your friends") - icon.name: "list-add-user" - icon.width: Kirigami.Units.gridUnit * 2 - icon.height: Kirigami.Units.gridUnit * 2 - - onClicked: pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'UserSearchPage'), { - connection: root.connection - }, { - title: i18nc("@title", "Find your friends") - }) - } - } - } - } - } - } - - Kirigami.PlaceholderMessage { - anchors.centerIn: parent - anchors.horizontalCenterOffset: (spaceDrawer.width + 1) / 2 - width: scrollView.width - Kirigami.Units.largeSpacing * 4 - visible: treeView.rows == 0 - text: if (RoomManager.sortFilterRoomTreeModel.filterText.length > 0) { - return spaceDrawer.showDirectChats ? i18n("No friends found") : i18n("No rooms found"); - } else { - return spaceDrawer.showDirectChats ? i18n("You haven't added any of your friends yet, click below to search for them.") : i18n("Join some rooms to get started"); - } - helpfulAction: spaceDrawer.showDirectChats ? userSearchAction : exploreRoomAction - - Kirigami.Action { - id: exploreRoomAction - icon.name: RoomManager.sortFilterRoomTreeModel.filterText.length > 0 ? "search" : "list-add" - text: RoomManager.sortFilterRoomTreeModel.filterText.length > 0 ? i18n("Search in room directory") : i18n("Explore rooms") - onTriggered: { - let dialog = pageStack.layers.push(Qt.createComponent('org.kde.neochat', 'ExploreRoomsPage'), { - connection: root.connection, - keyword: RoomManager.sortFilterRoomTreeModel.filterText - }, { - title: i18nc("@title", "Explore Rooms") - }); - dialog.roomSelected.connect((roomId, displayName, avatarUrl, alias, topic, memberCount, isJoined) => { - RoomManager.resolveResource(roomId.length > 0 ? roomId : alias, isJoined ? "" : "join"); - }); - } - } - - Kirigami.Action { - id: userSearchAction - icon.name: RoomManager.sortFilterRoomTreeModel.filterText.length > 0 ? "search" : "list-add" - text: RoomManager.sortFilterRoomTreeModel.filterText.length > 0 ? i18n("Search in friend directory") : i18n("Find your friends") - onTriggered: pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'UserSearchPage'), { - connection: root.connection - }, { - title: i18nc("@title", "Find your friends") - }) - } - } - footer: Loader { width: parent.width sourceComponent: Kirigami.Settings.isMobile ? exploreComponentMobile : userInfoDesktop } - MouseArea { - anchors.top: parent.top - anchors.bottom: parent.bottom - parent: applicationWindow().overlay.parent + TreeView { + id: treeView + topMargin: Math.round(Kirigami.Units.smallSpacing / 2) - x: root.currentWidth - width / 2 - width: Kirigami.Units.smallSpacing * 2 - z: root.z + 1 - enabled: RoomManager.hasOpenRoom && applicationWindow().width >= Kirigami.Units.gridUnit * 35 - visible: enabled - cursorShape: Qt.SplitHCursor + clip: true + reuseItems: false - property int _lastX - - onPressed: mouse => { - _lastX = mouse.x; - } - onPositionChanged: mouse => { - if (_lastX == -1) { - return; + model: SortFilterRoomTreeModel { + sourceModel: RoomTreeModel { + connection: root.connection } - if (mouse.x > _lastX) { - // we moved to the right - if (_private.currentWidth < _private.collapseWidth && _private.currentWidth + (mouse.x - _lastX) >= _private.collapseWidth) { - // Here we get back directly to a more wide mode. - _private.currentWidth = _private.defaultWidth; - NeoChatConfig.collapsed = false; - } else if (_private.currentWidth >= _private.collapseWidth) { - // Increase page width - _private.currentWidth = Math.min(_private.defaultWidth, _private.currentWidth + (mouse.x - _lastX)); + } + + selectionModel: ItemSelectionModel {} + + delegate: DelegateChooser { + role: "delegateType" + + DelegateChoice { + roleValue: "section" + delegate: RoomTreeSection { + collapsed: root.collapsed } - } else if (mouse.x < _lastX) { - const tmpWidth = _private.currentWidth - (_lastX - mouse.x); - if (tmpWidth < _private.collapseWidth) { - _private.currentWidth = Qt.binding(() => _private.collapsedSize); - NeoChatConfig.collapsed = true; - } else { - _private.currentWidth = tmpWidth; + } + + DelegateChoice { + roleValue: "normal" + delegate: RoomDelegate { + id: roomDelegate + required property int row + required property TreeView treeView + required property bool current + onCurrentChanged: if (current) { + forceActiveFocus(Qt.TabFocusReason); + } + + implicitWidth: treeView.width + connection: root.connection + collapsed: root.collapsed + highlighted: RoomManager.currentRoom === currentRoom + } + } + + DelegateChoice { + roleValue: "addDirect" + delegate: Delegates.RoundedItemDelegate { + text: i18n("Find your friends") + icon.name: "list-add-user" + icon.width: Kirigami.Units.gridUnit * 2 + icon.height: Kirigami.Units.gridUnit * 2 + + onClicked: pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'UserSearchPage'), { + connection: root.connection + }, { + title: i18nc("@title", "Find your friends") + }) } } } } - Component { - id: userInfo - UserInfo { - bottomEdge: false - connection: root.connection - } - } - - Component { - id: userInfoDesktop - UserInfoDesktop { - connection: root.connection - collapsed: root.collapsed - } - } Component { id: exploreComponent @@ -308,25 +130,10 @@ Kirigami.Page { } Component { - id: exploreComponentMobile - ExploreComponentMobile { + id: userInfoDesktop + UserInfoDesktop { connection: root.connection - - onTextChanged: newText => { - RoomManager.sortFilterRoomTreeModel.filterText = newText; - } + collapsed: root.collapsed } } - - /* - * Hold the modifiable currentWidth in a private object so that only internal - * members can modify it. - */ - QtObject { - id: _private - property int currentWidth: NeoChatConfig.collapsed ? collapsedSize : defaultWidth - readonly property int defaultWidth: Kirigami.Units.gridUnit * 15 - readonly property int collapseWidth: Kirigami.Units.gridUnit * 10 - readonly property int collapsedSize: Kirigami.Units.gridUnit + (NeoChatConfig.compactRoomList ? 0 : Kirigami.Units.largeSpacing * 2) + Kirigami.Units.largeSpacing * 2 + (scrollView.QQC2.ScrollBar.vertical.visible ? scrollView.QQC2.ScrollBar.vertical.width : 0) - } } diff --git a/src/qml/RoomMedia.qml b/src/qml/RoomMedia.qml index f12ea6742..94fb90483 100644 --- a/src/qml/RoomMedia.qml +++ b/src/qml/RoomMedia.qml @@ -38,32 +38,32 @@ QQC2.ScrollView { // HACK: Hide unnecessary horizontal scrollbar (https://bugreports.qt.io/browse/QTBUG-83890) QQC2.ScrollBar.horizontal.policy: QQC2.ScrollBar.AlwaysOff - ListView { - clip: true - verticalLayoutDirection: ListView.BottomToTop - - model: RoomManager.mediaMessageFilterModel - - delegate: DelegateChooser { - role: "type" - - DelegateChoice { - roleValue: MediaMessageFilterModel.Image - delegate: MessageDelegate { - alwaysFillWidth: true - cardBackground: false - room: root.currentRoom - } - } - - DelegateChoice { - roleValue: MediaMessageFilterModel.Video - delegate: MessageDelegate { - alwaysFillWidth: true - cardBackground: false - room: root.currentRoom - } - } - } - } + // ListView { + // clip: true + // verticalLayoutDirection: ListView.BottomToTop + // + // model: RoomManager.mediaMessageFilterModel + // + // delegate: DelegateChooser { + // role: "type" + // + // DelegateChoice { + // roleValue: MediaMessageFilterModel.Image + // delegate: MessageDelegate { + // alwaysFillWidth: true + // cardBackground: false + // room: root.currentRoom + // } + // } + // + // DelegateChoice { + // roleValue: MediaMessageFilterModel.Video + // delegate: MessageDelegate { + // alwaysFillWidth: true + // cardBackground: false + // room: root.currentRoom + // } + // } + // } + // } } diff --git a/src/qml/RoomPage.qml b/src/qml/RoomPage.qml index 5279bf59d..0a11bac75 100644 --- a/src/qml/RoomPage.qml +++ b/src/qml/RoomPage.qml @@ -32,7 +32,7 @@ Kirigami.Page { * * @sa TimelineModel */ - property TimelineModel timelineModel: RoomManager.timelineModel + // property TimelineModel timelineModel: RoomManager.timelineModel /** * @brief The MessageFilterModel to use. @@ -44,7 +44,7 @@ Kirigami.Page { * * @sa TimelineModel, MessageFilterModel */ - property MessageFilterModel messageFilterModel: RoomManager.messageFilterModel + // property MessageFilterModel messageFilterModel: RoomManager.messageFilterModel /** * @brief The MediaMessageFilterModel to use. @@ -57,7 +57,7 @@ Kirigami.Page { * * @sa TimelineModel, MessageFilterModel */ - property MediaMessageFilterModel mediaMessageFilterModel: RoomManager.mediaMessageFilterModel + // property MediaMessageFilterModel mediaMessageFilterModel: RoomManager.mediaMessageFilterModel property bool loading: !root.currentRoom || (root.currentRoom.timelineSize === 0 && !root.currentRoom.allHistoryLoaded) @@ -106,58 +106,58 @@ Kirigami.Page { position: Kirigami.InlineMessage.Position.Header } - Loader { - id: timelineViewLoader - anchors.fill: parent - active: root.currentRoom && !root.currentRoom.isInvite && !root.loading && !root.currentRoom.isSpace - sourceComponent: TimelineView { - id: timelineView - currentRoom: root.currentRoom - page: root - timelineModel: root.timelineModel - messageFilterModel: root.messageFilterModel - onFocusChatBar: { - if (chatBarLoader.item) { - chatBarLoader.item.forceActiveFocus(); - } - } - } - } + // Loader { + // id: timelineViewLoader + // anchors.fill: parent + // active: root.currentRoom && !root.currentRoom.isInvite && !root.loading && !root.currentRoom.isSpace + // sourceComponent: TimelineView { + // id: timelineView + // currentRoom: root.currentRoom + // page: root + // timelineModel: root.timelineModel + // messageFilterModel: root.messageFilterModel + // onFocusChatBar: { + // if (chatBarLoader.item) { + // chatBarLoader.item.forceActiveFocus(); + // } + // } + // } + // } - Loader { - id: invitationLoader - active: root.currentRoom && root.currentRoom.isInvite - anchors.centerIn: parent - sourceComponent: InvitationView { - currentRoom: root.currentRoom - anchors.centerIn: parent - } - } + // Loader { + // id: invitationLoader + // active: root.currentRoom && root.currentRoom.isInvite + // anchors.centerIn: parent + // sourceComponent: InvitationView { + // currentRoom: root.currentRoom + // anchors.centerIn: parent + // } + // } - Loader { - id: spaceLoader - active: root.currentRoom && root.currentRoom.isSpace - anchors.fill: parent - sourceComponent: SpaceHomePage {} - } + // Loader { + // id: spaceLoader + // active: root.currentRoom && root.currentRoom.isSpace + // anchors.fill: parent + // sourceComponent: SpaceHomePage {} + // } - Loader { - active: !RoomManager.currentRoom - anchors.centerIn: parent - sourceComponent: Kirigami.PlaceholderMessage { - icon.name: "org.kde.neochat" - text: i18n("Welcome to NeoChat") - explanation: i18n("Select or join a room to get started") - } - } + // Loader { + // active: !RoomManager.currentRoom + // anchors.centerIn: parent + // sourceComponent: Kirigami.PlaceholderMessage { + // icon.name: "org.kde.neochat" + // text: i18n("Welcome to NeoChat") + // explanation: i18n("Select or join a room to get started") + // } + // } - Loader { - active: root.loading && !invitationLoader.active && RoomManager.currentRoom && !spaceLoader.active - anchors.centerIn: parent - sourceComponent: Kirigami.LoadingPlaceholder { - anchors.centerIn: parent - } - } + // Loader { + // active: root.loading && !invitationLoader.active && RoomManager.currentRoom && !spaceLoader.active + // anchors.centerIn: parent + // sourceComponent: Kirigami.LoadingPlaceholder { + // anchors.centerIn: parent + // } + // } background: Rectangle { Kirigami.Theme.colorSet: Kirigami.Theme.View @@ -290,26 +290,26 @@ Kirigami.Page { } } - Component { - id: messageDelegateContextMenu - MessageDelegateContextMenu { - connection: root.connection - } - } + // Component { + // id: messageDelegateContextMenu + // MessageDelegateContextMenu { + // connection: root.connection + // } + // } - Component { - id: fileDelegateContextMenu - FileDelegateContextMenu { - connection: root.connection - } - } + // Component { + // id: fileDelegateContextMenu + // FileDelegateContextMenu { + // connection: root.connection + // } + // } - Component { - id: maximizeComponent - NeochatMaximizeComponent { - currentRoom: root.currentRoom - model: root.mediaMessageFilterModel - parent: root.QQC2.Overlay.overlay - } - } + // Component { + // id: maximizeComponent + // NeochatMaximizeComponent { + // currentRoom: root.currentRoom + // model: root.mediaMessageFilterModel + // parent: root.QQC2.Overlay.overlay + // } + // } } diff --git a/src/qml/RoomTreeSection.qml b/src/qml/RoomTreeSection.qml index 15b33cf7e..8564ae3fa 100644 --- a/src/qml/RoomTreeSection.qml +++ b/src/qml/RoomTreeSection.qml @@ -47,7 +47,7 @@ QQC2.ItemDelegate { opacity: 0.7 level: 5 type: Kirigami.Heading.Primary - text: root.collapsed ? "" : model.displayName + text: root.collapsed ? "" : root.displayName elide: Text.ElideRight // we override the Primary type's font weight (DemiBold) for Bold for contrast with small text diff --git a/src/qml/UserInfo.qml b/src/qml/UserInfo.qml index 9cbc1c927..81aa47146 100644 --- a/src/qml/UserInfo.qml +++ b/src/qml/UserInfo.qml @@ -54,7 +54,7 @@ RowLayout { spacing: Kirigami.Units.largeSpacing KirigamiComponents.Avatar { - readonly property url avatarUrl: root.connection.localUser.avatarUrl + readonly property url avatarUrl: root.connection.avatarUrl Layout.preferredWidth: Kirigami.Units.iconSizes.medium Layout.preferredHeight: Kirigami.Units.iconSizes.medium @@ -62,7 +62,7 @@ RowLayout { // Note: User::avatarUrl does not set user_id, and thus cannot be used directly here. Hence the makeMediaUrl. source: avatarUrl.toString().length > 0 ? root.connection.makeMediaUrl(avatarUrl) : "" - name: root.connection.localUser.displayName + name: root.connection.displayName } ColumnLayout { @@ -73,14 +73,14 @@ RowLayout { QQC2.Label { id: displayNameLabel Layout.fillWidth: true - text: root.connection.localUser.displayName + text: root.connection.displayName textFormat: Text.PlainText elide: Text.ElideRight } QQC2.Label { id: idLabel Layout.fillWidth: true - text: (root.connection.label.length > 0 ? (root.connection.label + " ") : "") + root.connection.localUser.id + text: root.connection.matrixId font.pointSize: displayNameLabel.font.pointSize * 0.8 opacity: 0.7 textFormat: Text.PlainText diff --git a/src/roommanager.h b/src/roommanager.h index 8f26fad71..f9c178da9 100644 --- a/src/roommanager.h +++ b/src/roommanager.h @@ -7,9 +7,9 @@ #include #include #include -#include -#include -#include +// #include +// #include +// #include #include "chatdocumenthandler.h" #include "enums/messagecomponenttype.h" diff --git a/src/settings/CMakeLists.txt b/src/settings/CMakeLists.txt index 4314a84ae..2bbdf007d 100644 --- a/src/settings/CMakeLists.txt +++ b/src/settings/CMakeLists.txt @@ -4,7 +4,7 @@ qt_add_library(settings STATIC) set_source_files_properties( - RoomSettingsView.qml + # RoomSettingsView.qml NeoChatSettingsView.qml PROPERTIES QT_QML_SINGLETON_TYPE TRUE @@ -15,33 +15,33 @@ ecm_add_qml_module(settings GENERATE_PLUGIN_SOURCE OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/src/org/kde/neochat/settings QML_FILES NeoChatSettingsView.qml - RoomSettingsView.qml - AccountsPage.qml - AccountEditorPage.qml + # RoomSettingsView.qml + # AccountsPage.qml + # AccountEditorPage.qml AppearanceSettingsPage.qml - DevicesPage.qml - EmoticonsPage.qml - EmoticonEditorPage.qml + # DevicesPage.qml + # EmoticonsPage.qml + # EmoticonEditorPage.qml GlobalNotificationsPage.qml NeoChatGeneralPage.qml NeoChatSecurityPage.qml NetworkProxyPage.qml - Permissions.qml - PushNotification.qml - RoomGeneralPage.qml - RoomSecurityPage.qml - ColorScheme.qml - DevicesCard.qml - DeviceDelegate.qml - EmoticonFormCard.qml - IdentityServerDelegate.qml - IgnoredUsersDialog.qml + # Permissions.qml + # PushNotification.qml + # RoomGeneralPage.qml + # RoomSecurityPage.qml + # ColorScheme.qml + # DevicesCard.qml + # DeviceDelegate.qml + # EmoticonFormCard.qml + # IdentityServerDelegate.qml + # IgnoredUsersDialog.qml NotificationRuleItem.qml - PasswordSheet.qml + # PasswordSheet.qml ThemeRadioButton.qml - ThreePIdCard.qml - ImportKeysDialog.qml - ExportKeysDialog.qml - RoomSortParameterDialog.qml - RoomProfile.qml + # ThreePIdCard.qml + # ImportKeysDialog.qml + # ExportKeysDialog.qml + # RoomSortParameterDialog.qml + # RoomProfile.qml ) diff --git a/src/utils.cpp b/src/utils.cpp index 0f3a55a6e..fe0b4e055 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -10,13 +10,9 @@ #include #endif -#include - #include #include -using namespace Quotient; - bool QmlUtils::isEmoji(const QString &text) { return Utils::isEmoji(text); @@ -48,10 +44,10 @@ QQuickItem *QmlUtils::focusedWindowItem() } } -QString QmlUtils::nameForPowerLevelValue(const int value) -{ - return PowerLevel::nameForLevel(PowerLevel::levelForValue(value)); -} +// QString QmlUtils::nameForPowerLevelValue(const int value) +// { +// return PowerLevel::nameForLevel(PowerLevel::levelForValue(value)); +// } bool Utils::isEmoji(const QString &text) { diff --git a/src/utils.h b/src/utils.h index 9f1d75b13..20d5b3c57 100644 --- a/src/utils.h +++ b/src/utils.h @@ -10,9 +10,7 @@ #include #include -#include - -#include "enums/powerlevel.h" +// #include "enums/powerlevel.h" using namespace Qt::StringLiterals; @@ -43,7 +41,7 @@ public: /** * @brief Invokable version of PowerLevel::nameForLevel which also calls PowerLevel::levelForValue. */ - Q_INVOKABLE QString nameForPowerLevelValue(int value); + // Q_INVOKABLE QString nameForPowerLevelValue(int value); private: QmlUtils() = default;