diff --git a/app/images/ReachedMonthlyContributorLimit.svg b/app/images/ReachedMonthlyContributorLimit.svg
new file mode 100644
index 000000000..c6f1c4a51
--- /dev/null
+++ b/app/images/ReachedMonthlyContributorLimit.svg
@@ -0,0 +1,24 @@
+
diff --git a/app/images/images.qrc b/app/images/images.qrc
index b0b772a30..ef3cf2f4f 100644
--- a/app/images/images.qrc
+++ b/app/images/images.qrc
@@ -35,5 +35,6 @@
SignIn.svg
NoWorkspace.svg
BlueInfo.svg
+ ReachedMonthlyContributorLimit.svg
diff --git a/app/mmstyle.h b/app/mmstyle.h
index 16587bb81..b51d4f8ea 100644
--- a/app/mmstyle.h
+++ b/app/mmstyle.h
@@ -198,6 +198,7 @@ class MMStyle: public QObject
Q_PROPERTY( QUrl acceptInvitationImage READ acceptInvitationImage CONSTANT )
Q_PROPERTY( QUrl acceptInvitationLogoImage READ acceptInvitationLogoImage CONSTANT )
Q_PROPERTY( QUrl reachedDataLimitImage READ reachedDataLimitImage CONSTANT )
+ Q_PROPERTY( QUrl reachedMonthlyContributorLimitImage READ reachedMonthlyContributorLimitImage CONSTANT )
Q_PROPERTY( QUrl uploadImage READ uploadImage CONSTANT )
Q_PROPERTY( QUrl noMapThemesImage READ noMapThemesImage CONSTANT )
Q_PROPERTY( QUrl syncFailedImage READ syncFailedImage CONSTANT )
@@ -496,6 +497,7 @@ class MMStyle: public QObject
QUrl noPermissionsImage() {return QUrl( "qrc:/images/NoPermissions.svg" );}
QUrl signInImage() {return QUrl( "qrc:/images/SignIn.svg" );}
QUrl reachedDataLimitImage() {return QUrl( "qrc:/images/ReachedDataLimit.svg" );}
+ QUrl reachedMonthlyContributorLimitImage() {return QUrl( "qrc:/images/ReachedMonthlyContributorLimit.svg" );}
QUrl warnLogoImage() {return QUrl( "qrc:/images/WarnLogoImage.svg" );}
QUrl mapPinImage() {return QUrl( "qrc:/images/MapPin.svg" );}
QUrl positionTrackingRunningImage() {return QUrl( "qrc:/images/PositionTrackingRunning.svg" );}
diff --git a/app/qml/CMakeLists.txt b/app/qml/CMakeLists.txt
index ccf99a8d5..9caf23291 100644
--- a/app/qml/CMakeLists.txt
+++ b/app/qml/CMakeLists.txt
@@ -59,6 +59,7 @@ set(MM_QML
dialogs/MMDownloadProjectDialog.qml
dialogs/MMMigrateToMerginDialog.qml
dialogs/MMMissingAuthDialog.qml
+ dialogs/MMMonthlyContributorsLimitDialog.qml
dialogs/MMNoPermissionsDialog.qml
dialogs/MMPositionTrackingDialog.qml
dialogs/MMProjectLimitDialog.qml
diff --git a/app/qml/dialogs/MMMonthlyContributorsLimitDialog.qml b/app/qml/dialogs/MMMonthlyContributorsLimitDialog.qml
new file mode 100644
index 000000000..1c3f923f0
--- /dev/null
+++ b/app/qml/dialogs/MMMonthlyContributorsLimitDialog.qml
@@ -0,0 +1,38 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+import QtQuick
+
+import "../components" as MMComponents
+
+
+MMComponents.MMDrawerDialog {
+ id: root
+
+ property int contributorsQuota
+
+ signal manageAccountClicked()
+
+ title: qsTr( "You've reached the maximum number of active monthly contributors (%1) for your current subscription." ).arg( contributorsQuota )
+ imageSource: __style.reachedMonthlyContributorLimitImage
+
+ description: qsTr( "Upgrade your subscription or wait until next month for the limit to reset." )
+
+ primaryButton.text: qsTr( "Upgrade" )
+ secondaryButton.text: qsTr( "Cancel" )
+
+ onPrimaryButtonClicked: {
+ root.manageAccountClicked()
+ close()
+ }
+
+ onSecondaryButtonClicked: {
+ close()
+ }
+}
diff --git a/app/qml/main.qml b/app/qml/main.qml
index d6b7ea116..4769ffa73 100644
--- a/app/qml/main.qml
+++ b/app/qml/main.qml
@@ -715,6 +715,12 @@ ApplicationWindow {
onManageAccountClicked: Qt.openUrlExternally(__inputHelp.merginSubscriptionLink)
}
+ MMMonthlyContributorsLimitDialog {
+ id: monthlyContributorsLimitDialog
+
+ onManageAccountClicked: Qt.openUrlExternally(__inputHelp.merginSubscriptionLink)
+ }
+
MMProjectLimitDialog {
id: projectLimitDialog
@@ -895,6 +901,11 @@ ApplicationWindow {
storageLimitDialog.open()
}
+ function onMonthlyContributorLimitReached( quota, serverMsg ) {
+ monthlyContributorsLimitDialog.contributorsQuota = quota
+ monthlyContributorsLimitDialog.open()
+ }
+
function onProjectLimitReached( maxProjects, errorMsg ) {
__merginApi.getUserInfo()
if (__merginApi.apiSupportsSubscriptions) {
@@ -914,7 +925,7 @@ ApplicationWindow {
}
function onMigrationRequested( version ) {
- if( __appSettings.ignoreMigrateVersion !== version ) {
+ if ( __appSettings.ignoreMigrateVersion !== version ) {
migrationDialog.version = version
migrationDialog.open()
}
diff --git a/core/merginapi.cpp b/core/merginapi.cpp
index ab5e4a618..b385c6e9f 100644
--- a/core/merginapi.cpp
+++ b/core/merginapi.cpp
@@ -2117,14 +2117,13 @@ void MerginApi::pushStartReplyFinished()
serverMsg = sSyncCanceledMessage;
QString code = extractServerErrorCode( data );
- bool showLimitReachedDialog = EnumHelper::isEqual( code, ErrorCode::StorageLimitHit );
CoreUtils::log( "push " + projectFullName, QStringLiteral( "FAILED - %1. %2" ).arg( r->errorString(), serverMsg ) );
transaction.replyPushStart->deleteLater();
transaction.replyPushStart = nullptr;
- if ( showLimitReachedDialog )
+ if ( EnumHelper::isEqual( code, ErrorCode::StorageLimitHit ) )
{
const QList files = transaction.pushQueue;
qreal uploadSize = 0;
@@ -2144,6 +2143,14 @@ void MerginApi::pushStartReplyFinished()
deleteProject( projectNamespace, projectName, false );
}
}
+ else if ( EnumHelper::isEqual( code, ErrorCode::MonthlyContributorsLimitHit ) )
+ {
+ int quota = 0;
+ QVariant maximunMonthlyContributor = extractServerErrorValue( data, "projects_quota" );
+ if ( maximunMonthlyContributor.isValid() )
+ quota = maximunMonthlyContributor.toInt();
+ emit monthlyContributorLimitReached( quota, serverMsg );
+ }
else
{
int httpCode = r->attribute( QNetworkRequest::HttpStatusCodeAttribute ).toInt();
diff --git a/core/merginapi.h b/core/merginapi.h
index 0e5380bb2..8e7ef31d7 100644
--- a/core/merginapi.h
+++ b/core/merginapi.h
@@ -195,7 +195,8 @@ class ErrorCode
{
Unknown = 0,
ProjectsLimitHit,
- StorageLimitHit
+ StorageLimitHit,
+ MonthlyContributorsLimitHit,
};
Q_ENUM( Value );
};
@@ -597,6 +598,7 @@ class MerginApi: public QObject
);
void storageLimitReached( qreal uploadSize );
+ void monthlyContributorLimitReached( int contributorsQuota, const QString &message );
void projectLimitReached( int maxProjects, const QString &message );
void migrationRequested( const QString &version );
void notifySuccess( const QString &message );
diff --git a/gallery/qml.qrc b/gallery/qml.qrc
index b54c2ff92..d19fa58e4 100644
--- a/gallery/qml.qrc
+++ b/gallery/qml.qrc
@@ -30,6 +30,7 @@
../app/qml/dialogs/MMStreamingModeDialog.qml
../app/qml/dialogs/MMPositionTrackingDialog.qml
../app/qml/dialogs/MMStorageLimitDialog.qml
+ ../app/qml/dialogs/MMMonthlyContributorsLimitDialog.qml
../app/qml/dialogs/MMCloseAccountDialog.qml
../app/qml/dialogs/MMRemoveProjectDialog.qml
../app/qml/dialogs/MMDownloadProjectDialog.qml
diff --git a/gallery/qml/pages/DrawerPage.qml b/gallery/qml/pages/DrawerPage.qml
index e3400a423..8304e7ecc 100644
--- a/gallery/qml/pages/DrawerPage.qml
+++ b/gallery/qml/pages/DrawerPage.qml
@@ -38,6 +38,11 @@ Page {
onClicked: storageLimitDialog.open()
}
+ Button {
+ text: "MMMonthlyContributorsLimitDialog"
+ onClicked: monthlyContributorsLimitDialog.open()
+ }
+
Button {
text: "MMCloseAccountDialog"
onClicked: closeAccountDialog.open()
@@ -289,6 +294,16 @@ Page {
}
}
+ MMMonthlyContributorsLimitDialog {
+ id: monthlyContributorsLimitDialog
+
+ contributorsQuota: 15
+
+ onPrimaryButtonClicked: {
+ console.log("Manage workspace clicked")
+ }
+ }
+
MMSyncFailedDialog {
id: syncFailedDialog
}
diff --git a/gallery/qml/pages/ImagesPage.qml b/gallery/qml/pages/ImagesPage.qml
index ed931d11b..bc4532417 100644
--- a/gallery/qml/pages/ImagesPage.qml
+++ b/gallery/qml/pages/ImagesPage.qml
@@ -41,6 +41,7 @@ ScrollView {
Column { Image { source: __style.externalGpsGreenImage } Text { text: "externalGpsGreenImage" } }
Column { Image { source: __style.externalGpsRedImage } Text { text: "externalGpsRedImage" } }
Column { Image { source: __style.reachedDataLimitImage } Text { text: "reachedDataLimitImage" } }
+ Column { Image { source: __style.reachedMonthlyContributorLimitImage } Text { text: "reachedMonthlyContributorLimitImage" } }
Column { Image { source: __style.positiveMMSymbolImage } Text { text: "positiveMMSymbolImage" } }
Column { Image { source: __style.negativeMMSymbolImage } Text { text: "negativeMMSymbolImage" } }
Column { Image { source: __style.closeAccountImage } Text { text: "closeAccountImage" } }