ContactsViewModel.cpp 6.86 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 19
/***************************************************************************
 * 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/>.   *
 **************************************************************************/
#include "pch.h"
20

atraczyk's avatar
atraczyk committed
21 22
#include "ContactsViewModel.h"

23
using namespace Windows::ApplicationModel::Core;
atraczyk's avatar
atraczyk committed
24 25
using namespace Windows::Data::Json;
using namespace Windows::Storage;
26 27 28
using namespace Windows::Storage::Streams;
using namespace Windows::UI::Core;

atraczyk's avatar
atraczyk committed
29 30 31 32 33 34 35 36

using namespace RingClientUWP;
using namespace ViewModel;

ContactsViewModel::ContactsViewModel()
{
    contactsList_ = ref new Vector<Contact^>();
    openContactsFromFile();
37 38 39 40 41 42 43 44 45

    /* connect delegates. */
    RingD::instance->incomingAccountMessage += ref new IncomingAccountMessage([&](String^ accountId,
    String^ from, String^ payload) {
        auto contact = findContactByName(from);

        if (contact == nullptr)
            contact = addNewContact(from, from); // contact checked inside addNewContact.

46 47
        bool isNotSelected = (contact != ContactsViewModel::instance->selectedContact) ? true : false;

48 49 50 51 52
        if (contact == nullptr) {
            ERR_("contact not handled!");
            return;
        }

53
        contact->_conversation->addMessage(""/* date not yet used*/, MSG_FROM_CONTACT, payload);
54

55 56 57
        /* save contacts conversation to disk */
        contact->saveConversationToFile();

58
        if (contact->ringID_ == from) {
59
            // increment contact's unread message count
60 61
            if(isNotSelected)
                contact->addNotifyNewConversationMessage();
62
            // update the xaml for all contacts
63
            notifyNewConversationMessage(isNotSelected);
64 65
            // save to disk
            saveContactsToFile();
66
        }
67
    });
atraczyk's avatar
atraczyk committed
68 69
}

70
Contact^ // refacto : remove "byName"
71
ContactsViewModel::findContactByName(String^ name)
atraczyk's avatar
atraczyk committed
72
{
73
    auto trimmedName = Utils::Trim(name);
atraczyk's avatar
atraczyk committed
74
    for each (Contact^ contact in contactsList_)
75
        if (contact->name_ == trimmedName)
atraczyk's avatar
atraczyk committed
76 77 78 79 80 81 82 83
            return contact;

    return nullptr;
}

Contact^
ContactsViewModel::addNewContact(String^ name, String^ ringId)
{
84 85 86
    auto trimmedName = Utils::Trim(name);
    if (contactsList_ && !findContactByName(trimmedName)) {
        Contact^ contact = ref new Contact(trimmedName, trimmedName, nullptr, 0);
atraczyk's avatar
atraczyk committed
87 88
        contactsList_->Append(contact);
        saveContactsToFile();
89
        contactAdded(contact);
atraczyk's avatar
atraczyk committed
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
        return contact;
    }

    return nullptr;
}

void
ContactsViewModel::saveContactsToFile()
{
    StorageFolder^ localfolder = ApplicationData::Current->LocalFolder;
    String^ contactsFile = ".profile\\contacts.json";

    try {
        create_task(localfolder->CreateFileAsync(contactsFile
                    , Windows::Storage::CreationCollisionOption::ReplaceExisting))
        .then([&](StorageFile^ newFile) {
            try {
                FileIO::WriteTextAsync(newFile, Stringify());
            }
            catch (Exception^ e) {
                RingDebug::instance->print("Exception while writing to contacts file");
            }
        });
    }
    catch (Exception^ e) {
        RingDebug::instance->print("Exception while opening contacts file");
    }
}

void
ContactsViewModel::openContactsFromFile()
{
    String^ contactsFile = ".profile\\contacts.json";

    Utils::fileExists(ApplicationData::Current->LocalFolder,
125 126
                      contactsFile)
    .then([this,contactsFile](bool contacts_file_exists)
atraczyk's avatar
atraczyk committed
127 128 129 130
    {
        if (contacts_file_exists) {
            try {
                create_task(ApplicationData::Current->LocalFolder->GetFileAsync(contactsFile))
131
                .then([this](StorageFile^ file)
atraczyk's avatar
atraczyk committed
132 133
                {
                    create_task(FileIO::ReadTextAsync(file))
134
                    .then([this](String^ fileContents) {
atraczyk's avatar
atraczyk committed
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
                        if (fileContents != nullptr)
                            Destringify(fileContents);
                    });
                });
            }
            catch (Exception^ e) {
                RingDebug::instance->print("Exception while opening contacts file");
            }
        }
    });
}

String^
ContactsViewModel::Stringify()
{
    JsonArray^ jsonArray = ref new JsonArray();

    for (unsigned int i = 0; i < contactsList_->Size; i++) {
        jsonArray->Append(contactsList_->GetAt(i)->ToJsonObject());
    }

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

    return jsonObject->Stringify();
}

void
ContactsViewModel::Destringify(String^ data)
{
165 166 167 168 169
    JsonObject^     jsonObject = JsonObject::Parse(data);
    String^         name;
    String^         ringid;
    String^         guid;
    unsigned int    unreadmessages;
atraczyk's avatar
atraczyk committed
170 171 172 173 174 175 176 177

    JsonArray^ contactlist = jsonObject->GetNamedArray(contactListKey, ref new JsonArray());
    for (unsigned int i = 0; i < contactlist->Size; i++) {
        IJsonValue^ contact = contactlist->GetAt(i);
        if (contact->ValueType == JsonValueType::Object) {
            JsonObject^ jsonContactObject = contact->GetObject();
            JsonObject^ contactObject = jsonContactObject->GetNamedObject(contactKey, nullptr);
            if (contactObject != nullptr) {
178 179 180 181
                name = contactObject->GetNamedString(nameKey);
                ringid = contactObject->GetNamedString(ringIDKey);
                guid = contactObject->GetNamedString(GUIDKey);
                unreadmessages = static_cast<uint16_t>(contactObject->GetNamedNumber(unreadMessagesKey));
atraczyk's avatar
atraczyk committed
182
            }
183 184 185
            auto contact = ref new Contact(name, ringid, guid, unreadmessages);
            contactsList_->Append(contact);
            contactAdded(contact);
atraczyk's avatar
atraczyk committed
186 187 188
        }
    }
}