Commit b8aab340 authored by Simon Redman's avatar Simon Redman
Browse files

[SMS App] Sms helper improvements

parent 4254b23d
Pipeline #19863 failed with stage
in 5 minutes and 16 seconds
......@@ -20,6 +20,7 @@ PUBLIC
Qt5::Core
Qt5::DBus
KF5::People
Qt5::Qml
kdeconnectinterfaces
)
......
......@@ -284,8 +284,3 @@ void ConversationListModel::createConversationForAddress(const QString& address)
item->setData(address, SenderRole);
appendRow(item);
}
bool ConversationListModel::isAddressValid(const QString& address)
{
return SmsHelper::isAddressValid(address);
}
......@@ -57,13 +57,6 @@ public:
Q_SCRIPTABLE void refresh();
/**
* This method ensurse whether the phone number format is valid or not
* TODO: This is here because I don't know how to make the QML call the smshelper directly
* but that is what should be happening!
*/
Q_INVOKABLE bool isAddressValid(const QString& address);
/**
* This method creates conversation with an arbitrary address
*/
......
......@@ -21,8 +21,6 @@
#include "conversationmodel.h"
#include <QClipboard>
#include <QGuiApplication>
#include <QLoggingCategory>
#include <KLocalizedString>
......@@ -112,17 +110,6 @@ void ConversationModel::requestMoreMessages(const quint32& howMany)
m_conversationsInterface->requestConversation(m_threadId, numMessages, numMessages + howMany);
}
QString ConversationModel::getTitleForAddresses(const QList<ConversationAddress>& addresses)
{
return SmsHelper::getTitleForAddresses(addresses);
}
void ConversationModel::copyToClipboard(const QString& message) const
{
// TODO: Remove this method as part of abstracting GUI elements to library
QGuiApplication::clipboard()->setText(message);
}
void ConversationModel::createRowFromMessage(const ConversationMessage& message, int pos)
{
if (message.threadID() != m_threadId) {
......
......@@ -66,19 +66,7 @@ public:
Q_INVOKABLE void sendReplyToConversation(const QString& message);
Q_INVOKABLE void sendMessageWithoutConversation(const QString& message, const QString& address);
Q_INVOKABLE void requestMoreMessages(const quint32& howMany = 10);
/**
* Convert a list of names into a single string suitable for display
* TODO: This is here because I don't know how to make the QML call the smshelper directly
* but that is what should be happening!
*/
Q_INVOKABLE QString getTitleForAddresses(const QList<ConversationAddress>& addresses);
/**
* This is the action invoked by the right-click menu to copy to the clipboard
* QML can't do this directly but this should be part of smshelper
* TODO: Move to smshelper (or maybe make part of kirigami-addons chat library?)
*/
Q_INVOKABLE void copyToClipboard(const QString& message) const;
Q_INVOKABLE QString getCharCountInfo(const QString& message) const;
Q_SIGNALS:
......
......@@ -33,6 +33,8 @@
#include <KLocalizedContext>
#include <KDBusService>
#include "smshelper.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
......@@ -67,6 +69,8 @@ int main(int argc, char *argv[])
qmlRegisterType<ConversationModel>("org.kde.kdeconnect.sms", 1, 0, "ConversationModel");
qmlRegisterType<ConversationListModel>("org.kde.kdeconnect.sms", 1, 0, "ConversationListModel");
qmlRegisterSingletonType<SmsHelper>("org.kde.kdeconnect.sms", 1, 0, "SmsHelper", SmsHelper::singletonProvider);
QQmlApplicationEngine engine;
engine.rootContext()->setContextObject(new KLocalizedContext(&engine));
engine.rootContext()->setContextProperties({
......
......@@ -60,7 +60,7 @@ RowLayout {
property bool isSpoiler
property string spoilerHint
property bool isShowingSpoiler: false
property string avatarUrl: null//kaidan.avatarStorage.getAvatarUrl(sender)
property string avatarUrl: ""
signal messageCopyRequested(string message)
......
......@@ -21,7 +21,7 @@
*/
import QtQuick 2.1
import QtQuick.Controls 2.2
import QtQuick.Controls 2.2 as Controls
import QtQuick.Layouts 1.1
import org.kde.people 1.0
import org.kde.kirigami 2.4 as Kirigami
......@@ -54,7 +54,7 @@ Kirigami.ScrollablePage
}
property var addresses
title: conversationModel.getTitleForAddresses(addresses)
title: SmsHelper.getTitleForAddresses(addresses)
Component.onCompleted: {
if (initialMessage.length > 0) {
......@@ -92,7 +92,7 @@ Kirigami.ScrollablePage
spacing: Kirigami.Units.largeSpacing
highlightMoveDuration: 0
BusyIndicator {
Controls.BusyIndicator {
running: !isInitalized
}
......@@ -151,7 +151,7 @@ Kirigami.ScrollablePage
}
onMessageCopyRequested: {
conversationModel.copyToClipboard(message)
SmsHelper.copyToClipboard(message)
}
}
......@@ -179,7 +179,7 @@ Kirigami.ScrollablePage
}
}
footer: Pane {
footer: Controls.Pane {
id: sendingArea
enabled: page.deviceConnected && !page.isMultitarget
layer.enabled: sendingArea.enabled
......@@ -199,14 +199,14 @@ Kirigami.ScrollablePage
RowLayout {
anchors.fill: parent
ScrollView {
Controls.ScrollView {
Layout.fillWidth: true
Layout.maximumHeight: page.height > 300 ? page.height / 3 : 2 * page.height / 3
contentWidth: page.width - sendButtonArea.width
clip: true
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
Controls.ScrollBar.horizontal.policy: Controls.ScrollBar.AlwaysOff
TextArea {
Controls.TextArea {
anchors.fill: parent
id: messageField
placeholderText: page.isMultitarget ? i18nd("kdeconnect-sms", "Replying to multitarget messages is not supported") : i18nd("kdeconnect-sms", "Compose message")
......@@ -227,11 +227,11 @@ Kirigami.ScrollablePage
}
}
}
ColumnLayout {
id: sendButtonArea
ToolButton {
Controls.ToolButton {
id: sendButton
Layout.preferredWidth: Kirigami.Units.gridUnit * 2
Layout.preferredHeight: Kirigami.Units.gridUnit * 2
......@@ -267,9 +267,8 @@ Kirigami.ScrollablePage
sendButton.enabled = true
}
}
Label {
Controls.Label {
id: "charCount"
text: conversationModel.getCharCountInfo(messageField.text)
visible: text.length > 0
......
......@@ -174,7 +174,7 @@ Kirigami.ScrollablePage
} else {
view.model.setConversationsFilterRole(ConversationListModel.ConversationIdRole)
}
view.model.setFilterFixedString(filter.text)
view.model.setFilterFixedString(SmsHelper.canonicalizePhoneNumber(filter.text))
view.currentIndex = 0
}
......@@ -199,7 +199,7 @@ Kirigami.ScrollablePage
id: newButton
text: i18nd("kdeconnect-sms", "New")
visible: true
enabled: conversationListModel.isAddressValid(filter.text) && deviceConnected
enabled: SmsHelper.isAddressValid(filter.text) && deviceConnected
ToolTip.visible: hovered
ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
ToolTip.text: i18nd("kdeconnect-sms", "Start new conversation")
......@@ -209,7 +209,7 @@ Kirigami.ScrollablePage
filter.enabled = false
// If the address entered by the user already exists then ignore adding new contact
if (!view.model.doesAddressExists(filter.text) && conversationListModel.isAddressValid(filter.text)) {
if (!view.model.doesAddressExists(filter.text) && smsHelper.isAddressValid(filter.text)) {
conversationListModel.createConversationForAddress(filter.text)
view.currentIndex = 0
}
......
......@@ -20,6 +20,8 @@
#include "smshelper.h"
#include <QClipboard>
#include <QGuiApplication>
#include <QIcon>
#include <QPainter>
#include <QRegularExpression>
......@@ -36,6 +38,14 @@
Q_LOGGING_CATEGORY(KDECONNECT_SMS_SMSHELPER, "kdeconnect.sms.smshelper")
QObject* SmsHelper::singletonProvider(QQmlEngine *engine, QJSEngine *scriptEngine)
{
Q_UNUSED(engine);
Q_UNUSED(scriptEngine);
return new SmsHelper();
}
bool SmsHelper::isPhoneNumberMatchCanonicalized(const QString& canonicalPhone1, const QString& canonicalPhone2)
{
if (canonicalPhone1.isEmpty() || canonicalPhone2.isEmpty()) {
......@@ -217,7 +227,8 @@ QSharedPointer<KPeople::PersonData> SmsHelper::lookupPersonByAddress(const QStri
return nullptr;
}
QIcon SmsHelper::combineIcons(const QList<QPixmap>& icons) {
QIcon SmsHelper::combineIcons(const QList<QPixmap>& icons)
{
QIcon icon;
if (icons.size() == 0) {
// We have no icon :(
......@@ -260,7 +271,8 @@ QIcon SmsHelper::combineIcons(const QList<QPixmap>& icons) {
return icon;
}
QString SmsHelper::getTitleForAddresses(const QList<ConversationAddress>& addresses) {
QString SmsHelper::getTitleForAddresses(const QList<ConversationAddress>& addresses)
{
QStringList titleParts;
for (const ConversationAddress& address : addresses) {
const auto personData = SmsHelper::lookupPersonByAddress(address.address());
......@@ -277,7 +289,8 @@ QString SmsHelper::getTitleForAddresses(const QList<ConversationAddress>& addres
return titleParts.join(QLatin1String(", "));
}
QIcon SmsHelper::getIconForAddresses(const QList<ConversationAddress>& addresses) {
QIcon SmsHelper::getIconForAddresses(const QList<ConversationAddress>& addresses)
{
QList<QPixmap> icons;
for (const ConversationAddress& address : addresses) {
const auto personData = SmsHelper::lookupPersonByAddress(address.address());
......@@ -295,6 +308,11 @@ QIcon SmsHelper::getIconForAddresses(const QList<ConversationAddress>& addresses
return combineIcons(icons);
}
void SmsHelper::copyToClipboard(const QString& text)
{
QGuiApplication::clipboard()->setText(text);
}
SmsCharCount SmsHelper::getCharCount(const QString& message)
{
const int remainingWhenEmpty = 160;
......
......@@ -22,10 +22,12 @@
#define SMSHELPER_H
#include <QIcon>
#include <QJSEngine>
#include <QLoggingCategory>
#include <QQmlEngine>
#include <QSharedPointer>
#include <KPeople/PersonData>
#include <QSharedPointer>
#include "interfaces/conversationmessage.h"
......@@ -36,9 +38,15 @@ Q_DECLARE_LOGGING_CATEGORY(KDECONNECT_SMS_SMSHELPER)
class PersonsCache;
class KDECONNECTSMSAPPLIB_EXPORT SmsHelper
class KDECONNECTSMSAPPLIB_EXPORT SmsHelper : public QObject
{
Q_OBJECT
public:
SmsHelper() = default;
~SmsHelper() = default;
static QObject* singletonProvider(QQmlEngine *engine, QJSEngine *scriptEngine);
enum CountryCode {
Australia,
CzechRepublic,
......@@ -48,19 +56,19 @@ public:
/**
* Return true to indicate the two phone numbers should be considered the same, false otherwise
*/
static bool isPhoneNumberMatch(const QString& phone1, const QString& phone2);
Q_INVOKABLE static bool isPhoneNumberMatch(const QString& phone1, const QString& phone2);
/**
* Return true to indicate the two phone numbers should be considered the same, false otherwise
* Requires canonicalized phone numbers as inputs
*/
static bool isPhoneNumberMatchCanonicalized(const QString& canonicalPhone1, const QString& canonicalPhone2);
Q_INVOKABLE static bool isPhoneNumberMatchCanonicalized(const QString& canonicalPhone1, const QString& canonicalPhone2);
/**
* See inline comments for how short codes are determined
* All information from https://en.wikipedia.org/wiki/Short_code
*/
static bool isShortCode(const QString& canonicalNumber, const CountryCode& country);
Q_INVOKABLE static bool isShortCode(const QString& canonicalNumber, const CountryCode& country);
/**
* Try to guess the country code from the passed number
......@@ -70,12 +78,12 @@ public:
/**
* Simplify a phone number to a known form
*/
static QString canonicalizePhoneNumber(const QString& phoneNumber);
Q_INVOKABLE static QString canonicalizePhoneNumber(const QString& phoneNumber);
/**
* Get the data for a particular person given their contact address
*/
static QSharedPointer<KPeople::PersonData> lookupPersonByAddress(const QString& address);
Q_INVOKABLE static QSharedPointer<KPeople::PersonData> lookupPersonByAddress(const QString& address);
/**
* Make an icon which combines the many icons
......@@ -86,14 +94,14 @@ public:
* If there are three, put one in the middle of the top and the remaining two in the bottom
* If there are four or more, put one in each corner (If more than four, some will be left out)
*/
static QIcon combineIcons(const QList<QPixmap>& icons);
Q_INVOKABLE static QIcon combineIcons(const QList<QPixmap>& icons);
/**
* Get a combination of all the addresses as a comma-separated list of:
* - The KPeople contact's name (if known)
* - The address (if the contact is not known)
*/
static QString getTitleForAddresses(const QList<ConversationAddress>& addresses);
Q_INVOKABLE static QString getTitleForAddresses(const QList<ConversationAddress>& addresses);
/**
* Get a combined icon for all contacts by finding:
......@@ -101,31 +109,33 @@ public:
* - A generic icon
* and then using SmsHelper::combineIcons
*/
static QIcon getIconForAddresses(const QList<ConversationAddress>& addresses);
Q_INVOKABLE static QIcon getIconForAddresses(const QList<ConversationAddress>& addresses);
/**
* Put the specified text into the system clipboard
*/
Q_INVOKABLE static void copyToClipboard(const QString& text);
/**
* Get the data for all persons currently stored on device
*/
static QList<QSharedPointer<KPeople::PersonData>> getAllPersons();
/**
* Get SMS character count status of SMS. It contains number of remaining characters
* in current SMS (automatically selects 7-bit, 8-bit or 16-bit mode), octet count and
* number of messages in concatenated SMS.
*/
static SmsCharCount getCharCount(const QString& message);
static bool isInGsmAlphabet(const QChar& ch);
static bool isInGsmAlphabetExtension(const QChar& ch);
Q_INVOKABLE static SmsCharCount getCharCount(const QString& message);
/**
* Used to validate arbitrary phone number entered by the user
*/
static bool isAddressValid(const QString& address);
Q_INVOKABLE static bool isAddressValid(const QString& address);
private:
SmsHelper(){};
~SmsHelper(){};
static bool isInGsmAlphabet(const QChar& ch);
static bool isInGsmAlphabetExtension(const QChar& ch);
};
#endif // SMSHELPER_H
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment