filesystem: change file saving and opening to blocking functions

- changes the file loading and saving for contacts, messages, and
  preferences files, from the UWP API's async file functions to c++
  standard fstream functions

Change-Id: If8ccf4d276573474fd34091deb8785accec5113c
Tuleap: #1051
diff --git a/Contact.cpp b/Contact.cpp
index e252bbb..fd463af 100644
--- a/Contact.cpp
+++ b/Contact.cpp
@@ -22,6 +22,8 @@
 

 #include "ObjBase.h" // for CoCreateGuid

 

+#include "fileutils.h"

+

 using namespace Windows::ApplicationModel::Core;

 using namespace Platform;

 using namespace Windows::Data::Json;

@@ -42,31 +44,19 @@
     if (GUID_ == nullptr)

         GUID_ = Utils::GetNewGUID();

 

-    // load conversation from disk

     conversation_ = ref new Conversation();

+

+    // load conversation from disk

     StorageFolder^ localfolder = ApplicationData::Current->LocalFolder;

-    String^ messagesFile = ".messages\\" + GUID_ + ".json";

-    Utils::fileExists(ApplicationData::Current->LocalFolder,

-                      messagesFile)

-    .then([this,messagesFile](bool messages_file_exists)

-    {

-        if (messages_file_exists) {

-            try {

-                create_task(ApplicationData::Current->LocalFolder->GetFileAsync(messagesFile))

-                .then([this](StorageFile^ file)

-                {

-                    create_task(FileIO::ReadTextAsync(file))

-                    .then([this](String^ fileContents) {

-                        if (fileContents != nullptr)

-                            DestringifyConversation(fileContents);

-                    });

-                });

-            }

-            catch (Exception^ e) {

-                RingDebug::instance->print("Exception while opening messages file");

-            }

-        }

-    });

+    String^ messagesFile = localfolder->Path + "\\" + ".messages\\" + GUID_ + ".json";

+

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

+

+    CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(CoreDispatcherPriority::Normal,

+    ref new DispatchedHandler([=]() {

+        if (fileContents != nullptr)

+            DestringifyConversation(fileContents);

+    }));

 

     notificationNewMessage_ = Windows::UI::Xaml::Visibility::Collapsed;

     unreadMessages_ = unreadmessages;

@@ -169,21 +159,14 @@
 Contact::saveConversationToFile()

 {

     StorageFolder^ localfolder = ApplicationData::Current->LocalFolder;

-    String^ messagesFile = ".messages\\" + GUID_ + ".json";

+    String^ messagesFile = localfolder->Path + "\\" + ".messages\\" + GUID_ + ".json";

 

-    try {

-        create_task(localfolder->CreateFileAsync(messagesFile

-                    , Windows::Storage::CreationCollisionOption::ReplaceExisting))

-        .then([&](StorageFile^ file) {

-            try {

-                FileIO::WriteTextAsync(file, StringifyConversation());

-            }

-            catch (Exception^ e) {

-                RingDebug::instance->print("Exception while writing to conversation file");

-            }

-        });

-    }

-    catch (Exception^ e) {

-        RingDebug::instance->print("Exception while opening conversation file");

+    if (ring::fileutils::recursive_mkdir(Utils::toString(localfolder->Path + "\\" + ".messages\\").c_str())) {

+        std::ofstream file(Utils::toString(messagesFile).c_str());

+        if (file.is_open())

+        {

+            file << Utils::toString(StringifyConversation());

+            file.close();

+        }

     }

 }
\ No newline at end of file
diff --git a/ContactsViewModel.cpp b/ContactsViewModel.cpp
index 45cae66..e49ea1c 100644
--- a/ContactsViewModel.cpp
+++ b/ContactsViewModel.cpp
@@ -20,6 +20,8 @@
 

 #include "ContactsViewModel.h"

 

+#include "fileutils.h"

+

 using namespace Windows::ApplicationModel::Core;

 using namespace Windows::Data::Json;

 using namespace Windows::Storage;

@@ -57,12 +59,13 @@
 

         if (contact->ringID_ == from) {

             // increment contact's unread message count

-            if(isNotSelected)

+            if (isNotSelected) {

                 contact->addNotifyNewConversationMessage();

+                // save to disk

+                saveContactsToFile();

+            }

             // update the xaml for all contacts

             notifyNewConversationMessage(isNotSelected);

-            // save to disk

-            saveContactsToFile();

         }

     });

 }

