Contact.cpp 8.58 KB
Newer Older
Nicolas Jager's avatar
Nicolas Jager committed
1 2 3
/**************************************************************************
* Copyright (C) 2016 by Savoir-faire Linux                                *
* Author: Jger Nicolas <nicolas.jager@savoirfairelinux.com>              *
4
* Author: Traczyk Andreas <traczyk.andreas@savoirfairelinux.com>          *
Nicolas Jager's avatar
Nicolas Jager committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
*                                                                         *
* 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"

#include "Contact.h"

23
#include <ObjBase.h> // for CoCreateGuid
24

25
#include "fileutils.h"
Nicolas Jager's avatar
Nicolas Jager committed
26
#include "direct.h"
27

Nicolas Jager's avatar
Nicolas Jager committed
28 29
using namespace Windows::ApplicationModel::Core;
using namespace Platform;
30
using namespace Windows::Data::Json;
Nicolas Jager's avatar
Nicolas Jager committed
31 32 33
using namespace Windows::UI::Core;

using namespace RingClientUWP;
34
using namespace ViewModel;
Nicolas Jager's avatar
Nicolas Jager committed
35

36 37 38 39
Contact::Contact(   String^ accountId,
                    String^ name,
                    String^ ringID,
                    String^ GUID,
40 41 42 43 44
                    uint32 unreadmessages,
                    ContactStatus contactStatus,
                    TrustStatus trustStatus,
                    bool isIncognitoContact,
                    String^ avatarColorString)
Nicolas Jager's avatar
Nicolas Jager committed
45
{
46
    vCard_ = ref new VCardUtils::VCard(this, accountId);
47

48
    name_   = name;
Nicolas Jager's avatar
Nicolas Jager committed
49
    ringID_ = ringID;
50 51 52 53 54
    GUID_   = GUID;

    if (GUID_ == nullptr)
        GUID_ = Utils::GetNewGUID();

55
    conversation_ = ref new Conversation();
56
    create_task([this]() { loadConversation(); });
57

58
    notificationNewMessage_ = Windows::UI::Xaml::Visibility::Collapsed;
59
    unreadMessages_ = unreadmessages;
60 61 62

    if(unreadMessages_) {
        notificationNewMessage = Windows::UI::Xaml::Visibility::Visible;
63
        NotifyPropertyChanged("unreadMessages");
64
    }
65

66
    _accountIdAssociated = accountId;
atraczyk's avatar
atraczyk committed
67
    _vcardUID = "";
68 69
    _avatarImage = ref new String(L" ");
    _avatarColorString = avatarColorString;
atraczyk's avatar
atraczyk committed
70
    _displayName = "";
Nicolas Jager's avatar
Nicolas Jager committed
71 72

    contactStatus_ = contactStatus;
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
    trustStatus_ = trustStatus;

    unreadContactRequest_ = trustStatus == TrustStatus::INCOMING_CONTACT_REQUEST ? true : false;

    lastTime_ = ResourceMananger::instance->getStringResource("m_never_called_");

    _isIncognitoContact = isIncognitoContact;
    presenceStatus_ = -1;
    subscribed_ = false;
}

void
Contact::loadConversation()
{
    // load conversation from disk
    StorageFolder^ localfolder = ApplicationData::Current->LocalFolder;
    String^ messagesFile = localfolder->Path + "\\" + ".messages\\" + GUID_ + ".json";

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

    CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(CoreDispatcherPriority::High,
        ref new DispatchedHandler([=]() {
        if (fileContents != nullptr)
            DestringifyConversation(fileContents);
    }));
98 99
}

Nicolas Jager's avatar
Nicolas Jager committed
100 101 102 103 104
void
Contact::NotifyPropertyChanged(String^ propertyName)
{
    CoreApplicationView^ view = CoreApplication::MainView;
    view->CoreWindow->Dispatcher->RunAsync(
105
        CoreDispatcherPriority::High,
Nicolas Jager's avatar
Nicolas Jager committed
106 107 108 109
        ref new DispatchedHandler([this, propertyName]()
    {
        PropertyChanged(this, ref new PropertyChangedEventArgs(propertyName));
    }));
110 111 112 113 114 115 116
}

JsonObject^
Contact::ToJsonObject()
{
    JsonObject^ contactObject = ref new JsonObject();
    contactObject->SetNamedValue(nameKey, JsonValue::CreateStringValue(name_));
atraczyk's avatar
atraczyk committed
117
    contactObject->SetNamedValue(displayNameKey, JsonValue::CreateStringValue(displayName_));
118
    contactObject->SetNamedValue(ringIDKey, JsonValue::CreateStringValue(ringID_));
119
    contactObject->SetNamedValue(GUIDKey, JsonValue::CreateStringValue(GUID_));
120
    contactObject->SetNamedValue(unreadMessagesKey, JsonValue::CreateNumberValue(unreadMessages_));
121
    contactObject->SetNamedValue(unreadContactRequestKey, JsonValue::CreateBooleanValue(unreadContactRequest_));
122
    contactObject->SetNamedValue(accountIdAssociatedKey, JsonValue::CreateStringValue(_accountIdAssociated));
atraczyk's avatar
atraczyk committed
123
    contactObject->SetNamedValue(vcardUIDKey, JsonValue::CreateStringValue(_vcardUID));
124
    contactObject->SetNamedValue(lastTimeKey, JsonValue::CreateStringValue(_lastTime));
125 126 127
    contactObject->SetNamedValue(trustStatusKey, JsonValue::CreateNumberValue(Utils::toUnderlyingValue(trustStatus_)));
    contactObject->SetNamedValue(isIncognitoContactKey, JsonValue::CreateBooleanValue(_isIncognitoContact));
    contactObject->SetNamedValue(avatarColorStringKey, JsonValue::CreateStringValue(avatarColorString_));
128 129 130 131 132 133

    JsonObject^ jsonObject = ref new JsonObject();
    jsonObject->SetNamedValue(contactKey, contactObject);

    return jsonObject;
}
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155

String^
Contact::StringifyConversation()
{
    JsonArray^ jsonArray = ref new JsonArray();

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

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

    return jsonObject->Stringify();
}

void
Contact::DestringifyConversation(String^ data)
{
    JsonObject^ jsonObject = JsonObject::Parse(data);
    bool        fromContact;
    String^     payload;
156 157 158
    std::time_t timeReceived;
    bool        isReceived;
    String^     messageIdStr;
159 160 161 162 163 164 165 166

    JsonArray^ messageList = jsonObject->GetNamedArray(conversationKey, ref new JsonArray());
    for (unsigned int i = 0; i < messageList->Size; i++) {
        IJsonValue^ message = messageList->GetAt(i);
        if (message->ValueType == JsonValueType::Object) {
            JsonObject^ jsonMessageObject = message->GetObject();
            JsonObject^ messageObject = jsonMessageObject->GetNamedObject(messageKey, nullptr);
            if (messageObject != nullptr) {
167 168 169 170 171 172 173 174 175 176
                if (messageObject->HasKey(fromContactKey))
                    fromContact = messageObject->GetNamedBoolean(fromContactKey);
                if (messageObject->HasKey(payloadKey))
                    payload = messageObject->GetNamedString(payloadKey);
                if (messageObject->HasKey(timeReceivedKey))
                    timeReceived = static_cast<std::time_t>(messageObject->GetNamedNumber(timeReceivedKey));
                if (messageObject->HasKey(isReceivedKey))
                    isReceived = messageObject->GetNamedBoolean(isReceivedKey);
                if (messageObject->HasKey(messageIdKey))
                    messageIdStr = messageObject->GetNamedString(messageIdKey);
177
            }
178
            conversation_->addMessage(fromContact, payload, timeReceived, isReceived, messageIdStr);
179 180 181 182
        }
    }
}

183 184
void
Contact::deleteConversationFile()
185 186 187 188 189 190 191 192 193 194 195 196
{
    StorageFolder^ localfolder = ApplicationData::Current->LocalFolder;
    String^ messagesFile = ".messages\\" + GUID_ + ".json";

    // refacto : Utils::fileExists fails here if the file doesn't exist, code below should replace fileExist everywhere
    create_task(localfolder->TryGetItemAsync(messagesFile)).then([](IStorageItem^ storageFile) {
        if (storageFile)
            storageFile->DeleteAsync();
    });

}

197 198 199 200
void
Contact::saveConversationToFile()
{
    StorageFolder^ localfolder = ApplicationData::Current->LocalFolder;
201 202
    String^ messagesFile = localfolder->Path + "\\" + ".messages\\" + GUID_ + ".json";

Nicolas Jager's avatar
Nicolas Jager committed
203
    if (_mkdir(Utils::toString(localfolder->Path + "\\" + ".messages\\").c_str())) {
204
        std::ofstream file(Utils::toString(messagesFile).c_str());
205
        if (file.is_open()) {
206 207 208
            file << Utils::toString(StringifyConversation());
            file.close();
        }
209
    }
Nicolas Jager's avatar
Nicolas Jager committed
210 211
}

212 213 214 215
VCardUtils::VCard^
Contact::getVCard()
{
    return vCard_;
216 217 218
}

void
219
Contact::raiseNotifyPropertyChanged(String^ propertyName)
220 221
{
    NotifyPropertyChanged(propertyName);
222
}