Commit efcd75c6 authored by Ronan Abhamon's avatar Ronan Abhamon

feat(ui/views/App/MainWindow/ContactEdit): deal with sip address & urls errors

parent 4f0d4737
<?xml version="1.0" encoding="UTF-8"?>
<svg width="12px" height="10px" viewBox="0 0 12 10" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 40.3 (33839) - http://www.bohemiancoding.com/sketch -->
<title>chat_error</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="chat_error">
<polygon id="Path-1067" fill="#FF0000" points="6.05012213 3.64153152e-14 0 10 12 10"></polygon>
<path d="M6,6 L6,3.5" id="chat_message_delivered-copy-4" stroke="#FFFFFF" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"></path>
<ellipse id="Oval-24" fill="#FFFFFF" cx="6.03499979" cy="8.13500017" rx="0.834999979" ry="0.834999979"></ellipse>
</g>
</g>
</svg>
\ No newline at end of file
......@@ -144,11 +144,19 @@
</message>
<message>
<source>companiesInput</source>
<translation type="unfinished"></translation>
<translation>Company</translation>
</message>
<message>
<source>companies</source>
<translation type="unfinished"></translation>
<translation>COMPANIES</translation>
</message>
<message>
<source>save</source>
<translation>SAVE</translation>
</message>
<message>
<source>cancel</source>
<translation>CANCEL</translation>
</message>
</context>
<context>
......
......@@ -142,6 +142,14 @@
<source>companies</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>save</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>cancel</source>
<translation type="unfinished">ANNULER</translation>
</message>
</context>
<context>
<name>Contacts</name>
......
......@@ -58,6 +58,7 @@
<file>assets/images/fullscreen_hovered.svg</file>
<file>assets/images/fullscreen_normal.svg</file>
<file>assets/images/fullscreen_pressed.svg</file>
<file>assets/images/generic_error.svg</file>
<file>assets/images/hangup_hovered.svg</file>
<file>assets/images/hangup_normal.svg</file>
<file>assets/images/hangup_pressed.svg</file>
......
......@@ -154,7 +154,7 @@ QVariantList ContactModel::getSipAddresses () const {
return list;
}
void ContactModel::addSipAddress (const QString &sip_address) {
bool ContactModel::addSipAddress (const QString &sip_address) {
shared_ptr<linphone::Address> address =
CoreManager::getInstance()->getCore()->createAddress(
Utils::qStringToLinphoneString(sip_address)
......@@ -162,7 +162,7 @@ void ContactModel::addSipAddress (const QString &sip_address) {
if (!address) {
qWarning() << QStringLiteral("Unable to add invalid sip address: `%1`.").arg(sip_address);
return;
return false;
}
qInfo() << QStringLiteral("Add new sip address: `%1`.").arg(sip_address);
......@@ -172,9 +172,11 @@ void ContactModel::addSipAddress (const QString &sip_address) {
m_linphone_friend->done();
emit contactUpdated();
return true;
}
bool ContactModel::removeSipAddress (const QString &sip_address) {
void ContactModel::removeSipAddress (const QString &sip_address) {
list<shared_ptr<linphone::Address> > addresses = m_linphone_friend->getAddresses();
string match = Utils::qStringToLinphoneString(sip_address);
......@@ -188,13 +190,13 @@ bool ContactModel::removeSipAddress (const QString &sip_address) {
if (it == addresses.cend()) {
qWarning() << QStringLiteral("Unable to found sip address: `%1`.")
.arg(sip_address);
return false;
return;
}
if (addresses.size() == 1) {
qWarning() << QStringLiteral("Unable to remove the only existing sip address: `%1`.")
.arg(sip_address);
return false;
return;
}
qInfo() << QStringLiteral("Remove sip address: `%1`.").arg(sip_address);
......@@ -205,14 +207,16 @@ bool ContactModel::removeSipAddress (const QString &sip_address) {
emit contactUpdated();
return true;
return;
}
void ContactModel::updateSipAddress (const QString &old_sip_address, const QString &sip_address) {
if (old_sip_address == sip_address || !removeSipAddress(old_sip_address))
return;
bool ContactModel::updateSipAddress (const QString &old_sip_address, const QString &sip_address) {
if (old_sip_address == sip_address || !addSipAddress(sip_address))
return false;
removeSipAddress(old_sip_address);
addSipAddress(sip_address);
return true;
}
// -------------------------------------------------------------------
......@@ -241,13 +245,13 @@ void ContactModel::addCompany (const QString &company) {
emit contactUpdated();
}
bool ContactModel::removeCompany (const QString &company) {
void ContactModel::removeCompany (const QString &company) {
shared_ptr<belcard::BelCard> belCard = m_linphone_friend->getVcard()->getBelcard();
shared_ptr<belcard::BelCardRole> value = findBelCardValue(belCard->getRoles(), company);
if (!value) {
qWarning() << QStringLiteral("Unable to remove company: `%1`.").arg(company);
return false;
return;
}
qInfo() << QStringLiteral("Remove company: `%1`.").arg(company);
......@@ -257,15 +261,14 @@ bool ContactModel::removeCompany (const QString &company) {
m_linphone_friend->done();
emit contactUpdated();
return true;
}
void ContactModel::updateCompany (const QString &old_company, const QString &company) {
if (old_company == company || !removeCompany(old_company))
if (old_company == company)
return;
addCompany(company);
removeCompany(old_company);
}
// -------------------------------------------------------------------
......@@ -279,7 +282,7 @@ QVariantList ContactModel::getEmails () const {
return list;
}
void ContactModel::addEmail (const QString &email) {
bool ContactModel::addEmail (const QString &email) {
shared_ptr<belcard::BelCard> belCard = m_linphone_friend->getVcard()->getBelcard();
shared_ptr<belcard::BelCardEmail> value =
belcard::BelCardGeneric::create<belcard::BelCardEmail>();
......@@ -292,15 +295,18 @@ void ContactModel::addEmail (const QString &email) {
m_linphone_friend->done();
emit contactUpdated();
// TODO: Check if email is valid.
return true;
}
bool ContactModel::removeEmail (const QString &email) {
void ContactModel::removeEmail (const QString &email) {
shared_ptr<belcard::BelCard> belCard = m_linphone_friend->getVcard()->getBelcard();
shared_ptr<belcard::BelCardEmail> value = findBelCardValue(belCard->getEmails(), email);
if (!value) {
qWarning() << QStringLiteral("Unable to remove email: `%1`.").arg(email);
return false;
return;
}
qInfo() << QStringLiteral("Remove email: `%1`.").arg(email);
......@@ -310,15 +316,15 @@ bool ContactModel::removeEmail (const QString &email) {
m_linphone_friend->done();
emit contactUpdated();
return true;
}
void ContactModel::updateEmail (const QString &old_email, const QString &email) {
if (old_email == email || !removeEmail(old_email))
return;
bool ContactModel::updateEmail (const QString &old_email, const QString &email) {
if (old_email == email || !addEmail(email))
return false;
removeEmail(old_email);
addEmail(email);
return true;
}
// -------------------------------------------------------------------
......@@ -332,7 +338,7 @@ QVariantList ContactModel::getUrls () const {
return list;
}
void ContactModel::addUrl (const QString &url) {
bool ContactModel::addUrl (const QString &url) {
shared_ptr<belcard::BelCard> belCard = m_linphone_friend->getVcard()->getBelcard();
shared_ptr<belcard::BelCardURL> value =
belcard::BelCardGeneric::create<belcard::BelCardURL>();
......@@ -345,15 +351,18 @@ void ContactModel::addUrl (const QString &url) {
m_linphone_friend->done();
emit contactUpdated();
// TODO: Check if url is valid.
return true;
}
bool ContactModel::removeUrl (const QString &url) {
void ContactModel::removeUrl (const QString &url) {
shared_ptr<belcard::BelCard> belCard = m_linphone_friend->getVcard()->getBelcard();
shared_ptr<belcard::BelCardURL> value = findBelCardValue(belCard->getURLs(), url);
if (!value) {
qWarning() << QStringLiteral("Unable to remove url: `%1`.").arg(url);
return false;
return;
}
qInfo() << QStringLiteral("Remove url: `%1`.").arg(url);
......@@ -363,20 +372,25 @@ bool ContactModel::removeUrl (const QString &url) {
m_linphone_friend->done();
emit contactUpdated();
}
bool ContactModel::updateUrl (const QString &old_url, const QString &url) {
if (old_url == url || !addUrl(url))
return false;
removeUrl(old_url);
return true;
}
void ContactModel::updateUrl (const QString &old_url, const QString &url) {
if (old_url == url || !removeUrl(old_url))
return;
// -------------------------------------------------------------------
QVariantMap ContactModel::getAddress () const {
addUrl(url);
}
// -------------------------------------------------------------------
void ContactModel::setAddress (const QVariantMap &address) {
QList<QVariantMap> ContactModel::getAddresses () const {
}
......
......@@ -20,12 +20,7 @@ class ContactModel : public QObject {
Q_PROPERTY(QVariantList companies READ getCompanies NOTIFY contactUpdated);
Q_PROPERTY(QVariantList emails READ getEmails NOTIFY contactUpdated);
Q_PROPERTY(QVariantList urls READ getUrls NOTIFY contactUpdated);
Q_PROPERTY(
QList<QVariantMap> addresses
READ getAddresses
NOTIFY contactUpdated
);
Q_PROPERTY(QVariantMap address READ getAddress WRITE setAddress NOTIFY contactUpdated);
Q_PROPERTY(
Presence::PresenceStatus presenceStatus
......@@ -49,21 +44,21 @@ public:
ContactModel (std::shared_ptr<linphone::Friend> linphone_friend);
public slots:
void addSipAddress (const QString &sip_address);
bool removeSipAddress (const QString &sip_address);
void updateSipAddress (const QString &old_sip_address, const QString &sip_address);
bool addSipAddress (const QString &sip_address);
void removeSipAddress (const QString &sip_address);
bool updateSipAddress (const QString &old_sip_address, const QString &sip_address);
void addCompany (const QString &company);
bool removeCompany (const QString &company);
void removeCompany (const QString &company);
void updateCompany (const QString &old_company, const QString &company);
void addEmail (const QString &email);
bool removeEmail (const QString &email);
void updateEmail (const QString &old_email, const QString &email);
bool addEmail (const QString &email);
void removeEmail (const QString &email);
bool updateEmail (const QString &old_email, const QString &email);
void addUrl (const QString &url);
bool removeUrl (const QString &url);
void updateUrl (const QString &old_url, const QString &url);
bool addUrl (const QString &url);
void removeUrl (const QString &url);
bool updateUrl (const QString &old_url, const QString &url);
signals:
void contactUpdated ();
......@@ -80,12 +75,13 @@ private:
QVariantList getEmails () const;
QVariantList getUrls () const;
QList<QVariantMap> getAddresses () const;
void setAddresses (const QList<QVariantMap> &addresses);
QVariantMap getAddress () const;
void setAddress (const QVariantMap &address);
Presence::PresenceStatus getPresenceStatus () const;
Presence::PresenceLevel getPresenceLevel () const;
// TODO: Remove!!!
QString getSipAddress () const;
Presence::PresenceStatus m_presence_status = Presence::Offline;
......
......@@ -14,22 +14,31 @@ RowLayout {
property alias title: text.text
property var defaultData: []
signal changed (int id, string default_value, string new_value)
signal removed (int id, string value)
signal changed (int index, string default_value, string new_value)
signal removed (int index, string value)
// -----------------------------------------------------------------
function setInvalid (index, status) {
Utils.assert(
index >= 0 && index < values.model.count,
'Index ' + index + 'not exists.'
)
values.model.setProperty(index, '$isInvalid', status)
}
function setData (data) {
var model = values.model
model.clear()
data.forEach(function (data) {
model.append({ $value: data })
model.append({ $value: data, $isInvalid: false })
})
}
function _addValue (value) {
values.model.append({ $value: value })
values.model.append({ $value: value, $isInvalid: false })
if (value.length === 0) {
addButton.enabled = false
......@@ -46,7 +55,10 @@ RowLayout {
}
} else {
var default_value = values.model.get(index).$value
listForm.changed(index, default_value, text)
if (text !== default_value) {
listForm.changed(index, default_value, text)
}
}
addButton.enabled = true
......@@ -130,12 +142,14 @@ RowLayout {
implicitHeight: textInput.height
width: parent.width
TransparentTextInput {
TransparentTextInput {
id: textInput
isInvalid: $isInvalid
text: $value
width: parent.width
height: ListFormStyle.lineHeight
width: parent.width
onEditingFinished: _handleEditionFinished(index, text)
}
......
......@@ -12,6 +12,7 @@ Item {
property alias font: textInput.font
property alias readOnly: textInput.readOnly
property alias text: textInput.text
property bool isInvalid: false
property int padding: TransparentTextInputStyle.padding
signal editingFinished
......@@ -25,6 +26,8 @@ Item {
}
Rectangle {
id: background
color: textInput.activeFocus && !textInput.readOnly
? TransparentTextInputStyle.backgroundColor
: // No Style constant, see component name.
......@@ -44,6 +47,16 @@ Item {
}
}
Icon {
id: icon
anchors.left: background.right
height: background.height
icon: 'generic_error'
iconSize: 12
visible: parent.isInvalid
}
TextInput {
id: textInput
......
......@@ -8,7 +8,7 @@ Item {
property bool _connected: false
function connect (emitter, signalName, handler) {
Utils.assert(!_connected, 'Smart connect is already connected!')
Utils.assert(!_connected, 'SmartConnect is already connected!')
emitter[signalName].connect(handler)
_connected = true
......
......@@ -74,6 +74,13 @@ function encodeTextToQmlRichFormat (text, options) {
return images.concat('<p>' + text + '</p>')
}
function extractFirstUri (str) {
var res = str.match(UriTools.URI_REGEX)
return res == null || startsWith(res[0], 'www')
? undefined
: res[0]
}
// -------------------------------------------------------------------
// Returns the top (root) parent of one object.
......
......@@ -49,6 +49,39 @@ ColumnLayout {
}
}
function _handleSipAddressChanged (index, default_value, new_value) {
if (!Utils.startsWith(new_value, 'sip:')) {
new_value = 'sip:' + new_value
if (new_value === default_value) {
return
}
}
var so_far_so_good = (default_value.length === 0)
? _contact.addSipAddress(new_value)
: _contact.updateSipAddress(default_value, new_value)
if (!so_far_so_good) {
addresses.setInvalid(index, true)
}
}
function _handleUrlChanged (index, default_value, new_value) {
var url = Utils.extractFirstUri(new_value)
if (url === default_value) {
return
}
var so_far_so_good = (default_value.length === 0)
? url && _contact.addUrl(new_value)
: url && _contact.updateUrl(default_value, new_value)
if (!so_far_so_good) {
urls.setInvalid(index, true)
}
}
// -----------------------------------------------------------------
spacing: 0
......@@ -168,13 +201,9 @@ ColumnLayout {
boundsBehavior: Flickable.StopAtBounds
clip: true
contentHeight: infoList.height
contentWidth: width - ScrollBar.vertical.width - leftMargin - rightMargin
contentWidth: width - ScrollBar.vertical.width
flickableDirection: Flickable.VerticalFlick
leftMargin: ContactEditStyle.values.leftMargin
rightMargin: ContactEditStyle.values.rightMargin
topMargin: ContactEditStyle.values.topMargin
ColumnLayout {
id: infoList
......@@ -187,19 +216,30 @@ ColumnLayout {
ListForm {
id: addresses
Layout.leftMargin: ContactEditStyle.values.leftMargin
Layout.rightMargin: ContactEditStyle.values.rightMargin
Layout.topMargin: ContactEditStyle.values.topMargin
defaultData: _contact.sipAddresses
placeholder: qsTr('sipAccountsInput')
title: qsTr('sipAccounts')
onChanged: default_value.length === 0
? _contact.addSipAddress(new_value)
: _contact.updateSipAddress(default_value, new_value)
onChanged: _handleSipAddressChanged(index, default_value, new_value)
onRemoved: _contact.removeSipAddress(value)
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: ContactEditStyle.values.separator.height
color: ContactEditStyle.values.separator.color
}
ListForm {
id: companies
Layout.leftMargin: ContactEditStyle.values.leftMargin
Layout.rightMargin: ContactEditStyle.values.rightMargin
defaultData: _contact.companies
placeholder: qsTr('companiesInput')
title: qsTr('companies')
......@@ -210,9 +250,18 @@ ColumnLayout {
onRemoved: _contact.removeCompany(value)
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: ContactEditStyle.values.separator.height
color: ContactEditStyle.values.separator.color
}
ListForm {
id: emails
Layout.leftMargin: ContactEditStyle.values.leftMargin
Layout.rightMargin: ContactEditStyle.values.rightMargin
defaultData: _contact.emails
placeholder: qsTr('emailsInput')
title: qsTr('emails')
......@@ -223,23 +272,52 @@ ColumnLayout {
onRemoved: _contact.removeEmail(value)
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: ContactEditStyle.values.separator.height
color: ContactEditStyle.values.separator.color
}
ListForm {
id: urls
Layout.leftMargin: ContactEditStyle.values.leftMargin
Layout.rightMargin: ContactEditStyle.values.rightMargin
defaultData: _contact.urls
placeholder: qsTr('webSitesInput')
title: qsTr('webSites')
onChanged: default_value.length === 0
? _contact.addUrl(new_value)
: _contact.updateUrl(default_value, new_value)
onChanged: _handleUrlChanged(index, default_value, new_value)
onRemoved: _contact.removeUrl(value)
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: ContactEditStyle.values.separator.height
color: ContactEditStyle.values.separator.color
}
Loader {
Layout.alignment: Qt.AlignHCenter
Layout.topMargin: ContactEditStyle.buttons.topMargin
sourceComponent: Row {
spacing: ContactEditStyle.buttons.spacing
TextButtonB {
text: qsTr('save')
}
TextButtonA {
text: qsTr('cancel')
}
}
}
Item {
Layout.bottomMargin: ContactEditStyle.values.bottomMargin
}
}
}
}
/* ListForm { */
/* title: qsTr('address') */
/* placeholder: qsTr('addressInput') */
/* } */
......@@ -25,9 +25,20 @@ QtObject {
}
}
property QtObject buttons: QtObject {
property int spacing: 20
property int topMargin: 20
}
property QtObject values: QtObject {
property int bottomMargin: 20
property int leftMargin: 40
property int rightMargin: 20
property int topMargin: 40
property int topMargin: 20
property QtObject separator: QtObject {
property color color: '#E8E8E8'
property int height: 1
}
}
}
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