@@ -97,51 +100,31 @@
 ContactsViewModel::saveContactsToFile()

 {

     StorageFolder^ localfolder = ApplicationData::Current->LocalFolder;

-    String^ contactsFile = ".profile\\contacts.json";

+    String^ contactsFile = localfolder->Path + "\\" + ".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");

+    if (ring::fileutils::recursive_mkdir(Utils::toString(localfolder->Path + "\\" + ".profile\\").c_str())) {

+        std::ofstream file(Utils::toString(contactsFile).c_str());

+        if (file.is_open())

+        {

+            file << Utils::toString(Stringify());

+            file.close();

+        }

     }

 }

 

 void

 ContactsViewModel::openContactsFromFile()

 {

-    String^ contactsFile = ".profile\\contacts.json";

+    StorageFolder^ localfolder = ApplicationData::Current->LocalFolder;

+    String^ contactsFile = localfolder->Path + "\\" + ".profile\\contacts.json";

 

-    Utils::fileExists(ApplicationData::Current->LocalFolder,

-                      contactsFile)

-    .then([this,contactsFile](bool contacts_file_exists)

-    {

-        if (contacts_file_exists) {

-            try {

-                create_task(ApplicationData::Current->LocalFolder->GetFileAsync(contactsFile))

-                .then([this](StorageFile^ file)

-                {

-                    create_task(FileIO::ReadTextAsync(file))

-                    .then([this](String^ fileContents) {

-                        if (fileContents != nullptr)

-                            Destringify(fileContents);

-                    });

-                });

-            }

-            catch (Exception^ e) {

-                RingDebug::instance->print("Exception while opening contacts file");

-            }

-        }

-    });

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

+

+    CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(CoreDispatcherPriority::Normal,

+    ref new DispatchedHandler([=]() {

+        if (fileContents != nullptr)

+            Destringify(fileContents);

+    }));

 }

 

 String^

diff --git a/Conversation.cpp b/Conversation.cpp
index 5e5c03c..4683e27 100644
--- a/Conversation.cpp
+++ b/Conversation.cpp
@@ -38,14 +38,9 @@
     message->Date = date;

     message->FromContact = fromContact;

     message->Payload = payload;

-    std::string owner((fromContact) ? "from contact" : " from me");

-    MSG_("{Conversation::addMessage}");

-    MSG_("owner = " + owner);

 

     /* add message to _messagesList_ */

     messagesList_->Append(message);

-

-    // TODO store message on the disk

 }

 

 JsonObject^

diff --git a/UserPreferences.cpp b/UserPreferences.cpp
index 2307c78..c9fd121 100644
--- a/UserPreferences.cpp
+++ b/UserPreferences.cpp
@@ -21,6 +21,8 @@
 

 using namespace Windows::Data::Json;

 using namespace Windows::Storage;

+using namespace Windows::UI::Core;

+using namespace Windows::ApplicationModel::Core;

 

 using namespace RingClientUWP;

 using namespace Platform;

