From 99e3134f5fd0e4ba36978d532e95d498fde2867e Mon Sep 17 00:00:00 2001 From: Graeme Arthur Date: Mon, 13 Nov 2023 15:25:37 +0100 Subject: [PATCH 01/10] Update version number --- Configuration/Version.xcconfig | 2 +- DuckDuckGo/Settings.bundle/Root.plist | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Configuration/Version.xcconfig b/Configuration/Version.xcconfig index f16be59a1f..773b0e1646 100644 --- a/Configuration/Version.xcconfig +++ b/Configuration/Version.xcconfig @@ -1 +1 @@ -MARKETING_VERSION = 7.96.0 +MARKETING_VERSION = 7.97.0 diff --git a/DuckDuckGo/Settings.bundle/Root.plist b/DuckDuckGo/Settings.bundle/Root.plist index fb5f1dc72e..52e3696d8c 100644 --- a/DuckDuckGo/Settings.bundle/Root.plist +++ b/DuckDuckGo/Settings.bundle/Root.plist @@ -6,7 +6,7 @@ DefaultValue - 7.96.0 + 7.97.0 Key version Title From 43fbc334fb6abfbe55495887be10645c18955c21 Mon Sep 17 00:00:00 2001 From: Graeme Arthur Date: Mon, 13 Nov 2023 15:25:56 +0100 Subject: [PATCH 02/10] Update embedded files --- .../AppPrivacyConfigurationDataProvider.swift | 4 +- Core/AppTrackerDataSetProvider.swift | 4 +- Core/ios-config.json | 518 ++++++++++++++---- Core/trackerData.json | 506 +++++++++++------ 4 files changed, 774 insertions(+), 258 deletions(-) diff --git a/Core/AppPrivacyConfigurationDataProvider.swift b/Core/AppPrivacyConfigurationDataProvider.swift index 3e07b81b83..4e4e1e6202 100644 --- a/Core/AppPrivacyConfigurationDataProvider.swift +++ b/Core/AppPrivacyConfigurationDataProvider.swift @@ -23,8 +23,8 @@ import BrowserServicesKit final public class AppPrivacyConfigurationDataProvider: EmbeddedDataProvider { public struct Constants { - public static let embeddedDataETag = "\"39c652b21aa330463726faf240e03445\"" - public static let embeddedDataSHA = "b19c28e816008ace47a9e3e58f74eef6558b5cbdcd7d79d098d7d2e56d686075" + public static let embeddedDataETag = "\"71b1b5499f333348df4f9bc52b74185f\"" + public static let embeddedDataSHA = "a5b30cf79e5efc40fec6fb28491a7484822041d927a6e2d8c9c7ccd3bd236c61" } public var embeddedDataEtag: String { diff --git a/Core/AppTrackerDataSetProvider.swift b/Core/AppTrackerDataSetProvider.swift index 625fe0a39b..c41f8ed1b5 100644 --- a/Core/AppTrackerDataSetProvider.swift +++ b/Core/AppTrackerDataSetProvider.swift @@ -23,8 +23,8 @@ import BrowserServicesKit final public class AppTrackerDataSetProvider: EmbeddedDataProvider { public struct Constants { - public static let embeddedDataETag = "\"3b73923ebfd4702c33aea682db0bac11\"" - public static let embeddedDataSHA = "16e1e52530db19badfefc9a07d76620f9c608c12dc144f67020da8a9a4ddb0fa" + public static let embeddedDataETag = "\"3a50d09fd78a893f1a284051d1f777de\"" + public static let embeddedDataSHA = "2c1995807a61fd9fa311baab01633411282759732f098765f5380bda5e92b9e2" } public var embeddedDataEtag: String { diff --git a/Core/ios-config.json b/Core/ios-config.json index 530bbe5602..ce6aeae32a 100644 --- a/Core/ios-config.json +++ b/Core/ios-config.json @@ -1,6 +1,6 @@ { "readme": "https://github.com/duckduckgo/privacy-configuration", - "version": 1699039046694, + "version": 1699875322077, "features": { "adClickAttribution": { "readme": "https://help.duckduckgo.com/duckduckgo-help-pages/privacy/web-tracking-protections/#3rd-party-tracker-loading-protection", @@ -82,6 +82,9 @@ }, { "domain": "marvel.com" + }, + { + "domain": "sundancecatalog.com" } ], "settings": { @@ -107,7 +110,7 @@ ] }, "state": "enabled", - "hash": "5a2395ef011fb7be4acb7885024e63fe" + "hash": "5bfae22c5e0cb13c0a25ce80531827ff" }, "androidBrowserConfig": { "exceptions": [], @@ -247,6 +250,9 @@ }, { "domain": "marvel.com" + }, + { + "domain": "sundancecatalog.com" } ], "settings": { @@ -255,7 +261,7 @@ ] }, "state": "enabled", - "hash": "03b154384cddc4cecfd685959d658256" + "hash": "4719cb6c793d13a9ac81c329f4d206c8" }, "autofill": { "exceptions": [ @@ -298,12 +304,15 @@ }, { "percent": 10 + }, + { + "percent": 100 } ] } } }, - "hash": "968968437514e582ebd4789a22207b91" + "hash": "3d95a9b3c8112148eda0ad09b1002b53" }, "clickToLoad": { "exceptions": [ @@ -915,6 +924,9 @@ }, { "domain": "marvel.com" + }, + { + "domain": "sundancecatalog.com" } ], "settings": { @@ -932,7 +944,7 @@ } }, "state": "disabled", - "hash": "f57113e4f2e7dd0fb93f5f73f9ef4fdb" + "hash": "36e8971fa9bb204b78a5929a14a108dd" }, "clickToPlay": { "exceptions": [ @@ -944,6 +956,9 @@ }, { "domain": "marvel.com" + }, + { + "domain": "sundancecatalog.com" } ], "settings": { @@ -956,7 +971,7 @@ } }, "state": "disabled", - "hash": "6724dd4acc868b402c6d23193bc6ba56" + "hash": "4390af06f967ef97a827aeab0ac0d1ca" }, "contentBlocking": { "state": "enabled", @@ -976,9 +991,6 @@ { "domain": "ads.google.com" }, - { - "domain": "sundancecatalog.com" - }, { "domain": "earth.google.com" }, @@ -987,9 +999,12 @@ }, { "domain": "marvel.com" + }, + { + "domain": "sundancecatalog.com" } ], - "hash": "aa730da73ce0d03c67fcac68f9196b97" + "hash": "71ad0f38f9ce2bbacae5ff7db05511ec" }, "cookie": { "settings": { @@ -1036,10 +1051,13 @@ }, { "domain": "marvel.com" + }, + { + "domain": "sundancecatalog.com" } ], "state": "disabled", - "hash": "01ed94213fc52b4ef93d988070491c49" + "hash": "e41dbd0af3841636937030d91bc305b1" }, "customUserAgent": { "settings": { @@ -1218,12 +1236,18 @@ { "domain": "marvel.com" }, + { + "domain": "sundancecatalog.com" + }, { "domain": "cvs.com" }, { "domain": "facebook.com" }, + { + "domain": "finewineandgoodspirits.com" + }, { "domain": "formula1.com" }, @@ -1261,12 +1285,15 @@ }, { "domain": "marvel.com" + }, + { + "domain": "sundancecatalog.com" } ] }, "exceptions": [], "state": "enabled", - "hash": "232df10f29daf038ce889d28a9064a6b" + "hash": "b101ded240bc51fce0ece83191b2da62" }, "duckPlayer": { "exceptions": [], @@ -1339,60 +1366,6 @@ { "domain": "duckduckgo.com" }, - { - "domain": "bild.de" - }, - { - "domain": "derstandard.at" - }, - { - "domain": "foxnews.com" - }, - { - "domain": "kbb.com" - }, - { - "domain": "wiwo.de" - }, - { - "domain": "metro.co.uk" - }, - { - "domain": "blick.ch" - }, - { - "domain": "thechive.com" - }, - { - "domain": "bizjournals.com" - }, - { - "domain": "slate.com" - }, - { - "domain": "dailycaller.com" - }, - { - "domain": "dailymail.co.uk" - }, - { - "domain": "eltiempo.com" - }, - { - "domain": "dailyherald.com" - }, - { - "domain": "publico.es" - }, - { - "domain": "rawstory.com" - }, - { - "domain": "allgemeine-zeitung.de" - }, - { - "domain": "thehindu.com" - }, { "domain": "earth.google.com" }, @@ -1401,6 +1374,9 @@ }, { "domain": "marvel.com" + }, + { + "domain": "sundancecatalog.com" } ], "settings": { @@ -1610,6 +1586,10 @@ "selector": ".ad_container", "type": "closest-empty" }, + { + "selector": ".ad-container--leaderboard", + "type": "hide-empty" + }, { "selector": ".ads_container", "type": "hide-empty" @@ -1813,10 +1793,6 @@ { "selector": "#ez-content-blocker-container", "type": "hide" - }, - { - "selector": "#notify-adblock", - "type": "hide" } ], "styleTagExceptions": [ @@ -1863,6 +1839,7 @@ "advertisementhide ad", "advertisement - scroll to continue", "advertisement · scroll to continue", + "advertisement - story continues below", "advertising", "advertising\nskip ad", "advertising\nskip ad\nskip ad\nskip ad", @@ -1911,6 +1888,35 @@ } ] }, + { + "domain": "allgemeine-zeitung.de", + "rules": [ + { + "type": "disable-default" + }, + { + "selector": ".adSlot", + "type": "hide-empty" + }, + { + "selector": ".adBorder", + "type": "hide-empty" + }, + { + "selector": ".nativeAd", + "type": "closest-empty" + } + ] + }, + { + "domain": "androidpolice.com", + "rules": [ + { + "selector": "[class*='ad-zone']", + "type": "hide" + } + ] + }, { "domain": "apnews.com", "rules": [ @@ -1951,6 +1957,31 @@ } ] }, + { + "domain": "bild.de", + "rules": [ + { + "type": "disable-default" + }, + { + "selector": "[id^='mrec']", + "type": "hide-empty" + }, + { + "selector": "#superbanner", + "type": "hide-empty" + } + ] + }, + { + "domain": "bizjournals.com", + "rules": [ + { + "selector": ".adwrap", + "type": "closest-empty" + } + ] + }, { "domain": "bleacherreport.com", "rules": [ @@ -1969,6 +2000,15 @@ } ] }, + { + "domain": "blick.ch", + "rules": [ + { + "selector": "[id*='appnexus-placement-']", + "type": "hide-empty" + } + ] + }, { "domain": "bloomberg.com", "rules": [ @@ -2070,6 +2110,31 @@ } ] }, + { + "domain": "dailyherald.com", + "rules": [ + { + "selector": ".instoryAdBlock", + "type": "hide" + } + ] + }, + { + "domain": "dailymail.co.uk", + "rules": [ + { + "type": "disable-default" + }, + { + "selector": "[class*='dmg-ads']", + "type": "hide-empty" + }, + { + "selector": ".mol-ads-label-container", + "type": "closest-empty" + } + ] + }, { "domain": "dallasnews.com", "rules": [ @@ -2235,6 +2300,27 @@ } ] }, + { + "domain": "foodnetwork.co.uk", + "rules": [ + { + "selector": ".bg-bodyBg", + "type": "hide-empty" + }, + { + "selector": ".module--ad-module-primary", + "type": "hide-empty" + }, + { + "selector": "#mtf-1", + "type": "closest-empty" + }, + { + "selector": "#btf-1", + "type": "closest-empty" + } + ] + }, { "domain": "football365.com", "rules": [ @@ -2481,6 +2567,15 @@ } ] }, + { + "domain": "insider.com", + "rules": [ + { + "selector": ".in-post-sticky", + "type": "hide-empty" + } + ] + }, { "domain": "investing.com", "rules": [ @@ -2581,6 +2676,18 @@ } ] }, + { + "domain": "metro.co.uk", + "rules": [ + { + "type": "disable-default" + }, + { + "selector": ".ad-slot-container", + "type": "hide-empty" + } + ] + }, { "domain": "mirror.co.uk", "rules": [ @@ -2847,6 +2954,19 @@ } ] }, + { + "domain": "publico.es", + "rules": [ + { + "selector": ".pb-ads", + "type": "hide-empty" + }, + { + "selector": "#sc_intxt_container", + "type": "hide" + } + ] + }, { "domain": "qz.com", "rules": [ @@ -2856,6 +2976,35 @@ } ] }, + { + "domain": "rawstory.com", + "rules": [ + { + "selector": ".container_proper-ad-unit", + "type": "hide" + }, + { + "selector": ".controlled_via_ad_manager", + "type": "hide" + }, + { + "selector": ".mgid_3x2", + "type": "hide-empty" + }, + { + "selector": ".proper-ad-unit", + "type": "hide" + }, + { + "selector": "[id^='rc-widget-']", + "type": "hide-empty" + }, + { + "selector": "#story-top-ad", + "type": "hide" + } + ] + }, { "domain": "reddit.com", "rules": [ @@ -2983,6 +3132,10 @@ { "selector": ".slate-ad", "type": "hide-empty" + }, + { + "selector": ".top-ad", + "type": "hide" } ] }, @@ -3021,6 +3174,15 @@ } ] }, + { + "domain": "sportbible.com", + "rules": [ + { + "selector": "[class*='Advert']", + "type": "hide" + } + ] + }, { "domain": "target.com", "rules": [ @@ -3039,6 +3201,15 @@ } ] }, + { + "domain": "thegatewaypundit.com", + "rules": [ + { + "selector": ".code-block", + "type": "hide" + } + ] + }, { "domain": "thehour.com", "rules": [ @@ -3048,6 +3219,15 @@ } ] }, + { + "domain": "thehindu.com", + "rules": [ + { + "selector": "#articledivrec", + "type": "hide-empty" + } + ] + }, { "domain": "thetimes.co.uk", "rules": [ @@ -3183,6 +3363,10 @@ { "selector": "[class^='Ad__Container-']", "type": "hide" + }, + { + "selector": "#ac-lre-player", + "type": "hide-empty" } ] }, @@ -3212,6 +3396,15 @@ } ] }, + { + "domain": "westernjournal.com", + "rules": [ + { + "selector": ".sponsor", + "type": "hide-empty" + } + ] + }, { "domain": "washingtonpost.com", "rules": [ @@ -3247,6 +3440,14 @@ } ] }, + { + "domain": "wiwo.de", + "rules": [ + { + "type": "disable-default" + } + ] + }, { "domain": "wsj.com", "rules": [ @@ -3409,7 +3610,7 @@ ] }, "state": "enabled", - "hash": "903602d78d217518a48be612b2a08f3e" + "hash": "15184cba961aadf588965f6caf070306" }, "exceptionHandler": { "exceptions": [ @@ -3421,10 +3622,13 @@ }, { "domain": "marvel.com" + }, + { + "domain": "sundancecatalog.com" } ], "state": "disabled", - "hash": "acf631a1f283d1ea71e5d3116f17a110" + "hash": "5e792dd491428702bc0104240fbce0ce" }, "fingerprintingAudio": { "state": "disabled", @@ -3440,9 +3644,12 @@ }, { "domain": "marvel.com" + }, + { + "domain": "sundancecatalog.com" } ], - "hash": "aec17726775580a32c51d6ad0559c13f" + "hash": "f25a8f2709e865c2bd743828c7ee2f77" }, "fingerprintingBattery": { "exceptions": [ @@ -3457,10 +3664,13 @@ }, { "domain": "marvel.com" + }, + { + "domain": "sundancecatalog.com" } ], "state": "enabled", - "hash": "f74e2255710593a76b5a80571da555a2" + "hash": "440f8d663d59430c93d66208655d9238" }, "fingerprintingCanvas": { "settings": { @@ -3559,10 +3769,13 @@ }, { "domain": "marvel.com" + }, + { + "domain": "sundancecatalog.com" } ], "state": "disabled", - "hash": "55ba309065f40d78a5f0308411d6df97" + "hash": "ea4c565bae27996f0d651300d757594c" }, "fingerprintingHardware": { "settings": { @@ -3610,10 +3823,13 @@ }, { "domain": "marvel.com" + }, + { + "domain": "sundancecatalog.com" } ], "state": "enabled", - "hash": "81bda64a0a893eebb721772fbd64126a" + "hash": "911cbc583f376d416ac75c57ecc577f1" }, "fingerprintingScreenSize": { "settings": { @@ -3661,10 +3877,13 @@ }, { "domain": "marvel.com" + }, + { + "domain": "sundancecatalog.com" } ], "state": "enabled", - "hash": "4fa7c8746240605af7885a953dcbdfe9" + "hash": "0fb22f84b750e0d29bad55bd95d9ce2b" }, "fingerprintingTemporaryStorage": { "exceptions": [ @@ -3682,10 +3901,13 @@ }, { "domain": "marvel.com" + }, + { + "domain": "sundancecatalog.com" } ], "state": "enabled", - "hash": "5e81950bd7e1cbf6489ed4fb7d5b57fb" + "hash": "568a23faa984c8e7eda002294ad8f82f" }, "googleRejected": { "exceptions": [ @@ -3697,10 +3919,13 @@ }, { "domain": "marvel.com" + }, + { + "domain": "sundancecatalog.com" } ], "state": "disabled", - "hash": "acf631a1f283d1ea71e5d3116f17a110" + "hash": "5e792dd491428702bc0104240fbce0ce" }, "gpc": { "state": "enabled", @@ -3737,6 +3962,9 @@ }, { "domain": "marvel.com" + }, + { + "domain": "sundancecatalog.com" } ], "settings": { @@ -3748,7 +3976,7 @@ "privacy-test-pages.site" ] }, - "hash": "0a23d1c1dc75bb6664af7d81c6f80e77" + "hash": "083267b595694bd75cda73218f8811c2" }, "harmfulApis": { "settings": { @@ -3858,10 +4086,13 @@ }, { "domain": "marvel.com" + }, + { + "domain": "sundancecatalog.com" } ], "state": "disabled", - "hash": "cd14e5f0c64cbe269b73cd40b8c89c42" + "hash": "44d3e707cba3ee0a3578f52dc2ce2aa4" }, "https": { "state": "enabled", @@ -3883,9 +4114,12 @@ }, { "domain": "marvel.com" + }, + { + "domain": "sundancecatalog.com" } ], - "hash": "b055b164b3c3a9f20ad93e041be1810e" + "hash": "f772808ed34cc9ea8cbcbb7cdaf74429" }, "incontextSignup": { "exceptions": [], @@ -3923,6 +4157,9 @@ }, { "domain": "marvel.com" + }, + { + "domain": "sundancecatalog.com" } ], "settings": { @@ -3933,7 +4170,7 @@ ] }, "state": "enabled", - "hash": "9cbed3731aad3fb286c8245ba8ff87dd" + "hash": "698de7b963d7d7942c5c5d1e986bb1b1" }, "networkProtection": { "state": "disabled", @@ -3966,10 +4203,13 @@ }, { "domain": "marvel.com" + }, + { + "domain": "sundancecatalog.com" } ], "state": "disabled", - "hash": "e2fe271add53f2e5dafb31b235d1fa54" + "hash": "841fa92b9728c9754f050662678f82c7" }, "privacyDashboard": { "exceptions": [], @@ -4012,10 +4252,13 @@ }, { "domain": "marvel.com" + }, + { + "domain": "sundancecatalog.com" } ], "state": "disabled", - "hash": "6a035dc634a0eaff88ce00de3905a1bb" + "hash": "0d3df0f7c24ebde89d2dced4e2d34322" }, "requestFilterer": { "state": "disabled", @@ -4028,12 +4271,15 @@ }, { "domain": "marvel.com" + }, + { + "domain": "sundancecatalog.com" } ], "settings": { "windowInMs": 0 }, - "hash": "591960d057333a55489a557f5cd7d121" + "hash": "0fff8017d8ea4b5609b8f5c110be1401" }, "runtimeChecks": { "state": "disabled", @@ -4046,10 +4292,13 @@ }, { "domain": "marvel.com" + }, + { + "domain": "sundancecatalog.com" } ], "settings": {}, - "hash": "158fe8be52fa1c0fabf08d8a12fd55b0" + "hash": "800a19533c728bbec7e31e466f898268" }, "serviceworkerInitiatedRequests": { "exceptions": [ @@ -4061,10 +4310,13 @@ }, { "domain": "marvel.com" + }, + { + "domain": "sundancecatalog.com" } ], "state": "disabled", - "hash": "acf631a1f283d1ea71e5d3116f17a110" + "hash": "5e792dd491428702bc0104240fbce0ce" }, "trackerAllowlist": { "state": "enabled", @@ -4191,6 +4443,16 @@ } ] }, + "adserver.adtech.advertising.com": { + "rules": [ + { + "rule": "adserver.adtech.advertising.com/pubapi/3.0/1/54669.7/0/0/ADTECH;v=2;cmd=bid;cors=yes", + "domains": [ + "collider.com" + ] + } + ] + }, "adswizz.com": { "rules": [ { @@ -4198,6 +4460,12 @@ "domains": [ "tunein.com" ] + }, + { + "rule": "adswizz.com/adswizz/js/SynchroClient2.js", + "domains": [ + "tunein.com" + ] } ] }, @@ -4773,7 +5041,6 @@ "rule": "pubads.g.doubleclick.net/gampad/ads", "domains": [ "crunchyroll.com", - "fifa.com", "nhl.com", "rocketnews24.com", "viki.com" @@ -5001,6 +5268,7 @@ { "rule": "app.five9.com", "domains": [ + "gmsdnv.com", "machiassavings.bank" ] } @@ -5205,6 +5473,12 @@ "" ] }, + { + "rule": "www.google.com/url", + "domains": [ + "" + ] + }, { "rule": "www.google.com/maps/", "domains": [ @@ -5213,6 +5487,16 @@ } ] }, + "googleapis.com": { + "rules": [ + { + "rule": "imasdk.googleapis.com/js/sdkloader/ima3.js", + "domains": [ + "nfl.com" + ] + } + ] + }, "googleoptimize.com": { "rules": [ { @@ -5235,6 +5519,14 @@ "zefoy.com" ] }, + { + "rule": "pagead2.googlesyndication.com/pagead/show_ads.js", + "domains": [ + "luckylandslots.com", + "rocketnews24.com", + "zefoy.com" + ] + }, { "rule": "tpc.googlesyndication.com/pagead/js/loader21.html", "domains": [ @@ -5383,6 +5675,7 @@ "thecw38.com", "thecw46.com", "thecwtc.com", + "thenationaldesk.com", "turnto10.com", "univisionseattle.com", "upnorthlive.com", @@ -5483,6 +5776,12 @@ "domains": [ "pippintitle.com" ] + }, + { + "rule": "no-cache.hubspot.com/cta/default/", + "domains": [ + "" + ] } ] }, @@ -5588,6 +5887,16 @@ } ] }, + "jsdelivr.net": { + "rules": [ + { + "rule": "cdn.jsdelivr.net/npm/@fingerprintjs/fingerprintjs@3/dist/fp.js", + "domains": [ + "sbermarket.ru" + ] + } + ] + }, "kampyle.com": { "rules": [ { @@ -5638,6 +5947,7 @@ { "rule": "static.klaviyo.com/onsite/js/klaviyo.js", "domains": [ + "essentialpraxis.com", "kidsguide.com", "urbanebikes.com" ] @@ -6774,9 +7084,12 @@ }, { "domain": "marvel.com" + }, + { + "domain": "sundancecatalog.com" } ], - "hash": "2ea09955d838b29daa5416586bb2f25a" + "hash": "65670bfba426ac832fe6bb2082c432c8" }, "trackingCookies1p": { "settings": { @@ -6794,10 +7107,13 @@ }, { "domain": "marvel.com" + }, + { + "domain": "sundancecatalog.com" } ], "state": "disabled", - "hash": "057704f003231b68cde1faca12adec27" + "hash": "4dddf681372a2aea9788090b13db6e6f" }, "trackingCookies3p": { "settings": { @@ -6812,10 +7128,13 @@ }, { "domain": "marvel.com" + }, + { + "domain": "sundancecatalog.com" } ], "state": "disabled", - "hash": "e2fe271add53f2e5dafb31b235d1fa54" + "hash": "841fa92b9728c9754f050662678f82c7" }, "trackingParameters": { "exceptions": [ @@ -6828,6 +7147,9 @@ { "domain": "marvel.com" }, + { + "domain": "sundancecatalog.com" + }, { "domain": "theverge.com" } @@ -6862,7 +7184,7 @@ ] }, "state": "enabled", - "hash": "2ca96907627936c8912983c971c5f1c9" + "hash": "f2437495da4898e8e048643ab38ef372" }, "userAgentRotation": { "settings": { @@ -6877,10 +7199,13 @@ }, { "domain": "marvel.com" + }, + { + "domain": "sundancecatalog.com" } ], "state": "disabled", - "hash": "3893596da5fb3653a6adc10538f08a2e" + "hash": "f65d10dfdf6739feab99a08d42734747" }, "voiceSearch": { "exceptions": [], @@ -6897,6 +7222,9 @@ }, { "domain": "marvel.com" + }, + { + "domain": "sundancecatalog.com" } ], "state": "enabled", @@ -6929,7 +7257,7 @@ } ] }, - "hash": "3702e5c5e88b46c494d8e4ef4e17a8da" + "hash": "4e94cff79e689ff320de22a57e242bdd" }, "windowsPermissionUsage": { "exceptions": [], diff --git a/Core/trackerData.json b/Core/trackerData.json index 18ddb15be4..84975e1a36 100644 --- a/Core/trackerData.json +++ b/Core/trackerData.json @@ -1,7 +1,7 @@ { "_builtWith": { - "tracker-radar": "29f80529aa526f0a0f8daadb1c8717d6dccdbb1a45f98477de48e8a8d213d386-4013b4e91930c643394cb31c6c745356f133b04f", - "tracker-surrogates": "d61691a2fdf9f4dc062a8d248fd1e78c20b5b892" + "tracker-radar": "ae2fbc01abd26abf1903208a5cabbaed6a96ab2aa13779d2125a98fc45fee2cd-4013b4e91930c643394cb31c6c745356f133b04f", + "tracker-surrogates": "abd6067fac9693cc5a43d48931b111ca08cb0d5a" }, "readme": "https://github.com/duckduckgo/tracker-blocklists", "trackers": { @@ -136,45 +136,14 @@ "Ad Motivated Tracking", "Advertising" ], - "default": "ignore", + "default": "block", "rules": [ { - "rule": "2mdn\\.net/dot\\.gif" - }, - { - "rule": "2mdn\\.net/10533936/1679336805544/" - }, - { - "rule": "2mdn\\.net/8762481/1679421215390" - }, - { - "rule": "2mdn\\.net/879366/" - }, - { - "rule": "2mdn\\.net/ads/" - }, - { - "rule": "2mdn\\.net/creatives/assets/" - }, - { - "rule": "2mdn\\.net/dfp/" - }, - { - "rule": "2mdn\\.net/dynamic/2/" - }, - { - "rule": "2mdn\\.net/sadbundle/" - }, - { - "rule": "2mdn\\.net/simgad/[0-9]+" - }, - { - "rule": "2mdn\\.net/videoplayback" + "rule": "2mdn\\.net/instream/html5/ima3\\.js", + "surrogate": "google-ima.js" }, { "rule": "2mdn\\.net/instream/video/client\\.js", - "fingerprinting": 1, - "cookies": 0, "exceptions": { "domains": [ "dailywire.com", @@ -822,7 +791,17 @@ "Social - Share", "Third-Party Analytics Marketing" ], - "default": "block" + "default": "block", + "rules": [ + { + "rule": "static\\.addtoany\\.com/menu/page\\.js", + "exceptions": { + "domains": [ + "tiny.cc" + ] + } + } + ] }, "adelixir.com": { "domain": "adelixir.com", @@ -2519,9 +2498,16 @@ "foxbusiness.com", "foxnews.com", "fyi.tv", + "gamingbible.co.uk", + "gamingbible.com", "history.com", + "ladbible.com", "mylifetime.com", - "sueddeutsche.de" + "sportbible.com", + "sueddeutsche.de", + "tyla.com", + "unilad.co.uk", + "unilad.com" ] } } @@ -4474,14 +4460,7 @@ "fingerprinting": 2, "cookies": 0.000824, "categories": [], - "default": "ignore", - "rules": [ - { - "rule": "boldchat\\.com/aid/.*/vms\\.js", - "fingerprinting": 2, - "cookies": 0.000201 - } - ] + "default": "ignore" }, "booking.com": { "domain": "booking.com", @@ -7761,9 +7740,14 @@ "default": "ignore", "rules": [ { - "rule": "dbukjj6eu5tsf\\.cloudfront\\.net\\/assets\\.sidearmsports\\.com\\/common\\/js\\/20170825\\/video\\.js", + "rule": "dbukjj6eu5tsf\\.cloudfront\\.net/assets\\.sidearmsports\\.com/common/js/20170825/video\\.js", "fingerprinting": 3, - "cookies": 0 + "cookies": 0, + "exceptions": { + "domains": [ + "utsports.com" + ] + } } ] }, @@ -8257,6 +8241,14 @@ "sbs.com.au" ] } + }, + { + "rule": "g\\.doubleclick\\.net/pagead/ads", + "exceptions": { + "domains": [ + "fukuishimbun.co.jp" + ] + } } ] }, @@ -9825,11 +9817,6 @@ ], "default": "ignore", "rules": [ - { - "rule": "facebook\\.net/.*/all\\.js", - "fingerprinting": 1, - "cookies": 0.0000408 - }, { "rule": "facebook\\.net/.*/fbevents\\.js", "fingerprinting": 1, @@ -10814,14 +10801,7 @@ "fingerprinting": 1, "cookies": 0.0000408, "categories": [], - "default": "ignore", - "rules": [ - { - "rule": "geoip-js\\.com\\/js\\/apis\\/geoip2\\/v2\\.1\\/geoip2\\.js", - "fingerprinting": 1, - "cookies": 0.0000204 - } - ] + "default": "ignore" }, "getblue.io": { "domain": "getblue.io", @@ -11502,7 +11482,33 @@ "Ad Motivated Tracking", "Advertising" ], - "default": "block" + "default": "ignore", + "rules": [ + { + "rule": "googleadservices\\.com/gampad/cookie\\.js" + }, + { + "rule": "googleadservices\\.com/pagead/conversion\\.js" + }, + { + "rule": "googleadservices\\.com/gampad/google_service\\.js" + }, + { + "rule": "googleadservices\\.com/gampad/google_ads\\.js" + }, + { + "rule": "googleadservices\\.com/favicon\\.ico" + }, + { + "rule": "googleadservices\\.com/ga/phone" + }, + { + "rule": "googleadservices\\.com/ccm/conversion/845940546/" + }, + { + "rule": "googleadservices\\.com/pagead/conversion/" + } + ] }, "googlehosted.com": { "domain": "googlehosted.com", @@ -11619,9 +11625,28 @@ "rule": "googlesyndication\\.com/adsbygoogle\\.js", "surrogate": "adsbygoogle.js" }, + { + "rule": "pagead2\\.googlesyndication\\.com/pagead/js/adsbygoogle\\.js", + "surrogate": "adsbygoogle.js", + "exceptions": { + "domains": [ + "dronedj.com", + "fukuishimbun.co.jp", + "spaceexplored.com" + ] + } + }, { "rule": "googlesyndication\\.com/pagead/js/adsbygoogle\\.js", "surrogate": "adsbygoogle.js" + }, + { + "rule": "pagead2\\.googlesyndication\\.com/pagead/managed/js/adsense", + "exceptions": { + "domains": [ + "fukuishimbun.co.jp" + ] + } } ] }, @@ -11986,11 +12011,6 @@ "rule": "groovehq\\.com\\/api\\/shim\\/27299f7da6676b065f217a683a418325", "fingerprinting": 2, "cookies": 0 - }, - { - "rule": "groovehq\\.com\\/_next\\/static\\/chunks\\/9fd8c5e27f99fce506e2e5d3b010ddba7982b0f2\\.7fb5a86b2706698b7a7e\\.js", - "fingerprinting": 2, - "cookies": 0 } ] }, @@ -12908,14 +12928,6 @@ ] } }, - { - "rule": "hubspot\\.com/api/livechat-public/v1/", - "exceptions": { - "types": [ - "xmlhttprequest" - ] - } - }, { "rule": "hubspot\\.com/hubfs/", "exceptions": { @@ -13255,7 +13267,13 @@ "Content Delivery", "Embedded Content" ], - "default": "ignore" + "default": "ignore", + "rules": [ + { + "rule": "imasdk\\.googleapis\\.com/js/sdkloader/ima3\\.js", + "surrogate": "google-ima.js" + } + ] }, "imedia.cz": { "domain": "imedia.cz", @@ -14240,18 +14258,6 @@ } ] }, - "ipify.org": { - "domain": "ipify.org", - "owner": { - "name": "ipify.org", - "displayName": "ipify.org" - }, - "prevalence": 0.00555, - "fingerprinting": 1, - "cookies": 0.000116, - "categories": [], - "default": "block" - }, "iplsc.com": { "domain": "iplsc.com", "owner": { @@ -15484,25 +15490,7 @@ "Embedded Content", "Third-Party Analytics Marketing" ], - "default": "ignore", - "rules": [ - { - "rule": "lightboxcdn\\.com/vendor/.*/user\\.js", - "fingerprinting": 3, - "cookies": 0.0000749 - }, - { - "rule": "lightboxcdn\\.com\\/w37htfhcq2\\/vendor\\/721dac7b-a982-4a33-afe7-ffe31144fbdd\\/user\\.js", - "fingerprinting": 3, - "cookies": 0.0000136 - }, - { - "rule": "lightboxcdn\\.com\\/vendor\\/b90a8cf1-793b-4cc5-b282-f863e44f81fa\\/lightbox_inline\\.js", - "fingerprinting": 0, - "cookies": 0, - "comment": "pixel" - } - ] + "default": "ignore" }, "lijit.com": { "domain": "lijit.com", @@ -15653,7 +15641,60 @@ "Ad Motivated Tracking", "Advertising" ], - "default": "block" + "default": "ignore", + "rules": [ + { + "rule": "linksynergy\\.com/rcs" + }, + { + "rule": "linksynergy\\.com/jsp" + }, + { + "rule": "linksynergy\\.com/cs" + }, + { + "rule": "linksynergy\\.com/act\\.php" + }, + { + "rule": "linksynergy\\.com/t" + }, + { + "rule": "linksynergy\\.com/consent/v1/p" + }, + { + "rule": "linksynergy\\.com/imp" + }, + { + "rule": "linksynergy\\.com/consent/v3/p" + }, + { + "rule": "linksynergy\\.com/phoenix/phoenix-2\\.26\\.min\\.js" + }, + { + "rule": "linksynergy\\.com/privacy/ad_choices\\.png" + }, + { + "rule": "linksynergy\\.com/fs-bin/show" + }, + { + "rule": "linksynergy\\.com/cc" + }, + { + "rule": "linksynergy\\.com/js/" + }, + { + "rule": "linksynergy\\.com/wakeup/" + }, + { + "rule": "linksynergy\\.com/advertisers/owllab9118/" + }, + { + "rule": "linksynergy\\.com/pix/[0-9]+" + }, + { + "rule": "linksynergy\\.com/[0-9]+\\.ct\\.js" + } + ] }, "list-manage.com": { "domain": "list-manage.com", @@ -16454,7 +16495,8 @@ "Embedded Content", "Social - Share" ], - "default": "ignore" + "default": "ignore", + "rules": [] }, "mailchimp.com": { "domain": "mailchimp.com", @@ -18041,7 +18083,20 @@ "fingerprinting": 0, "cookies": 0.00373, "categories": [], - "default": "block" + "default": "block", + "rules": [ + { + "rule": "hello\\.myfonts\\.net/count/", + "exceptions": { + "domains": [ + "condor.com" + ], + "types": [ + "stylesheet" + ] + } + } + ] }, "myregistry.com": { "domain": "myregistry.com", @@ -18105,7 +18160,30 @@ "fingerprinting": 2, "cookies": 0.00189, "categories": [], - "default": "block" + "default": "ignore", + "rules": [ + { + "rule": "nakanohito\\.jp/b3/bi\\.js" + }, + { + "rule": "nakanohito\\.jp/b3/" + }, + { + "rule": "nakanohito\\.jp/uhj2/uh\\.js" + }, + { + "rule": "nakanohito\\.jp/cm/inner\\.css" + }, + { + "rule": "nakanohito\\.jp/ua/uwa\\.js" + }, + { + "rule": "nakanohito\\.jp/ua/" + }, + { + "rule": "nakanohito\\.jp/chatbot_pc\\.css" + } + ] }, "nanorep.co": { "domain": "nanorep.co", @@ -18359,6 +18437,15 @@ ], "default": "block", "rules": [ + { + "rule": "js-agent\\.newrelic\\.com", + "exceptions": { + "domains": [ + "chaturbate.com", + "johnlewis.com" + ] + } + }, { "rule": "newrelic\\.com", "exceptions": { @@ -18712,11 +18799,7 @@ "rules": [ { "rule": "npttech\\.com/advertising\\.js", - "exceptions": { - "types": [ - "script" - ] - } + "surrogate": "noop.js" } ] }, @@ -18734,7 +18817,17 @@ "categories": [ "Analytics" ], - "default": "block" + "default": "block", + "rules": [ + { + "rule": "nr-data\\.net", + "exceptions": { + "domains": [ + "chaturbate.com" + ] + } + } + ] }, "nrich.ai": { "domain": "nrich.ai", @@ -20377,7 +20470,39 @@ "Audience Measurement", "Third-Party Analytics Marketing" ], - "default": "block" + "default": "ignore", + "rules": [ + { + "rule": "parsely\\.com/plogger/" + }, + { + "rule": "parsely\\.com/videoplugins/brightcove/videojs-parsely-loader-v1-latest\\.min\\.js" + }, + { + "rule": "parsely\\.com/videoplugins/brightcove/videojs-parsely-v1-latest\\.min\\.js" + }, + { + "rule": "parsely\\.com/v2/profile" + }, + { + "rule": "parsely\\.com/px/" + }, + { + "rule": "parsely\\.com/v2/related" + }, + { + "rule": "parsely\\.com/v2/analytics/posts" + }, + { + "rule": "parsely\\.com/v2/similar" + }, + { + "rule": "parsely\\.com/keys/adweek\\.com/p\\.js" + }, + { + "rule": "parsely\\.com/v2/search" + } + ] }, "partplanes.com": { "domain": "partplanes.com", @@ -20592,7 +20717,17 @@ "fingerprinting": 2, "cookies": 0.00574, "categories": [], - "default": "block" + "default": "block", + "rules": [ + { + "rule": "edge\\.permutive\\.app", + "exceptions": { + "domains": [ + "globaltv.com" + ] + } + } + ] }, "permutive.com": { "domain": "permutive.com", @@ -21133,11 +21268,6 @@ "categories": [], "default": "ignore", "rules": [ - { - "rule": "powr\\.io\\/powr\\.js", - "fingerprinting": 1, - "cookies": 0.00000681 - }, { "rule": "powr\\.io\\/popup\\/u\\/61af4f5f_1680291259", "fingerprinting": 1, @@ -21409,14 +21539,7 @@ "fingerprinting": 1, "cookies": 0.000197, "categories": [], - "default": "ignore", - "rules": [ - { - "rule": "providesupport\\.com\\/sjs\\/static\\.js", - "fingerprinting": 1, - "cookies": 0.000123 - } - ] + "default": "ignore" }, "pswec.com": { "domain": "pswec.com", @@ -23122,7 +23245,23 @@ "Ad Motivated Tracking", "Advertising" ], - "default": "block" + "default": "block", + "rules": [ + { + "rule": "micro\\.rubiconproject\\.com/prebid/dynamic/.*\\.js", + "exceptions": { + "domains": [ + "gamingbible.co.uk", + "gamingbible.com", + "ladbible.com", + "sportbible.com", + "tyla.com", + "unilad.co.uk", + "unilad.com" + ] + } + } + ] }, "ruralrobin.com": { "domain": "ruralrobin.com", @@ -25973,7 +26112,7 @@ "cookies": 0.0000136 }, { - "rule": "storage\\.googleapis\\.com/code\\.snapengage\\.com/", + "rule": "storage\\.googleapis\\.com/code\\.snapengage\\.com/js/", "fingerprinting": 3, "cookies": 0.0000136 }, @@ -27133,7 +27272,60 @@ "fingerprinting": 1, "cookies": 0.0436, "categories": [], - "default": "block" + "default": "ignore", + "rules": [ + { + "rule": "tiktok\\.com/i18n/pixel/events\\.js" + }, + { + "rule": "tiktok\\.com/i18n/pixel/static/identify_d1af3\\.js" + }, + { + "rule": "tiktok\\.com/api/v2/pixel" + }, + { + "rule": "tiktok\\.com/i18n/pixel/sdk\\.js" + }, + { + "rule": "tiktok\\.com/api/v2/performance_interaction" + }, + { + "rule": "tiktok\\.com/i18n/pixel/config\\.js" + }, + { + "rule": "tiktok\\.com/i18n/pixel/disable_cookie" + }, + { + "rule": "tiktok\\.com/i18n/pixel/static/identify_821f6\\.js" + }, + { + "rule": "tiktok\\.com/v1/user/webid" + }, + { + "rule": "tiktok\\.com/service/2/abtest_config/" + }, + { + "rule": "tiktok\\.com/web/resource" + }, + { + "rule": "tiktok\\.com/v1/list" + }, + { + "rule": "tiktok\\.com/web/report" + }, + { + "rule": "tiktok\\.com/oembed" + }, + { + "rule": "tiktok\\.com/i18n/pixel/enable_cookie" + }, + { + "rule": "tiktok\\.com/i18n/pixel/static/identify_a7248\\.js" + }, + { + "rule": "tiktok\\.com/i18n/pixel/static/main\\..*\\.js" + } + ] }, "tinypass.com": { "domain": "tinypass.com", @@ -29123,7 +29315,18 @@ "categories": [ "Advertising" ], - "default": "block" + "default": "block", + "rules": [ + { + "rule": "cdn\\.viglink\\.com/api/vglnk\\.js", + "exceptions": { + "domains": [ + "9to5mac.com", + "electrek.co" + ] + } + } + ] }, "visualwebsiteoptimizer.com": { "domain": "visualwebsiteoptimizer.com", @@ -29856,6 +30059,14 @@ "categories": [], "default": "ignore", "rules": [ + { + "rule": "universal\\.wgplayer\\.com/tag/", + "exceptions": { + "domains": [ + "yoho.games" + ] + } + }, { "rule": "wgplayer\\.com\\/tag\\/", "fingerprinting": 1, @@ -31264,21 +31475,6 @@ "categories": [], "default": "block" }, - "zopim.com": { - "domain": "zopim.com", - "owner": { - "name": "Zendesk, Inc.", - "displayName": "Zendesk", - "privacyPolicy": "https://www.zendesk.com/company/customers-partners/privacy-policy/" - }, - "prevalence": 0.0078, - "fingerprinting": 1, - "cookies": 0.00153, - "categories": [ - "Embedded Content" - ], - "default": "block" - }, "zprk.io": { "domain": "zprk.io", "owner": { @@ -42275,13 +42471,6 @@ "prevalence": 0.0926, "displayName": "iPerceptions" }, - "ipify.org": { - "domains": [ - "ipify.org" - ], - "prevalence": 0.0163, - "displayName": "ipify.org" - }, "Grupa Interia.pl Sp. z o.o. sp. k.": { "domains": [ "adretail.pl", @@ -51319,7 +51508,6 @@ "iocnt.net": "INFOnline GmbH", "iper2.com": "iPerceptions Inc.", "iperceptions.com": "iPerceptions Inc.", - "ipify.org": "ipify.org", "adretail.pl": "Grupa Interia.pl Sp. z o.o. sp. k.", "adsearch.pl": "Grupa Interia.pl Sp. z o.o. sp. k.", "bryk.pl": "Grupa Interia.pl Sp. z o.o. sp. k.", From 5addaa4427162ec8910c57712a874589a84be61b Mon Sep 17 00:00:00 2001 From: amddg44 Date: Thu, 16 Nov 2023 17:37:04 +0100 Subject: [PATCH 03/10] Autofill "Never Save for this Site" feature (#2104) Task/Issue URL: https://app.asana.com/0/0/1205783642285427/f Tech Design URL: https://app.asana.com/0/481882893211075/1205590957854802/f CC: Description: Adds the functionality to allow users to choose to "Never Save for this Site" from the autofill save login prompt, with the option to reset this list from the Logins screen. --- Core/PixelEvent.swift | 12 ++- Core/UserDefaultsPropertyWrapper.swift | 2 +- DuckDuckGo.xcodeproj/project.pbxproj | 14 ++- .../xcshareddata/swiftpm/Package.resolved | 8 +- DuckDuckGo/AppDependencyProvider.swift | 2 + DuckDuckGo/AppUserDefaults.swift | 2 +- DuckDuckGo/AutofillLoginListViewModel.swift | 20 ++++- DuckDuckGo/AutofillLoginPromptView.swift | 2 +- ...ofillLoginSettingsListViewController.swift | 43 +++++++++- .../AutofillNeverPromptWebsitesManager.swift | 84 ++++++++++++++++++ .../AutofillNeverSavedTableViewCell.swift | 78 +++++++++++++++++ DuckDuckGo/AutofillViews.swift | 15 +--- DuckDuckGo/EmailSignupViewController.swift | 4 + DuckDuckGo/PasswordGenerationPromptView.swift | 7 +- DuckDuckGo/SaveAutofillLoginManager.swift | 7 ++ DuckDuckGo/SaveLoginView.swift | 16 ++-- DuckDuckGo/SaveLoginViewController.swift | 6 ++ DuckDuckGo/SaveLoginViewModel.swift | 7 ++ DuckDuckGo/ScriptSourceProviding.swift | 6 +- DuckDuckGo/TabViewController.swift | 54 +++++++++++- DuckDuckGo/UserScripts.swift | 1 + DuckDuckGo/UserText.swift | 18 ++-- DuckDuckGo/bg.lproj/Localizable.strings | 29 ++++--- DuckDuckGo/cs.lproj/Localizable.strings | 29 ++++--- DuckDuckGo/da.lproj/Localizable.strings | 29 ++++--- DuckDuckGo/de.lproj/Localizable.strings | 29 ++++--- DuckDuckGo/el.lproj/Localizable.strings | 29 ++++--- DuckDuckGo/en.lproj/Localizable.strings | 29 ++++--- DuckDuckGo/es.lproj/Localizable.strings | 29 ++++--- DuckDuckGo/et.lproj/Localizable.strings | 29 ++++--- DuckDuckGo/fi.lproj/Localizable.strings | 29 ++++--- DuckDuckGo/fr.lproj/Localizable.strings | 29 ++++--- DuckDuckGo/hr.lproj/Localizable.strings | 29 ++++--- DuckDuckGo/hu.lproj/Localizable.strings | 29 ++++--- DuckDuckGo/it.lproj/Localizable.strings | 29 ++++--- DuckDuckGo/lt.lproj/Localizable.strings | 29 ++++--- DuckDuckGo/lv.lproj/Localizable.strings | 29 ++++--- DuckDuckGo/nb.lproj/Localizable.strings | 29 ++++--- DuckDuckGo/nl.lproj/Localizable.strings | 29 ++++--- DuckDuckGo/pl.lproj/Localizable.strings | 29 ++++--- DuckDuckGo/pt.lproj/Localizable.strings | 29 ++++--- DuckDuckGo/ro.lproj/Localizable.strings | 29 ++++--- DuckDuckGo/ru.lproj/Localizable.strings | 29 ++++--- DuckDuckGo/sk.lproj/Localizable.strings | 29 ++++--- DuckDuckGo/sl.lproj/Localizable.strings | 29 ++++--- DuckDuckGo/sv.lproj/Localizable.strings | 29 ++++--- DuckDuckGo/tr.lproj/Localizable.strings | 29 ++++--- .../AutofillLoginListViewModelTests.swift | 41 ++++++++- ...ofillNeverPromptWebsitesManagerTests.swift | 85 +++++++++++++++++++ DuckDuckGoTests/MockDependencyProvider.swift | 2 + DuckDuckGoTests/MockSecureVault.swift | 53 ++++++++++++ 51 files changed, 1010 insertions(+), 304 deletions(-) create mode 100644 DuckDuckGo/AutofillNeverPromptWebsitesManager.swift create mode 100644 DuckDuckGo/AutofillNeverSavedTableViewCell.swift create mode 100644 DuckDuckGoTests/AutofillNeverPromptWebsitesManagerTests.swift diff --git a/Core/PixelEvent.swift b/Core/PixelEvent.swift index f2186f5827..37e48dcb73 100644 --- a/Core/PixelEvent.swift +++ b/Core/PixelEvent.swift @@ -203,7 +203,8 @@ extension Pixel { case autofillLoginsSaveLoginModalDisplayed case autofillLoginsSaveLoginModalConfirmed case autofillLoginsSaveLoginModalDismissed - + case autofillLoginsSaveLoginModalExcludeSiteConfirmed + case autofillLoginsSavePasswordModalDisplayed case autofillLoginsSavePasswordModalConfirmed case autofillLoginsSavePasswordModalDismissed @@ -238,6 +239,9 @@ extension Pixel { case autofillLoginsSettingsEnabled case autofillLoginsSettingsDisabled case autofillLoginsSettingsAddNewLoginErrorAttemptedToCreateDuplicate + case autofillLoginsSettingsResetExcludedDisplayed + case autofillLoginsSettingsResetExcludedConfirmed + case autofillLoginsSettingsResetExcludedDismissed case autofillLoginsPasswordGenerationPromptDisplayed case autofillLoginsPasswordGenerationPromptConfirmed @@ -699,7 +703,8 @@ extension Pixel.Event { case .autofillLoginsSaveLoginModalDisplayed: return "m_autofill_logins_save_login_inline_displayed" case .autofillLoginsSaveLoginModalConfirmed: return "m_autofill_logins_save_login_inline_confirmed" case .autofillLoginsSaveLoginModalDismissed: return "m_autofill_logins_save_login_inline_dismissed" - + case .autofillLoginsSaveLoginModalExcludeSiteConfirmed: return "m_autofill_logins_save_login_exclude_site_confirmed" + case .autofillLoginsSavePasswordModalDisplayed: return "m_autofill_logins_save_password_inline_displayed" case .autofillLoginsSavePasswordModalConfirmed: return "m_autofill_logins_save_password_inline_confirmed" case .autofillLoginsSavePasswordModalDismissed: return "m_autofill_logins_save_password_inline_dismissed" @@ -741,6 +746,9 @@ extension Pixel.Event { case .autofillLoginsSettingsDisabled: return "m_autofill_logins_settings_disabled" case .autofillLoginsSettingsAddNewLoginErrorAttemptedToCreateDuplicate: return "m_autofill_logins_settings_add-new-login_error_attempted-to-create-duplicate" + case .autofillLoginsSettingsResetExcludedDisplayed: return "m_autofill_settings_reset_excluded_displayed" + case .autofillLoginsSettingsResetExcludedConfirmed: return "m_autofill_settings_reset_excluded_confirmed" + case .autofillLoginsSettingsResetExcludedDismissed: return "m_autofill_settings_reset_excluded_dismissed" case .autofillLoginsPasswordGenerationPromptDisplayed: return "m_autofill_logins_password_generation_prompt_displayed" case .autofillLoginsPasswordGenerationPromptConfirmed: return "m_autofill_logins_password_generation_prompt_confirmed" diff --git a/Core/UserDefaultsPropertyWrapper.swift b/Core/UserDefaultsPropertyWrapper.swift index 78a4507ba0..47c17546f9 100644 --- a/Core/UserDefaultsPropertyWrapper.swift +++ b/Core/UserDefaultsPropertyWrapper.swift @@ -81,7 +81,7 @@ public struct UserDefaultsWrapper { case autofillCredentialsSavePromptShowAtLeastOnce = "com.duckduckgo.ios.autofillCredentialsSavePromptShowAtLeastOnce" case autofillCredentialsHasBeenEnabledAutomaticallyIfNecessary = "com.duckduckgo.ios.autofillCredentialsHasBeenEnabledAutomaticallyIfNecessary" - + case featureFlaggingDidVerifyInternalUser = "com.duckduckgo.app.featureFlaggingDidVerifyInternalUser" case voiceSearchEnabled = "com.duckduckgo.app.voiceSearchEnabled" diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 1e1427e621..df675a8b52 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -715,9 +715,12 @@ C1B7B52D2894469D0098FD6A /* DefaultVariantManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1B7B52C2894469D0098FD6A /* DefaultVariantManager.swift */; }; C1B7B53028944E390098FD6A /* RemoteMessagingStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1B7B52F28944E390098FD6A /* RemoteMessagingStoreTests.swift */; }; C1B7B53428944EFA0098FD6A /* CoreDataTestUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1B7B53328944EFA0098FD6A /* CoreDataTestUtilities.swift */; }; + C1B924B72ACD6E6800EE7B06 /* AutofillNeverSavedTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1B924B62ACD6E6800EE7B06 /* AutofillNeverSavedTableViewCell.swift */; }; C1BF0BA529B63D7200482B73 /* AutofillLoginPromptHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1BF0BA429B63D7200482B73 /* AutofillLoginPromptHelper.swift */; }; C1BF0BA929B63E2200482B73 /* AutofillLoginPromptViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1BF0BA729B63E1A00482B73 /* AutofillLoginPromptViewModelTests.swift */; }; C1CCCBA7283E101500CF3791 /* FaviconsHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1CCCBA6283E101500CF3791 /* FaviconsHelper.swift */; }; + C1CDA3162AFB9C7F006D1476 /* AutofillNeverPromptWebsitesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1CDA3152AFB9C7F006D1476 /* AutofillNeverPromptWebsitesManager.swift */; }; + C1CDA31E2AFBF811006D1476 /* AutofillNeverPromptWebsitesManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1CDA31D2AFBF811006D1476 /* AutofillNeverPromptWebsitesManagerTests.swift */; }; C1D21E2D293A5965006E5A05 /* AutofillLoginSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1D21E2C293A5965006E5A05 /* AutofillLoginSession.swift */; }; C1D21E2F293A599C006E5A05 /* AutofillLoginSessionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1D21E2E293A599C006E5A05 /* AutofillLoginSessionTests.swift */; }; C1F341C52A6924000032057B /* EmailAddressPromptView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1F341C42A6924000032057B /* EmailAddressPromptView.swift */; }; @@ -2303,9 +2306,12 @@ C1B7B52C2894469D0098FD6A /* DefaultVariantManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultVariantManager.swift; sourceTree = ""; }; C1B7B52F28944E390098FD6A /* RemoteMessagingStoreTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RemoteMessagingStoreTests.swift; sourceTree = ""; }; C1B7B53328944EFA0098FD6A /* CoreDataTestUtilities.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataTestUtilities.swift; sourceTree = ""; }; + C1B924B62ACD6E6800EE7B06 /* AutofillNeverSavedTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutofillNeverSavedTableViewCell.swift; sourceTree = ""; }; C1BF0BA429B63D7200482B73 /* AutofillLoginPromptHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AutofillLoginPromptHelper.swift; sourceTree = ""; }; C1BF0BA729B63E1A00482B73 /* AutofillLoginPromptViewModelTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AutofillLoginPromptViewModelTests.swift; sourceTree = ""; }; C1CCCBA6283E101500CF3791 /* FaviconsHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FaviconsHelper.swift; sourceTree = ""; }; + C1CDA3152AFB9C7F006D1476 /* AutofillNeverPromptWebsitesManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AutofillNeverPromptWebsitesManager.swift; sourceTree = ""; }; + C1CDA31D2AFBF811006D1476 /* AutofillNeverPromptWebsitesManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutofillNeverPromptWebsitesManagerTests.swift; sourceTree = ""; }; C1D21E2C293A5965006E5A05 /* AutofillLoginSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutofillLoginSession.swift; sourceTree = ""; }; C1D21E2E293A599C006E5A05 /* AutofillLoginSessionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutofillLoginSessionTests.swift; sourceTree = ""; }; C1F341C42A6924000032057B /* EmailAddressPromptView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmailAddressPromptView.swift; sourceTree = ""; }; @@ -3308,6 +3314,7 @@ 311BD1AE2836BB4200AEF6C1 /* AutofillItemsLockedView.swift */, 2DC3FBD62FBAF21E87610FA8 /* AutofillNoAuthAvailableView.swift */, C18ED4392AB6F77600BF3805 /* AutofillSettingsEnableFooterView.swift */, + C1B924B62ACD6E6800EE7B06 /* AutofillNeverSavedTableViewCell.swift */, ); name = Table; sourceTree = ""; @@ -5260,6 +5267,7 @@ C1BF0BA629B63E0400482B73 /* AutofillLoginUI */, F40F843528C938370081AE75 /* AutofillLoginListViewModelTests.swift */, C1D21E2E293A599C006E5A05 /* AutofillLoginSessionTests.swift */, + C1CDA31D2AFBF811006D1476 /* AutofillNeverPromptWebsitesManagerTests.swift */, ); name = Autofill; sourceTree = ""; @@ -5270,6 +5278,7 @@ D63657182A7BAE7C001AF19D /* EmailManagerRequestDelegate.swift */, F4147353283BF834004AA7A5 /* AutofillContentScopeFeatureToggles.swift */, C1D21E2C293A5965006E5A05 /* AutofillLoginSession.swift */, + C1CDA3152AFB9C7F006D1476 /* AutofillNeverPromptWebsitesManager.swift */, C13B32D12A0E750700A59236 /* AutofillSettingStatus.swift */, 319A370F28299A850079FBCE /* PasswordHider.swift */, 31C70B5428045E3500FB6AD1 /* SecureVaultErrorReporter.swift */, @@ -6206,6 +6215,7 @@ F1668BCE1E798081008CBA04 /* BookmarksViewController.swift in Sources */, 1E162610296C5C630004127F /* CustomDaxDialogViewModel.swift in Sources */, 8590CB69268A4E190089F6BF /* DebugEtagStorage.swift in Sources */, + C1CDA3162AFB9C7F006D1476 /* AutofillNeverPromptWebsitesManager.swift in Sources */, F1CA3C371F045878005FADB3 /* PrivacyStore.swift in Sources */, 37FCAAC029930E26000E420A /* FailedAssertionView.swift in Sources */, F4E1936625AF722F001D2666 /* HighlightCutOutView.swift in Sources */, @@ -6253,6 +6263,7 @@ CB9B873C278C8FEA001F4906 /* WidgetEducationView.swift in Sources */, 85F200002215C17B006BB258 /* FindInPage.swift in Sources */, F1386BA41E6846C40062FC3C /* TabDelegate.swift in Sources */, + C1B924B72ACD6E6800EE7B06 /* AutofillNeverSavedTableViewCell.swift in Sources */, 020108A929A7C1CD00644F9D /* AppTrackerImageCache.swift in Sources */, 3132FA2A27A0788F00DD7A12 /* QuickLookPreviewHelper.swift in Sources */, C1D21E2D293A5965006E5A05 /* AutofillLoginSession.swift in Sources */, @@ -6641,6 +6652,7 @@ C1D21E2F293A599C006E5A05 /* AutofillLoginSessionTests.swift in Sources */, 85D2187924BF6B8B004373D2 /* FaviconSourcesProviderTests.swift in Sources */, 1E8146AD28C8ABF000D1AF63 /* TrackerAnimationLogicTests.swift in Sources */, + C1CDA31E2AFBF811006D1476 /* AutofillNeverPromptWebsitesManagerTests.swift in Sources */, B6AD9E3A28D456820019CDE9 /* PrivacyConfigurationManagerMock.swift in Sources */, F189AED71F18F6DE001EBAE1 /* TabTests.swift in Sources */, F13B4BFB1F18E3D900814661 /* TabsModelPersistenceExtensionTests.swift in Sources */, @@ -9131,7 +9143,7 @@ repositoryURL = "https://github.com/DuckDuckGo/BrowserServicesKit"; requirement = { kind = exactVersion; - version = 84.0.1; + version = 84.1.0; }; }; C14882EB27F211A000D59F0C /* XCRemoteSwiftPackageReference "SwiftSoup" */ = { diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index f1c1475dc4..5c2f7dbb33 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -15,8 +15,8 @@ "repositoryURL": "https://github.com/DuckDuckGo/BrowserServicesKit", "state": { "branch": null, - "revision": "075773533bfca9196115674d2ab1b085570854dd", - "version": "84.0.1" + "revision": "641018cef1a3a13e9fdeb490b18639d1cb25569f", + "version": "84.1.0" } }, { @@ -51,8 +51,8 @@ "repositoryURL": "https://github.com/duckduckgo/duckduckgo-autofill.git", "state": { "branch": null, - "revision": "c8e895c8fd50dc76e8d8dc827a636ad77b7f46ff", - "version": "9.0.0" + "revision": "93677cc02cfe650ce7f417246afd0e8e972cd83e", + "version": "10.0.0" } }, { diff --git a/DuckDuckGo/AppDependencyProvider.swift b/DuckDuckGo/AppDependencyProvider.swift index 3b42c75074..5f7854281c 100644 --- a/DuckDuckGo/AppDependencyProvider.swift +++ b/DuckDuckGo/AppDependencyProvider.swift @@ -34,6 +34,7 @@ protocol DependencyProvider { var voiceSearchHelper: VoiceSearchHelperProtocol { get } var downloadManager: DownloadManager { get } var autofillLoginSession: AutofillLoginSession { get } + var autofillNeverPromptWebsitesManager: AutofillNeverPromptWebsitesManager { get } var configurationManager: ConfigurationManager { get } } @@ -56,6 +57,7 @@ class AppDependencyProvider: DependencyProvider { let voiceSearchHelper: VoiceSearchHelperProtocol = VoiceSearchHelper() let downloadManager = DownloadManager() let autofillLoginSession = AutofillLoginSession() + lazy var autofillNeverPromptWebsitesManager = AutofillNeverPromptWebsitesManager() let configurationManager = ConfigurationManager() } diff --git a/DuckDuckGo/AppUserDefaults.swift b/DuckDuckGo/AppUserDefaults.swift index f06c8d7180..552e381a02 100644 --- a/DuckDuckGo/AppUserDefaults.swift +++ b/DuckDuckGo/AppUserDefaults.swift @@ -252,7 +252,7 @@ public class AppUserDefaults: AppSettings { userDefaults?.set(newValue, forKey: Keys.autofillCredentialsEnabled) } } - + @UserDefaultsWrapper(key: .autofillCredentialsSavePromptShowAtLeastOnce, defaultValue: false) var autofillCredentialsSavePromptShowAtLeastOnce: Bool diff --git a/DuckDuckGo/AutofillLoginListViewModel.swift b/DuckDuckGo/AutofillLoginListViewModel.swift index ae9642b488..2295c54873 100644 --- a/DuckDuckGo/AutofillLoginListViewModel.swift +++ b/DuckDuckGo/AutofillLoginListViewModel.swift @@ -45,6 +45,11 @@ internal enum AutofillLoginListSectionType: Comparable { static let miscSectionHeading = "#" } +internal enum EnableAutofillRows: Int, CaseIterable { + case toggleAutofill + case resetNeverPromptWebsites +} + final class AutofillLoginListViewModel: ObservableObject { enum ViewState { @@ -66,10 +71,12 @@ final class AutofillLoginListViewModel: ObservableObject { private let tld: TLD private var currentTabUrl: URL? private let secureVault: (any AutofillSecureVault)? + private let autofillNeverPromptWebsitesManager: AutofillNeverPromptWebsitesManager private var cachedDeletedCredentials: SecureVaultModels.WebsiteCredentials? private let autofillDomainNameUrlMatcher = AutofillDomainNameUrlMatcher() private let autofillDomainNameUrlSort = AutofillDomainNameUrlSort() + @Published private (set) var viewState: AutofillLoginListViewModel.ViewState = .authLocked @Published private(set) var sections = [AutofillLoginListSectionType]() { didSet { @@ -89,11 +96,13 @@ final class AutofillLoginListViewModel: ObservableObject { } } - init(appSettings: AppSettings, tld: TLD, secureVault: (any AutofillSecureVault)?, currentTabUrl: URL? = nil) { + init(appSettings: AppSettings, tld: TLD, secureVault: (any AutofillSecureVault)?, currentTabUrl: URL? = nil, autofillNeverPromptWebsitesManager: AutofillNeverPromptWebsitesManager = AppDependencyProvider.shared.autofillNeverPromptWebsitesManager) { self.appSettings = appSettings self.tld = tld self.secureVault = secureVault self.currentTabUrl = currentTabUrl + self.autofillNeverPromptWebsitesManager = autofillNeverPromptWebsitesManager + updateData() authenticationNotRequired = !hasAccountsSaved || AppDependencyProvider.shared.autofillLoginSession.isValidSession setupCancellables() @@ -153,7 +162,7 @@ final class AutofillLoginListViewModel: ObservableObject { func rowsInSection(_ section: Int) -> Int { switch self.sections[section] { case .enableAutofill: - return 1 + return autofillNeverPromptWebsitesManager.neverPromptWebsites.isEmpty ? 1 : 2 case .credentials(_, let items): return items.count } @@ -180,8 +189,11 @@ final class AutofillLoginListViewModel: ObservableObject { } self.sections = makeSections(with: filteredAccounts) } - - + + func resetNeverPromptWebsites() { + _ = autofillNeverPromptWebsitesManager.deleteAllNeverPromptWebsites() + } + // MARK: Private Methods private func fetchAccounts() -> [SecureVaultModels.WebsiteAccount] { diff --git a/DuckDuckGo/AutofillLoginPromptView.swift b/DuckDuckGo/AutofillLoginPromptView.swift index 0a75d988ee..4570c243f8 100644 --- a/DuckDuckGo/AutofillLoginPromptView.swift +++ b/DuckDuckGo/AutofillLoginPromptView.swift @@ -44,7 +44,7 @@ struct AutofillLoginPromptView: View { VStack { Spacer() .frame(height: Const.Size.topPadding) - AutofillViews.WebsiteWithFavicon(accountDomain: viewModel.domain) + AutofillViews.AppIconHeader() Spacer() .frame(height: Const.Size.headlineTopPadding) AutofillViews.Headline(title: viewModel.message) diff --git a/DuckDuckGo/AutofillLoginSettingsListViewController.swift b/DuckDuckGo/AutofillLoginSettingsListViewController.swift index 2055e7b03f..89fa680bc1 100644 --- a/DuckDuckGo/AutofillLoginSettingsListViewController.swift +++ b/DuckDuckGo/AutofillLoginSettingsListViewController.swift @@ -77,6 +77,7 @@ final class AutofillLoginSettingsListViewController: UIViewController { tableView.estimatedSectionFooterHeight = 40 tableView.registerCell(ofType: AutofillListItemTableViewCell.self) tableView.registerCell(ofType: EnableAutofillSettingsTableViewCell.self) + tableView.registerCell(ofType: AutofillNeverSavedTableViewCell.self) // Have to set tableHeaderView height otherwise tableView content will jump when adding / removing searchController due to tableView insetGrouped style tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 24)) return tableView @@ -217,7 +218,23 @@ final class AutofillLoginSettingsListViewController: UIViewController { navigationController?.pushViewController(detailsController, animated: animated) detailsViewController = detailsController } - + + private func presentNeverPromptResetPromptAtIndexPath(_ indexPath: IndexPath) { + let controller = UIAlertController(title: "", + message: UserText.autofillResetNeverSavedActionTitle, + preferredStyle: .actionSheet) + controller.addAction(UIAlertAction(title: UserText.autofillResetNeverSavedActionConfirmButton, style: .destructive) { [weak self] _ in + self?.viewModel.resetNeverPromptWebsites() + self?.tableView.reloadData() + Pixel.fire(pixel: .autofillLoginsSettingsResetExcludedConfirmed) + }) + controller.addAction(UIAlertAction(title: UserText.autofillResetNeverSavedActionCancelButton, style: .cancel) { _ in + Pixel.fire(pixel: .autofillLoginsSettingsResetExcludedDismissed) + }) + present(controller: controller, fromView: tableView.cellForRow(at: indexPath) ?? tableView) + Pixel.fire(pixel: .autofillLoginsSettingsResetExcludedDisplayed) + } + private func setupCancellables() { viewModel.$viewState .receive(on: DispatchQueue.main) @@ -470,6 +487,12 @@ final class AutofillLoginSettingsListViewController: UIViewController { cell.theme = ThemeManager.shared.currentTheme return cell } + + private func neverSavedCell(for tableView: UITableView, indexPath: IndexPath) -> AutofillNeverSavedTableViewCell { + let cell = tableView.dequeueCell(ofType: AutofillNeverSavedTableViewCell.self, for: indexPath) + cell.theme = ThemeManager.shared.currentTheme + return cell + } } // MARK: UITableViewDelegate @@ -489,11 +512,16 @@ extension AutofillLoginSettingsListViewController: UITableViewDelegate { tableView.deselectRow(at: indexPath, animated: true) switch viewModel.sections[indexPath.section] { + case .enableAutofill: + switch EnableAutofillRows(rawValue: indexPath.row) { + case .resetNeverPromptWebsites: + presentNeverPromptResetPromptAtIndexPath(indexPath) + default: + break + } case .credentials(_, let items): let item = items[indexPath.row] showAccountDetails(item.account) - default: - break } } @@ -541,7 +569,14 @@ extension AutofillLoginSettingsListViewController: UITableViewDataSource { func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { switch viewModel.sections[indexPath.section] { case .enableAutofill: - return enableAutofillCell(for: tableView, indexPath: indexPath) + switch EnableAutofillRows(rawValue: indexPath.row) { + case .toggleAutofill: + return enableAutofillCell(for: tableView, indexPath: indexPath) + case .resetNeverPromptWebsites: + return neverSavedCell(for: tableView, indexPath: indexPath) + default: + fatalError("No cell for row at index \(indexPath.row)") + } case .credentials(_, let items): return credentialCell(for: tableView, item: items[indexPath.row], indexPath: indexPath) } diff --git a/DuckDuckGo/AutofillNeverPromptWebsitesManager.swift b/DuckDuckGo/AutofillNeverPromptWebsitesManager.swift new file mode 100644 index 0000000000..1671e0b5fb --- /dev/null +++ b/DuckDuckGo/AutofillNeverPromptWebsitesManager.swift @@ -0,0 +1,84 @@ +// +// AutofillNeverPromptWebsitesManager.swift +// DuckDuckGo +// +// Copyright © 2023 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 Foundation +import BrowserServicesKit +import Core + +class AutofillNeverPromptWebsitesManager { + + public private(set) var neverPromptWebsites: [SecureVaultModels.NeverPromptWebsites] = [] + + private let secureVault: (any AutofillSecureVault)? + + public init(secureVault: (any AutofillSecureVault)? = try? AutofillSecureVaultFactory.makeVault(errorReporter: SecureVaultErrorReporter.shared)) { + self.secureVault = secureVault + + fetchNeverPromptWebsites() + } + + public func hasNeverPromptWebsitesFor(domain: String) -> Bool { + return neverPromptWebsites.contains { $0.domain == domain } + } + + public func saveNeverPromptWebsite(_ domain: String) throws -> Int64? { + guard let secureVault = secureVault else { + return nil + } + + do { + let id = try secureVault.storeNeverPromptWebsites(SecureVaultModels.NeverPromptWebsites(domain: domain)) + + fetchNeverPromptWebsites() + return id + } catch { + Pixel.fire(pixel: .secureVaultError, error: error) + throw error + } + } + + public func deleteAllNeverPromptWebsites() -> Bool { + guard let secureVault = secureVault else { + return false + } + + do { + try secureVault.deleteAllNeverPromptWebsites() + + fetchNeverPromptWebsites() + return true + } catch { + Pixel.fire(pixel: .secureVaultError, error: error) + return false + } + } + + private func fetchNeverPromptWebsites() { + guard let secureVault = secureVault else { + return + } + + do { + neverPromptWebsites = try secureVault.neverPromptWebsites() + } catch { + Pixel.fire(pixel: .secureVaultError, error: error) + neverPromptWebsites = [] + } + } +} diff --git a/DuckDuckGo/AutofillNeverSavedTableViewCell.swift b/DuckDuckGo/AutofillNeverSavedTableViewCell.swift new file mode 100644 index 0000000000..adfc4c5e53 --- /dev/null +++ b/DuckDuckGo/AutofillNeverSavedTableViewCell.swift @@ -0,0 +1,78 @@ +// +// AutofillNeverSavedTableViewCell.swift +// DuckDuckGo +// +// Copyright © 2023 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 UIKit +import DesignResourcesKit + +class AutofillNeverSavedTableViewCell: UITableViewCell { + + var theme: Theme? { + didSet { + updateTheme() + } + } + + private lazy var titleLabel: UILabel = { + let label = UILabel(frame: CGRect.zero) + label.font = .preferredFont(forTextStyle: .callout) + label.text = UserText.autofillNeverSavedSettings + label.numberOfLines = 0 + label.lineBreakMode = .byWordWrapping + return label + }() + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + setupSubviews() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setupSubviews() { + installSubviews() + installConstraints() + } + + private func installSubviews() { + contentView.addSubview(titleLabel) + } + + private func installConstraints() { + titleLabel.translatesAutoresizingMaskIntoConstraints = false + let margins = contentView.layoutMarginsGuide + + NSLayoutConstraint.activate([ + titleLabel.topAnchor.constraint(equalTo: margins.topAnchor), + titleLabel.bottomAnchor.constraint(equalTo: margins.bottomAnchor), + titleLabel.leadingAnchor.constraint(equalTo: margins.leadingAnchor), + titleLabel.trailingAnchor.constraint(equalTo: margins.trailingAnchor) + ]) + } + + private func updateTheme() { + guard let theme = theme else { + return + } + + titleLabel.textColor = theme.autofillDefaultTitleTextColor + contentView.backgroundColor = UIColor(designSystemColor: .surface) + } +} diff --git a/DuckDuckGo/AutofillViews.swift b/DuckDuckGo/AutofillViews.swift index 8dab1a504d..aae551c98f 100644 --- a/DuckDuckGo/AutofillViews.swift +++ b/DuckDuckGo/AutofillViews.swift @@ -55,18 +55,10 @@ struct AutofillViews { } } - struct WebsiteWithFavicon: View { - let accountDomain: String - + struct AppIconHeader: View { var body: some View { - HStack { - FaviconView(viewModel: FaviconViewModel(domain: accountDomain)) - .scaledToFit() - .frame(width: Const.Size.logoImage, height: Const.Size.logoImage) - Text(accountDomain) - .daxFootnoteRegular() - .foregroundColor(Color(designSystemColor: .textSecondary)) - } + Image.appIcon + .scaledToFit() } } @@ -241,4 +233,5 @@ private enum Const { private extension Image { static let close = Image("Close-24") + static let appIcon = Image("WaitlistShareSheetLogo") } diff --git a/DuckDuckGo/EmailSignupViewController.swift b/DuckDuckGo/EmailSignupViewController.swift index 2bcfe0f28e..abcce2eb84 100644 --- a/DuckDuckGo/EmailSignupViewController.swift +++ b/DuckDuckGo/EmailSignupViewController.swift @@ -421,6 +421,10 @@ extension EmailSignupViewController: SecureVaultManagerDelegate { // no-op } + func secureVaultManager(_: SecureVaultManager, didRequestRuntimeConfigurationForDomain domain: String, completionHandler: @escaping (String?) -> Void) { + completionHandler(nil) + } + func secureVaultManager(_: SecureVaultManager, didReceivePixel pixel: AutofillUserScript.JSPixel) { guard !pixel.isEmailPixel else { // The iOS app uses a native email autofill UI, and sends its pixels separately. Ignore pixels sent from the JS layer. diff --git a/DuckDuckGo/PasswordGenerationPromptView.swift b/DuckDuckGo/PasswordGenerationPromptView.swift index 1ed7fcdc0f..470084db8f 100644 --- a/DuckDuckGo/PasswordGenerationPromptView.swift +++ b/DuckDuckGo/PasswordGenerationPromptView.swift @@ -42,8 +42,12 @@ struct PasswordGenerationPromptView: View { .zIndex(1) VStack { + Spacer() + .frame(height: Const.Size.topPadding) + AutofillViews.AppIconHeader() + Spacer() + .frame(height: Const.Size.headlineTopPadding) AutofillViews.Headline(title: UserText.autofillPasswordGenerationPromptTitle) - .padding(.top, Const.Size.topPadding) if #available(iOS 16.0, *) { passwordView .padding([.top, .bottom], passwordVerticalPadding) @@ -185,6 +189,7 @@ private enum Const { static let closeButtonOffsetPortrait: CGFloat = 44.0 static let closeButtonOffsetPortraitSmallFrame: CGFloat = 16.0 static let topPadding: CGFloat = 56.0 + static let headlineTopPadding: CGFloat = 24.0 static let ios15scrollOffset: CGFloat = 80.0 static let passwordButtonSpacing: CGFloat = 10.0 static let passwordPaddingHeight: CGFloat = 28.0 diff --git a/DuckDuckGo/SaveAutofillLoginManager.swift b/DuckDuckGo/SaveAutofillLoginManager.swift index 139e12c12d..725b2f823d 100644 --- a/DuckDuckGo/SaveAutofillLoginManager.swift +++ b/DuckDuckGo/SaveAutofillLoginManager.swift @@ -94,6 +94,13 @@ final class SaveAutofillLoginManager: SaveAutofillLoginManagerProtocol { } } + func isNeverPromptWebsiteForDomain() -> Bool { + guard let domain = credentials.account.domain else { + return false + } + return AppDependencyProvider.shared.autofillNeverPromptWebsitesManager.hasNeverPromptWebsitesFor(domain: domain) + } + private var savedMatchingPasswordWithoutUsername: SecureVaultModels.WebsiteCredentials? { let credentialsWithSamePassword = domainStoredCredentials.filter { storedCredentials in storedCredentials.password == credentials.password && (storedCredentials.account.username?.count ?? 0) == 0 diff --git a/DuckDuckGo/SaveLoginView.swift b/DuckDuckGo/SaveLoginView.swift index 4e80ca014a..f2dc2cb311 100644 --- a/DuckDuckGo/SaveLoginView.swift +++ b/DuckDuckGo/SaveLoginView.swift @@ -46,10 +46,8 @@ struct SaveLoginView: View { private var title: String { switch layoutType { - case .newUser, .saveLogin: + case .newUser, .saveLogin, .savePassword: return UserText.autofillSaveLoginTitleNewUser - case .savePassword: - return UserText.autofillSavePasswordTitle case .updateUsername: return UserText.autofillUpdateUsernameTitle case .updatePassword: @@ -59,9 +57,7 @@ struct SaveLoginView: View { private var confirmButton: String { switch layoutType { - case .newUser, .saveLogin: - return UserText.autofillSaveLoginSaveCTA - case .savePassword: + case .newUser, .saveLogin, .savePassword: return UserText.autofillSavePasswordSaveCTA case .updateUsername: return UserText.autofillUpdateUsernameSaveCTA @@ -90,7 +86,7 @@ struct SaveLoginView: View { VStack { Spacer() .frame(height: Const.Size.topPadding) - AutofillViews.WebsiteWithFavicon(accountDomain: viewModel.accountDomain) + AutofillViews.AppIconHeader() Spacer() .frame(height: Const.Size.headlineTopPadding) AutofillViews.Headline(title: title) @@ -141,8 +137,8 @@ struct SaveLoginView: View { AutofillViews.PrimaryButton(title: confirmButton, action: viewModel.save) - AutofillViews.TertiaryButton(title: UserText.autofillSaveLoginNotNowCTA, - action: viewModel.cancelButtonPressed) + AutofillViews.TertiaryButton(title: UserText.autofillSaveLoginNeverPromptCTA, + action: viewModel.neverPrompt) } } @@ -218,7 +214,7 @@ private enum Const { struct SaveLoginView_Previews: PreviewProvider { private struct MockManager: SaveAutofillLoginManagerProtocol { - + var username: String { "dax@duck.com" } var visiblePassword: String { "supersecurepasswordquack" } var isNewAccount: Bool { false } diff --git a/DuckDuckGo/SaveLoginViewController.swift b/DuckDuckGo/SaveLoginViewController.swift index 82d0afec9e..056546bed6 100644 --- a/DuckDuckGo/SaveLoginViewController.swift +++ b/DuckDuckGo/SaveLoginViewController.swift @@ -26,6 +26,7 @@ protocol SaveLoginViewControllerDelegate: AnyObject { func saveLoginViewController(_ viewController: SaveLoginViewController, didSaveCredentials credentials: SecureVaultModels.WebsiteCredentials) func saveLoginViewController(_ viewController: SaveLoginViewController, didUpdateCredentials credentials: SecureVaultModels.WebsiteCredentials) func saveLoginViewControllerDidCancel(_ viewController: SaveLoginViewController) + func saveLoginViewController(_ viewController: SaveLoginViewController, didRequestNeverPromptForWebsite domain: String) func saveLoginViewController(_ viewController: SaveLoginViewController, didRequestPresentConfirmKeepUsingAlertController alertController: UIAlertController) } @@ -136,6 +137,11 @@ extension SaveLoginViewController: SaveLoginViewModelDelegate { delegate?.saveLoginViewControllerDidCancel(self) } + func saveLoginViewModelNeverPrompt(_ viewModel: SaveLoginViewModel) { + Pixel.fire(pixel: .autofillLoginsSaveLoginModalExcludeSiteConfirmed) + delegate?.saveLoginViewController(self, didRequestNeverPromptForWebsite: viewModel.accountDomain) + } + func saveLoginViewModelConfirmKeepUsing(_ viewModel: SaveLoginViewModel, isAlreadyDismissed: Bool) { let isSelfPresentingAlert = !isAlreadyDismissed diff --git a/DuckDuckGo/SaveLoginViewModel.swift b/DuckDuckGo/SaveLoginViewModel.swift index 074b3b76d4..1586627994 100644 --- a/DuckDuckGo/SaveLoginViewModel.swift +++ b/DuckDuckGo/SaveLoginViewModel.swift @@ -24,6 +24,7 @@ import Core protocol SaveLoginViewModelDelegate: AnyObject { func saveLoginViewModelDidSave(_ viewModel: SaveLoginViewModel) func saveLoginViewModelDidCancel(_ viewModel: SaveLoginViewModel) + func saveLoginViewModelNeverPrompt(_ viewModel: SaveLoginViewModel) func saveLoginViewModelConfirmKeepUsing(_ viewModel: SaveLoginViewModel, isAlreadyDismissed: Bool) func saveLoginViewModelDidResizeContent(_ viewModel: SaveLoginViewModel, contentHeight: CGFloat) } @@ -180,4 +181,10 @@ final class SaveLoginViewModel: ObservableObject { autofillFirstTimeUser = false delegate?.saveLoginViewModelDidSave(self) } + + func neverPrompt() { + didSave = true + autofillFirstTimeUser = false + delegate?.saveLoginViewModelNeverPrompt(self) + } } diff --git a/DuckDuckGo/ScriptSourceProviding.swift b/DuckDuckGo/ScriptSourceProviding.swift index 5ac97820af..615dfc71a2 100644 --- a/DuckDuckGo/ScriptSourceProviding.swift +++ b/DuckDuckGo/ScriptSourceProviding.swift @@ -74,8 +74,10 @@ struct DefaultScriptSourceProvider: ScriptSourceProviding { private static func makeAutofillSource(privacyConfigurationManager: PrivacyConfigurationManaging, properties: ContentScopeProperties) -> AutofillUserScriptSourceProvider { - DefaultAutofillSourceProvider(privacyConfigurationManager: privacyConfigurationManager, - properties: properties) + return DefaultAutofillSourceProvider.Builder(privacyConfigurationManager: privacyConfigurationManager, + properties: properties) + .withJSLoading() + .build() } private static func buildContentBlockerRulesConfig(contentBlockingManager: ContentBlockerRulesManagerProtocol, diff --git a/DuckDuckGo/TabViewController.swift b/DuckDuckGo/TabViewController.swift index 2220dbebe6..e54ad09196 100644 --- a/DuckDuckGo/TabViewController.swift +++ b/DuckDuckGo/TabViewController.swift @@ -90,6 +90,7 @@ class TabViewController: UIViewController { lazy var featureFlagger = AppDependencyProvider.shared.featureFlagger private lazy var internalUserDecider = AppDependencyProvider.shared.internalUserDecider + private lazy var autofillNeverPromptWebsitesManager = AppDependencyProvider.shared.autofillNeverPromptWebsitesManager private lazy var autofillWebsiteAccountMatcher = AutofillWebsiteAccountMatcher(autofillUrlMatcher: AutofillDomainNameUrlMatcher(), tld: TabViewController.tld) private(set) var tabModel: Tab @@ -122,6 +123,8 @@ class TabViewController: UIViewController { private var saveLoginPromptLastDismissed: Date? private var saveLoginPromptIsPresenting: Bool = false + private var cachedRuntimeConfigurationForDomain: [String: String?] = [:] + // If no trackers dax dialog was shown recently in this tab, ie without the user navigating somewhere else, e.g. backgrounding or tab switcher private var woShownRecently = false @@ -616,6 +619,7 @@ class TabViewController: UIViewController { public func reload() { updateContentMode() + cachedRuntimeConfigurationForDomain = [:] webView.reload() privacyDashboard?.dismiss(animated: true) } @@ -2301,7 +2305,7 @@ extension TabViewController: SecureVaultManagerDelegate { func secureVaultInitFailed(_ error: SecureStorageError) { SecureVaultErrorReporter.shared.secureVaultInitFailed(error) } - + func secureVaultManagerIsEnabledStatus(_ manager: SecureVaultManager, forType type: AutofillType?) -> Bool { let isEnabled = AutofillSettingStatus.isAutofillEnabledInSettings && featureFlagger.isFeatureOn(.autofillCredentialInjecting) && @@ -2314,8 +2318,8 @@ extension TabViewController: SecureVaultManagerDelegate { return isEnabled } - func secureVaultManagerShouldSaveData(_: SecureVaultManager) -> Bool { - true + func secureVaultManagerShouldSaveData(_ manager: SecureVaultManager) -> Bool { + return secureVaultManagerIsEnabledStatus(manager, forType: nil) } func secureVaultManager(_ vault: SecureVaultManager, @@ -2454,6 +2458,38 @@ extension TabViewController: SecureVaultManagerDelegate { func secureVaultManager(_: BrowserServicesKit.SecureVaultManager, didRequestPasswordManagerForDomain domain: String) { } + func secureVaultManager(_: SecureVaultManager, didRequestRuntimeConfigurationForDomain domain: String, completionHandler: @escaping (String?) -> Void) { + // didRequestRuntimeConfigurationForDomain fires for every iframe loaded on a website + // so caching the runtime configuration for the domain to prevent unnecessary re-building of the configuration + if let runtimeConfigurationForDomain = cachedRuntimeConfigurationForDomain[domain] as? String { + completionHandler(runtimeConfigurationForDomain) + return + } + + let runtimeConfiguration = + DefaultAutofillSourceProvider.Builder(privacyConfigurationManager: ContentBlocking.shared.privacyConfigurationManager, + properties: buildContentScopePropertiesForDomain(domain)) + .build() + .buildRuntimeConfigResponse() + + cachedRuntimeConfigurationForDomain = [domain: runtimeConfiguration] + completionHandler(runtimeConfiguration) + } + + private func buildContentScopePropertiesForDomain(_ domain: String) -> ContentScopeProperties { + var supportedFeatures = ContentScopeFeatureToggles.supportedFeaturesOniOS + + if AutofillSettingStatus.isAutofillEnabledInSettings, + featureFlagger.isFeatureOn(.autofillCredentialsSaving), + autofillNeverPromptWebsitesManager.hasNeverPromptWebsitesFor(domain: domain) { + supportedFeatures.passwordGeneration = false + } + + return ContentScopeProperties(gpcEnabled: appSettings.sendDoNotSell, + sessionKey: autofillUserScript?.sessionKey ?? "", + featureToggles: supportedFeatures) + } + func secureVaultManager(_: SecureVaultManager, didReceivePixel pixel: AutofillUserScript.JSPixel) { guard !pixel.isEmailPixel else { // The iOS app uses a native email autofill UI, and sends its pixels separately. Ignore pixels sent from the JS layer. @@ -2518,6 +2554,18 @@ extension TabViewController: SaveLoginViewControllerDelegate { saveLoginPromptLastDismissed = Date() saveLoginPromptIsPresenting = false } + + func saveLoginViewController(_ viewController: SaveLoginViewController, didRequestNeverPromptForWebsite domain: String) { + viewController.dismiss(animated: true) + saveLoginPromptLastDismissed = Date() + saveLoginPromptIsPresenting = false + + do { + _ = try autofillNeverPromptWebsitesManager.saveNeverPromptWebsite(domain) + } catch { + os_log("%: failed to save never prompt for website %s", type: .error, #function, error.localizedDescription) + } + } func saveLoginViewController(_ viewController: SaveLoginViewController, didRequestPresentConfirmKeepUsingAlertController alertController: UIAlertController) { diff --git a/DuckDuckGo/UserScripts.swift b/DuckDuckGo/UserScripts.swift index 9f8b7cafeb..06cd05c46e 100644 --- a/DuckDuckGo/UserScripts.swift +++ b/DuckDuckGo/UserScripts.swift @@ -45,6 +45,7 @@ final class UserScripts: UserScriptsProvider { contentBlockerUserScript = ContentBlockerRulesUserScript(configuration: sourceProvider.contentBlockerRulesConfig) surrogatesScript = SurrogatesUserScript(configuration: sourceProvider.surrogatesConfig) autofillUserScript = AutofillUserScript(scriptSourceProvider: sourceProvider.autofillSourceProvider) + autofillUserScript.sessionKey = sourceProvider.contentScopeProperties.sessionKey loginFormDetectionScript = sourceProvider.loginDetectionEnabled ? LoginFormDetectionUserScript() : nil contentScopeUserScript = ContentScopeUserScript(sourceProvider.privacyConfigurationManager, diff --git a/DuckDuckGo/UserText.swift b/DuckDuckGo/UserText.swift index 3f89922b72..08452d8e89 100644 --- a/DuckDuckGo/UserText.swift +++ b/DuckDuckGo/UserText.swift @@ -401,21 +401,20 @@ public struct UserText { public static let emptyDownloads = NSLocalizedString("downloads.downloads-list.empty", value: "No files downloaded yet", comment: "Empty downloads list placholder") - public static let autofillSaveLoginTitleNewUser = NSLocalizedString("autofill.save-login.new-user.title", value: "Do you want DuckDuckGo to save your Login?", comment: "Title displayed on modal asking for the user to save the login for the first time") + public static let autofillSaveLoginTitleNewUser = NSLocalizedString("autofill.save-login.new-user.title", value: "Do you want DuckDuckGo to save your password?", comment: "Title displayed on modal asking for the user to save the login for the first time") public static let autofillSaveLoginTitle = NSLocalizedString("autofill.save-login.title", value: "Save Login?", comment: "Title displayed on modal asking for the user to save the login") public static let autofillUpdateUsernameTitle = NSLocalizedString("autofill.update-usernamr.title", value: "Update username?", comment: "Title displayed on modal asking for the user to update the username") - public static let autofillSaveLoginMessageNewUser = NSLocalizedString("autofill.save-login.new-user.message", value: "Logins are stored securely on your device in the Logins menu.", comment: "Message displayed on modal asking for the user to save the login for the first time") + public static let autofillSaveLoginMessageNewUser = NSLocalizedString("autofill.save-login.new-user.message", value: "Passwords are stored securely on your device in the Logins menu.", comment: "Message displayed on modal asking for the user to save the login for the first time") public static let autofillSaveLoginNotNowCTA = NSLocalizedString("autofill.save-login.not-now.CTA", value: "Don’t Save", comment: "Cancel CTA displayed on modal asking for the user to save the login") - - public static let autofillSavePasswordTitle = NSLocalizedString("autofill.save-password.title", value: "Save Password?", comment: "Title displayed on modal asking for the user to save the password") + public static let autofillSaveLoginNeverPromptCTA = NSLocalizedString("autofill.save-login.never-prompt.CTA", value:"Never Ask for This Site", comment: "CTA displayed on modal asking if the user never wants to be prompted to save a login for this website agin") + public static func autofillUpdatePassword(for title: String) -> String { let message = NSLocalizedString("autofill.update-password.title", value: "Update password for\n%@?", comment: "Title displayed on modal asking for the user to update the password") return message.format(arguments: title) } - public static let autoUpdatePasswordMessage = NSLocalizedString("autofill.update-password.message", value: "DuckDuckGo will update this stored Login on your device.", comment: "Message displayed on modal asking for the user to update the password") + public static let autoUpdatePasswordMessage = NSLocalizedString("autofill.update-password.message", value: "DuckDuckGo will update this stored password on your device.", comment: "Message displayed on modal asking for the user to update the password") - public static let autofillSaveLoginSaveCTA = NSLocalizedString("autofill.save-login.save.CTA", value: "Save Login", comment: "Confirm CTA displayed on modal asking for the user to save the login") public static let autofillSavePasswordSaveCTA = NSLocalizedString("autofill.save-password.save.CTA", value: "Save Password", comment: "Confirm CTA displayed on modal asking for the user to save the password") public static let autofillUpdatePasswordSaveCTA = NSLocalizedString("autofill.update-password.save.CTA", value: "Update Password", comment: "Confirm CTA displayed on modal asking for the user to update the password") public static let autofillShowPassword = NSLocalizedString("autofill.show-password", value: "Show Password", comment: "Accessibility title for a Show Password button displaying actial password instead of *****") @@ -729,13 +728,18 @@ But if you *do* want a peek under the hood, you can find more information about """, comment: "about page") public static let autofillEnableSettings = NSLocalizedString("autofill.logins.list.enable", value:"Save and Autofill Logins", comment: "Title for a toggle that enables autofill") + public static let autofillNeverSavedSettings = NSLocalizedString("autofill.logins.list.never.saved", value:"Reset Excluded Sites", comment: "Title for a button that allows a user to reset their list of never saved sites") public static let autofillLoginListTitle = NSLocalizedString("autofill.logins.list.title", value:"Logins", comment: "Title for screen listing autofill logins") public static let autofillLoginListSearchPlaceholder = NSLocalizedString("autofill.logins.list.search-placeholder", value:"Search Logins", comment: "Placeholder for search field on autofill login listing") public static let autofillLoginListSuggested = NSLocalizedString("autofill.logins.list.suggested", value:"Suggested", comment: "Section title for group of suggested saved logins") + public static let autofillResetNeverSavedActionTitle = NSLocalizedString("autofill.logins.list.never.saved.reset.action.title", value:"If you reset excluded sites, you will be prompted to save your Login next time you sign in to any of these sites.", comment: "Alert title") + public static let autofillResetNeverSavedActionConfirmButton = NSLocalizedString("autofill.logins.list.never.saved.reset.action.confirm", value: "Reset Excluded Sites", comment: "Confirm button to reset list of never saved sites") + public static let autofillResetNeverSavedActionCancelButton = NSLocalizedString("autofill.logins.list.never.saved.reset.action.cancel", value: "Cancel", comment: "Cancel button for resetting list of never saved sites") + public static let autofillLoginPromptAuthenticationCancelButton = NSLocalizedString("autofill.logins.prompt.auth.cancel", value:"Cancel", comment: "Cancel button for auth during login prompt") public static let autofillLoginPromptAuthenticationReason = NSLocalizedString("autofill.logins.prompt.auth.reason", value:"Unlock To Use Saved Login", comment: "Reason for auth during login prompt") - public static let autofillLoginPromptTitle = NSLocalizedString("autofill.logins.prompt.title", value:"Use a saved Login?", comment: "Title for autofill login prompt") + public static let autofillLoginPromptTitle = NSLocalizedString("autofill.logins.prompt.title", value:"Use a saved password?", comment: "Title for autofill login prompt") public static let autofillLoginPromptExactMatchTitle = NSLocalizedString("autofill.logins.prompt.exact.match.title", value:"From this website", comment: "Title for section of autofill logins that are an exact match to the current website") public static func autofillLoginPromptPartialMatchTitle(for type: String) -> String { let message = NSLocalizedString("autofill.logins.prompt.partial.match.title", value: "From %@", comment: "Title for section of autofill logins that are an approximate match to the current website") diff --git a/DuckDuckGo/bg.lproj/Localizable.strings b/DuckDuckGo/bg.lproj/Localizable.strings index a8a38eceec..ebb2fec0f5 100644 --- a/DuckDuckGo/bg.lproj/Localizable.strings +++ b/DuckDuckGo/bg.lproj/Localizable.strings @@ -529,6 +529,18 @@ /* Toast message when a login item without a title is deleted */ "autofill.logins.list.login-deleted-message-no-title" = "Данните за вход са изтрити"; +/* Title for a button that allows a user to reset their list of never saved sites */ +"autofill.logins.list.never.saved" = "Нулиране на изключените сайтове"; + +/* Cancel button for resetting list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.cancel" = "Отмени"; + +/* Confirm button to reset list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.confirm" = "Нулиране на изключените сайтове"; + +/* Alert title */ +"autofill.logins.list.never.saved.reset.action.title" = "Ако нулирате изключените сайтове, при следващото влизане в някой от тези сайтове ще бъдете подканени да запазите данните си за вход."; + /* Placeholder for search field on autofill login listing */ "autofill.logins.list.search-placeholder" = "Търсене на данни за вход"; @@ -563,7 +575,7 @@ "autofill.logins.prompt.password.button.title" = "Парола за %@"; /* Title for autofill login prompt */ -"autofill.logins.prompt.title" = "Да се използват ли запазените данни за вход?"; +"autofill.logins.prompt.title" = "Използване на запазена парола?"; /* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ "autofill.logins.search.no-results.subtitle" = "за '%@'"; @@ -613,27 +625,24 @@ /* Title for the alert dialog telling the user an updated username is no longer a private email address */ "autofill.removed.duck.address.title" = "Потребителското име на личен Duck Address беше премахнато"; +/* CTA displayed on modal asking if the user never wants to be prompted to save a login for this website agin */ +"autofill.save-login.never-prompt.CTA" = "Никога не питай за този сайт"; + /* Message displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.message" = "Данните за вход се съхраняват на сигурно място в менюто Данни за вход на Вашето устройство."; +"autofill.save-login.new-user.message" = "Паролите се съхраняват на сигурно място в менюто Данни за вход на Вашето устройство."; /* Title displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.title" = "Искате ли DuckDuckGo да запази данните за вход?"; +"autofill.save-login.new-user.title" = "Искате ли DuckDuckGo да запази Вашата парола?"; /* Cancel CTA displayed on modal asking for the user to save the login */ "autofill.save-login.not-now.CTA" = "Не записвай"; -/* Confirm CTA displayed on modal asking for the user to save the login */ -"autofill.save-login.save.CTA" = "Запазване на данните за вход"; - /* Title displayed on modal asking for the user to save the login */ "autofill.save-login.title" = "Запазване на данните за вход?"; /* Confirm CTA displayed on modal asking for the user to save the password */ "autofill.save-password.save.CTA" = "Запазване на паролата"; -/* Title displayed on modal asking for the user to save the password */ -"autofill.save-password.title" = "Запазване на паролата?"; - /* Accessibility title for a Show Password button displaying actial password instead of ***** */ "autofill.show-password" = "Показване на паролата"; @@ -641,7 +650,7 @@ "autofill.signin.to.manage" = "%@ за управление на Вашите Duck Address на това устройство."; /* Message displayed on modal asking for the user to update the password */ -"autofill.update-password.message" = "DuckDuckGo ще актуализира запазените данни за вход във Вашето устройство."; +"autofill.update-password.message" = "DuckDuckGo ще актуализира запазената парола във Вашето устройство."; /* Confirm CTA displayed on modal asking for the user to update the password */ "autofill.update-password.save.CTA" = "Актуализиране на паролата"; diff --git a/DuckDuckGo/cs.lproj/Localizable.strings b/DuckDuckGo/cs.lproj/Localizable.strings index d0ede74744..02864ed0e8 100644 --- a/DuckDuckGo/cs.lproj/Localizable.strings +++ b/DuckDuckGo/cs.lproj/Localizable.strings @@ -529,6 +529,18 @@ /* Toast message when a login item without a title is deleted */ "autofill.logins.list.login-deleted-message-no-title" = "Přihlašovací údaje smazány"; +/* Title for a button that allows a user to reset their list of never saved sites */ +"autofill.logins.list.never.saved" = "Obnovit vyloučené stránky"; + +/* Cancel button for resetting list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.cancel" = "Zrušit"; + +/* Confirm button to reset list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.confirm" = "Obnovit vyloučené stránky"; + +/* Alert title */ +"autofill.logins.list.never.saved.reset.action.title" = "Pokud vyloučené weby resetuješ, při příštím přihlašování na některý z nich se ti zobrazí výzva k uložení přihlašovacích údajů."; + /* Placeholder for search field on autofill login listing */ "autofill.logins.list.search-placeholder" = "Hledání přihlašovacích údajů"; @@ -563,7 +575,7 @@ "autofill.logins.prompt.password.button.title" = "Heslo pro %@"; /* Title for autofill login prompt */ -"autofill.logins.prompt.title" = "Použít uložené přihlášení?"; +"autofill.logins.prompt.title" = "Použít uložené heslo?"; /* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ "autofill.logins.search.no-results.subtitle" = "pro „%@“"; @@ -613,27 +625,24 @@ /* Title for the alert dialog telling the user an updated username is no longer a private email address */ "autofill.removed.duck.address.title" = "Soukromé uživatelské jméno Duck Address je smazané"; +/* CTA displayed on modal asking if the user never wants to be prompted to save a login for this website agin */ +"autofill.save-login.never-prompt.CTA" = "Na téhle stránce už se neptat"; + /* Message displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.message" = "Přihlašovací údaje jsou bezpečně uložené v zařízení v nabídce Přihlášení."; +"autofill.save-login.new-user.message" = "Hesla jsou bezpečně uložená v zařízení v nabídce Přihlášení."; /* Title displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.title" = "Má DuckDuckGo uložit přihlašovací údaje?"; +"autofill.save-login.new-user.title" = "Má DuckDuckGo uložit heslo?"; /* Cancel CTA displayed on modal asking for the user to save the login */ "autofill.save-login.not-now.CTA" = "Neukládat"; -/* Confirm CTA displayed on modal asking for the user to save the login */ -"autofill.save-login.save.CTA" = "Uložit přihlašovací údaje"; - /* Title displayed on modal asking for the user to save the login */ "autofill.save-login.title" = "Uložit přihlašovací údaje?"; /* Confirm CTA displayed on modal asking for the user to save the password */ "autofill.save-password.save.CTA" = "Uložit heslo"; -/* Title displayed on modal asking for the user to save the password */ -"autofill.save-password.title" = "Uložit heslo?"; - /* Accessibility title for a Show Password button displaying actial password instead of ***** */ "autofill.show-password" = "Zobrazit heslo"; @@ -641,7 +650,7 @@ "autofill.signin.to.manage" = "%@ pro správu adres Duck Address na tomto zařízení."; /* Message displayed on modal asking for the user to update the password */ -"autofill.update-password.message" = "DuckDuckGo zaktualizuje toto uložené přihlášení ve tvém zařízení."; +"autofill.update-password.message" = "DuckDuckGo aktualizuje tohle uložené heslo ve tvém zařízení."; /* Confirm CTA displayed on modal asking for the user to update the password */ "autofill.update-password.save.CTA" = "Aktualizuj si heslo"; diff --git a/DuckDuckGo/da.lproj/Localizable.strings b/DuckDuckGo/da.lproj/Localizable.strings index 36e78c8a2f..a0e9bb2c37 100644 --- a/DuckDuckGo/da.lproj/Localizable.strings +++ b/DuckDuckGo/da.lproj/Localizable.strings @@ -529,6 +529,18 @@ /* Toast message when a login item without a title is deleted */ "autofill.logins.list.login-deleted-message-no-title" = "Login slettet"; +/* Title for a button that allows a user to reset their list of never saved sites */ +"autofill.logins.list.never.saved" = "Nulstil ekskluderede websteder"; + +/* Cancel button for resetting list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.cancel" = "Annullér"; + +/* Confirm button to reset list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.confirm" = "Nulstil ekskluderede websteder"; + +/* Alert title */ +"autofill.logins.list.never.saved.reset.action.title" = "Hvis du nulstiller ekskluderede websteder, vil du blive bedt om at gemme dit login, næste gang du logger ind på en af disse sider."; + /* Placeholder for search field on autofill login listing */ "autofill.logins.list.search-placeholder" = "Søg logins"; @@ -563,7 +575,7 @@ "autofill.logins.prompt.password.button.title" = "Adgangskode til %@"; /* Title for autofill login prompt */ -"autofill.logins.prompt.title" = "Vil du bruge et gemt login?"; +"autofill.logins.prompt.title" = "Brug en gemt adgangskode?"; /* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ "autofill.logins.search.no-results.subtitle" = "for '%@'"; @@ -613,27 +625,24 @@ /* Title for the alert dialog telling the user an updated username is no longer a private email address */ "autofill.removed.duck.address.title" = "Privat Duck Address-brugernavn blev fjernet"; +/* CTA displayed on modal asking if the user never wants to be prompted to save a login for this website agin */ +"autofill.save-login.never-prompt.CTA" = "Spørg aldrig på dette websted"; + /* Message displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.message" = "Logins gemmes sikkert på din enhed i menuen Logins."; +"autofill.save-login.new-user.message" = "Adgangskoder gemmes sikkert på din enhed i menuen Logins."; /* Title displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.title" = "Skal DuckDuckGo gemme dit login?"; +"autofill.save-login.new-user.title" = "Skal DuckDuckGo gemme din adgangskode?"; /* Cancel CTA displayed on modal asking for the user to save the login */ "autofill.save-login.not-now.CTA" = "Gem ikke"; -/* Confirm CTA displayed on modal asking for the user to save the login */ -"autofill.save-login.save.CTA" = "Gem login"; - /* Title displayed on modal asking for the user to save the login */ "autofill.save-login.title" = "Gem login?"; /* Confirm CTA displayed on modal asking for the user to save the password */ "autofill.save-password.save.CTA" = "Gem adgangskode"; -/* Title displayed on modal asking for the user to save the password */ -"autofill.save-password.title" = "Gem adgangskode?"; - /* Accessibility title for a Show Password button displaying actial password instead of ***** */ "autofill.show-password" = "Vis adgangskode"; @@ -641,7 +650,7 @@ "autofill.signin.to.manage" = "%@ for at administrere dine Duck-adresser på denne enhed."; /* Message displayed on modal asking for the user to update the password */ -"autofill.update-password.message" = "DuckDuckGo opdaterer dette gemte login på din enhed."; +"autofill.update-password.message" = "DuckDuckGo opdaterer denne gemte adgangskode på din enhed."; /* Confirm CTA displayed on modal asking for the user to update the password */ "autofill.update-password.save.CTA" = "Opdater adgangskode"; diff --git a/DuckDuckGo/de.lproj/Localizable.strings b/DuckDuckGo/de.lproj/Localizable.strings index 93ea701619..6f59a19e6e 100644 --- a/DuckDuckGo/de.lproj/Localizable.strings +++ b/DuckDuckGo/de.lproj/Localizable.strings @@ -529,6 +529,18 @@ /* Toast message when a login item without a title is deleted */ "autofill.logins.list.login-deleted-message-no-title" = "Anmeldedaten gelöscht"; +/* Title for a button that allows a user to reset their list of never saved sites */ +"autofill.logins.list.never.saved" = "Ausgeschlossene Websites zurücksetzen"; + +/* Cancel button for resetting list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.cancel" = "Abbrechen"; + +/* Confirm button to reset list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.confirm" = "Ausgeschlossene Websites zurücksetzen"; + +/* Alert title */ +"autofill.logins.list.never.saved.reset.action.title" = "Wenn du die ausgeschlossenen Websites zurücksetzt, wirst du aufgefordert, deine Anmeldedaten zu speichern, wenn du dich das nächste Mal auf einer dieser Websites anmeldest."; + /* Placeholder for search field on autofill login listing */ "autofill.logins.list.search-placeholder" = "Anmeldedaten suchen"; @@ -563,7 +575,7 @@ "autofill.logins.prompt.password.button.title" = "Passwort für %@"; /* Title for autofill login prompt */ -"autofill.logins.prompt.title" = "Gespeicherte Anmeldedaten verwenden?"; +"autofill.logins.prompt.title" = "Gespeichertes Passwort verwenden?"; /* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ "autofill.logins.search.no-results.subtitle" = "für „%@“"; @@ -613,27 +625,24 @@ /* Title for the alert dialog telling the user an updated username is no longer a private email address */ "autofill.removed.duck.address.title" = "Benutzername von Private Duck Address wurde entfernt"; +/* CTA displayed on modal asking if the user never wants to be prompted to save a login for this website agin */ +"autofill.save-login.never-prompt.CTA" = "Für diese Website niemals fragen"; + /* Message displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.message" = "Anmeldedaten werden sicher auf deinem Gerät im Anmeldedaten-Menü gespeichert."; +"autofill.save-login.new-user.message" = "Passwörter werden sicher auf deinem Gerät im Anmeldedaten-Menü gespeichert."; /* Title displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.title" = "Möchtest du, dass DuckDuckGo deine Anmeldedaten speichert?"; +"autofill.save-login.new-user.title" = "Möchtest du, dass DuckDuckGo dein Passwort speichert?"; /* Cancel CTA displayed on modal asking for the user to save the login */ "autofill.save-login.not-now.CTA" = "Nicht speichern"; -/* Confirm CTA displayed on modal asking for the user to save the login */ -"autofill.save-login.save.CTA" = "Anmeldedaten speichern"; - /* Title displayed on modal asking for the user to save the login */ "autofill.save-login.title" = "Anmeldedaten speichern?"; /* Confirm CTA displayed on modal asking for the user to save the password */ "autofill.save-password.save.CTA" = "Passwort speichern"; -/* Title displayed on modal asking for the user to save the password */ -"autofill.save-password.title" = "Passwort speichern?"; - /* Accessibility title for a Show Password button displaying actial password instead of ***** */ "autofill.show-password" = "Passwort anzeigen"; @@ -641,7 +650,7 @@ "autofill.signin.to.manage" = "%@, um deine Duck Addresses auf diesem Gerät zu verwalten."; /* Message displayed on modal asking for the user to update the password */ -"autofill.update-password.message" = "DuckDuckGo aktualisiert diese gespeicherten Anmeldedaten auf deinem Gerät."; +"autofill.update-password.message" = "DuckDuckGo aktualisiert dieses gespeicherte Passwort auf deinem Gerät."; /* Confirm CTA displayed on modal asking for the user to update the password */ "autofill.update-password.save.CTA" = "Passwort aktualisieren"; diff --git a/DuckDuckGo/el.lproj/Localizable.strings b/DuckDuckGo/el.lproj/Localizable.strings index 9f2cd24469..ff3591fc75 100644 --- a/DuckDuckGo/el.lproj/Localizable.strings +++ b/DuckDuckGo/el.lproj/Localizable.strings @@ -529,6 +529,18 @@ /* Toast message when a login item without a title is deleted */ "autofill.logins.list.login-deleted-message-no-title" = "Η σύνδεση διαγράφηκε"; +/* Title for a button that allows a user to reset their list of never saved sites */ +"autofill.logins.list.never.saved" = "Επαναφορά αποκλεισμένων ιστότοπων"; + +/* Cancel button for resetting list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.cancel" = "Ακύρωση"; + +/* Confirm button to reset list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.confirm" = "Επαναφορά αποκλεισμένων ιστότοπων"; + +/* Alert title */ +"autofill.logins.list.never.saved.reset.action.title" = "Εάν κάνετε επαναφορά των αποκλεισμένων ιστότοπων, θα σας ζητηθεί να αποθηκεύσετε τη σύνδεσή σας την επόμενη φορά που θα συνδεθείτε σε οποιονδήποτε από τους ιστότοπους αυτούς."; + /* Placeholder for search field on autofill login listing */ "autofill.logins.list.search-placeholder" = "Αναζήτηση στοιχείων σύνδεσης"; @@ -563,7 +575,7 @@ "autofill.logins.prompt.password.button.title" = "Κωδικός πρόσβασης για %@"; /* Title for autofill login prompt */ -"autofill.logins.prompt.title" = "Χρήση αποθηκευμένων στοιχείων σύνδεσης;"; +"autofill.logins.prompt.title" = "Χρήση αποθηκευμένου κωδικού πρόσβασης;"; /* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ "autofill.logins.search.no-results.subtitle" = "για '%@'"; @@ -613,27 +625,24 @@ /* Title for the alert dialog telling the user an updated username is no longer a private email address */ "autofill.removed.duck.address.title" = "Το ιδιωτικό όνομα χρήστη Duck Address καταργήθηκε"; +/* CTA displayed on modal asking if the user never wants to be prompted to save a login for this website agin */ +"autofill.save-login.never-prompt.CTA" = "Μην ζητάτε ποτέ αυτόν τον ιστότοπο"; + /* Message displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.message" = "Οι συνδέσεις αποθηκεύονται με ασφάλεια στη συσκευή σας στο μενού Συνδέσεις."; +"autofill.save-login.new-user.message" = "Οι κωδικοί πρόσβασης αποθηκεύονται με ασφάλεια στη συσκευή σας στο μενού Συνδέσεις."; /* Title displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.title" = "Θέλετε να αποθηκεύσει το DuckDuckGo τη σύνδεσή σας;"; +"autofill.save-login.new-user.title" = "Θέλετε το DuckDuckGo να αποθηκεύσει τον κωδικό πρόσβασής σας;"; /* Cancel CTA displayed on modal asking for the user to save the login */ "autofill.save-login.not-now.CTA" = "Να μην αποθηκευτεί"; -/* Confirm CTA displayed on modal asking for the user to save the login */ -"autofill.save-login.save.CTA" = "Αποθήκευση σύνδεσης"; - /* Title displayed on modal asking for the user to save the login */ "autofill.save-login.title" = "Αποθήκευση σύνδεσης;"; /* Confirm CTA displayed on modal asking for the user to save the password */ "autofill.save-password.save.CTA" = "Αποθήκευση κωδικού πρόσβασης"; -/* Title displayed on modal asking for the user to save the password */ -"autofill.save-password.title" = "Αποθήκευση κωδικού πρόσβασης;"; - /* Accessibility title for a Show Password button displaying actial password instead of ***** */ "autofill.show-password" = "Εμφάνιση κωδικού πρόσβασης"; @@ -641,7 +650,7 @@ "autofill.signin.to.manage" = "%@ για διαχείριση των διευθύνσεών σας Duck Address σε αυτήν τη συσκευή."; /* Message displayed on modal asking for the user to update the password */ -"autofill.update-password.message" = "Το DuckDuckGo θα ενημερώσει αυτήν την αποθηκευμένη σύνδεση στη συσκευή σας."; +"autofill.update-password.message" = "Το DuckDuckGo θα ενημερώσει αυτόν τον αποθηκευμένο κωδικό πρόσβασης στη συσκευή σας."; /* Confirm CTA displayed on modal asking for the user to update the password */ "autofill.update-password.save.CTA" = "Ενημέρωση κωδικού πρόσβασης"; diff --git a/DuckDuckGo/en.lproj/Localizable.strings b/DuckDuckGo/en.lproj/Localizable.strings index 928beb63e0..14489e1a91 100644 --- a/DuckDuckGo/en.lproj/Localizable.strings +++ b/DuckDuckGo/en.lproj/Localizable.strings @@ -544,6 +544,18 @@ /* Toast message when a login item without a title is deleted */ "autofill.logins.list.login-deleted-message-no-title" = "Login deleted"; +/* Title for a button that allows a user to reset their list of never saved sites */ +"autofill.logins.list.never.saved" = "Reset Excluded Sites"; + +/* Cancel button for resetting list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.cancel" = "Cancel"; + +/* Confirm button to reset list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.confirm" = "Reset Excluded Sites"; + +/* Alert title */ +"autofill.logins.list.never.saved.reset.action.title" = "If you reset excluded sites, you will be prompted to save your Login next time you sign in to any of these sites."; + /* Placeholder for search field on autofill login listing */ "autofill.logins.list.search-placeholder" = "Search Logins"; @@ -578,7 +590,7 @@ "autofill.logins.prompt.password.button.title" = "Password for %@"; /* Title for autofill login prompt */ -"autofill.logins.prompt.title" = "Use a saved Login?"; +"autofill.logins.prompt.title" = "Use a saved password?"; /* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ "autofill.logins.search.no-results.subtitle" = "for '%@'"; @@ -628,27 +640,24 @@ /* Title for the alert dialog telling the user an updated username is no longer a private email address */ "autofill.removed.duck.address.title" = "Private Duck Address username was removed"; +/* CTA displayed on modal asking if the user never wants to be prompted to save a login for this website agin */ +"autofill.save-login.never-prompt.CTA" = "Never Ask for This Site"; + /* Message displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.message" = "Logins are stored securely on your device in the Logins menu."; +"autofill.save-login.new-user.message" = "Passwords are stored securely on your device in the Logins menu."; /* Title displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.title" = "Do you want DuckDuckGo to save your Login?"; +"autofill.save-login.new-user.title" = "Do you want DuckDuckGo to save your password?"; /* Cancel CTA displayed on modal asking for the user to save the login */ "autofill.save-login.not-now.CTA" = "Don’t Save"; -/* Confirm CTA displayed on modal asking for the user to save the login */ -"autofill.save-login.save.CTA" = "Save Login"; - /* Title displayed on modal asking for the user to save the login */ "autofill.save-login.title" = "Save Login?"; /* Confirm CTA displayed on modal asking for the user to save the password */ "autofill.save-password.save.CTA" = "Save Password"; -/* Title displayed on modal asking for the user to save the password */ -"autofill.save-password.title" = "Save Password?"; - /* Accessibility title for a Show Password button displaying actial password instead of ***** */ "autofill.show-password" = "Show Password"; @@ -656,7 +665,7 @@ "autofill.signin.to.manage" = "%@ to manage your Duck Addresses on this device."; /* Message displayed on modal asking for the user to update the password */ -"autofill.update-password.message" = "DuckDuckGo will update this stored Login on your device."; +"autofill.update-password.message" = "DuckDuckGo will update this stored password on your device."; /* Confirm CTA displayed on modal asking for the user to update the password */ "autofill.update-password.save.CTA" = "Update Password"; diff --git a/DuckDuckGo/es.lproj/Localizable.strings b/DuckDuckGo/es.lproj/Localizable.strings index b5d389db5e..9262ddf95a 100644 --- a/DuckDuckGo/es.lproj/Localizable.strings +++ b/DuckDuckGo/es.lproj/Localizable.strings @@ -529,6 +529,18 @@ /* Toast message when a login item without a title is deleted */ "autofill.logins.list.login-deleted-message-no-title" = "Inicio de sesión eliminado"; +/* Title for a button that allows a user to reset their list of never saved sites */ +"autofill.logins.list.never.saved" = "Restablecer sitios excluidos"; + +/* Cancel button for resetting list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.cancel" = "Cancelar"; + +/* Confirm button to reset list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.confirm" = "Restablecer sitios excluidos"; + +/* Alert title */ +"autofill.logins.list.never.saved.reset.action.title" = "Si restableces los sitios excluidos, se te pedirá que guardes tus datos de inicio de sesión la próxima vez que accedas a cualquiera de estos sitios."; + /* Placeholder for search field on autofill login listing */ "autofill.logins.list.search-placeholder" = "Buscar inicios de sesión"; @@ -563,7 +575,7 @@ "autofill.logins.prompt.password.button.title" = "Contraseña para %@"; /* Title for autofill login prompt */ -"autofill.logins.prompt.title" = "¿Usar un inicio de sesión guardado?"; +"autofill.logins.prompt.title" = "¿Usar una contraseña guardada?"; /* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ "autofill.logins.search.no-results.subtitle" = "para '%@'"; @@ -613,27 +625,24 @@ /* Title for the alert dialog telling the user an updated username is no longer a private email address */ "autofill.removed.duck.address.title" = "Se ha eliminado el nombre de usuario de la Duck Address privada"; +/* CTA displayed on modal asking if the user never wants to be prompted to save a login for this website agin */ +"autofill.save-login.never-prompt.CTA" = "No preguntar nunca para esta página"; + /* Message displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.message" = "Los inicios de sesión se almacenan de forma segura en tu dispositivo en el menú Inicios de sesión."; +"autofill.save-login.new-user.message" = "Las contraseñas se almacenan de forma segura en tu dispositivo en el menú Inicios de sesión."; /* Title displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.title" = "¿Quieres que DuckDuckGo guarde tu inicio de sesión?"; +"autofill.save-login.new-user.title" = "¿Quieres que DuckDuckGo guarde tu contraseña?"; /* Cancel CTA displayed on modal asking for the user to save the login */ "autofill.save-login.not-now.CTA" = "No guardar"; -/* Confirm CTA displayed on modal asking for the user to save the login */ -"autofill.save-login.save.CTA" = "Guardar inicio de sesión"; - /* Title displayed on modal asking for the user to save the login */ "autofill.save-login.title" = "¿Guardar inicio de sesión?"; /* Confirm CTA displayed on modal asking for the user to save the password */ "autofill.save-password.save.CTA" = "Guardar contraseña"; -/* Title displayed on modal asking for the user to save the password */ -"autofill.save-password.title" = "¿Guardar contraseña?"; - /* Accessibility title for a Show Password button displaying actial password instead of ***** */ "autofill.show-password" = "Mostrar contraseña"; @@ -641,7 +650,7 @@ "autofill.signin.to.manage" = "%@ para gestionar tus Duck Addresses en este dispositivo."; /* Message displayed on modal asking for the user to update the password */ -"autofill.update-password.message" = "DuckDuckGo actualizará este inicio de sesión almacenado en tu dispositivo."; +"autofill.update-password.message" = "DuckDuckGo actualizará esta contraseña almacenada en tu dispositivo."; /* Confirm CTA displayed on modal asking for the user to update the password */ "autofill.update-password.save.CTA" = "Actualizar contraseña"; diff --git a/DuckDuckGo/et.lproj/Localizable.strings b/DuckDuckGo/et.lproj/Localizable.strings index e895da5908..3df8179e8c 100644 --- a/DuckDuckGo/et.lproj/Localizable.strings +++ b/DuckDuckGo/et.lproj/Localizable.strings @@ -529,6 +529,18 @@ /* Toast message when a login item without a title is deleted */ "autofill.logins.list.login-deleted-message-no-title" = "Sisselogimisandmed kustutati"; +/* Title for a button that allows a user to reset their list of never saved sites */ +"autofill.logins.list.never.saved" = "Lähtesta välistatud saidid"; + +/* Cancel button for resetting list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.cancel" = "Tühista"; + +/* Confirm button to reset list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.confirm" = "Lähtesta välistatud saidid"; + +/* Alert title */ +"autofill.logins.list.never.saved.reset.action.title" = "Kui lähtestad välistatud saidid, küsitakse järgmisel mõnele neist saitidest sisselogimisel, kas soovid salvestada oma sisselogimisandmed."; + /* Placeholder for search field on autofill login listing */ "autofill.logins.list.search-placeholder" = "Otsi sisselogimisandmeid"; @@ -563,7 +575,7 @@ "autofill.logins.prompt.password.button.title" = "Parool veebisaidi %@ jaoks"; /* Title for autofill login prompt */ -"autofill.logins.prompt.title" = "Kas kasutada salvestatud sisselogimisandmeid?"; +"autofill.logins.prompt.title" = "Kas kasutada salvestatud parooli?"; /* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ "autofill.logins.search.no-results.subtitle" = "otsinguga '%@'"; @@ -613,27 +625,24 @@ /* Title for the alert dialog telling the user an updated username is no longer a private email address */ "autofill.removed.duck.address.title" = "Privaatse Duck Addressi kasutajanimi eemaldati"; +/* CTA displayed on modal asking if the user never wants to be prompted to save a login for this website agin */ +"autofill.save-login.never-prompt.CTA" = "Ära selle saidi kohta rohkem küsi"; + /* Message displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.message" = "Logisid hoitakse turvaliselt sinu seadmes logide menüüs."; +"autofill.save-login.new-user.message" = "Paroole hoitakse turvaliselt sinu seadmes sisselogimisandmete menüüs."; /* Title displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.title" = "Kas soovid, et DuckDuckGo salvestaks sinu sisselogimisandmed?"; +"autofill.save-login.new-user.title" = "Kas soovid, et DuckDuckGo salvestaks sinu parooli?"; /* Cancel CTA displayed on modal asking for the user to save the login */ "autofill.save-login.not-now.CTA" = "Ära salvesta"; -/* Confirm CTA displayed on modal asking for the user to save the login */ -"autofill.save-login.save.CTA" = "Salvesta sisselogimisandmed"; - /* Title displayed on modal asking for the user to save the login */ "autofill.save-login.title" = "Kas salvestada sisselogimisandmed?"; /* Confirm CTA displayed on modal asking for the user to save the password */ "autofill.save-password.save.CTA" = "Salvesta parool"; -/* Title displayed on modal asking for the user to save the password */ -"autofill.save-password.title" = "Kas salvestada parool?"; - /* Accessibility title for a Show Password button displaying actial password instead of ***** */ "autofill.show-password" = "Kuva parool"; @@ -641,7 +650,7 @@ "autofill.signin.to.manage" = "%@, et hallata selles seadmes oma Duck Addresse."; /* Message displayed on modal asking for the user to update the password */ -"autofill.update-password.message" = "DuckDuckGo värskendab need salvestatud sisselogimisandmed sinu seadmes."; +"autofill.update-password.message" = "DuckDuckGo värskendab selle salvestatud parooli sinu seadmes."; /* Confirm CTA displayed on modal asking for the user to update the password */ "autofill.update-password.save.CTA" = "Värskenda parooli"; diff --git a/DuckDuckGo/fi.lproj/Localizable.strings b/DuckDuckGo/fi.lproj/Localizable.strings index 98e26c789f..2f5ff76343 100644 --- a/DuckDuckGo/fi.lproj/Localizable.strings +++ b/DuckDuckGo/fi.lproj/Localizable.strings @@ -529,6 +529,18 @@ /* Toast message when a login item without a title is deleted */ "autofill.logins.list.login-deleted-message-no-title" = "Kirjautumistieto poistettu"; +/* Title for a button that allows a user to reset their list of never saved sites */ +"autofill.logins.list.never.saved" = "Nollaa poissuljetut sivustot"; + +/* Cancel button for resetting list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.cancel" = "Peruuta"; + +/* Confirm button to reset list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.confirm" = "Nollaa poissuljetut sivustot"; + +/* Alert title */ +"autofill.logins.list.never.saved.reset.action.title" = "Jos nollaat poissuljetut sivustot, sinua pyydetään tallentamaan kirjautumistietosi, kun seuraavan kerran kirjaudut sisään jollekin näistä sivustoista."; + /* Placeholder for search field on autofill login listing */ "autofill.logins.list.search-placeholder" = "Hae kirjautumistietoja"; @@ -563,7 +575,7 @@ "autofill.logins.prompt.password.button.title" = "Sivuston %@ salasana"; /* Title for autofill login prompt */ -"autofill.logins.prompt.title" = "Käytä tallennettuja kirjautumistietoja?"; +"autofill.logins.prompt.title" = "Käytetäänkö tallennettua salasanaa?"; /* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ "autofill.logins.search.no-results.subtitle" = "kohteelle '%@'"; @@ -613,27 +625,24 @@ /* Title for the alert dialog telling the user an updated username is no longer a private email address */ "autofill.removed.duck.address.title" = "Yksityinen Duck Address -käyttäjätunnus on poistettu"; +/* CTA displayed on modal asking if the user never wants to be prompted to save a login for this website agin */ +"autofill.save-login.never-prompt.CTA" = "Älä kysy enää tällä sivustolla"; + /* Message displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.message" = "Kirjautumistiedot tallennetaan turvallisesti laitteellesi kirjautumistiedot-valikkoon."; +"autofill.save-login.new-user.message" = "Salasanat tallennetaan turvallisesti laitteellesi kirjautumistiedot-valikkoon."; /* Title displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.title" = "Haluatko, että DuckDuckGo tallentaa kirjautumistietosi?"; +"autofill.save-login.new-user.title" = "Haluatko, että DuckDuckGo tallentaa salasanasi?"; /* Cancel CTA displayed on modal asking for the user to save the login */ "autofill.save-login.not-now.CTA" = "Älä tallenna"; -/* Confirm CTA displayed on modal asking for the user to save the login */ -"autofill.save-login.save.CTA" = "Tallenna kirjautumistiedot"; - /* Title displayed on modal asking for the user to save the login */ "autofill.save-login.title" = "Tallennetaanko kirjautumistiedot?"; /* Confirm CTA displayed on modal asking for the user to save the password */ "autofill.save-password.save.CTA" = "Tallenna salasana"; -/* Title displayed on modal asking for the user to save the password */ -"autofill.save-password.title" = "Tallennetaanko salasana?"; - /* Accessibility title for a Show Password button displaying actial password instead of ***** */ "autofill.show-password" = "Näytä salasana"; @@ -641,7 +650,7 @@ "autofill.signin.to.manage" = "%@ hallitaksesi Duck Address -osoitteita tällä laitteella."; /* Message displayed on modal asking for the user to update the password */ -"autofill.update-password.message" = "DuckDuckGo päivittää tämän laitteellesi tallennetun kirjautumistiedon."; +"autofill.update-password.message" = "DuckDuckGo päivittää tämän tallennetun salasanan laitteellesi."; /* Confirm CTA displayed on modal asking for the user to update the password */ "autofill.update-password.save.CTA" = "Päivitä salasana"; diff --git a/DuckDuckGo/fr.lproj/Localizable.strings b/DuckDuckGo/fr.lproj/Localizable.strings index 4831775401..e29c841bb2 100644 --- a/DuckDuckGo/fr.lproj/Localizable.strings +++ b/DuckDuckGo/fr.lproj/Localizable.strings @@ -529,6 +529,18 @@ /* Toast message when a login item without a title is deleted */ "autofill.logins.list.login-deleted-message-no-title" = "Identifiant supprimé"; +/* Title for a button that allows a user to reset their list of never saved sites */ +"autofill.logins.list.never.saved" = "Réinitialiser les sites exclus"; + +/* Cancel button for resetting list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.cancel" = "Annuler"; + +/* Confirm button to reset list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.confirm" = "Réinitialiser les sites exclus"; + +/* Alert title */ +"autofill.logins.list.never.saved.reset.action.title" = "Si vous réinitialisez les sites exclus, on vous invitera à enregistrer votre identifiant la prochaine fois que vous vous connecterez à l'un de ces sites."; + /* Placeholder for search field on autofill login listing */ "autofill.logins.list.search-placeholder" = "Recherche d'identifiants"; @@ -563,7 +575,7 @@ "autofill.logins.prompt.password.button.title" = "Mot de passe pour %@"; /* Title for autofill login prompt */ -"autofill.logins.prompt.title" = "Utiliser un identifiant enregistré ?"; +"autofill.logins.prompt.title" = "Utiliser un mot de passe enregistré ?"; /* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ "autofill.logins.search.no-results.subtitle" = "pour '%@'"; @@ -613,27 +625,24 @@ /* Title for the alert dialog telling the user an updated username is no longer a private email address */ "autofill.removed.duck.address.title" = "Le nom d'utilisateur de la Duck Address privée a été supprimé"; +/* CTA displayed on modal asking if the user never wants to be prompted to save a login for this website agin */ +"autofill.save-login.never-prompt.CTA" = "Ne jamais demander pour ce site"; + /* Message displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.message" = "Les identifiants de connexion sont stockés en toute sécurité sur votre appareil dans le menu Identifiants."; +"autofill.save-login.new-user.message" = "Les mots de passe sont stockés en toute sécurité sur votre appareil dans le menu Identifiants."; /* Title displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.title" = "Voulez-vous que DuckDuckGo enregistre votre identifiant ?"; +"autofill.save-login.new-user.title" = "Voulez-vous que DuckDuckGo enregistre votre mot de passe ?"; /* Cancel CTA displayed on modal asking for the user to save the login */ "autofill.save-login.not-now.CTA" = "Ne pas enregistrer"; -/* Confirm CTA displayed on modal asking for the user to save the login */ -"autofill.save-login.save.CTA" = "Enregistrer l'identifiant"; - /* Title displayed on modal asking for the user to save the login */ "autofill.save-login.title" = "Enregistrer l'identifiant ?"; /* Confirm CTA displayed on modal asking for the user to save the password */ "autofill.save-password.save.CTA" = "Enregistrer le mot de passe"; -/* Title displayed on modal asking for the user to save the password */ -"autofill.save-password.title" = "Enregistrer le mot de passe ?"; - /* Accessibility title for a Show Password button displaying actial password instead of ***** */ "autofill.show-password" = "Afficher le mot de passe"; @@ -641,7 +650,7 @@ "autofill.signin.to.manage" = "%@ pour gérer vos Duck Addresses sur cet appareil."; /* Message displayed on modal asking for the user to update the password */ -"autofill.update-password.message" = "DuckDuckGo mettra à jour cet identifiant enregistré sur votre appareil."; +"autofill.update-password.message" = "DuckDuckGo mettra à jour ce mot de passe enregistré sur votre appareil."; /* Confirm CTA displayed on modal asking for the user to update the password */ "autofill.update-password.save.CTA" = "Modifier le mot de passe"; diff --git a/DuckDuckGo/hr.lproj/Localizable.strings b/DuckDuckGo/hr.lproj/Localizable.strings index d997b91152..47220b3f4c 100644 --- a/DuckDuckGo/hr.lproj/Localizable.strings +++ b/DuckDuckGo/hr.lproj/Localizable.strings @@ -529,6 +529,18 @@ /* Toast message when a login item without a title is deleted */ "autofill.logins.list.login-deleted-message-no-title" = "Prijava je izbrisana"; +/* Title for a button that allows a user to reset their list of never saved sites */ +"autofill.logins.list.never.saved" = "Vrati izvorne isključene web lokacije"; + +/* Cancel button for resetting list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.cancel" = "Otkaži"; + +/* Confirm button to reset list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.confirm" = "Resetiraj isključene web lokacije"; + +/* Alert title */ +"autofill.logins.list.never.saved.reset.action.title" = "Ako resetiraš isključene web lokacije, od tebe će se zatražiti da spremiš svoju prijavu sljedeći put kad se prijaviš na bilo koju od ovih lokacija."; + /* Placeholder for search field on autofill login listing */ "autofill.logins.list.search-placeholder" = "Pretraživanje prijava"; @@ -563,7 +575,7 @@ "autofill.logins.prompt.password.button.title" = "Lozinka za %@"; /* Title for autofill login prompt */ -"autofill.logins.prompt.title" = "Koristiti spremljene podatke za prijavu?"; +"autofill.logins.prompt.title" = "Koristiti spremljenu lozinku?"; /* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ "autofill.logins.search.no-results.subtitle" = "za '%@'"; @@ -613,27 +625,24 @@ /* Title for the alert dialog telling the user an updated username is no longer a private email address */ "autofill.removed.duck.address.title" = "Korisničko ime privatne Duck Address adrese uklonjeno je"; +/* CTA displayed on modal asking if the user never wants to be prompted to save a login for this website agin */ +"autofill.save-login.never-prompt.CTA" = "Nikada ne traži za ovu web lokaciju"; + /* Message displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.message" = "Prijave su sigurno pohranjene na tvom uređaju u izborniku Prijave."; +"autofill.save-login.new-user.message" = "Lozinke su sigurno pohranjene na tvom uređaju u izborniku Prijava."; /* Title displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.title" = "Želiš li da DuckDuckGo spremi tvoju prijavu?"; +"autofill.save-login.new-user.title" = "Želiš li da DuckDuckGo spremi tvoju lozinku?"; /* Cancel CTA displayed on modal asking for the user to save the login */ "autofill.save-login.not-now.CTA" = "Nemoj spremiti"; -/* Confirm CTA displayed on modal asking for the user to save the login */ -"autofill.save-login.save.CTA" = "Spremi prijavu"; - /* Title displayed on modal asking for the user to save the login */ "autofill.save-login.title" = "Želiš li spremiti prijavu?"; /* Confirm CTA displayed on modal asking for the user to save the password */ "autofill.save-password.save.CTA" = "Spremi lozinku"; -/* Title displayed on modal asking for the user to save the password */ -"autofill.save-password.title" = "Želiš li spremiti lozinku?"; - /* Accessibility title for a Show Password button displaying actial password instead of ***** */ "autofill.show-password" = "Pokaži lozinku"; @@ -641,7 +650,7 @@ "autofill.signin.to.manage" = "%@ za upravljanje tvojim Duck Address adresama na ovom uređaju."; /* Message displayed on modal asking for the user to update the password */ -"autofill.update-password.message" = "DuckDuckGo će ažurirati ovu spremljenu prijavu na tvom uređaju."; +"autofill.update-password.message" = "DuckDuckGo će ažurirati ovu pohranjenu lozinku na tvom uređaju."; /* Confirm CTA displayed on modal asking for the user to update the password */ "autofill.update-password.save.CTA" = "Ažuriraj lozinku"; diff --git a/DuckDuckGo/hu.lproj/Localizable.strings b/DuckDuckGo/hu.lproj/Localizable.strings index 106dcde5b1..340223040d 100644 --- a/DuckDuckGo/hu.lproj/Localizable.strings +++ b/DuckDuckGo/hu.lproj/Localizable.strings @@ -529,6 +529,18 @@ /* Toast message when a login item without a title is deleted */ "autofill.logins.list.login-deleted-message-no-title" = "Bejelentkezés törölve"; +/* Title for a button that allows a user to reset their list of never saved sites */ +"autofill.logins.list.never.saved" = "Kizárt webhelyek visszaállítása"; + +/* Cancel button for resetting list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.cancel" = "Mégsem"; + +/* Confirm button to reset list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.confirm" = "Kizárt webhelyek visszaállítása"; + +/* Alert title */ +"autofill.logins.list.never.saved.reset.action.title" = "A kizárt webhelyek visszaállítása esetén a rendszer a bejelentkezési adataid mentését kéri, amikor legközelebb bejelentkezel ezen webhelyek bármelyikére."; + /* Placeholder for search field on autofill login listing */ "autofill.logins.list.search-placeholder" = "Bejelentkezési adatok keresése"; @@ -563,7 +575,7 @@ "autofill.logins.prompt.password.button.title" = "%@ jelszava"; /* Title for autofill login prompt */ -"autofill.logins.prompt.title" = "Mentett bejelentkezés használata?"; +"autofill.logins.prompt.title" = "Mentett jelszót használsz?"; /* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ "autofill.logins.search.no-results.subtitle" = "erre: „%@“"; @@ -613,27 +625,24 @@ /* Title for the alert dialog telling the user an updated username is no longer a private email address */ "autofill.removed.duck.address.title" = "Privát Duck-cím felhasználóneve eltávolítva"; +/* CTA displayed on modal asking if the user never wants to be prompted to save a login for this website agin */ +"autofill.save-login.never-prompt.CTA" = "Soha ne kérdezzen rá ennél a webhelynél"; + /* Message displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.message" = "A rendszer biztonságosan tárolja az eszköz Bejelentkezés menüjében elérhető bejelentkezési adatokat."; +"autofill.save-login.new-user.message" = "A rendszer biztonságosan tárolja az eszköz Bejelentkezés menüjében elérhető jelszavakat."; /* Title displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.title" = "A DuckDuckGo mentse a bejelentkezést?"; +"autofill.save-login.new-user.title" = "A DuckDuckGo mentse a jelszót?"; /* Cancel CTA displayed on modal asking for the user to save the login */ "autofill.save-login.not-now.CTA" = "Mentés mellőzése"; -/* Confirm CTA displayed on modal asking for the user to save the login */ -"autofill.save-login.save.CTA" = "Bejelentkezés mentése"; - /* Title displayed on modal asking for the user to save the login */ "autofill.save-login.title" = "Mented a bejelentkezést?"; /* Confirm CTA displayed on modal asking for the user to save the password */ "autofill.save-password.save.CTA" = "Jelszó mentése"; -/* Title displayed on modal asking for the user to save the password */ -"autofill.save-password.title" = "Mented a jelszót?"; - /* Accessibility title for a Show Password button displaying actial password instead of ***** */ "autofill.show-password" = "Jelszó megjelenítése"; @@ -641,7 +650,7 @@ "autofill.signin.to.manage" = "%@ a Duck-címek kezeléséhez ezen az eszközön."; /* Message displayed on modal asking for the user to update the password */ -"autofill.update-password.message" = "A DuckDuckGo frissíti az eszközödön ezt a tárolt bejelentkezést."; +"autofill.update-password.message" = "A DuckDuckGo frissíti az eszközödön ezt a tárolt jelszót."; /* Confirm CTA displayed on modal asking for the user to update the password */ "autofill.update-password.save.CTA" = "Jelszó frissítése"; diff --git a/DuckDuckGo/it.lproj/Localizable.strings b/DuckDuckGo/it.lproj/Localizable.strings index 09a883c5c0..70109a5069 100644 --- a/DuckDuckGo/it.lproj/Localizable.strings +++ b/DuckDuckGo/it.lproj/Localizable.strings @@ -529,6 +529,18 @@ /* Toast message when a login item without a title is deleted */ "autofill.logins.list.login-deleted-message-no-title" = "Dati di accesso eliminati"; +/* Title for a button that allows a user to reset their list of never saved sites */ +"autofill.logins.list.never.saved" = "Ripristina siti esclusi"; + +/* Cancel button for resetting list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.cancel" = "Annulla"; + +/* Confirm button to reset list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.confirm" = "Ripristina siti esclusi"; + +/* Alert title */ +"autofill.logins.list.never.saved.reset.action.title" = "Se ripristini i siti esclusi, ti verrà richiesto di salvare i tuoi dati di accesso la prossima volta che accederai a uno di questi siti."; + /* Placeholder for search field on autofill login listing */ "autofill.logins.list.search-placeholder" = "Cerca dati di accesso"; @@ -563,7 +575,7 @@ "autofill.logins.prompt.password.button.title" = "Password per %@"; /* Title for autofill login prompt */ -"autofill.logins.prompt.title" = "Usare i dati di accesso salvati?"; +"autofill.logins.prompt.title" = "Utilizzare una password salvata?"; /* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ "autofill.logins.search.no-results.subtitle" = "per \"%@\""; @@ -613,27 +625,24 @@ /* Title for the alert dialog telling the user an updated username is no longer a private email address */ "autofill.removed.duck.address.title" = "Il nome utente Private Duck Address è stato rimosso"; +/* CTA displayed on modal asking if the user never wants to be prompted to save a login for this website agin */ +"autofill.save-login.never-prompt.CTA" = "Non chiedere mai per questo sito"; + /* Message displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.message" = "Gli accessi sono archiviati in modo sicuro sul tuo dispositivo nel menu Accessi."; +"autofill.save-login.new-user.message" = "Le password sono archiviate in modo sicuro sul tuo dispositivo nel menu Accessi."; /* Title displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.title" = "Vuoi che DuckDuckGo salvi i dati di accesso?"; +"autofill.save-login.new-user.title" = "Vuoi che DuckDuckGo salvi la password?"; /* Cancel CTA displayed on modal asking for the user to save the login */ "autofill.save-login.not-now.CTA" = "Non salvare"; -/* Confirm CTA displayed on modal asking for the user to save the login */ -"autofill.save-login.save.CTA" = "Salva dati di accesso"; - /* Title displayed on modal asking for the user to save the login */ "autofill.save-login.title" = "Salvare dati di accesso?"; /* Confirm CTA displayed on modal asking for the user to save the password */ "autofill.save-password.save.CTA" = "Salva password"; -/* Title displayed on modal asking for the user to save the password */ -"autofill.save-password.title" = "Salvare password?"; - /* Accessibility title for a Show Password button displaying actial password instead of ***** */ "autofill.show-password" = "Mostra password"; @@ -641,7 +650,7 @@ "autofill.signin.to.manage" = "%@ per gestire i tuoi Duck Address su questo dispositivo."; /* Message displayed on modal asking for the user to update the password */ -"autofill.update-password.message" = "DuckDuckGo aggiornerà questi dati di accesso memorizzati sul tuo dispositivo."; +"autofill.update-password.message" = "DuckDuckGo aggiornerà questa password memorizzata sul tuo dispositivo."; /* Confirm CTA displayed on modal asking for the user to update the password */ "autofill.update-password.save.CTA" = "Aggiorna password"; diff --git a/DuckDuckGo/lt.lproj/Localizable.strings b/DuckDuckGo/lt.lproj/Localizable.strings index a84e48bbcc..3a1bb62474 100644 --- a/DuckDuckGo/lt.lproj/Localizable.strings +++ b/DuckDuckGo/lt.lproj/Localizable.strings @@ -529,6 +529,18 @@ /* Toast message when a login item without a title is deleted */ "autofill.logins.list.login-deleted-message-no-title" = "Prisijungimas ištrintas"; +/* Title for a button that allows a user to reset their list of never saved sites */ +"autofill.logins.list.never.saved" = "Iš naujo nustatyti neįtrauktas svetaines"; + +/* Cancel button for resetting list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.cancel" = "Atšaukti"; + +/* Confirm button to reset list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.confirm" = "Iš naujo nustatyti neįtrauktas svetaines"; + +/* Alert title */ +"autofill.logins.list.never.saved.reset.action.title" = "Jei iš naujo nustatysite neįtrauktas svetaines, kitą kartą, kai prisijungsite prie bet kurios iš šių svetainių, būsite paraginti išsaugoti savo prisijungimo vardą."; + /* Placeholder for search field on autofill login listing */ "autofill.logins.list.search-placeholder" = "Ieškoti prisijungimų"; @@ -563,7 +575,7 @@ "autofill.logins.prompt.password.button.title" = "Slaptažodis, skirtas %@"; /* Title for autofill login prompt */ -"autofill.logins.prompt.title" = "Naudoti išsaugotą prisijungimą?"; +"autofill.logins.prompt.title" = "Naudoti išsaugotą slaptažodį?"; /* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ "autofill.logins.search.no-results.subtitle" = "„%@“"; @@ -613,27 +625,24 @@ /* Title for the alert dialog telling the user an updated username is no longer a private email address */ "autofill.removed.duck.address.title" = "Privatus „Duck Address“ naudotojo vardas buvo pašalintas"; +/* CTA displayed on modal asking if the user never wants to be prompted to save a login for this website agin */ +"autofill.save-login.never-prompt.CTA" = "Niekada neklauskite šioje svetainėje"; + /* Message displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.message" = "Prisijungimai saugiai saugomi jūsų įrenginio meniu „Prisijungimai“."; +"autofill.save-login.new-user.message" = "Slaptažodžiai saugiai saugomi jūsų įrenginio meniu „Prisijungimai“."; /* Title displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.title" = "Ar norite, kad „DuckDuckGo“ išsaugotų jūsų prisijungimą?"; +"autofill.save-login.new-user.title" = "Ar norite, kad „DuckDuckGo“ išsaugotų jūsų slaptažodį?"; /* Cancel CTA displayed on modal asking for the user to save the login */ "autofill.save-login.not-now.CTA" = "Neišsaugokite"; -/* Confirm CTA displayed on modal asking for the user to save the login */ -"autofill.save-login.save.CTA" = "Išsaugoti prisijungimą"; - /* Title displayed on modal asking for the user to save the login */ "autofill.save-login.title" = "Išsaugoti prisijungimą?"; /* Confirm CTA displayed on modal asking for the user to save the password */ "autofill.save-password.save.CTA" = "Išsaugoti slaptažodį"; -/* Title displayed on modal asking for the user to save the password */ -"autofill.save-password.title" = "Išsaugoti slaptažodį?"; - /* Accessibility title for a Show Password button displaying actial password instead of ***** */ "autofill.show-password" = "Rodyti slaptažodį"; @@ -641,7 +650,7 @@ "autofill.signin.to.manage" = "%@, kad galėtumėte valdyti savo „Duck Address“ šiame įrenginyje."; /* Message displayed on modal asking for the user to update the password */ -"autofill.update-password.message" = "„DuckDuckGo“ atnaujins šį jūsų įrenginyje įrašytą prisijungimą."; +"autofill.update-password.message" = "„DuckDuckGo“ atnaujins šį jūsų įrenginyje išsaugotą slaptažodį."; /* Confirm CTA displayed on modal asking for the user to update the password */ "autofill.update-password.save.CTA" = "Atnaujinti slaptažodį"; diff --git a/DuckDuckGo/lv.lproj/Localizable.strings b/DuckDuckGo/lv.lproj/Localizable.strings index f7d274b201..02d64bd141 100644 --- a/DuckDuckGo/lv.lproj/Localizable.strings +++ b/DuckDuckGo/lv.lproj/Localizable.strings @@ -529,6 +529,18 @@ /* Toast message when a login item without a title is deleted */ "autofill.logins.list.login-deleted-message-no-title" = "Pieteikšanās dati izdzēsti"; +/* Title for a button that allows a user to reset their list of never saved sites */ +"autofill.logins.list.never.saved" = "Atiestatīt izslēgtās vietnes"; + +/* Cancel button for resetting list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.cancel" = "Atcelt"; + +/* Confirm button to reset list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.confirm" = "Atiestatīt izslēgtās vietnes"; + +/* Alert title */ +"autofill.logins.list.never.saved.reset.action.title" = "Ja atiestatīsi izslēgtās vietnes, nākamreiz pierakstoties kādā no šīm vietnēm, tev tiks piedāvāts saglabāt savus pieteikšanās datus."; + /* Placeholder for search field on autofill login listing */ "autofill.logins.list.search-placeholder" = "Meklēt pieteikšanās datus"; @@ -563,7 +575,7 @@ "autofill.logins.prompt.password.button.title" = "%@ parole"; /* Title for autofill login prompt */ -"autofill.logins.prompt.title" = "Vai izmantot saglabātos pieteikšanās datus?"; +"autofill.logins.prompt.title" = "Izmantot saglabāto paroli?"; /* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ "autofill.logins.search.no-results.subtitle" = "meklējumam \"%@\""; @@ -613,27 +625,24 @@ /* Title for the alert dialog telling the user an updated username is no longer a private email address */ "autofill.removed.duck.address.title" = "Privātās Duck adreses lietotājvārds tika noņemts"; +/* CTA displayed on modal asking if the user never wants to be prompted to save a login for this website agin */ +"autofill.save-login.never-prompt.CTA" = "Nekad nejautāt par šo vietni"; + /* Message displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.message" = "Pieteikšanās dati tiek droši saglabāti tavā ierīcē, izvēlnē Pieteikšanās dati."; +"autofill.save-login.new-user.message" = "Paroles tiek droši saglabātas tavā ierīcē, izvēlnē Pieteikšanās dati."; /* Title displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.title" = "Vai vēlies, lai DuckDuckGo saglabātu tavus pieteikšanās datus?"; +"autofill.save-login.new-user.title" = "Vai vēlies, lai DuckDuckGo saglabātu tavu paroli?"; /* Cancel CTA displayed on modal asking for the user to save the login */ "autofill.save-login.not-now.CTA" = "Nesaglabāt"; -/* Confirm CTA displayed on modal asking for the user to save the login */ -"autofill.save-login.save.CTA" = "Saglabāt pieteikšanās datus"; - /* Title displayed on modal asking for the user to save the login */ "autofill.save-login.title" = "Saglabāt pieteikšanās datus?"; /* Confirm CTA displayed on modal asking for the user to save the password */ "autofill.save-password.save.CTA" = "Saglabāt paroli"; -/* Title displayed on modal asking for the user to save the password */ -"autofill.save-password.title" = "Saglabāt paroli?"; - /* Accessibility title for a Show Password button displaying actial password instead of ***** */ "autofill.show-password" = "Rādīt paroli"; @@ -641,7 +650,7 @@ "autofill.signin.to.manage" = "%@, lai pārvaldītu savas Duck adreses šajā ierīcē."; /* Message displayed on modal asking for the user to update the password */ -"autofill.update-password.message" = "DuckDuckGo atjauninās šos saglabātos pieteikšanās datus tavā ierīcē."; +"autofill.update-password.message" = "DuckDuckGo atjauninās tavā ierīcē saglabāto paroli."; /* Confirm CTA displayed on modal asking for the user to update the password */ "autofill.update-password.save.CTA" = "Atjaunināt paroli"; diff --git a/DuckDuckGo/nb.lproj/Localizable.strings b/DuckDuckGo/nb.lproj/Localizable.strings index 6193960e6e..5ace68b096 100644 --- a/DuckDuckGo/nb.lproj/Localizable.strings +++ b/DuckDuckGo/nb.lproj/Localizable.strings @@ -529,6 +529,18 @@ /* Toast message when a login item without a title is deleted */ "autofill.logins.list.login-deleted-message-no-title" = "Påloggingen er slettet"; +/* Title for a button that allows a user to reset their list of never saved sites */ +"autofill.logins.list.never.saved" = "Tilbakestill ekskluderte nettsteder"; + +/* Cancel button for resetting list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.cancel" = "Avbryt"; + +/* Confirm button to reset list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.confirm" = "Tilbakestill ekskluderte nettsteder"; + +/* Alert title */ +"autofill.logins.list.never.saved.reset.action.title" = "Hvis du tilbakestiller ekskluderte nettsteder, blir du bedt om å lagre påloggingsinformasjonen din neste gang du logger på disse nettstedene."; + /* Placeholder for search field on autofill login listing */ "autofill.logins.list.search-placeholder" = "Søk i pålogginger"; @@ -563,7 +575,7 @@ "autofill.logins.prompt.password.button.title" = "Passord for %@"; /* Title for autofill login prompt */ -"autofill.logins.prompt.title" = "Vil du bruke en lagret pålogging?"; +"autofill.logins.prompt.title" = "Vil du bruke et lagret passord?"; /* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ "autofill.logins.search.no-results.subtitle" = "for «%@»"; @@ -613,27 +625,24 @@ /* Title for the alert dialog telling the user an updated username is no longer a private email address */ "autofill.removed.duck.address.title" = "Brukernavn for privat Duck-adresse ble fjernet"; +/* CTA displayed on modal asking if the user never wants to be prompted to save a login for this website agin */ +"autofill.save-login.never-prompt.CTA" = "Aldri spør for dette nettstedet"; + /* Message displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.message" = "Pålogginger lagres trygt på enheten din i påloggingsmenyen."; +"autofill.save-login.new-user.message" = "Passord lagres trygt på enheten din i påloggingsmenyen."; /* Title displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.title" = "Vil du at DuckDuckGo skal lagre påloggingen din?"; +"autofill.save-login.new-user.title" = "Vil du at DuckDuckGo skal lagre passordet ditt?"; /* Cancel CTA displayed on modal asking for the user to save the login */ "autofill.save-login.not-now.CTA" = "Ikke lagre"; -/* Confirm CTA displayed on modal asking for the user to save the login */ -"autofill.save-login.save.CTA" = "Lagre påloggingen"; - /* Title displayed on modal asking for the user to save the login */ "autofill.save-login.title" = "Vil du lagre påloggingen?"; /* Confirm CTA displayed on modal asking for the user to save the password */ "autofill.save-password.save.CTA" = "Lagre passordet"; -/* Title displayed on modal asking for the user to save the password */ -"autofill.save-password.title" = "Vil du lagre passordet?"; - /* Accessibility title for a Show Password button displaying actial password instead of ***** */ "autofill.show-password" = "Vis passord"; @@ -641,7 +650,7 @@ "autofill.signin.to.manage" = "%@ for å administrere Duck-adressene dine på denne enheten."; /* Message displayed on modal asking for the user to update the password */ -"autofill.update-password.message" = "DuckDuckGo oppdaterer denne lagrede påloggingen på enheten din."; +"autofill.update-password.message" = "DuckDuckGo oppdaterer dette lagrede passordet på enheten din."; /* Confirm CTA displayed on modal asking for the user to update the password */ "autofill.update-password.save.CTA" = "Oppdater passordet"; diff --git a/DuckDuckGo/nl.lproj/Localizable.strings b/DuckDuckGo/nl.lproj/Localizable.strings index e7669b6136..0a52970964 100644 --- a/DuckDuckGo/nl.lproj/Localizable.strings +++ b/DuckDuckGo/nl.lproj/Localizable.strings @@ -529,6 +529,18 @@ /* Toast message when a login item without a title is deleted */ "autofill.logins.list.login-deleted-message-no-title" = "Aanmeldgegevens verwijderd"; +/* Title for a button that allows a user to reset their list of never saved sites */ +"autofill.logins.list.never.saved" = "Uitgesloten sites opnieuw instellen"; + +/* Cancel button for resetting list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.cancel" = "Annuleren"; + +/* Confirm button to reset list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.confirm" = "Uitgesloten sites opnieuw instellen"; + +/* Alert title */ +"autofill.logins.list.never.saved.reset.action.title" = "Als je uitgesloten sites opnieuw instelt, zie je de volgende keer dat je bij een van deze sites inlogt een melding om je inloggegevens op te slaan."; + /* Placeholder for search field on autofill login listing */ "autofill.logins.list.search-placeholder" = "Aanmeldgegevens zoeken"; @@ -563,7 +575,7 @@ "autofill.logins.prompt.password.button.title" = "Wachtwoord voor %@"; /* Title for autofill login prompt */ -"autofill.logins.prompt.title" = "Opgeslagen aanmeldgegevens gebruiken?"; +"autofill.logins.prompt.title" = "Een opgeslagen wachtwoord gebruiken?"; /* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ "autofill.logins.search.no-results.subtitle" = "voor '%@'"; @@ -613,27 +625,24 @@ /* Title for the alert dialog telling the user an updated username is no longer a private email address */ "autofill.removed.duck.address.title" = "De persoonlijke gebruikersnaam voor het Duck Address is verwijderd"; +/* CTA displayed on modal asking if the user never wants to be prompted to save a login for this website agin */ +"autofill.save-login.never-prompt.CTA" = "Nooit vragen voor deze site"; + /* Message displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.message" = "Aanmeldgegevens worden veilig opgeslagen op je apparaat in het menu 'Aanmeldingen'."; +"autofill.save-login.new-user.message" = "Wachtwoorden worden veilig opgeslagen op je apparaat in het menu 'Aanmeldingen'."; /* Title displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.title" = "Wil je dat DuckDuckGo je login opslaat?"; +"autofill.save-login.new-user.title" = "Wil je dat DuckDuckGo je wachtwoord opslaat?"; /* Cancel CTA displayed on modal asking for the user to save the login */ "autofill.save-login.not-now.CTA" = "Niet opslaan"; -/* Confirm CTA displayed on modal asking for the user to save the login */ -"autofill.save-login.save.CTA" = "Login opslaan"; - /* Title displayed on modal asking for the user to save the login */ "autofill.save-login.title" = "Login opslaan?"; /* Confirm CTA displayed on modal asking for the user to save the password */ "autofill.save-password.save.CTA" = "Wachtwoord opslaan"; -/* Title displayed on modal asking for the user to save the password */ -"autofill.save-password.title" = "Wachtwoord opslaan?"; - /* Accessibility title for a Show Password button displaying actial password instead of ***** */ "autofill.show-password" = "Wachtwoord weergeven"; @@ -641,7 +650,7 @@ "autofill.signin.to.manage" = "%@ om je Duck-adressen op dit apparaat te beheren."; /* Message displayed on modal asking for the user to update the password */ -"autofill.update-password.message" = "DuckDuckGo werkt deze opgeslagen aanmeldgegevens op je apparaat bij."; +"autofill.update-password.message" = "DuckDuckGo werkt dit opgeslagen wachtwoord op je apparaat bij."; /* Confirm CTA displayed on modal asking for the user to update the password */ "autofill.update-password.save.CTA" = "Wachtwoord bijwerken"; diff --git a/DuckDuckGo/pl.lproj/Localizable.strings b/DuckDuckGo/pl.lproj/Localizable.strings index 29a6530843..a9577094e3 100644 --- a/DuckDuckGo/pl.lproj/Localizable.strings +++ b/DuckDuckGo/pl.lproj/Localizable.strings @@ -529,6 +529,18 @@ /* Toast message when a login item without a title is deleted */ "autofill.logins.list.login-deleted-message-no-title" = "Login usunięty"; +/* Title for a button that allows a user to reset their list of never saved sites */ +"autofill.logins.list.never.saved" = "Resetowanie wykluczonych witryn"; + +/* Cancel button for resetting list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.cancel" = "Anuluj"; + +/* Confirm button to reset list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.confirm" = "Resetowanie wykluczonych witryn"; + +/* Alert title */ +"autofill.logins.list.never.saved.reset.action.title" = "Jeśli zresetujesz wykluczone witryny, przy następnym logowaniu do dowolnej z nich pojawi się monit o zapisanie danych logowania."; + /* Placeholder for search field on autofill login listing */ "autofill.logins.list.search-placeholder" = "Wyszukiwanie loginów"; @@ -563,7 +575,7 @@ "autofill.logins.prompt.password.button.title" = "Hasło %@"; /* Title for autofill login prompt */ -"autofill.logins.prompt.title" = "Czy chcesz użyć zapisanego loginu?"; +"autofill.logins.prompt.title" = "Użyć zapisanego hasła?"; /* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ "autofill.logins.search.no-results.subtitle" = "dla frazy: %@"; @@ -613,27 +625,24 @@ /* Title for the alert dialog telling the user an updated username is no longer a private email address */ "autofill.removed.duck.address.title" = "Nazwa użytkownika prywatnego adresu Duck Address została usunięta"; +/* CTA displayed on modal asking if the user never wants to be prompted to save a login for this website agin */ +"autofill.save-login.never-prompt.CTA" = "Nigdy nie pytaj o tę witrynę"; + /* Message displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.message" = "Loginy są bezpiecznie przechowywane na Twoim urządzeniu w menu Loginy."; +"autofill.save-login.new-user.message" = "Hasła są bezpiecznie przechowywane na Twoim urządzeniu w menu Loginy."; /* Title displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.title" = "Czy chcesz zapisać dane logowania w DuckDuckGo?"; +"autofill.save-login.new-user.title" = "Czy chcesz zapisać hasło w DuckDuckGo?"; /* Cancel CTA displayed on modal asking for the user to save the login */ "autofill.save-login.not-now.CTA" = "Nie zapisuj"; -/* Confirm CTA displayed on modal asking for the user to save the login */ -"autofill.save-login.save.CTA" = "Zapisz logowanie"; - /* Title displayed on modal asking for the user to save the login */ "autofill.save-login.title" = "Zapisać logowanie?"; /* Confirm CTA displayed on modal asking for the user to save the password */ "autofill.save-password.save.CTA" = "Zapisz hasło"; -/* Title displayed on modal asking for the user to save the password */ -"autofill.save-password.title" = "Zapisać hasło?"; - /* Accessibility title for a Show Password button displaying actial password instead of ***** */ "autofill.show-password" = "Pokaż hasło"; @@ -641,7 +650,7 @@ "autofill.signin.to.manage" = "%@, aby zarządzać adresami Duck Address na tym urządzeniu."; /* Message displayed on modal asking for the user to update the password */ -"autofill.update-password.message" = "DuckDuckGo zaktualizuje ten zapisany login na Twoim urządzeniu."; +"autofill.update-password.message" = "DuckDuckGo zaktualizuje to zapisane hasło na Twoim urządzeniu."; /* Confirm CTA displayed on modal asking for the user to update the password */ "autofill.update-password.save.CTA" = "Aktualizuj hasło"; diff --git a/DuckDuckGo/pt.lproj/Localizable.strings b/DuckDuckGo/pt.lproj/Localizable.strings index 7f1f5eddb8..929e1ca91a 100644 --- a/DuckDuckGo/pt.lproj/Localizable.strings +++ b/DuckDuckGo/pt.lproj/Localizable.strings @@ -529,6 +529,18 @@ /* Toast message when a login item without a title is deleted */ "autofill.logins.list.login-deleted-message-no-title" = "Início de sessão eliminado"; +/* Title for a button that allows a user to reset their list of never saved sites */ +"autofill.logins.list.never.saved" = "Repor sites excluídos"; + +/* Cancel button for resetting list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.cancel" = "Cancelar"; + +/* Confirm button to reset list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.confirm" = "Repor sites excluídos"; + +/* Alert title */ +"autofill.logins.list.never.saved.reset.action.title" = "Se repuseres os sites excluídos, ser-te-á pedido que guardes os teus dados de início de sessão da próxima vez que iniciares sessão num destes sites."; + /* Placeholder for search field on autofill login listing */ "autofill.logins.list.search-placeholder" = "Pesquisar inícios de sessão"; @@ -563,7 +575,7 @@ "autofill.logins.prompt.password.button.title" = "Palavra-passe para % @"; /* Title for autofill login prompt */ -"autofill.logins.prompt.title" = "Utilizar um início de sessão guardado?"; +"autofill.logins.prompt.title" = "Usar uma palavra-passe guardada?"; /* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ "autofill.logins.search.no-results.subtitle" = "para \"%@\""; @@ -613,27 +625,24 @@ /* Title for the alert dialog telling the user an updated username is no longer a private email address */ "autofill.removed.duck.address.title" = "O nome de utilizador privado do Duck Address foi removido"; +/* CTA displayed on modal asking if the user never wants to be prompted to save a login for this website agin */ +"autofill.save-login.never-prompt.CTA" = "Nunca pedir para este site"; + /* Message displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.message" = "Os dados de início de sessão são armazenados de forma segura no teu dispositivo no menu Inícios de sessão."; +"autofill.save-login.new-user.message" = "As palavras-passe são armazenadas de forma segura no teu dispositivo no menu Inícios de sessão."; /* Title displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.title" = "Queres que o DuckDuckGo guarde o teu início de sessão?"; +"autofill.save-login.new-user.title" = "Queres que o DuckDuckGo guarde a tua palavra-passe?"; /* Cancel CTA displayed on modal asking for the user to save the login */ "autofill.save-login.not-now.CTA" = "Não guardes"; -/* Confirm CTA displayed on modal asking for the user to save the login */ -"autofill.save-login.save.CTA" = "Guardar início de sessão"; - /* Title displayed on modal asking for the user to save the login */ "autofill.save-login.title" = "Guardar início de sessão?"; /* Confirm CTA displayed on modal asking for the user to save the password */ "autofill.save-password.save.CTA" = "Guardar palavra-passe"; -/* Title displayed on modal asking for the user to save the password */ -"autofill.save-password.title" = "Guardar palavra-passe?"; - /* Accessibility title for a Show Password button displaying actial password instead of ***** */ "autofill.show-password" = "Mostrar palavra-passe"; @@ -641,7 +650,7 @@ "autofill.signin.to.manage" = "%@ para gerires os teus Duck Addresses neste dispositivo."; /* Message displayed on modal asking for the user to update the password */ -"autofill.update-password.message" = "O DuckDuckGo vai atualizar este início de sessão armazenado no teu dispositivo."; +"autofill.update-password.message" = "O DuckDuckGo vai atualizar esta palavra-passe armazenada no teu dispositivo."; /* Confirm CTA displayed on modal asking for the user to update the password */ "autofill.update-password.save.CTA" = "Atualizar palavra-passe"; diff --git a/DuckDuckGo/ro.lproj/Localizable.strings b/DuckDuckGo/ro.lproj/Localizable.strings index 313a252957..0064a3f2b3 100644 --- a/DuckDuckGo/ro.lproj/Localizable.strings +++ b/DuckDuckGo/ro.lproj/Localizable.strings @@ -529,6 +529,18 @@ /* Toast message when a login item without a title is deleted */ "autofill.logins.list.login-deleted-message-no-title" = "Date de conectare șterse"; +/* Title for a button that allows a user to reset their list of never saved sites */ +"autofill.logins.list.never.saved" = "Resetează site-urile excluse"; + +/* Cancel button for resetting list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.cancel" = "Renunță"; + +/* Confirm button to reset list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.confirm" = "Resetează site-urile excluse"; + +/* Alert title */ +"autofill.logins.list.never.saved.reset.action.title" = "Dacă resetezi site-urile excluse, ți se va cere să îți salvezi datele de conectare data viitoare când te conectezi la oricare dintre aceste site-uri."; + /* Placeholder for search field on autofill login listing */ "autofill.logins.list.search-placeholder" = "Date de autentificare pentru căutare"; @@ -563,7 +575,7 @@ "autofill.logins.prompt.password.button.title" = "Parola pentru %@"; /* Title for autofill login prompt */ -"autofill.logins.prompt.title" = "Folosești datele de conectare salvate?"; +"autofill.logins.prompt.title" = "Folosești o parolă salvată?"; /* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ "autofill.logins.search.no-results.subtitle" = "pentru „%@”"; @@ -613,27 +625,24 @@ /* Title for the alert dialog telling the user an updated username is no longer a private email address */ "autofill.removed.duck.address.title" = "Numele de utilizator pentru Duck Address privată a fost eliminat"; +/* CTA displayed on modal asking if the user never wants to be prompted to save a login for this website agin */ +"autofill.save-login.never-prompt.CTA" = "Nu solicita niciodată pentru acest site"; + /* Message displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.message" = "Conexiunile sunt stocate în siguranță pe dispozitivul dvs. în meniul Conectări."; +"autofill.save-login.new-user.message" = "Parolele sunt stocate în siguranță pe dispozitivul dvs. în meniul Autentificări."; /* Title displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.title" = "Dorești ca DuckDuckGo să îți salveze datele de autentificare?"; +"autofill.save-login.new-user.title" = "Dorești ca DuckDuckGo să-ți salveze parola?"; /* Cancel CTA displayed on modal asking for the user to save the login */ "autofill.save-login.not-now.CTA" = "Nu salva"; -/* Confirm CTA displayed on modal asking for the user to save the login */ -"autofill.save-login.save.CTA" = "Salvează autentificarea"; - /* Title displayed on modal asking for the user to save the login */ "autofill.save-login.title" = "Salvezi autentificarea?"; /* Confirm CTA displayed on modal asking for the user to save the password */ "autofill.save-password.save.CTA" = "Salvează parola"; -/* Title displayed on modal asking for the user to save the password */ -"autofill.save-password.title" = "Salvezi parola?"; - /* Accessibility title for a Show Password button displaying actial password instead of ***** */ "autofill.show-password" = "Arată parola"; @@ -641,7 +650,7 @@ "autofill.signin.to.manage" = "%@ pentru a-ți gestiona adresele Duck Address pe acest dispozitiv."; /* Message displayed on modal asking for the user to update the password */ -"autofill.update-password.message" = "DuckDuckGo va actualiza aceste date de conectare stocate pe dispozitivul tău."; +"autofill.update-password.message" = "DuckDuckGo va actualiza această parolă stocată pe dispozitivul tău."; /* Confirm CTA displayed on modal asking for the user to update the password */ "autofill.update-password.save.CTA" = "Actualizează parola"; diff --git a/DuckDuckGo/ru.lproj/Localizable.strings b/DuckDuckGo/ru.lproj/Localizable.strings index 4c33e53f36..4b79bf5001 100644 --- a/DuckDuckGo/ru.lproj/Localizable.strings +++ b/DuckDuckGo/ru.lproj/Localizable.strings @@ -529,6 +529,18 @@ /* Toast message when a login item without a title is deleted */ "autofill.logins.list.login-deleted-message-no-title" = "Логин удален"; +/* Title for a button that allows a user to reset their list of never saved sites */ +"autofill.logins.list.never.saved" = "Сбросить список исключений"; + +/* Cancel button for resetting list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.cancel" = "Отменить"; + +/* Confirm button to reset list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.confirm" = "Сбросить список исключений"; + +/* Alert title */ +"autofill.logins.list.never.saved.reset.action.title" = "В случае сброса списка исключений, при следующем входе на любой из этих сайтов вам предложат сохранить свои учетные данные."; + /* Placeholder for search field on autofill login listing */ "autofill.logins.list.search-placeholder" = "Поиск логинов"; @@ -563,7 +575,7 @@ "autofill.logins.prompt.password.button.title" = "Пароль %@"; /* Title for autofill login prompt */ -"autofill.logins.prompt.title" = "Использовать сохраненный логин?"; +"autofill.logins.prompt.title" = "Использовать сохраненный пароль?"; /* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ "autofill.logins.search.no-results.subtitle" = "по запросу «%@»"; @@ -613,27 +625,24 @@ /* Title for the alert dialog telling the user an updated username is no longer a private email address */ "autofill.removed.duck.address.title" = "Приватное имя пользователя Duck Address удалено"; +/* CTA displayed on modal asking if the user never wants to be prompted to save a login for this website agin */ +"autofill.save-login.never-prompt.CTA" = "Больше не спрашивать на этом сайте"; + /* Message displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.message" = "Учетные данные надежно хранятся на вашем устройстве в меню «Логины»."; +"autofill.save-login.new-user.message" = "Пароли надежно хранятся на вашем устройстве в меню «Логины»."; /* Title displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.title" = "Хотите, чтобы DuckDuckGo сохранил логин?"; +"autofill.save-login.new-user.title" = "Хотите, чтобы DuckDuckGo сохранил ваш пароль?"; /* Cancel CTA displayed on modal asking for the user to save the login */ "autofill.save-login.not-now.CTA" = "Не сохранять"; -/* Confirm CTA displayed on modal asking for the user to save the login */ -"autofill.save-login.save.CTA" = "Сохранить логин"; - /* Title displayed on modal asking for the user to save the login */ "autofill.save-login.title" = "Сохранить логин?"; /* Confirm CTA displayed on modal asking for the user to save the password */ "autofill.save-password.save.CTA" = "Сохранить пароль"; -/* Title displayed on modal asking for the user to save the password */ -"autofill.save-password.title" = "Сохранить пароль?"; - /* Accessibility title for a Show Password button displaying actial password instead of ***** */ "autofill.show-password" = "Показать пароль"; @@ -641,7 +650,7 @@ "autofill.signin.to.manage" = "%@ для управления адресами Duck Address с этого устройства."; /* Message displayed on modal asking for the user to update the password */ -"autofill.update-password.message" = "DuckDuckGo обновит логин, сохраненный на вашем устройстве."; +"autofill.update-password.message" = "DuckDuckGo обновит пароль, сохраненный на вашем устройстве."; /* Confirm CTA displayed on modal asking for the user to update the password */ "autofill.update-password.save.CTA" = "Обновить пароль"; diff --git a/DuckDuckGo/sk.lproj/Localizable.strings b/DuckDuckGo/sk.lproj/Localizable.strings index 234ca6884d..2cc71be60f 100644 --- a/DuckDuckGo/sk.lproj/Localizable.strings +++ b/DuckDuckGo/sk.lproj/Localizable.strings @@ -529,6 +529,18 @@ /* Toast message when a login item without a title is deleted */ "autofill.logins.list.login-deleted-message-no-title" = "Prihlasovacie údaje boli odstránené"; +/* Title for a button that allows a user to reset their list of never saved sites */ +"autofill.logins.list.never.saved" = "Obnovenie vylúčených lokalít"; + +/* Cancel button for resetting list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.cancel" = "Zrušiť"; + +/* Confirm button to reset list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.confirm" = "Obnovenie vylúčených lokalít"; + +/* Alert title */ +"autofill.logins.list.never.saved.reset.action.title" = "Ak obnovíte vylúčené lokality, pri ďalšom prihlásení na niektorú z týchto lokalít dostanete výzvu na uloženie prihlasovacích údajov."; + /* Placeholder for search field on autofill login listing */ "autofill.logins.list.search-placeholder" = "Vyhľadávanie prihlásení"; @@ -563,7 +575,7 @@ "autofill.logins.prompt.password.button.title" = "Heslo pre %@"; /* Title for autofill login prompt */ -"autofill.logins.prompt.title" = "Použiť uložené prihlasovacie údaje?"; +"autofill.logins.prompt.title" = "Použiť uložené heslo?"; /* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ "autofill.logins.search.no-results.subtitle" = "pre „%@”"; @@ -613,27 +625,24 @@ /* Title for the alert dialog telling the user an updated username is no longer a private email address */ "autofill.removed.duck.address.title" = "Používateľské meno Private Duck Address bolo odstránené"; +/* CTA displayed on modal asking if the user never wants to be prompted to save a login for this website agin */ +"autofill.save-login.never-prompt.CTA" = "Nikdy sa nepýtať na túto stránku"; + /* Message displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.message" = "Prihlasovacie údaje sú bezpečne uložené v zariadení v ponuke Prihlásenia."; +"autofill.save-login.new-user.message" = "Heslá sú bezpečne uložené na vašom zariadení v ponuke Prihlásenia."; /* Title displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.title" = "Chcete, aby DuckDuckGo uložil vaše prihlasovacie údaje?"; +"autofill.save-login.new-user.title" = "Chcete, aby DuckDuckGo uložil vaše heslo?"; /* Cancel CTA displayed on modal asking for the user to save the login */ "autofill.save-login.not-now.CTA" = "Neukladať"; -/* Confirm CTA displayed on modal asking for the user to save the login */ -"autofill.save-login.save.CTA" = "Uložiť prihlasovacie údaje"; - /* Title displayed on modal asking for the user to save the login */ "autofill.save-login.title" = "Uložiť prihlasovacie údaje?"; /* Confirm CTA displayed on modal asking for the user to save the password */ "autofill.save-password.save.CTA" = "Uložiť heslo"; -/* Title displayed on modal asking for the user to save the password */ -"autofill.save-password.title" = "Uložiť heslo?"; - /* Accessibility title for a Show Password button displaying actial password instead of ***** */ "autofill.show-password" = "Zobraziť heslo"; @@ -641,7 +650,7 @@ "autofill.signin.to.manage" = "%@ na správu vašich Duck adries na tomto zariadení."; /* Message displayed on modal asking for the user to update the password */ -"autofill.update-password.message" = "DuckDuckGo bude aktualizovať tieto uložené prihlasovacie údaje vo vašom zariadení."; +"autofill.update-password.message" = "DuckDuckGo aktualizuje toto uložené heslo vo vašom zariadení."; /* Confirm CTA displayed on modal asking for the user to update the password */ "autofill.update-password.save.CTA" = "Aktualizovať heslo"; diff --git a/DuckDuckGo/sl.lproj/Localizable.strings b/DuckDuckGo/sl.lproj/Localizable.strings index 81eb46dbb6..47190ef484 100644 --- a/DuckDuckGo/sl.lproj/Localizable.strings +++ b/DuckDuckGo/sl.lproj/Localizable.strings @@ -529,6 +529,18 @@ /* Toast message when a login item without a title is deleted */ "autofill.logins.list.login-deleted-message-no-title" = "Prijava je izbrisana"; +/* Title for a button that allows a user to reset their list of never saved sites */ +"autofill.logins.list.never.saved" = "Ponastavi izključena spletna mesta"; + +/* Cancel button for resetting list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.cancel" = "Prekliči"; + +/* Confirm button to reset list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.confirm" = "Ponastavi izključena spletna mesta"; + +/* Alert title */ +"autofill.logins.list.never.saved.reset.action.title" = "Če ponastavite izključena spletna mesta, boste ob naslednji prijavi na katero koli od teh spletnih mest pozvani, da shranite svojo prijavo."; + /* Placeholder for search field on autofill login listing */ "autofill.logins.list.search-placeholder" = "Iskanje podatkov za prijavo"; @@ -563,7 +575,7 @@ "autofill.logins.prompt.password.button.title" = "Geslo za %@"; /* Title for autofill login prompt */ -"autofill.logins.prompt.title" = "Želite uporabiti shranjene podatke za prijavo?"; +"autofill.logins.prompt.title" = "Želite uporabiti shranjeno geslo?"; /* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ "autofill.logins.search.no-results.subtitle" = "za »%@«"; @@ -613,27 +625,24 @@ /* Title for the alert dialog telling the user an updated username is no longer a private email address */ "autofill.removed.duck.address.title" = "Uporabniško ime za zasebni naslov Duck Address je bilo odstranjeno"; +/* CTA displayed on modal asking if the user never wants to be prompted to save a login for this website agin */ +"autofill.save-login.never-prompt.CTA" = "Nikoli ne vprašaj za to spletno mesto"; + /* Message displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.message" = "Prijave so varno shranjene v vaši napravi v meniju Prijave."; +"autofill.save-login.new-user.message" = "Gesla so varno shranjena v napravi v meniju Prijave."; /* Title displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.title" = "Ali želite, da DuckDuckGo shrani vašo prijavo?"; +"autofill.save-login.new-user.title" = "Ali želite, da DuckDuckGo shrani vaše geslo?"; /* Cancel CTA displayed on modal asking for the user to save the login */ "autofill.save-login.not-now.CTA" = "Ne shrani"; -/* Confirm CTA displayed on modal asking for the user to save the login */ -"autofill.save-login.save.CTA" = "Shrani prijavo"; - /* Title displayed on modal asking for the user to save the login */ "autofill.save-login.title" = "Želite shraniti prijavo?"; /* Confirm CTA displayed on modal asking for the user to save the password */ "autofill.save-password.save.CTA" = "Shrani geslo"; -/* Title displayed on modal asking for the user to save the password */ -"autofill.save-password.title" = "Želite shraniti geslo?"; - /* Accessibility title for a Show Password button displaying actial password instead of ***** */ "autofill.show-password" = "Prikaži geslo"; @@ -641,7 +650,7 @@ "autofill.signin.to.manage" = "%@ za upravljanje naslovov Duck Address v tej napravi."; /* Message displayed on modal asking for the user to update the password */ -"autofill.update-password.message" = "DuckDuckGo bo posodobil to shranjeno prijavo v vaši napravi."; +"autofill.update-password.message" = "DuckDuckGo bo posodobil to shranjeno geslo v vaši napravi."; /* Confirm CTA displayed on modal asking for the user to update the password */ "autofill.update-password.save.CTA" = "Posodobitev gesla"; diff --git a/DuckDuckGo/sv.lproj/Localizable.strings b/DuckDuckGo/sv.lproj/Localizable.strings index b2549b8d22..8cd3fdbc47 100644 --- a/DuckDuckGo/sv.lproj/Localizable.strings +++ b/DuckDuckGo/sv.lproj/Localizable.strings @@ -529,6 +529,18 @@ /* Toast message when a login item without a title is deleted */ "autofill.logins.list.login-deleted-message-no-title" = "Inloggning raderad"; +/* Title for a button that allows a user to reset their list of never saved sites */ +"autofill.logins.list.never.saved" = "Återställ exkluderade webbplatser"; + +/* Cancel button for resetting list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.cancel" = "Avbryt"; + +/* Confirm button to reset list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.confirm" = "Återställ exkluderade webbplatser"; + +/* Alert title */ +"autofill.logins.list.never.saved.reset.action.title" = "Om du återställer exkluderade webbplatser kommer du att uppmanas att spara din inloggning nästa gång du loggar in på någon av dessa webbplatser."; + /* Placeholder for search field on autofill login listing */ "autofill.logins.list.search-placeholder" = "Sök inloggningar"; @@ -563,7 +575,7 @@ "autofill.logins.prompt.password.button.title" = "Lösenord för %@"; /* Title for autofill login prompt */ -"autofill.logins.prompt.title" = "Använd sparad inloggning?"; +"autofill.logins.prompt.title" = "Vill du använda ett sparat lösenord?"; /* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ "autofill.logins.search.no-results.subtitle" = "för ”%@”"; @@ -613,27 +625,24 @@ /* Title for the alert dialog telling the user an updated username is no longer a private email address */ "autofill.removed.duck.address.title" = "Användarnamn för privat Duck Address har tagits bort"; +/* CTA displayed on modal asking if the user never wants to be prompted to save a login for this website agin */ +"autofill.save-login.never-prompt.CTA" = "Fråga aldrig för den här webbplatsen"; + /* Message displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.message" = "Inloggningar lagras säkert på din enhet i menyn Inloggningar."; +"autofill.save-login.new-user.message" = "Lösenord lagras säkert på din enhet i menyn Inloggningar."; /* Title displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.title" = "Vill du att DuckDuckGo ska spara din inloggning?"; +"autofill.save-login.new-user.title" = "Vill du att DuckDuckGo ska spara ditt lösenord?"; /* Cancel CTA displayed on modal asking for the user to save the login */ "autofill.save-login.not-now.CTA" = "Spara inte"; -/* Confirm CTA displayed on modal asking for the user to save the login */ -"autofill.save-login.save.CTA" = "Spara inloggning"; - /* Title displayed on modal asking for the user to save the login */ "autofill.save-login.title" = "Spara inloggning?"; /* Confirm CTA displayed on modal asking for the user to save the password */ "autofill.save-password.save.CTA" = "Spara lösenord"; -/* Title displayed on modal asking for the user to save the password */ -"autofill.save-password.title" = "Spara lösenord?"; - /* Accessibility title for a Show Password button displaying actial password instead of ***** */ "autofill.show-password" = "Visa lösenord"; @@ -641,7 +650,7 @@ "autofill.signin.to.manage" = "%@ för att hantera Duck Addresses på denna enhet."; /* Message displayed on modal asking for the user to update the password */ -"autofill.update-password.message" = "DuckDuckGo uppdaterar den här lagrade inloggningen på din enhet."; +"autofill.update-password.message" = "DuckDuckGo kommer att uppdatera det lagrade lösenordet på din enhet."; /* Confirm CTA displayed on modal asking for the user to update the password */ "autofill.update-password.save.CTA" = "Uppdatera lösenord"; diff --git a/DuckDuckGo/tr.lproj/Localizable.strings b/DuckDuckGo/tr.lproj/Localizable.strings index 1b5077a154..1b87ef3f5d 100644 --- a/DuckDuckGo/tr.lproj/Localizable.strings +++ b/DuckDuckGo/tr.lproj/Localizable.strings @@ -529,6 +529,18 @@ /* Toast message when a login item without a title is deleted */ "autofill.logins.list.login-deleted-message-no-title" = "Giriş bilgileri silindi"; +/* Title for a button that allows a user to reset their list of never saved sites */ +"autofill.logins.list.never.saved" = "Hariç Tutulan Siteleri Sıfırla"; + +/* Cancel button for resetting list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.cancel" = "İptal"; + +/* Confirm button to reset list of never saved sites */ +"autofill.logins.list.never.saved.reset.action.confirm" = "Hariç Tutulan Siteleri Sıfırla"; + +/* Alert title */ +"autofill.logins.list.never.saved.reset.action.title" = "Hariç tutulan siteleri sıfırlarsanız, bu sitelerden herhangi birinde bir sonraki oturum açışınızda Giriş bilgilerinizi kaydetmeniz istenecektir."; + /* Placeholder for search field on autofill login listing */ "autofill.logins.list.search-placeholder" = "Giriş Ara"; @@ -563,7 +575,7 @@ "autofill.logins.prompt.password.button.title" = "%@ için parola"; /* Title for autofill login prompt */ -"autofill.logins.prompt.title" = "Kayıtlı Giriş kullanılsın mı?"; +"autofill.logins.prompt.title" = "Kayıtlı bir şifre mi kullanıyorsunuz?"; /* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ "autofill.logins.search.no-results.subtitle" = "\"%@\" için"; @@ -613,27 +625,24 @@ /* Title for the alert dialog telling the user an updated username is no longer a private email address */ "autofill.removed.duck.address.title" = "Özel Duck Address kullanıcı adı kaldırıldı"; +/* CTA displayed on modal asking if the user never wants to be prompted to save a login for this website agin */ +"autofill.save-login.never-prompt.CTA" = "Bu Site için Hiçbir Zaman Sorma"; + /* Message displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.message" = "Giriş bilgileri cihazınızdaki Giriş Bilgileri menüsünde güvenli bir şekilde saklanır."; +"autofill.save-login.new-user.message" = "Şifreler cihazınızdaki Oturum Açma menüsünde güvenli bir şekilde saklanır."; /* Title displayed on modal asking for the user to save the login for the first time */ -"autofill.save-login.new-user.title" = "DuckDuckGo'nun Girişinizi kaydetmesini istiyor musunuz?"; +"autofill.save-login.new-user.title" = "DuckDuckGo'nun şifrenizi kaydetmesini istiyor musunuz?"; /* Cancel CTA displayed on modal asking for the user to save the login */ "autofill.save-login.not-now.CTA" = "Kaydetme"; -/* Confirm CTA displayed on modal asking for the user to save the login */ -"autofill.save-login.save.CTA" = "Girişi Kaydet"; - /* Title displayed on modal asking for the user to save the login */ "autofill.save-login.title" = "Giriş Kaydedilsin mi?"; /* Confirm CTA displayed on modal asking for the user to save the password */ "autofill.save-password.save.CTA" = "Şifre Kaydet"; -/* Title displayed on modal asking for the user to save the password */ -"autofill.save-password.title" = "Şifre Kaydedilsin mi?"; - /* Accessibility title for a Show Password button displaying actial password instead of ***** */ "autofill.show-password" = "Parolayı göster"; @@ -641,7 +650,7 @@ "autofill.signin.to.manage" = "Bu cihazdaki Duck Address'leri yönetmek için %@."; /* Message displayed on modal asking for the user to update the password */ -"autofill.update-password.message" = "DuckDuckGo, cihazınızdaki bu kayıtlı Giriş bilgisini güncelleyecektir."; +"autofill.update-password.message" = "DuckDuckGo bu kayıtlı şifreyi cihazınızda güncelleyecektir."; /* Confirm CTA displayed on modal asking for the user to update the password */ "autofill.update-password.save.CTA" = "Şifreyi Güncelle"; diff --git a/DuckDuckGoTests/AutofillLoginListViewModelTests.swift b/DuckDuckGoTests/AutofillLoginListViewModelTests.swift index cd6ff8c211..bf6d6eace3 100644 --- a/DuckDuckGoTests/AutofillLoginListViewModelTests.swift +++ b/DuckDuckGoTests/AutofillLoginListViewModelTests.swift @@ -31,6 +31,18 @@ class AutofillLoginListViewModelTests: XCTestCase { private let tld = TLD() private let appSettings = AppUserDefaults() private let vault = (try? MockSecureVaultFactory.makeVault(errorReporter: nil))! + private var manager: AutofillNeverPromptWebsitesManager! + + override func setUpWithError() throws { + try super.setUpWithError() + manager = AutofillNeverPromptWebsitesManager(secureVault: vault) + } + + override func tearDownWithError() throws { + manager = nil + + try super.tearDownWithError() + } func testWhenOneLoginDeletedWithNoSuggestionsThenAlphabeticalSectionIsDeleted() { let accountIdToDelete = "1" @@ -38,7 +50,7 @@ class AutofillLoginListViewModelTests: XCTestCase { SecureVaultModels.WebsiteAccount(id: accountIdToDelete, title: nil, username: "", domain: "testsite.com", created: Date(), lastUpdated: Date()) ] - let model = AutofillLoginListViewModel(appSettings: appSettings, tld: tld, secureVault: vault) + let model = AutofillLoginListViewModel(appSettings: appSettings, tld: tld, secureVault: vault, autofillNeverPromptWebsitesManager: manager) let tableContentsToDelete = model.tableContentsToDelete(accountId: accountIdToDelete) XCTAssertEqual(tableContentsToDelete.sectionsToDelete.count, 1) XCTAssertEqual(tableContentsToDelete.rowsToDelete.count, 0) @@ -52,7 +64,7 @@ class AutofillLoginListViewModelTests: XCTestCase { SecureVaultModels.WebsiteAccount(id: "3", title: nil, username: "", domain: "testsite3.com", created: Date(), lastUpdated: Date()) ] - let model = AutofillLoginListViewModel(appSettings: appSettings, tld: tld, secureVault: vault) + let model = AutofillLoginListViewModel(appSettings: appSettings, tld: tld, secureVault: vault, autofillNeverPromptWebsitesManager: manager) let tableContentsToDelete = model.tableContentsToDelete(accountId: accountIdToDelete) XCTAssertEqual(tableContentsToDelete.sectionsToDelete.count, 0) XCTAssertEqual(tableContentsToDelete.rowsToDelete.count, 1) @@ -100,6 +112,31 @@ class AutofillLoginListViewModelTests: XCTestCase { XCTAssertEqual(tableContentsToDelete.sectionsToDelete.count, 0) XCTAssertEqual(tableContentsToDelete.rowsToDelete.count, 2) } + + func testWhenNoNeverPromptWebsitesSavedThenNeverPromptSectionIsNotShown() { + XCTAssertTrue(manager.deleteAllNeverPromptWebsites()) + let model = AutofillLoginListViewModel(appSettings: appSettings, tld: tld, secureVault: vault, autofillNeverPromptWebsitesManager: manager) + XCTAssertEqual(model.rowsInSection(0), 1) + } + + func testWhenOneNeverPromptWebsiteSavedThenNeverPromptSectionIsShown() { + XCTAssertTrue(manager.deleteAllNeverPromptWebsites()) + XCTAssertNoThrow(try manager.saveNeverPromptWebsite("example.com")) + let model = AutofillLoginListViewModel(appSettings: appSettings, tld: tld, secureVault: vault, autofillNeverPromptWebsitesManager: manager) + XCTAssertEqual(model.rowsInSection(0), 2) + } + + func testWhenManyNeverPromptWebsiteSavedThenNeverPromptSectionIsShown() { + XCTAssertTrue(manager.deleteAllNeverPromptWebsites()) + XCTAssertNoThrow(try manager.saveNeverPromptWebsite("example.com")) + XCTAssertNoThrow(try manager.saveNeverPromptWebsite("example.co.uk")) + XCTAssertNoThrow(try manager.saveNeverPromptWebsite("duckduckgo.com")) + XCTAssertNoThrow(try manager.saveNeverPromptWebsite("daxisawesome.com")) + XCTAssertNoThrow(try manager.saveNeverPromptWebsite("123domain.com")) + + let model = AutofillLoginListViewModel(appSettings: appSettings, tld: tld, secureVault: vault, autofillNeverPromptWebsitesManager: manager) + XCTAssertEqual(model.rowsInSection(0), 2) + } } class AutofillLoginListSectionTypeTests: XCTestCase { diff --git a/DuckDuckGoTests/AutofillNeverPromptWebsitesManagerTests.swift b/DuckDuckGoTests/AutofillNeverPromptWebsitesManagerTests.swift new file mode 100644 index 0000000000..cea49d96c2 --- /dev/null +++ b/DuckDuckGoTests/AutofillNeverPromptWebsitesManagerTests.swift @@ -0,0 +1,85 @@ +// +// AutofillNeverPromptWebsitesManagerTests.swift +// DuckDuckGo +// +// Copyright © 2023 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 XCTest + +@testable import DuckDuckGo +import BrowserServicesKit + +final class AutofillNeverPromptWebsitesManagerTests: XCTestCase { + + private var manager: AutofillNeverPromptWebsitesManager! + private let vault = (try? MockSecureVaultFactory.makeVault(errorReporter: nil))! + + override func setUpWithError() throws { + try super.setUpWithError() + manager = AutofillNeverPromptWebsitesManager(secureVault: vault) + } + + override func tearDownWithError() throws { + manager = nil + + try super.tearDownWithError() + } + + func testWhenSavingNeverPromptWebsiteThenHasNeverPromptWebsiteForDomain() throws { + let domain = "example.com" + _ = try manager.saveNeverPromptWebsite(domain) + + let result = manager.hasNeverPromptWebsitesFor(domain: domain) + + XCTAssertTrue(result) + } + + func testWhenMultipleNeverPromptWebsitesThenHasNeverPromptWebsiteForDomain() { + XCTAssertTrue(manager.deleteAllNeverPromptWebsites()) + + XCTAssertNoThrow(try manager.saveNeverPromptWebsite("example.com")) + XCTAssertNoThrow(try manager.saveNeverPromptWebsite("sub.example.com")) + XCTAssertNoThrow(try manager.saveNeverPromptWebsite("anotherdomain.com")) + + XCTAssertEqual(manager.neverPromptWebsites.count, 3) + XCTAssertTrue(manager.hasNeverPromptWebsitesFor(domain: "example.com")) + } + + func testWhenDeletingAllNeverPromptWebsitesTheAllNeverPromptWebsitesDeleted() { + XCTAssertTrue(manager.deleteAllNeverPromptWebsites()) + + let domain = "example.com" + XCTAssertNoThrow(try manager.saveNeverPromptWebsite(domain)) + XCTAssertEqual(manager.neverPromptWebsites.count, 1) + + XCTAssertTrue(manager.deleteAllNeverPromptWebsites()) + XCTAssertEqual(manager.neverPromptWebsites.count, 0) + } + + func testWhenNoNeverPromptWebsitesForDomainThenNoHasNeverPromptWebsitesForDomain() { + let domain = "example.com" + XCTAssertTrue(manager.deleteAllNeverPromptWebsites()) + XCTAssertFalse(manager.hasNeverPromptWebsitesFor(domain: domain)) + } + + func testWhenSaveNeverPromptWebsiteThatAlreadyExistsThenHasNeverPromptWebsiteForDomain() { + let domain = "example.com" + XCTAssertNoThrow(try manager.saveNeverPromptWebsite(domain)) + XCTAssertNoThrow(try manager.saveNeverPromptWebsite(domain)) + XCTAssertTrue(manager.hasNeverPromptWebsitesFor(domain: "example.com")) + } + +} diff --git a/DuckDuckGoTests/MockDependencyProvider.swift b/DuckDuckGoTests/MockDependencyProvider.swift index e16288eeb9..7676843d3c 100644 --- a/DuckDuckGoTests/MockDependencyProvider.swift +++ b/DuckDuckGoTests/MockDependencyProvider.swift @@ -34,6 +34,7 @@ class MockDependencyProvider: DependencyProvider { var voiceSearchHelper: VoiceSearchHelperProtocol var downloadManager: DownloadManager var autofillLoginSession: AutofillLoginSession + var autofillNeverPromptWebsitesManager: AutofillNeverPromptWebsitesManager var configurationManager: ConfigurationManager init() { @@ -48,6 +49,7 @@ class MockDependencyProvider: DependencyProvider { voiceSearchHelper = defaultProvider.voiceSearchHelper downloadManager = defaultProvider.downloadManager autofillLoginSession = defaultProvider.autofillLoginSession + autofillNeverPromptWebsitesManager = defaultProvider.autofillNeverPromptWebsitesManager configurationManager = defaultProvider.configurationManager } } diff --git a/DuckDuckGoTests/MockSecureVault.swift b/DuckDuckGoTests/MockSecureVault.swift index 9949ea064a..9dfc62644f 100644 --- a/DuckDuckGoTests/MockSecureVault.swift +++ b/DuckDuckGoTests/MockSecureVault.swift @@ -44,6 +44,7 @@ final class MockSecureVault: AutofillSecureVault { var storedAccounts: [SecureVaultModels.WebsiteAccount] = [] var storedCredentials: [Int64: SecureVaultModels.WebsiteCredentials] = [:] + var storedNeverPromptWebsites = [SecureVaultModels.NeverPromptWebsites]() var storedNotes: [SecureVaultModels.Note] = [] var storedIdentities: [SecureVaultModels.Identity] = [] var storedCards: [SecureVaultModels.CreditCard] = [] @@ -99,6 +100,29 @@ final class MockSecureVault: AutofillSecureVault { storedCredentials[accountId] = nil } + func neverPromptWebsites() throws -> [SecureVaultModels.NeverPromptWebsites] { + return storedNeverPromptWebsites + } + + func hasNeverPromptWebsitesFor(domain: String) throws -> Bool { + return !storedNeverPromptWebsites.filter { $0.domain == domain }.isEmpty + } + + func storeNeverPromptWebsites(_ neverPromptWebsite: SecureVaultModels.NeverPromptWebsites) throws -> Int64 { + if let neverPromptWebsiteId = neverPromptWebsite.id { + storedNeverPromptWebsites.append(neverPromptWebsite) + return neverPromptWebsiteId + } else { + storedNeverPromptWebsites.append(neverPromptWebsite) + return -1 + } + + } + + func deleteAllNeverPromptWebsites() throws { + storedNeverPromptWebsites = [] + } + func notes() throws -> [SecureVaultModels.Note] { return storedNotes } @@ -203,6 +227,8 @@ class MockDatabaseProvider: AutofillDatabaseProvider { var _forDomain = [String]() var _credentialsDict = [Int64: SecureVaultModels.WebsiteCredentials]() var _note: SecureVaultModels.Note? + var _neverPromptWebsites = [SecureVaultModels.NeverPromptWebsites]() + var db: GRDB.DatabaseWriter // swiftlint:enable identifier_name @@ -247,6 +273,33 @@ class MockDatabaseProvider: AutofillDatabaseProvider { return _accounts } + func neverPromptWebsites() throws -> [SecureVaultModels.NeverPromptWebsites] { + return _neverPromptWebsites + } + + func hasNeverPromptWebsitesFor(domain: String) throws -> Bool { + return false + } + + func storeNeverPromptWebsite(_ neverPromptWebsite: SecureVaultModels.NeverPromptWebsites) throws -> Int64 { + if let neverPromptWebsiteId = neverPromptWebsite.id { + _neverPromptWebsites.append(neverPromptWebsite) + return neverPromptWebsiteId + } else { + return -1 + } + } + + func deleteAllNeverPromptWebsites() throws { + _neverPromptWebsites.removeAll() + } + + func updateNeverPromptWebsite(_ neverPromptWebsite: SecureVaultModels.NeverPromptWebsites) throws { + } + + func insertNeverPromptWebsite(_ neverPromptWebsite: SecureVaultModels.NeverPromptWebsites) throws { + } + func notes() throws -> [SecureVaultModels.Note] { return _notes } From 743f3fac88b224fc48c7cd52c87caa9f572f8583 Mon Sep 17 00:00:00 2001 From: Sam Symons Date: Thu, 16 Nov 2023 12:54:26 -0800 Subject: [PATCH 04/10] Document LinkPresentation usage (#2172) Task/Issue URL: https://app.asana.com/0/414235014887631/1205931087930998/f Tech Design URL: CC: @ayoy Description: This PR adds a comment to the LinkPresentation usage. --- DuckDuckGo/Favicons.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DuckDuckGo/Favicons.swift b/DuckDuckGo/Favicons.swift index 74487c3585..ceda1bf9d3 100644 --- a/DuckDuckGo/Favicons.swift +++ b/DuckDuckGo/Favicons.swift @@ -381,6 +381,8 @@ public class Favicons { return } + /// DuckDuckGo Privacy Browser uses built-in functionality from iOS to fetch the highest quality favicons for your bookmarks and favorites. + /// This functionality uses a user agent that is different from other network requests made by the app in order to find the best favicon available. let metadataFetcher = LPMetadataProvider() let completion: (LPLinkMetadata?, Error?) -> Void = { metadata, metadataError in guard let iconProvider = metadata?.iconProvider, metadataError == nil else { From 89e8c618e6f5b3d9f1b38b60f622a6c00b76cbd5 Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Fri, 17 Nov 2023 00:00:47 +0100 Subject: [PATCH 05/10] Updates BSK --- DuckDuckGo.xcodeproj/project.pbxproj | 4 ++-- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index df675a8b52..b68847d517 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -9142,8 +9142,8 @@ isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/DuckDuckGo/BrowserServicesKit"; requirement = { - kind = exactVersion; - version = 84.1.0; + kind = revision; + revision = 7fec563329fce91afaa705fa4e04753353411c2f; }; }; C14882EB27F211A000D59F0C /* XCRemoteSwiftPackageReference "SwiftSoup" */ = { diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 5c2f7dbb33..694cd3eea2 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -15,8 +15,8 @@ "repositoryURL": "https://github.com/DuckDuckGo/BrowserServicesKit", "state": { "branch": null, - "revision": "641018cef1a3a13e9fdeb490b18639d1cb25569f", - "version": "84.1.0" + "revision": "7fec563329fce91afaa705fa4e04753353411c2f", + "version": null } }, { From 6eb65d332f00f58bf23e19a4ac63cbcaadefacb1 Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Fri, 17 Nov 2023 00:02:47 +0100 Subject: [PATCH 06/10] Updates BSK --- DuckDuckGo.xcodeproj/project.pbxproj | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index b68847d517..35ddce3bce 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -9143,7 +9143,7 @@ repositoryURL = "https://github.com/DuckDuckGo/BrowserServicesKit"; requirement = { kind = revision; - revision = 7fec563329fce91afaa705fa4e04753353411c2f; + revision = 8233956d88a5ab6b14ab603ac6e907ec220c0df9; }; }; C14882EB27F211A000D59F0C /* XCRemoteSwiftPackageReference "SwiftSoup" */ = { diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 694cd3eea2..624b9dc24a 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -15,7 +15,7 @@ "repositoryURL": "https://github.com/DuckDuckGo/BrowserServicesKit", "state": { "branch": null, - "revision": "7fec563329fce91afaa705fa4e04753353411c2f", + "revision": "8233956d88a5ab6b14ab603ac6e907ec220c0df9", "version": null } }, From c7e5bf5bfacd511316ebab3e5411bca20f26acb1 Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Fri, 17 Nov 2023 00:04:04 +0100 Subject: [PATCH 07/10] Rolls back a BSK change by mistake --- DuckDuckGo.xcodeproj/project.pbxproj | 4 ++-- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 35ddce3bce..df675a8b52 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -9142,8 +9142,8 @@ isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/DuckDuckGo/BrowserServicesKit"; requirement = { - kind = revision; - revision = 8233956d88a5ab6b14ab603ac6e907ec220c0df9; + kind = exactVersion; + version = 84.1.0; }; }; C14882EB27F211A000D59F0C /* XCRemoteSwiftPackageReference "SwiftSoup" */ = { diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 624b9dc24a..5c2f7dbb33 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -15,8 +15,8 @@ "repositoryURL": "https://github.com/DuckDuckGo/BrowserServicesKit", "state": { "branch": null, - "revision": "8233956d88a5ab6b14ab603ac6e907ec220c0df9", - "version": null + "revision": "641018cef1a3a13e9fdeb490b18639d1cb25569f", + "version": "84.1.0" } }, { From efa39b4263f22aba06cef08a33be031933bea98c Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Fri, 17 Nov 2023 02:34:27 +0100 Subject: [PATCH 08/10] Updates BSK (#2173) --- DuckDuckGo.xcodeproj/project.pbxproj | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index df675a8b52..41659805c7 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -9143,7 +9143,7 @@ repositoryURL = "https://github.com/DuckDuckGo/BrowserServicesKit"; requirement = { kind = exactVersion; - version = 84.1.0; + version = 84.1.1; }; }; C14882EB27F211A000D59F0C /* XCRemoteSwiftPackageReference "SwiftSoup" */ = { diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 5c2f7dbb33..a9e3205a3a 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -15,8 +15,8 @@ "repositoryURL": "https://github.com/DuckDuckGo/BrowserServicesKit", "state": { "branch": null, - "revision": "641018cef1a3a13e9fdeb490b18639d1cb25569f", - "version": "84.1.0" + "revision": "b97c451037f7a24aef6389be8252df301d2294cd", + "version": "84.1.1" } }, { From 1809630cc4f44899bdb8dc61104f7d5cf3459718 Mon Sep 17 00:00:00 2001 From: Lorenzo Mattei Date: Fri, 17 Nov 2023 12:55:21 +0100 Subject: [PATCH 09/10] Update email protection e2e test to match the new UI (#2170) --- .maestro/release_tests/emailprotection.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.maestro/release_tests/emailprotection.yaml b/.maestro/release_tests/emailprotection.yaml index 67b41ef000..e4cc61fba4 100644 --- a/.maestro/release_tests/emailprotection.yaml +++ b/.maestro/release_tests/emailprotection.yaml @@ -17,7 +17,7 @@ tags: - scroll - scroll - assertVisible: Email Protection -- tapOn: Email Protection, Block email trackers and hide your address +- tapOn: Email Protection - assertVisible: id: searchEntry - assertVisible: https://duckduckgo.com/email/ From 3bddbca2ca7d0f0b6c0553136fb82fe694944280 Mon Sep 17 00:00:00 2001 From: Christopher Brind Date: Fri, 17 Nov 2023 12:32:11 +0000 Subject: [PATCH 10/10] fix pass kit related crash on iPad (#2171) --- DuckDuckGo/FilePreviewHelper.swift | 5 ++++- DuckDuckGo/PassKitPreviewHelper.swift | 5 +++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/DuckDuckGo/FilePreviewHelper.swift b/DuckDuckGo/FilePreviewHelper.swift index f13b508379..f8f4009311 100644 --- a/DuckDuckGo/FilePreviewHelper.swift +++ b/DuckDuckGo/FilePreviewHelper.swift @@ -33,7 +33,10 @@ struct FilePreviewHelper { static func canAutoPreviewMIMEType(_ mimeType: MIMEType) -> Bool { switch mimeType { - case .reality, .usdz, .passbook, .calendar: + case .passbook: + return UIDevice.current.userInterfaceIdiom == .phone + + case .reality, .usdz, .calendar: return true default: return false diff --git a/DuckDuckGo/PassKitPreviewHelper.swift b/DuckDuckGo/PassKitPreviewHelper.swift index 6b95cbe2e6..3a734eee03 100644 --- a/DuckDuckGo/PassKitPreviewHelper.swift +++ b/DuckDuckGo/PassKitPreviewHelper.swift @@ -34,8 +34,9 @@ class PassKitPreviewHelper: FilePreview { do { let data = try Data(contentsOf: self.filePath) let pass = try PKPass(data: data) - let controller = PKAddPassesViewController(pass: pass)! - viewController?.present(controller, animated: true) + if let controller = PKAddPassesViewController(pass: pass) { + viewController?.present(controller, animated: true) + } } catch { os_log("Can't present passkit: %s", type: .debug, error.localizedDescription) }