mirror of
https://github.com/passepartoutvpn/passepartout-apple.git
synced 2025-02-20 23:02:14 +00:00
Show the list of features included in each product (#1157)
List product features inline in the paywall. Inside the list, highlight the required features that originated the paywall.
This commit is contained in:
parent
954475e117
commit
914520009a
@ -55,6 +55,7 @@ struct InstalledProfileView: View, Routable {
|
|||||||
toggleButton
|
toggleButton
|
||||||
}
|
}
|
||||||
.modifier(HeaderModifier(layout: layout))
|
.modifier(HeaderModifier(layout: layout))
|
||||||
|
.unanimated()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -786,20 +786,20 @@ public enum Strings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public enum Product {
|
||||||
|
/// Included features
|
||||||
|
public static let includedFeatures = Strings.tr("Localizable", "views.paywall.product.included_features", fallback: "Included features")
|
||||||
|
}
|
||||||
public enum Rows {
|
public enum Rows {
|
||||||
/// Restore purchases
|
/// Restore purchases
|
||||||
public static let restorePurchases = Strings.tr("Localizable", "views.paywall.rows.restore_purchases", fallback: "Restore purchases")
|
public static let restorePurchases = Strings.tr("Localizable", "views.paywall.rows.restore_purchases", fallback: "Restore purchases")
|
||||||
}
|
}
|
||||||
public enum Sections {
|
public enum Sections {
|
||||||
public enum IncludedFeatures {
|
|
||||||
/// Also includes
|
|
||||||
public static let header = Strings.tr("Localizable", "views.paywall.sections.included_features.header", fallback: "Also includes")
|
|
||||||
}
|
|
||||||
public enum Products {
|
public enum Products {
|
||||||
/// All purchases support Family Sharing.
|
/// All purchases support Family Sharing.
|
||||||
public static let footer = Strings.tr("Localizable", "views.paywall.sections.products.footer", fallback: "All purchases support Family Sharing.")
|
public static let footer = Strings.tr("Localizable", "views.paywall.sections.products.footer", fallback: "All purchases support Family Sharing.")
|
||||||
/// Available products
|
/// Suggested products
|
||||||
public static let header = Strings.tr("Localizable", "views.paywall.sections.products.header", fallback: "Available products")
|
public static let header = Strings.tr("Localizable", "views.paywall.sections.products.header", fallback: "Suggested products")
|
||||||
}
|
}
|
||||||
public enum RequiredFeatures {
|
public enum RequiredFeatures {
|
||||||
/// Required features
|
/// Required features
|
||||||
|
@ -260,12 +260,13 @@
|
|||||||
"views.paywall.alerts.verification.connect.1" = "Ihre Käufe werden überprüft.";
|
"views.paywall.alerts.verification.connect.1" = "Ihre Käufe werden überprüft.";
|
||||||
"views.paywall.alerts.verification.connect.2" = "Falls die Überprüfung nicht abgeschlossen werden kann, wird die Verbindung in %d Minuten beendet.";
|
"views.paywall.alerts.verification.connect.2" = "Falls die Überprüfung nicht abgeschlossen werden kann, wird die Verbindung in %d Minuten beendet.";
|
||||||
"views.paywall.alerts.verification.edit" = "Bitte warten Sie, während Ihre Käufe überprüft werden.";
|
"views.paywall.alerts.verification.edit" = "Bitte warten Sie, während Ihre Käufe überprüft werden.";
|
||||||
|
"views.paywall.product.included_features" = "Enthaltene Funktionen";
|
||||||
"views.paywall.rows.restore_purchases" = "Käufe wiederherstellen";
|
"views.paywall.rows.restore_purchases" = "Käufe wiederherstellen";
|
||||||
"views.paywall.sections.all_features.header" = "Die Vollversion enthält";
|
"views.paywall.sections.all_features.header" = "Die Vollversion enthält";
|
||||||
"views.paywall.sections.full_products.header" = "Vollversion";
|
"views.paywall.sections.full_products.header" = "Vollversion";
|
||||||
"views.paywall.sections.included_features.header" = "Enthält außerdem";
|
"views.paywall.sections.included_features.header" = "Enthält außerdem";
|
||||||
"views.paywall.sections.products.footer" = "Alle Käufe unterstützen die Familienfreigabe.";
|
"views.paywall.sections.products.footer" = "Alle Käufe unterstützen die Familienfreigabe.";
|
||||||
"views.paywall.sections.products.header" = "Verfügbare Produkte";
|
"views.paywall.sections.products.header" = "Empfohlene Produkte";
|
||||||
"views.paywall.sections.required_features.header" = "Erforderliche Funktionen";
|
"views.paywall.sections.required_features.header" = "Erforderliche Funktionen";
|
||||||
"views.paywall.sections.restore.footer" = "Wenn du diese App oder Funktion in der Vergangenheit gekauft hast, kannst du deine Käufe wiederherstellen.";
|
"views.paywall.sections.restore.footer" = "Wenn du diese App oder Funktion in der Vergangenheit gekauft hast, kannst du deine Käufe wiederherstellen.";
|
||||||
"views.paywall.sections.restore.header" = "Wiederherstellen";
|
"views.paywall.sections.restore.header" = "Wiederherstellen";
|
||||||
|
@ -260,12 +260,13 @@
|
|||||||
"views.paywall.alerts.verification.connect.1" = "Οι αγορές σας επαληθεύονται.";
|
"views.paywall.alerts.verification.connect.1" = "Οι αγορές σας επαληθεύονται.";
|
||||||
"views.paywall.alerts.verification.connect.2" = "Αν η επαλήθευση δεν ολοκληρωθεί, η σύνδεση θα τερματιστεί σε %d λεπτά.";
|
"views.paywall.alerts.verification.connect.2" = "Αν η επαλήθευση δεν ολοκληρωθεί, η σύνδεση θα τερματιστεί σε %d λεπτά.";
|
||||||
"views.paywall.alerts.verification.edit" = "Παρακαλώ περιμένετε όσο επαληθεύονται οι αγορές σας.";
|
"views.paywall.alerts.verification.edit" = "Παρακαλώ περιμένετε όσο επαληθεύονται οι αγορές σας.";
|
||||||
|
"views.paywall.product.included_features" = "Περιλαμβανόμενες λειτουργίες";
|
||||||
"views.paywall.rows.restore_purchases" = "Επαναφορά αγορών";
|
"views.paywall.rows.restore_purchases" = "Επαναφορά αγορών";
|
||||||
"views.paywall.sections.all_features.header" = "Η πλήρης έκδοση περιλαμβάνει";
|
"views.paywall.sections.all_features.header" = "Η πλήρης έκδοση περιλαμβάνει";
|
||||||
"views.paywall.sections.full_products.header" = "Πλήρης έκδοση";
|
"views.paywall.sections.full_products.header" = "Πλήρης έκδοση";
|
||||||
"views.paywall.sections.included_features.header" = "Περιλαμβάνει επίσης";
|
"views.paywall.sections.included_features.header" = "Περιλαμβάνει επίσης";
|
||||||
"views.paywall.sections.products.footer" = "Όλες οι αγορές υποστηρίζουν την Οικογενειακή Κοινή Χρήση.";
|
"views.paywall.sections.products.footer" = "Όλες οι αγορές υποστηρίζουν την Οικογενειακή Κοινή Χρήση.";
|
||||||
"views.paywall.sections.products.header" = "Διαθέσιμα προϊόντα";
|
"views.paywall.sections.products.header" = "Προτεινόμενα προϊόντα";
|
||||||
"views.paywall.sections.required_features.header" = "Απαιτούμενες λειτουργίες";
|
"views.paywall.sections.required_features.header" = "Απαιτούμενες λειτουργίες";
|
||||||
"views.paywall.sections.restore.footer" = "Εάν αγοράσατε αυτήν την εφαρμογή ή λειτουργία στο παρελθόν, μπορείτε να επαναφέρετε τις αγορές σας.";
|
"views.paywall.sections.restore.footer" = "Εάν αγοράσατε αυτήν την εφαρμογή ή λειτουργία στο παρελθόν, μπορείτε να επαναφέρετε τις αγορές σας.";
|
||||||
"views.paywall.sections.restore.header" = "Επαναφορά";
|
"views.paywall.sections.restore.header" = "Επαναφορά";
|
||||||
|
@ -78,12 +78,12 @@
|
|||||||
"views.migration.alerts.delete.message" = "Do you want to discard these profiles? You will not be able to recover them later.\n\n%@";
|
"views.migration.alerts.delete.message" = "Do you want to discard these profiles? You will not be able to recover them later.\n\n%@";
|
||||||
|
|
||||||
"views.paywall.sections.required_features.header" = "Required features";
|
"views.paywall.sections.required_features.header" = "Required features";
|
||||||
"views.paywall.sections.included_features.header" = "Also includes";
|
"views.paywall.sections.products.header" = "Suggested products";
|
||||||
"views.paywall.sections.products.header" = "Available products";
|
|
||||||
"views.paywall.sections.products.footer" = "All purchases support Family Sharing.";
|
"views.paywall.sections.products.footer" = "All purchases support Family Sharing.";
|
||||||
"views.paywall.sections.restore.header" = "Restore";
|
"views.paywall.sections.restore.header" = "Restore";
|
||||||
"views.paywall.sections.restore.footer" = "If you bought this app or feature in the past, you can restore your purchases.";
|
"views.paywall.sections.restore.footer" = "If you bought this app or feature in the past, you can restore your purchases.";
|
||||||
"views.paywall.rows.restore_purchases" = "Restore purchases";
|
"views.paywall.rows.restore_purchases" = "Restore purchases";
|
||||||
|
"views.paywall.product.included_features" = "Included features";
|
||||||
"views.paywall.alerts.confirmation.title" = "Purchase required";
|
"views.paywall.alerts.confirmation.title" = "Purchase required";
|
||||||
"views.paywall.alerts.confirmation.message" = "This profile requires paid features to work.";
|
"views.paywall.alerts.confirmation.message" = "This profile requires paid features to work.";
|
||||||
"views.paywall.alerts.confirmation.message.connect" = "You may test the connection for %d minutes.";
|
"views.paywall.alerts.confirmation.message.connect" = "You may test the connection for %d minutes.";
|
||||||
|
@ -260,12 +260,13 @@
|
|||||||
"views.paywall.alerts.verification.connect.1" = "Tus compras están siendo verificadas.";
|
"views.paywall.alerts.verification.connect.1" = "Tus compras están siendo verificadas.";
|
||||||
"views.paywall.alerts.verification.connect.2" = "Si la verificación no se completa, la conexión finalizará en %d minutos.";
|
"views.paywall.alerts.verification.connect.2" = "Si la verificación no se completa, la conexión finalizará en %d minutos.";
|
||||||
"views.paywall.alerts.verification.edit" = "Por favor, espera mientras verificamos tus compras.";
|
"views.paywall.alerts.verification.edit" = "Por favor, espera mientras verificamos tus compras.";
|
||||||
|
"views.paywall.product.included_features" = "Funciones incluidas";
|
||||||
"views.paywall.rows.restore_purchases" = "Restaurar compras";
|
"views.paywall.rows.restore_purchases" = "Restaurar compras";
|
||||||
"views.paywall.sections.all_features.header" = "La versión completa incluye";
|
"views.paywall.sections.all_features.header" = "La versión completa incluye";
|
||||||
"views.paywall.sections.full_products.header" = "Versión completa";
|
"views.paywall.sections.full_products.header" = "Versión completa";
|
||||||
"views.paywall.sections.included_features.header" = "También incluye";
|
"views.paywall.sections.included_features.header" = "También incluye";
|
||||||
"views.paywall.sections.products.footer" = "Todas las compras admiten En Familia.";
|
"views.paywall.sections.products.footer" = "Todas las compras admiten En Familia.";
|
||||||
"views.paywall.sections.products.header" = "Productos disponibles";
|
"views.paywall.sections.products.header" = "Productos sugeridos";
|
||||||
"views.paywall.sections.required_features.header" = "Características requeridas";
|
"views.paywall.sections.required_features.header" = "Características requeridas";
|
||||||
"views.paywall.sections.restore.footer" = "Si compraste esta app o característica en el pasado, puedes restaurar tus compras.";
|
"views.paywall.sections.restore.footer" = "Si compraste esta app o característica en el pasado, puedes restaurar tus compras.";
|
||||||
"views.paywall.sections.restore.header" = "Restaurar";
|
"views.paywall.sections.restore.header" = "Restaurar";
|
||||||
|
@ -260,12 +260,13 @@
|
|||||||
"views.paywall.alerts.verification.connect.1" = "Vos achats sont en cours de vérification.";
|
"views.paywall.alerts.verification.connect.1" = "Vos achats sont en cours de vérification.";
|
||||||
"views.paywall.alerts.verification.connect.2" = "Si la vérification ne peut être complétée, la connexion s’arrêtera dans %d minutes.";
|
"views.paywall.alerts.verification.connect.2" = "Si la vérification ne peut être complétée, la connexion s’arrêtera dans %d minutes.";
|
||||||
"views.paywall.alerts.verification.edit" = "Veuillez patienter pendant la vérification de vos achats.";
|
"views.paywall.alerts.verification.edit" = "Veuillez patienter pendant la vérification de vos achats.";
|
||||||
|
"views.paywall.product.included_features" = "Fonctionnalités incluses";
|
||||||
"views.paywall.rows.restore_purchases" = "Restaurer les achats";
|
"views.paywall.rows.restore_purchases" = "Restaurer les achats";
|
||||||
"views.paywall.sections.all_features.header" = "La version complète inclut";
|
"views.paywall.sections.all_features.header" = "La version complète inclut";
|
||||||
"views.paywall.sections.full_products.header" = "Version complète";
|
"views.paywall.sections.full_products.header" = "Version complète";
|
||||||
"views.paywall.sections.included_features.header" = "Comprend également";
|
"views.paywall.sections.included_features.header" = "Comprend également";
|
||||||
"views.paywall.sections.products.footer" = "Tous les achats prennent en charge le Partage familial.";
|
"views.paywall.sections.products.footer" = "Tous les achats prennent en charge le Partage familial.";
|
||||||
"views.paywall.sections.products.header" = "Produits disponibles";
|
"views.paywall.sections.products.header" = "Produits suggérés";
|
||||||
"views.paywall.sections.required_features.header" = "Fonctionnalités requises";
|
"views.paywall.sections.required_features.header" = "Fonctionnalités requises";
|
||||||
"views.paywall.sections.restore.footer" = "Si vous avez acheté cette application ou cette fonctionnalité dans le passé, vous pouvez restaurer vos achats.";
|
"views.paywall.sections.restore.footer" = "Si vous avez acheté cette application ou cette fonctionnalité dans le passé, vous pouvez restaurer vos achats.";
|
||||||
"views.paywall.sections.restore.header" = "Restaurer";
|
"views.paywall.sections.restore.header" = "Restaurer";
|
||||||
|
@ -260,12 +260,13 @@
|
|||||||
"views.paywall.alerts.verification.connect.1" = "I tuoi acquisti sono in fase di verifica.";
|
"views.paywall.alerts.verification.connect.1" = "I tuoi acquisti sono in fase di verifica.";
|
||||||
"views.paywall.alerts.verification.connect.2" = "Se la verifica non può essere completata, la connessione terminerà tra %d minuti.";
|
"views.paywall.alerts.verification.connect.2" = "Se la verifica non può essere completata, la connessione terminerà tra %d minuti.";
|
||||||
"views.paywall.alerts.verification.edit" = "Attendere mentre i tuoi acquisti vengono verificati.";
|
"views.paywall.alerts.verification.edit" = "Attendere mentre i tuoi acquisti vengono verificati.";
|
||||||
|
"views.paywall.product.included_features" = "Funzionalità incluse";
|
||||||
"views.paywall.rows.restore_purchases" = "Ripristina acquisti";
|
"views.paywall.rows.restore_purchases" = "Ripristina acquisti";
|
||||||
"views.paywall.sections.all_features.header" = "La versione completa include";
|
"views.paywall.sections.all_features.header" = "La versione completa include";
|
||||||
"views.paywall.sections.full_products.header" = "Versione completa";
|
"views.paywall.sections.full_products.header" = "Versione completa";
|
||||||
"views.paywall.sections.included_features.header" = "Include anche";
|
"views.paywall.sections.included_features.header" = "Include anche";
|
||||||
"views.paywall.sections.products.footer" = "Tutti gli acquisti supportano “In famiglia”.";
|
"views.paywall.sections.products.footer" = "Tutti gli acquisti supportano “In famiglia”.";
|
||||||
"views.paywall.sections.products.header" = "Prodotti disponibili";
|
"views.paywall.sections.products.header" = "Prodotti suggeriti";
|
||||||
"views.paywall.sections.required_features.header" = "Funzionalità richieste";
|
"views.paywall.sections.required_features.header" = "Funzionalità richieste";
|
||||||
"views.paywall.sections.restore.footer" = "Se hai acquistato questa app o funzionalità in passato, puoi ripristinare i tuoi acquisti.";
|
"views.paywall.sections.restore.footer" = "Se hai acquistato questa app o funzionalità in passato, puoi ripristinare i tuoi acquisti.";
|
||||||
"views.paywall.sections.restore.header" = "Ripristina";
|
"views.paywall.sections.restore.header" = "Ripristina";
|
||||||
|
@ -260,12 +260,13 @@
|
|||||||
"views.paywall.alerts.verification.connect.1" = "Je aankopen worden geverifieerd.";
|
"views.paywall.alerts.verification.connect.1" = "Je aankopen worden geverifieerd.";
|
||||||
"views.paywall.alerts.verification.connect.2" = "Als de verificatie niet kan worden voltooid, wordt de verbinding over %d minuten beëindigd.";
|
"views.paywall.alerts.verification.connect.2" = "Als de verificatie niet kan worden voltooid, wordt de verbinding over %d minuten beëindigd.";
|
||||||
"views.paywall.alerts.verification.edit" = "Even geduld terwijl we je aankopen verifiëren.";
|
"views.paywall.alerts.verification.edit" = "Even geduld terwijl we je aankopen verifiëren.";
|
||||||
|
"views.paywall.product.included_features" = "Inbegrepen functies";
|
||||||
"views.paywall.rows.restore_purchases" = "Aankopen herstellen";
|
"views.paywall.rows.restore_purchases" = "Aankopen herstellen";
|
||||||
"views.paywall.sections.all_features.header" = "De volledige versie bevat";
|
"views.paywall.sections.all_features.header" = "De volledige versie bevat";
|
||||||
"views.paywall.sections.full_products.header" = "Volledige versie";
|
"views.paywall.sections.full_products.header" = "Volledige versie";
|
||||||
"views.paywall.sections.included_features.header" = "Bevat ook";
|
"views.paywall.sections.included_features.header" = "Bevat ook";
|
||||||
"views.paywall.sections.products.footer" = "Alle aankopen ondersteunen Delen met gezin.";
|
"views.paywall.sections.products.footer" = "Alle aankopen ondersteunen Delen met gezin.";
|
||||||
"views.paywall.sections.products.header" = "Beschikbare producten";
|
"views.paywall.sections.products.header" = "Voorgestelde producten";
|
||||||
"views.paywall.sections.required_features.header" = "Vereiste functies";
|
"views.paywall.sections.required_features.header" = "Vereiste functies";
|
||||||
"views.paywall.sections.restore.footer" = "Als je deze app of functie eerder hebt gekocht, kun je je aankopen herstellen.";
|
"views.paywall.sections.restore.footer" = "Als je deze app of functie eerder hebt gekocht, kun je je aankopen herstellen.";
|
||||||
"views.paywall.sections.restore.header" = "Herstellen";
|
"views.paywall.sections.restore.header" = "Herstellen";
|
||||||
|
@ -260,12 +260,13 @@
|
|||||||
"views.paywall.alerts.verification.connect.1" = "Twoje zakupy są weryfikowane.";
|
"views.paywall.alerts.verification.connect.1" = "Twoje zakupy są weryfikowane.";
|
||||||
"views.paywall.alerts.verification.connect.2" = "Jeśli weryfikacja nie zostanie zakończona, połączenie zostanie zakończone za %d minut.";
|
"views.paywall.alerts.verification.connect.2" = "Jeśli weryfikacja nie zostanie zakończona, połączenie zostanie zakończone za %d minut.";
|
||||||
"views.paywall.alerts.verification.edit" = "Proszę czekać, trwa weryfikacja zakupów.";
|
"views.paywall.alerts.verification.edit" = "Proszę czekać, trwa weryfikacja zakupów.";
|
||||||
|
"views.paywall.product.included_features" = "Uwzględnione funkcje";
|
||||||
"views.paywall.rows.restore_purchases" = "Przywróć zakupy";
|
"views.paywall.rows.restore_purchases" = "Przywróć zakupy";
|
||||||
"views.paywall.sections.all_features.header" = "Pełna wersja zawiera";
|
"views.paywall.sections.all_features.header" = "Pełna wersja zawiera";
|
||||||
"views.paywall.sections.full_products.header" = "Pełna wersja";
|
"views.paywall.sections.full_products.header" = "Pełna wersja";
|
||||||
"views.paywall.sections.included_features.header" = "Zawiera także";
|
"views.paywall.sections.included_features.header" = "Zawiera także";
|
||||||
"views.paywall.sections.products.footer" = "Wszystkie zakupy obsługują Chmurę rodzinną.";
|
"views.paywall.sections.products.footer" = "Wszystkie zakupy obsługują Chmurę rodzinną.";
|
||||||
"views.paywall.sections.products.header" = "Dostępne produkty";
|
"views.paywall.sections.products.header" = "Sugerowane produkty";
|
||||||
"views.paywall.sections.required_features.header" = "Wymagane funkcje";
|
"views.paywall.sections.required_features.header" = "Wymagane funkcje";
|
||||||
"views.paywall.sections.restore.footer" = "Jeśli wcześniej kupiłeś tę aplikację lub funkcję, możesz przywrócić swoje zakupy.";
|
"views.paywall.sections.restore.footer" = "Jeśli wcześniej kupiłeś tę aplikację lub funkcję, możesz przywrócić swoje zakupy.";
|
||||||
"views.paywall.sections.restore.header" = "Przywróć";
|
"views.paywall.sections.restore.header" = "Przywróć";
|
||||||
|
@ -260,12 +260,13 @@
|
|||||||
"views.paywall.alerts.verification.connect.1" = "Suas compras estão sendo verificadas.";
|
"views.paywall.alerts.verification.connect.1" = "Suas compras estão sendo verificadas.";
|
||||||
"views.paywall.alerts.verification.connect.2" = "Se a verificação não for concluída, a conexão será encerrada em %d minutos.";
|
"views.paywall.alerts.verification.connect.2" = "Se a verificação não for concluída, a conexão será encerrada em %d minutos.";
|
||||||
"views.paywall.alerts.verification.edit" = "Aguarde enquanto suas compras estão sendo verificadas.";
|
"views.paywall.alerts.verification.edit" = "Aguarde enquanto suas compras estão sendo verificadas.";
|
||||||
|
"views.paywall.product.included_features" = "Recursos incluídos";
|
||||||
"views.paywall.rows.restore_purchases" = "Restaurar compras";
|
"views.paywall.rows.restore_purchases" = "Restaurar compras";
|
||||||
"views.paywall.sections.all_features.header" = "A versão completa inclui";
|
"views.paywall.sections.all_features.header" = "A versão completa inclui";
|
||||||
"views.paywall.sections.full_products.header" = "Versão completa";
|
"views.paywall.sections.full_products.header" = "Versão completa";
|
||||||
"views.paywall.sections.included_features.header" = "Também inclui";
|
"views.paywall.sections.included_features.header" = "Também inclui";
|
||||||
"views.paywall.sections.products.footer" = "Todas as compras são compatíveis com Compartilhamento Familiar.";
|
"views.paywall.sections.products.footer" = "Todas as compras são compatíveis com Compartilhamento Familiar.";
|
||||||
"views.paywall.sections.products.header" = "Produtos disponíveis";
|
"views.paywall.sections.products.header" = "Produtos sugeridos";
|
||||||
"views.paywall.sections.required_features.header" = "Recursos necessários";
|
"views.paywall.sections.required_features.header" = "Recursos necessários";
|
||||||
"views.paywall.sections.restore.footer" = "Se você comprou este app ou recurso no passado, pode restaurar suas compras.";
|
"views.paywall.sections.restore.footer" = "Se você comprou este app ou recurso no passado, pode restaurar suas compras.";
|
||||||
"views.paywall.sections.restore.header" = "Restaurar";
|
"views.paywall.sections.restore.header" = "Restaurar";
|
||||||
|
@ -260,12 +260,13 @@
|
|||||||
"views.paywall.alerts.verification.connect.1" = "Ваши покупки проверяются.";
|
"views.paywall.alerts.verification.connect.1" = "Ваши покупки проверяются.";
|
||||||
"views.paywall.alerts.verification.connect.2" = "Если проверка не будет завершена, соединение завершится через %d минут.";
|
"views.paywall.alerts.verification.connect.2" = "Если проверка не будет завершена, соединение завершится через %d минут.";
|
||||||
"views.paywall.alerts.verification.edit" = "Пожалуйста, подождите, пока ваши покупки проверяются.";
|
"views.paywall.alerts.verification.edit" = "Пожалуйста, подождите, пока ваши покупки проверяются.";
|
||||||
|
"views.paywall.product.included_features" = "Включенные функции";
|
||||||
"views.paywall.rows.restore_purchases" = "Восстановить покупки";
|
"views.paywall.rows.restore_purchases" = "Восстановить покупки";
|
||||||
"views.paywall.sections.all_features.header" = "Полная версия включает";
|
"views.paywall.sections.all_features.header" = "Полная версия включает";
|
||||||
"views.paywall.sections.full_products.header" = "Полная версия";
|
"views.paywall.sections.full_products.header" = "Полная версия";
|
||||||
"views.paywall.sections.included_features.header" = "Также включает";
|
"views.paywall.sections.included_features.header" = "Также включает";
|
||||||
"views.paywall.sections.products.footer" = "Все покупки поддерживают Семейный доступ.";
|
"views.paywall.sections.products.footer" = "Все покупки поддерживают Семейный доступ.";
|
||||||
"views.paywall.sections.products.header" = "Доступные продукты";
|
"views.paywall.sections.products.header" = "Рекомендуемые продукты";
|
||||||
"views.paywall.sections.required_features.header" = "Необходимые функции";
|
"views.paywall.sections.required_features.header" = "Необходимые функции";
|
||||||
"views.paywall.sections.restore.footer" = "Если вы уже купили это приложение или функцию в прошлом, вы можете восстановить свои покупки.";
|
"views.paywall.sections.restore.footer" = "Если вы уже купили это приложение или функцию в прошлом, вы можете восстановить свои покупки.";
|
||||||
"views.paywall.sections.restore.header" = "Восстановить";
|
"views.paywall.sections.restore.header" = "Восстановить";
|
||||||
|
@ -260,12 +260,13 @@
|
|||||||
"views.paywall.alerts.verification.connect.1" = "Dina köp verifieras.";
|
"views.paywall.alerts.verification.connect.1" = "Dina köp verifieras.";
|
||||||
"views.paywall.alerts.verification.connect.2" = "Om verifieringen inte kan slutföras kommer anslutningen att avslutas om %d minuter.";
|
"views.paywall.alerts.verification.connect.2" = "Om verifieringen inte kan slutföras kommer anslutningen att avslutas om %d minuter.";
|
||||||
"views.paywall.alerts.verification.edit" = "Vänligen vänta medan dina köp verifieras.";
|
"views.paywall.alerts.verification.edit" = "Vänligen vänta medan dina köp verifieras.";
|
||||||
|
"views.paywall.product.included_features" = "Inkluderade funktioner";
|
||||||
"views.paywall.rows.restore_purchases" = "Återställ köp";
|
"views.paywall.rows.restore_purchases" = "Återställ köp";
|
||||||
"views.paywall.sections.all_features.header" = "Den fullständiga versionen innehåller";
|
"views.paywall.sections.all_features.header" = "Den fullständiga versionen innehåller";
|
||||||
"views.paywall.sections.full_products.header" = "Fullständig version";
|
"views.paywall.sections.full_products.header" = "Fullständig version";
|
||||||
"views.paywall.sections.included_features.header" = "Inkluderar även";
|
"views.paywall.sections.included_features.header" = "Inkluderar även";
|
||||||
"views.paywall.sections.products.footer" = "Alla köp stöder Familjedelning.";
|
"views.paywall.sections.products.footer" = "Alla köp stöder Familjedelning.";
|
||||||
"views.paywall.sections.products.header" = "Tillgängliga produkter";
|
"views.paywall.sections.products.header" = "Föreslagna produkter";
|
||||||
"views.paywall.sections.required_features.header" = "Krävda funktioner";
|
"views.paywall.sections.required_features.header" = "Krävda funktioner";
|
||||||
"views.paywall.sections.restore.footer" = "Om du har köpt denna app eller funktion tidigare kan du återställa dina köp.";
|
"views.paywall.sections.restore.footer" = "Om du har köpt denna app eller funktion tidigare kan du återställa dina köp.";
|
||||||
"views.paywall.sections.restore.header" = "Återställ";
|
"views.paywall.sections.restore.header" = "Återställ";
|
||||||
|
@ -260,12 +260,13 @@
|
|||||||
"views.paywall.alerts.verification.connect.1" = "Ваші покупки перевіряються.";
|
"views.paywall.alerts.verification.connect.1" = "Ваші покупки перевіряються.";
|
||||||
"views.paywall.alerts.verification.connect.2" = "Якщо перевірку не вдасться завершити, підключення завершиться через %d хвилин.";
|
"views.paywall.alerts.verification.connect.2" = "Якщо перевірку не вдасться завершити, підключення завершиться через %d хвилин.";
|
||||||
"views.paywall.alerts.verification.edit" = "Будь ласка, зачекайте, поки ваші покупки перевіряються.";
|
"views.paywall.alerts.verification.edit" = "Будь ласка, зачекайте, поки ваші покупки перевіряються.";
|
||||||
|
"views.paywall.product.included_features" = "Включені функції";
|
||||||
"views.paywall.rows.restore_purchases" = "Відновити покупки";
|
"views.paywall.rows.restore_purchases" = "Відновити покупки";
|
||||||
"views.paywall.sections.all_features.header" = "Повна версія включає";
|
"views.paywall.sections.all_features.header" = "Повна версія включає";
|
||||||
"views.paywall.sections.full_products.header" = "Повна версія";
|
"views.paywall.sections.full_products.header" = "Повна версія";
|
||||||
"views.paywall.sections.included_features.header" = "Також включає";
|
"views.paywall.sections.included_features.header" = "Також включає";
|
||||||
"views.paywall.sections.products.footer" = "Усі покупки підтримують “Сімейний доступ”.";
|
"views.paywall.sections.products.footer" = "Усі покупки підтримують “Сімейний доступ”.";
|
||||||
"views.paywall.sections.products.header" = "Доступні продукти";
|
"views.paywall.sections.products.header" = "Рекомендовані продукти";
|
||||||
"views.paywall.sections.required_features.header" = "Необхідні функції";
|
"views.paywall.sections.required_features.header" = "Необхідні функції";
|
||||||
"views.paywall.sections.restore.footer" = "Якщо ви раніше купували цей додаток або функцію, ви можете відновити свої покупки.";
|
"views.paywall.sections.restore.footer" = "Якщо ви раніше купували цей додаток або функцію, ви можете відновити свої покупки.";
|
||||||
"views.paywall.sections.restore.header" = "Відновлення";
|
"views.paywall.sections.restore.header" = "Відновлення";
|
||||||
|
@ -260,12 +260,13 @@
|
|||||||
"views.paywall.alerts.verification.connect.1" = "您的购买正在验证中。";
|
"views.paywall.alerts.verification.connect.1" = "您的购买正在验证中。";
|
||||||
"views.paywall.alerts.verification.connect.2" = "如果无法完成验证,连接将在 %d 分钟后断开。";
|
"views.paywall.alerts.verification.connect.2" = "如果无法完成验证,连接将在 %d 分钟后断开。";
|
||||||
"views.paywall.alerts.verification.edit" = "请稍候,您的购买正在验证中。";
|
"views.paywall.alerts.verification.edit" = "请稍候,您的购买正在验证中。";
|
||||||
|
"views.paywall.product.included_features" = "包含的功能";
|
||||||
"views.paywall.rows.restore_purchases" = "恢复购买";
|
"views.paywall.rows.restore_purchases" = "恢复购买";
|
||||||
"views.paywall.sections.all_features.header" = "完整版本包括";
|
"views.paywall.sections.all_features.header" = "完整版本包括";
|
||||||
"views.paywall.sections.full_products.header" = "完整版本";
|
"views.paywall.sections.full_products.header" = "完整版本";
|
||||||
"views.paywall.sections.included_features.header" = "还包括";
|
"views.paywall.sections.included_features.header" = "还包括";
|
||||||
"views.paywall.sections.products.footer" = "所有购买均支持“家人共享”。";
|
"views.paywall.sections.products.footer" = "所有购买均支持“家人共享”。";
|
||||||
"views.paywall.sections.products.header" = "可用产品";
|
"views.paywall.sections.products.header" = "推荐产品";
|
||||||
"views.paywall.sections.required_features.header" = "必需功能";
|
"views.paywall.sections.required_features.header" = "必需功能";
|
||||||
"views.paywall.sections.restore.footer" = "如果您过去购买过此应用或功能,可以恢复您的购买记录。";
|
"views.paywall.sections.restore.footer" = "如果您过去购买过此应用或功能,可以恢复您的购买记录。";
|
||||||
"views.paywall.sections.restore.header" = "恢复";
|
"views.paywall.sections.restore.header" = "恢复";
|
||||||
|
@ -74,6 +74,7 @@ extension Theme {
|
|||||||
case tunnelUninstall
|
case tunnelUninstall
|
||||||
case tvOff
|
case tvOff
|
||||||
case tvOn
|
case tvOn
|
||||||
|
case undisclose
|
||||||
case upgrade
|
case upgrade
|
||||||
case warning
|
case warning
|
||||||
}
|
}
|
||||||
@ -135,6 +136,7 @@ extension Theme.ImageName {
|
|||||||
return "tv"
|
return "tv"
|
||||||
}
|
}
|
||||||
case .tvOn: return "tv"
|
case .tvOn: return "tv"
|
||||||
|
case .undisclose: return "chevron.up"
|
||||||
case .upgrade: return "arrow.up.circle"
|
case .upgrade: return "arrow.up.circle"
|
||||||
case .warning: return "exclamationmark.triangle"
|
case .warning: return "exclamationmark.triangle"
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ enum FeatureListViewStyle {
|
|||||||
struct FeatureListView<Content>: View where Content: View {
|
struct FeatureListView<Content>: View where Content: View {
|
||||||
let style: FeatureListViewStyle
|
let style: FeatureListViewStyle
|
||||||
|
|
||||||
let header: String
|
var header: String?
|
||||||
|
|
||||||
let features: [AppFeature]
|
let features: [AppFeature]
|
||||||
|
|
||||||
@ -50,12 +50,7 @@ struct FeatureListView<Content>: View where Content: View {
|
|||||||
|
|
||||||
#if !os(tvOS)
|
#if !os(tvOS)
|
||||||
case .table:
|
case .table:
|
||||||
// XXX: work around Table artifact when 1 row and no headers
|
tableView
|
||||||
if features.count > 1 {
|
|
||||||
tableView
|
|
||||||
} else {
|
|
||||||
listView
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -70,10 +65,8 @@ private extension FeatureListView {
|
|||||||
#if !os(tvOS)
|
#if !os(tvOS)
|
||||||
var tableView: some View {
|
var tableView: some View {
|
||||||
Table(features.sorted()) {
|
Table(features.sorted()) {
|
||||||
TableColumn("", content: content)
|
TableColumn(header ?? "", content: content)
|
||||||
}
|
}
|
||||||
.withoutColumnHeaders()
|
|
||||||
.themeSection(header: header)
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,8 @@ public struct PaywallProductView: View {
|
|||||||
|
|
||||||
private let product: InAppProduct
|
private let product: InAppProduct
|
||||||
|
|
||||||
|
private let highlightedFeatures: Set<AppFeature>
|
||||||
|
|
||||||
@Binding
|
@Binding
|
||||||
private var purchasingIdentifier: String?
|
private var purchasingIdentifier: String?
|
||||||
|
|
||||||
@ -43,10 +45,14 @@ public struct PaywallProductView: View {
|
|||||||
|
|
||||||
private let onError: (Error) -> Void
|
private let onError: (Error) -> Void
|
||||||
|
|
||||||
|
@State
|
||||||
|
private var isPresentingFeatures = false
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
iapManager: IAPManager,
|
iapManager: IAPManager,
|
||||||
style: PaywallProductViewStyle,
|
style: PaywallProductViewStyle,
|
||||||
product: InAppProduct,
|
product: InAppProduct,
|
||||||
|
highlightedFeatures: Set<AppFeature> = [],
|
||||||
purchasingIdentifier: Binding<String?>,
|
purchasingIdentifier: Binding<String?>,
|
||||||
onComplete: @escaping (String, InAppPurchaseResult) -> Void,
|
onComplete: @escaping (String, InAppPurchaseResult) -> Void,
|
||||||
onError: @escaping (Error) -> Void
|
onError: @escaping (Error) -> Void
|
||||||
@ -54,12 +60,30 @@ public struct PaywallProductView: View {
|
|||||||
self.iapManager = iapManager
|
self.iapManager = iapManager
|
||||||
self.style = style
|
self.style = style
|
||||||
self.product = product
|
self.product = product
|
||||||
|
self.highlightedFeatures = highlightedFeatures
|
||||||
_purchasingIdentifier = purchasingIdentifier
|
_purchasingIdentifier = purchasingIdentifier
|
||||||
self.onComplete = onComplete
|
self.onComplete = onComplete
|
||||||
self.onError = onError
|
self.onError = onError
|
||||||
}
|
}
|
||||||
|
|
||||||
public var body: some View {
|
public var body: some View {
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
productView
|
||||||
|
Group {
|
||||||
|
includedFeaturesButton
|
||||||
|
.padding(.top, 8)
|
||||||
|
includedFeaturesList
|
||||||
|
.if(isPresentingFeatures)
|
||||||
|
}
|
||||||
|
.font(.subheadline)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension PaywallProductView {
|
||||||
|
|
||||||
|
@ViewBuilder
|
||||||
|
var productView: some View {
|
||||||
if #available(iOS 17, macOS 14, tvOS 17, *) {
|
if #available(iOS 17, macOS 14, tvOS 17, *) {
|
||||||
StoreKitProductView(
|
StoreKitProductView(
|
||||||
style: style,
|
style: style,
|
||||||
@ -79,4 +103,60 @@ public struct PaywallProductView: View {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var includedFeaturesButton: some View {
|
||||||
|
Button {
|
||||||
|
isPresentingFeatures.toggle()
|
||||||
|
} label: {
|
||||||
|
HStack {
|
||||||
|
Text(Strings.Views.Paywall.Product.includedFeatures)
|
||||||
|
ThemeImage(isPresentingFeatures ? .undisclose : .disclose)
|
||||||
|
}
|
||||||
|
.contentShape(.rect)
|
||||||
|
}
|
||||||
|
.buttonStyle(.plain)
|
||||||
|
.cursor(.hand)
|
||||||
|
}
|
||||||
|
|
||||||
|
var includedFeaturesList: some View {
|
||||||
|
AppProduct(rawValue: product.productIdentifier)
|
||||||
|
.map { product in
|
||||||
|
FeatureListView(
|
||||||
|
style: .list,
|
||||||
|
features: product.features,
|
||||||
|
content: featureView
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func featureView(for feature: AppFeature) -> some View {
|
||||||
|
HStack {
|
||||||
|
ThemeImage(.marked)
|
||||||
|
.opaque(highlightedFeatures.contains(feature))
|
||||||
|
|
||||||
|
Text(feature.localizedDescription)
|
||||||
|
.fontWeight(highlightedFeatures.contains(feature) ? .bold : .regular)
|
||||||
|
.scrollableOnTV()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#Preview {
|
||||||
|
List {
|
||||||
|
PaywallProductView(
|
||||||
|
iapManager: .forPreviews,
|
||||||
|
style: .paywall,
|
||||||
|
product: InAppProduct(
|
||||||
|
productIdentifier: AppProduct.Features.appleTV.rawValue,
|
||||||
|
localizedTitle: "Foo",
|
||||||
|
localizedPrice: "$10",
|
||||||
|
native: nil
|
||||||
|
),
|
||||||
|
highlightedFeatures: [.appleTV],
|
||||||
|
purchasingIdentifier: .constant(nil),
|
||||||
|
onComplete: { _, _ in },
|
||||||
|
onError: { _ in }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.withMockEnvironment()
|
||||||
}
|
}
|
||||||
|
@ -88,9 +88,6 @@ private extension PaywallView {
|
|||||||
Form {
|
Form {
|
||||||
requiredFeaturesView
|
requiredFeaturesView
|
||||||
productsView
|
productsView
|
||||||
if suggestedProducts == nil {
|
|
||||||
alsoIncludedEssentialsView
|
|
||||||
}
|
|
||||||
restoreView
|
restoreView
|
||||||
linksView
|
linksView
|
||||||
}
|
}
|
||||||
@ -123,6 +120,7 @@ private extension PaywallView {
|
|||||||
iapManager: iapManager,
|
iapManager: iapManager,
|
||||||
style: .paywall,
|
style: .paywall,
|
||||||
product: $0,
|
product: $0,
|
||||||
|
highlightedFeatures: requiredFeatures,
|
||||||
purchasingIdentifier: $purchasingIdentifier,
|
purchasingIdentifier: $purchasingIdentifier,
|
||||||
onComplete: onComplete,
|
onComplete: onComplete,
|
||||||
onError: onError
|
onError: onError
|
||||||
@ -136,22 +134,6 @@ private extension PaywallView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var alsoIncludedEssentialsView: some View {
|
|
||||||
essentialFeatures
|
|
||||||
.filter {
|
|
||||||
!requiredFeatures.contains($0)
|
|
||||||
}
|
|
||||||
.nilIfEmpty
|
|
||||||
.map {
|
|
||||||
FeatureListView(
|
|
||||||
style: featuresStyle,
|
|
||||||
header: Strings.Views.Paywall.Sections.IncludedFeatures.header,
|
|
||||||
features: $0,
|
|
||||||
content: featureView(for:)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var linksView: some View {
|
var linksView: some View {
|
||||||
Section {
|
Section {
|
||||||
Link(Strings.Unlocalized.eula, destination: Constants.shared.websites.eula)
|
Link(Strings.Unlocalized.eula, destination: Constants.shared.websites.eula)
|
||||||
@ -159,14 +141,6 @@ private extension PaywallView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var featuresStyle: FeatureListViewStyle {
|
|
||||||
#if os(iOS)
|
|
||||||
.list
|
|
||||||
#else
|
|
||||||
.table
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
func featureView(for feature: AppFeature) -> some View {
|
func featureView(for feature: AppFeature) -> some View {
|
||||||
Text(feature.localizedDescription)
|
Text(feature.localizedDescription)
|
||||||
.scrollableOnTV()
|
.scrollableOnTV()
|
||||||
|
Loading…
Reference in New Issue
Block a user