@@ -30,64 +32,35 @@
 UserPreferences::save()

 {

     StorageFolder^ localfolder = ApplicationData::Current->LocalFolder;

-    String^ preferencesFile = "preferences.json";

+    String^ preferencesFile = localfolder->Path + "\\" + "preferences.json";

 

-    try {

-        create_task(localfolder->CreateFileAsync(preferencesFile

-            ,Windows::Storage::CreationCollisionOption::ReplaceExisting))

-            .then([&](StorageFile^ newFile){

-            try {

-                FileIO::WriteTextAsync(newFile,Stringify());

-            }

-            catch (Exception^ e) {

-                RingDebug::instance->print("Exception while writing to preferences file");

-            }

-        });

-    }

-    catch (Exception^ e) {

-        RingDebug::instance->print("Exception while opening preferences file");

+    std::ofstream file(Utils::toString(preferencesFile).c_str());

+    if (file.is_open())

+    {

+        file << Utils::toString(Stringify());

+        file.close();

     }

 }

 

 void

 UserPreferences::load()

 {

-    String^ preferencesFile = "preferences.json";

+    StorageFolder^ localfolder = ApplicationData::Current->LocalFolder;

+    String^ preferencesFile = localfolder->Path + "\\preferences.json";

 

-    Utils::fileExists(ApplicationData::Current->LocalFolder,

-        preferencesFile)

-        .then([this,preferencesFile](bool contacts_file_exists)

-    {

-        if (contacts_file_exists) {

-            try {

-                create_task(ApplicationData::Current->LocalFolder->GetFileAsync(preferencesFile))

-                    .then([this](StorageFile^ file)

-                {

-                    try {

-                        create_task(FileIO::ReadTextAsync(file))

-                            .then([this](String^ fileContents){

-                            if (fileContents != nullptr) {

-                                Destringify(fileContents);

-                                // select account index after loading preferences

-                                selectIndex(PREF_ACCOUNT_INDEX);

-                                if (PREF_PROFILE_PHOTO)

-                                    loadProfileImage();

-                            }

-                        });

-                    }

-                    catch (Exception^ e) {

-                        RingDebug::instance->print("Exception while reading preferences file");

-                    }

-                });

-            }

-            catch (Exception^ e) {

-                RingDebug::instance->print("Exception while opening preferences file");

-            }

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

+

+    CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(CoreDispatcherPriority::Normal,

+    ref new DispatchedHandler([=]() {

+        if (fileContents != nullptr) {

+            Destringify(fileContents);

+            selectIndex(PREF_ACCOUNT_INDEX);

+            if (PREF_PROFILE_PHOTO)

+                loadProfileImage();

         }

-        else {

+        else

             selectIndex(0);

-        }

-    });

+    }));

 }

 

 String^

diff --git a/Utils.h b/Utils.h
index 0a61889..5eada9a 100644
--- a/Utils.h
+++ b/Utils.h
@@ -137,5 +137,13 @@
     throw Exception::CreateException(hr);

 }

 

+std::string

+getStringFromFile(const std::string& filename)

+{

+    std::ifstream file(filename);

+    return std::string((std::istreambuf_iterator<char>(file)),

+        (std::istreambuf_iterator<char>()));

+}

+

 }

 }

diff --git a/pch.h b/pch.h
index 725fb55..7e2d825 100644
--- a/pch.h
+++ b/pch.h
@@ -21,6 +21,10 @@
 #include <iomanip>

 #include <ppltasks.h>

 #include <queue>

+#include <fstream>

+#include <iostream>

+#include <sstream>

+#include <string>

 

 /* required by generated headers. */

 #include "App.xaml.h"

diff --git a/ring-client-uwp.vcxproj b/ring-client-uwp.vcxproj
index 48f7621..802976c 100644
--- a/ring-client-uwp.vcxproj
+++ b/ring-client-uwp.vcxproj
@@ -149,7 +149,7 @@
       <ForceFileOutput>MultiplyDefinedSymbolOnly</ForceFileOutput>

     </Link>

     <Link>

-      <AdditionalDependencies>shell32.lib;strmiids.lib;dring.lib;WindowsApp.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <AdditionalDependencies>winsqlite3.lib;shell32.lib;strmiids.lib;dring.lib;WindowsApp.lib;%(AdditionalDependencies)</AdditionalDependencies>

     </Link>

     <Link>

       <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>