From 1aa4e5105fedd996026f7f81bd6fb7b24adb6382 Mon Sep 17 00:00:00 2001 From: Sam Symons Date: Wed, 18 Dec 2024 17:42:46 -0800 Subject: [PATCH 1/8] [Release PR] Update VPN localization (#3675) Task/Issue URL: https://app.asana.com/0/1207941519901927/1209009536812109/f Tech Design URL: CC: Description: This PR updates VPN localization to fix an issue on macOS 11 and 12. --- .../Localizable.xcstrings | 6 ++++++ DuckDuckGoVPN/Localizable.xcstrings | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/DuckDuckGo/NetworkProtection/NetworkExtensionTargets/NetworkExtensionAndNotificationTargets/Localizable.xcstrings b/DuckDuckGo/NetworkProtection/NetworkExtensionTargets/NetworkExtensionAndNotificationTargets/Localizable.xcstrings index a4d7368f52..b3cab01392 100644 --- a/DuckDuckGo/NetworkProtection/NetworkExtensionTargets/NetworkExtensionAndNotificationTargets/Localizable.xcstrings +++ b/DuckDuckGo/NetworkProtection/NetworkExtensionTargets/NetworkExtensionAndNotificationTargets/Localizable.xcstrings @@ -557,6 +557,12 @@ "value" : "Reconnect" } }, + "en-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reconnect" + } + }, "es" : { "stringUnit" : { "state" : "translated", diff --git a/DuckDuckGoVPN/Localizable.xcstrings b/DuckDuckGoVPN/Localizable.xcstrings index c18410e568..43636be9c4 100644 --- a/DuckDuckGoVPN/Localizable.xcstrings +++ b/DuckDuckGoVPN/Localizable.xcstrings @@ -557,6 +557,12 @@ "value" : "DuckDuckGo VPN" } }, + "en-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "DuckDuckGo VPN" + } + }, "es" : { "stringUnit" : { "state" : "translated", From 6c2feace6872332c94a6b6944fd41862b1922616 Mon Sep 17 00:00:00 2001 From: Anka Date: Thu, 19 Dec 2024 01:55:20 +0000 Subject: [PATCH 2/8] Set marketing version to 1.118.1 --- Configuration/Version.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Configuration/Version.xcconfig b/Configuration/Version.xcconfig index 8d10a20e0d..ae898aec0f 100644 --- a/Configuration/Version.xcconfig +++ b/Configuration/Version.xcconfig @@ -1 +1 @@ -MARKETING_VERSION = 1.118.0 +MARKETING_VERSION = 1.118.1 From b9af8577a4a75cd4d46e8970f2b5ab6114d6d05a Mon Sep 17 00:00:00 2001 From: Anka Date: Thu, 19 Dec 2024 01:55:22 +0000 Subject: [PATCH 3/8] Bump version to 1.118.1 (331) --- Configuration/BuildNumber.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Configuration/BuildNumber.xcconfig b/Configuration/BuildNumber.xcconfig index 71e870878b..38b8ff3b68 100644 --- a/Configuration/BuildNumber.xcconfig +++ b/Configuration/BuildNumber.xcconfig @@ -1 +1 @@ -CURRENT_PROJECT_VERSION = 329 +CURRENT_PROJECT_VERSION = 331 From c64f8f495f8fae05f1e16f2ba355ac9c9034685f Mon Sep 17 00:00:00 2001 From: Sam Symons Date: Wed, 18 Dec 2024 17:42:46 -0800 Subject: [PATCH 4/8] [Release PR] Update VPN localization (#3675) Task/Issue URL: https://app.asana.com/0/1207941519901927/1209009536812109/f Tech Design URL: CC: Description: This PR updates VPN localization to fix an issue on macOS 11 and 12. --- .../Localizable.xcstrings | 6 ++++++ DuckDuckGoVPN/Localizable.xcstrings | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/DuckDuckGo/NetworkProtection/NetworkExtensionTargets/NetworkExtensionAndNotificationTargets/Localizable.xcstrings b/DuckDuckGo/NetworkProtection/NetworkExtensionTargets/NetworkExtensionAndNotificationTargets/Localizable.xcstrings index a4d7368f52..b3cab01392 100644 --- a/DuckDuckGo/NetworkProtection/NetworkExtensionTargets/NetworkExtensionAndNotificationTargets/Localizable.xcstrings +++ b/DuckDuckGo/NetworkProtection/NetworkExtensionTargets/NetworkExtensionAndNotificationTargets/Localizable.xcstrings @@ -557,6 +557,12 @@ "value" : "Reconnect" } }, + "en-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reconnect" + } + }, "es" : { "stringUnit" : { "state" : "translated", diff --git a/DuckDuckGoVPN/Localizable.xcstrings b/DuckDuckGoVPN/Localizable.xcstrings index c18410e568..43636be9c4 100644 --- a/DuckDuckGoVPN/Localizable.xcstrings +++ b/DuckDuckGoVPN/Localizable.xcstrings @@ -557,6 +557,12 @@ "value" : "DuckDuckGo VPN" } }, + "en-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "DuckDuckGo VPN" + } + }, "es" : { "stringUnit" : { "state" : "translated", From 8c0d8495fb6164700f25465f16baf9e5e7726f9e Mon Sep 17 00:00:00 2001 From: Michal Smaga Date: Thu, 19 Dec 2024 17:49:59 +0100 Subject: [PATCH 5/8] Update to Privacy Pro settings footer (#3679) Task/Issue URL: https://app.asana.com/0/1142021229838617/1209014429605257/f Description: Following https://app.asana.com/0/1142021229838617/1208961863805375/f: Update the Privacy Pro settings to include link to Privacy Policy. Restore right alignment fro buttons on subscription dialogs. --- DuckDuckGo/Localizable.xcstrings | 112 +++++++++++++----- .../PreferencesSubscriptionModel.swift | 5 + .../PreferencesSubscriptionView.swift | 35 +++--- .../Resources/Localizable.xcstrings | 60 ++++++++++ .../Sources/SubscriptionUI/UserText.swift | 1 + 5 files changed, 160 insertions(+), 53 deletions(-) diff --git a/DuckDuckGo/Localizable.xcstrings b/DuckDuckGo/Localizable.xcstrings index ba0c0a8fe9..f0dbc2e23a 100644 --- a/DuckDuckGo/Localizable.xcstrings +++ b/DuckDuckGo/Localizable.xcstrings @@ -37013,11 +37013,59 @@ "comment" : "Title shown in an error page tab that warn users of security risks on a website that has been flagged as Malware.", "extractionState" : "extracted_with_value", "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Warnung: Website ist möglicherweise bösartig" + } + }, "en" : { "stringUnit" : { "state" : "new", "value" : "Warning: Site May Be Malicious" } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Advertencia: el sitio puede ser malicioso" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Avertissement : le site est peut-être malveillant" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Attenzione: il sito potrebbe essere dannoso" + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Opgelet: Deze website kan schadelijk zijn" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ostrzeżenie: witryna może być złośliwa" + } + }, + "pt" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aviso: o site pode ser malicioso" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Внимание! Потенциально вредоносный сайт" + } } } }, @@ -47104,8 +47152,8 @@ "localizations" : { "de" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Erlaube DuckDuckGo, dich zu warnen, bevor eine Webseite geladen wird, die als bösartig oder betrügerisch gekennzeichnet wurde." + "state" : "translated", + "value" : "Warne mich auf Websites, die als Phishing- oder Malware-Websites gekennzeichnet sind." } }, "en" : { @@ -47116,44 +47164,44 @@ }, "es" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Permite que DuckDuckGo te avise antes de cargar una página web que se haya marcado como maliciosa o fraudulenta." + "state" : "translated", + "value" : "Avisarme sobre sitios marcados como phishing o malware." } }, "fr" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Autorisez DuckDuckGo à vous avertir avant de charger une page Web signalée comme malveillante ou frauduleuse." + "state" : "translated", + "value" : "Mettez-moi en garde contre les sites signalés pour hameçonnage ou comme étant des logiciels malveillants." } }, "it" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Consenti a DuckDuckGo di avvisarti prima di caricare una pagina web contrassegnata come dannosa o fraudolenta." + "state" : "translated", + "value" : "Avvisami sui siti contrassegnati per phishing o malware." } }, "nl" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Laat DuckDuckGo je waarschuwen voordat je een webpagina laadt die als kwaadaardig of frauduleus is gemarkeerd." + "state" : "translated", + "value" : "Waarschuw me op websites die zijn aangeduid als phishing of malware." } }, "pl" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Zezwól DuckDuckGo na ostrzeganie przed załadowaniem strony internetowej, która została oznaczona jako złośliwa lub jako oszustwo." + "state" : "translated", + "value" : "Ostrzegaj mnie przed witrynami oznaczonymi jako wyłudzanie informacji lub złośliwe oprogramowanie." } }, "pt" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Permitir que o DuckDuckGo te avise antes de carregar uma página que foi sinalizada como maliciosa ou fraudulenta." + "state" : "translated", + "value" : "Avisar-me sobre sites sinalizados como phishing ou malware." } }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Разрешить DuckDuckGo предупреждать вас о потенциально вредоносных или мошеннических сайтах перед загрузкой страницы." + "state" : "translated", + "value" : "Предупреждать о вредоносных и фишинговых сайтах" } } } @@ -47224,8 +47272,8 @@ "localizations" : { "de" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Das Deaktivieren dieser Funktion kann deine persönlichen Daten gefährden. Wenn du dir über die damit verbundenen Risiken im Klaren bist, kannst du trotzdem fortfahren." + "state" : "translated", + "value" : "Das Deaktivieren dieser Funktion kann deine persönlichen Daten gefährden." } }, "en" : { @@ -47236,44 +47284,44 @@ }, "es" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Desactivar esta función puede poner en riesgo tu información personal. Hazlo solo si entiendes completamente el riesgo que implica." + "state" : "translated", + "value" : "Desactivar esta función puede poner en riesgo tu información personal." } }, "fr" : { "stringUnit" : { - "state" : "needs_review", - "value" : "La désactivation de cette fonctionnalité peut mettre vos informations personnelles en danger. Faites-le uniquement si vous comprenez parfaitement les risques encourus." + "state" : "translated", + "value" : "La désactivation de cette fonctionnalité peut mettre vos informations personnelles en danger." } }, "it" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Disabilitando questa funzione, potresti mettere a rischio i tuoi dati personali. Fallo solo se comprendi appieno il rischio che comporta." + "state" : "translated", + "value" : "Disabilitando questa funzione, potresti mettere a rischio i tuoi dati personali." } }, "nl" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Als je deze functie uitschakelt, kunnen je persoonlijke gegevens in gevaar komen. Doe dit alleen als je het risico volledig begrijpt." + "state" : "translated", + "value" : "Als je deze functie uitschakelt, kunnen je persoonlijke gegevens in gevaar komen." } }, "pl" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Wyłączenie tej funkcji może narazić Twoje dane osobowe na ryzyko. Rób to tylko wtedy, gdy rozumiesz związane z tym zagrożenie." + "state" : "translated", + "value" : "Wyłączenie tej funkcji może narazić Twoje dane osobowe na ryzyko." } }, "pt" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Desativar esta funcionalidade pode pôr em risco as tuas informações pessoais. Não desatives a menos que compreendas os riscos." + "state" : "translated", + "value" : "Desativar esta funcionalidade pode pôr em risco as tuas informações pessoais." } }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "При отключении этой функции ваши личные данные могут оказаться под угрозой. Эту функцию следует деактивировать только в том случае, если вы осознаете связанные с этим риски." + "state" : "translated", + "value" : "При отключении этой функции ваши личные данные могут оказаться под угрозой." } } } diff --git a/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/Preferences/PreferencesSubscriptionModel.swift b/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/Preferences/PreferencesSubscriptionModel.swift index dfed042d42..e0a7bab18c 100644 --- a/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/Preferences/PreferencesSubscriptionModel.swift +++ b/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/Preferences/PreferencesSubscriptionModel.swift @@ -315,6 +315,11 @@ public final class PreferencesSubscriptionModel: ObservableObject { userEventHandler(.openFeedback) } + @MainActor + func openPrivacyPolicy() { + openURLHandler(URL(string: "https://duckduckgo.com/pro/privacy-terms")!) + } + @MainActor func refreshSubscriptionPendingState() { if subscriptionManager.currentEnvironment.purchasePlatform == .appStore { diff --git a/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/Preferences/PreferencesSubscriptionView.swift b/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/Preferences/PreferencesSubscriptionView.swift index ec66c0b134..8bcc0f4ba0 100644 --- a/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/Preferences/PreferencesSubscriptionView.swift +++ b/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/Preferences/PreferencesSubscriptionView.swift @@ -101,11 +101,6 @@ public struct PreferencesSubscriptionView: View { // Help section helpSection - - // Feedback section - if subscriptionFeatureAvailability.usesUnifiedFeedbackForm, state == .subscriptionActive { - feedbackSection - } } .onAppear(perform: { model.didAppear() @@ -303,24 +298,21 @@ public struct PreferencesSubscriptionView: View { private var helpSection: some View { PreferencePaneSection { TextMenuItemHeader(UserText.preferencesSubscriptionFooterTitle, bottomPadding: 0) - HStack(alignment: .top, spacing: 6) { - if !model.isROWLaunched { - TextMenuItemCaption(UserText.preferencesSubscriptionFooterCaption) - } else { - TextMenuItemCaption(UserText.preferencesSubscriptionHelpFooterCaption) - } - Button(UserText.viewFaqsButton) { model.openFAQ() } + if !model.isROWLaunched { + TextMenuItemCaption(UserText.preferencesSubscriptionFooterCaption) + .padding(.bottom, 8) + } else { + TextMenuItemCaption(UserText.preferencesSubscriptionHelpFooterCaption) + .padding(.bottom, 8) } - } - } + VStack(alignment: .leading, spacing: 16) { + TextButton(UserText.viewFaqsButton, weight: .semibold) { model.openFAQ() } - @ViewBuilder - private var feedbackSection: some View { - PreferencePaneSection { - TextMenuItemHeader(UserText.preferencesSubscriptionFeedbackTitle, bottomPadding: 0) - HStack(alignment: .top, spacing: 6) { - TextMenuItemCaption(UserText.preferencesSubscriptionFeedbackCaption) - Button(UserText.preferencesSubscriptionFeedbackButton) { model.openUnifiedFeedbackForm() } + if subscriptionFeatureAvailability.usesUnifiedFeedbackForm, state == .subscriptionActive { + TextButton(UserText.preferencesSubscriptionFeedbackButton, weight: .semibold) { model.openUnifiedFeedbackForm() } + } + + TextButton(UserText.preferencesPrivacyPolicyButton, weight: .semibold) { model.openPrivacyPolicy() } } } } @@ -495,6 +487,7 @@ private struct SubscriptionDialog: View where Buttons: View { .fixMultilineScrollableText() .foregroundColor(Color(.textPrimary)) } buttons: { + Spacer() buttons() } } diff --git a/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/Resources/Localizable.xcstrings b/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/Resources/Localizable.xcstrings index c7836d0be0..f909d5486a 100644 --- a/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/Resources/Localizable.xcstrings +++ b/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/Resources/Localizable.xcstrings @@ -2265,6 +2265,66 @@ } } }, + "subscription.preferences.privacypolicy.button" : { + "comment" : "Title for the privacy policy button", + "extractionState" : "extracted_with_value", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Datenschutzerklärung und Nutzungsbedingungen" + } + }, + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Privacy Policy and Terms of Service" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Política de privacidad y condiciones del servicio" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Politique de confidentialité et conditions d'utilisation" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Privacy policy e Termini del servizio" + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Privacybeleid en servicevoorwaarden" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Polityka prywatności i warunki użytkowania" + } + }, + "pt" : { + "stringUnit" : { + "state" : "translated", + "value" : "Política de Privacidade e Termos de Serviço" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Политика конфиденциальности и условия обслуживания" + } + } + } + }, "subscription.preferences.purchase.button" : { "comment" : "Button to open a page where user can learn more and purchase the subscription", "extractionState" : "extracted_with_value", diff --git a/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/UserText.swift b/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/UserText.swift index a0c9d163a0..8f4e5a018a 100644 --- a/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/UserText.swift +++ b/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/UserText.swift @@ -54,6 +54,7 @@ enum UserText { static let preferencesSubscriptionFeedbackTitle = NSLocalizedString("subscription.preferences.feedback.title", bundle: Bundle.module, value: "Send Feedback", comment: "Title for the subscription feedback section") static let preferencesSubscriptionFeedbackCaption = NSLocalizedString("subscription.preferences.feedback.caption", bundle: Bundle.module, value: "Help improve Privacy Pro. Your feedback matters to us. Feel free to report any issues or provide general feedback.", comment: "Caption for the subscription feedback section") static let preferencesSubscriptionFeedbackButton = NSLocalizedString("subscription.preferences.feedback.button", bundle: Bundle.module, value: "Send Feedback", comment: "Title for the subscription feedback button") + static let preferencesPrivacyPolicyButton = NSLocalizedString("subscription.preferences.privacypolicy.button", bundle: Bundle.module, value: "Privacy Policy and Terms of Service", comment: "Title for the privacy policy button") static func preferencesSubscriptionRenewingCaption(billingPeriod: Subscription.BillingPeriod, formattedDate: String) -> String { let localized: String From cf52650423b873865288e7323d8a19d154ebe8d3 Mon Sep 17 00:00:00 2001 From: Michal Smaga Date: Thu, 19 Dec 2024 17:49:59 +0100 Subject: [PATCH 6/8] Update to Privacy Pro settings footer (#3679) Task/Issue URL: https://app.asana.com/0/1142021229838617/1209014429605257/f Description: Following https://app.asana.com/0/1142021229838617/1208961863805375/f: Update the Privacy Pro settings to include link to Privacy Policy. Restore right alignment fro buttons on subscription dialogs. # Conflicts: # DuckDuckGo/Localizable.xcstrings --- .../PreferencesSubscriptionModel.swift | 5 ++ .../PreferencesSubscriptionView.swift | 35 +++++------ .../Resources/Localizable.xcstrings | 60 +++++++++++++++++++ .../Sources/SubscriptionUI/UserText.swift | 1 + 4 files changed, 80 insertions(+), 21 deletions(-) diff --git a/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/Preferences/PreferencesSubscriptionModel.swift b/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/Preferences/PreferencesSubscriptionModel.swift index dfed042d42..e0a7bab18c 100644 --- a/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/Preferences/PreferencesSubscriptionModel.swift +++ b/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/Preferences/PreferencesSubscriptionModel.swift @@ -315,6 +315,11 @@ public final class PreferencesSubscriptionModel: ObservableObject { userEventHandler(.openFeedback) } + @MainActor + func openPrivacyPolicy() { + openURLHandler(URL(string: "https://duckduckgo.com/pro/privacy-terms")!) + } + @MainActor func refreshSubscriptionPendingState() { if subscriptionManager.currentEnvironment.purchasePlatform == .appStore { diff --git a/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/Preferences/PreferencesSubscriptionView.swift b/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/Preferences/PreferencesSubscriptionView.swift index ec66c0b134..8bcc0f4ba0 100644 --- a/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/Preferences/PreferencesSubscriptionView.swift +++ b/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/Preferences/PreferencesSubscriptionView.swift @@ -101,11 +101,6 @@ public struct PreferencesSubscriptionView: View { // Help section helpSection - - // Feedback section - if subscriptionFeatureAvailability.usesUnifiedFeedbackForm, state == .subscriptionActive { - feedbackSection - } } .onAppear(perform: { model.didAppear() @@ -303,24 +298,21 @@ public struct PreferencesSubscriptionView: View { private var helpSection: some View { PreferencePaneSection { TextMenuItemHeader(UserText.preferencesSubscriptionFooterTitle, bottomPadding: 0) - HStack(alignment: .top, spacing: 6) { - if !model.isROWLaunched { - TextMenuItemCaption(UserText.preferencesSubscriptionFooterCaption) - } else { - TextMenuItemCaption(UserText.preferencesSubscriptionHelpFooterCaption) - } - Button(UserText.viewFaqsButton) { model.openFAQ() } + if !model.isROWLaunched { + TextMenuItemCaption(UserText.preferencesSubscriptionFooterCaption) + .padding(.bottom, 8) + } else { + TextMenuItemCaption(UserText.preferencesSubscriptionHelpFooterCaption) + .padding(.bottom, 8) } - } - } + VStack(alignment: .leading, spacing: 16) { + TextButton(UserText.viewFaqsButton, weight: .semibold) { model.openFAQ() } - @ViewBuilder - private var feedbackSection: some View { - PreferencePaneSection { - TextMenuItemHeader(UserText.preferencesSubscriptionFeedbackTitle, bottomPadding: 0) - HStack(alignment: .top, spacing: 6) { - TextMenuItemCaption(UserText.preferencesSubscriptionFeedbackCaption) - Button(UserText.preferencesSubscriptionFeedbackButton) { model.openUnifiedFeedbackForm() } + if subscriptionFeatureAvailability.usesUnifiedFeedbackForm, state == .subscriptionActive { + TextButton(UserText.preferencesSubscriptionFeedbackButton, weight: .semibold) { model.openUnifiedFeedbackForm() } + } + + TextButton(UserText.preferencesPrivacyPolicyButton, weight: .semibold) { model.openPrivacyPolicy() } } } } @@ -495,6 +487,7 @@ private struct SubscriptionDialog: View where Buttons: View { .fixMultilineScrollableText() .foregroundColor(Color(.textPrimary)) } buttons: { + Spacer() buttons() } } diff --git a/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/Resources/Localizable.xcstrings b/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/Resources/Localizable.xcstrings index c7836d0be0..f909d5486a 100644 --- a/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/Resources/Localizable.xcstrings +++ b/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/Resources/Localizable.xcstrings @@ -2265,6 +2265,66 @@ } } }, + "subscription.preferences.privacypolicy.button" : { + "comment" : "Title for the privacy policy button", + "extractionState" : "extracted_with_value", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Datenschutzerklärung und Nutzungsbedingungen" + } + }, + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Privacy Policy and Terms of Service" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Política de privacidad y condiciones del servicio" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Politique de confidentialité et conditions d'utilisation" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Privacy policy e Termini del servizio" + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Privacybeleid en servicevoorwaarden" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Polityka prywatności i warunki użytkowania" + } + }, + "pt" : { + "stringUnit" : { + "state" : "translated", + "value" : "Política de Privacidade e Termos de Serviço" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Политика конфиденциальности и условия обслуживания" + } + } + } + }, "subscription.preferences.purchase.button" : { "comment" : "Button to open a page where user can learn more and purchase the subscription", "extractionState" : "extracted_with_value", diff --git a/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/UserText.swift b/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/UserText.swift index a0c9d163a0..8f4e5a018a 100644 --- a/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/UserText.swift +++ b/LocalPackages/SubscriptionUI/Sources/SubscriptionUI/UserText.swift @@ -54,6 +54,7 @@ enum UserText { static let preferencesSubscriptionFeedbackTitle = NSLocalizedString("subscription.preferences.feedback.title", bundle: Bundle.module, value: "Send Feedback", comment: "Title for the subscription feedback section") static let preferencesSubscriptionFeedbackCaption = NSLocalizedString("subscription.preferences.feedback.caption", bundle: Bundle.module, value: "Help improve Privacy Pro. Your feedback matters to us. Feel free to report any issues or provide general feedback.", comment: "Caption for the subscription feedback section") static let preferencesSubscriptionFeedbackButton = NSLocalizedString("subscription.preferences.feedback.button", bundle: Bundle.module, value: "Send Feedback", comment: "Title for the subscription feedback button") + static let preferencesPrivacyPolicyButton = NSLocalizedString("subscription.preferences.privacypolicy.button", bundle: Bundle.module, value: "Privacy Policy and Terms of Service", comment: "Title for the privacy policy button") static func preferencesSubscriptionRenewingCaption(billingPeriod: Subscription.BillingPeriod, formattedDate: String) -> String { let localized: String From f8fda48c2670e96be07de56ecba824a988f85e04 Mon Sep 17 00:00:00 2001 From: Anka Date: Thu, 19 Dec 2024 18:25:24 +0000 Subject: [PATCH 7/8] Bump version to 1.119.0 (332) --- Configuration/BuildNumber.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Configuration/BuildNumber.xcconfig b/Configuration/BuildNumber.xcconfig index 610113ea86..78ac15dc98 100644 --- a/Configuration/BuildNumber.xcconfig +++ b/Configuration/BuildNumber.xcconfig @@ -1 +1 @@ -CURRENT_PROJECT_VERSION = 330 +CURRENT_PROJECT_VERSION = 332 From ab35023580ab8488c8df141fd6d8139d546be062 Mon Sep 17 00:00:00 2001 From: Jonathan Jackson Date: Thu, 19 Dec 2024 16:27:02 -0500 Subject: [PATCH 8/8] CRCID Support when reporting crashes (#3653) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task/Issue URL: https://app.asana.com/0/1208592102886666/1208759541597499/f Tech Design URL: https://app.asana.com/0/1208592102886666/1208660326715650/f **Description**: DO NOT MERGE - this is a draft for input, not ready to go live yet. MacOS support for crash report cohort IDs (CRCIDs) when sending crash reports. **Optional E2E tests**: - [ ] Run PIR E2E tests Check this to run the Personal Information Removal end to end tests. If updating CCF, or any PIR related code, tick this. **Steps to test this PR**: To cause and report a crash: 1. Launch the app and force a crash, which can be done from Debug (menu) → Simulate Crash → fatalError (or similar). 2. Launch the app again (easiest with a debugger) 3. You will be prompted to submit the crash. When submitting, watch logs for “crcid” and “crash” and you should see output from these changes confirming a CRCID is received and updated. 4. Repeat steps 2-3 again, and you should see that the CRCID received initially is what’s submitted with the next crash. --- DuckDuckGo.xcodeproj/project.pbxproj | 16 ++++++- .../xcshareddata/swiftpm/Package.resolved | 4 +- DuckDuckGo/Application/AppDelegate.swift | 3 +- .../Model/CrashReportSenderExtensions.swift | 43 +++++++++++++++++++ .../CrashReports/Model/CrashReporter.swift | 7 ++- DuckDuckGo/Statistics/GeneralPixel.swift | 8 ++++ .../DataBrokerProtection/Package.swift | 2 +- LocalPackages/FeatureFlags/Package.swift | 2 +- .../NetworkProtectionMac/Package.swift | 2 +- LocalPackages/NewTabPage/Package.swift | 2 +- LocalPackages/SubscriptionUI/Package.swift | 2 +- LocalPackages/WebKitExtensions/Package.swift | 2 +- 12 files changed, 81 insertions(+), 12 deletions(-) create mode 100644 DuckDuckGo/CrashReports/Model/CrashReportSenderExtensions.swift diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 50887e402a..12f63ecaf6 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -1319,6 +1319,9 @@ 37FC2A192CF903080048E226 /* MockPrivacyStats.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FC2A172CF903060048E226 /* MockPrivacyStats.swift */; }; 37FD78112A29EBD100B36DB1 /* SyncErrorHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FD78102A29EBD100B36DB1 /* SyncErrorHandler.swift */; }; 37FD78122A29EBD100B36DB1 /* SyncErrorHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FD78102A29EBD100B36DB1 /* SyncErrorHandler.swift */; }; + 46066CBC2D1330A100AB683B /* Persistence in Frameworks */ = {isa = PBXBuildFile; productRef = 46066CBB2D1330A100AB683B /* Persistence */; }; + 467D16672D0C98D5007C020A /* CrashReportSenderExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 467D16662D0C98D5007C020A /* CrashReportSenderExtensions.swift */; }; + 467D16682D0C98D5007C020A /* CrashReportSenderExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 467D16662D0C98D5007C020A /* CrashReportSenderExtensions.swift */; }; 4B0135CE2729F1AA00D54834 /* NSPasteboardExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B0135CD2729F1AA00D54834 /* NSPasteboardExtension.swift */; }; 4B02198925E05FAC00ED7DEA /* FireproofingURLExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B02197F25E05FAC00ED7DEA /* FireproofingURLExtensions.swift */; }; 4B02198A25E05FAC00ED7DEA /* FireproofDomains.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B02198125E05FAC00ED7DEA /* FireproofDomains.swift */; }; @@ -3796,6 +3799,7 @@ 37F8ABD22CE3EE5B00CB0294 /* FeatureFlagOverridesMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeatureFlagOverridesMenu.swift; sourceTree = ""; }; 37FC2A172CF903060048E226 /* MockPrivacyStats.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockPrivacyStats.swift; sourceTree = ""; }; 37FD78102A29EBD100B36DB1 /* SyncErrorHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncErrorHandler.swift; sourceTree = ""; }; + 467D16662D0C98D5007C020A /* CrashReportSenderExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrashReportSenderExtensions.swift; sourceTree = ""; }; 4B0135CD2729F1AA00D54834 /* NSPasteboardExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSPasteboardExtension.swift; sourceTree = ""; }; 4B02197F25E05FAC00ED7DEA /* FireproofingURLExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FireproofingURLExtensions.swift; sourceTree = ""; }; 4B02198125E05FAC00ED7DEA /* FireproofDomains.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FireproofDomains.swift; sourceTree = ""; }; @@ -5345,6 +5349,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 46066CBC2D1330A100AB683B /* Persistence in Frameworks */, B6DA44172616C13800DD1EC2 /* OHHTTPStubs in Frameworks */, F116A7C32BD1924B00F3FCF7 /* PixelKitTestingUtilities in Frameworks */, 84BBC8012CFA0D3800BAE57A /* TestUtils in Frameworks */, @@ -8639,6 +8644,7 @@ AAC30A27268E045400D2D9CD /* CrashReportReader.swift */, AAC30A2D268F1EE300D2D9CD /* CrashReportPromptPresenter.swift */, AAC30A29268E239100D2D9CD /* CrashReport.swift */, + 467D16662D0C98D5007C020A /* CrashReportSenderExtensions.swift */, ); path = Model; sourceTree = ""; @@ -10497,6 +10503,7 @@ 9DC5FACA2C6B8E050011F068 /* AppKitExtensions */, 84BBC8002CFA0D3800BAE57A /* TestUtils */, 374EFDEE2D01C70300B30939 /* Utilities */, + 46066CBB2D1330A100AB683B /* Persistence */, ); productName = DuckDuckGoTests; productReference = AA585D90248FD31400E9A3E2 /* Unit Tests.xctest */; @@ -11571,6 +11578,7 @@ 37197EA82942443D00394917 /* BrowserTabViewController.swift in Sources */, 3706FB39293F65D500E42796 /* PrivacyDashboardPopover.swift in Sources */, 3706FB3B293F65D500E42796 /* RootView.swift in Sources */, + 467D16672D0C98D5007C020A /* CrashReportSenderExtensions.swift in Sources */, 3706FB3C293F65D500E42796 /* AddressBarTextField.swift in Sources */, 3706FB3D293F65D500E42796 /* FocusRingView.swift in Sources */, 3706FB3E293F65D500E42796 /* BookmarksBarViewModel.swift in Sources */, @@ -13085,6 +13093,7 @@ AABEE6A524AA0A7F0043105B /* SuggestionViewController.swift in Sources */, 1D6216B229069BBF00386B2C /* BWKeyStorage.swift in Sources */, AA7E919F287872EA00AB6B62 /* VisitViewModel.swift in Sources */, + 467D16682D0C98D5007C020A /* CrashReportSenderExtensions.swift in Sources */, 7BD7B0012C19D3830039D20A /* VPNIPCResources.swift in Sources */, C1935A1B2C88F9ED001AD72D /* SyncPromoViewModel.swift in Sources */, B6676BE12AA986A700525A21 /* AddressBarTextEditor.swift in Sources */, @@ -15297,7 +15306,7 @@ repositoryURL = "https://github.com/duckduckgo/BrowserServicesKit"; requirement = { kind = exactVersion; - version = 221.3.0; + version = 222.1.0; }; }; 9FF521422BAA8FF300B9819B /* XCRemoteSwiftPackageReference "lottie-spm" */ = { @@ -15700,6 +15709,11 @@ package = 9807F643278CA16F00E1547B /* XCRemoteSwiftPackageReference "BrowserServicesKit" */; productName = Navigation; }; + 46066CBB2D1330A100AB683B /* Persistence */ = { + isa = XCSwiftPackageProductDependency; + package = 9807F643278CA16F00E1547B /* XCRemoteSwiftPackageReference "BrowserServicesKit" */; + productName = Persistence; + }; 4B2D062B2A11C0E100DE1F49 /* Networking */ = { isa = XCSwiftPackageProductDependency; package = 9807F643278CA16F00E1547B /* XCRemoteSwiftPackageReference "BrowserServicesKit" */; diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index f38fb5f4a6..602e95e476 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -32,8 +32,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/duckduckgo/BrowserServicesKit", "state" : { - "revision" : "b71ed70ce9b0ef3ce51d4f96da0193ab70493944", - "version" : "221.3.0" + "revision" : "5704d77e3b4c77c7387518d796d31a35f7a1ffcf", + "version" : "222.1.0" } }, { diff --git a/DuckDuckGo/Application/AppDelegate.swift b/DuckDuckGo/Application/AppDelegate.swift index 1b0788355b..3aa256fb0f 100644 --- a/DuckDuckGo/Application/AppDelegate.swift +++ b/DuckDuckGo/Application/AppDelegate.swift @@ -71,7 +71,8 @@ final class AppDelegate: NSObject, NSApplicationDelegate { let fileStore: FileStore #if APPSTORE - private let crashCollection = CrashCollection(platform: .macOSAppStore) + private let crashCollection = CrashCollection(crashReportSender: CrashReportSender(platform: .macOSAppStore, + pixelEvents: CrashReportSender.pixelEvents)) #else private let crashReporter = CrashReporter() #endif diff --git a/DuckDuckGo/CrashReports/Model/CrashReportSenderExtensions.swift b/DuckDuckGo/CrashReports/Model/CrashReportSenderExtensions.swift new file mode 100644 index 0000000000..85618d2d99 --- /dev/null +++ b/DuckDuckGo/CrashReports/Model/CrashReportSenderExtensions.swift @@ -0,0 +1,43 @@ +// +// CrashReportSenderExtensions.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Crashes +import Common +import PixelKit + +extension CrashReportSender { + + static let pixelEvents: EventMapping = .init { event, _, _, _ in + switch event { + case CrashReportSenderError.crcidMissing: + PixelKit.fire(GeneralPixel.crashReportCRCIDMissing) + + case CrashReportSenderError.submissionFailed(let error): + if let error { + PixelKit.fire(DebugEvent(GeneralPixel.crashReportingSubmissionFailed), + frequency: .standard, + withHeaders: [:], + withAdditionalParameters: ["HTTPStatusCode": "\(error.statusCode)"], + withError: nil, + allowedQueryReservedCharacters: nil) + } else { + PixelKit.fire(GeneralPixel.crashReportingSubmissionFailed) + } + } + } +} diff --git a/DuckDuckGo/CrashReports/Model/CrashReporter.swift b/DuckDuckGo/CrashReports/Model/CrashReporter.swift index b3456a3adb..4883679907 100644 --- a/DuckDuckGo/CrashReports/Model/CrashReporter.swift +++ b/DuckDuckGo/CrashReports/Model/CrashReporter.swift @@ -24,7 +24,8 @@ import PixelKit final class CrashReporter { private let reader = CrashReportReader() - private lazy var sender = CrashReportSender(platform: .macOS) + private lazy var sender = CrashReportSender(platform: .macOS, pixelEvents: CrashReportSender.pixelEvents) + private lazy var crcidManager = CRCIDManager() private lazy var promptPresenter = CrashReportPromptPresenter() @UserDefaultsWrapper(key: .lastCrashReportCheckDate, defaultValue: nil) @@ -56,7 +57,9 @@ final class CrashReporter { return } Task { - await self.sender.send(contentData) + let crcid = self.crcidManager.crcid + let result = await self.sender.send(contentData, crcid: crcid) + self.crcidManager.handleCrashSenderResult(result: result.result, response: result.response) } } diff --git a/DuckDuckGo/Statistics/GeneralPixel.swift b/DuckDuckGo/Statistics/GeneralPixel.swift index 2a92aa9845..0c24d26481 100644 --- a/DuckDuckGo/Statistics/GeneralPixel.swift +++ b/DuckDuckGo/Statistics/GeneralPixel.swift @@ -26,6 +26,8 @@ enum GeneralPixel: PixelKitEventV2 { case crash case crashOnCrashHandlersSetUp + case crashReportingSubmissionFailed + case crashReportCRCIDMissing case compileRulesWait(onboardingShown: OnboardingShown, waitTime: CompileRulesWaitTime, result: WaitResult) case launchInitial(cohort: String) case launch(isDefault: Bool) @@ -473,6 +475,12 @@ enum GeneralPixel: PixelKitEventV2 { case .crashOnCrashHandlersSetUp: return "m_mac_crash_on_handlers_setup" + case .crashReportCRCIDMissing: + return "m_mac_crashreporting_crcid-missing" + + case .crashReportingSubmissionFailed: + return "m_mac_crashreporting_submission-failed" + case .compileRulesWait(onboardingShown: let onboardingShown, waitTime: let waitTime, result: let result): return "m_mac_cbr-wait_\(onboardingShown)_\(waitTime)_\(result)" diff --git a/LocalPackages/DataBrokerProtection/Package.swift b/LocalPackages/DataBrokerProtection/Package.swift index 79e021c472..2cb2248e15 100644 --- a/LocalPackages/DataBrokerProtection/Package.swift +++ b/LocalPackages/DataBrokerProtection/Package.swift @@ -29,7 +29,7 @@ let package = Package( targets: ["DataBrokerProtection"]) ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "221.3.0"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "222.1.0"), .package(path: "../SwiftUIExtensions"), .package(path: "../AppKitExtensions"), .package(path: "../XPCHelper"), diff --git a/LocalPackages/FeatureFlags/Package.swift b/LocalPackages/FeatureFlags/Package.swift index dcb3d9194f..c552f688dd 100644 --- a/LocalPackages/FeatureFlags/Package.swift +++ b/LocalPackages/FeatureFlags/Package.swift @@ -32,7 +32,7 @@ let package = Package( targets: ["FeatureFlags"]), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "221.3.0"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "222.1.0"), ], targets: [ // Targets are the basic building blocks of a package, defining a module or a test suite. diff --git a/LocalPackages/NetworkProtectionMac/Package.swift b/LocalPackages/NetworkProtectionMac/Package.swift index 3431d62c5a..ba1c4334a4 100644 --- a/LocalPackages/NetworkProtectionMac/Package.swift +++ b/LocalPackages/NetworkProtectionMac/Package.swift @@ -33,7 +33,7 @@ let package = Package( .library(name: "VPNAppLauncher", targets: ["VPNAppLauncher"]), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "221.3.0"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "222.1.0"), .package(url: "https://github.com/airbnb/lottie-spm", exact: "4.4.3"), .package(path: "../AppLauncher"), .package(path: "../UDSHelper"), diff --git a/LocalPackages/NewTabPage/Package.swift b/LocalPackages/NewTabPage/Package.swift index 46ba37e00c..f062a29127 100644 --- a/LocalPackages/NewTabPage/Package.swift +++ b/LocalPackages/NewTabPage/Package.swift @@ -32,7 +32,7 @@ let package = Package( targets: ["NewTabPage"]), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "221.3.0"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "222.1.0"), .package(path: "../WebKitExtensions"), .package(path: "../Utilities"), ], diff --git a/LocalPackages/SubscriptionUI/Package.swift b/LocalPackages/SubscriptionUI/Package.swift index 40bb88836f..1b4ee7bdce 100644 --- a/LocalPackages/SubscriptionUI/Package.swift +++ b/LocalPackages/SubscriptionUI/Package.swift @@ -13,7 +13,7 @@ let package = Package( targets: ["SubscriptionUI"]), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "221.3.0"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "222.1.0"), .package(path: "../SwiftUIExtensions"), .package(path: "../FeatureFlags") ], diff --git a/LocalPackages/WebKitExtensions/Package.swift b/LocalPackages/WebKitExtensions/Package.swift index 44e660355b..00965ec758 100644 --- a/LocalPackages/WebKitExtensions/Package.swift +++ b/LocalPackages/WebKitExtensions/Package.swift @@ -32,7 +32,7 @@ let package = Package( ), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "221.3.0"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "222.1.0"), .package(path: "../AppKitExtensions") ], targets: [