Audacity 3.2.0
UserPanel.cpp
Go to the documentation of this file.
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*!********************************************************************
3
4 Audacity: A Digital Audio Editor
5
6 UserPanel.cpp
7
8 Dmitry Vedenko
9
10**********************************************************************/
11
12#include "UserPanel.h"
13
14#include <cassert>
15
16#include <wx/button.h>
17#include <wx/sizer.h>
18#include <wx/stattext.h>
19
20#ifdef HAS_CUSTOM_URL_HANDLING
21# include "URLSchemesRegistry.h"
22#endif
23
25
26#include "OAuthService.h"
27#include "ServiceConfig.h"
28#include "UserService.h"
29
30#include "CodeConversions.h"
31#include "ExportUtils.h"
32
33#include "AllThemeResources.h"
34#include "Theme.h"
35
36#include "UserImage.h"
37
38#include "MemoryX.h"
39
40#include "HelpSystem.h"
41
43{
44
45namespace
46{
47const wxSize avatarSize = { 32, 32 };
48const auto notLinkedText = XO("Account not linked");
49const auto anonymousText = XO("Anonymous");
50} // namespace
51
53 const ServiceConfig& serviceConfig, OAuthService& authService,
54 UserService& userService, LinkMode linkMode, AudiocomTrace trace,
55 wxWindow* parent, const wxPoint& pos, const wxSize& size)
56 : wxPanelWrapper { parent, wxID_ANY, pos, size }
57 , mServiceConfig { serviceConfig }
58 , mAuthService { authService }
59 , mUserService { userService }
60 , mAudiocomTrace { trace }
61 , mUserDataChangedSubscription { userService.Subscribe(
62 [this](const auto&) { UpdateUserData(); }) }
63 , mLinkMode { linkMode }
64{
65 mUserImage = safenew UserImage(this, avatarSize);
66 mUserImage->SetLabel( mLinkMode == LinkMode::Link ?
67 notLinkedText : anonymousText ); // for screen readers
68 mUserName = safenew wxStaticText(
69 this,
70 wxID_ANY,
71 ( mLinkMode == LinkMode::Link ?
72 notLinkedText : anonymousText).Translation() );
73
74 mLinkButton =
75 safenew wxButton(this, wxID_ANY, XXO("&Link Account").Translation());
76 mLinkButton->Bind(wxEVT_BUTTON, [this](auto) { OnLinkButtonPressed(); });
77
78 mLinkButton->Show(mLinkMode == LinkMode::Link);
79
80 auto sizer = safenew wxBoxSizer { wxHORIZONTAL };
81
82 sizer->Add(mUserImage, 0, wxALIGN_CENTER_VERTICAL);
83 sizer->AddSpacer(8);
84 sizer->Add(mUserName, 0, wxALIGN_CENTER_VERTICAL);
85 sizer->AddStretchSpacer();
86 sizer->Add(mLinkButton, 0, wxALIGN_CENTER_VERTICAL);
87
88 SetSizerAndFit(sizer);
89 UpdateUserData();
90}
91
92UserPanel::~UserPanel() = default;
93
94bool UserPanel::IsAuthorized() const
95{
96 return mIsAuthorized;
97}
98
99void UserPanel::OnStateChanged(bool isAuthorized)
100{
101 if (mIsAuthorized == isAuthorized)
102 return;
103
104 mIsAuthorized = isAuthorized;
105 Publish(UserPanelStateChangedMessage { isAuthorized });
106}
107
108void UserPanel::UpdateUserData()
109{
110 Freeze();
111
112 auto layoutUpdater = finally(
113 [this]()
114 {
115 mLinkButton->Fit();
116
117 Layout();
118 Thaw();
119
120 auto parent = GetParent();
121
122 if (parent != nullptr)
123 parent->Refresh();
124 else
125 Refresh();
126 });
127
128 auto& oauthService = GetOAuthService();
129
130 if (!oauthService.HasRefreshToken())
131 {
132 SetAnonymousState();
133 return;
134 }
135
136 if (!oauthService.HasAccessToken())
137 oauthService.ValidateAuth({}, mAudiocomTrace, true);
138
139 auto& userService = GetUserService();
140
141 if (userService.GetUserSlug().empty())
142 {
143 SetAnonymousState();
144 return;
145 }
146
147 const auto displayName = userService.GetDisplayName();
148
149 if (!displayName.empty()) {
150 mUserName->SetLabel(displayName);
151 mUserImage->wxPanel::SetLabel(displayName); // for screen readers
152 }
153
154 const auto avatarPath = userService.GetAvatarPath();
155
156 if (!avatarPath.empty())
157 mUserImage->SetBitmap(avatarPath);
158 else
159 mUserImage->SetBitmap(theTheme.Bitmap(bmpAnonymousUser));
160
161 mLinkButton->SetLabel(( mLinkMode == LinkMode::Link ?
162 XXO("&Unlink Account") :
163 XXO("&Sign Out") ).Translation());
164 mLinkButton->Show();
165
166 OnStateChanged(true);
167}
168
169void UserPanel::OnLinkButtonPressed()
170{
171 auto& oauthService = GetOAuthService();
172
173 if (oauthService.HasAccessToken())
174 oauthService.UnlinkAccount(mAudiocomTrace);
175 else
176 {
178 mServiceConfig.GetOAuthLoginPage(mAudiocomTrace)) });
179
180#ifdef HAS_CUSTOM_URL_HANDLING
182#endif
183 {
184 LinkWithTokenDialog dlg(mAudiocomTrace, this);
185 dlg.ShowModal();
186 }
187 }
188}
189
190void UserPanel::SetAnonymousState()
191{
192 mUserName->SetLabel(anonymousText.Translation());
193 mUserImage->SetBitmap(theTheme.Bitmap(bmpAnonymousUser));
194 mUserImage->SetLabel(anonymousText); // for screen readers
195 mLinkButton->SetLabel(XXO("&Link Account").Translation());
196 mLinkButton->Show(mLinkMode == LinkMode::Link);
197
198 OnStateChanged(false);
199}
200
201} // namespace audacity::cloud::audiocom
Declare functions to perform UTF-8 to std::wstring conversions.
AudiocomTrace
Definition: ExportUtils.h:27
XO("Cut/Copy/Paste")
XXO("&Cut/Copy/Paste Toolbar")
#define safenew
Definition: MemoryX.h:10
THEME_API Theme theTheme
Definition: Theme.cpp:82
wxBitmap & Bitmap(int iIndex)
bool IsURLHandlingSupported() const noexcept
Returns true, if Audacity can handle custom URLs.
static URLSchemesRegistry & Get()
Retrieves the registry instance.
Service responsible for OAuth authentication against the audio.com service.
Definition: OAuthService.h:43
Configuration for the audio.com.
Definition: ServiceConfig.h:25
UserPanel(const ServiceConfig &serviceConfig, OAuthService &authService, UserService &userService, LinkMode linkMode, AudiocomTrace, wxWindow *parent=nullptr, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize)
Definition: UserPanel.cpp:52
Service for providing information about the user profile.
Definition: UserService.h:28
void SetLabel(const TranslatableString &title)
bool OpenInDefaultBrowser(const wxString &url)
Open an URL in default browser.
Definition: BasicUI.cpp:246
UserService & GetUserService()
OAuthService & GetOAuthService()
Returns the instance of the OAuthService.
wxString ToWXString(const std::string &str)