diff --git a/.travis.yml b/.travis.yml index 08126853..443836cf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -137,11 +137,11 @@ before_install: # Use TRAVIS_TAG if defined, or the short commit SHA otherwise - export VERSION=${TRAVIS_TAG:-$(git rev-parse --short HEAD)} install: - - ./.ci/install.sh + - travis_wait ./.ci/install.sh - export PATH=/usr/local/bin:${PATH} script: - - ./.ci/script.sh + - travis_wait ./.ci/script.sh - sed -i -e "s/VERSION_NAME_VALUE/${VERSION}/g" ./.ci/bintray-release.json || true - cp ./.ci/bintray-release.json . deploy: diff --git a/CMakeLists.txt b/CMakeLists.txt index 282dc3ae..c962d2da 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,8 +35,6 @@ option(USE_BUNDLED_OPENSSL "Use the bundled version of OpenSSL." option(USE_BUNDLED_MTXCLIENT "Use the bundled version of the Matrix Client library." ${HUNTER_ENABLED}) option(USE_BUNDLED_SODIUM "Use the bundled version of libsodium." ${HUNTER_ENABLED}) -option(USE_BUNDLED_ZLIB "Use the bundled version of zlib." - ${HUNTER_ENABLED}) option(USE_BUNDLED_LMDB "Use the bundled version of lmdb." ${HUNTER_ENABLED}) option(USE_BUNDLED_LMDBXX "Use the bundled version of lmdb++." @@ -323,10 +321,7 @@ find_package(Boost 1.70 REQUIRED COMPONENTS iostreams system thread) -if(USE_BUNDLED_ZLIB) - hunter_add_package(ZLIB) -endif() -find_package(ZLIB REQUIRED) + if(USE_BUNDLED_OPENSSL) hunter_add_package(OpenSSL) endif() @@ -338,7 +333,7 @@ if(USE_BUNDLED_MTXCLIENT) FetchContent_Declare( MatrixClient GIT_REPOSITORY https://github.com/Nheko-Reborn/mtxclient.git - GIT_TAG 71bd56b66cf634341ffef804f07d33f01fd57c25 + GIT_TAG 1018c0822b80cdfc5d6b589fe94d1fd759113ef6 ) FetchContent_MakeAvailable(MatrixClient) else() diff --git a/README.md b/README.md index 0cb3e044..d051eadd 100644 --- a/README.md +++ b/README.md @@ -97,13 +97,6 @@ guix install nheko #### macOS (10.14 and above) - -with [macports](https://www.macports.org/): - -```sh -sudo port install nheko -``` - with [homebrew](https://brew.sh/): ```sh @@ -120,7 +113,7 @@ brew cask install nheko - [LMDB](https://symas.com/lightning-memory-mapped-database/) - [cmark](https://github.com/commonmark/cmark) 0.29 or greater. - Boost 1.70 or greater. -- [libolm](https://git.matrix.org/git/olm) +- [libolm](https://gitlab.matrix.org/matrix-org/olm) - [libsodium](https://github.com/jedisct1/libsodium) - [spdlog](https://github.com/gabime/spdlog) - A compiler that supports C++ 17: @@ -210,7 +203,7 @@ guix environment nheko ```bash brew update -brew install qt5 lmdb cmake llvm libsodium spdlog boost cmark +brew install qt5 lmdb cmake llvm libsodium spdlog boost cmark libolm ``` ##### Windows diff --git a/io.github.NhekoReborn.Nheko.json b/io.github.NhekoReborn.Nheko.json index 60d984fb..3de04370 100644 --- a/io.github.NhekoReborn.Nheko.json +++ b/io.github.NhekoReborn.Nheko.json @@ -146,9 +146,9 @@ "name": "mtxclient", "sources": [ { - "sha256": "7055f1459a43a12f27f949564624f13cc593ac894e445e6de0e6563ad38ebc3e", + "sha256": "537f4e6b280f351ad950cd6598c2407505a55f0d6c856b4ff97a9c59fc6fdb7a", "type": "archive", - "url": "https://github.com/Nheko-Reborn/mtxclient/archive/71bd56b66cf634341ffef804f07d33f01fd57c25.tar.gz" + "url": "https://github.com/Nheko-Reborn/mtxclient/archive/1018c0822b80cdfc5d6b589fe94d1fd759113ef6.tar.gz" } ] }, diff --git a/resources/langs/.gitignore b/resources/langs/.gitignore new file mode 100644 index 00000000..fc168248 --- /dev/null +++ b/resources/langs/.gitignore @@ -0,0 +1 @@ +*.qm \ No newline at end of file diff --git a/resources/langs/nheko_de.ts b/resources/langs/nheko_de.ts index 90f0e7d3..24c6cea7 100644 --- a/resources/langs/nheko_de.ts +++ b/resources/langs/nheko_de.ts @@ -245,7 +245,7 @@ This message is not encrypted! - + Diese Nachricht ist nicht verschlüsselt! @@ -673,7 +673,7 @@ Beispiel: https://mein.server:8787 %1 made this room require and invitation to join. - + %1 hat eingestellt, dass dieser Raum eine Einladung benötigt um beizutreten. @@ -1037,7 +1037,7 @@ Beispiel: https://mein.server:8787 INTERFACE - + OBERFLÄCHE diff --git a/resources/langs/nheko_en.qm b/resources/langs/nheko_en.qm deleted file mode 100644 index 0973db2d..00000000 Binary files a/resources/langs/nheko_en.qm and /dev/null differ diff --git a/resources/qml/TimelineRow.qml b/resources/qml/TimelineRow.qml index 9fc98419..07831c59 100644 --- a/resources/qml/TimelineRow.qml +++ b/resources/qml/TimelineRow.qml @@ -14,6 +14,7 @@ MouseArea { height: row.height propagateComposedEvents: true preventStealing: true + hoverEnabled: true acceptedButtons: Qt.LeftButton | Qt.RightButton onClicked: { @@ -24,7 +25,10 @@ MouseArea { if (mouse.source === Qt.MouseEventNotSynthesized) messageContextMenu.show(model.id, model.type, model.isEncrypted, row) } - + Rectangle { + color: (timelineSettings.message_hover_highlight && parent.containsMouse) ? colors.base : "transparent" + anchors.fill: row + } RowLayout { id: row diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index ea5e6d60..721fd2b8 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -34,6 +34,7 @@ Page { id: timelineSettings category: "user/timeline" property bool buttons: true + property bool message_hover_highlight: false } EmojiPicker { @@ -113,6 +114,7 @@ Page { } BusyIndicator { + visible: running anchors.centerIn: parent running: timelineManager.isInitialSync height: 200 diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp index bfefd7bb..6670532c 100644 --- a/src/ChatPage.cpp +++ b/src/ChatPage.cpp @@ -1017,7 +1017,7 @@ ChatPage::trySync() // TODO: fine grained error handling try { cache::saveState(res); - olm::handle_to_device_messages(res.to_device); + olm::handle_to_device_messages(res.to_device.events); auto updates = cache::roomUpdates(res); @@ -1240,7 +1240,7 @@ ChatPage::initialSyncHandler(const mtx::responses::Sync &res, mtx::http::Request try { cache::saveState(res); - olm::handle_to_device_messages(res.to_device); + olm::handle_to_device_messages(res.to_device.events); emit initializeViews(std::move(res.rooms)); emit initializeRoomList(cache::roomInfo()); diff --git a/src/Olm.cpp b/src/Olm.cpp index 8ea39566..2c4f6186 100644 --- a/src/Olm.cpp +++ b/src/Olm.cpp @@ -23,52 +23,55 @@ client() } void -handle_to_device_messages(const std::vector &msgs) +handle_to_device_messages(const std::vector &msgs) { if (msgs.empty()) return; nhlog::crypto()->info("received {} to_device messages", msgs.size()); + nlohmann::json j_msg; for (const auto &msg : msgs) { - if (msg.count("type") == 0) { + j_msg = std::visit([](auto &e) { return json(e); }, std::move(msg)); + if (j_msg.count("type") == 0) { nhlog::crypto()->warn("received message with no type field: {}", - msg.dump(2)); + j_msg.dump(2)); continue; } - std::string msg_type = msg.at("type"); + std::string msg_type = j_msg.at("type"); if (msg_type == to_string(mtx::events::EventType::RoomEncrypted)) { try { - OlmMessage olm_msg = msg; + OlmMessage olm_msg = j_msg; handle_olm_message(std::move(olm_msg)); } catch (const nlohmann::json::exception &e) { nhlog::crypto()->warn( - "parsing error for olm message: {} {}", e.what(), msg.dump(2)); + "parsing error for olm message: {} {}", e.what(), j_msg.dump(2)); } catch (const std::invalid_argument &e) { - nhlog::crypto()->warn( - "validation error for olm message: {} {}", e.what(), msg.dump(2)); + nhlog::crypto()->warn("validation error for olm message: {} {}", + e.what(), + j_msg.dump(2)); } } else if (msg_type == to_string(mtx::events::EventType::RoomKeyRequest)) { - nhlog::crypto()->warn("handling key request event: {}", msg.dump(2)); + nhlog::crypto()->warn("handling key request event: {}", j_msg.dump(2)); try { - mtx::events::msg::KeyRequest req = msg; - if (req.action == mtx::events::msg::RequestAction::Request) - handle_key_request_message(std::move(req)); + mtx::events::DeviceEvent req = j_msg; + if (req.content.action == mtx::events::msg::RequestAction::Request) + handle_key_request_message(req); else nhlog::crypto()->warn( "ignore key request (unhandled action): {}", - req.request_id); + req.content.request_id); } catch (const nlohmann::json::exception &e) { nhlog::crypto()->warn( "parsing error for key_request message: {} {}", e.what(), - msg.dump(2)); + j_msg.dump(2)); } } else { - nhlog::crypto()->warn("unhandled event: {}", msg.dump(2)); + nhlog::crypto()->warn("unhandled event: {}", j_msg.dump(2)); } } } @@ -341,51 +344,53 @@ send_key_request_for(const std::string &room_id, } void -handle_key_request_message(const mtx::events::msg::KeyRequest &req) +handle_key_request_message(const mtx::events::DeviceEvent &req) { - if (req.algorithm != MEGOLM_ALGO) { + if (req.content.algorithm != MEGOLM_ALGO) { nhlog::crypto()->debug("ignoring key request {} with invalid algorithm: {}", - req.request_id, - req.algorithm); + req.content.request_id, + req.content.algorithm); return; } // Check if we were the sender of the session being requested. - if (req.sender_key != olm::client()->identity_keys().curve25519) { + if (req.content.sender_key != olm::client()->identity_keys().curve25519) { nhlog::crypto()->debug("ignoring key request {} because we were not the sender: " "\nrequested({}) ours({})", - req.request_id, - req.sender_key, + req.content.request_id, + req.content.sender_key, olm::client()->identity_keys().curve25519); return; } // Check if we have the keys for the requested session. - if (!cache::outboundMegolmSessionExists(req.room_id)) { - nhlog::crypto()->warn("requested session not found in room: {}", req.room_id); + if (!cache::outboundMegolmSessionExists(req.content.room_id)) { + nhlog::crypto()->warn("requested session not found in room: {}", + req.content.room_id); return; } // Check that the requested session_id and the one we have saved match. - const auto session = cache::getOutboundMegolmSession(req.room_id); - if (req.session_id != session.data.session_id) { + const auto session = cache::getOutboundMegolmSession(req.content.room_id); + if (req.content.session_id != session.data.session_id) { nhlog::crypto()->warn("session id of retrieved session doesn't match the request: " "requested({}), ours({})", - req.session_id, + req.content.session_id, session.data.session_id); return; } - if (!cache::isRoomMember(req.sender, req.room_id)) { + if (!cache::isRoomMember(req.sender, req.content.room_id)) { nhlog::crypto()->warn( "user {} that requested the session key is not member of the room {}", req.sender, - req.room_id); + req.content.room_id); return; } - if (!utils::respondsToKeyRequests(req.room_id)) { - nhlog::crypto()->debug("ignoring all key requests for room {}", req.room_id); + if (!utils::respondsToKeyRequests(req.content.room_id)) { + nhlog::crypto()->debug("ignoring all key requests for room {}", + req.content.room_id); return; } @@ -393,11 +398,11 @@ handle_key_request_message(const mtx::events::msg::KeyRequest &req) // Prepare the m.room_key event. // auto payload = json{{"algorithm", "m.megolm.v1.aes-sha2"}, - {"room_id", req.room_id}, - {"session_id", req.session_id}, + {"room_id", req.content.room_id}, + {"session_id", req.content.session_id}, {"session_key", session.data.session_key}}; - send_megolm_key_to_device(req.sender, req.requesting_device_id, payload); + send_megolm_key_to_device(req.sender, req.content.requesting_device_id, payload); } void diff --git a/src/Olm.h b/src/Olm.h index 28521413..09038ad1 100644 --- a/src/Olm.h +++ b/src/Olm.h @@ -40,7 +40,7 @@ mtx::crypto::OlmClient * client(); void -handle_to_device_messages(const std::vector &msgs); +handle_to_device_messages(const std::vector &msgs); nlohmann::json try_olm_decryption(const std::string &sender_key, @@ -77,7 +77,7 @@ send_key_request_for(const std::string &room_id, const mtx::events::EncryptedEvent &); void -handle_key_request_message(const mtx::events::msg::KeyRequest &); +handle_key_request_message(const mtx::events::DeviceEvent &); void send_megolm_key_to_device(const std::string &user_id, diff --git a/src/UserSettingsPage.cpp b/src/UserSettingsPage.cpp index e19aa876..6af08e12 100644 --- a/src/UserSettingsPage.cpp +++ b/src/UserSettingsPage.cpp @@ -51,11 +51,13 @@ void UserSettings::load() { QSettings settings; - isTrayEnabled_ = settings.value("user/window/tray", false).toBool(); - hasDesktopNotifications_ = settings.value("user/desktop_notifications", true).toBool(); - isStartInTrayEnabled_ = settings.value("user/window/start_in_tray", false).toBool(); - isGroupViewEnabled_ = settings.value("user/group_view", true).toBool(); - isButtonsInTimelineEnabled_ = settings.value("user/timeline/buttons", true).toBool(); + isTrayEnabled_ = settings.value("user/window/tray", false).toBool(); + hasDesktopNotifications_ = settings.value("user/desktop_notifications", true).toBool(); + isStartInTrayEnabled_ = settings.value("user/window/start_in_tray", false).toBool(); + isGroupViewEnabled_ = settings.value("user/group_view", true).toBool(); + isButtonsInTimelineEnabled_ = settings.value("user/timeline/buttons", true).toBool(); + isMessageHoverHighlightEnabled_ = + settings.value("user/timeline/message_hover_highlight", false).toBool(); isMarkdownEnabled_ = settings.value("user/markdown_enabled", true).toBool(); isTypingNotificationsEnabled_ = settings.value("user/typing_notifications", true).toBool(); sortByImportance_ = settings.value("user/sort_by_unread", true).toBool(); @@ -165,6 +167,7 @@ UserSettings::save() settings.beginGroup("timeline"); settings.setValue("buttons", isButtonsInTimelineEnabled_); + settings.setValue("message_hover_highlight", isMessageHoverHighlightEnabled_); settings.endGroup(); settings.setValue("avatar_circles", avatarCircles_); @@ -235,6 +238,7 @@ UserSettingsPage::UserSettingsPage(QSharedPointer settings, QWidge groupViewToggle_ = new Toggle{this}; timelineButtonsToggle_ = new Toggle{this}; typingNotifications_ = new Toggle{this}; + messageHoverHighlight_ = new Toggle{this}; sortByImportance_ = new Toggle{this}; readReceipts_ = new Toggle{this}; markdownEnabled_ = new Toggle{this}; @@ -345,6 +349,7 @@ UserSettingsPage::UserSettingsPage(QSharedPointer settings, QWidge boxWrap(tr("Read receipts"), readReceipts_); boxWrap(tr("Send messages as Markdown"), markdownEnabled_); boxWrap(tr("Desktop notifications"), desktopNotifications_); + boxWrap(tr("Highlight message on hover"), messageHoverHighlight_); formLayout_->addRow(uiLabel_); formLayout_->addRow(new HorizontalLine{this}); @@ -463,6 +468,10 @@ UserSettingsPage::UserSettingsPage(QSharedPointer settings, QWidge settings_->setDesktopNotifications(!isDisabled); }); + connect(messageHoverHighlight_, &Toggle::toggled, this, [this](bool isDisabled) { + settings_->setMessageHoverHighlight(!isDisabled); + }); + connect( sessionKeysImportBtn, &QPushButton::clicked, this, &UserSettingsPage::importSessionKeys); @@ -495,6 +504,7 @@ UserSettingsPage::showEvent(QShowEvent *) readReceipts_->setState(!settings_->isReadReceiptsEnabled()); markdownEnabled_->setState(!settings_->isMarkdownEnabled()); desktopNotifications_->setState(!settings_->hasDesktopNotifications()); + messageHoverHighlight_->setState(!settings_->isMessageHoverHighlightEnabled()); deviceIdValue_->setText(QString::fromStdString(http::client()->device_id())); deviceFingerprintValue_->setText( diff --git a/src/UserSettingsPage.h b/src/UserSettingsPage.h index 6b9834ea..088bbfb5 100644 --- a/src/UserSettingsPage.h +++ b/src/UserSettingsPage.h @@ -44,6 +44,11 @@ public: void load(); void applyTheme(); void setTheme(QString theme); + void setMessageHoverHighlight(bool state) + { + isMessageHoverHighlightEnabled_ = state; + save(); + } void setTray(bool state) { isTrayEnabled_ = state; @@ -118,6 +123,7 @@ public: } QString theme() const { return !theme_.isEmpty() ? theme_ : defaultTheme_; } + bool isMessageHoverHighlightEnabled() const { return isMessageHoverHighlightEnabled_; } bool isTrayEnabled() const { return isTrayEnabled_; } bool isStartInTrayEnabled() const { return isStartInTrayEnabled_; } bool isGroupViewEnabled() const { return isGroupViewEnabled_; } @@ -144,6 +150,7 @@ private: ? "light" : "system"; QString theme_; + bool isMessageHoverHighlightEnabled_; bool isTrayEnabled_; bool isStartInTrayEnabled_; bool isGroupViewEnabled_; @@ -203,6 +210,7 @@ private: Toggle *groupViewToggle_; Toggle *timelineButtonsToggle_; Toggle *typingNotifications_; + Toggle *messageHoverHighlight_; Toggle *sortByImportance_; Toggle *readReceipts_; Toggle *markdownEnabled_; diff --git a/src/main.cpp b/src/main.cpp index 09c326f4..ec4f638d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -116,6 +116,7 @@ main(int argc, char *argv[]) QCoreApplication::setApplicationName("nheko"); QCoreApplication::setApplicationVersion(nheko::version); QCoreApplication::setOrganizationName("nheko"); + QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); SingleApplication app(argc,