From e2f547149a5d54747ab44a6f777f91edd8d2f76e Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Mon, 27 Jan 2020 15:59:25 +0100 Subject: [PATCH 1/6] Allow sending messages as plain text --- src/ChatPage.cpp | 2 +- src/UserSettingsPage.cpp | 93 ++++++++++++---------------- src/UserSettingsPage.h | 10 +++ src/install-debian.txt | 24 +++++++ src/timeline/TimelineViewManager.cpp | 17 +++-- src/timeline/TimelineViewManager.h | 5 +- 6 files changed, 90 insertions(+), 61 deletions(-) create mode 100644 src/install-debian.txt diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp index 125e229a..c7739281 100644 --- a/src/ChatPage.cpp +++ b/src/ChatPage.cpp @@ -116,7 +116,7 @@ ChatPage::ChatPage(QSharedPointer userSettings, QWidget *parent) contentLayout_->setMargin(0); top_bar_ = new TopRoomBar(this); - view_manager_ = new TimelineViewManager(this); + view_manager_ = new TimelineViewManager(userSettings_, this); contentLayout_->addWidget(top_bar_); contentLayout_->addWidget(view_manager_->getWidget()); diff --git a/src/UserSettingsPage.cpp b/src/UserSettingsPage.cpp index 6809d605..b73f80a1 100644 --- a/src/UserSettingsPage.cpp +++ b/src/UserSettingsPage.cpp @@ -50,6 +50,7 @@ UserSettings::load() 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(); + isMarkdownEnabled_ = settings.value("user/markdown_enabled", true).toBool(); isTypingNotificationsEnabled_ = settings.value("user/typing_notifications", true).toBool(); isReadReceiptsEnabled_ = settings.value("user/read_receipts", true).toBool(); theme_ = settings.value("user/theme", defaultTheme_).toString(); @@ -126,6 +127,7 @@ UserSettings::save() settings.setValue("typing_notifications", isTypingNotificationsEnabled_); settings.setValue("read_receipts", isReadReceiptsEnabled_); settings.setValue("group_view", isGroupViewEnabled_); + settings.setValue("markdown_enabled", isMarkdownEnabled_); settings.setValue("desktop_notifications", hasDesktopNotifications_); settings.setValue("theme", theme()); settings.setValue("font_family", font_); @@ -167,70 +169,46 @@ UserSettingsPage::UserSettingsPage(QSharedPointer settings, QWidge topBarLayout_->addWidget(backBtn_, 1, Qt::AlignLeft | Qt::AlignVCenter); topBarLayout_->addStretch(1); - auto trayOptionLayout_ = new QHBoxLayout; - trayOptionLayout_->setContentsMargins(0, OptionMargin, 0, OptionMargin); - auto trayLabel = new QLabel(tr("Minimize to tray"), this); - trayLabel->setFont(font); - trayToggle_ = new Toggle(this); + auto addSetting = [this, &font](QString labelText) { + auto layout = new QHBoxLayout; + layout->setContentsMargins(0, OptionMargin, 0, OptionMargin); - trayOptionLayout_->addWidget(trayLabel); - trayOptionLayout_->addWidget(trayToggle_, 0, Qt::AlignRight); + auto label = new QLabel(labelText, this); + label->setFont(font); - auto startInTrayOptionLayout_ = new QHBoxLayout; - startInTrayOptionLayout_->setContentsMargins(0, OptionMargin, 0, OptionMargin); - auto startInTrayLabel = new QLabel(tr("Start in tray"), this); - startInTrayLabel->setFont(font); - startInTrayToggle_ = new Toggle(this); + auto toggle = new Toggle(this); + + layout->addWidget(label); + layout->addWidget(toggle, 0, Qt::AlignRight); + + return std::pair{layout, toggle}; + }; + + QHBoxLayout *trayOptionLayout_ = nullptr; + std::tie(trayOptionLayout_, trayToggle_) = addSetting(tr("Minimize to tray")); + + QHBoxLayout *startInTrayOptionLayout_ = nullptr; + std::tie(startInTrayOptionLayout_, startInTrayToggle_) = addSetting(tr("Start in tray")); if (!settings_->isTrayEnabled()) startInTrayToggle_->setDisabled(true); - startInTrayOptionLayout_->addWidget(startInTrayLabel); - startInTrayOptionLayout_->addWidget(startInTrayToggle_, 0, Qt::AlignRight); + QHBoxLayout *groupViewLayout = nullptr; + std::tie(groupViewLayout, groupViewToggle_) = addSetting(tr("Group's sidebar")); - auto groupViewLayout = new QHBoxLayout; - groupViewLayout->setContentsMargins(0, OptionMargin, 0, OptionMargin); - auto groupViewLabel = new QLabel(tr("Group's sidebar"), this); - groupViewLabel->setFont(font); - groupViewToggle_ = new Toggle(this); + QHBoxLayout *avatarViewLayout = nullptr; + std::tie(avatarViewLayout, avatarCircles_) = addSetting(tr("Circular Avatars")); - groupViewLayout->addWidget(groupViewLabel); - groupViewLayout->addWidget(groupViewToggle_, 0, Qt::AlignRight); + QHBoxLayout *typingLayout = nullptr; + std::tie(typingLayout, typingNotifications_) = addSetting(tr("Typing notifications")); - auto avatarViewLayout = new QHBoxLayout; - avatarViewLayout->setContentsMargins(0, OptionMargin, 0, OptionMargin); - auto avatarViewLabel = new QLabel(tr("Circular Avatars"), this); - avatarViewLabel->setFont(font); - avatarCircles_ = new Toggle(this); + QHBoxLayout *receiptsLayout = nullptr; + std::tie(receiptsLayout, readReceipts_) = addSetting(tr("Read receipts")); - avatarViewLayout->addWidget(avatarViewLabel); - avatarViewLayout->addWidget(avatarCircles_, 0, Qt::AlignRight); + QHBoxLayout *markdownLayout = nullptr; + std::tie(markdownLayout, markdownEnabled_) = addSetting(tr("Send messages as markdown")); - auto typingLayout = new QHBoxLayout; - typingLayout->setContentsMargins(0, OptionMargin, 0, OptionMargin); - auto typingLabel = new QLabel(tr("Typing notifications"), this); - typingLabel->setFont(font); - typingNotifications_ = new Toggle(this); - - typingLayout->addWidget(typingLabel); - typingLayout->addWidget(typingNotifications_, 0, Qt::AlignRight); - - auto receiptsLayout = new QHBoxLayout; - receiptsLayout->setContentsMargins(0, OptionMargin, 0, OptionMargin); - auto receiptsLabel = new QLabel(tr("Read receipts"), this); - receiptsLabel->setFont(font); - readReceipts_ = new Toggle(this); - - receiptsLayout->addWidget(receiptsLabel); - receiptsLayout->addWidget(readReceipts_, 0, Qt::AlignRight); - - auto desktopLayout = new QHBoxLayout; - desktopLayout->setContentsMargins(0, OptionMargin, 0, OptionMargin); - auto desktopLabel = new QLabel(tr("Desktop notifications"), this); - desktopLabel->setFont(font); - desktopNotifications_ = new Toggle(this); - - desktopLayout->addWidget(desktopLabel); - desktopLayout->addWidget(desktopNotifications_, 0, Qt::AlignRight); + QHBoxLayout *desktopLayout = nullptr; + std::tie(desktopLayout, desktopNotifications_) = addSetting(tr("Desktop notifications")); auto scaleFactorOptionLayout = new QHBoxLayout; scaleFactorOptionLayout->setContentsMargins(0, OptionMargin, 0, OptionMargin); @@ -385,6 +363,7 @@ UserSettingsPage::UserSettingsPage(QSharedPointer settings, QWidge mainLayout_->addWidget(new HorizontalLine(this)); mainLayout_->addLayout(typingLayout); mainLayout_->addLayout(receiptsLayout); + mainLayout_->addLayout(markdownLayout); mainLayout_->addLayout(desktopLayout); mainLayout_->addWidget(new HorizontalLine(this)); @@ -466,6 +445,10 @@ UserSettingsPage::UserSettingsPage(QSharedPointer settings, QWidge settings_->setAvatarCircles(!isDisabled); }); + connect(markdownEnabled_, &Toggle::toggled, this, [this](bool isDisabled) { + settings_->setMarkdownEnabled(!isDisabled); + }); + connect(typingNotifications_, &Toggle::toggled, this, [this](bool isDisabled) { settings_->setTypingNotifications(!isDisabled); }); @@ -496,8 +479,10 @@ UserSettingsPage::showEvent(QShowEvent *) trayToggle_->setState(!settings_->isTrayEnabled()); startInTrayToggle_->setState(!settings_->isStartInTrayEnabled()); groupViewToggle_->setState(!settings_->isGroupViewEnabled()); + avatarCircles_->setState(!settings_->isAvatarCirclesEnabled()); typingNotifications_->setState(!settings_->isTypingNotificationsEnabled()); readReceipts_->setState(!settings_->isReadReceiptsEnabled()); + markdownEnabled_->setState(!settings_->isMarkdownEnabled()); desktopNotifications_->setState(!settings_->hasDesktopNotifications()); deviceIdValue_->setText(QString::fromStdString(http::client()->device_id())); diff --git a/src/UserSettingsPage.h b/src/UserSettingsPage.h index 28236e83..8658e80e 100644 --- a/src/UserSettingsPage.h +++ b/src/UserSettingsPage.h @@ -68,6 +68,12 @@ public: save(); } + void setMarkdownEnabled(bool state) + { + isMarkdownEnabled_ = state; + save(); + } + void setReadReceipts(bool state) { isReadReceiptsEnabled_ = state; @@ -96,6 +102,8 @@ public: bool isTrayEnabled() const { return isTrayEnabled_; } bool isStartInTrayEnabled() const { return isStartInTrayEnabled_; } bool isGroupViewEnabled() const { return isGroupViewEnabled_; } + bool isAvatarCirclesEnabled() const { return avatarCircles_; } + bool isMarkdownEnabled() const { return isMarkdownEnabled_; } bool isTypingNotificationsEnabled() const { return isTypingNotificationsEnabled_; } bool isReadReceiptsEnabled() const { return isReadReceiptsEnabled_; } bool hasDesktopNotifications() const { return hasDesktopNotifications_; } @@ -116,6 +124,7 @@ private: bool isTrayEnabled_; bool isStartInTrayEnabled_; bool isGroupViewEnabled_; + bool isMarkdownEnabled_; bool isTypingNotificationsEnabled_; bool isReadReceiptsEnabled_; bool hasDesktopNotifications_; @@ -168,6 +177,7 @@ private: Toggle *groupViewToggle_; Toggle *typingNotifications_; Toggle *readReceipts_; + Toggle *markdownEnabled_; Toggle *desktopNotifications_; Toggle *avatarCircles_; QLabel *deviceFingerprintValue_; diff --git a/src/install-debian.txt b/src/install-debian.txt new file mode 100644 index 00000000..68387665 --- /dev/null +++ b/src/install-debian.txt @@ -0,0 +1,24 @@ +sudo apt install cmake +sudo apt install gcc make automake +sudo apt install qt5-default +sudo apt install liblmdb-dev +sudo apt install qttools5-dev-tools +sudo apt install qttools5-dev-tools +sudo apt install qttools5 +sudo apt install qt5-qmltooling-plugins qml-module-qtgstreamer +sudo apt install libqt5webview5-dev +sudo apt install libqt5quickcontrols2-5 +sudo apt install qtquickcontrols2-5-dev +sudo apt install libssl-dev +sudo apt install qml-module-qtgraphicaleffects +sudo apt install qml-module-qtquick-controls2 +sudo apt install qml-module-qtquick-layouts +sudo apt install qml-module-qtmultimedia +sudo apt install qml-module-qt-labs-settings qml-module-qt-labs-sharedimage +sudo apt install qttools5-dev +sudo apt install libqt5svg5-dev +sudo apt install qt5multimedia +sudo apt install libqt5multimedia5 +sudo apt install libqt5multimedia5-plugins libqt5multimediagsttools5 libqt5multimediaquick5 libqt5multimediawidgets5 +sudo apt install qt5ct +sudo apt install qtmultimedia5-dev diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index b3fd65a1..578d075f 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -18,8 +18,7 @@ Q_DECLARE_METATYPE(mtx::events::collections::TimelineEvents) void TimelineViewManager::updateColorPalette() { - UserSettings settings; - if (settings.theme() == "light") { + if (settings->theme() == "light") { QPalette lightActive(/*windowText*/ QColor("#333"), /*button*/ QColor("#333"), /*light*/ QColor(), @@ -31,7 +30,7 @@ TimelineViewManager::updateColorPalette() /*window*/ QColor("white")); view->rootContext()->setContextProperty("currentActivePalette", lightActive); view->rootContext()->setContextProperty("currentInactivePalette", lightActive); - } else if (settings.theme() == "dark") { + } else if (settings->theme() == "dark") { QPalette darkActive(/*windowText*/ QColor("#caccd1"), /*button*/ QColor("#caccd1"), /*light*/ QColor(), @@ -50,9 +49,10 @@ TimelineViewManager::updateColorPalette() } } -TimelineViewManager::TimelineViewManager(QWidget *parent) +TimelineViewManager::TimelineViewManager(QSharedPointer userSettings, QWidget *parent) : imgProvider(new MxcImageProvider()) , colorImgProvider(new ColorImageProvider()) + , settings(userSettings) { qmlRegisterUncreatableMetaObject(qml_mtx_events::staticMetaObject, "im.nheko", @@ -207,6 +207,11 @@ TimelineViewManager::queueTextMessage(const QString &msg, const std::optionalrelated_event; } + if (!settings->isMarkdownEnabled()) { + text.format = ""; + text.formatted_body = ""; + } + if (timeline_) timeline_->sendMessage(text); } @@ -219,8 +224,10 @@ TimelineViewManager::queueEmoteMessage(const QString &msg) mtx::events::msg::Emote emote; emote.body = msg.trimmed().toStdString(); - if (html != msg.trimmed().toHtmlEscaped()) + if (html != msg.trimmed().toHtmlEscaped() && settings->isMarkdownEnabled()) { emote.formatted_body = html.toStdString(); + emote.format = "org.matrix.custom.html"; + } if (timeline_) timeline_->sendMessage(emote); diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h index 63075649..426e066f 100644 --- a/src/timeline/TimelineViewManager.h +++ b/src/timeline/TimelineViewManager.h @@ -15,6 +15,7 @@ class MxcImageProvider; class ColorImageProvider; +class UserSettings; class TimelineViewManager : public QObject { @@ -26,7 +27,7 @@ class TimelineViewManager : public QObject bool isInitialSync MEMBER isInitialSync_ READ isInitialSync NOTIFY initialSyncChanged) public: - TimelineViewManager(QWidget *parent = 0); + TimelineViewManager(QSharedPointer userSettings, QWidget *parent = 0); QWidget *getWidget() const { return container; } void sync(const mtx::responses::Rooms &rooms); @@ -97,4 +98,6 @@ private: QHash> models; TimelineModel *timeline_ = nullptr; bool isInitialSync_ = true; + + QSharedPointer settings; }; From 9c368fa7f448715c2ce04c61097e0cb18091774b Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Mon, 27 Jan 2020 17:05:40 +0100 Subject: [PATCH 2/6] Fix reply rendering without markdown in riot --- src/timeline/TimelineModel.cpp | 23 ++++++++++++++++++++--- src/timeline/TimelineViewManager.cpp | 25 ++++++++++++++++--------- 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index fb8c0095..03b7d6a7 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -281,9 +281,26 @@ TimelineModel::data(const QString &id, int role) const case FormattedBody: { const static QRegularExpression replyFallback( ".*", QRegularExpression::DotMatchesEverythingOption); - return QVariant( - utils::replaceEmoji(utils::linkifyMessage(utils::escapeBlacklistedHtml( - formattedBodyWithFallback(event).remove(replyFallback))))); + + bool isReply = !in_reply_to_event(event).empty(); + + auto formattedBody_ = QString::fromStdString(formatted_body(event)); + if (formattedBody_.isEmpty()) { + auto body_ = QString::fromStdString(body(event)); + + if (isReply) { + while (body_.startsWith("> ")) + body_ = body_.right(body_.size() - body_.indexOf('\n') - 1); + if (body_.startsWith('\n')) + body_ = body_.right(body_.size() - 1); + } + formattedBody_ = body_.toHtmlEscaped(); + } else { + if (isReply) + formattedBody_ = formattedBody_.remove(replyFallback); + } + return QVariant(utils::replaceEmoji( + utils::linkifyMessage(utils::escapeBlacklistedHtml(formattedBody_)))); } case Url: return QVariant(QString::fromStdString(url(event))); diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index 578d075f..9008d9d2 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -186,8 +186,11 @@ TimelineViewManager::queueTextMessage(const QString &msg, const std::optionalisMarkdownEnabled()) { + text.format = "org.matrix.custom.html"; + text.formatted_body = utils::markdownToHtml(msg).toStdString(); + } if (related) { QString body; @@ -202,14 +205,18 @@ TimelineViewManager::queueTextMessage(const QString &msg, const std::optionalrelated_event; - } - if (!settings->isMarkdownEnabled()) { - text.format = ""; - text.formatted_body = ""; + // NOTE(Nico): rich replies always need a formatted_body! + text.format = "org.matrix.custom.html"; + if (settings->isMarkdownEnabled()) + text.formatted_body = + utils::getFormattedQuoteBody(*related, utils::markdownToHtml(msg)) + .toStdString(); + else + text.formatted_body = + utils::getFormattedQuoteBody(*related, msg.toHtmlEscaped()).toStdString(); + + text.relates_to.in_reply_to.event_id = related->related_event; } if (timeline_) From e81a4e8f9abb7f2dbdc419929bcaf6a3d4065bea Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Mon, 27 Jan 2020 17:25:09 +0100 Subject: [PATCH 3/6] Don't send useless formatted_bodies --- src/Utils.cpp | 4 ++++ src/timeline/TimelineViewManager.cpp | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Utils.cpp b/src/Utils.cpp index 5a67ef62..76ffed31 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -397,6 +397,10 @@ utils::markdownToHtml(const QString &text) auto result = linkifyMessage(escapeBlacklistedHtml(QString::fromStdString(html))).trimmed(); + if (result.count("

") == 1 && result.startsWith("

") && result.endsWith("

")) { + result = result.mid(3, result.size() - 3 - 4); + } + return result; } diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index 9008d9d2..a1f23cf5 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -188,8 +188,13 @@ TimelineViewManager::queueTextMessage(const QString &msg, const std::optionalisMarkdownEnabled()) { - text.format = "org.matrix.custom.html"; text.formatted_body = utils::markdownToHtml(msg).toStdString(); + + // Don't send formatted_body, when we don't need to + if (text.formatted_body == text.body) + text.formatted_body = ""; + else + text.format = "org.matrix.custom.html"; } if (related) { From 792c39d304d567eaea039009eeb2f655848abbc3 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Mon, 27 Jan 2020 18:27:31 +0100 Subject: [PATCH 4/6] fix typo in build command in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7c06daeb..49ec50ae 100644 --- a/README.md +++ b/README.md @@ -209,7 +209,7 @@ cmake --build build To use bundled dependencies you can use hunter, i.e.: ```bash -cmake -H. -Bbuild -DHUNTER_ENABLED=ON -DCMAKE_BUILD_TYPE=OFF -DUSE_BUNDLED_OPENSSL=OFF +cmake -H. -Bbuild -DHUNTER_ENABLED=ON -DBUILD_SHARED_LIBS=OFF -DUSE_BUNDLED_OPENSSL=OFF cmake --build build --config Release ``` From 760d4ddef9b5af92272a4422f8bc5ed4b3f005ed Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Mon, 27 Jan 2020 18:36:34 +0100 Subject: [PATCH 5/6] Fix newlines in plain text messages again --- src/timeline/TimelineModel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index 03b7d6a7..f34cb405 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -294,7 +294,7 @@ TimelineModel::data(const QString &id, int role) const if (body_.startsWith('\n')) body_ = body_.right(body_.size() - 1); } - formattedBody_ = body_.toHtmlEscaped(); + formattedBody_ = body_.toHtmlEscaped().replace('\n', "
"); } else { if (isReply) formattedBody_ = formattedBody_.remove(replyFallback); From b0ff1baa1d1c38523b5479a5191a5559f4c21bf6 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Wed, 29 Jan 2020 00:30:53 +0100 Subject: [PATCH 6/6] Add command for invite,kick,ban and unban --- CMakeLists.txt | 2 +- resources/langs/nheko_de.ts | 101 ++++++++++++++++++++++++++++----- resources/langs/nheko_el.ts | 101 ++++++++++++++++++++++++++++----- resources/langs/nheko_en.ts | 101 ++++++++++++++++++++++++++++----- resources/langs/nheko_fi.ts | 101 ++++++++++++++++++++++++++++----- resources/langs/nheko_fr.ts | 101 ++++++++++++++++++++++++++++----- resources/langs/nheko_nl.ts | 101 ++++++++++++++++++++++++++++----- resources/langs/nheko_pl.ts | 101 ++++++++++++++++++++++++++++----- resources/langs/nheko_ru.ts | 101 ++++++++++++++++++++++++++++----- resources/langs/nheko_zh_CN.ts | 101 ++++++++++++++++++++++++++++----- src/ChatPage.cpp | 99 +++++++++++++++++++++++++++++--- src/TextInputWidget.cpp | 8 +++ src/TextInputWidget.h | 4 ++ 13 files changed, 877 insertions(+), 145 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d5faa4a9..c2496f2f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -333,7 +333,7 @@ if(USE_BUNDLED_MTXCLIENT) FetchContent_Declare( MatrixClient GIT_REPOSITORY https://github.com/Nheko-Reborn/mtxclient.git - GIT_TAG 1fd59de2a37e6b547db8e5b52114f3f10171ef2f + GIT_TAG 03b5008a05f895e91e3968de7b68db50f6c41b2a ) FetchContent_MakeAvailable(MatrixClient) else() diff --git a/resources/langs/nheko_de.ts b/resources/langs/nheko_de.ts index e4271a6e..32526797 100644 --- a/resources/langs/nheko_de.ts +++ b/resources/langs/nheko_de.ts @@ -4,7 +4,53 @@ ChatPage - + + Failed to invite user: %1 + + + + + + Invited user: %1 + + + + + Failed to invite %1 to %2: %3 + + + + + Failed to kick %1 to %2: %3 + + + + + Kicked user: %1 + + + + + Failed to ban %1 in %2: %3 + + + + + Banned user: %1 + + + + + Failed to unban %1 in %2: %3 + + + + + Unbanned user: %1 + + + + Failed to upload media. Please try again. Medienupload fehlgeschlagen. Bitte versuche es erneut. @@ -25,17 +71,37 @@ - + Please try to login again: %1 Bitte melde dich erneut an: %1 - + + Failed to join room: %1 + + + + + You joined the room + + + + + Failed to remove invite: %1 + + + + Room creation failed: %1 Raum konnte nicht erstellt werden: %1 - + + Room %1 created + + + + Failed to leave room: %1 Konnte den Raum nicht verlassen: %1 @@ -385,7 +451,7 @@ Emoji - + Select a file Datei auswählen @@ -403,7 +469,7 @@ TimelineModel - + -- Encrypted Event (No keys found for decryption) -- Placeholder, when the message was not decrypted yet or can't be decrypted -- verschlüsselter Event (keine Schlüssel zur Entschlüsselung gefunden) -- @@ -646,42 +712,47 @@ UserSettingsPage - + Minimize to tray Ins Benachrichtigungsfeld minimieren - + Start in tray Im Benachrichtigungsfeld starten - + Group's sidebar Gruppen-Seitenleiste - + Circular Avatars Runde Profilbilder - + Typing notifications Schreibbenachrichtigungen - + Read receipts Lesebestätigungen - + + Send messages as markdown + + + + Desktop notifications Desktopbenachrichtigungen - + Scale factor Skalierungsfaktor @@ -741,7 +812,7 @@ ALLGEMEINES - + Open Sessions File Öffne Sessions Datei diff --git a/resources/langs/nheko_el.ts b/resources/langs/nheko_el.ts index 982a14ac..4344c568 100644 --- a/resources/langs/nheko_el.ts +++ b/resources/langs/nheko_el.ts @@ -4,7 +4,53 @@ ChatPage - + + Failed to invite user: %1 + + + + + + Invited user: %1 + + + + + Failed to invite %1 to %2: %3 + + + + + Failed to kick %1 to %2: %3 + + + + + Kicked user: %1 + + + + + Failed to ban %1 in %2: %3 + + + + + Banned user: %1 + + + + + Failed to unban %1 in %2: %3 + + + + + Unbanned user: %1 + + + + Failed to upload media. Please try again. @@ -25,17 +71,37 @@ - + Please try to login again: %1 - + + Failed to join room: %1 + + + + + You joined the room + + + + + Failed to remove invite: %1 + + + + Room creation failed: %1 - + + Room %1 created + + + + Failed to leave room: %1 @@ -385,7 +451,7 @@ - + Select a file Διάλεξε ένα αρχείο @@ -403,7 +469,7 @@ TimelineModel - + -- Encrypted Event (No keys found for decryption) -- Placeholder, when the message was not decrypted yet or can't be decrypted @@ -646,42 +712,47 @@ UserSettingsPage - + Minimize to tray Ελαχιστοποίηση - + Start in tray - + Group's sidebar - + Circular Avatars - + Typing notifications - + Read receipts - + + Send messages as markdown + + + + Desktop notifications - + Scale factor @@ -741,7 +812,7 @@ ΓΕΝΙΚΑ - + Open Sessions File diff --git a/resources/langs/nheko_en.ts b/resources/langs/nheko_en.ts index 60b1fe3d..fee87ffb 100644 --- a/resources/langs/nheko_en.ts +++ b/resources/langs/nheko_en.ts @@ -4,7 +4,53 @@ ChatPage - + + Failed to invite user: %1 + + + + + + Invited user: %1 + + + + + Failed to invite %1 to %2: %3 + + + + + Failed to kick %1 to %2: %3 + + + + + Kicked user: %1 + + + + + Failed to ban %1 in %2: %3 + + + + + Banned user: %1 + + + + + Failed to unban %1 in %2: %3 + + + + + Unbanned user: %1 + + + + Failed to upload media. Please try again. @@ -25,17 +71,37 @@ - + Please try to login again: %1 Please try to login again: %1 - + + Failed to join room: %1 + + + + + You joined the room + + + + + Failed to remove invite: %1 + + + + Room creation failed: %1 Room creation failed: %1 - + + Room %1 created + + + + Failed to leave room: %1 Failed to leave room: %1 @@ -385,7 +451,7 @@ Emoji - + Select a file Select a file @@ -403,7 +469,7 @@ TimelineModel - + -- Encrypted Event (No keys found for decryption) -- Placeholder, when the message was not decrypted yet or can't be decrypted -- Encrypted Event (No keys found for decryption) -- @@ -646,42 +712,47 @@ UserSettingsPage - + Minimize to tray Minimize to tray - + Start in tray Start in tray - + Group's sidebar Group's sidebar - + Circular Avatars - + Typing notifications Typing notifications - + Read receipts Read receipts - + + Send messages as markdown + + + + Desktop notifications Desktop notifications - + Scale factor Scale factor @@ -741,7 +812,7 @@ GENERAL - + Open Sessions File Open Sessions File diff --git a/resources/langs/nheko_fi.ts b/resources/langs/nheko_fi.ts index b4b184c9..f6e2756c 100644 --- a/resources/langs/nheko_fi.ts +++ b/resources/langs/nheko_fi.ts @@ -4,7 +4,53 @@ ChatPage - + + Failed to invite user: %1 + + + + + + Invited user: %1 + + + + + Failed to invite %1 to %2: %3 + + + + + Failed to kick %1 to %2: %3 + + + + + Kicked user: %1 + + + + + Failed to ban %1 in %2: %3 + + + + + Banned user: %1 + + + + + Failed to unban %1 in %2: %3 + + + + + Unbanned user: %1 + + + + Failed to upload media. Please try again. @@ -25,17 +71,37 @@ - + Please try to login again: %1 Ole hyvä ja yritä kirjautua sisään uudelleen: %1 - + + Failed to join room: %1 + + + + + You joined the room + + + + + Failed to remove invite: %1 + + + + Room creation failed: %1 Huoneen luominen epäonnistui: %1 - + + Room %1 created + + + + Failed to leave room: %1 Huoneesta poistuminen epäonnistui: %1 @@ -385,7 +451,7 @@ Emoji - + Select a file Valitse tiedosto @@ -403,7 +469,7 @@ TimelineModel - + -- Encrypted Event (No keys found for decryption) -- Placeholder, when the message was not decrypted yet or can't be decrypted -- Salattu viesti (salauksen purkuavaimia ei löydetty) -- @@ -646,42 +712,47 @@ UserSettingsPage - + Minimize to tray Pienennä ilmoitusalueelle - + Start in tray Aloita ilmoitusalueella - + Group's sidebar Ryhmäsivupalkki - + Circular Avatars - + Typing notifications Kirjoitusilmoitukset - + Read receipts Lukukuittaukset - + + Send messages as markdown + + + + Desktop notifications Työpöytäilmoitukset - + Scale factor Mittakerroin @@ -741,7 +812,7 @@ YLEISET ASETUKSET - + Open Sessions File Avaa Istuntoavaintiedosto diff --git a/resources/langs/nheko_fr.ts b/resources/langs/nheko_fr.ts index c713dcb1..89dd8cdd 100644 --- a/resources/langs/nheko_fr.ts +++ b/resources/langs/nheko_fr.ts @@ -4,7 +4,53 @@ ChatPage - + + Failed to invite user: %1 + + + + + + Invited user: %1 + + + + + Failed to invite %1 to %2: %3 + + + + + Failed to kick %1 to %2: %3 + + + + + Kicked user: %1 + + + + + Failed to ban %1 in %2: %3 + + + + + Banned user: %1 + + + + + Failed to unban %1 in %2: %3 + + + + + Unbanned user: %1 + + + + Failed to upload media. Please try again. @@ -25,17 +71,37 @@ - + Please try to login again: %1 - + + Failed to join room: %1 + + + + + You joined the room + + + + + Failed to remove invite: %1 + + + + Room creation failed: %1 - + + Room %1 created + + + + Failed to leave room: %1 @@ -386,7 +452,7 @@ - + Select a file Sélectionnez un fichier @@ -404,7 +470,7 @@ TimelineModel - + -- Encrypted Event (No keys found for decryption) -- Placeholder, when the message was not decrypted yet or can't be decrypted @@ -647,42 +713,47 @@ UserSettingsPage - + Minimize to tray Réduire à la barre des tâches - + Start in tray Démarrer dans la barre des tâches - + Group's sidebar Barre latérale des groupes - + Circular Avatars - + Typing notifications Notifications d'écriture - + Read receipts Accusés de lecture - + + Send messages as markdown + + + + Desktop notifications - + Scale factor @@ -742,7 +813,7 @@ GÉNÉRAL - + Open Sessions File diff --git a/resources/langs/nheko_nl.ts b/resources/langs/nheko_nl.ts index 82b0f881..2aa5de74 100644 --- a/resources/langs/nheko_nl.ts +++ b/resources/langs/nheko_nl.ts @@ -4,7 +4,53 @@ ChatPage - + + Failed to invite user: %1 + + + + + + Invited user: %1 + + + + + Failed to invite %1 to %2: %3 + + + + + Failed to kick %1 to %2: %3 + + + + + Kicked user: %1 + + + + + Failed to ban %1 in %2: %3 + + + + + Banned user: %1 + + + + + Failed to unban %1 in %2: %3 + + + + + Unbanned user: %1 + + + + Failed to upload media. Please try again. @@ -25,17 +71,37 @@ - + Please try to login again: %1 - + + Failed to join room: %1 + + + + + You joined the room + + + + + Failed to remove invite: %1 + + + + Room creation failed: %1 - + + Room %1 created + + + + Failed to leave room: %1 @@ -385,7 +451,7 @@ - + Select a file Kies een bestand @@ -403,7 +469,7 @@ TimelineModel - + -- Encrypted Event (No keys found for decryption) -- Placeholder, when the message was not decrypted yet or can't be decrypted @@ -646,42 +712,47 @@ UserSettingsPage - + Minimize to tray Minimaliseren naar systeemvak - + Start in tray Geminimaliseerd opstarten - + Group's sidebar Zijbalk van groep - + Circular Avatars - + Typing notifications Meldingen bij typen van berichten - + Read receipts Leesbevestigingen - + + Send messages as markdown + + + + Desktop notifications - + Scale factor @@ -741,7 +812,7 @@ ALGEMEEN - + Open Sessions File diff --git a/resources/langs/nheko_pl.ts b/resources/langs/nheko_pl.ts index 6fb2133b..88dfe2b9 100644 --- a/resources/langs/nheko_pl.ts +++ b/resources/langs/nheko_pl.ts @@ -4,7 +4,53 @@ ChatPage - + + Failed to invite user: %1 + + + + + + Invited user: %1 + + + + + Failed to invite %1 to %2: %3 + + + + + Failed to kick %1 to %2: %3 + + + + + Kicked user: %1 + + + + + Failed to ban %1 in %2: %3 + + + + + Banned user: %1 + + + + + Failed to unban %1 in %2: %3 + + + + + Unbanned user: %1 + + + + Failed to upload media. Please try again. @@ -25,17 +71,37 @@ - + Please try to login again: %1 Spróbuj zalogować się ponownie: %1 - + + Failed to join room: %1 + + + + + You joined the room + + + + + Failed to remove invite: %1 + + + + Room creation failed: %1 Tworzenie pokoju nie powiodło się: %1 - + + Room %1 created + + + + Failed to leave room: %1 Nie udało się opuścić pokoju: %1 @@ -385,7 +451,7 @@ Emoji - + Select a file Wybierz plik @@ -403,7 +469,7 @@ TimelineModel - + -- Encrypted Event (No keys found for decryption) -- Placeholder, when the message was not decrypted yet or can't be decrypted @@ -647,42 +713,47 @@ UserSettingsPage - + Minimize to tray Zminimalizuj do paska zadań - + Start in tray Rozpocznij na pasku zadań - + Group's sidebar Pasek boczny grupy - + Circular Avatars - + Typing notifications Powiadomienia o pisaniu - + Read receipts Potwierdzenia przeczytania - + + Send messages as markdown + + + + Desktop notifications Powiadomienia na pulpicie - + Scale factor @@ -742,7 +813,7 @@ OGÓLNE - + Open Sessions File diff --git a/resources/langs/nheko_ru.ts b/resources/langs/nheko_ru.ts index 1b84074f..07e169f7 100644 --- a/resources/langs/nheko_ru.ts +++ b/resources/langs/nheko_ru.ts @@ -4,7 +4,53 @@ ChatPage - + + Failed to invite user: %1 + + + + + + Invited user: %1 + + + + + Failed to invite %1 to %2: %3 + + + + + Failed to kick %1 to %2: %3 + + + + + Kicked user: %1 + + + + + Failed to ban %1 in %2: %3 + + + + + Banned user: %1 + + + + + Failed to unban %1 in %2: %3 + + + + + Unbanned user: %1 + + + + Failed to upload media. Please try again. @@ -25,17 +71,37 @@ - + Please try to login again: %1 Повторите попытку входа: %1 - + + Failed to join room: %1 + + + + + You joined the room + + + + + Failed to remove invite: %1 + + + + Room creation failed: %1 Не удалось создать комнату: %1 - + + Room %1 created + + + + Failed to leave room: %1 Не удалось покинуть комнату: %1 @@ -385,7 +451,7 @@ - + Select a file Выберите файл @@ -403,7 +469,7 @@ TimelineModel - + -- Encrypted Event (No keys found for decryption) -- Placeholder, when the message was not decrypted yet or can't be decrypted @@ -647,42 +713,47 @@ UserSettingsPage - + Minimize to tray Сворачивать в системную панель - + Start in tray Запускать в системной панели - + Group's sidebar Боковая панель групп - + Circular Avatars - + Typing notifications Сообщать о наборе сообщения - + Read receipts Подтверждать прочтение - + + Send messages as markdown + + + + Desktop notifications Уведомления на рабочем столе - + Scale factor Масштаб @@ -742,7 +813,7 @@ ГЛАВНОЕ - + Open Sessions File Открыть файл сеансов diff --git a/resources/langs/nheko_zh_CN.ts b/resources/langs/nheko_zh_CN.ts index f8b19434..c7e42fba 100644 --- a/resources/langs/nheko_zh_CN.ts +++ b/resources/langs/nheko_zh_CN.ts @@ -4,7 +4,53 @@ ChatPage - + + Failed to invite user: %1 + + + + + + Invited user: %1 + + + + + Failed to invite %1 to %2: %3 + + + + + Failed to kick %1 to %2: %3 + + + + + Kicked user: %1 + + + + + Failed to ban %1 in %2: %3 + + + + + Banned user: %1 + + + + + Failed to unban %1 in %2: %3 + + + + + Unbanned user: %1 + + + + Failed to upload media. Please try again. @@ -25,17 +71,37 @@ - + Please try to login again: %1 请尝试再次登录:%1 - + + Failed to join room: %1 + + + + + You joined the room + + + + + Failed to remove invite: %1 + + + + Room creation failed: %1 创建聊天室失败:%1 - + + Room %1 created + + + + Failed to leave room: %1 离开聊天室失败:%1 @@ -385,7 +451,7 @@ - + Select a file 选择一个文件 @@ -403,7 +469,7 @@ TimelineModel - + -- Encrypted Event (No keys found for decryption) -- Placeholder, when the message was not decrypted yet or can't be decrypted @@ -645,42 +711,47 @@ UserSettingsPage - + Minimize to tray 最小化至托盘 - + Start in tray 在托盘启动 - + Group's sidebar 群组侧边栏 - + Circular Avatars - + Typing notifications 打字通知 - + Read receipts 阅读回执 - + + Send messages as markdown + + + + Desktop notifications 桌面通知 - + Scale factor @@ -740,7 +811,7 @@ 通用 - + Open Sessions File 打开会话文件 diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp index c7739281..a337baac 100644 --- a/src/ChatPage.cpp +++ b/src/ChatPage.cpp @@ -208,12 +208,11 @@ ChatPage::ChatPage(QSharedPointer userSettings, QWidget *parent) mtx::http::RequestErr err) { if (err) { emit showNotification( - QString("Failed to invite user: %1").arg(user)); + tr("Failed to invite user: %1").arg(user)); return; } - emit showNotification( - QString("Invited user: %1").arg(user)); + emit showNotification(tr("Invited user: %1").arg(user)); }); }); } @@ -280,6 +279,89 @@ ChatPage::ChatPage(QSharedPointer userSettings, QWidget *parent) connect(text_input_, &TextInputWidget::sendJoinRoomRequest, this, &ChatPage::joinRoom); + // invites and bans via quick command + connect(text_input_, + &TextInputWidget::sendInviteRoomRequest, + this, + [this](QString userid, QString reason) { + http::client()->invite_user( + current_room_.toStdString(), + userid.toStdString(), + [this, userid, room = current_room_](const mtx::responses::Empty &, + mtx::http::RequestErr err) { + if (err) { + emit showNotification(tr("Failed to invite %1 to %2: %3") + .arg(userid) + .arg(room) + .arg(QString::fromStdString( + err->matrix_error.error))); + } else + emit showNotification(tr("Invited user: %1").arg(userid)); + }, + reason.trimmed().toStdString()); + }); + connect(text_input_, + &TextInputWidget::sendKickRoomRequest, + this, + [this](QString userid, QString reason) { + http::client()->kick_user( + current_room_.toStdString(), + userid.toStdString(), + [this, userid, room = current_room_](const mtx::responses::Empty &, + mtx::http::RequestErr err) { + if (err) { + emit showNotification(tr("Failed to kick %1 to %2: %3") + .arg(userid) + .arg(room) + .arg(QString::fromStdString( + err->matrix_error.error))); + } else + emit showNotification(tr("Kicked user: %1").arg(userid)); + }, + reason.trimmed().toStdString()); + }); + connect(text_input_, + &TextInputWidget::sendBanRoomRequest, + this, + [this](QString userid, QString reason) { + http::client()->ban_user( + current_room_.toStdString(), + userid.toStdString(), + [this, userid, room = current_room_](const mtx::responses::Empty &, + mtx::http::RequestErr err) { + if (err) { + emit showNotification(tr("Failed to ban %1 in %2: %3") + .arg(userid) + .arg(room) + .arg(QString::fromStdString( + err->matrix_error.error))); + } else + emit showNotification(tr("Banned user: %1").arg(userid)); + }, + reason.trimmed().toStdString()); + }); + connect( + text_input_, + &TextInputWidget::sendUnbanRoomRequest, + this, + [this](QString userid, QString reason) { + http::client()->unban_user( + current_room_.toStdString(), + userid.toStdString(), + [this, userid, room = current_room_](const mtx::responses::Empty &, + mtx::http::RequestErr err) { + if (err) { + emit showNotification( + tr("Failed to unban %1 in %2: %3") + .arg(userid) + .arg(room) + .arg(QString::fromStdString(err->matrix_error.error))); + } else + emit showNotification(tr("Unbanned user: %1").arg(userid)); + }, + reason.trimmed().toStdString()); + }); + connect( text_input_, &TextInputWidget::uploadMedia, @@ -998,19 +1080,18 @@ ChatPage::joinRoom(const QString &room) room_id, [this, room_id](const nlohmann::json &, mtx::http::RequestErr err) { if (err) { emit showNotification( - QString("Failed to join room: %1") + tr("Failed to join room: %1") .arg(QString::fromStdString(err->matrix_error.error))); return; } - emit showNotification("You joined the room"); + emit tr("You joined the room"); // We remove any invites with the same room_id. try { cache::removeInvite(room_id); } catch (const lmdb::error &e) { - emit showNotification( - QString("Failed to remove invite: %1").arg(e.what())); + emit showNotification(tr("Failed to remove invite: %1").arg(e.what())); } }); } @@ -1033,8 +1114,8 @@ ChatPage::createRoom(const mtx::requests::CreateRoom &req) return; } - emit showNotification(QString("Room %1 created") - .arg(QString::fromStdString(res.room_id.to_string()))); + emit showNotification( + tr("Room %1 created").arg(QString::fromStdString(res.room_id.to_string()))); }); } diff --git a/src/TextInputWidget.cpp b/src/TextInputWidget.cpp index b6b51980..52686c0f 100644 --- a/src/TextInputWidget.cpp +++ b/src/TextInputWidget.cpp @@ -605,6 +605,14 @@ TextInputWidget::command(QString command, QString args) sendEmoteMessage(args, input_->related); } else if (command == "join") { sendJoinRoomRequest(args); + } else if (command == "invite") { + sendInviteRoomRequest(args.section(' ', 0, 0), args.section(' ', 1, -1)); + } else if (command == "kick") { + sendKickRoomRequest(args.section(' ', 0, 0), args.section(' ', 1, -1)); + } else if (command == "ban") { + sendBanRoomRequest(args.section(' ', 0, 0), args.section(' ', 1, -1)); + } else if (command == "unban") { + sendUnbanRoomRequest(args.section(' ', 0, 0), args.section(' ', 1, -1)); } else if (command == "shrug") { sendTextMessage("¯\\_(ツ)_/¯", input_->related); } else if (command == "fliptable") { diff --git a/src/TextInputWidget.h b/src/TextInputWidget.h index 6641d97c..4bdb2509 100644 --- a/src/TextInputWidget.h +++ b/src/TextInputWidget.h @@ -183,6 +183,10 @@ signals: const std::optional &related); void sendJoinRoomRequest(const QString &room); + void sendInviteRoomRequest(const QString &userid, const QString &reason); + void sendKickRoomRequest(const QString &userid, const QString &reason); + void sendBanRoomRequest(const QString &userid, const QString &reason); + void sendUnbanRoomRequest(const QString &userid, const QString &reason); void startedTyping(); void stoppedTyping();