From 671c3024713121d6021e3f1b624d449fa847d8ba Mon Sep 17 00:00:00 2001 From: Dmitry Vedenko Date: Mon, 5 Jun 2023 12:43:48 +0300 Subject: [PATCH 1/3] New way to handle upload success and upload failure --- .../lib-cloud-audiocom/ServiceConfig.cpp | 8 ++++- libraries/lib-cloud-audiocom/ServiceConfig.h | 2 ++ .../lib-cloud-audiocom/UploadService.cpp | 11 ++++-- libraries/lib-cloud-audiocom/UploadService.h | 4 +++ src/cloud/audiocom/ShareAudioDialog.cpp | 36 +++++-------------- 5 files changed, 30 insertions(+), 31 deletions(-) diff --git a/libraries/lib-cloud-audiocom/ServiceConfig.cpp b/libraries/lib-cloud-audiocom/ServiceConfig.cpp index 71fec36c3880..e75b567050c3 100644 --- a/libraries/lib-cloud-audiocom/ServiceConfig.cpp +++ b/libraries/lib-cloud-audiocom/ServiceConfig.cpp @@ -46,11 +46,17 @@ std::string ServiceConfig::GetAPIUrl(std::string_view apiURI) const std::string ServiceConfig::GetFinishUploadPage( std::string_view audioID, std::string_view token) const { - return "http://audio.com/audacity/upload?audioId=" + std::string(audioID) + + return "https://audio.com/audacity/upload?audioId=" + std::string(audioID) + "&token=" + std::string(token) + "&clientId=" + std::string(GetOAuthClientID()); } +std::string ServiceConfig::GetAudioURL( + std::string_view userSlug, std::string_view audioSlug) const +{ + return "https://audio.com/" + std::string(userSlug) + "/audio/" + std::string(audioSlug) + "/edit"; +} + std::chrono::milliseconds ServiceConfig::GetProgressCallbackTimeout() const { return std::chrono::seconds(3); diff --git a/libraries/lib-cloud-audiocom/ServiceConfig.h b/libraries/lib-cloud-audiocom/ServiceConfig.h index 8eaeb81036ab..092fb4c5ef76 100644 --- a/libraries/lib-cloud-audiocom/ServiceConfig.h +++ b/libraries/lib-cloud-audiocom/ServiceConfig.h @@ -35,6 +35,8 @@ class CLOUD_AUDIOCOM_API ServiceConfig final std::string GetAPIUrl(std::string_view apiURI) const; //! Helper to construct the page URL for the anonymous upload last stage std::string GetFinishUploadPage(std::string_view audioID, std::string_view token) const; + //! Helper to construct the page URL for the authorised upload + std::string GetAudioURL(std::string_view userSlug, std::string_view audioSlug) const; //! Timeout between progress callbacks std::chrono::milliseconds GetProgressCallbackTimeout() const; //! Preferred audio format diff --git a/libraries/lib-cloud-audiocom/UploadService.cpp b/libraries/lib-cloud-audiocom/UploadService.cpp index 071dd19a5329..633ea8901871 100644 --- a/libraries/lib-cloud-audiocom/UploadService.cpp +++ b/libraries/lib-cloud-audiocom/UploadService.cpp @@ -206,6 +206,7 @@ struct AudiocomUploadOperation final : std::string mAudioID; std::string mUploadToken; + std::string mUserName; std::string mAudioSlug; @@ -264,10 +265,14 @@ struct AudiocomUploadOperation final : if (mCompletedCallback) { + const auto uploadURL = + mAuthToken.empty() ? + mServiceConfig.GetFinishUploadPage(mAudioID, mUploadToken) : + mServiceConfig.GetAudioURL(mUserName, mAudioSlug); mCompletedCallback( { UploadOperationCompleted::Result::Success, - UploadSuccessfulPayload { mAudioID, mAudioSlug } }); + UploadSuccessfulPayload { mAudioID, mAudioSlug, mUploadToken, uploadURL } }); } mProgressCallback = {}; @@ -395,6 +400,8 @@ struct AudiocomUploadOperation final : if (extra.HasMember("token")) mUploadToken = extra["token"].GetString(); + + mUserName = extra["audio"]["username"].GetString(); } const auto encType = document.HasMember("enctype") ? @@ -579,7 +586,7 @@ UploadOperationHandle UploadService::Upload( mServiceConfig, fileName, projectName, isPublic, std::move(completedCallback), std::move(progressCallback)); - mOAuthService.ValidateAuth([operation](std::string_view authToken) + mOAuthService.ValidateAuth([operation, this](std::string_view authToken) { operation->InitiateUpload(authToken); }); return UploadOperationHandle { operation }; diff --git a/libraries/lib-cloud-audiocom/UploadService.h b/libraries/lib-cloud-audiocom/UploadService.h index 23aa20080149..55f61e3427d7 100644 --- a/libraries/lib-cloud-audiocom/UploadService.h +++ b/libraries/lib-cloud-audiocom/UploadService.h @@ -43,6 +43,10 @@ struct CLOUD_AUDIOCOM_API UploadSuccessfulPayload final std::string audioId; //! "Slug" to be used for shareable URL construction std::string audioSlug; + //! Upload token, if any + std::string uploadToken; + //! URL to the uploaded audio + std::string audioUrl; }; //! Message that is sent when upload is finished. diff --git a/src/cloud/audiocom/ShareAudioDialog.cpp b/src/cloud/audiocom/ShareAudioDialog.cpp index df55f3a32ca4..bd64efd1afe3 100644 --- a/src/cloud/audiocom/ShareAudioDialog.cpp +++ b/src/cloud/audiocom/ShareAudioDialog.cpp @@ -436,28 +436,8 @@ void ShareAudioDialog::StartUploadProcess() void ShareAudioDialog::HandleUploadSucceeded( const UploadSuccessfulPayload& payload) { - mProgressPanel.timePanel->Hide(); - mProgressPanel.title->SetLabel(XO("Upload complete!").Translation()); - mProgressPanel.info->Show(); - - mProgressPanel.info->SetLabel( - "By pressing continue, you will be taken to audio.com and given a shareable link."); - mProgressPanel.info->Wrap(mProgressPanel.root->GetSize().GetWidth()); - - mContinueAction = [this, slug = std::string(payload.audioSlug)]() - { - EndModal(wxID_CLOSE); - auto url = wxString::Format( - "https://audio.com/%s/%s/edit", GetUserService().GetUserSlug(), - audacity::ToWXString(slug)); - - OpenInDefaultBrowser(url); - }; - - mContinueButton->Show(); - - Layout(); - Fit(); + EndModal(wxID_CLOSE); + OpenInDefaultBrowser(wxString { payload.audioUrl }); } void ShareAudioDialog::HandleUploadFailed(const UploadFailedPayload& payload) @@ -466,12 +446,7 @@ void ShareAudioDialog::HandleUploadFailed(const UploadFailedPayload& payload) TranslatableString message; - if (payload.status == 401) - { - message = XO( - "We are unable to upload this file. Please try again and make sure to link to your audio.com account before uploading."); - } - else + if (!payload.message.empty()) { auto details = payload.message; @@ -480,6 +455,11 @@ void ShareAudioDialog::HandleUploadFailed(const UploadFailedPayload& payload) message = XO("Error: %s").Format(details); } + else + { + message = XO( + "We are unable to upload this file. Please try again and make sure to link to your audio.com account before uploading."); + } BasicUI::ShowErrorDialog( {}, XO("Upload error"), From 237d38edf2360c29012a9b9b19a3541192c0c975 Mon Sep 17 00:00:00 2001 From: Dmitry Vedenko Date: Mon, 5 Jun 2023 15:26:43 +0300 Subject: [PATCH 2/3] Allow setting track title before the upload --- src/cloud/audiocom/ShareAudioDialog.cpp | 85 +++++++++++++++++-------- src/cloud/audiocom/ShareAudioDialog.h | 3 + 2 files changed, 62 insertions(+), 26 deletions(-) diff --git a/src/cloud/audiocom/ShareAudioDialog.cpp b/src/cloud/audiocom/ShareAudioDialog.cpp index bd64efd1afe3..c84611466f39 100644 --- a/src/cloud/audiocom/ShareAudioDialog.cpp +++ b/src/cloud/audiocom/ShareAudioDialog.cpp @@ -240,13 +240,26 @@ void ShareAudioDialog::Populate(ShuttleGui& s) mContinueButton = s.AddButton(XXO("C&ontinue")); mContinueButton->Bind(wxEVT_BUTTON, [this](auto) { OnContinue(); }); - mContinueButton->Enable(mIsAuthorised); } s.EndHorizontalLay(); } s.EndInvisiblePanel(); } s.EndHorizontalLay(); + + const auto title = mProject.GetProjectName(); + + if (!title.empty()) + mInitialStatePanel.trackTitle->SetValue(title); + + mContinueButton->Enable(mIsAuthorised && mInitialStatePanel.HasValidTitle()); + + mInitialStatePanel.trackTitle->Bind( + wxEVT_TEXT, + [this](auto&) { + mContinueButton->Enable( + mIsAuthorised && mInitialStatePanel.HasValidTitle()); + }); } void ShareAudioDialog::OnCancel() @@ -389,7 +402,7 @@ void ShareAudioDialog::StartUploadProcess() mServices->uploadPromise = mServices->uploadService.Upload( mFilePath, - mProject.GetProjectName(), + mInitialStatePanel.GetTrackTitle(), false, [this](const auto& result) { @@ -603,35 +616,41 @@ void ShareAudioDialog::InitialStatePanel::PopulateInitialStatePanel( s.SetBorder(0); s.AddWindow(safenew wxStaticLine { s.GetParent() }, wxEXPAND); - - s.AddSpace(16); - s.StartInvisiblePanel(); + + s.StartInvisiblePanel(16); { - anonInfoPanel = s.StartInvisiblePanel(); + s.StartInvisiblePanel(); { - s.SetBorder(30); - - AccessibleLinksFormatter privacyPolicy(XO( - "Your audio will be uploaded to our sharing service: %s,%%which requires a free account to use.")); + s.AddFixedText(XO("Track Title")); + s.AddSpace(8); + trackTitle = s.AddTextBox({}, {}, 60); + trackTitle->SetName(XO("Track Title").Translation()); + s.AddSpace(16); - privacyPolicy.FormatLink( - L"%s", XO("audio.com"), "https://audio.com"); + anonInfoPanel = s.StartInvisiblePanel(); + { + AccessibleLinksFormatter privacyPolicy(XO( + "Your audio will be uploaded to our sharing service: %s,%%which requires a free account to use.")); - privacyPolicy.FormatLink( - L"%%", TranslatableString {}, - AccessibleLinksFormatter::LinkClickedHandler {}); + privacyPolicy.FormatLink( + L"%s", XO("audio.com"), "https://audio.com"); - privacyPolicy.Populate(s); - } - s.EndInvisiblePanel(); + privacyPolicy.FormatLink( + L"%%", TranslatableString {}, + AccessibleLinksFormatter::LinkClickedHandler {}); - authorizedInfoPanel = s.StartInvisiblePanel(); - s.StartHorizontalLay(wxEXPAND, 1); - { - s.AddSpace(30); - s.AddFixedText(XO("Press \"Continue\" to upload to audio.com")); + privacyPolicy.Populate(s); + } + s.EndInvisiblePanel(); + + authorizedInfoPanel = s.StartInvisiblePanel(); + s.StartHorizontalLay(wxEXPAND, 1); + { + s.AddFixedText(XO("Press \"Continue\" to upload to audio.com")); + } + s.EndHorizontalLay(); + s.EndInvisiblePanel(); } - s.EndHorizontalLay(); s.EndInvisiblePanel(); } s.EndInvisiblePanel(); @@ -655,6 +674,8 @@ void ShareAudioDialog::InitialStatePanel::UpdateUserData() rootParent->Layout(); rootParent->Thaw(); + + rootParent->Refresh(); }); auto& oauthService = GetOAuthService(); @@ -694,9 +715,9 @@ void ShareAudioDialog::InitialStatePanel::UpdateUserData() anonInfoPanel->Hide(); authorizedInfoPanel->Show(); - + if (parent.mContinueButton != nullptr) - parent.mContinueButton->Enable(); + parent.mContinueButton->Enable(!trackTitle->GetValue().empty()); } void ShareAudioDialog::InitialStatePanel::OnLinkButtonPressed() @@ -735,6 +756,18 @@ void ShareAudioDialog::InitialStatePanel::SetAnonymousState() parent.mContinueButton->Enable(false); } +wxString ShareAudioDialog::InitialStatePanel::GetTrackTitle() const +{ + wxString ret { trackTitle->GetValue() }; + ret.Trim(true).Trim(false); + return ret; +} + +bool ShareAudioDialog::InitialStatePanel::HasValidTitle() const +{ + return !GetTrackTitle().empty(); +} + void ShareAudioDialog::ProgressPanel::PopulateProgressPanel(ShuttleGui& s) { root = s.StartInvisiblePanel(16); diff --git a/src/cloud/audiocom/ShareAudioDialog.h b/src/cloud/audiocom/ShareAudioDialog.h index a6ad83715370..9e3460f15078 100644 --- a/src/cloud/audiocom/ShareAudioDialog.h +++ b/src/cloud/audiocom/ShareAudioDialog.h @@ -79,6 +79,7 @@ class ShareAudioDialog final : wxButton* oauthButton { nullptr }; wxPanel* anonInfoPanel { nullptr }; wxPanel* authorizedInfoPanel { nullptr }; + wxTextCtrl* trackTitle { nullptr }; Observer::Subscription mUserDataChangedSubscription; @@ -89,6 +90,8 @@ class ShareAudioDialog final : void SetAnonymousState(); + wxString GetTrackTitle() const; + bool HasValidTitle() const; } mInitialStatePanel; struct ProgressPanel final From 86e0d7cabbdfef3f5db53521b02ed16b6139dfc5 Mon Sep 17 00:00:00 2001 From: Dmitry Vedenko Date: Tue, 6 Jun 2023 17:10:03 +0300 Subject: [PATCH 3/3] Focus the Tack Title when dialog is opened --- src/cloud/audiocom/ShareAudioDialog.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/cloud/audiocom/ShareAudioDialog.cpp b/src/cloud/audiocom/ShareAudioDialog.cpp index c84611466f39..31c94a6b1673 100644 --- a/src/cloud/audiocom/ShareAudioDialog.cpp +++ b/src/cloud/audiocom/ShareAudioDialog.cpp @@ -250,7 +250,10 @@ void ShareAudioDialog::Populate(ShuttleGui& s) const auto title = mProject.GetProjectName(); if (!title.empty()) + { mInitialStatePanel.trackTitle->SetValue(title); + mInitialStatePanel.trackTitle->SetInsertionPoint(title.length()); + } mContinueButton->Enable(mIsAuthorised && mInitialStatePanel.HasValidTitle()); @@ -625,6 +628,8 @@ void ShareAudioDialog::InitialStatePanel::PopulateInitialStatePanel( s.AddSpace(8); trackTitle = s.AddTextBox({}, {}, 60); trackTitle->SetName(XO("Track Title").Translation()); + trackTitle->SetFocus(); + trackTitle->SetMaxLength(100); s.AddSpace(16); anonInfoPanel = s.StartInvisiblePanel(); @@ -717,7 +722,7 @@ void ShareAudioDialog::InitialStatePanel::UpdateUserData() authorizedInfoPanel->Show(); if (parent.mContinueButton != nullptr) - parent.mContinueButton->Enable(!trackTitle->GetValue().empty()); + parent.mContinueButton->Enable(!trackTitle->GetValue().empty()); } void ShareAudioDialog::InitialStatePanel::OnLinkButtonPressed()