ContactListModel.cpp 11.5 KB
Newer Older
atraczyk's avatar
atraczyk committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/***************************************************************************
 * Copyright (C) 2016 by Savoir-faire Linux                                *
 * Author: Jäger Nicolas <nicolas.jager@savoirfairelinux.com>              *
 * Author: Traczyk Andreas <andreas.traczyk@savoirfairelinux.com>          *
 *                                                                         *
 * This program 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.                                     *
 *                                                                         *
 * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.   *
 **************************************************************************/
19

20 21
#include "pch.h"
#include "ContactListModel.h"
atraczyk's avatar
atraczyk committed
22

23
#include "fileutils.h"
24
#include "presencemanager_interface.h"
25

26
using namespace Windows::ApplicationModel::Core;
atraczyk's avatar
atraczyk committed
27 28
using namespace Windows::Data::Json;
using namespace Windows::Storage;
29 30 31
using namespace Windows::Storage::Streams;
using namespace Windows::UI::Core;

atraczyk's avatar
atraczyk committed
32 33 34
using namespace RingClientUWP;
using namespace ViewModel;

35
ContactListModel::ContactListModel(String^ account) : m_Owner(account)
atraczyk's avatar
atraczyk committed
36 37 38
{
    contactsList_ = ref new Vector<Contact^>();
    openContactsFromFile();
39 40

    /* connect delegates. */
41 42
    RingD::instance->registeredNameFound +=
        ref new RingClientUWP::RegisteredNameFound(this, &ContactListModel::OnregisteredNameFound);
atraczyk's avatar
atraczyk committed
43 44
}

45
Contact^ // refacto : remove "byName"
46
ContactListModel::findContactByName(String^ name)
atraczyk's avatar
atraczyk committed
47
{
48
    auto trimmedName = Utils::Trim(name);
atraczyk's avatar
atraczyk committed
49
    for each (Contact^ contact in contactsList_)
Nicolas Jager's avatar
Nicolas Jager committed
50
        if (contact->_name == trimmedName)
atraczyk's avatar
atraczyk committed
51 52 53 54 55
            return contact;

    return nullptr;
}

56 57
Contact^
ContactListModel::findContactByRingId(String^ ringId)
58 59 60 61 62 63 64 65
{
    for each (Contact^ contact in contactsList_)
        if (contact->ringID_ == ringId)
            return contact;

    return nullptr;
}

atraczyk's avatar
atraczyk committed
66
Contact^
67
ContactListModel::addNewContact(String^ name, String^ ringId, TrustStatus trustStatus, bool isIncognitoContact, ContactStatus contactStatus)
atraczyk's avatar
atraczyk committed
68
{
69 70
    auto trimmedName = Utils::Trim(name);
    if (contactsList_ && !findContactByName(trimmedName)) {
71 72 73 74 75 76 77 78 79 80 81 82 83
        String^ avatarColorString = Utils::getRandomColorString();
        if (auto acc = AccountsViewModel::instance->findItem(m_Owner)) {
            if (acc->accountType_ == "RING") {
                if (ringId)
                    avatarColorString = Utils::getRandomColorStringFromString(ringId);
                else
                    avatarColorString = Utils::getRandomColorStringFromString(name);
            }
            else if (name != "") {
                avatarColorString = Utils::getRandomColorStringFromString(name);
            }
        }
        Contact^ contact = ref new Contact(m_Owner, trimmedName, ringId, nullptr, 0, contactStatus, trustStatus, isIncognitoContact, avatarColorString);
atraczyk's avatar
atraczyk committed
84 85
        contactsList_->Append(contact);
        saveContactsToFile();
86
        AccountsViewModel::instance->raiseContactAdded(m_Owner, contact);
atraczyk's avatar
atraczyk committed
87 88 89 90 91 92 93
        return contact;
    }

    return nullptr;
}

void
94
ContactListModel::saveContactsToFile()
atraczyk's avatar
atraczyk committed
95 96
{
    StorageFolder^ localfolder = ApplicationData::Current->LocalFolder;
97
    String^ contactsFile = localfolder->Path + "\\" + ".profile\\" + m_Owner + "\\contacts.json";
98

99
    if (ring::fileutils::recursive_mkdir(Utils::toString(localfolder->Path + "\\" + ".profile\\" + m_Owner).c_str())) {
100 101 102 103 104 105
        std::ofstream file(Utils::toString(contactsFile).c_str());
        if (file.is_open())
        {
            file << Utils::toString(Stringify());
            file.close();
        }
atraczyk's avatar
atraczyk committed
106 107 108 109
    }
}

void
110
ContactListModel::openContactsFromFile()
atraczyk's avatar
atraczyk committed
111
{
112
    StorageFolder^ localfolder = ApplicationData::Current->LocalFolder;
113
    String^ contactsFile = localfolder->Path + "\\" + ".profile\\" + m_Owner + "\\contacts.json";
114 115 116

    String^ fileContents = Utils::toPlatformString(Utils::getStringFromFile(Utils::toString(contactsFile)));

117
    CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(CoreDispatcherPriority::High,
118 119 120 121
    ref new DispatchedHandler([=]() {
        if (fileContents != nullptr)
            Destringify(fileContents);
    }));
atraczyk's avatar
atraczyk committed
122 123 124
}

String^
125
ContactListModel::Stringify()
atraczyk's avatar
atraczyk committed
126 127 128
{
    JsonArray^ jsonArray = ref new JsonArray();

atraczyk's avatar
atraczyk committed
129
    for (int i = contactsList_->Size - 1; i >= 0; i--) {
atraczyk's avatar
atraczyk committed
130 131 132 133 134 135 136 137 138 139
        jsonArray->Append(contactsList_->GetAt(i)->ToJsonObject());
    }

    JsonObject^ jsonObject = ref new JsonObject();
    jsonObject->SetNamedValue(contactListKey, jsonArray);

    return jsonObject->Stringify();
}

