Colorful emoji in reaction
Use ICU to determine if the string contains only emojis
This commit is contained in:
@@ -63,9 +63,9 @@ set_package_properties(KF6 PROPERTIES
|
|||||||
PURPOSE "Basic application components"
|
PURPOSE "Basic application components"
|
||||||
)
|
)
|
||||||
set_package_properties(KF6Kirigami2 PROPERTIES
|
set_package_properties(KF6Kirigami2 PROPERTIES
|
||||||
TYPE REQUIRED
|
TYPE REQUIRED
|
||||||
PURPOSE "Kirigami application UI framework"
|
PURPOSE "Kirigami application UI framework"
|
||||||
)
|
)
|
||||||
find_package(KF6KirigamiAddons 0.7.2 REQUIRED)
|
find_package(KF6KirigamiAddons 0.7.2 REQUIRED)
|
||||||
|
|
||||||
if(ANDROID)
|
if(ANDROID)
|
||||||
@@ -81,6 +81,12 @@ else()
|
|||||||
TYPE RUNTIME
|
TYPE RUNTIME
|
||||||
)
|
)
|
||||||
ecm_find_qmlmodule(org.kde.syntaxhighlighting 1.0)
|
ecm_find_qmlmodule(org.kde.syntaxhighlighting 1.0)
|
||||||
|
|
||||||
|
find_package(ICU 61.0 COMPONENTS uc)
|
||||||
|
set_package_properties(ICU PROPERTIES
|
||||||
|
TYPE REQUIRED
|
||||||
|
PURPOSE "Unicode library"
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT ANDROID AND NOT WIN32 AND NOT APPLE)
|
if (NOT ANDROID AND NOT WIN32 AND NOT APPLE)
|
||||||
|
|||||||
@@ -319,9 +319,10 @@ if(NOT ANDROID)
|
|||||||
else()
|
else()
|
||||||
target_sources(neochat PRIVATE trayicon.cpp trayicon.h)
|
target_sources(neochat PRIVATE trayicon.cpp trayicon.h)
|
||||||
endif()
|
endif()
|
||||||
target_link_libraries(neochat PUBLIC KF6::ConfigWidgets KF6::WindowSystem)
|
target_link_libraries(neochat PUBLIC KF6::ConfigWidgets KF6::WindowSystem ICU::uc)
|
||||||
target_compile_definitions(neochat PUBLIC -DHAVE_COLORSCHEME)
|
target_compile_definitions(neochat PUBLIC -DHAVE_COLORSCHEME)
|
||||||
target_compile_definitions(neochat PUBLIC -DHAVE_WINDOWSYSTEM)
|
target_compile_definitions(neochat PUBLIC -DHAVE_WINDOWSYSTEM)
|
||||||
|
target_compile_definitions(neochat PUBLIC -DHAVE_ICU)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT ANDROID AND NOT WIN32 AND NOT APPLE)
|
if (NOT ANDROID AND NOT WIN32 AND NOT APPLE)
|
||||||
|
|||||||
@@ -4,6 +4,12 @@
|
|||||||
#include "reactionmodel.h"
|
#include "reactionmodel.h"
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#ifdef HAVE_ICU
|
||||||
|
#include <QTextBoundaryFinder>
|
||||||
|
#include <QTextCharFormat>
|
||||||
|
#include <unicode/uchar.h>
|
||||||
|
#include <unicode/urename.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <KLocalizedString>
|
#include <KLocalizedString>
|
||||||
|
|
||||||
@@ -29,11 +35,38 @@ QVariant ReactionModel::data(const QModelIndex &index, int role) const
|
|||||||
|
|
||||||
const auto &reaction = m_reactions.at(index.row());
|
const auto &reaction = m_reactions.at(index.row());
|
||||||
|
|
||||||
if (role == TextRole) {
|
const auto isEmoji = [](const QString &text) {
|
||||||
|
#ifdef HAVE_ICU
|
||||||
|
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;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto reactionText = isEmoji(reaction.reaction)
|
||||||
|
? QStringLiteral("<span style=\"font-family: 'emoji';\">") + reaction.reaction + QStringLiteral("</span>")
|
||||||
|
: reaction.reaction;
|
||||||
|
|
||||||
|
if (role == TextContentRole) {
|
||||||
if (reaction.authors.count() > 1) {
|
if (reaction.authors.count() > 1) {
|
||||||
return QStringLiteral("%1 %2").arg(reaction.reaction, QString::number(reaction.authors.count()));
|
return QStringLiteral("%1 %2").arg(reactionText, QString::number(reaction.authors.count()));
|
||||||
} else {
|
} else {
|
||||||
return reaction.reaction;
|
return reactionText;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +97,7 @@ QVariant ReactionModel::data(const QModelIndex &index, int role) const
|
|||||||
"%2 reacted with %3",
|
"%2 reacted with %3",
|
||||||
reaction.authors.count(),
|
reaction.authors.count(),
|
||||||
text,
|
text,
|
||||||
reaction.reaction);
|
reactionText);
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,7 +134,7 @@ void ReactionModel::setReactions(QList<Reaction> reactions)
|
|||||||
QHash<int, QByteArray> ReactionModel::roleNames() const
|
QHash<int, QByteArray> ReactionModel::roleNames() const
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
{TextRole, "text"},
|
{TextContentRole, "textContent"},
|
||||||
{ReactionRole, "reaction"},
|
{ReactionRole, "reaction"},
|
||||||
{ToolTipRole, "toolTip"},
|
{ToolTipRole, "toolTip"},
|
||||||
{AuthorsRole, "authors"},
|
{AuthorsRole, "authors"},
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public:
|
|||||||
* @brief Defines the model roles.
|
* @brief Defines the model roles.
|
||||||
*/
|
*/
|
||||||
enum Roles {
|
enum Roles {
|
||||||
TextRole = Qt::DisplayRole, /**< The text to show in the reaction. */
|
TextContentRole = Qt::DisplayRole, /**< The text to show in the reaction. */
|
||||||
ReactionRole, /**< The reaction emoji. */
|
ReactionRole, /**< The reaction emoji. */
|
||||||
ToolTipRole, /**< The tool tip to show for the reaction. */
|
ToolTipRole, /**< The tool tip to show for the reaction. */
|
||||||
AuthorsRole, /**< The list of authors who sent the given reaction. */
|
AuthorsRole, /**< The list of authors who sent the given reaction. */
|
||||||
|
|||||||
@@ -28,39 +28,45 @@ Flow {
|
|||||||
id: reactionRepeater
|
id: reactionRepeater
|
||||||
|
|
||||||
delegate: QQC2.AbstractButton {
|
delegate: QQC2.AbstractButton {
|
||||||
width: Math.max(reactionTextMetrics.advanceWidth + Kirigami.Units.smallSpacing * 4, height)
|
id: reactionDelegate
|
||||||
|
|
||||||
|
required property string textContent
|
||||||
|
required property string reaction
|
||||||
|
required property string toolTip
|
||||||
|
required property bool hasLocalUser
|
||||||
|
|
||||||
|
width: Math.max(contentItem.implicitWidth + leftPadding + rightPadding, height)
|
||||||
|
height: Math.round(Kirigami.Units.gridUnit * 1.5)
|
||||||
|
|
||||||
contentItem: QQC2.Label {
|
contentItem: QQC2.Label {
|
||||||
id: reactionLabel
|
id: reactionLabel
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
text: model.text
|
text: reactionDelegate.textContent
|
||||||
|
background: null
|
||||||
TextMetrics {
|
wrapMode: TextEdit.NoWrap
|
||||||
id: reactionTextMetrics
|
textFormat: Text.RichText
|
||||||
text: reactionLabel.text
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
padding: Kirigami.Units.smallSpacing
|
padding: Kirigami.Units.smallSpacing
|
||||||
|
|
||||||
background: Kirigami.ShadowedRectangle {
|
background: Kirigami.ShadowedRectangle {
|
||||||
color: model.hasLocalUser ? Kirigami.Theme.positiveBackgroundColor : Kirigami.Theme.backgroundColor
|
color: reactionDelegate.hasLocalUser ? Kirigami.Theme.positiveBackgroundColor : Kirigami.Theme.backgroundColor
|
||||||
Kirigami.Theme.inherit: false
|
Kirigami.Theme.inherit: false
|
||||||
Kirigami.Theme.colorSet: Kirigami.Theme.View
|
Kirigami.Theme.colorSet: Kirigami.Theme.View
|
||||||
radius: height / 2
|
radius: height / 2
|
||||||
shadow {
|
shadow {
|
||||||
size: Kirigami.Units.smallSpacing
|
size: Kirigami.Units.smallSpacing
|
||||||
color: !model.hasLocalUser ? Qt.rgba(0.0, 0.0, 0.0, 0.10) : Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, 0.10)
|
color: !reactionDelegate.hasLocalUser ? Qt.rgba(0.0, 0.0, 0.0, 0.10) : Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, 0.10)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: reactionClicked(model.reaction)
|
onClicked: reactionClicked(reactionDelegate.reaction)
|
||||||
|
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
|
|
||||||
QQC2.ToolTip.visible: hovered
|
QQC2.ToolTip.visible: hovered
|
||||||
QQC2.ToolTip.text: model.toolTip
|
QQC2.ToolTip.text: reactionDelegate.toolTip
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user