From 050f4809556e97be457526c1dfe60a15fe4d819b Mon Sep 17 00:00:00 2001 From: Tobias Fella Date: Tue, 30 May 2023 18:37:15 +0200 Subject: [PATCH] Fix emojis in a different way Apparently the existing fix is difficult to ship for distros. This is an alternative way, that manually goes over every text and sets the font family appropriately. Unfortunately, we need a textDocument for that, which labels don't have, meaning we have to use TextEdits instead... --- CMakeLists.txt | 11 +- cmake/Flatpak.cmake | 14 -- cmake/Flatpak/99-noto-mono-color-emoji.conf | 23 -- src/CMakeLists.txt | 3 +- src/chatdocumenthandler.cpp | 3 + src/emojifixer.cpp | 72 ++++++ src/emojifixer.h | 20 ++ src/main.cpp | 8 +- src/qml/Component/Emoji/EmojiPicker.qml | 2 +- src/qml/Component/NeoChatTabButton.qml | 92 ++++++++ .../Component/Timeline/ReactionDelegate.qml | 18 +- src/qml/Component/Timeline/RichLabel.qml | 9 +- src/qml/Page/RoomList/RoomDelegate.qml | 218 ++++++++++++------ src/qml/Panel/GroupChatDrawerHeader.qml | 1 + src/res.qrc | 1 + 15 files changed, 367 insertions(+), 128 deletions(-) delete mode 100644 cmake/Flatpak.cmake delete mode 100644 cmake/Flatpak/99-noto-mono-color-emoji.conf create mode 100644 src/emojifixer.cpp create mode 100644 src/emojifixer.h create mode 100644 src/qml/Component/NeoChatTabButton.qml diff --git a/CMakeLists.txt b/CMakeLists.txt index 88f8222a8..355954da5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,10 +44,6 @@ if (NOT ANDROID) include(KDEClangFormat) endif() -if(NEOCHAT_FLATPAK) - include(cmake/Flatpak.cmake) -endif() - ecm_setup_version(${PROJECT_VERSION} VARIABLE_PREFIX NEOCHAT VERSION_HEADER ${CMAKE_CURRENT_BINARY_DIR}/neochat-version.h @@ -75,6 +71,13 @@ set_package_properties(Qt${QT_MAJOR_VERSION}Keychain PROPERTIES PURPOSE "Secure storage of account secrets" ) + +find_package(ICU 61.0 COMPONENTS uc) +set_package_properties(ICU PROPERTIES + TYPE REQUIRED + PURPOSE "Unicode library" +) + if(ANDROID) find_package(OpenSSL) set_package_properties(OpenSSL PROPERTIES diff --git a/cmake/Flatpak.cmake b/cmake/Flatpak.cmake deleted file mode 100644 index fd35e49be..000000000 --- a/cmake/Flatpak.cmake +++ /dev/null @@ -1,14 +0,0 @@ -# SPDX-FileCopyrightText: 2020 Carl Schwan -# SPDX-License-Identifier: BSD-2-Clause - -include(GNUInstallDirs) - -# Include FontConfig config which uses the Emoji One font from the -# KDE Flatpak SDK. -install( - FILES - ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Flatpak/99-noto-mono-color-emoji.conf - DESTINATION - ${CMAKE_INSTALL_SYSCONFDIR}/fonts/local.conf -) - diff --git a/cmake/Flatpak/99-noto-mono-color-emoji.conf b/cmake/Flatpak/99-noto-mono-color-emoji.conf deleted file mode 100644 index 36cf12046..000000000 --- a/cmake/Flatpak/99-noto-mono-color-emoji.conf +++ /dev/null @@ -1,23 +0,0 @@ - - - - - serif - - Noto Color Emoji - - - - sans-serif - - Noto Color Emoji - - - - monospace - - Noto Color Emoji - - - - diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 264937af6..9d04e5c9b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -55,6 +55,7 @@ add_library(neochat STATIC events/joinrulesevent.cpp events/stickerevent.cpp models/reactionmodel.cpp + emojifixer.cpp ) ecm_qt_declare_logging_category(neochat @@ -109,7 +110,7 @@ else() endif() target_include_directories(neochat PRIVATE ${CMAKE_BINARY_DIR}) -target_link_libraries(neochat PUBLIC Qt::Core Qt::Quick Qt::Qml Qt::Gui Qt::Multimedia Qt::Network Qt::QuickControls2 KF${QT_MAJOR_VERSION}::I18n KF${QT_MAJOR_VERSION}::Kirigami2 KF${QT_MAJOR_VERSION}::Notifications KF${QT_MAJOR_VERSION}::ConfigCore KF${QT_MAJOR_VERSION}::ConfigGui KF${QT_MAJOR_VERSION}::CoreAddons KF${QT_MAJOR_VERSION}::SonnetCore KF${QT_MAJOR_VERSION}::ItemModels Quotient${QUOTIENT_SUFFIX} cmark::cmark ${QTKEYCHAIN_LIBRARIES} QCoro::Core) +target_link_libraries(neochat PUBLIC Qt::Core Qt::Quick Qt::Qml Qt::Gui Qt::Multimedia Qt::Network Qt::QuickControls2 KF${QT_MAJOR_VERSION}::I18n KF${QT_MAJOR_VERSION}::Kirigami2 KF${QT_MAJOR_VERSION}::Notifications KF${QT_MAJOR_VERSION}::ConfigCore KF${QT_MAJOR_VERSION}::ConfigGui KF${QT_MAJOR_VERSION}::CoreAddons KF${QT_MAJOR_VERSION}::SonnetCore KF${QT_MAJOR_VERSION}::ItemModels Quotient${QUOTIENT_SUFFIX} cmark::cmark ${QTKEYCHAIN_LIBRARIES} QCoro::Core ICU::uc) kconfig_add_kcfg_files(neochat GENERATE_MOC neochatconfig.kcfgc) if(NEOCHAT_FLATPAK) diff --git a/src/chatdocumenthandler.cpp b/src/chatdocumenthandler.cpp index ba799ebf3..648df90d8 100644 --- a/src/chatdocumenthandler.cpp +++ b/src/chatdocumenthandler.cpp @@ -14,6 +14,7 @@ #include #include +#include "emojifixer.h" #include "neochatroom.h" class SyntaxHighlighter : public QSyntaxHighlighter @@ -183,6 +184,8 @@ void ChatDocumentHandler::setDocument(QQuickTextDocument *document) m_document->textDocument()->disconnect(this); } m_document = document; + static EmojiFixer emojiFixer; + emojiFixer.addTextDocument(document); Q_EMIT documentChanged(); } diff --git a/src/emojifixer.cpp b/src/emojifixer.cpp new file mode 100644 index 000000000..831319b77 --- /dev/null +++ b/src/emojifixer.cpp @@ -0,0 +1,72 @@ +// SPDX-FileCopyrightText: Tobias Fella +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "emojifixer.h" + +bool isEmoji(const QString &text) +{ + QTextBoundaryFinder finder(QTextBoundaryFinder::Grapheme, text); + int from = 0; + while (finder.toNextBoundary() != -1) { + auto to = finder.position(); + if (text[from].isSpace()) { + from = to; + continue; + } + + auto first = text.mid(from, to - from).toUcs4()[0]; + if (!u_hasBinaryProperty(first, UCHAR_EMOJI_PRESENTATION)) { + return false; + } + from = to; + } + return true; +} + +void EmojiFixer::addTextDocument(QQuickTextDocument *document) +{ + if (!document) { + return; + } + fix(document->textDocument()); +} + +void EmojiFixer::fix(QTextDocument *document) +{ + disconnect(document, nullptr, this, nullptr); + QTextCursor curs(document); + QTextCharFormat format; + auto font = QGuiApplication::font(); + font.setFamily("emoji"); + format.setFont(font); + + QTextBoundaryFinder finder(QTextBoundaryFinder::Grapheme, document->toRawText()); + + int from = 0; + while (finder.toNextBoundary() != -1) { + auto to = finder.position(); + + auto first = document->toRawText().mid(from, to - from).toUcs4()[0]; + if (u_hasBinaryProperty(first, UCHAR_EMOJI_PRESENTATION)) { + curs.setPosition(from, QTextCursor::MoveAnchor); + curs.setPosition(to, QTextCursor::KeepAnchor); + curs.setCharFormat(format); + } + from = to; + } + connect(document, &QTextDocument::contentsChanged, this, [this, document]() { + fix(document); + }); +} diff --git a/src/emojifixer.h b/src/emojifixer.h new file mode 100644 index 000000000..06d4b4e06 --- /dev/null +++ b/src/emojifixer.h @@ -0,0 +1,20 @@ +// SPDX-FileCopyrightText: Tobias Fella +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +class QQuickTextDocument; +class QTextDocument; + +class EmojiFixer : public QObject +{ + Q_OBJECT + +public: + Q_INVOKABLE void addTextDocument(QQuickTextDocument *doc); + +private: + void fix(QTextDocument *doc); +}; diff --git a/src/main.cpp b/src/main.cpp index 01d9789e9..ea5f45200 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -88,6 +88,7 @@ #ifdef HAVE_COLORSCHEME #include "colorschemer.h" #endif +#include "emojifixer.h" #include "models/completionmodel.h" #include "models/statemodel.h" #include "neochatuser.h" @@ -188,12 +189,6 @@ int main(int argc, char *argv[]) initLogging(); -#ifdef NEOCHAT_FLATPAK - // Copy over the included FontConfig configuration to the - // app's config dir: - QFile::copy("/app/etc/fonts/conf.d/99-noto-mono-color-emoji.conf", "/var/config/fontconfig/conf.d/99-noto-mono-color-emoji.conf"); -#endif - Clipboard clipboard; auto config = NeoChatConfig::self(); FileTypeSingleton fileTypeSingleton; @@ -246,6 +241,7 @@ int main(int argc, char *argv[]) qmlRegisterType("org.kde.neochat", 1, 0, "StateModel"); qmlRegisterType("org.kde.neochat", 1, 0, "StateFilterModel"); qmlRegisterType("org.kde.neochat", 1, 0, "SearchModel"); + qmlRegisterSingletonInstance("org.kde.neochat", 1, 0, "EmojiFixer", new EmojiFixer); #ifdef QUOTIENT_07 qmlRegisterType("org.kde.neochat", 1, 0, "PollHandler"); #endif diff --git a/src/qml/Component/Emoji/EmojiPicker.qml b/src/qml/Component/Emoji/EmojiPicker.qml index 91933b229..572e47109 100644 --- a/src/qml/Component/Emoji/EmojiPicker.qml +++ b/src/qml/Component/Emoji/EmojiPicker.qml @@ -165,7 +165,7 @@ ColumnLayout { Component { id: emojiDelegate - Kirigami.NavigationTabButton { + NeoChatTabButton { width: root.categoryIconSize height: width checked: categories.currentIndex === model.index diff --git a/src/qml/Component/NeoChatTabButton.qml b/src/qml/Component/NeoChatTabButton.qml new file mode 100644 index 000000000..7439f0b28 --- /dev/null +++ b/src/qml/Component/NeoChatTabButton.qml @@ -0,0 +1,92 @@ +// SPDX-FileCopyrightText: 2021 Devin Lin +// SPDX-FileCopyrightText: 2021 Noah Davis +// SPDX-License-Identifier: LGPL-2.0-or-later + +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Controls 2.15 as QQC2 +import QtQuick.Templates 2.15 as T +import org.kde.kirigami 2.19 as Kirigami + +import org.kde.neochat 1.0 + +T.TabButton { + id: control + + property color foregroundColor: Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, 0.85) + property color highlightForegroundColor: Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, 0.85) + property color highlightBarColor: Kirigami.Theme.highlightColor + + property color pressedColor: Qt.rgba(highlightBarColor.r, highlightBarColor.g, highlightBarColor.b, 0.3) + property color hoverSelectColor: Qt.rgba(highlightBarColor.r, highlightBarColor.g, highlightBarColor.b, 0.2) + property color checkedBorderColor: Qt.rgba(highlightBarColor.r, highlightBarColor.g, highlightBarColor.b, 0.7) + property color pressedBorderColor: Qt.rgba(highlightBarColor.r, highlightBarColor.g, highlightBarColor.b, 0.9) + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding) + + display: T.AbstractButton.TextUnderIcon + + Kirigami.Theme.colorSet: Kirigami.Theme.Window + Kirigami.Theme.inherit: false + + // not using the hover handler built into control, since it seems to misbehave and + // permanently report hovered after a touch event + HoverHandler { + id: hoverHandler + } + + padding: Kirigami.Units.smallSpacing + spacing: Kirigami.Units.smallSpacing + + icon.height: control.display === T.AbstractButton.TextBesideIcon ? Kirigami.Units.iconSizes.small : Kirigami.Units.iconSizes.smallMedium + icon.width: control.display === T.AbstractButton.TextBesideIcon ? Kirigami.Units.iconSizes.small : Kirigami.Units.iconSizes.smallMedium + icon.color: control.checked ? control.highlightForegroundColor : control.foregroundColor + + background: Rectangle { + Kirigami.Theme.colorSet: Kirigami.Theme.Button + Kirigami.Theme.inherit: false + + implicitHeight: Kirigami.Units.gridUnit * 3 + Kirigami.Units.smallSpacing * 2 + + color: "transparent" + + Rectangle { + width: parent.width - Kirigami.Units.largeSpacing + height: parent.height - Kirigami.Units.largeSpacing + anchors.centerIn: parent + + radius: Kirigami.Units.smallSpacing + color: control.down ? pressedColor : (control.checked || hoverHandler.hovered ? hoverSelectColor : "transparent") + + border.color: control.checked ? checkedBorderColor : (control.down ? pressedBorderColor : color) + border.width: 1 + + Behavior on color { ColorAnimation { duration: Kirigami.Units.shortDuration } } + Behavior on border.color { ColorAnimation { duration: Kirigami.Units.shortDuration } } + } + } + + contentItem: QQC2.Label { + id: label + Kirigami.MnemonicData.enabled: control.enabled && control.visible + Kirigami.MnemonicData.controlType: Kirigami.MnemonicData.MenuItem + Kirigami.MnemonicData.label: control.text + + text: Kirigami.MnemonicData.richTextLabel + horizontalAlignment: Text.AlignHCenter + + wrapMode: Text.Wrap + elide: Text.ElideMiddle + color: control.checked ? control.highlightForegroundColor : control.foregroundColor + + font.bold: control.checked + font.family: "emoji" + font.pointSize: Kirigami.Theme.defaultFont.pointSize * 1.20 + + Behavior on color { ColorAnimation {} } + Behavior on opacity { NumberAnimation {} } + } +} diff --git a/src/qml/Component/Timeline/ReactionDelegate.qml b/src/qml/Component/Timeline/ReactionDelegate.qml index 8d8d503bf..605acb9a9 100644 --- a/src/qml/Component/Timeline/ReactionDelegate.qml +++ b/src/qml/Component/Timeline/ReactionDelegate.qml @@ -6,6 +6,7 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 as QQC2 import org.kde.kirigami 2.15 as Kirigami +import org.kde.neochat 1.0 Flow { id: root @@ -28,15 +29,18 @@ Flow { id: reactionRepeater model: root.model - delegate: QQC2.AbstractButton { + delegate: QQC2.Control { width: Math.max(reactionTextMetrics.advanceWidth + Kirigami.Units.smallSpacing * 4, height) - contentItem: QQC2.Label { + contentItem: TextEdit { id: reactionLabel horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter text: model.text - + readOnly: true + Component.onCompleted: EmojiFixer.addTextDocument(reactionLabel.textDocument) + color: Kirigami.Theme.textColor + selectByMouse: false TextMetrics { id: reactionTextMetrics text: reactionLabel.text @@ -56,12 +60,16 @@ Flow { border.width: 1 } - onClicked: reactionClicked(model.reaction) + MouseArea { + anchors.fill: parent + onClicked: reactionClicked(model.reaction) + hoverEnabled: true + } - hoverEnabled: true QQC2.ToolTip.visible: hovered QQC2.ToolTip.text: model.toolTip + QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay } } } diff --git a/src/qml/Component/Timeline/RichLabel.qml b/src/qml/Component/Timeline/RichLabel.qml index d41745cbc..d6a467a38 100644 --- a/src/qml/Component/Timeline/RichLabel.qml +++ b/src/qml/Component/Timeline/RichLabel.qml @@ -43,9 +43,12 @@ TextEdit { persistentSelection: true - // Work around QTBUG 93281 - Component.onCompleted: if (text.includes(" diff --git a/src/qml/Page/RoomList/RoomDelegate.qml b/src/qml/Page/RoomList/RoomDelegate.qml index 48fff1b3e..8aac4da4e 100644 --- a/src/qml/Page/RoomList/RoomDelegate.qml +++ b/src/qml/Page/RoomList/RoomDelegate.qml @@ -13,7 +13,7 @@ import org.kde.neochat 1.0 import './' as RoomList -Kirigami.BasicListItem { +Kirigami.AbstractListItem { id: root required property int index @@ -26,7 +26,6 @@ Kirigami.BasicListItem { required property string subtitleText required property string displayName - readonly property bool hasNotifications: notificationCount > 0 topPadding: Kirigami.Units.largeSpacing @@ -35,16 +34,154 @@ Kirigami.BasicListItem { visible: root.categoryVisible || root.filterText.length > 0 || Config.mergeRoomList highlighted: ListView.view.currentIndex === index focus: true - icon: undefined - bold: root.hasNotifications + property bool bold: root.hasNotifications - label: root.displayName - labelItem.textFormat: Text.PlainText + contentItem: Item { + id: contItem - subtitle: root.subtitleText - subtitleItem { - textFormat: Text.PlainText - visible: !Config.compactRoomList + implicitWidth: layout.implicitWidth + + Binding on implicitHeight { + value: Math.max(iconItem.size, (!subtitleItem.visible && root.reserveSpaceForSubtitle ? (labelItem.implicitHeight + labelColumn.spacing + subtitleItem.implicitHeight): labelColumn.implicitHeight) ) + delayed: true + } + + RowLayout { + id: layout + spacing: LayoutMirroring.enabled ? root.rightPadding : root.leftPadding + anchors.left: contItem.left + anchors.leftMargin: root.leading ? root.leadingPadding : 0 + anchors.right: contItem.right + anchors.rightMargin: root.trailing ? root.trailingPadding : 0 + anchors.verticalCenter: parent.verticalCenter + + Kirigami.Avatar { + source: root.avatar ? `image://mxc/${root.avatar}` : "" + name: root.displayName + implicitWidth: visible ? height : 0 + visible: Config.showAvatarInRoomDrawer + Layout.preferredWidth: sourceSize.width + Layout.preferredHeight: sourceSize.height + sourceSize { + width: Kirigami.Units.gridUnit + Kirigami.Units.largeSpacing * 2 + height: Kirigami.Units.gridUnit + Kirigami.Units.largeSpacing * 2 + } + } + + Kirigami.Icon { + id: iconItem + source: root.icon.name !== "" ? root.icon.name : root.icon.source + property int size: subtitleItem.visible || reserveSpaceForSubtitle ? Kirigami.Units.iconSizes.medium : Kirigami.Units.iconSizes.smallMedium + Layout.minimumHeight: size + Layout.maximumHeight: size + Layout.minimumWidth: size + Layout.maximumWidth: size + selected: (root.highlighted || root.checked || root.down) + opacity: root.fadeContent ? 0.6 : 1.0 + visible: source.toString() !== "" + } + ColumnLayout { + id: labelColumn + spacing: 0 + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter + TextEdit { + id: labelItem + text: labelMetrics.elidedText + Layout.fillWidth: true + Layout.alignment: subtitleItem.visible ? Qt.AlignLeft | Qt.AlignBottom : Qt.AlignLeft | Qt.AlignVCenter + color: (root.highlighted || root.checked || root.down) ? root.activeTextColor : root.textColor + font.weight: root.bold ? Font.Bold : Font.Normal + opacity: root.fadeContent ? 0.6 : 1.0 + readOnly: true + Component.onCompleted: EmojiFixer.addTextDocument(labelItem.textDocument) + TextMetrics { + id: labelMetrics + font: labelItem.font + text: root.displayName + elideWidth: labelItem.width + elide: Qt.ElideRight + } + MouseArea { + anchors.fill: parent + onClicked: RoomManager.enterRoom(root.currentRoom) + onPressAndHold: createRoomListContextMenu() + } + } + TextEdit { + id: subtitleItem + Layout.fillWidth: true + Layout.alignment: subtitleItem.visible ? Qt.AlignLeft | Qt.AlignTop : Qt.AlignLeft | Qt.AlignVCenter + color: (root.highlighted || root.checked || root.down) ? root.activeTextColor : root.textColor + //elide: Text.ElideRight + font: Kirigami.Theme.smallFont + opacity: root.fadeContent ? 0.6 : (root.bold ? 0.9 : 0.7) + text: subtitleMetrics.elidedText + textFormat: Text.PlainText + visible: !Config.compactRoomList + readOnly: true + Component.onCompleted: EmojiFixer.addTextDocument(subtitleItem.textDocument) + TextMetrics { + id: subtitleMetrics + font: subtitleItem.font + text: root.subtitleText + elideWidth: subtitleItem.width + elide: Qt.ElideRight + } + MouseArea { + anchors.fill: parent + onClicked: RoomManager.enterRoom(root.currentRoom) + onPressAndHold: createRoomListContextMenu() + } + } + } + Kirigami.Icon { + source: "notifications-disabled" + enabled: false + implicitWidth: Kirigami.Units.iconSizes.smallMedium + implicitHeight: Kirigami.Units.iconSizes.smallMedium + visible: currentRoom.pushNotificationState === PushNotificationState.Mute && !configButton.visible && !hasNotifications + Accessible.name: i18n("Muted room") + Layout.rightMargin: Kirigami.Units.smallSpacing + } + QQC2.Label { + id: notificationCountLabel + text: notificationCount + visible: hasNotifications + color: Kirigami.Theme.textColor + horizontalAlignment: Text.AlignHCenter + background: Rectangle { + visible: notificationCount > 0 + Kirigami.Theme.colorSet: Kirigami.Theme.Button + color: highlightCount > 0 ? Kirigami.Theme.positiveTextColor : Kirigami.Theme.disabledTextColor + opacity: highlightCount > 0 ? 1 : 0.3 + radius: height / 2 + } + + Layout.rightMargin: Kirigami.Units.smallSpacing + Layout.minimumHeight: Kirigami.Units.iconSizes.smallMedium + Layout.minimumWidth: Math.max(notificationCountTextMetrics.advanceWidth + Kirigami.Units.smallSpacing * 2, height) + + TextMetrics { + id: notificationCountTextMetrics + text: notificationCountLabel.text + } + } + QQC2.Button { + id: configButton + visible: root.hovered && !Kirigami.Settings.isMobile && !Config.compactRoomList + text: i18n("Configure room") + display: QQC2.Button.IconOnly + + icon.name: "configure" + onClicked: createRoomListContextMenu() + } + TapHandler { + acceptedButtons: Qt.RightButton + acceptedDevices: PointerDevice.Mouse + onTapped: createRoomListContextMenu() + } + } } onClicked: RoomManager.enterRoom(root.currentRoom) @@ -53,67 +190,6 @@ Kirigami.BasicListItem { Keys.onEnterPressed: RoomManager.enterRoom(root.currentRoom) Keys.onReturnPressed: RoomManager.enterRoom(root.currentRoom) - TapHandler { - acceptedButtons: Qt.RightButton - acceptedDevices: PointerDevice.Mouse - onTapped: createRoomListContextMenu() - } - - leading: Kirigami.Avatar { - source: root.avatar ? `image://mxc/${root.avatar}` : "" - name: root.displayName - implicitWidth: visible ? height : 0 - visible: Config.showAvatarInRoomDrawer - sourceSize { - width: Kirigami.Units.gridUnit + Kirigami.Units.largeSpacing * 2 - height: Kirigami.Units.gridUnit + Kirigami.Units.largeSpacing * 2 - } - } - - trailing: RowLayout { - Kirigami.Icon { - source: "notifications-disabled" - enabled: false - implicitWidth: Kirigami.Units.iconSizes.smallMedium - implicitHeight: Kirigami.Units.iconSizes.smallMedium - visible: currentRoom.pushNotificationState === PushNotificationState.Mute && !configButton.visible && !hasNotifications - Accessible.name: i18n("Muted room") - Layout.rightMargin: Kirigami.Units.smallSpacing - } - QQC2.Label { - id: notificationCountLabel - text: notificationCount - visible: hasNotifications - color: Kirigami.Theme.textColor - horizontalAlignment: Text.AlignHCenter - background: Rectangle { - visible: notificationCount > 0 - Kirigami.Theme.colorSet: Kirigami.Theme.Button - color: highlightCount > 0 ? Kirigami.Theme.positiveTextColor : Kirigami.Theme.disabledTextColor - opacity: highlightCount > 0 ? 1 : 0.3 - radius: height / 2 - } - - Layout.rightMargin: Kirigami.Units.smallSpacing - Layout.minimumHeight: Kirigami.Units.iconSizes.smallMedium - Layout.minimumWidth: Math.max(notificationCountTextMetrics.advanceWidth + Kirigami.Units.smallSpacing * 2, height) - - TextMetrics { - id: notificationCountTextMetrics - text: notificationCountLabel.text - } - } - QQC2.Button { - id: configButton - visible: root.hovered && !Kirigami.Settings.isMobile && !Config.compactRoomList - text: i18n("Configure room") - display: QQC2.Button.IconOnly - - icon.name: "configure" - onClicked: createRoomListContextMenu() - } - } - function createRoomListContextMenu() { const component = Qt.createComponent(Qt.resolvedUrl("./ContextMenu.qml")) const menu = component.createObject(root, { diff --git a/src/qml/Panel/GroupChatDrawerHeader.qml b/src/qml/Panel/GroupChatDrawerHeader.qml index 0dd108aca..d1cde2091 100644 --- a/src/qml/Panel/GroupChatDrawerHeader.qml +++ b/src/qml/Panel/GroupChatDrawerHeader.qml @@ -92,6 +92,7 @@ ColumnLayout { cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.IBeamCursor } background: Item {} + Component.onCompleted: EmojiFixer.addTextDocument(topicText.textDocument) } } diff --git a/src/res.qrc b/src/res.qrc index 9bddd3a25..c7a245c15 100644 --- a/src/res.qrc +++ b/src/res.qrc @@ -124,6 +124,7 @@ qml/Component/TimelineView.qml qml/Component/InvitationView.qml qml/Component/AvatarTabButton.qml + qml/Component/NeoChatTabButton.qml qml/Page/RoomList/SpaceDrawer.qml