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