feat: new services description (#2412)

* feat: iap for apple now use storekit2

* fix: fixed error 101 on connection event

* feat: enhance StoreKit2Helper to handle entitlements and improve restore service from App Store functionality

* chore: add isInAppPurchase and isTestPurchase in primary config

* refactor: use end_date from primary config for renew ui

* fix: hide renew button for free

* fix: hide renew button for appstore purchases

* feat: add new premium info page

* feat: add new free info page

* chore: minor fixes

* refactor: move plan and benefits into separate models

* fix: fixed expired status when configs without an end date

* feat: add trial api support

* chore: add api message parsing for 422 error

* feat: move privacy policy and term of use to gateway

* feat: add iap support for new premium info page

* chore: minor fixes

* chore: minor fix

* chore: minor fixes

* feat: additional parsing for storekit subscription plans

* chore: minor codestyle fixes

* chore: simplify benefits

* chore: hide extend buttons on external premium

* feat: add trial error processing

* fix: remove wrong check from tiral handler

* chore: cleanup

---------

Co-authored-by: spectrum <yyy@amnezia.org>
This commit is contained in:
vkamn
2026-04-08 11:21:12 +07:00
committed by GitHub
parent bf3d11e5c4
commit 78f504e35c
51 changed files with 2372 additions and 930 deletions
@@ -20,9 +20,14 @@ PageType {
property var processedServer
property bool subscriptionExpired: false
property bool subscriptionExpiringSoon: false
property bool isSubscriptionRenewalAvailable: false
property bool isInAppPurchase: false
function updateSubscriptionState() {
root.subscriptionExpired = ServersModel.getProcessedServerData("isSubscriptionExpired")
root.subscriptionExpiringSoon = ServersModel.getProcessedServerData("isSubscriptionExpiringSoon")
root.isSubscriptionRenewalAvailable = ApiAccountInfoModel.data("isSubscriptionRenewalAvailable")
root.isInAppPurchase = ApiAccountInfoModel.data("isInAppPurchase")
}
Component.onCompleted: {
@@ -38,6 +43,14 @@ PageType {
}
}
Connections {
target: ApiAccountInfoModel
function onModelReset() {
root.updateSubscriptionState()
}
}
SortFilterProxyModel {
id: proxyServersModel
objectName: "proxyServersModel"
@@ -87,7 +100,7 @@ PageType {
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 16
Layout.bottomMargin: 4
Layout.bottomMargin: root.subscriptionExpired || root.subscriptionExpiringSoon ? 0 : 4
actionButtonImage: "qrc:/images/controls/settings.svg"
@@ -105,26 +118,27 @@ PageType {
}
}
CaptionTextType {
ParagraphTextType {
visible: root.subscriptionExpired || root.subscriptionExpiringSoon
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 16
Layout.topMargin: 4
Layout.topMargin: 12
text: root.subscriptionExpired ? qsTr("Subscription expired") : qsTr("Subscription expiring soon")
color: root.subscriptionExpired ? AmneziaStyle.color.vibrantRed : AmneziaStyle.color.goldenApricot
}
BasicButtonType {
visible: root.subscriptionExpired || root.subscriptionExpiringSoon
visible: (root.subscriptionExpired || root.subscriptionExpiringSoon)
&& root.isSubscriptionRenewalAvailable && !root.isInAppPurchase
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 16
Layout.topMargin: 8
Layout.bottomMargin: 4
Layout.topMargin: 28
Layout.bottomMargin: 0
defaultColor: AmneziaStyle.color.paleGray
hoveredColor: AmneziaStyle.color.lightGray
@@ -138,11 +152,11 @@ PageType {
}
}
CaptionTextType {
ParagraphTextType {
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 16
Layout.topMargin: (root.subscriptionExpired || root.subscriptionExpiringSoon) ? 8 : 4
Layout.topMargin: (root.subscriptionExpired || root.subscriptionExpiringSoon) ? 12 : 4
Layout.bottomMargin: 8
text: qsTr("Location for connection")