diff options
-rw-r--r-- | backends/cloud/cloudmanager.cpp | 29 | ||||
-rw-r--r-- | backends/cloud/cloudmanager.h | 9 | ||||
-rw-r--r-- | backends/cloud/dropbox/dropboxstorage.cpp | 27 | ||||
-rw-r--r-- | backends/cloud/googledrive/googledrivestorage.cpp | 49 | ||||
-rw-r--r-- | backends/cloud/onedrive/onedrivestorage.cpp | 41 | ||||
-rw-r--r-- | backends/cloud/savessyncrequest.cpp | 5 | ||||
-rw-r--r-- | backends/cloud/storage.h | 10 | ||||
-rw-r--r-- | gui/options.cpp | 42 | ||||
-rw-r--r-- | gui/options.h | 9 | ||||
-rw-r--r-- | gui/themes/scummmodern/scummmodern_layout.stx | 3 | ||||
-rw-r--r-- | gui/themes/scummmodern/scummmodern_layout_lowres.stx | 3 |
11 files changed, 166 insertions, 61 deletions
diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index a1b1ed1525..9456dd84a4 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -135,6 +135,7 @@ void CloudManager::replaceStorage(Storage *storage, uint32 index) { _activeStorage = storage; _currentStorageIndex = index; save(); + if (_activeStorage) _activeStorage->info(nullptr, nullptr); //automatically calls setStorageUsername() } Storage *CloudManager::getCurrentStorage() const { @@ -209,6 +210,34 @@ void CloudManager::printBool(Storage::BoolResponse response) const { debug("bool = %s", (response.value ? "true" : "false")); } +Networking::Request *CloudManager::listDirectory(Common::String path, Storage::ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { + Storage *storage = getCurrentStorage(); + if (storage) storage->listDirectory(path, callback, errorCallback, recursive); + else { + delete callback; + delete errorCallback; + //TODO: should we call errorCallback? + } + return nullptr; +} + +Networking::Request *CloudManager::info(Storage::StorageInfoCallback callback, Networking::ErrorCallback errorCallback) { + Storage *storage = getCurrentStorage(); + if (storage) storage->info(callback, errorCallback); + else { + delete callback; + delete errorCallback; + //TODO: should we call errorCallback? + } + return nullptr; +} + +Common::String CloudManager::savesDirectoryPath() { + Storage *storage = getCurrentStorage(); + if (storage) return storage->savesDirectoryPath(); + return ""; +} + SavesSyncRequest *CloudManager::syncSaves(Storage::BoolCallback callback, Networking::ErrorCallback errorCallback) { Storage *storage = getCurrentStorage(); if (storage) { diff --git a/backends/cloud/cloudmanager.h b/backends/cloud/cloudmanager.h index 7ce7e925da..fd130c5ee8 100644 --- a/backends/cloud/cloudmanager.h +++ b/backends/cloud/cloudmanager.h @@ -170,6 +170,15 @@ public: */ void setStorageLastSync(uint32 index, Common::String date); + /** Returns ListDirectoryResponse with list of files. */ + Networking::Request *listDirectory(Common::String path, Storage::ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false); + + /** Return the StorageInfo struct. */ + Networking::Request *info(Storage::StorageInfoCallback callback, Networking::ErrorCallback errorCallback); + + /** Returns storage's saves directory path with the trailing slash. */ + Common::String savesDirectoryPath(); + /** * Starts saves syncing process in currently active storage if there is any. */ diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index e59e19eef9..faff10f1d9 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -162,20 +162,19 @@ void DropboxStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networ return; } - if (outerCallback) { - //Dropbox documentation states there is no errors for this API method - Common::JSONObject info = json->asObject(); - Common::String uid = Common::String::format("%d", (int)info.getVal("uid")->asIntegerNumber()); - Common::String name = info.getVal("display_name")->asString(); - Common::String email = info.getVal("email")->asString(); - Common::JSONObject quota = info.getVal("quota_info")->asObject(); - uint64 quotaNormal = quota.getVal("normal")->asIntegerNumber(); - uint64 quotaShared = quota.getVal("shared")->asIntegerNumber(); - uint64 quotaAllocated = quota.getVal("quota")->asIntegerNumber(); - - CloudMan.setStorageUsedSpace(kStorageDropboxId, quotaNormal + quotaShared); //TODO that's not ScummVM's actually - CloudMan.setStorageUsername(kStorageDropboxId, email); - + //Dropbox documentation states there is no errors for this API method + Common::JSONObject info = json->asObject(); + Common::String uid = Common::String::format("%d", (int)info.getVal("uid")->asIntegerNumber()); + Common::String name = info.getVal("display_name")->asString(); + Common::String email = info.getVal("email")->asString(); + Common::JSONObject quota = info.getVal("quota_info")->asObject(); + uint64 quotaNormal = quota.getVal("normal")->asIntegerNumber(); + uint64 quotaShared = quota.getVal("shared")->asIntegerNumber(); + uint64 quotaAllocated = quota.getVal("quota")->asIntegerNumber(); + + CloudMan.setStorageUsername(kStorageDropboxId, email); + + if (outerCallback) { (*outerCallback)(StorageInfoResponse(nullptr, StorageInfo(uid, name, email, quotaNormal+quotaShared, quotaAllocated))); delete outerCallback; } diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index 143b7ac52c..3196cbe041 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -156,33 +156,32 @@ void GoogleDriveStorage::infoInnerCallback(StorageInfoCallback outerCallback, Ne return; } - if (outerCallback) { - Common::JSONObject info = json->asObject(); - - Common::String uid, name, email; - uint64 quotaUsed = 0, quotaAllocated = 0; - - if (info.contains("user") && info.getVal("user")->isObject()) { - //"me":true, "kind":"drive#user","photoLink": "", - //"displayName":"Alexander Tkachev","emailAddress":"alexander@tkachov.ru","permissionId":"" - Common::JSONObject user = info.getVal("user")->asObject(); - uid = user.getVal("permissionId")->asString(); //not sure it's user's id, but who cares anyway? - name = user.getVal("displayName")->asString(); - email = user.getVal("emailAddress")->asString(); - } - - if (info.contains("storageQuota") && info.getVal("storageQuota")->isObject()) { - //"usageInDrive":"6332462","limit":"18253611008","usage":"6332462","usageInDriveTrash":"0" - Common::JSONObject storageQuota = info.getVal("storageQuota")->asObject(); - Common::String usage = storageQuota.getVal("usage")->asString(); - Common::String limit = storageQuota.getVal("limit")->asString(); - quotaUsed = atoull(usage); - quotaAllocated = atoull(limit); - } + Common::JSONObject info = json->asObject(); + + Common::String uid, name, email; + uint64 quotaUsed = 0, quotaAllocated = 0; + + if (info.contains("user") && info.getVal("user")->isObject()) { + //"me":true, "kind":"drive#user","photoLink": "", + //"displayName":"Alexander Tkachev","emailAddress":"alexander@tkachov.ru","permissionId":"" + Common::JSONObject user = info.getVal("user")->asObject(); + uid = user.getVal("permissionId")->asString(); //not sure it's user's id, but who cares anyway? + name = user.getVal("displayName")->asString(); + email = user.getVal("emailAddress")->asString(); + } - CloudMan.setStorageUsedSpace(kStorageGoogleDriveId, quotaUsed); //TODO that's not ScummVM's actually - CloudMan.setStorageUsername(kStorageGoogleDriveId, email); + if (info.contains("storageQuota") && info.getVal("storageQuota")->isObject()) { + //"usageInDrive":"6332462","limit":"18253611008","usage":"6332462","usageInDriveTrash":"0" + Common::JSONObject storageQuota = info.getVal("storageQuota")->asObject(); + Common::String usage = storageQuota.getVal("usage")->asString(); + Common::String limit = storageQuota.getVal("limit")->asString(); + quotaUsed = atoull(usage); + quotaAllocated = atoull(limit); + } + + CloudMan.setStorageUsername(kStorageGoogleDriveId, email); + if (outerCallback) { (*outerCallback)(StorageInfoResponse(nullptr, StorageInfo(uid, name, email, quotaUsed, quotaAllocated))); delete outerCallback; } diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index 82681756c4..178d43c8be 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -139,28 +139,31 @@ void OneDriveStorage::infoInnerCallback(StorageInfoCallback outerCallback, Netwo delete outerCallback; return; } - - if (outerCallback) { - Common::JSONObject info = json->asObject(); - - Common::String uid, name, email; - uint64 quotaUsed = 0, quotaAllocated = 26843545600L; // 25 GB, because I actually don't know any way to find out the real one - - if (info.contains("createdBy") && info.getVal("createdBy")->isObject()) { - Common::JSONObject createdBy = info.getVal("createdBy")->asObject(); - if (createdBy.contains("user") && createdBy.getVal("user")->isObject()) { - Common::JSONObject user = createdBy.getVal("user")->asObject(); - uid = user.getVal("id")->asString(); - name = user.getVal("displayName")->asString(); - } + + Common::JSONObject info = json->asObject(); + + Common::String uid, name, email; + uint64 quotaUsed = 0, quotaAllocated = 26843545600L; // 25 GB, because I actually don't know any way to find out the real one + + if (info.contains("createdBy") && info.getVal("createdBy")->isObject()) { + Common::JSONObject createdBy = info.getVal("createdBy")->asObject(); + if (createdBy.contains("user") && createdBy.getVal("user")->isObject()) { + Common::JSONObject user = createdBy.getVal("user")->asObject(); + uid = user.getVal("id")->asString(); + name = user.getVal("displayName")->asString(); } + } - if (info.contains("size") && info.getVal("size")->isIntegerNumber()) { - quotaUsed = info.getVal("size")->asIntegerNumber(); - } + if (info.contains("size") && info.getVal("size")->isIntegerNumber()) { + quotaUsed = info.getVal("size")->asIntegerNumber(); + } + + Common::String username = email; + if (username == "") username = name; + if (username == "") username = uid; + CloudMan.setStorageUsername(kStorageOneDriveId, username); - CloudMan.setStorageUsedSpace(kStorageOneDriveId, quotaUsed); //TODO that's not ScummVM's actually - CloudMan.setStorageUsername(kStorageOneDriveId, email); + if (outerCallback) { (*outerCallback)(StorageInfoResponse(nullptr, StorageInfo(uid, name, email, quotaUsed, quotaAllocated))); delete outerCallback; } diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index cdf1dbac07..e1739f9693 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -21,6 +21,7 @@ */ #include "backends/cloud/savessyncrequest.h" +#include "backends/cloud/cloudmanager.h" #include "common/config-manager.h" #include "common/debug.h" #include "common/file.h" @@ -82,9 +83,11 @@ void SavesSyncRequest::directoryListedCallback(Storage::ListDirectoryResponse re //determine which files to download and which files to upload Common::Array<StorageFile> &remoteFiles = response.value; + uint64 totalSize = 0; for (uint32 i = 0; i < remoteFiles.size(); ++i) { StorageFile &file = remoteFiles[i]; if (file.isDirectory()) continue; + totalSize += file.size(); if (file.name() == TIMESTAMPS_FILENAME) continue; Common::String name = file.name(); @@ -107,6 +110,8 @@ void SavesSyncRequest::directoryListedCallback(Storage::ListDirectoryResponse re } } + CloudMan.setStorageUsedSpace(CloudMan.getStorageIndex(), totalSize); + //upload files which are unavailable in cloud for (Common::HashMap<Common::String, bool>::iterator i = localFileNotAvailableInCloud.begin(); i != localFileNotAvailableInCloud.end(); ++i) { if (i->_key == TIMESTAMPS_FILENAME) continue; diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 11d8f6beb9..a76f2169bc 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -116,7 +116,7 @@ public: * a callback, which is called, when request is complete. */ - /** Returns ListDirectoryStatus struct with list of files. */ + /** Returns ListDirectoryResponse with list of files. */ virtual Networking::Request *listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false) = 0; /** Returns UploadStatus struct with info about uploaded file. */ @@ -143,7 +143,13 @@ public: /** Calls the callback when finished. */ virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) = 0; - /** Returns the StorageInfo struct. */ + /** + * Return the StorageInfo struct via <callback>. + * Call the <errorCallback> if failed to get information. + * + * @note on success Storage should also call + * CloudMan.setStorageUsername(). + */ virtual Networking::Request *info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback) = 0; /** Returns storage's saves directory path with the trailing slash. */ diff --git a/gui/options.cpp b/gui/options.cpp index ac3cc0cc3a..2ab6b1eb6b 100644 --- a/gui/options.cpp +++ b/gui/options.cpp @@ -91,7 +91,8 @@ enum { #ifdef USE_CLOUD enum { - kConfigureStorageCmd = 'cfst' + kConfigureStorageCmd = 'cfst', + kRefreshStorageCmd = 'rfst' }; #endif @@ -1290,8 +1291,10 @@ GlobalOptionsDialog::GlobalOptionsDialog() _storageLastSync = new StaticTextWidget(tab, "GlobalOptions_Cloud.StorageLastSyncLabel", "<never>"); _storageConnectButton = new ButtonWidget(tab, "GlobalOptions_Cloud.ConnectButton", _("Connect"), _("Open wizard dialog to connect your cloud storage account"), kConfigureStorageCmd); + _storageRefreshButton = new ButtonWidget(tab, "GlobalOptions_Cloud.RefreshButton", _("Refresh"), _("Refresh current cloud storage information (username and usage)"), kRefreshStorageCmd); setupCloudTab(); + _redrawCloudTab = false; #endif // Activate the first tab @@ -1587,6 +1590,14 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3 draw(); break; } + case kRefreshStorageCmd: + { + CloudMan.info(new Common::Callback<GlobalOptionsDialog, Cloud::Storage::StorageInfoResponse>(this, &GlobalOptionsDialog::storageInfoCallback), nullptr); + Common::String dir = CloudMan.savesDirectoryPath(); + if (dir.lastChar() == '/') dir.deleteLastChar(); + CloudMan.listDirectory(dir, new Common::Callback<GlobalOptionsDialog, Cloud::Storage::ListDirectoryResponse>(this, &GlobalOptionsDialog::storageListDirectoryCallback), nullptr); + break; + } #endif #ifdef GUI_ENABLE_KEYSDIALOG case kChooseKeyMappingCmd: @@ -1609,6 +1620,17 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3 } } +void GlobalOptionsDialog::handleTickle() { + OptionsDialog::handleTickle(); +#ifdef USE_CLOUD + if (_redrawCloudTab) { + setupCloudTab(); + draw(); + _redrawCloudTab = false; + } +#endif +} + void GlobalOptionsDialog::reflowLayout() { int activeTab = _tabWidget->getActiveTab(); @@ -1673,6 +1695,24 @@ void GlobalOptionsDialog::setupCloudTab() { _storageLastSync->setVisible(shown); } if (_storageConnectButton) _storageConnectButton->setVisible(shown); + if (_storageRefreshButton) _storageRefreshButton->setVisible(shown && _selectedStorageIndex == CloudMan.getStorageIndex()); +} + +void GlobalOptionsDialog::storageInfoCallback(Cloud::Storage::StorageInfoResponse response) { + //we could've used response.value.email() + //but Storage already notified CloudMan + //so we just set the flag to redraw our cloud tab + _redrawCloudTab = true; +} + +void GlobalOptionsDialog::storageListDirectoryCallback(Cloud::Storage::ListDirectoryResponse response) { + Common::Array<Cloud::StorageFile> &files = response.value; + uint64 totalSize = 0; + for (uint32 i = 0; i < files.size(); ++i) + if (!files[i].isDirectory()) + totalSize += files[i].size(); + CloudMan.setStorageUsedSpace(CloudMan.getStorageIndex(), totalSize); + _redrawCloudTab = true; } #endif diff --git a/gui/options.h b/gui/options.h index 4addf717b8..1454ddbfc8 100644 --- a/gui/options.h +++ b/gui/options.h @@ -37,6 +37,10 @@ #include "gui/fluidsynth-dialog.h" #endif +#ifdef USE_CLOUD +#include "backends/cloud/storage.h" +#endif + namespace GUI { class CheckboxWidget; @@ -206,6 +210,7 @@ public: void open(); void close(); void handleCommand(CommandSender *sender, uint32 cmd, uint32 data); + void handleTickle(); virtual void reflowLayout(); @@ -256,8 +261,12 @@ protected: StaticTextWidget *_storageLastSyncDesc; StaticTextWidget *_storageLastSync; ButtonWidget *_storageConnectButton; + ButtonWidget *_storageRefreshButton; + bool _redrawCloudTab; void setupCloudTab(); + void storageInfoCallback(Cloud::Storage::StorageInfoResponse response); + void storageListDirectoryCallback(Cloud::Storage::ListDirectoryResponse response); #endif }; diff --git a/gui/themes/scummmodern/scummmodern_layout.stx b/gui/themes/scummmodern/scummmodern_layout.stx index 8406fc9b28..824c6fa790 100644 --- a/gui/themes/scummmodern/scummmodern_layout.stx +++ b/gui/themes/scummmodern/scummmodern_layout.stx @@ -576,6 +576,9 @@ <widget name = 'ConnectButton' type = 'Button' /> + <widget name = 'RefreshButton' + type = 'Button' + /> </layout> </layout> </dialog> diff --git a/gui/themes/scummmodern/scummmodern_layout_lowres.stx b/gui/themes/scummmodern/scummmodern_layout_lowres.stx index 13d854c9ac..3d2c3b49a7 100644 --- a/gui/themes/scummmodern/scummmodern_layout_lowres.stx +++ b/gui/themes/scummmodern/scummmodern_layout_lowres.stx @@ -573,6 +573,9 @@ <widget name = 'ConnectButton' type = 'Button' /> + <widget name = 'RefreshButton' + type = 'Button' + /> </layout> </layout> </dialog> |