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 const auto slug = audacity::ToUTF8(GetUserService().GetUserSlug());
146
148 GetServiceConfig().GetProjectsPageUrl(slug));
149
151 &mProject,
152 XO("Waiting for space to free up"),
153 XO("Once you have made storage space available on audio.com, click Retry."),
154 }
155 .ShowDialog();
156 SaveToCloud(mProject, UploadMode::Normal);
157 }
158 else if (result == ProjectLimitDialog::SaveLocallyButtonIdentifier())
159 {
160 if (!ResaveLocally(mProject))
161 SaveToCloud(mProject, UploadMode::Normal);
162 }
163 }
164 break;
165 case CloudSyncError::ProjectVersionConflict:
166 {
167 if (
169 ProjectVersionConflictDialogMode::Save }
170 .ShowDialog() == ProjectVersionConflictDialog::UseLocalIdentifier())
171 {
172 SaveToCloud(mProject, UploadMode::ForceOverwrite);
173 }
174 else
175 {
176 ReopenProject(mProject);
177 }
178 }
179 break;
180 case CloudSyncError::ProjectNotFound:
181 {
182 if (
183 NotCloudProjectDialog { &mProject }.ShowDialog() ==
184 NotCloudProjectDialog::SaveLocallyIdentifier())
185 {
186 if (!ResaveLocally(mProject))
187 SaveToCloud(mProject, UploadMode::CreateNew);
188 }
189 else
190 {
191 SaveToCloud(mProject, UploadMode::CreateNew);
192 }
193 }
194 break;
195 case CloudSyncError::Network:
196 {
197 ConnectionIssuesDialog { &mProject }.ShowDialog();
198 }
199 break;
200 case CloudSyncError::DataUploadFailed:
201 [[fallthrough]];
202 case CloudSyncError::Server:
203 [[fallthrough]];
204 case CloudSyncError::ClientFailure:
206 break;
208 [[fallthrough]];
209 default:
210 break;
211 }
212
213 wxLogError(
214 "Cloud sync has failed: %s", audacity::ToWXString(error.ErrorMessage));
215}
216
217} // 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()
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:244
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
Definition: BasicUI.cpp:200
void Yield()
Dispatch waiting events, including actions enqueued by CallAfter.
Definition: BasicUI.cpp:223
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:294
void OnSave(const CommandContext &context)
Definition: FileMenus.cpp:252
void ReopenProject(AudacityProject &project)
bool ResaveLocally(AudacityProject &project)
void SaveToCloud(AudacityProject &project, UploadMode mode, CreateSnapshotCallback snapshotCallback)
void ResumeProjectUpload(ProjectCloudExtension &projectCloudExtension, std::function< void()> 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)