// // FileBrowserPane.xaml.cpp // Implementation of the FileBrowserPane class // #include "pch.h" #include "FileBrowserPane.xaml.h" #include "App.xaml.h" #include "stringhelper.h" #include using namespace VBA10; using namespace Platform; using namespace Windows::Foundation; using namespace Windows::Foundation::Collections; using namespace Windows::UI::Xaml; using namespace Windows::UI::Xaml::Controls; using namespace Windows::UI::Xaml::Controls::Primitives; using namespace Windows::UI::Xaml::Data; using namespace Windows::UI::Xaml::Input; using namespace Windows::UI::Xaml::Media; using namespace Windows::UI::Xaml::Navigation; using namespace Windows::UI::Popups; using namespace std; // The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236 FileBrowserPane::FileBrowserPane() { InitializeComponent(); this->fileVector = ref new Platform::Collections::Vector(); this->FileListvs->Source = this->fileVector; this->fileList->SelectedItem = nullptr; //load the skydrive list // Make an asynchronous call to OneDrive's REST interface to get the // user's album info, which is formatted as JSON objects, then parse // the JSON, create local objects and store them in the data model for this page. this->onedriveStack = ref new Vector^>(); this->onedriveStack->Append(ref new Platform::Collections::Vector()); //create the root item OneDriveFileItem^ root = ref new OneDriveFileItem(); root->Name = "OneDrive"; root->OneDriveID = "me/skydrive"; root->Type = OneDriveItemType::Folder; root->ParentID = ""; this->onedriveStack->GetAt(0)->Append(root); this->txtCurrentFolder->Text = root->Name; //get the content of the root this->txtLoading->Visibility = Windows::UI::Xaml::Visibility::Visible; this->loading = true; this->backBtn->IsEnabled = false; App::LiveClient->get(L"/me/skydrive/files") .then([this](web::json::value v) { client_GetCompleted(v); // Perform updates on the UI thread // to avoid the E_RPC_WRONG_THREAD exception. }, task_continuation_context::use_current()) .then([](task t) { try { // Handle exceptions in task chain. t.get(); } //catch (const http_exception& e) //{ // wostringstream str; // str << hex << e.error_code(); // dm->Status = L"Not connected. HTTP error code: " + ref new String(str.str().c_str()); //} catch (const exception& e) { //wostringstream str; //str << e.what(); //dm->Status = L"Not connected. Error: " + ref new String(str.str().c_str()); } }, task_continuation_context::use_current()); } void FileBrowserPane::client_GetCompleted(web::json::value v) { this->fileVector = ref new Platform::Collections::Vector(); //int test = v[L"data"].as_array().size(); for (const auto& it : (v[L"data"]).as_array()) { auto album = it; OneDriveFileItem^ a = ref new OneDriveFileItem(); wstring name = album[L"name"].as_string(); a->Name = ref new String(name.c_str()); wstring type = album[L"type"].as_string(); if (type == L"folder" || type == L"album") a->Type = OneDriveItemType::Folder; else { //get extension int index = name.find_last_of('.'); wstring ext = name.substr(index + 1); transform(ext.begin(), ext.end(), ext.begin(), ::tolower); a->Type = GetOneDriveItemType(ext); //default, will change below } a->OneDriveID = ref new String(album[L"id"].as_string().c_str()); a->ParentID = ref new String(album[L"parent_id"].as_string().c_str()); if (a->Type == OneDriveItemType::Folder) a->FolderChildrenCount = album[L"count"].as_integer(); a->OneDriveLink = ref new String(album[L"link"].as_string().c_str()); this->fileVector->Append(a); } this->onedriveStack->Append(fileVector); this->FileListvs->Source = this->fileVector; this->fileList->SelectedItem = nullptr; this->txtLoading->Visibility = Windows::UI::Xaml::Visibility::Collapsed; if (this->onedriveStack->Size <= 2) this->backBtn->IsEnabled = false; else this->backBtn->IsEnabled = true; this->loading = false; } void FileBrowserPane::fileList_SelectionChanged(Platform::Object^ sender, Windows::UI::Xaml::Controls::SelectionChangedEventArgs^ e) { if (this->loading) return; auto loader = Windows::ApplicationModel::Resources::ResourceLoader::GetForViewIndependentUse(); OneDriveFileItem ^ item = (OneDriveFileItem ^)(this->fileList->SelectedItem); if (item == nullptr) return; if (item->Type == OneDriveItemType::Folder) { this->FileListvs->Source = nullptr; this->txtCurrentFolder->Text = item->Name; //get the content of the folder this->txtLoading->Visibility = Windows::UI::Xaml::Visibility::Visible; this->loading = true; this->backBtn->IsEnabled = false; Platform::String ^id = item->OneDriveID; wstring wid(id->Begin(), id->End()); App::LiveClient->get(wid + L"/files") .then([this](web::json::value v) { client_GetCompleted(v); }, task_continuation_context::use_current()) .then([](task t) { try { // Handle exceptions in task chain. t.get(); } catch (const exception& e) { } }, task_continuation_context::use_current()); } else if (item->Type == OneDriveItemType::ROM) { if (item->Downloading) //prevent double downloading of 1 file return; item->Downloading = true; //download file DownloadFile(item, CreationCollisionOption::GenerateUniqueName).then([this, item, loader](size_t size) { //update rom dabatase //calculate snapshot name Platform::String ^file_path = item->File->Path; wstring wfilepath(file_path->Begin(), file_path->End()); wstring folderpath; wstring filename; wstring filenamenoext; wstring ext; splitFilePath(wfilepath, folderpath, filename, filenamenoext, ext); wstring snapshotname = filenamenoext + L".jpg"; Platform::String^ psnapshotname = ref new Platform::String(snapshotname.c_str()); Platform::String^ pfilenamenoext = ref new Platform::String(filenamenoext.c_str()); //create rom entry ROMDBEntry^ entry = ref new ROMDBEntry(0, pfilenamenoext, item->File->Name, ApplicationData::Current->LocalFolder->Path, "none", psnapshotname); entry->Folder = ApplicationData::Current->LocalFolder; App::ROMDB->AllROMDBEntries->Append(entry); create_task(App::ROMDB->AddAsync(entry)).then([entry] { //copy the default snapshot file over StorageFolder ^installDir = Windows::ApplicationModel::Package::Current->InstalledLocation; return installDir->GetFolderAsync("Assets/"); }).then([entry, item, loader](StorageFolder^ assetFolder) { return assetFolder->GetFileAsync("no_snapshot.png"); }).then([entry, item, loader](StorageFile ^file) { //copy snapshot file to would be location return file->CopyAsync(entry->Folder, entry->SnapshotUri, NameCollisionOption::ReplaceExisting); }).then([entry, loader](StorageFile ^file) { //open file return file->OpenAsync(FileAccessMode::Read); }).then([entry, item, loader](IRandomAccessStream^ stream) { //load bitmap image for snapshot entry->Snapshot = ref new BitmapImage(); return entry->Snapshot->SetSourceAsync(stream); }).then([item, loader](task t) { try { t.get(); // .get() didn't throw, so we succeeded, print out success message item->Downloading = false; MessageDialog ^dialog = ref new MessageDialog(item->File->Name + " " + loader->GetString("ImportedSuccessText")); dialog->ShowAsync(); } catch (Platform::Exception ^ex) { MessageDialog ^dialog = ref new MessageDialog(ex->Message); dialog->ShowAsync(); } }); }); } else if (item->Type == OneDriveItemType::SRAM || item->Type == OneDriveItemType::Savestate) { if (item->Downloading) //prevent double downloading of 1 file return; //get the save name without extension wstring name(item->Name->Begin(), item->Name->End()); int index = name.find_last_of('.'); //wstring ext = name.substr(index + 1); wstring filenamenoext = name.substr(0, index); Platform::String^ pfilenamenoext = ref new Platform::String(filenamenoext.c_str()); ROMDBEntry^ entry = App::ROMDB->GetEntryFromName(pfilenamenoext); if (entry == nullptr) { MessageDialog ^dialog = ref new MessageDialog(loader->GetString("NoMatchingROMError"), loader->GetString("ErrorText")); dialog->ShowAsync(); } else { //start download the file item->Downloading = true; DownloadFile(item, CreationCollisionOption::ReplaceExisting).then([item, entry, loader](size_t size) { item->Downloading = false; //if the file is ingame save then prevent autoloading if (item->Type == OneDriveItemType::SRAM) entry->AutoLoadLastState = false; MessageDialog ^dialog = ref new MessageDialog(item->File->Name + " " + loader->GetString("ImportedSuccessText")); dialog->ShowAsync(); }); } } else { MessageDialog ^dialog = ref new MessageDialog(loader->GetString("FileNotSupportedError")); dialog->ShowAsync(); } } task FileBrowserPane::DownloadFile(OneDriveFileItem^ item, CreationCollisionOption collitionOption) { return create_task(ApplicationData::Current->LocalFolder->CreateFileAsync(item->Name, collitionOption)) .then([this, item] (StorageFile^ file) { item->File = file; return App::LiveClient->download(item->OneDriveID->Data(), file); }).then([](task t) { try { return t.get(); } catch (Platform::Exception^ ex) { // We'll handle the specific errors below. MessageDialog ^dialog = ref new MessageDialog(ex->Message); dialog->ShowAsync(); size_t length = 0; return length; } }); } void FileBrowserPane::closeBtn_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) { auto loader = Windows::ApplicationModel::Resources::ResourceLoader::GetForViewIndependentUse(); //check to see if any thing is downloading for (unsigned int i = 0; i < this->fileVector->Size; i++) { OneDriveFileItem^ item = this->fileVector->GetAt(i); if (item->Downloading) { MessageDialog ^dialog = ref new MessageDialog(loader->GetString("PleaseWaitDownloadText")); dialog->ShowAsync(); return; } } if (Frame->CanGoBack) { Frame->GoBack(); } } void FileBrowserPane::OnNavigatingFrom(Windows::UI::Xaml::Navigation::NavigatingCancelEventArgs^ e) { auto loader = Windows::ApplicationModel::Resources::ResourceLoader::GetForViewIndependentUse(); for (unsigned int i = 0; i < this->fileVector->Size; i++) { OneDriveFileItem^ item = this->fileVector->GetAt(i); if (item->Downloading) { MessageDialog ^dialog = ref new MessageDialog(loader->GetString("PleaseWaitDownloadText")); dialog->ShowAsync(); e->Cancel = true; break; } } } OneDriveItemType FileBrowserPane::GetOneDriveItemType(wstring ext) { if (ext == L"zip" || ext == L"zib") { return OneDriveItemType::Zip; } else if (ext == L"rar") { return OneDriveItemType::Rar; } else if (ext == L"7z") { return OneDriveItemType::SevenZip; } else if (ext == L"gb" || ext == L"gbc" || ext == L"gba") { return OneDriveItemType::ROM; } else if (ext == L"sgm") { return OneDriveItemType::Savestate; } else if (ext == L"sav") { return OneDriveItemType::SRAM; } return OneDriveItemType::File; } void FileBrowserPane::backBtn_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) { //TODO: add handle while downloading if (this->onedriveStack->Size <= 2) { return; } auto loader = Windows::ApplicationModel::Resources::ResourceLoader::GetForViewIndependentUse(); //check to see if any thing is downloading for (unsigned int i = 0; i < this->fileVector->Size; i++) { OneDriveFileItem^ item = this->fileVector->GetAt(i); if (item->Downloading) { MessageDialog ^dialog = ref new MessageDialog(loader->GetString("PleaseWaitDownloadText")); dialog->ShowAsync(); return; } } //remove last folder in stack this->onedriveStack->RemoveAtEnd(); //set source for the upper folder this->loading = true; IVector^ currentFolder = this->onedriveStack->GetAt(this->onedriveStack->Size - 1); this->FileListvs->Source = currentFolder; this->fileList->SelectedItem = nullptr; //find parent name String^ parentName = ""; if (this->onedriveStack->Size == 2) //special case { parentName = this->onedriveStack->GetAt(0)->GetAt(0)->Name; this->backBtn->IsEnabled = false; } else { IVector^ parentFolder = this->onedriveStack->GetAt(this->onedriveStack->Size - 2); OneDriveFileItem^ currentItem = currentFolder->GetAt(0); for (unsigned int i = 0; i <= parentFolder->Size - 1; i++) { OneDriveFileItem^ parentItem = parentFolder->GetAt(i); if (parentItem->OneDriveID == currentItem->ParentID) { parentName = parentItem->Name; break; } } this->backBtn->IsEnabled = true; } this->txtCurrentFolder->Text = parentName; this->loading = false; }