diff --git a/modules/mod-cloud-audiocom/CMakeLists.txt b/modules/mod-cloud-audiocom/CMakeLists.txt index 59df54c9b688..deb303d08c4a 100644 --- a/modules/mod-cloud-audiocom/CMakeLists.txt +++ b/modules/mod-cloud-audiocom/CMakeLists.txt @@ -14,6 +14,8 @@ set( SOURCES ui/ShareAudioToolbar.h ui/UserImage.cpp ui/UserImage.h + ui/UserPanel.cpp + ui/UserPanel.h AudioComModule.cpp AuthorizationHandler.cpp diff --git a/modules/mod-cloud-audiocom/ui/ShareAudioDialog.cpp b/modules/mod-cloud-audiocom/ui/ShareAudioDialog.cpp index 8d5719cd3b67..75b82bf2ec02 100644 --- a/modules/mod-cloud-audiocom/ui/ShareAudioDialog.cpp +++ b/modules/mod-cloud-audiocom/ui/ShareAudioDialog.cpp @@ -37,8 +37,7 @@ #include "UserService.h" #include "AuthorizationHandler.h" -#include "LinkAccountDialog.h" -#include "UserImage.h" +#include "UserPanel.h" #include "CodeConversions.h" @@ -52,16 +51,10 @@ #include "HelpSystem.h" #include "ProjectRate.h" -#ifdef HAS_CUSTOM_URL_HANDLING -#include "URLSchemesRegistry.h" -#endif - namespace cloud::audiocom { namespace { -const wxSize avatarSize = { 32, 32 }; - wxString GenerateTempPath(FileExtension extension) { const auto tempPath = GetUploadTempPath(); @@ -589,8 +582,6 @@ void ShareAudioDialog::UpdateProgress(uint64_t current, uint64_t total) ShareAudioDialog::InitialStatePanel::InitialStatePanel(ShareAudioDialog& parent) : parent { parent } - , mUserDataChangedSubscription( - GetUserService().Subscribe([this](const auto&) { UpdateUserData(); })) { } @@ -602,36 +593,13 @@ void ShareAudioDialog::InitialStatePanel::PopulateInitialStatePanel( { s.SetBorder(16); - s.StartHorizontalLay(wxEXPAND, 0); - { - avatar = safenew UserImage(s.GetParent(), avatarSize); - - s.AddWindow(avatar); - - s.StartVerticalLay(wxEXPAND, 1); - { - s.SetBorder(0); - s.AddSpace(0, 0, 1); - name = s.AddVariableText(XO("Anonymous")); - s.AddSpace(0, 0, 1); - } - s.EndVerticalLay(); + userPanel = safenew UserPanel { GetServiceConfig(), GetOAuthService(), + GetUserService(), true, s.GetParent() }; - s.AddSpace(0, 0, 1); + mUserDataChangedSubscription = userPanel->Subscribe( + [this](auto message) { UpdateUserData(message.IsAuthorized); }); - s.StartVerticalLay(wxEXPAND, 1); - { - s.AddSpace(0, 0, 1); - - s.SetBorder(16); - oauthButton = s.AddButton(XXO("&Link Account")); - oauthButton->Bind( - wxEVT_BUTTON, [this](auto) { OnLinkButtonPressed(); }); - s.AddSpace(0, 0, 1); - } - s.EndVerticalLay(); - } - s.EndHorizontalLay(); + s.Prop(0).AddWindow(userPanel, wxEXPAND); s.SetBorder(0); @@ -681,102 +649,23 @@ void ShareAudioDialog::InitialStatePanel::PopulateInitialStatePanel( s.EndVerticalLay(); s.EndInvisiblePanel(); - UpdateUserData(); + UpdateUserData( + GetOAuthService().HasRefreshToken() && + !GetUserService().GetUserSlug().empty()); } -void ShareAudioDialog::InitialStatePanel::UpdateUserData() +void ShareAudioDialog::InitialStatePanel::UpdateUserData(bool authorized) { - auto rootParent = root->GetParent(); - rootParent->Freeze(); - - auto layoutUpdater = finally( - [rootParent = root->GetParent(), this]() - { - oauthButton->Fit(); - rootParent->Fit(); - rootParent->Layout(); - - rootParent->Thaw(); - - rootParent->Refresh(); - }); - - auto& oauthService = GetOAuthService(); - - if (!oauthService.HasRefreshToken()) - { - SetAnonymousState(); - return; - } - - if (!oauthService.HasAccessToken()) - oauthService.ValidateAuth({}); - - auto& userService = GetUserService(); + parent.mIsAuthorised = authorized; - if (userService.GetUserSlug().empty()) - { - SetAnonymousState(); - return; - } - - const auto displayName = userService.GetDisplayName(); - - if (!displayName.empty()) - name->SetLabel(displayName); - - const auto avatarPath = userService.GetAvatarPath(); - - if (!avatarPath.empty()) - avatar->SetBitmap(avatarPath); - else - avatar->SetBitmap(theTheme.Bitmap(bmpAnonymousUser)); - - oauthButton->SetLabel(XXO("&Unlink Account").Translation()); - - parent.mIsAuthorised = true; - - anonInfoPanel->Hide(); - authorizedInfoPanel->Show(); + anonInfoPanel->Show(!authorized); + authorizedInfoPanel->Show(authorized); if (parent.mContinueButton != nullptr) - parent.mContinueButton->Enable(!trackTitle->GetValue().empty()); -} - -void ShareAudioDialog::InitialStatePanel::OnLinkButtonPressed() -{ - auto& oauthService = GetOAuthService(); + parent.mContinueButton->Enable( + authorized && !trackTitle->GetValue().empty()); - if (oauthService.HasAccessToken()) - oauthService.UnlinkAccount(); - else - { - OpenInDefaultBrowser( - { audacity::ToWXString(GetServiceConfig().GetOAuthLoginPage()) }); - -#ifdef HAS_CUSTOM_URL_HANDLING - if (!URLSchemesRegistry::Get().IsURLHandlingSupported()) -#endif - { - LinkAccountDialog dlg(root); - dlg.ShowModal(); - } - } -} - -void ShareAudioDialog::InitialStatePanel::SetAnonymousState() -{ - parent.mIsAuthorised = false; - - name->SetLabel(XO("Anonymous").Translation()); - avatar->SetBitmap(theTheme.Bitmap(bmpAnonymousUser)); - oauthButton->SetLabel(XXO("&Link Account").Translation()); - - anonInfoPanel->Show(); - authorizedInfoPanel->Hide(); - - if (parent.mContinueButton != nullptr) - parent.mContinueButton->Enable(false); + root->GetParent()->Layout(); } wxString ShareAudioDialog::InitialStatePanel::GetTrackTitle() const diff --git a/modules/mod-cloud-audiocom/ui/ShareAudioDialog.h b/modules/mod-cloud-audiocom/ui/ShareAudioDialog.h index 429022c90f62..9813c26be083 100644 --- a/modules/mod-cloud-audiocom/ui/ShareAudioDialog.h +++ b/modules/mod-cloud-audiocom/ui/ShareAudioDialog.h @@ -31,7 +31,7 @@ class wxRadioButton; namespace cloud::audiocom { -class UserImage; +class UserPanel; struct UploadFailedPayload; struct UploadSuccessfulPayload; @@ -69,9 +69,7 @@ class ShareAudioDialog final : wxWindow* root { nullptr }; - UserImage* avatar { nullptr }; - wxStaticText* name { nullptr }; - wxButton* oauthButton { nullptr }; + UserPanel* userPanel { nullptr }; wxPanel* anonInfoPanel { nullptr }; wxPanel* authorizedInfoPanel { nullptr }; wxTextCtrl* trackTitle { nullptr }; @@ -80,10 +78,7 @@ class ShareAudioDialog final : void PopulateInitialStatePanel(ShuttleGui& s); - void UpdateUserData(); - void OnLinkButtonPressed(); - - void SetAnonymousState(); + void UpdateUserData(bool authorized); wxString GetTrackTitle() const; bool HasValidTitle() const; diff --git a/modules/mod-cloud-audiocom/ui/UserPanel.cpp b/modules/mod-cloud-audiocom/ui/UserPanel.cpp new file mode 100644 index 000000000000..9ed23c3ce49f --- /dev/null +++ b/modules/mod-cloud-audiocom/ui/UserPanel.cpp @@ -0,0 +1,164 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/*!******************************************************************** + + Audacity: A Digital Audio Editor + + UserPanel.cpp + + Dmitry Vedenko + +**********************************************************************/ + +#include "UserPanel.h" + +#include + +#include +#include +#include + +#ifdef HAS_CUSTOM_URL_HANDLING +# include "URLSchemesRegistry.h" +#endif + +#include "LinkAccountDialog.h" + +#include "ServiceConfig.h" +#include "OAuthService.h" +#include "UserService.h" + +#include "CodeConversions.h" + +#include "ShuttleGui.h" +#include "Theme.h" +#include "AllThemeResources.h" + +#include "UserImage.h" + +#include "MemoryX.h" + +#include "HelpSystem.h" + +namespace cloud::audiocom +{ + +namespace +{ +const wxSize avatarSize = { 32, 32 }; +} // namespace + +UserPanel::UserPanel( + const ServiceConfig& serviceConfig, OAuthService& authService, + UserService& userService, bool hasLinkButton, wxWindow* parent, + const wxPoint& pos, const wxSize& size) + : wxPanelWrapper { parent, wxID_ANY, pos, size } + , mServiceConfig { serviceConfig } + , mAuthService { authService } + , mUserService { userService } + , mUserDataChangedSubscription { + userService.Subscribe([this](const auto&) { UpdateUserData(); }) + } +{ + + mUserImage = safenew UserImage(this, avatarSize); + mUserName = safenew wxStaticText(this, wxID_ANY, XO("Anonymous").Translation()); + mLinkButton = safenew wxButton(this, wxID_ANY, XXO("&Link Account").Translation()); + mLinkButton->Bind(wxEVT_BUTTON, [this](auto) { OnLinkButtonPressed(); }); + mLinkButton->Show(hasLinkButton); + + auto sizer = safenew wxBoxSizer { wxHORIZONTAL }; + + sizer->Add(mUserImage, 0, wxALIGN_CENTER_VERTICAL); + sizer->AddSpacer(8); + sizer->Add(mUserName, 0, wxALIGN_CENTER_VERTICAL); + sizer->AddStretchSpacer(); + sizer->Add(mLinkButton, 0, wxALIGN_CENTER_VERTICAL); + + SetSizerAndFit(sizer); + UpdateUserData(); +} + +UserPanel::~UserPanel() = default; + +void UserPanel::UpdateUserData() +{ + Freeze(); + + auto layoutUpdater = finally( + [this]() + { + mLinkButton->Fit(); + + Layout(); + Thaw(); + + Refresh(); + }); + + auto& oauthService = GetOAuthService(); + + if (!oauthService.HasRefreshToken()) + { + SetAnonymousState(); + return; + } + + if (!oauthService.HasAccessToken()) + oauthService.ValidateAuth({}); + + auto& userService = GetUserService(); + + if (userService.GetUserSlug().empty()) + { + SetAnonymousState(); + return; + } + + const auto displayName = userService.GetDisplayName(); + + if (!displayName.empty()) + mUserName->SetLabel(displayName); + + const auto avatarPath = userService.GetAvatarPath(); + + if (!avatarPath.empty()) + mUserImage->SetBitmap(avatarPath); + else + mUserImage->SetBitmap(theTheme.Bitmap(bmpAnonymousUser)); + + mLinkButton->SetLabel(XXO("&Unlink Account").Translation()); + + Publish(UserPanelStateChangedMessage { true }); +} + +void UserPanel::OnLinkButtonPressed() +{ + auto& oauthService = GetOAuthService(); + + if (oauthService.HasAccessToken()) + oauthService.UnlinkAccount(); + else + { + OpenInDefaultBrowser( + { audacity::ToWXString(mServiceConfig.GetOAuthLoginPage()) }); + +#ifdef HAS_CUSTOM_URL_HANDLING + if (!URLSchemesRegistry::Get().IsURLHandlingSupported()) +#endif + { + LinkAccountDialog dlg(this); + dlg.ShowModal(); + } + } +} + +void UserPanel::SetAnonymousState() +{ + mUserName->SetLabel(XO("Anonymous").Translation()); + mUserImage->SetBitmap(theTheme.Bitmap(bmpAnonymousUser)); + mLinkButton->SetLabel(XXO("&Link Account").Translation()); + + Publish(UserPanelStateChangedMessage { false }); +} + +} // namespace cloud::audiocom diff --git a/modules/mod-cloud-audiocom/ui/UserPanel.h b/modules/mod-cloud-audiocom/ui/UserPanel.h new file mode 100644 index 000000000000..bb50284de79d --- /dev/null +++ b/modules/mod-cloud-audiocom/ui/UserPanel.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/*!******************************************************************** + + Audacity: A Digital Audio Editor + + UserPanel.h + + Dmitry Vedenko + +**********************************************************************/ +#pragma once + +#include "wxPanelWrapper.h" +#include "Observer.h" + +class wxStaticText; +class wxButton; + +namespace cloud::audiocom +{ +class ServiceConfig; +class OAuthService; +class UserService; +class UserImage; + +struct UserPanelStateChangedMessage final +{ + bool IsAuthorized; +}; + +class UserPanel final + : public wxPanelWrapper + , public Observer::Publisher +{ +public: + UserPanel( + const ServiceConfig& serviceConfig, + OAuthService& authService, UserService& userService, + bool hasLinkButton, wxWindow* parent = nullptr, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize); + + ~UserPanel() override; + +private: + void UpdateUserData(); + void OnLinkButtonPressed(); + void SetAnonymousState(); + + const ServiceConfig& mServiceConfig; + OAuthService& mAuthService; + UserService& mUserService; + + UserImage* mUserImage {}; + wxStaticText* mUserName {}; + wxButton* mLinkButton {}; + + Observer::Subscription mUserDataChangedSubscription; +}; // class UserPanel + +} // namespace cloud::audiocom