From 1aa4e5105fedd996026f7f81bd6fb7b24adb6382 Mon Sep 17 00:00:00 2001 From: Sam Symons Date: Wed, 18 Dec 2024 17:42:46 -0800 Subject: [PATCH 01/11] [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 02/11] 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 03/11] 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 04/11] [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 05/11] 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 06/11] 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 07/11] 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 08/11] 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: [ From ceee9e79af81ab28acf25216d521136ff76cb26f Mon Sep 17 00:00:00 2001 From: Sam Symons Date: Thu, 19 Dec 2024 15:49:14 -0800 Subject: [PATCH 09/11] Upgrade to Xcode 16.2 (#3677) Task/Issue URL: https://app.asana.com/0/1203301625297703/1209011361031638/f Tech Design URL: CC: Description: This PR upgrades CI to Xcode 16.2. --- .xcode-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.xcode-version b/.xcode-version index c32b0ec5ab..f6eb05e3c6 100644 --- a/.xcode-version +++ b/.xcode-version @@ -1 +1 @@ -16.1 +16.2 From ce9fa03e497e969d2481f4d5dea7dfdd9e703574 Mon Sep 17 00:00:00 2001 From: Alexey Martemyanov Date: Fri, 20 Dec 2024 13:10:15 +0600 Subject: [PATCH 10/11] BSK -> 223.0.0 --- DuckDuckGo.xcodeproj/project.pbxproj | 4 ++-- .../xcshareddata/swiftpm/Package.resolved | 12 ++++++------ LocalPackages/DataBrokerProtection/Package.swift | 2 +- LocalPackages/FeatureFlags/Package.swift | 2 +- LocalPackages/NetworkProtectionMac/Package.swift | 2 +- LocalPackages/NewTabPage/Package.swift | 2 +- LocalPackages/SubscriptionUI/Package.swift | 2 +- LocalPackages/WebKitExtensions/Package.swift | 2 +- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 1183e8fcc6..fe3c441db6 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -15296,8 +15296,8 @@ isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/duckduckgo/BrowserServicesKit"; requirement = { - branch = "alex/malware-protection-pixels"; - kind = branch; + kind = exactVersion; + version = 223.0.0; }; }; 9FF521422BAA8FF300B9819B /* XCRemoteSwiftPackageReference "lottie-spm" */ = { diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index e72a22a961..abbc299c08 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" : { - "branch" : "alex/malware-protection-pixels", - "revision" : "2686d3b15309d60b25b0e2913ada53362cb37b4d" + "revision" : "e8f94cf597f4a447f86f39f461b736ac9ea280ce", + "version" : "223.0.0" } }, { @@ -41,8 +41,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/duckduckgo/content-scope-scripts", "state" : { - "revision" : "93ea6c3e771bc0b743b38cefbff548c10add9898", - "version" : "6.42.0" + "revision" : "bc808eb735d9eb72d5c54cf2452b104b6a370e25", + "version" : "6.43.0" } }, { @@ -104,8 +104,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/duckduckgo/privacy-dashboard", "state" : { - "revision" : "022c845b06ace6a4aa712a4fa3e79da32193d5c6", - "version" : "7.4.0" + "revision" : "2e2baf7d31c7d8e158a58bc1cb79498c1c727fd2", + "version" : "7.5.0" } }, { diff --git a/LocalPackages/DataBrokerProtection/Package.swift b/LocalPackages/DataBrokerProtection/Package.swift index 79e021c472..2734364a32 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: "223.0.0"), .package(path: "../SwiftUIExtensions"), .package(path: "../AppKitExtensions"), .package(path: "../XPCHelper"), diff --git a/LocalPackages/FeatureFlags/Package.swift b/LocalPackages/FeatureFlags/Package.swift index dcb3d9194f..5cdd9db7b0 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: "223.0.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..9cb58c15b0 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: "223.0.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..b1e912c146 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: "223.0.0"), .package(path: "../WebKitExtensions"), .package(path: "../Utilities"), ], diff --git a/LocalPackages/SubscriptionUI/Package.swift b/LocalPackages/SubscriptionUI/Package.swift index 40bb88836f..c16d25e667 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: "223.0.0"), .package(path: "../SwiftUIExtensions"), .package(path: "../FeatureFlags") ], diff --git a/LocalPackages/WebKitExtensions/Package.swift b/LocalPackages/WebKitExtensions/Package.swift index 44e660355b..df1842ee94 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: "223.0.0"), .package(path: "../AppKitExtensions") ], targets: [ From ca053a31b54c020bd69dc0a9268ba600affc67d5 Mon Sep 17 00:00:00 2001 From: amddg44 Date: Fri, 20 Dec 2024 09:10:02 +0100 Subject: [PATCH 11/11] Updated Safari import passwords instructions for macOS 15.2 (#3671) Task/Issue URL: https://app.asana.com/0/1201462886803403/1208921574824172/f Tech Design URL: CC: **Description**: Update copy on the passwords data import flow in line with latest Safari updates from macOS 15.2 --- .../DataImport/View/FileImportView.swift | 40 +++++++++---- DuckDuckGo/Localizable.xcstrings | 60 +++++++++++++++++++ 2 files changed, 88 insertions(+), 12 deletions(-) diff --git a/DuckDuckGo/DataImport/View/FileImportView.swift b/DuckDuckGo/DataImport/View/FileImportView.swift index 8e704b2293..6536a1cc0a 100644 --- a/DuckDuckGo/DataImport/View/FileImportView.swift +++ b/DuckDuckGo/DataImport/View/FileImportView.swift @@ -275,18 +275,34 @@ func fileImportInstructionsBuilder(source: DataImport.Source, dataType: DataImpo button(UserText.importBookmarksSelectHTMLFile) case (.safari, .passwords), (.safariTechnologyPreview, .passwords): - NSLocalizedString("import.csv.instructions.safari", value: """ - %d Open **Safari** - %d Select **File → Export → Passwords** - %d Save the passwords file someplace you can find it (e.g., Desktop) - %d %@ - """, comment: """ - Instructions to import Passwords as CSV from Safari. - %N$d - step number - %5$@ - “Select Passwords CSV File” button - **bold text**; _italic text_ - """) - button(UserText.importLoginsSelectCSVFile) + if #available(macOS 15.2, *) { + NSLocalizedString("import.csv.instructions.safari.macos15-2", value: """ + %d Open **Safari** + %d Open the **File menu → Export Browsing Data to File...** + %d Select **passwords** and save the file someplace you can find it (e.g., Desktop) + %d Double click the .zip file to unzip it + %d %@ + """, comment: """ + Instructions to import Passwords as CSV from Safari zip file on >= macOS 15.2. + %N$d - step number + %5$@ - “Select Passwords CSV File” button + **bold text**; _italic text_ + """) + button(UserText.importLoginsSelectCSVFile) + } else { + NSLocalizedString("import.csv.instructions.safari", value: """ + %d Open **Safari** + %d Select **File → Export → Passwords** + %d Save the passwords file someplace you can find it (e.g., Desktop) + %d %@ + """, comment: """ + Instructions to import Passwords as CSV from Safari. + %N$d - step number + %5$@ - “Select Passwords CSV File” button + **bold text**; _italic text_ + """) + button(UserText.importLoginsSelectCSVFile) + } case (.safari, .bookmarks), (.safariTechnologyPreview, .bookmarks): NSLocalizedString("import.html.instructions.safari", value: """ diff --git a/DuckDuckGo/Localizable.xcstrings b/DuckDuckGo/Localizable.xcstrings index f0dbc2e23a..4d3d7c5407 100644 --- a/DuckDuckGo/Localizable.xcstrings +++ b/DuckDuckGo/Localizable.xcstrings @@ -31111,6 +31111,66 @@ } } }, + "import.csv.instructions.safari.macos15-2" : { + "comment" : "Instructions to import Passwords as CSV from Safari zip file on >= macOS 15.2.\n%N$d - step number\n%5$@ - “Select Passwords CSV File” button\n**bold text**; _italic text_", + "extractionState" : "extracted_with_value", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "%1$d Öffne **Safari**\n%2$d Öffne das Menü **Datei → Browserdaten in Datei exportieren ...**\n%3$d Wähle **Passwörter** und speichere die Datei an einem Ort, an dem du sie wiederfindest (z. B. Desktop)\n%4$d Doppelklicke auf die .zip-Datei, um sie zu entpacken\n%5$d %6$@" + } + }, + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "%1$d Open **Safari**\n%2$d Open the **File menu → Export Browsing Data to File...**\n%3$d Select **passwords** and save the file someplace you can find it (e.g., Desktop)\n%4$d Double click the .zip file to unzip it\n%5$d %6$@" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "%1$d Abre **Safari**\n%2$d Abre el menú **Archivo → Exportar datos de navegación a archivo...**\n%3$d Selecciona **contraseñas** y guarda el archivo en algún lugar donde puedas encontrarlo (por ejemplo, en el escritorio)\n%4$d Haz doble clic en el archivo .zip para descomprimirlo\n%5$d %6$@" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "%1$d Ouvrez **Safari**\n%2$d Ouvrez le **menu Fichier → Exporter les données de navigation vers le fichier…**\n%3$d Sélectionnez **mots de passe** et enregistrez le fichier à un endroit où le trouver facilement (par exemple, sur le bureau)\n%4$d Double-cliquez sur le fichier .zip pour le décompresser\n%5$d %6$@" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "%1$d Apri **Safari**\n%2$d Apri il menu **File → Esporta i dati di navigazione in un file...**\n%3$d Seleziona **password** e salva il file in una posizione che ti consenta di trovarlo (ad esempio, sul desktop)\n%4$d Fai doppio clic sul file .zip per decomprimerlo\n%5$d %6$@" + } + }, + "nl" : { + "stringUnit" : { + "state" : "translated", + "value" : "%1$d Open **Safari**\n%2$d Open het menu **Bestand → Browsergegevens exporteren naar bestand...**\n%3$d Selecteer **wachtwoorden** en sla het bestand op een plek op waar je het kunt vinden (bijv. je bureaublad)\n%4$d Dubbelklik op het .zip-bestand om het uit te pakken\n%5$d %6$@" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "%1$d Otwórz **Safari**\n%2$d Otwórz menu **Plik → Eksportuj dane przeglądania do pliku...**\n%3$d Wybierz **hasła** i zapisz plik w łatwo dostępnym miejscu (np. na biurku)\n%4$d Kliknij dwukrotnie plik .zip w celu jego rozpakowania\n%5$d %6$@" + } + }, + "pt" : { + "stringUnit" : { + "state" : "translated", + "value" : "%1$d Abre o **Safari**\n%2$d Abre o menu **Ficheiro → Exportar dados de navegação para ficheiro...**\n%3$d Seleciona **palavras-passe** e guarda o ficheiro num local onde o possas encontrar (por exemplo, no ambiente de trabalho)\n%4$d Clica duas vezes no ficheiro .zip para o descomprimir\n%5$d %6$@" + } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "%1$d Запустите **Safari**\n%2$d Откройте меню **Файл → Экспортировать данные просмотров в файл...**\n%3$d Выберите **пароли** и сохраните файл там, где вы легко его найдете (например, на рабочем столе)\n%4$d Дважды нажмите мышью файл .zip, чтобы распаковать его\n%5$d %6$@" + } + } + } + }, "import.csv.instructions.vivaldi" : { "comment" : "Instructions to import Passwords exported as CSV from Vivaldi browser.\n%N$d - step number\n%2$s - browser name (Vivaldi)\n%5$@ - menu button icon\n%8$@ - “Select Passwords CSV File” button\n**bold text**; _italic text_", "extractionState" : "extracted_with_value",