Search for emojis with :<keyword>
This commit is contained in:
parent
3410903afb
commit
a78f60f974
9 changed files with 271 additions and 2 deletions
BIN
db/emojis.db
Normal file
BIN
db/emojis.db
Normal file
Binary file not shown.
|
@ -16,7 +16,7 @@ CONFIG += sailfishapp sailfishapp_i18n
|
|||
|
||||
PKGCONFIG += nemonotifications-qt5 ngf-qt5
|
||||
|
||||
QT += core dbus
|
||||
QT += core dbus sql
|
||||
|
||||
SOURCES += src/harbour-fernschreiber.cpp \
|
||||
src/appsettings.cpp \
|
||||
|
@ -24,6 +24,7 @@ SOURCES += src/harbour-fernschreiber.cpp \
|
|||
src/chatmodel.cpp \
|
||||
src/dbusadaptor.cpp \
|
||||
src/dbusinterface.cpp \
|
||||
src/emojisearchworker.cpp \
|
||||
src/fernschreiberutils.cpp \
|
||||
src/notificationmanager.cpp \
|
||||
src/processlauncher.cpp \
|
||||
|
@ -102,8 +103,11 @@ ICONPATH = /usr/share/icons/hicolor
|
|||
fernschreiber.desktop.path = /usr/share/applications/
|
||||
fernschreiber.desktop.files = harbour-fernschreiber.desktop
|
||||
|
||||
database.files = db
|
||||
database.path = /usr/share/$${TARGET}
|
||||
|
||||
INSTALLS += telegram 86.png 108.png 128.png 172.png 256.png \
|
||||
fernschreiber.desktop gui images
|
||||
fernschreiber.desktop gui images database
|
||||
|
||||
HEADERS += \
|
||||
src/appsettings.h \
|
||||
|
@ -111,6 +115,7 @@ HEADERS += \
|
|||
src/chatmodel.h \
|
||||
src/dbusadaptor.h \
|
||||
src/dbusinterface.h \
|
||||
src/emojisearchworker.h \
|
||||
src/fernschreiberutils.h \
|
||||
src/notificationmanager.h \
|
||||
src/processlauncher.h \
|
||||
|
|
|
@ -43,6 +43,7 @@ Page {
|
|||
property variant chatPartnerInformation;
|
||||
property variant chatGroupInformation;
|
||||
property int chatOnlineMemberCount: 0;
|
||||
property variant emojiProposals;
|
||||
|
||||
function updateChatPartnerStatusText() {
|
||||
if (chatPartnerInformation.status['@type'] === "userStatusEmpty" ) {
|
||||
|
@ -176,6 +177,44 @@ Page {
|
|||
controlSendButton();
|
||||
}
|
||||
|
||||
function getWordBoundaries(text, cursorPosition) {
|
||||
var wordBoundaries = { beginIndex : 0, endIndex : text.length};
|
||||
var currentIndex = 0;
|
||||
for (currentIndex = (cursorPosition - 1); currentIndex > 0; currentIndex--) {
|
||||
if (text.charAt(currentIndex) === ' ') {
|
||||
wordBoundaries.beginIndex = currentIndex + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (currentIndex = cursorPosition; currentIndex < text.length; currentIndex++) {
|
||||
if (text.charAt(currentIndex) === ' ') {
|
||||
wordBoundaries.endIndex = currentIndex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return wordBoundaries;
|
||||
}
|
||||
|
||||
function handleMessageTextReplacement(text, cursorPosition) {
|
||||
var wordBoundaries = getWordBoundaries(text, cursorPosition);
|
||||
|
||||
var currentWord = text.substring(wordBoundaries.beginIndex, wordBoundaries.endIndex);
|
||||
if (currentWord.length > 1 && currentWord.charAt(0) === ':') {
|
||||
tdLibWrapper.searchEmoji(currentWord.substring(1));
|
||||
} else {
|
||||
chatPage.emojiProposals = null;
|
||||
}
|
||||
}
|
||||
|
||||
function replaceMessageText(text, cursorPosition, newText) {
|
||||
var wordBoundaries = getWordBoundaries(text, cursorPosition);
|
||||
var newCompleteText = text.substring(0, wordBoundaries.beginIndex) + newText + " " + text.substring(wordBoundaries.endIndex);
|
||||
var newIndex = wordBoundaries.beginIndex + newText.length + 1;
|
||||
newMessageTextField.text = newCompleteText;
|
||||
newMessageTextField.cursorPosition = newIndex;
|
||||
lostFocusTimer.start();
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
initializePage();
|
||||
}
|
||||
|
@ -227,6 +266,9 @@ Page {
|
|||
uploadingProgressBar.maximumValue = fileInformation.size;
|
||||
uploadingProgressBar.value = fileInformation.remote.uploaded_size;
|
||||
}
|
||||
onEmojiSearchSuccessful: {
|
||||
chatPage.emojiProposals = result;
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
|
@ -269,6 +311,26 @@ Page {
|
|||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: lostFocusTimer
|
||||
interval: 200
|
||||
running: false
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
newMessageTextField.forceActiveFocus();
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: textReplacementTimer
|
||||
interval: 600
|
||||
running: false
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
handleMessageTextReplacement(newMessageTextField.text, newMessageTextField.cursorPosition);
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: chatContactTimeUpdater
|
||||
interval: 60000
|
||||
|
@ -1151,6 +1213,58 @@ Page {
|
|||
|
||||
}
|
||||
|
||||
Column {
|
||||
id: emojiColumn
|
||||
width: parent.width
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
visible: emojiProposals ? ( emojiProposals.length > 0 ? true : false ) : false
|
||||
opacity: emojiProposals ? ( emojiProposals.length > 0 ? 1 : 0 ) : 0
|
||||
Behavior on opacity { NumberAnimation {} }
|
||||
spacing: Theme.paddingMedium
|
||||
|
||||
Flickable {
|
||||
width: parent.width
|
||||
height: emojiResultRow.height + Theme.paddingSmall
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
contentWidth: emojiResultRow.width
|
||||
clip: true
|
||||
Row {
|
||||
id: emojiResultRow
|
||||
spacing: Theme.paddingMedium
|
||||
Repeater {
|
||||
model: emojiProposals
|
||||
|
||||
Item {
|
||||
height: singleEmojiRow.height
|
||||
width: singleEmojiRow.width
|
||||
|
||||
Row {
|
||||
id: singleEmojiRow
|
||||
spacing: Theme.paddingSmall
|
||||
|
||||
Image {
|
||||
id: emojiPicture
|
||||
source: "../js/emoji/" + modelData.file_name
|
||||
width: Theme.fontSizeLarge
|
||||
height: Theme.fontSizeLarge
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
replaceMessageText(newMessageTextField.text, newMessageTextField.cursorPosition, modelData.emoji);
|
||||
emojiProposals = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
width: parent.width
|
||||
|
||||
|
@ -1199,6 +1313,7 @@ Page {
|
|||
|
||||
onTextChanged: {
|
||||
controlSendButton();
|
||||
textReplacementTimer.restart();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ BuildRequires: pkgconfig(Qt5Core)
|
|||
BuildRequires: pkgconfig(Qt5Qml)
|
||||
BuildRequires: pkgconfig(Qt5Quick)
|
||||
BuildRequires: pkgconfig(Qt5DBus)
|
||||
BuildRequires: pkgconfig(Qt5Sql)
|
||||
BuildRequires: pkgconfig(nemonotifications-qt5)
|
||||
BuildRequires: pkgconfig(ngf-qt5)
|
||||
BuildRequires: desktop-file-utils
|
||||
|
|
|
@ -24,6 +24,7 @@ PkgConfigBR:
|
|||
- Qt5Qml
|
||||
- Qt5Quick
|
||||
- Qt5DBus
|
||||
- Qt5Sql
|
||||
- nemonotifications-qt5
|
||||
- ngf-qt5
|
||||
|
||||
|
|
69
src/emojisearchworker.cpp
Normal file
69
src/emojisearchworker.cpp
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "emojisearchworker.h"
|
||||
|
||||
#define LOG(x) qDebug() << "[EmojiSearchWorker]" << x
|
||||
|
||||
EmojiSearchWorker::~EmojiSearchWorker()
|
||||
{
|
||||
LOG("Destroying myself...");
|
||||
database.close();
|
||||
}
|
||||
|
||||
EmojiSearchWorker::EmojiSearchWorker(QObject *parent) : QThread(parent)
|
||||
{
|
||||
LOG("Initializing Emoji database");
|
||||
QSqlDatabase::removeDatabase("emojis");
|
||||
database = QSqlDatabase::addDatabase("QSQLITE", "emojis");
|
||||
database.setDatabaseName("/usr/share/harbour-fernschreiber/db/emojis.db");
|
||||
}
|
||||
|
||||
void EmojiSearchWorker::setParameters(const QString &queryString)
|
||||
{
|
||||
this->queryString = queryString;
|
||||
}
|
||||
|
||||
void EmojiSearchWorker::performSearch()
|
||||
{
|
||||
LOG("Performing emoji search" << this->queryString);
|
||||
QVariantList resultList;
|
||||
|
||||
if (database.open()) {
|
||||
QSqlQuery query(database);
|
||||
query.prepare("select * from emojis where description match (:queryString) limit 25");
|
||||
query.bindValue(":queryString", queryString + "*");
|
||||
query.exec();
|
||||
while (query.next()) {
|
||||
if (isInterruptionRequested()) {
|
||||
break;
|
||||
}
|
||||
QVariantMap foundEmoji;
|
||||
foundEmoji.insert("file_name", query.value(0).toString());
|
||||
foundEmoji.insert("emoji", query.value(1).toString());
|
||||
foundEmoji.insert("emoji_version", query.value(2).toString());
|
||||
foundEmoji.insert("description", query.value(3).toString());
|
||||
resultList.append(foundEmoji);
|
||||
}
|
||||
database.close();
|
||||
} else {
|
||||
LOG("Unable to perform a query on database" << database.lastError().databaseText());
|
||||
}
|
||||
|
||||
emit searchCompleted(queryString, resultList);
|
||||
}
|
52
src/emojisearchworker.h
Normal file
52
src/emojisearchworker.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef EMOJISEARCHWORKER_H
|
||||
#define EMOJISEARCHWORKER_H
|
||||
|
||||
#include <QThread>
|
||||
#include <QSqlDatabase>
|
||||
#include <QSqlQuery>
|
||||
#include <QSqlError>
|
||||
#include <QVariantList>
|
||||
#include <QDebug>
|
||||
|
||||
class EmojiSearchWorker : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
void run() Q_DECL_OVERRIDE {
|
||||
performSearch();
|
||||
}
|
||||
public:
|
||||
~EmojiSearchWorker() override;
|
||||
explicit EmojiSearchWorker(QObject *parent = nullptr);
|
||||
void setParameters(const QString &queryString);
|
||||
|
||||
signals:
|
||||
void searchCompleted(const QString &queryString, const QVariantList &resultList);
|
||||
|
||||
public slots:
|
||||
|
||||
private:
|
||||
QSqlDatabase database;
|
||||
QString queryString;
|
||||
|
||||
void performSearch();
|
||||
};
|
||||
|
||||
#endif // EMOJISEARCHWORKER_H
|
|
@ -93,6 +93,8 @@ TDLibWrapper::TDLibWrapper(QObject *parent) : QObject(parent)
|
|||
connect(this->tdLibReceiver, SIGNAL(stickerSets(QVariantList)), this, SLOT(handleStickerSets(QVariantList)));
|
||||
connect(this->tdLibReceiver, SIGNAL(stickerSet(QVariantMap)), this, SLOT(handleStickerSet(QVariantMap)));
|
||||
|
||||
connect(&emojiSearchWorker, SIGNAL(searchCompleted(QString, QVariantList)), this, SLOT(handleEmojiSearchCompleted(QString, QVariantList)));
|
||||
|
||||
this->tdLibReceiver->start();
|
||||
|
||||
this->setLogVerbosityLevel();
|
||||
|
@ -467,6 +469,16 @@ void TDLibWrapper::getStickerSet(const QString &setId)
|
|||
this->sendRequest(requestObject);
|
||||
}
|
||||
|
||||
void TDLibWrapper::searchEmoji(const QString &queryString)
|
||||
{
|
||||
LOG("Searching emoji" << queryString);
|
||||
while (this->emojiSearchWorker.isRunning()) {
|
||||
this->emojiSearchWorker.requestInterruption();
|
||||
}
|
||||
this->emojiSearchWorker.setParameters(queryString);
|
||||
this->emojiSearchWorker.start();
|
||||
}
|
||||
|
||||
QVariantMap TDLibWrapper::getUserInformation()
|
||||
{
|
||||
return this->userInformation;
|
||||
|
@ -828,6 +840,12 @@ void TDLibWrapper::handleStickerSet(const QVariantMap &stickerSet)
|
|||
emit stickerSetReceived(stickerSet);
|
||||
}
|
||||
|
||||
void TDLibWrapper::handleEmojiSearchCompleted(const QString &queryString, const QVariantList &resultList)
|
||||
{
|
||||
LOG("Emoji search completed" << queryString);
|
||||
emit emojiSearchSuccessful(resultList);
|
||||
}
|
||||
|
||||
void TDLibWrapper::setInitialParameters()
|
||||
{
|
||||
LOG("Sending initial parameters to TD Lib");
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "tdlibreceiver.h"
|
||||
#include "dbusadaptor.h"
|
||||
#include "dbusinterface.h"
|
||||
#include "emojisearchworker.h"
|
||||
|
||||
class TDLibWrapper : public QObject
|
||||
{
|
||||
|
@ -129,6 +130,9 @@ public:
|
|||
Q_INVOKABLE void getInstalledStickerSets();
|
||||
Q_INVOKABLE void getStickerSet(const QString &setId);
|
||||
|
||||
// Others (candidates for extraction ;))
|
||||
Q_INVOKABLE void searchEmoji(const QString &queryString);
|
||||
|
||||
public:
|
||||
const Group* getGroup(qlonglong groupId) const;
|
||||
static ChatMemberStatus chatMemberStatusFromString(const QString &status);
|
||||
|
@ -169,6 +173,7 @@ signals:
|
|||
void installedStickerSetsUpdated(const QVariantList &stickerSetIds);
|
||||
void stickerSetsReceived(const QVariantList &stickerSets);
|
||||
void stickerSetReceived(const QVariantMap &stickerSet);
|
||||
void emojiSearchSuccessful(const QVariantList &result);
|
||||
|
||||
public slots:
|
||||
void handleVersionDetected(const QString &version);
|
||||
|
@ -204,6 +209,7 @@ public slots:
|
|||
void handleInstalledStickerSetsUpdated(const QVariantList &stickerSetIds);
|
||||
void handleStickerSets(const QVariantList &stickerSets);
|
||||
void handleStickerSet(const QVariantMap &stickerSet);
|
||||
void handleEmojiSearchCompleted(const QString &queryString, const QVariantList &resultList);
|
||||
|
||||
private:
|
||||
void setInitialParameters();
|
||||
|
@ -228,6 +234,8 @@ private:
|
|||
QVariantMap unreadChatInformation;
|
||||
QHash<qlonglong,Group*> basicGroups;
|
||||
QHash<qlonglong,Group*> superGroups;
|
||||
EmojiSearchWorker emojiSearchWorker;
|
||||
|
||||
};
|
||||
|
||||
#endif // TDLIBWRAPPER_H
|
||||
|
|
Loading…
Reference in a new issue