Add granular status to avatar upload

This commit is contained in:
Ryan Huffman 2018-12-23 00:13:01 -08:00
parent b717188ed0
commit 8c56e35f69
4 changed files with 93 additions and 113 deletions

View file

@ -25,8 +25,10 @@ Item {
property var footer: Item { property var footer: Item {
id: uploadFooter id: uploadFooter
anchors.fill: parent anchors.fill: parent
anchors.rightMargin: 17 anchors.rightMargin: 17
HifiControls.Button { HifiControls.Button {
id: uploadButton id: uploadButton
enabled: Account.loggedIn enabled: Account.loggedIn
@ -64,7 +66,7 @@ Item {
root.uploader.uploadProgress.connect(function(uploaded, total) { root.uploader.uploadProgress.connect(function(uploaded, total) {
console.log("Uploader progress: " + uploaded + " / " + total); console.log("Uploader progress: " + uploaded + " / " + total);
}); });
root.uploader.completed.connect(function() { root.uploader.finished.connect(function() {
try { try {
var response = JSON.parse(root.uploader.responseData); var response = JSON.parse(root.uploader.responseData);
console.log("Uploader complete! " + response); console.log("Uploader complete! " + response);

View file

@ -28,7 +28,7 @@ Item {
onVisibleChanged: { onVisibleChanged: {
console.log("Visibility changed"); console.log("Visibility changed");
if (visible) { if (visible) {
root.uploader.completed.connect(function() { root.uploader.finished.connect(function() {
console.log("Did complete"); console.log("Did complete");
backToProjectTimer.start(); backToProjectTimer.start();
}); });
@ -36,127 +36,94 @@ Item {
} }
Item { Item {
visible: !!root.uploader && !root.uploader.complete id: uploadStatus
visible: !!root.uploader
anchors.fill: parent anchors.fill: parent
AnimatedImage { Item {
id: uploadSpinner id: statusItem
anchors { width: parent.width
horizontalCenter: parent.horizontalCenter height: 128
verticalCenter: parent.verticalCenter
AnimatedImage {
id: uploadSpinner
visible: !!root.uploader && !root.uploader.complete
anchors {
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
source: "../../../icons/loader-snake-64-w.gif"
playing: true
z: 10000
} }
source: "../../../icons/loader-snake-64-w.gif" HiFiGlyphs {
playing: true id: errorIcon
z: 10000 visible: !!root.uploader && root.uploader.complete && root.uploader.error !== 0
}
}
Item { anchors {
id: failureScreen horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
visible: !!root.uploader && root.uploader.complete && root.uploader.error !== 0 size: 128
text: "w"
anchors.fill: parent color: "red"
HiFiGlyphs {
id: errorIcon
anchors {
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
} }
size: 128 HiFiGlyphs {
text: "w" id: successIcon
color: "red"
}
Column { visible: !!root.uploader && root.uploader.complete && root.uploader.error === 0
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: errorIcon.bottom
Text {
anchors.horizontalCenter: parent.horizontalCenter
text: "Error" anchors {
font.pointSize: 24 horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
color: "white" size: 128
} text: "\ue01a"
Text { color: "#1FC6A6"
text: "Your avatar has not been uploaded."
font.pointSize: 16
anchors.horizontalCenter: parent.horizontalCenter
color: "white"
} }
} }
} Item {
id: statusRows
Item { anchors.top: statusItem.bottom
id: successScreen
visible: !!root.uploader && root.uploader.complete && root.uploader.error === 0 AvatarUploadStatusItem {
id: statusCategories
text: "Retreiving categories"
anchors.fill: parent state: root.uploader.state == 1 ? "running" : (root.uploader.state > 1 ? "success" : (root.uploader.error ? "fail" : ""))
HiFiGlyphs {
id: successIcon
anchors {
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
} }
AvatarUploadStatusItem {
id: statusUploading
anchors.top: statusCategories.bottom
text: "Uploading data"
size: 128 state: root.uploader.state == 2 ? "running" : (root.uploader.state > 2 ? "success" : (root.uploader.error ? "fail" : ""))
text: "\ue01a"
color: "#1FC6A6"
}
Column {
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: successIcon.bottom
Text {
id: successText
anchors.horizontalCenter: parent.horizontalCenter
text: "Congratulations!"
font.pointSize: 24
color: "white"
} }
Text { // TODO add waiting for response
text: "Your avatar has been uploaded." //AvatarUploadStatusItem {
font.pointSize: 16 //id: statusResponse
//text: "Waiting for completion"
//}
AvatarUploadStatusItem {
id: statusInventory
anchors.top: statusUploading.bottom
text: "Waiting for inventory"
anchors.horizontalCenter: parent.horizontalCenter state: root.uploader.state == 3 ? "running" : (root.uploader.state > 3 ? "success" : (root.uploader.error ? "fail" : ""))
color: "white"
} }
} }
HifiControls.Button {
width: implicitWidth
height: implicitHeight
anchors.bottom: parent.bottom
anchors.right: parent.right
text: "View in Inventory"
color: hifi.buttons.blue
colorScheme: root.colorScheme
onClicked: function() {
console.log("Opening in inventory");
AvatarPackagerCore.currentAvatarProject.openInInventory();
}
}
} }
Column { Column {
@ -165,8 +132,6 @@ Item {
visible: false visible: false
Text { Text {
id: uploadStatus
text: "Uploading" text: "Uploading"
color: "white" color: "white"

View file

@ -39,15 +39,25 @@ MarketplaceItemUploader::MarketplaceItemUploader(QString title,
} }
void MarketplaceItemUploader::setState(State newState) { void MarketplaceItemUploader::setState(State newState) {
Q_ASSERT(newState != _state);
qDebug() << "Setting uploader state to: " << newState; qDebug() << "Setting uploader state to: " << newState;
_state = newState; _state = newState;
emit stateChanged(newState); emit stateChanged(newState);
if (newState == State::Complete) { if (newState == State::Complete) {
emit completed(); emit completed();
emit finished();
} }
} }
void MarketplaceItemUploader::setError(Error error) {
Q_ASSERT(_error == Error::None);
_error = error;
emit errorChanged(error);
emit finished();
}
void MarketplaceItemUploader::send() { void MarketplaceItemUploader::send() {
doGetCategories(); doGetCategories();
} }
@ -105,14 +115,12 @@ void MarketplaceItemUploader::doGetCategories() {
qDebug() << "Done " << success << id; qDebug() << "Done " << success << id;
if (!success) { if (!success) {
qWarning() << "Failed to find marketplace category id"; qWarning() << "Failed to find marketplace category id";
_error = Error::Unknown; setError(Error::Unknown);
setState(State::Complete);
} else { } else {
doUploadAvatar(); doUploadAvatar();
} }
} else { } else {
_error = Error::Unknown; setError(Error::Unknown);
setState(State::Complete);
} }
}); });
} }
@ -132,8 +140,7 @@ void MarketplaceItemUploader::doUploadAvatar() {
QuaZipFile zipFile{ &zip }; QuaZipFile zipFile{ &zip };
if (!zipFile.open(QIODevice::WriteOnly, QuaZipNewInfo(fileInfo.fileName()))) { if (!zipFile.open(QIODevice::WriteOnly, QuaZipNewInfo(fileInfo.fileName()))) {
qWarning() << "Could not open zip file:" << zipFile.getZipError(); qWarning() << "Could not open zip file:" << zipFile.getZipError();
_error = Error::Unknown; setError(Error::Unknown);
setState(State::Complete);
return; return;
} }
QFile file{ filePath }; QFile file{ filePath };
@ -204,14 +211,13 @@ void MarketplaceItemUploader::doUploadAvatar() {
if (status == "success") { if (status == "success") {
_marketplaceID = QUuid::fromString(doc["data"].toObject()["marketplace_id"].toString()); _marketplaceID = QUuid::fromString(doc["data"].toObject()["marketplace_id"].toString());
_itemVersion = doc["data"].toObject()["version"].toDouble(); _itemVersion = doc["data"].toObject()["version"].toDouble();
setState(State::WaitingForInventory);
doWaitForInventory(); doWaitForInventory();
} else { } else {
_error = Error::Unknown; setError(Error::Unknown);
setState(State::Complete);
} }
} else { } else {
_error = Error::Unknown; setError(Error::Unknown);
setState(State::Complete);
} }
}); });
@ -282,8 +288,7 @@ void MarketplaceItemUploader::doWaitForInventory() {
} else { } else {
qDebug() << "Failed to find item in inventory"; qDebug() << "Failed to find item in inventory";
if (_numRequestsForInventory > 8) { if (_numRequestsForInventory > 8) {
_error = Error::Unknown; setError(Error::Unknown);
setState(State::Complete);
} else { } else {
QTimer::singleShot(5000, [this]() { doWaitForInventory(); }); QTimer::singleShot(5000, [this]() { doWaitForInventory(); });
} }

View file

@ -23,7 +23,7 @@ class MarketplaceItemUploader : public QObject {
Q_PROPERTY(bool complete READ getComplete NOTIFY stateChanged) Q_PROPERTY(bool complete READ getComplete NOTIFY stateChanged)
Q_PROPERTY(State state READ getState NOTIFY stateChanged) Q_PROPERTY(State state READ getState NOTIFY stateChanged)
Q_PROPERTY(Error error READ getError) Q_PROPERTY(Error error READ getError NOTIFY errorChanged)
Q_PROPERTY(QString responseData READ getResponseData) Q_PROPERTY(QString responseData READ getResponseData)
public: public:
enum class Error enum class Error
@ -51,11 +51,14 @@ public:
Q_INVOKABLE void send(); Q_INVOKABLE void send();
void setError(Error error);
QString getResponseData() const { return _responseData; } QString getResponseData() const { return _responseData; }
void setState(State newState); void setState(State newState);
State getState() const { return _state; } State getState() const { return _state; }
bool getComplete() const { return _state == State::Complete; } bool getComplete() const { return _state == State::Complete; }
QUuid getMarketplaceID() const { return _marketplaceID; } QUuid getMarketplaceID() const { return _marketplaceID; }
Error getError() const { return _error; } Error getError() const { return _error; }
@ -63,7 +66,12 @@ public:
signals: signals:
void uploadProgress(qint64 bytesSent, qint64 bytesTotal); void uploadProgress(qint64 bytesSent, qint64 bytesTotal);
void completed(); void completed();
void stateChanged(State newState); void stateChanged(State newState);
void errorChanged(Error error);
// Triggered when the upload has finished, either succesfully completing, or stopping with an error
void finished();
private: private:
void doGetCategories(); void doGetCategories();