Audacity 3.2.0
ProjectCloudUIExtension.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 ProjectCloudUIExtension.cpp
7
8 Dmitry Vedenko
9
10**********************************************************************/
12
13#include <wx/log.h>
14
17
24
27
28#include "OAuthService.h"
29#include "ServiceConfig.h"
30#include "UserService.h"
31
32#include "BasicUI.h"
33#include "CodeConversions.h"
34#include "Project.h"
35
37{
38namespace
39{
42 { return std::make_shared<ProjectCloudUIExtension>(project); }
43};
44
47} };
48} // namespace
49
51 : mProject { project }
52 , mCloudStatusChangedSubscription {
53 ProjectCloudExtension::Get(project).SubscribeStatusChanged(
54 [this](const auto& status) { OnCloudStatusChanged(status); }, true)
55 }
56{
57}
58
59ProjectCloudUIExtension::~ProjectCloudUIExtension() = default;
60
62{
63 return project.AttachedObjects::Get<ProjectCloudUIExtension&>(key);
64}
65
68{
69 return Get(const_cast<AudacityProject&>(project));
70}
71
72void ProjectCloudUIExtension::SetUploadProgress(double progress)
73{
74 mProgress = progress;
75}
76
77bool ProjectCloudUIExtension::AllowClosing()
78{
79 while (mInSync.load(std::memory_order_acquire) && !mClosingCancelled)
80 {
81 if (mProgressDialog == nullptr)
82 {
83 mProgressDialog = BasicUI::MakeProgress(
84 XO("Save to audio.com"),
85 XO("Project is syncing with audio.com. Do you want to stop the sync process?"),
87 }
88
89 const auto result = mProgressDialog->Poll(mProgress * 10000, 10000);
90
92 {
93 mClosingCancelled = true;
94 mProgressDialog.reset();
95 }
96
98 ProjectCloudExtension::Get(mProject).CancelSync();
99
101 }
102
103 bool closingCancelled = mClosingCancelled;
104 mClosingCancelled = false;
105
106 mProgressDialog.reset();
107
108 return !mInSync.load(std::memory_order_acquire) || !closingCancelled;
109}
110
111void ProjectCloudUIExtension::OnCloudStatusChanged(
112 const CloudStatusChangedMessage& message)
113{
114 mInSync = message.IsSyncing();
115
116 if (!mInSync)
117 mProgressDialog.reset();
118 else
119 SetUploadProgress(message.Progress);
120
121 // It the sync was successful - check for unsuccessful operations before
122 if (message.Status == ProjectSyncStatus::Synced)
124
125 if (message.Status != ProjectSyncStatus::Failed || !message.Error)
126 return;
127
128 const auto error = *message.Error;
129
130 switch (error.Type)
131 {
133 // How do we got here? Probable auth_token is invalid?
135 SaveToCloud(mProject, UploadMode::Normal);
136 break;
137 case CloudSyncError::ProjectLimitReached:
138 [[fallthrough]];
139 case CloudSyncError::ProjectStorageLimitReached:
140 {
141 auto result = ProjectLimitDialog { &mProject }.ShowDialog();
142
143 if (result == ProjectLimitDialog::VisitAudioComIdentifier())
144 {
145 auto& userService = GetUserService();
146 auto& oauthService = GetOAuthService();
147 auto& serviceConfig = GetServiceConfig();
148
149 const auto slug = audacity::ToUTF8(userService.GetUserSlug());
150 const auto projectsPath = serviceConfig.GetProjectsPagePath(slug, message.audiocomTrace);
151 const auto url = oauthService.MakeAudioComAuthorizeURL(slug, projectsPath);
152
154
156 &mProject,
157 XO("Waiting for space to free up"),
158 XO("Once you have made storage space available on audio.com, click Retry."),
159 }
160 .ShowDialog();
161 SaveToCloud(mProject, UploadMode::Normal);
162 }
163 else if (result == ProjectLimitDialog::SaveLocallyButtonIdentifier())
164 {
165 if (!ResaveLocally(mProject))
166 SaveToCloud(mProject, UploadMode::Normal);
167 }
168 }
169 break;
170 case CloudSyncError::ProjectVersionConflict:
171 {
172 if (
174 ProjectVersionConflictDialogMode::Save }
175 .ShowDialog() == ProjectVersionConflictDialog::UseLocalIdentifier())
176 {
177 SaveToCloud(mProject, UploadMode::ForceOverwrite);
178 }
179 else
180 {
181 ReopenProject(mProject);
182 }
183 }
184 break;
185 case CloudSyncError::ProjectNotFound:
186 {
187 if (
188 NotCloudProjectDialog { &mProject }.ShowDialog() ==
189 NotCloudProjectDialog::SaveLocallyIdentifier())
190 {
191 if (!ResaveLocally(mProject))
192 SaveToCloud(mProject, UploadMode::CreateNew);
193 }
194 else
195 {
196 SaveToCloud(mProject, UploadMode::CreateNew);
197 }
198 }
199 break;
200 case CloudSyncError::Network:
201 {
202 ConnectionIssuesDialog { &mProject }.ShowDialog();
203 }
204 break;
205 case CloudSyncError::DataUploadFailed:
206 [[fallthrough]];
207 case CloudSyncError::Server:
208 [[fallthrough]];
209 case CloudSyncError::ClientFailure:
211 break;
213 [[fallthrough]];
214 default:
215 break;
216 }
217
218 wxLogError(
219 "Cloud sync has failed: %s", audacity::ToWXString(error.ErrorMessage));
220}
221
222} // namespace audacity::cloud::audiocom::sync
Toolkit-neutral facade for basic user interface services.
Declare functions to perform UTF-8 to std::wstring conversions.
XO("Cut/Copy/Paste")
const auto project
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
Client code makes static instance from a factory of attachments; passes it to Get or Find as a retrie...
Definition: ClientData.h:275
typename GlobalVariable< OnCloseHook, const std::function< bool(AudacityProject &) >, nullptr, Options... >::Scope Scope
void UnlinkAccount(AudiocomTrace)
Removes access and refresh token, notifies about the logout.
DialogButtonIdentifier ShowDialog(std::function< DialogButtonIdentifier()> poller={})
static ProjectCloudUIExtension & Get(AudacityProject &project)
void OnCloudStatusChanged(const CloudStatusChangedMessage &message)
@ ProgressShowCancel
Definition: BasicUI.h:142
@ ProgressShowStop
Definition: BasicUI.h:141
bool OpenInDefaultBrowser(const wxString &url)
Open an URL in default browser.
Definition: BasicUI.cpp:246
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
Definition: BasicUI.cpp:202
void Yield()
Dispatch waiting events, including actions enqueued by CallAfter.
Definition: BasicUI.cpp:225
std::unique_ptr< ProgressDialog > MakeProgress(const TranslatableString &title, const TranslatableString &message, unsigned flags=(ProgressShowStop|ProgressShowCancel), const TranslatableString &remainingLabelText={})
Create and display a progress dialog.
Definition: BasicUI.h:302
void OnSave(const CommandContext &context)
Definition: FileMenus.cpp:254
void ReopenProject(AudacityProject &project)
bool ResaveLocally(AudacityProject &project)
void SaveToCloud(AudacityProject &project, UploadMode mode, CreateSnapshotCallback snapshotCallback)
void ResumeProjectUpload(ProjectCloudExtension &projectCloudExtension, std::function< void(AudiocomTrace)> onBeforeUploadStarts)
UserService & GetUserService()
OAuthService & GetOAuthService()
Returns the instance of the OAuthService.
const ServiceConfig & GetServiceConfig()
Returns the instance of the ServiceConfig.
std::string ToUTF8(const std::wstring &wstr)
wxString ToWXString(const std::string &str)