void
140
ContactListModel::Destringify(String^ data)
atraczyk's avatar
atraczyk committed
141
{
142
    JsonObject^     jsonObject = JsonObject::Parse(data);
143 144 145 146 147 148 149 150 151 152 153 154
    String^         name = "";
    String^         displayname = "";
    String^         ringid = "";
    String^         guid = "";
    uint32          unreadMessages = 0;
    String^         accountIdAssociated = "";
    String^         vcardUID = "";
    String^         lastTime = "";
    uint8           trustStatus = Utils::toUnderlyingValue(TrustStatus::TRUSTED);
    bool            unreadContactRequest = false;
    bool            isIncognitoContact = false;
    String^         avatarColorString;
atraczyk's avatar
atraczyk committed
155 156

    JsonArray^ contactlist = jsonObject->GetNamedArray(contactListKey, ref new JsonArray());
atraczyk's avatar
atraczyk committed
157
    for (int i = contactlist->Size - 1; i >= 0; i--) {
atraczyk's avatar
atraczyk committed
158 159 160 161 162
        IJsonValue^ contact = contactlist->GetAt(i);
        if (contact->ValueType == JsonValueType::Object) {
            JsonObject^ jsonContactObject = contact->GetObject();
            JsonObject^ contactObject = jsonContactObject->GetNamedObject(contactKey, nullptr);
            if (contactObject != nullptr) {
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
                if (contactObject->HasKey(nameKey))
                    name = contactObject->GetNamedString(nameKey);
                if (contactObject->HasKey(displayNameKey))
                    displayname = contactObject->GetNamedString(displayNameKey);
                if (contactObject->HasKey(ringIDKey))
                    ringid = contactObject->GetNamedString(ringIDKey);
                if (contactObject->HasKey(GUIDKey))
                    guid = contactObject->GetNamedString(GUIDKey);
                if (contactObject->HasKey(unreadMessagesKey))
                    unreadMessages = static_cast<uint32>(contactObject->GetNamedNumber(unreadMessagesKey));
                if (contactObject->HasKey(unreadContactRequestKey))
                    unreadContactRequest = contactObject->GetNamedBoolean(unreadContactRequestKey);
                if (contactObject->HasKey(accountIdAssociatedKey))
                    accountIdAssociated = contactObject->GetNamedString(accountIdAssociatedKey);
                if (contactObject->HasKey(vcardUIDKey))
                    vcardUID = contactObject->GetNamedString(vcardUIDKey);
179 180
                if (contactObject->HasKey(lastTimeKey))
                    lastTime = contactObject->GetNamedString(lastTimeKey);
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
                if (contactObject->HasKey(trustStatusKey))
                    trustStatus = static_cast<uint8>(contactObject->GetNamedNumber(trustStatusKey));
                if (contactObject->HasKey(isIncognitoContactKey))
                    isIncognitoContact = contactObject->GetNamedBoolean(isIncognitoContactKey);
                if (contactObject->HasKey(avatarColorStringKey)) {
                    auto oldColorString = contactObject->GetNamedString(avatarColorStringKey);
                    if (oldColorString != "") {
                        avatarColorString = oldColorString;
                    }
                    else {
                        if (auto acc = AccountsViewModel::instance->findItem(m_Owner)) {
                            if (acc->accountType_ == "RING") {
                                avatarColorString = Utils::getRandomColorStringFromString(ringid);
                            }
                            else if (name != "") {
                                avatarColorString = Utils::getRandomColorStringFromString(name);
                            }
                            else {
                                avatarColorString = Utils::getRandomColorString();
                            }
                        }
                        else
                            avatarColorString = Utils::getRandomColorString();
                    }
                }
atraczyk's avatar
atraczyk committed
206
            }
207 208 209 210 211 212 213 214 215 216
            auto contact = ref new Contact( m_Owner,
                                            name,
                                            ringid,
                                            guid,
                                            unreadMessages,
                                            ContactStatus::READY,
                                            Utils::toEnum<TrustStatus>(trustStatus),
                                            isIncognitoContact,
                                            avatarColorString);
            contact->_unreadContactRequest = unreadContactRequest;
atraczyk's avatar
atraczyk committed
217
            contact->_displayName = displayname;
218
            contact->_accountIdAssociated = accountIdAssociated;
atraczyk's avatar
atraczyk committed
219 220
            // contact image
            contact->_vcardUID = vcardUID;
221 222 223
            if (lastTime)
                contact->_lastTime = lastTime;

224 225 226
            std::string vcardDir = RingD::instance->getLocalFolder() + ".vcards\\";
            std::string pngFile = Utils::toString(contact->_vcardUID) + ".png";
            std::string contactImageFile = vcardDir + pngFile;
atraczyk's avatar
atraczyk committed
227
            if (Utils::fileExists(contactImageFile)) {
228
                //RingClientUWP::ResourceMananger::instance->preloadImage(Utils::toPlatformString(contactImageFile));
atraczyk's avatar
atraczyk committed
229 230
                contact->_avatarImage = Utils::toPlatformString(contactImageFile);
            }
231
            contactsList_->Append(contact);
232
            AccountsViewModel::instance->raiseContactAdded(m_Owner, contact);
atraczyk's avatar
atraczyk committed
233 234 235
        }
    }
}
236

237 238
void
ContactListModel::deleteContact(Contact ^ contact)
239 240 241 242 243
{
    unsigned int index;

    if (contactsList_->IndexOf(contact, &index)) {
        contact->deleteConversationFile();
244 245 246
        RingD::instance->removeContact(
            Utils::toString(contact->_accountIdAssociated),
            Utils::toString(contact->ringID_));
247 248 249 250 251 252
        contactsList_->RemoveAt(index);
    }

    saveContactsToFile();
}

atraczyk's avatar
atraczyk committed
253
void
254
ContactListModel::modifyContact(Contact^ contact)
atraczyk's avatar
atraczyk committed
255
{
256
    AccountsViewModel::instance->raiseContactDataModified(m_Owner, contact);
Nicolas Jager's avatar
Nicolas Jager committed
257 258
}

259
void
260
ContactListModel::OnregisteredNameFound(RingClientUWP::LookupStatus status,  const std::string& accountId, const std::string &address, const std::string &name)
Nicolas Jager's avatar
Nicolas Jager committed
261 262
{
    if (status == LookupStatus::SUCCESS) {
263
        for each (Contact^ contact in contactsList_) {
Nicolas Jager's avatar
Nicolas Jager committed
264 265 266 267
            if (contact->ringID_ == Utils::toPlatformString(address)) {
                contact->_name = Utils::toPlatformString(name);
                saveContactsToFile();
            }
268
        }
Nicolas Jager's avatar
Nicolas Jager committed
269 270
    }
}