diff --git a/AutofillCredentialProvider/AutofillCredentialProvider.entitlements b/AutofillCredentialProvider/AutofillCredentialProvider.entitlements index b50ab55a01..f7959669d1 100644 --- a/AutofillCredentialProvider/AutofillCredentialProvider.entitlements +++ b/AutofillCredentialProvider/AutofillCredentialProvider.entitlements @@ -3,6 +3,16 @@ com.apple.developer.authentication-services.autofill-credential-provider - + + com.apple.security.application-groups + + $(GROUP_ID_PREFIX).vault + $(GROUP_ID_PREFIX).bookmarks + + keychain-access-groups + + $(AppIdentifierPrefix)$(APP_ID) + $(AppIdentifierPrefix)$(VAULT_APP_GROUP) + diff --git a/AutofillCredentialProvider/CredentialProvider/CredentialProviderActivation/CredentialProviderActivatedView.swift b/AutofillCredentialProvider/CredentialProvider/CredentialProviderActivation/CredentialProviderActivatedView.swift index 1f6a32564b..fe36f9e3b2 100644 --- a/AutofillCredentialProvider/CredentialProvider/CredentialProviderActivation/CredentialProviderActivatedView.swift +++ b/AutofillCredentialProvider/CredentialProvider/CredentialProviderActivation/CredentialProviderActivatedView.swift @@ -49,12 +49,6 @@ struct CredentialProviderActivatedView: View { .padding(.top, 16) .multilineTextAlignment(.center) - Text(UserText.credentialProviderActivatedSubtitle) - .daxBodyRegular() - .foregroundColor(Color(designSystemColor: .textSecondary)) - .padding(.top, 8) - .multilineTextAlignment(.center) - Spacer() Button { @@ -67,7 +61,7 @@ struct CredentialProviderActivatedView: View { } .padding(.horizontal, 24) - .navigationBarItems(trailing: Button(UserText.actionCancel) { + .navigationBarItems(trailing: Button(UserText.actionDone) { viewModel.dismiss() }) } diff --git a/AutofillCredentialProvider/CredentialProvider/CredentialProviderActivation/CredentialProviderActivatedViewModel.swift b/AutofillCredentialProvider/CredentialProvider/CredentialProviderActivation/CredentialProviderActivatedViewModel.swift index 759683d555..bdf4eba455 100644 --- a/AutofillCredentialProvider/CredentialProvider/CredentialProviderActivation/CredentialProviderActivatedViewModel.swift +++ b/AutofillCredentialProvider/CredentialProvider/CredentialProviderActivation/CredentialProviderActivatedViewModel.swift @@ -18,6 +18,7 @@ // import Foundation +import Core struct CredentialProviderActivatedViewModel { @@ -30,10 +31,12 @@ struct CredentialProviderActivatedViewModel { } func dismiss() { + Pixel.fire(pixel: .autofillExtensionWelcomeDismiss) completion?(false) } func launchDDGApp() { + Pixel.fire(pixel: .autofillExtensionWelcomeLaunchApp) completion?(true) } } diff --git a/AutofillCredentialProvider/CredentialProvider/CredentialProviderList/CredentialProviderListItemTableViewCell.swift b/AutofillCredentialProvider/CredentialProvider/CredentialProviderList/CredentialProviderListItemTableViewCell.swift index 2e659cc21e..a0701ec178 100644 --- a/AutofillCredentialProvider/CredentialProvider/CredentialProviderList/CredentialProviderListItemTableViewCell.swift +++ b/AutofillCredentialProvider/CredentialProvider/CredentialProviderList/CredentialProviderListItemTableViewCell.swift @@ -24,7 +24,9 @@ import DesignResourcesKit class CredentialProviderListItemTableViewCell: UITableViewCell { static var reuseIdentifier = "CredentialProviderListItemTableViewCell" - + + var disclosureButtonTapped: (() -> Void)? + private lazy var titleLabel: UILabel = { let label = UILabel(frame: CGRect.zero) label.font = .preferredFont(forTextStyle: .callout) @@ -64,7 +66,23 @@ class CredentialProviderListItemTableViewCell: UITableViewCell { stackView.alignment = .center return stackView }() - + + private lazy var disclosureButton: UIButton = { + let button = UIButton(type: .system) + let image = UIImage(systemName: "chevron.forward") + let boldImage = image?.withConfiguration(UIImage.SymbolConfiguration(pointSize: 11, weight: .bold)) + button.setImage(boldImage, for: .normal) + button.tintColor = UIColor.tertiaryLabel + button.addTarget(self, action: #selector(handleDisclosureButtonTap), for: .touchUpInside) + + let buttonSize: CGFloat = 44 + button.frame = CGRect(x: 0, y: 0, width: buttonSize, height: buttonSize) + button.contentHorizontalAlignment = .center + button.contentVerticalAlignment = .center + + return button + }() + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) installSubviews() @@ -85,22 +103,29 @@ class CredentialProviderListItemTableViewCell: UITableViewCell { private func installSubviews() { contentView.addSubview(contentStackView) + contentView.addSubview(disclosureButton) installConstraints() } private func installConstraints() { contentStackView.translatesAutoresizingMaskIntoConstraints = false iconImageView.translatesAutoresizingMaskIntoConstraints = false - + disclosureButton.translatesAutoresizingMaskIntoConstraints = false + let imageSize: CGFloat = 32 let margins = contentView.layoutMarginsGuide NSLayoutConstraint.activate([ iconImageView.widthAnchor.constraint(equalToConstant: imageSize), iconImageView.heightAnchor.constraint(equalToConstant: imageSize), - + + disclosureButton.widthAnchor.constraint(equalToConstant: 44), + disclosureButton.heightAnchor.constraint(equalToConstant: 44), + disclosureButton.centerYAnchor.constraint(equalTo: margins.centerYAnchor), + disclosureButton.trailingAnchor.constraint(equalTo: margins.trailingAnchor, constant: 16), + contentStackView.leadingAnchor.constraint(equalTo: margins.leadingAnchor), - contentStackView.trailingAnchor.constraint(equalTo: margins.trailingAnchor), + contentStackView.trailingAnchor.constraint(equalTo: disclosureButton.leadingAnchor, constant: -12), contentStackView.topAnchor.constraint(equalTo: margins.topAnchor), contentStackView.bottomAnchor.constraint(equalTo: margins.bottomAnchor) ]) @@ -109,7 +134,7 @@ class CredentialProviderListItemTableViewCell: UITableViewCell { private func setupContentView(with item: AutofillLoginItem) { titleLabel.text = item.title subtitleLabel.text = item.subtitle - iconImageView.image = loadImageFromCache(forDomain: item.account.domain) + iconImageView.image = FaviconHelper.loadImageFromCache(forDomain: item.account.domain, preferredFakeFaviconLetters: item.preferredFaviconLetters) } override func layoutSubviews() { @@ -118,67 +143,9 @@ class CredentialProviderListItemTableViewCell: UITableViewCell { separatorInset = UIEdgeInsets(top: 0, left: contentView.layoutMargins.left + textStackView.frame.origin.x, bottom: 0, right: 0) } - - - private func loadImageFromCache(forDomain domain: String?) -> UIImage? { - guard let domain = domain, - let cacheUrl = FaviconsCacheType.fireproof.cacheLocation() else { return nil } - - let key = FaviconHasher.createHash(ofDomain: domain) - // Slight leap here to avoid loading Kingisher as a library for the widgets. - // Once dependency management is fixed, link it and use Favicons directly. - let imageUrl = cacheUrl.appendingPathComponent("com.onevcat.Kingfisher.ImageCache.fireproof").appendingPathComponent(key) - - guard let data = (try? Data(contentsOf: imageUrl)) else { - let image = createFakeFavicon(forDomain: domain, size: 32, backgroundColor: UIColor.forDomain(domain), preferredFakeFaviconLetters: item?.preferredFaviconLetters) - return image - } - - return UIImage(data: data)?.toSRGB() - } - - private func createFakeFavicon(forDomain domain: String, - size: CGFloat = 192, - backgroundColor: UIColor = UIColor.red, - bold: Bool = true, - preferredFakeFaviconLetters: String? = nil, - letterCount: Int = 2) -> UIImage? { - - let cornerRadius = size * 0.125 - let imageRect = CGRect(x: 0, y: 0, width: size, height: size) - let padding = size * 0.16 - let labelFrame = CGRect(x: padding, y: padding, width: imageRect.width - (2 * padding), height: imageRect.height - (2 * padding)) - - let renderer = UIGraphicsImageRenderer(size: imageRect.size) - let icon = renderer.image { imageContext in - let context = imageContext.cgContext - - context.setFillColor(backgroundColor.cgColor) - context.addPath(CGPath(roundedRect: imageRect, cornerWidth: cornerRadius, cornerHeight: cornerRadius, transform: nil)) - context.fillPath() - - let label = UILabel(frame: labelFrame) - label.numberOfLines = 1 - label.adjustsFontSizeToFitWidth = true - label.minimumScaleFactor = 0.1 - label.baselineAdjustment = .alignCenters - label.font = bold ? UIFont.boldSystemFont(ofSize: size) : UIFont.systemFont(ofSize: size) - label.textColor = .white - label.textAlignment = .center - - if let prefferedPrefix = preferredFakeFaviconLetters?.droppingWwwPrefix().prefix(letterCount).capitalized { - label.text = prefferedPrefix - } else { - label.text = item?.preferredFaviconLetters.capitalized ?? "#" - } - - context.translateBy(x: padding, y: padding) - - label.layer.draw(in: context) - } - - return icon.withRenderingMode(.alwaysOriginal) + @objc private func handleDisclosureButtonTap() { + disclosureButtonTapped?() } - + } diff --git a/AutofillCredentialProvider/CredentialProvider/CredentialProviderList/CredentialProviderListViewController.swift b/AutofillCredentialProvider/CredentialProvider/CredentialProviderList/CredentialProviderListViewController.swift index e0d0e8eaff..6094773e0c 100644 --- a/AutofillCredentialProvider/CredentialProvider/CredentialProviderList/CredentialProviderListViewController.swift +++ b/AutofillCredentialProvider/CredentialProvider/CredentialProviderList/CredentialProviderListViewController.swift @@ -21,13 +21,17 @@ import UIKit import AuthenticationServices import BrowserServicesKit import Combine +import Common import Core import SwiftUI final class CredentialProviderListViewController: UIViewController { private let viewModel: CredentialProviderListViewModel + private let shouldProvideTextToInsert: Bool + private let tld: TLD private let onRowSelected: (AutofillLoginItem) -> Void + private let onTextProvided: (String) -> Void private let onDismiss: () -> Void private var cancellables: Set = [] @@ -80,21 +84,35 @@ final class CredentialProviderListViewController: UIViewController { constant: (tableView.frame.height / 2)) }() - init(serviceIdentifiers: [ASCredentialServiceIdentifier], secureVault: (any AutofillSecureVault)?, credentialIdentityStoreManager: AutofillCredentialIdentityStoreManaging, + shouldProvideTextToInsert: Bool, + tld: TLD, onRowSelected: @escaping (AutofillLoginItem) -> Void, + onTextProvided: @escaping (String) -> Void, onDismiss: @escaping () -> Void) { self.viewModel = CredentialProviderListViewModel(serviceIdentifiers: serviceIdentifiers, secureVault: secureVault, - credentialIdentityStoreManager: credentialIdentityStoreManager) + credentialIdentityStoreManager: credentialIdentityStoreManager, + tld: tld) + self.shouldProvideTextToInsert = shouldProvideTextToInsert + self.tld = tld self.onRowSelected = onRowSelected + self.onTextProvided = onTextProvided self.onDismiss = onDismiss super.init(nibName: nil, bundle: nil) - authenticate() + if #available(iOS 18.0, *) { + authenticate() + } else { + // pre-iOS 18.0 authentication can fail silently if extension is loaded twice in quick succession + // if authenticate is called without a slight delay + DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { [weak self] in + self?.authenticate() + } + } } required init?(coder: NSCoder) { @@ -106,6 +124,10 @@ final class CredentialProviderListViewController: UIViewController { title = UserText.credentialProviderListTitle + if let itemPrompt = viewModel.serviceIdentifierPromptLabel { + navigationItem.prompt = itemPrompt + } + let doneItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneTapped)) navigationItem.rightBarButtonItem = doneItem @@ -117,6 +139,8 @@ final class CredentialProviderListViewController: UIViewController { registerForKeyboardNotifications() navigationItem.searchController = searchController + + Pixel.fire(pixel: .autofillExtensionPasswordsOpened) } override func viewWillDisappear(_ animated: Bool) { @@ -156,19 +180,17 @@ final class CredentialProviderListViewController: UIViewController { } private func authenticate() { - DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { [weak self] in - self?.viewModel.authenticate {[weak self] error in - guard let self = self else { return } - - if error != nil { - if error != .noAuthAvailable { - self.onDismiss() - } else { - let alert = UIAlertController.makeDeviceAuthenticationAlert { [weak self] in - self?.onDismiss() - } - present(alert, animated: true) + viewModel.authenticate {[weak self] error in + guard let self = self else { return } + + if error != nil { + if error != .noAuthAvailable { + self.onDismiss() + } else { + let alert = UIAlertController.makeDeviceAuthenticationAlert { [weak self] in + self?.onDismiss() } + present(alert, animated: true) } } } @@ -270,6 +292,7 @@ final class CredentialProviderListViewController: UIViewController { @objc private func doneTapped() { onDismiss() + Pixel.fire(pixel: .autofillExtensionPasswordsDismissed) } } @@ -293,6 +316,11 @@ extension CredentialProviderListViewController: UITableViewDataSource { } cell.item = items[indexPath.row] cell.backgroundColor = UIColor(designSystemColor: .surface) + + cell.disclosureButtonTapped = { [weak self] in + let item = items[indexPath.row] + self?.presentDetailsForCredentials(item: item) + } return cell default: return UITableViewCell() @@ -312,6 +340,14 @@ extension CredentialProviderListViewController: UITableViewDataSource { viewModel.viewState == .showItems ? UILocalizedIndexedCollation.current().sectionIndexTitles : [] } + private func presentDetailsForCredentials(item: AutofillLoginItem) { + let detailViewController = CredentialProviderListDetailsViewController(account: item.account, + tld: tld, + shouldProvideTextToInsert: self.shouldProvideTextToInsert) + detailViewController.delegate = self + + self.navigationController?.pushViewController(detailViewController, animated: true) + } } extension CredentialProviderListViewController: UITableViewDelegate { @@ -321,9 +357,14 @@ extension CredentialProviderListViewController: UITableViewDelegate { switch viewModel.sections[indexPath.section] { case .suggestions(_, items: let items), .credentials(_, let items): let item = items[indexPath.row] - onRowSelected(item) + if shouldProvideTextToInsert { + presentDetailsForCredentials(item: item) + } else { + onRowSelected(item) + Pixel.fire(pixel: .autofillExtensionPasswordSelected) + } default: - break + return } } @@ -378,5 +419,12 @@ extension CredentialProviderListViewController { (tableView.frame.height / 2) - searchController.searchBar.frame.height ) } +} + +extension CredentialProviderListViewController: CredentialProviderListDetailsViewControllerDelegate { + + func credentialProviderListDetailsViewControllerDidProvideText(_ controller: CredentialProviderListDetailsViewController, text: String) { + onTextProvided(text) + } } diff --git a/AutofillCredentialProvider/CredentialProvider/CredentialProviderList/CredentialProviderListViewModel.swift b/AutofillCredentialProvider/CredentialProvider/CredentialProviderList/CredentialProviderListViewModel.swift index 40664022a6..1b0ab0c601 100644 --- a/AutofillCredentialProvider/CredentialProvider/CredentialProviderList/CredentialProviderListViewModel.swift +++ b/AutofillCredentialProvider/CredentialProvider/CredentialProviderList/CredentialProviderListViewModel.swift @@ -36,7 +36,13 @@ final class CredentialProviderListViewModel: ObservableObject { case searchingNoResults } - var isSearching: Bool = false + var isSearching: Bool = false { + didSet { + if oldValue != isSearching, isSearching { + Pixel.fire(pixel: .autofillExtensionPasswordsSearch) + } + } + } var authenticationNotRequired = false private let serviceIdentifiers: [ASCredentialServiceIdentifier] @@ -45,7 +51,7 @@ final class CredentialProviderListViewModel: ObservableObject { private var accounts = [SecureVaultModels.WebsiteAccount]() private var accountsToSuggest = [SecureVaultModels.WebsiteAccount]() private var cancellables: Set = [] - private let tld: TLD = TLD() + private let tld: TLD private let autofillDomainNameUrlMatcher = AutofillDomainNameUrlMatcher() private let autofillDomainNameUrlSort = AutofillDomainNameUrlSort() @@ -55,6 +61,13 @@ final class CredentialProviderListViewModel: ObservableObject { return !accounts.isEmpty } + var serviceIdentifierPromptLabel: String? { + guard let identifier = serviceIdentifiers.first?.identifier else { + return nil + } + return String(format: UserText.credentialProviderListPrompt, autofillDomainNameUrlMatcher.normalizeUrlForWeb(identifier)) + } + @Published private(set) var viewState: CredentialProviderListViewModel.ViewState = .authLocked @Published private(set) var sections = [AutofillLoginListSectionType]() { didSet { @@ -64,10 +77,12 @@ final class CredentialProviderListViewModel: ObservableObject { init(serviceIdentifiers: [ASCredentialServiceIdentifier], secureVault: (any AutofillSecureVault)?, - credentialIdentityStoreManager: AutofillCredentialIdentityStoreManaging) { + credentialIdentityStoreManager: AutofillCredentialIdentityStoreManaging, + tld: TLD) { self.serviceIdentifiers = serviceIdentifiers self.secureVault = secureVault self.credentialIdentityStoreManager = credentialIdentityStoreManager + self.tld = tld if let count = getAccountsCount() { authenticationNotRequired = count == 0 diff --git a/AutofillCredentialProvider/CredentialProvider/CredentialProviderListDetails/CredentialProviderListDetailsView.swift b/AutofillCredentialProvider/CredentialProvider/CredentialProviderListDetails/CredentialProviderListDetailsView.swift new file mode 100644 index 0000000000..ae2a9113ce --- /dev/null +++ b/AutofillCredentialProvider/CredentialProvider/CredentialProviderListDetails/CredentialProviderListDetailsView.swift @@ -0,0 +1,359 @@ +// +// CredentialProviderListDetailsView.swift +// DuckDuckGo +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import SwiftUI +import DuckUI +import DesignResourcesKit + +struct CredentialProviderListDetailsView: View { + + @ObservedObject var viewModel: CredentialProviderListDetailsViewModel + + var body: some View { + listWithBackground + } + + @ViewBuilder + private var listWithBackground: some View { + if #available(iOS 16.0, *) { + list + .scrollContentBackground(.hidden) + .background(Color(designSystemColor: .background)) + } else { + list + .background(Color(designSystemColor: .background)) + } + } + + private var list: some View { + List { + viewingContentView + } + .simultaneousGesture( + DragGesture().onChanged({_ in + viewModel.selectedCell = nil + })) + .listStyle(.insetGrouped) + } + + private var viewingContentView: some View { + Group { + Section { + Header(viewModel: viewModel.headerViewModel) + } + + Section { + usernameCell() + .onTapGesture { + if viewModel.shouldProvideTextToInsert { + viewModel.textToReturn(.username) + } + } + + passwordCell() + .onTapGesture { + if viewModel.shouldProvideTextToInsert { + viewModel.textToReturn(.password) + } + } + } + + Section { + addressCell() + } + + Section { + notesCell() + } + } + } + + private func usernameCell() -> some View { + CopyableCell(title: UserText.credentialProviderDetailsUsername, + subtitle: viewModel.usernameDisplayString, + selectedCell: $viewModel.selectedCell, + buttonImageName: "Copy-24", + buttonAccessibilityLabel: UserText.credentialProviderDetailsCopyPrompt(for: UserText.credentialProviderDetailsUsername), + buttonAction: { viewModel.copyToPasteboard(.username) }) + } + + private func passwordCell() -> some View { + CopyableCell(title: UserText.credentialProviderDetailsPassword, + subtitle: viewModel.userVisiblePassword, + selectedCell: $viewModel.selectedCell, + isMonospaced: true, + buttonImageName: viewModel.isPasswordHidden ? "Eye-24" : "Eye-Closed-24", + buttonAccessibilityLabel: viewModel.isPasswordHidden ? UserText.credentialProviderDetailsShowPassword : UserText.credentialProviderDetailsHidePassword, + buttonAction: { viewModel.isPasswordHidden.toggle() }, + secondaryButtonImageName: "Copy-24", + secondaryButtonAccessibilityLabel: UserText.credentialProviderDetailsCopyPrompt(for: UserText.credentialProviderDetailsPassword), + secondaryButtonAction: { viewModel.copyToPasteboard(.password) }) + } + + private func addressCell() -> some View { + CopyableCell(title: UserText.credentialProviderDetailsAddress, + subtitle: viewModel.address, + selectedCell: $viewModel.selectedCell, + truncationMode: .middle, + buttonImageName: "Copy-24", + buttonAccessibilityLabel: UserText.credentialProviderDetailsCopyPrompt(for: UserText.credentialProviderDetailsAddress), + buttonAction: { viewModel.copyToPasteboard(.address) }) + } + + private func notesCell() -> some View { + CopyableCell(title: UserText.credentialProviderDetailsNotes, + subtitle: viewModel.notes, + selectedCell: $viewModel.selectedCell, + truncationMode: .middle, + multiLine: true) + } + +} + +private struct Header: View { + + @Environment(\.colorScheme) private var colorScheme + + private struct Constants { + static let imageSize: CGFloat = 32 + static let horizontalStackSpacing: CGFloat = 12 + static let verticalStackSpacing: CGFloat = 1 + static let viewHeight: CGFloat = 60 + static let insets = EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16) + } + + var viewModel: CredentialProviderListDetailsHeaderViewModel + + var body: some View { + HStack(spacing: Constants.horizontalStackSpacing) { + Image(uiImage: viewModel.favicon) + .resizable() + .cornerRadius(4) + .scaledToFit() + .frame(width: Constants.imageSize, height: Constants.imageSize) + .accessibilityHidden(true) + + VStack(alignment: .leading, spacing: Constants.verticalStackSpacing) { + Text(viewModel.title) + .font(.callout) + .foregroundColor(colorScheme == .light ? .gray90 : .white) + .truncationMode(.middle) + .lineLimit(1) + + Text(viewModel.subtitle) + .font(.footnote) + .foregroundColor(colorScheme == .light ? .gray50 : .gray20) + } + + Spacer() + } + .frame(minHeight: Constants.viewHeight) + .frame(maxWidth: .infinity) + .contentShape(Rectangle()) + .listRowBackground(Color(designSystemColor: .surface)) + .listRowInsets(Constants.insets) + } +} + +private struct CopyableCell: View { + @State private var id = UUID() + let title: String + let subtitle: String + @Binding var selectedCell: UUID? + var truncationMode: Text.TruncationMode = .tail + var multiLine: Bool = false + var isMonospaced: Bool = false + + var buttonImageName: String? + var buttonAccessibilityLabel: String? + var buttonAction: (() -> Void)? + + var secondaryButtonImageName: String? + var secondaryButtonAccessibilityLabel: String? + var secondaryButtonAction: (() -> Void)? + + var shouldProvideTextToInsertAction: (() -> Void)? + + var body: some View { + ZStack { + HStack { + VStack(alignment: .leading, spacing: Constants.verticalPadding) { + Text(title) + .label4Style() + HStack { + if multiLine { + Text(subtitle) + .label4Style(design: isMonospaced ? .monospaced : .default, + foregroundColorLight: ForegroundColor(isSelected: selectedCell == id).color, + foregroundColorDark: .gray30) + .truncationMode(truncationMode) + .frame(maxHeight: .greatestFiniteMagnitude) + .textSelection(.enabled) + } else { + Text(subtitle) + .label4Style(design: isMonospaced ? .monospaced : .default, + foregroundColorLight: ForegroundColor(isSelected: selectedCell == id).color, + foregroundColorDark: .gray30) + .truncationMode(truncationMode) + } + } + } + .padding(EdgeInsets(top: 8, leading: 0, bottom: 8, trailing: 8)) + + if secondaryButtonImageName != nil { + Spacer(minLength: Constants.textFieldImageSize * 2 + 8) + } else { + Spacer(minLength: buttonImageName != nil ? Constants.textFieldImageSize : 8) + } + } + + if let buttonImageName = buttonImageName, let buttonAccessibilityLabel = buttonAccessibilityLabel { + let differenceBetweenImageSizeAndTapAreaPerEdge = (Constants.textFieldTapSize - Constants.textFieldImageSize) / 2.0 + HStack(alignment: .center, spacing: 0) { + Spacer() + + Button { + buttonAction?() + self.selectedCell = nil + } label: { + VStack(alignment: .trailing) { + Spacer() + HStack { + Spacer() + Image(buttonImageName) + .resizable() + .frame(width: Constants.textFieldImageSize, height: Constants.textFieldImageSize) + .foregroundColor(Color(UIColor.label).opacity(Constants.textFieldImageOpacity)) + .opacity(subtitle.isEmpty ? 0 : 1) + Spacer() + } + Spacer() + } + } + .buttonStyle(.plain) // Prevent taps from being forwarded to the container view + // can't use .clear here or else both button padded area and container both respond to tap events + .background(BackgroundColor(isSelected: selectedCell == id).color.opacity(0)) + .accessibilityLabel(buttonAccessibilityLabel) + .contentShape(Rectangle()) + .frame(width: Constants.textFieldTapSize, height: Constants.textFieldTapSize) + + if let secondaryButtonImageName = secondaryButtonImageName, + let secondaryButtonAccessibilityLabel = secondaryButtonAccessibilityLabel { + Button { + secondaryButtonAction?() + self.selectedCell = nil + } label: { + VStack(alignment: .trailing) { + Spacer() + HStack { + Spacer() + Image(secondaryButtonImageName) + .resizable() + .frame(width: Constants.textFieldImageSize, height: Constants.textFieldImageSize) + .foregroundColor(Color(UIColor.label).opacity(Constants.textFieldImageOpacity)) + .opacity(subtitle.isEmpty ? 0 : 1) + Spacer() + } + Spacer() + } + } + .buttonStyle(.plain) // Prevent taps from being forwarded to the container view + .background(BackgroundColor(isSelected: selectedCell == id).color.opacity(0)) + .accessibilityLabel(secondaryButtonAccessibilityLabel) + .contentShape(Rectangle()) + .frame(width: Constants.textFieldTapSize, height: Constants.textFieldTapSize) + } + + } + .padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: -differenceBetweenImageSizeAndTapAreaPerEdge)) + } + } + .selectableBackground(isSelected: selectedCell == id) + } +} + +private extension View { + func copyable(isSelected: Bool) -> some View { + modifier(Copyable(isSelected: isSelected)) + } + + func selectableBackground(isSelected: Bool) -> some View { + modifier(SelectableBackground(isSelected: isSelected)) + } +} + +private struct Copyable: ViewModifier { + var isSelected: Bool + + public func body(content: Content) -> some View { + ZStack { + Rectangle() + .foregroundColor(.clear) + + content + .allowsHitTesting(false) + .contentShape(Rectangle()) + .frame(maxWidth: .infinity) + .frame(minHeight: Constants.minRowHeight) + } + } +} + +private struct SelectableBackground: ViewModifier { + var isSelected: Bool + + public func body(content: Content) -> some View { + content + .listRowBackground(BackgroundColor(isSelected: isSelected).color) + .listRowInsets(.init(top: 0, leading: 16, bottom: 0, trailing: 16)) + } +} + +private struct ForegroundColor { + let isSelected: Bool + + var color: Color { + if isSelected { + return .gray90 + } else { + return .gray50 + } + } +} + +private struct BackgroundColor { + let isSelected: Bool + + var color: Color { + if isSelected { + return Color("AutofillCellSelectedBackground") + } else { + return Color(designSystemColor: .surface) + } + } +} + +private struct Constants { + static let verticalPadding: CGFloat = 4 + static let minRowHeight: CGFloat = 60 + static let textFieldImageOpacity: CGFloat = 0.84 + static let textFieldImageSize: CGFloat = 24 + static let textFieldTapSize: CGFloat = 36 + static let insets = EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16) +} diff --git a/AutofillCredentialProvider/CredentialProvider/CredentialProviderListDetails/CredentialProviderListDetailsViewController.swift b/AutofillCredentialProvider/CredentialProvider/CredentialProviderListDetails/CredentialProviderListDetailsViewController.swift new file mode 100644 index 0000000000..cb4a37c95c --- /dev/null +++ b/AutofillCredentialProvider/CredentialProvider/CredentialProviderListDetails/CredentialProviderListDetailsViewController.swift @@ -0,0 +1,125 @@ +// +// CredentialProviderListDetailsViewController.swift +// DuckDuckGo +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import UIKit +import SwiftUI +import BrowserServicesKit +import Common +import Combine +import Core + +protocol CredentialProviderListDetailsViewControllerDelegate: AnyObject { + func credentialProviderListDetailsViewControllerDidProvideText(_ controller: CredentialProviderListDetailsViewController, text: String) +} + +class CredentialProviderListDetailsViewController: UIViewController { + + private enum Constants { + static let padding: CGFloat = 16 + } + + weak var delegate: CredentialProviderListDetailsViewControllerDelegate? + private let viewModel: CredentialProviderListDetailsViewModel + private var cancellables: Set = [] + private var contentView: UIView? + + init(account: SecureVaultModels.WebsiteAccount? = nil, tld: TLD, shouldProvideTextToInsert: Bool = false) { + self.viewModel = CredentialProviderListDetailsViewModel(account: account, + tld: tld, + shouldProvideTextToInsert: shouldProvideTextToInsert) + super.init(nibName: nil, bundle: nil) + self.viewModel.delegate = self + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + var account: SecureVaultModels.WebsiteAccount? { + get { + viewModel.account + } + set { + if let newValue { + viewModel.updateData(with: newValue) + } + } + } + + override func viewDidLoad() { + super.viewDidLoad() + + installSubviews() + setupCancellables() + setupNavigationBar() + } + + private func installSubviews() { + installContentView() + } + + private func setupCancellables() { + Publishers.MergeMany( + viewModel.$title, + viewModel.$username, + viewModel.$password, + viewModel.$address, + viewModel.$notes) + .receive(on: DispatchQueue.main) + .sink { [weak self] _ in + self?.setupNavigationBar() + } + .store(in: &cancellables) + + } + + private func installContentView() { + let contentView = CredentialProviderListDetailsView(viewModel: viewModel) + let hostingController = UIHostingController(rootView: contentView) + addChild(hostingController) + hostingController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight] + hostingController.view.frame = view.bounds + view.addSubview(hostingController.view) + hostingController.didMove(toParent: self) + self.contentView = hostingController.view + } + + private func setupNavigationBar() { + title = viewModel.navigationTitle + } + + func showActionMessage(_ message: String) { + ActionMessageView.present( + message: message, + actionTitle: "", + onAction: {}, + inView: self.view + ) + } +} + +extension CredentialProviderListDetailsViewController: CredentialProviderListDetailsViewModelDelegate { + func credentialProviderListDetailsViewModelDidProvideText(text: String) { + delegate?.credentialProviderListDetailsViewControllerDidProvideText(self, text: text) + } + + func credentialProviderListDetailsViewModelShowActionMessage(message: String) { + showActionMessage(message) + } +} diff --git a/AutofillCredentialProvider/CredentialProvider/CredentialProviderListDetails/CredentialProviderListDetailsViewModel.swift b/AutofillCredentialProvider/CredentialProvider/CredentialProviderListDetails/CredentialProviderListDetailsViewModel.swift new file mode 100644 index 0000000000..33fac86061 --- /dev/null +++ b/AutofillCredentialProvider/CredentialProvider/CredentialProviderListDetails/CredentialProviderListDetailsViewModel.swift @@ -0,0 +1,192 @@ +// +// CredentialProviderListDetailsViewModel.swift +// DuckDuckGo +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import UIKit +import SwiftUI +import BrowserServicesKit +import Common +import Combine +import Core + +protocol CredentialProviderListDetailsViewModelDelegate: AnyObject { + func credentialProviderListDetailsViewModelShowActionMessage(message: String) + func credentialProviderListDetailsViewModelDidProvideText(text: String) +} + +final class CredentialProviderListDetailsViewModel: ObservableObject { + enum ViewMode { + case view + } + + enum PasteboardCopyAction { + case username + case password + case address + case notes + } + + weak var delegate: CredentialProviderListDetailsViewModelDelegate? + var account: SecureVaultModels.WebsiteAccount? + + private let tld: TLD + private let autofillDomainNameUrlMatcher = AutofillDomainNameUrlMatcher() + private let autofillDomainNameUrlSort = AutofillDomainNameUrlSort() + + @ObservedObject var headerViewModel: CredentialProviderListDetailsHeaderViewModel + @Published var isPasswordHidden = true + @Published var username = "" + @Published var password = "" + @Published var address = "" + @Published var notes = "" + @Published var title = "" + @Published var selectedCell: UUID? + + private var passwordData: Data { + password.data(using: .utf8)! + } + + var navigationTitle: String { + return title.isEmpty ? address : title + } + + var websiteIsValidUrl: Bool { + account?.domain?.toTrimmedURL != nil + } + + var userVisiblePassword: String { + let passwordHider = PasswordHider(password: password) + return isPasswordHidden ? passwordHider.hiddenPassword : passwordHider.password + } + + var usernameDisplayString: String { + AutofillInterfaceEmailTruncator.truncateEmail(username, maxLength: 36) + } + + let shouldProvideTextToInsert: Bool + + internal init(account: SecureVaultModels.WebsiteAccount? = nil, + tld: TLD, + emailManager: EmailManager = EmailManager(), + shouldProvideTextToInsert: Bool) { + self.account = account + self.tld = tld + self.headerViewModel = CredentialProviderListDetailsHeaderViewModel() + self.shouldProvideTextToInsert = shouldProvideTextToInsert + if let account = account { + self.updateData(with: account) + } + } + + func updateData(with account: SecureVaultModels.WebsiteAccount) { + self.account = account + username = account.username ?? "" + address = account.domain ?? "" + title = account.title ?? "" + notes = account.notes ?? "" + headerViewModel.updateData(with: account, + tld: tld, + autofillDomainNameUrlMatcher: autofillDomainNameUrlMatcher, + autofillDomainNameUrlSort: autofillDomainNameUrlSort) + setupPassword(with: account) + } + + func copyToPasteboard(_ action: PasteboardCopyAction) { + var message = "" + switch action { + case .username: + message = UserText.credentialProviderDetailsCopyToastUsernameCopied + UIPasteboard.general.string = username + Pixel.fire(pixel: .autofillManagementCopyUsername) + case .password: + message = UserText.credentialProviderDetailsCopyToastPasswordCopied + UIPasteboard.general.string = password + Pixel.fire(pixel: .autofillManagementCopyPassword) + case .address: + message = UserText.credentialProviderDetailsCopyToastAddressCopied + UIPasteboard.general.string = address + case .notes: + message = UserText.credentialProviderDetailsCopyToastNotesCopied + UIPasteboard.general.string = notes + } + + delegate?.credentialProviderListDetailsViewModelShowActionMessage(message: message) + } + + func textToReturn(_ action: PasteboardCopyAction) { + var text = "" + switch action { + case .username: + text = username + case .password: + text = password + default: + return + } + + delegate?.credentialProviderListDetailsViewModelDidProvideText(text: text) + } + + private func setupPassword(with account: SecureVaultModels.WebsiteAccount) { + do { + if let accountID = account.id, let accountIdInt = Int64(accountID) { + let vault = try AutofillSecureVaultFactory.makeVault(reporter: nil) + + if let credential = try + vault.websiteCredentialsFor(accountId: accountIdInt) { + self.password = credential.password.flatMap { String(data: $0, encoding: .utf8) } ?? "" + } + } + } catch { + Pixel.fire(pixel: .secureVaultError, error: error) + } + } + + private func handleSecureVaultError(_ error: Error) { + Pixel.fire(pixel: .secureVaultError, error: error) + } +} + +final class CredentialProviderListDetailsHeaderViewModel: ObservableObject { + private var dateFormatter: DateFormatter = { + let dateFormatter = DateFormatter() + dateFormatter.dateStyle = .medium + dateFormatter.timeStyle = .short + return dateFormatter + }() + + @Published var title: String = "" + @Published var subtitle: String = "" + @Published var domain: String = "" + @Published var favicon: UIImage = UIImage(named: "Logo")! + + func updateData(with account: SecureVaultModels.WebsiteAccount, tld: TLD, autofillDomainNameUrlMatcher: AutofillDomainNameUrlMatcher, autofillDomainNameUrlSort: AutofillDomainNameUrlSort) { + self.title = account.name(tld: tld, autofillDomainNameUrlMatcher: autofillDomainNameUrlMatcher) + self.subtitle = UserText.credentialProviderDetailsLastUpdated(for: (dateFormatter.string(from: account.lastUpdated))) + self.domain = account.domain ?? "" + + // Update favicon + let accountName = account.name(tld: tld, autofillDomainNameUrlMatcher: autofillDomainNameUrlMatcher) + let accountTitle = (account.title?.isEmpty == false) ? account.title! : "#" + let preferredFakeFaviconLetters = tld.eTLDplus1(accountName) ?? accountTitle + if let image = FaviconHelper.loadImageFromCache(forDomain: domain, preferredFakeFaviconLetters: preferredFakeFaviconLetters) { + self.favicon = image + } + } + +} diff --git a/AutofillCredentialProvider/CredentialProvider/CredentialProviderViewController.swift b/AutofillCredentialProvider/CredentialProvider/CredentialProviderViewController.swift index 397b1a5781..35f730611e 100644 --- a/AutofillCredentialProvider/CredentialProvider/CredentialProviderViewController.swift +++ b/AutofillCredentialProvider/CredentialProvider/CredentialProviderViewController.swift @@ -112,26 +112,39 @@ class CredentialProviderViewController: ASCredentialProviderViewController { Task { await credentialIdentityStoreManager.populateCredentialStore() } + + Pixel.fire(pixel: .autofillExtensionEnabled) + } + + @available(iOSApplicationExtension 18.0, *) + override func prepareInterfaceForUserChoosingTextToInsert() { + loadCredentialsList(for: [], shouldProvideTextToInsert: true) } // MARK: - Private - private func loadCredentialsList(for serviceIdentifiers: [ASCredentialServiceIdentifier], returnString: Bool = false) { + private func loadCredentialsList(for serviceIdentifiers: [ASCredentialServiceIdentifier], shouldProvideTextToInsert: Bool = false) { let credentialProviderListViewController = CredentialProviderListViewController(serviceIdentifiers: serviceIdentifiers, secureVault: secureVault, credentialIdentityStoreManager: credentialIdentityStoreManager, + shouldProvideTextToInsert: shouldProvideTextToInsert, + tld: tld, onRowSelected: { [weak self] item in - guard let self = self else { - self?.extensionContext.cancelRequest(withError: NSError(domain: ASExtensionErrorDomain, - code: ASExtensionError.failed.rawValue)) - return - } + guard let self = self else { + self?.extensionContext.cancelRequest(withError: NSError(domain: ASExtensionErrorDomain, + code: ASExtensionError.failed.rawValue)) + return + } - let credential = self.vaultCredentialManager.fetchCredential(for: item.account) + let credential = self.vaultCredentialManager.fetchCredential(for: item.account) - self.extensionContext.completeRequest(withSelectedCredential: credential, completionHandler: nil) + self.extensionContext.completeRequest(withSelectedCredential: credential, completionHandler: nil) - }, onDismiss: { + }, onTextProvided: { [weak self] text in + if #available(iOSApplicationExtension 18.0, *) { + self?.extensionContext.completeRequest(withTextToInsert: text) + } + }, onDismiss: { self.extensionContext.cancelRequest(withError: NSError(domain: ASExtensionErrorDomain, code: ASExtensionError.userCanceled.rawValue)) }) @@ -150,20 +163,24 @@ class CredentialProviderViewController: ASCredentialProviderViewController { guard let passwordCredential = vaultCredentialManager.fetchCredential(for: credentialIdentity) else { self.extensionContext.cancelRequest(withError: NSError(domain: ASExtensionErrorDomain, code: ASExtensionError.credentialIdentityNotFound.rawValue)) + Pixel.fire(pixel: .autofillExtensionQuickTypeCancelled) return } self.extensionContext.completeRequest(withSelectedCredential: passwordCredential) + Pixel.fire(pixel: .autofillExtensionQuickTypeConfirmed) } private func provideCredential(for credentialIdentity: ASPasswordCredentialIdentity) { guard let passwordCredential = vaultCredentialManager.fetchCredential(for: credentialIdentity) else { self.extensionContext.cancelRequest(withError: NSError(domain: ASExtensionErrorDomain, code: ASExtensionError.credentialIdentityNotFound.rawValue)) + Pixel.fire(pixel: .autofillExtensionQuickTypeCancelled) return } self.extensionContext.completeRequest(withSelectedCredential: passwordCredential) + Pixel.fire(pixel: .autofillExtensionQuickTypeConfirmed) } private func authenticateAndHandleCredential(provideCredential: @escaping () -> Void) { diff --git a/AutofillCredentialProvider/CredentialProvider/Resources/Assets.xcassets/AutofillCellSelectedBackground.colorset/Contents.json b/AutofillCredentialProvider/CredentialProvider/Resources/Assets.xcassets/AutofillCellSelectedBackground.colorset/Contents.json new file mode 100644 index 0000000000..cc91bfda6f --- /dev/null +++ b/AutofillCredentialProvider/CredentialProvider/Resources/Assets.xcassets/AutofillCellSelectedBackground.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "display-p3", + "components" : { + "alpha" : "1.000", + "blue" : "0.800", + "green" : "0.800", + "red" : "0.800" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "display-p3", + "components" : { + "alpha" : "1.000", + "blue" : "0.267", + "green" : "0.267", + "red" : "0.267" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AutofillCredentialProvider/CredentialProvider/Resources/Assets.xcassets/Copy-24.imageset/Contents.json b/AutofillCredentialProvider/CredentialProvider/Resources/Assets.xcassets/Copy-24.imageset/Contents.json new file mode 100644 index 0000000000..1a533a908e --- /dev/null +++ b/AutofillCredentialProvider/CredentialProvider/Resources/Assets.xcassets/Copy-24.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "Copy-24.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/AutofillCredentialProvider/CredentialProvider/Resources/Assets.xcassets/Copy-24.imageset/Copy-24.pdf b/AutofillCredentialProvider/CredentialProvider/Resources/Assets.xcassets/Copy-24.imageset/Copy-24.pdf new file mode 100644 index 0000000000..56407ef84b Binary files /dev/null and b/AutofillCredentialProvider/CredentialProvider/Resources/Assets.xcassets/Copy-24.imageset/Copy-24.pdf differ diff --git a/AutofillCredentialProvider/CredentialProvider/Resources/Assets.xcassets/Eye-24.imageset/Contents.json b/AutofillCredentialProvider/CredentialProvider/Resources/Assets.xcassets/Eye-24.imageset/Contents.json new file mode 100644 index 0000000000..d46a04ef5b --- /dev/null +++ b/AutofillCredentialProvider/CredentialProvider/Resources/Assets.xcassets/Eye-24.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "Eye-24.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/AutofillCredentialProvider/CredentialProvider/Resources/Assets.xcassets/Eye-24.imageset/Eye-24.pdf b/AutofillCredentialProvider/CredentialProvider/Resources/Assets.xcassets/Eye-24.imageset/Eye-24.pdf new file mode 100644 index 0000000000..ac69e29aa6 Binary files /dev/null and b/AutofillCredentialProvider/CredentialProvider/Resources/Assets.xcassets/Eye-24.imageset/Eye-24.pdf differ diff --git a/AutofillCredentialProvider/CredentialProvider/Resources/Assets.xcassets/Eye-Closed-24.imageset/Contents.json b/AutofillCredentialProvider/CredentialProvider/Resources/Assets.xcassets/Eye-Closed-24.imageset/Contents.json new file mode 100644 index 0000000000..ac2612ee62 --- /dev/null +++ b/AutofillCredentialProvider/CredentialProvider/Resources/Assets.xcassets/Eye-Closed-24.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "Eye-Closed-24.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/AutofillCredentialProvider/CredentialProvider/Resources/Assets.xcassets/Eye-Closed-24.imageset/Eye-Closed-24.pdf b/AutofillCredentialProvider/CredentialProvider/Resources/Assets.xcassets/Eye-Closed-24.imageset/Eye-Closed-24.pdf new file mode 100644 index 0000000000..78b200d65b Binary files /dev/null and b/AutofillCredentialProvider/CredentialProvider/Resources/Assets.xcassets/Eye-Closed-24.imageset/Eye-Closed-24.pdf differ diff --git a/AutofillCredentialProvider/CredentialProvider/Resources/Assets.xcassets/Logo.imageset/Contents.json b/AutofillCredentialProvider/CredentialProvider/Resources/Assets.xcassets/Logo.imageset/Contents.json new file mode 100644 index 0000000000..5cf237b7f3 --- /dev/null +++ b/AutofillCredentialProvider/CredentialProvider/Resources/Assets.xcassets/Logo.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "Dax_default.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/AutofillCredentialProvider/CredentialProvider/Resources/Assets.xcassets/Logo.imageset/Dax_default.pdf b/AutofillCredentialProvider/CredentialProvider/Resources/Assets.xcassets/Logo.imageset/Dax_default.pdf new file mode 100644 index 0000000000..46ebb1057c Binary files /dev/null and b/AutofillCredentialProvider/CredentialProvider/Resources/Assets.xcassets/Logo.imageset/Dax_default.pdf differ diff --git a/AutofillCredentialProvider/CredentialProvider/Resources/UserText.swift b/AutofillCredentialProvider/CredentialProvider/Resources/UserText.swift index 74922adc7a..9068764c55 100644 --- a/AutofillCredentialProvider/CredentialProvider/Resources/UserText.swift +++ b/AutofillCredentialProvider/CredentialProvider/Resources/UserText.swift @@ -21,18 +21,18 @@ import Foundation final class UserText { - static let credentialProviderActivatedTitle = NSLocalizedString("credential.provider.activated.title", value: "Autofill activated!", comment: "The title of the screen confirming DuckDuckGo can now be used for autofilling passwords") - - static let credentialProviderActivatedSubtitle = NSLocalizedString("credential.provider.activated.subtitle", value: "You can now autofill your DuckDuckGo passwords from anywhere.", comment: "The subtitle of the screen confirming DuckDuckGo can now be used for autofilling passwords") + static let credentialProviderActivatedTitle = NSLocalizedString("credential.provider.activated.title", value: "Autofill Passwords activated!", comment: "The title of the screen confirming DuckDuckGo can now be used for autofilling passwords") static let credentialProviderActivatedButton = NSLocalizedString("credential.provider.activated.button", value: "Open DuckDuckGo", comment: "Title of button to launch the DuckDuckGo app") - static let actionCancel = NSLocalizedString("action.button.cancel", value: "Cancel", comment: "Cancel button title") + static let actionClose = NSLocalizedString("action.button.close", value: "Close", comment: "Close button title") - static let actionClose = NSLocalizedString("action.button.cancel", value: "Close", comment: "Close button title") + static let actionDone = NSLocalizedString("action.button.done", value: "Done", comment: "Done button title") static let credentialProviderListTitle = NSLocalizedString("credential.provider.list.title", value: "Passwords", comment: "Title for screen listing autofill logins") + static let credentialProviderListPrompt = NSLocalizedString("credential.provider.list.prompt", value: "Choose a password to use for \"%@\"", comment: "Prompt above the title for screen listing autofill logins, example: Choose a password to use for \"website.com\"") + static let credentialProviderListSearchPlaceholder = NSLocalizedString("credential.provider.list.search-placeholder", value: "Search passwords", comment: "Placeholder for search field on autofill login listing") static let credentialProviderListEmptyViewTitle = NSLocalizedString("credential.provider.list.empty-view.title", value: "No passwords saved yet", comment: "Title for view displayed when autofill has no items") @@ -58,6 +58,29 @@ final class UserText { static let deviceTypeiPhone = NSLocalizedString("credential.provider.device.type.iphone", value: "iPhone", comment: "Device type is iPhone") static let deviceTypeiPad = NSLocalizedString("credential.provider.device.type.pad", value: "iPad", comment: "Device type is iPad") - static let deviceTypeDefault = NSLocalizedString("credential.providerdevice.type.default", value: "device", comment: "Default string used if users device is not iPhone or iPad") + static let deviceTypeDefault = NSLocalizedString("credential.provider.device.type.default", value: "device", comment: "Default string used if users device is not iPhone or iPad") + + public static let credentialProviderDetailsCopyToastUsernameCopied = NSLocalizedString("credential.provider.list.details.copy-toast.username-copied", value: "Username copied", comment: "Title for toast when copying username") + public static let credentialProviderDetailsCopyToastPasswordCopied = NSLocalizedString("credential.provider.list.details.copy-toast.password-copied", value: "Password copied", comment: "Title for toast when copying password") + public static let credentialProviderDetailsCopyToastAddressCopied = NSLocalizedString("credential.provider.list.details.copy-toast.address-copied", value: "Address copied", comment: "Title for toast when copying address") + public static let credentialProviderDetailsCopyToastNotesCopied = NSLocalizedString("credential.provider.list.details.copy-toast.notes-copied", value: "Notes copied", comment: "Title for toast when copying notes") + + public static func credentialProviderDetailsLastUpdated(for date: String) -> String { + let message = NSLocalizedString("credential.provider.list.details.last-updated", value: "Last updated %@", comment: "Message displaying when the login was last updated") + return message.format(arguments: date) + } + + public static let credentialProviderDetailsLoginName = NSLocalizedString("credential.provider.list.details.login-name", value: "Title", comment: "Login name label for login details on autofill") + public static let credentialProviderDetailsUsername = NSLocalizedString("credential.provider.list.details.username", value: "Username", comment: "Username label for login details on autofill") + public static let credentialProviderDetailsPassword = NSLocalizedString("credential.provider.list.details.password", value: "Password", comment: "Password label for login details on autofill") + public static let credentialProviderDetailsAddress = NSLocalizedString("credential.provider.list.details.address", value: "Website URL", comment: "Address label for login details on autofill") + public static let credentialProviderDetailsNotes = NSLocalizedString("credential.provider.list.details.notes", value: "Notes", comment: "Notes label for login details on autofill") + + public static func credentialProviderDetailsCopyPrompt(for type: String) -> String { + let message = NSLocalizedString("credential.provider.list.details.copy-prompt", value: "Copy %@", comment: "Menu item text for copying autofill login details") + return message.format(arguments: type) + } + public static let credentialProviderDetailsShowPassword = NSLocalizedString("credential.provider.list.details.show-password", value: "Show Password", comment: "Accessibility title for a Show Password button displaying actial password instead of *****") + public static let credentialProviderDetailsHidePassword = NSLocalizedString("credential.provider.list.details.hide-password", value: "Hide Password", comment: "Accessibility title for a Hide Password button replacing displayed password with *****") } diff --git a/AutofillCredentialProvider/CredentialProvider/Shared/ActionMessageView.swift b/AutofillCredentialProvider/CredentialProvider/Shared/ActionMessageView.swift new file mode 100644 index 0000000000..50a1b38a4e --- /dev/null +++ b/AutofillCredentialProvider/CredentialProvider/Shared/ActionMessageView.swift @@ -0,0 +1,197 @@ +// +// ActionMessageView.swift +// DuckDuckGo +// +// Copyright © 2021 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 + +extension ActionMessageView: NibLoading {} + +class ActionMessageView: UIView { + + enum PresentationLocation { + case withBottomBar(andAddressBarBottom: Bool) + case withoutBottomBar + } + + private static var presentedMessages = [ActionMessageView]() + + private enum Constants { + static var maxWidth: CGFloat = 346 + static var minimumHorizontalPadding: CGFloat = 20 + static var cornerRadius: CGFloat = 10 + + static var animationDuration: TimeInterval = 0.2 + static var duration: TimeInterval = 3.0 + + static var windowBottomPaddingWithBottomBar: CGFloat { + if UIDevice.current.userInterfaceIdiom == .phone && !UIDevice.current.orientation.isPortrait { + return 40 + } + + return 70 + } + + static var windowBottomPaddingWithAddressBar: CGFloat { + return windowBottomPaddingWithBottomBar + 52 + } + + static var windowBottomPaddingWithoutBottomBar: CGFloat { + return 0 + } + + } + + private static func bottomPadding(for location: PresentationLocation) -> CGFloat { + switch location { + case .withBottomBar(let isAddressBarBottom): + return isAddressBarBottom ? Constants.windowBottomPaddingWithAddressBar : Constants.windowBottomPaddingWithBottomBar + case .withoutBottomBar: + return Constants.windowBottomPaddingWithoutBottomBar + } + } + + @IBOutlet weak var message: UILabel! + @IBOutlet weak var actionButton: UIButton! + + @IBOutlet var labelToButton: NSLayoutConstraint! + @IBOutlet var labelToTrailing: NSLayoutConstraint! + + private var action: () -> Void = {} + private var onDidDismiss: () -> Void = {} + + private var dismissWorkItem: DispatchWorkItem? + + static func loadFromXib() -> ActionMessageView { + return ActionMessageView.load(nibName: "ActionMessageView") + } + + override func awakeFromNib() { + super.awakeFromNib() + + layer.cornerRadius = Constants.cornerRadius + } + + static func present(message: NSAttributedString, + numberOfLines: Int = 0, + actionTitle: String? = nil, + presentationLocation: PresentationLocation = .withBottomBar(andAddressBarBottom: false), + duration: TimeInterval = Constants.duration, + onAction: @escaping () -> Void = {}, + onDidDismiss: @escaping () -> Void = {}, + inView: UIView) { + let messageView = loadFromXib() + messageView.message.attributedText = message + messageView.message.numberOfLines = numberOfLines + ActionMessageView.present(messageView: messageView, + message: message.string, + actionTitle: actionTitle, + presentationLocation: presentationLocation, + duration: duration, + onAction: onAction, + onDidDismiss: onDidDismiss, + inView: inView) + } + + static func present(message: String, + actionTitle: String? = nil, + presentationLocation: PresentationLocation = .withBottomBar(andAddressBarBottom: false), + duration: TimeInterval = Constants.duration, + onAction: @escaping () -> Void = {}, + onDidDismiss: @escaping () -> Void = {}, + inView: UIView) { + let messageView = loadFromXib() + messageView.message.text = message + ActionMessageView.present(messageView: messageView, + message: message, + actionTitle: actionTitle, + presentationLocation: presentationLocation, + duration: duration, + onAction: onAction, + onDidDismiss: onDidDismiss, + inView: inView) + } + + private static func present(messageView: ActionMessageView, + message: String, + actionTitle: String? = nil, + presentationLocation: PresentationLocation = .withBottomBar(andAddressBarBottom: false), + duration: TimeInterval = Constants.duration, + onAction: @escaping () -> Void = {}, + onDidDismiss: @escaping () -> Void = {}, + inView: UIView) { + dismissAllMessages() + + if let actionTitle = actionTitle, let title = messageView.actionButton.attributedTitle(for: .normal) { + messageView.actionButton.setAttributedTitle(title.withText(actionTitle), for: .normal) + messageView.action = onAction + } else { + messageView.labelToButton.isActive = false + messageView.labelToTrailing.isActive = true + messageView.actionButton.isHidden = true + } + messageView.onDidDismiss = onDidDismiss + + inView.addSubview(messageView) + inView.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: messageView.bottomAnchor, + constant: bottomPadding(for: presentationLocation)).isActive = true + + let messageViewWidth = inView.frame.width <= Constants.maxWidth ? inView.frame.width - Constants.minimumHorizontalPadding : Constants.maxWidth + messageView.widthAnchor.constraint(equalToConstant: messageViewWidth).isActive = true + messageView.centerXAnchor.constraint(equalTo: inView.centerXAnchor).isActive = true + + inView.layoutIfNeeded() + + messageView.alpha = 0 + UIView.animate(withDuration: Constants.animationDuration) { + messageView.alpha = 1 + } completion: { _ in + UIAccessibility.post(notification: .announcement, argument: message) + } + + let workItem = DispatchWorkItem { [weak messageView] in + messageView?.dismissAndFadeOut() + } + messageView.dismissWorkItem = workItem + DispatchQueue.main.asyncAfter(deadline: .now() + duration, execute: workItem) + presentedMessages.append(messageView) + } + + static func dismissAllMessages() { + presentedMessages.forEach { $0.dismissAndFadeOut() } + } + + func dismissAndFadeOut() { + dismissWorkItem?.cancel() + dismissWorkItem = nil + + UIView.animate(withDuration: Constants.animationDuration, animations: { + self.alpha = 0 + }, completion: { _ in + self.removeFromSuperview() + if let position = Self.presentedMessages.firstIndex(of: self) { + Self.presentedMessages.remove(at: position) + } + self.onDidDismiss() + }) + } + + @IBAction func onButtonTap() { + action() + dismissAndFadeOut() + } +} diff --git a/AutofillCredentialProvider/CredentialProvider/Shared/ActionMessageView.xib b/AutofillCredentialProvider/CredentialProvider/Shared/ActionMessageView.xib new file mode 100644 index 0000000000..2c532dc85f --- /dev/null +++ b/AutofillCredentialProvider/CredentialProvider/Shared/ActionMessageView.xib @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/AutofillCredentialProvider/CredentialProvider/Shared/FaviconHelper.swift b/AutofillCredentialProvider/CredentialProvider/Shared/FaviconHelper.swift new file mode 100644 index 0000000000..b1d95ef7a8 --- /dev/null +++ b/AutofillCredentialProvider/CredentialProvider/Shared/FaviconHelper.swift @@ -0,0 +1,87 @@ +// +// FaviconHelper.swift +// DuckDuckGo +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import Common +import Core +import UIKit + +struct FaviconHelper { + + static func loadImageFromCache(forDomain domain: String?, preferredFakeFaviconLetters: String) -> UIImage? { + guard let domain = domain, + let cacheUrl = FaviconsCacheType.fireproof.cacheLocation() else { return nil } + + let key = FaviconHasher.createHash(ofDomain: domain) + + // Slight leap here to avoid loading Kingfisher as a library for the widgets. + // Once dependency management is fixed, link it and use Favicons directly. + let imageUrl = cacheUrl.appendingPathComponent("com.onevcat.Kingfisher.ImageCache.fireproof").appendingPathComponent(key) + + guard let data = (try? Data(contentsOf: imageUrl)) else { + let image = Self.createFakeFavicon(forDomain: domain, size: 32, backgroundColor: UIColor.forDomain(domain), preferredFakeFaviconLetters: preferredFakeFaviconLetters) + return image + } + + return UIImage(data: data)?.toSRGB() + } + + private static func createFakeFavicon(forDomain domain: String, + size: CGFloat = 192, + backgroundColor: UIColor = UIColor.red, + bold: Bool = true, + preferredFakeFaviconLetters: String? = nil, + letterCount: Int = 2) -> UIImage? { + + let cornerRadius = size * 0.125 + let imageRect = CGRect(x: 0, y: 0, width: size, height: size) + let padding = size * 0.16 + let labelFrame = CGRect(x: padding, y: padding, width: imageRect.width - (2 * padding), height: imageRect.height - (2 * padding)) + + let renderer = UIGraphicsImageRenderer(size: imageRect.size) + let icon = renderer.image { imageContext in + let context = imageContext.cgContext + + context.setFillColor(backgroundColor.cgColor) + context.addPath(CGPath(roundedRect: imageRect, cornerWidth: cornerRadius, cornerHeight: cornerRadius, transform: nil)) + context.fillPath() + + let label = UILabel(frame: labelFrame) + label.numberOfLines = 1 + label.adjustsFontSizeToFitWidth = true + label.minimumScaleFactor = 0.1 + label.baselineAdjustment = .alignCenters + label.font = bold ? UIFont.boldSystemFont(ofSize: size) : UIFont.systemFont(ofSize: size) + label.textColor = .white + label.textAlignment = .center + + if let preferedPrefix = preferredFakeFaviconLetters?.droppingWwwPrefix().prefix(letterCount).capitalized { + label.text = preferedPrefix + } else { + label.text = preferredFakeFaviconLetters?.capitalized ?? "#" + } + + context.translateBy(x: padding, y: padding) + + label.layer.draw(in: context) + } + + return icon.withRenderingMode(.alwaysOriginal) + } +} diff --git a/AutofillCredentialProvider/CredentialProvider/Shared/NibLoading.swift b/AutofillCredentialProvider/CredentialProvider/Shared/NibLoading.swift new file mode 100644 index 0000000000..af24b38f7c --- /dev/null +++ b/AutofillCredentialProvider/CredentialProvider/Shared/NibLoading.swift @@ -0,0 +1,34 @@ +// +// NibLoading.swift +// DuckDuckGo +// +// Copyright © 2017 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 + +protocol NibLoading { +} + +extension NibLoading where Self: UIView { + static func load(nibName: String) -> Self { + let nib = UINib(nibName: nibName, bundle: nil) + guard let view = nib.instantiate(withOwner: self, options: nil).first as? Self else { + fatalError("Error instantiating view") + } + view.autoresizingMask = [UIView.AutoresizingMask.flexibleWidth, UIView.AutoresizingMask.flexibleHeight] + return view + } +} diff --git a/AutofillCredentialProvider/Info.plist b/AutofillCredentialProvider/Info.plist index cb9ba8ea30..c00abcf6dc 100644 --- a/AutofillCredentialProvider/Info.plist +++ b/AutofillCredentialProvider/Info.plist @@ -12,6 +12,13 @@ $(PRODUCT_MODULE_NAME).CredentialProviderViewController ASCredentialProviderExtensionShowsConfigurationUI + ASCredentialProviderExtensionCapabilities + + ProvidesPasswords + + ProvidesTextToInsert + + NSExtensionPointIdentifier com.apple.authentication-services-credential-provider-ui diff --git a/AutofillCredentialProvider/bg.lproj/InfoPlist.strings b/AutofillCredentialProvider/bg.lproj/InfoPlist.strings new file mode 100644 index 0000000000..9809aa19f5 --- /dev/null +++ b/AutofillCredentialProvider/bg.lproj/InfoPlist.strings @@ -0,0 +1,9 @@ +/* Bundle display name */ +"CFBundleDisplayName" = "AutofillCredentialProvider"; + +/* Bundle name */ +"CFBundleName" = "AutofillCredentialProvider"; + +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "Copyright © 2024 DuckDuckGo. All rights reserved."; + diff --git a/AutofillCredentialProvider/bg.lproj/Localizable.strings b/AutofillCredentialProvider/bg.lproj/Localizable.strings new file mode 100644 index 0000000000..82a8dc2b8c --- /dev/null +++ b/AutofillCredentialProvider/bg.lproj/Localizable.strings @@ -0,0 +1,96 @@ +/* Close button title */ +"action.button.close" = "Затваряне"; + +/* Done button title */ +"action.button.done" = "Готово"; + +/* Title of button to launch the DuckDuckGo app */ +"credential.provider.activated.button" = "Отваряне на DuckDuckGo"; + +/* The title of the screen confirming DuckDuckGo can now be used for autofilling passwords */ +"credential.provider.activated.title" = "Автоматичното попълване на пароли е активирано!"; + +/* Default string used if users device is not iPhone or iPad */ +"credential.provider.device.type.default" = "устройство"; + +/* Device type is iPhone */ +"credential.provider.device.type.iphone" = "iPhone"; + +/* Device type is iPad */ +"credential.provider.device.type.pad" = "iPad"; + +/* Cancel button for auth when opening login list */ +"credential.provider.list.auth.cancel" = "Отмени"; + +/* Reason for auth when opening screen with list of saved passwords */ +"credential.provider.list.auth.reason" = "Отключете устройството, за да получите достъп до паролите"; + +/* Address label for login details on autofill */ +"credential.provider.list.details.address" = "Адрес на уебсайта"; + +/* Menu item text for copying autofill login details */ +"credential.provider.list.details.copy-prompt" = "Копиране на %@"; + +/* Title for toast when copying address */ +"credential.provider.list.details.copy-toast.address-copied" = "Адресът е копиран"; + +/* Title for toast when copying notes */ +"credential.provider.list.details.copy-toast.notes-copied" = "Бележките са копирани"; + +/* Title for toast when copying password */ +"credential.provider.list.details.copy-toast.password-copied" = "Паролата е копирана"; + +/* Title for toast when copying username */ +"credential.provider.list.details.copy-toast.username-copied" = "Потребителското име е копирано"; + +/* Accessibility title for a Hide Password button replacing displayed password with ***** */ +"credential.provider.list.details.hide-password" = "Скриване на паролата"; + +/* Message displaying when the login was last updated */ +"credential.provider.list.details.last-updated" = "Последна актуализация %@"; + +/* Login name label for login details on autofill */ +"credential.provider.list.details.login-name" = "Заглавие"; + +/* Notes label for login details on autofill */ +"credential.provider.list.details.notes" = "Бележки"; + +/* Password label for login details on autofill */ +"credential.provider.list.details.password" = "Парола"; + +/* Accessibility title for a Show Password button displaying actial password instead of ***** */ +"credential.provider.list.details.show-password" = "Показване на паролата"; + +/* Username label for login details on autofill */ +"credential.provider.list.details.username" = "Потребителско име"; + +/* Footer label displayed below table section with option to enable autofill */ +"credential.provider.list.empty-view.footer" = "Паролите се съхраняват сигурно на Вашето устройство."; + +/* Title for view displayed when autofill has no items */ +"credential.provider.list.empty-view.title" = "Все още няма запазени пароли"; + +/* Prompt above the title for screen listing autofill logins, example: Choose a password to use for "website.com" */ +"credential.provider.list.prompt" = "Избиране на парола, която да бъде използвана за „%@“"; + +/* Placeholder for search field on autofill login listing */ +"credential.provider.list.search-placeholder" = "Търсене на пароли"; + +/* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ +"credential.provider.list.search.no-results.subtitle" = "за '%@'"; + +/* Title displayed when there are no results on Autofill search */ +"credential.provider.list.search.no-results.title" = "Няма резултати"; + +/* Section title for group of suggested saved logins */ +"credential.provider.list.suggested" = "Предложения"; + +/* Title for screen listing autofill logins */ +"credential.provider.list.title" = "Пароли"; + +/* Message for alert when device authentication is not set, where %@ is iPhone|iPad|device */ +"credential.provider.no-device-auth-set.message" = "Задаване на парола на %@ за автоматично попълване на паролите за DuckDuckGo."; + +/* Title for alert when device authentication is not set */ +"credential.provider.no-device-auth-set.title" = "Изисква се парола на устройството"; + diff --git a/AutofillCredentialProvider/cs.lproj/InfoPlist.strings b/AutofillCredentialProvider/cs.lproj/InfoPlist.strings new file mode 100644 index 0000000000..9809aa19f5 --- /dev/null +++ b/AutofillCredentialProvider/cs.lproj/InfoPlist.strings @@ -0,0 +1,9 @@ +/* Bundle display name */ +"CFBundleDisplayName" = "AutofillCredentialProvider"; + +/* Bundle name */ +"CFBundleName" = "AutofillCredentialProvider"; + +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "Copyright © 2024 DuckDuckGo. All rights reserved."; + diff --git a/AutofillCredentialProvider/cs.lproj/Localizable.strings b/AutofillCredentialProvider/cs.lproj/Localizable.strings new file mode 100644 index 0000000000..230c19ae1c --- /dev/null +++ b/AutofillCredentialProvider/cs.lproj/Localizable.strings @@ -0,0 +1,96 @@ +/* Close button title */ +"action.button.close" = "Zavřít"; + +/* Done button title */ +"action.button.done" = "Hotovo"; + +/* Title of button to launch the DuckDuckGo app */ +"credential.provider.activated.button" = "Otevřít DuckDuckGo"; + +/* The title of the screen confirming DuckDuckGo can now be used for autofilling passwords */ +"credential.provider.activated.title" = "Automatické vyplňování hesel je zapnuté."; + +/* Default string used if users device is not iPhone or iPad */ +"credential.provider.device.type.default" = "zařízení"; + +/* Device type is iPhone */ +"credential.provider.device.type.iphone" = "iPhonu"; + +/* Device type is iPad */ +"credential.provider.device.type.pad" = "iPadu"; + +/* Cancel button for auth when opening login list */ +"credential.provider.list.auth.cancel" = "Zrušit"; + +/* Reason for auth when opening screen with list of saved passwords */ +"credential.provider.list.auth.reason" = "Pro přístup k heslům zařízení odemkni"; + +/* Address label for login details on autofill */ +"credential.provider.list.details.address" = "URL webové stránky"; + +/* Menu item text for copying autofill login details */ +"credential.provider.list.details.copy-prompt" = "Kopírovat %@"; + +/* Title for toast when copying address */ +"credential.provider.list.details.copy-toast.address-copied" = "Adresa zkopírovaná"; + +/* Title for toast when copying notes */ +"credential.provider.list.details.copy-toast.notes-copied" = "Poznámky zkopírované"; + +/* Title for toast when copying password */ +"credential.provider.list.details.copy-toast.password-copied" = "Heslo zkopírované"; + +/* Title for toast when copying username */ +"credential.provider.list.details.copy-toast.username-copied" = "Uživatelské jméno zkopírované"; + +/* Accessibility title for a Hide Password button replacing displayed password with ***** */ +"credential.provider.list.details.hide-password" = "Skrýt heslo"; + +/* Message displaying when the login was last updated */ +"credential.provider.list.details.last-updated" = "Poslední aktualizace %@"; + +/* Login name label for login details on autofill */ +"credential.provider.list.details.login-name" = "Název"; + +/* Notes label for login details on autofill */ +"credential.provider.list.details.notes" = "Poznámky"; + +/* Password label for login details on autofill */ +"credential.provider.list.details.password" = "Heslo"; + +/* Accessibility title for a Show Password button displaying actial password instead of ***** */ +"credential.provider.list.details.show-password" = "Zobrazit heslo"; + +/* Username label for login details on autofill */ +"credential.provider.list.details.username" = "Uživatelské jméno"; + +/* Footer label displayed below table section with option to enable autofill */ +"credential.provider.list.empty-view.footer" = "Hesla se bezpečně ukládají do tvého zařízení."; + +/* Title for view displayed when autofill has no items */ +"credential.provider.list.empty-view.title" = "Zatím nemáš uložená žádná hesla"; + +/* Prompt above the title for screen listing autofill logins, example: Choose a password to use for "website.com" */ +"credential.provider.list.prompt" = "Vyber si, které heslo použiješ pro účet %@"; + +/* Placeholder for search field on autofill login listing */ +"credential.provider.list.search-placeholder" = "Prohledat hesla"; + +/* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ +"credential.provider.list.search.no-results.subtitle" = "pro „%@“"; + +/* Title displayed when there are no results on Autofill search */ +"credential.provider.list.search.no-results.title" = "Žádné výsledky"; + +/* Section title for group of suggested saved logins */ +"credential.provider.list.suggested" = "Navrhované"; + +/* Title for screen listing autofill logins */ +"credential.provider.list.title" = "Hesla"; + +/* Message for alert when device authentication is not set, where %@ is iPhone|iPad|device */ +"credential.provider.no-device-auth-set.message" = "Nastav si přístupový kód pro zařízení %@ a DuckDuckGo bude automaticky vyplňovat hesla."; + +/* Title for alert when device authentication is not set */ +"credential.provider.no-device-auth-set.title" = "Přístupový kód pro zařízení je povinný"; + diff --git a/AutofillCredentialProvider/da.lproj/InfoPlist.strings b/AutofillCredentialProvider/da.lproj/InfoPlist.strings new file mode 100644 index 0000000000..9809aa19f5 --- /dev/null +++ b/AutofillCredentialProvider/da.lproj/InfoPlist.strings @@ -0,0 +1,9 @@ +/* Bundle display name */ +"CFBundleDisplayName" = "AutofillCredentialProvider"; + +/* Bundle name */ +"CFBundleName" = "AutofillCredentialProvider"; + +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "Copyright © 2024 DuckDuckGo. All rights reserved."; + diff --git a/AutofillCredentialProvider/da.lproj/Localizable.strings b/AutofillCredentialProvider/da.lproj/Localizable.strings new file mode 100644 index 0000000000..49ea766df6 --- /dev/null +++ b/AutofillCredentialProvider/da.lproj/Localizable.strings @@ -0,0 +1,96 @@ +/* Close button title */ +"action.button.close" = "Luk"; + +/* Done button title */ +"action.button.done" = "Færdig"; + +/* Title of button to launch the DuckDuckGo app */ +"credential.provider.activated.button" = "Åbn DuckDuckGo"; + +/* The title of the screen confirming DuckDuckGo can now be used for autofilling passwords */ +"credential.provider.activated.title" = "Automatisk udfyldning af adgangskoder er aktiveret!"; + +/* Default string used if users device is not iPhone or iPad */ +"credential.provider.device.type.default" = "enhed"; + +/* Device type is iPhone */ +"credential.provider.device.type.iphone" = "iPhone"; + +/* Device type is iPad */ +"credential.provider.device.type.pad" = "iPad"; + +/* Cancel button for auth when opening login list */ +"credential.provider.list.auth.cancel" = "Annullér"; + +/* Reason for auth when opening screen with list of saved passwords */ +"credential.provider.list.auth.reason" = "Lås enheden op for at få adgang til adgangskoder"; + +/* Address label for login details on autofill */ +"credential.provider.list.details.address" = "URL til webstedet"; + +/* Menu item text for copying autofill login details */ +"credential.provider.list.details.copy-prompt" = "Kopiér %@"; + +/* Title for toast when copying address */ +"credential.provider.list.details.copy-toast.address-copied" = "Adresse kopieret"; + +/* Title for toast when copying notes */ +"credential.provider.list.details.copy-toast.notes-copied" = "Noter kopieret"; + +/* Title for toast when copying password */ +"credential.provider.list.details.copy-toast.password-copied" = "Adgangskode kopieret"; + +/* Title for toast when copying username */ +"credential.provider.list.details.copy-toast.username-copied" = "Brugernavn kopieret"; + +/* Accessibility title for a Hide Password button replacing displayed password with ***** */ +"credential.provider.list.details.hide-password" = "Skjul adgangskode"; + +/* Message displaying when the login was last updated */ +"credential.provider.list.details.last-updated" = "Sidst opdateret %@"; + +/* Login name label for login details on autofill */ +"credential.provider.list.details.login-name" = "Titel"; + +/* Notes label for login details on autofill */ +"credential.provider.list.details.notes" = "Noter"; + +/* Password label for login details on autofill */ +"credential.provider.list.details.password" = "Adgangskode"; + +/* Accessibility title for a Show Password button displaying actial password instead of ***** */ +"credential.provider.list.details.show-password" = "Vis adgangskode"; + +/* Username label for login details on autofill */ +"credential.provider.list.details.username" = "Brugernavn"; + +/* Footer label displayed below table section with option to enable autofill */ +"credential.provider.list.empty-view.footer" = "Adgangskoder gemmes sikkert på din enhed."; + +/* Title for view displayed when autofill has no items */ +"credential.provider.list.empty-view.title" = "Ingen adgangskoder gemt endnu"; + +/* Prompt above the title for screen listing autofill logins, example: Choose a password to use for "website.com" */ +"credential.provider.list.prompt" = "Vælg en adgangskode til \"%@\""; + +/* Placeholder for search field on autofill login listing */ +"credential.provider.list.search-placeholder" = "Søg adgangskoder"; + +/* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ +"credential.provider.list.search.no-results.subtitle" = "for '%@'"; + +/* Title displayed when there are no results on Autofill search */ +"credential.provider.list.search.no-results.title" = "Ingen resultater"; + +/* Section title for group of suggested saved logins */ +"credential.provider.list.suggested" = "Foreslået"; + +/* Title for screen listing autofill logins */ +"credential.provider.list.title" = "Adgangskoder"; + +/* Message for alert when device authentication is not set, where %@ is iPhone|iPad|device */ +"credential.provider.no-device-auth-set.message" = "Opret en adgangskode på %@ for automatisk at udfylde dine DuckDuckGo-adgangskoder."; + +/* Title for alert when device authentication is not set */ +"credential.provider.no-device-auth-set.title" = "Adgangskode til enheden påkrævet"; + diff --git a/AutofillCredentialProvider/de.lproj/InfoPlist.strings b/AutofillCredentialProvider/de.lproj/InfoPlist.strings new file mode 100644 index 0000000000..9809aa19f5 --- /dev/null +++ b/AutofillCredentialProvider/de.lproj/InfoPlist.strings @@ -0,0 +1,9 @@ +/* Bundle display name */ +"CFBundleDisplayName" = "AutofillCredentialProvider"; + +/* Bundle name */ +"CFBundleName" = "AutofillCredentialProvider"; + +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "Copyright © 2024 DuckDuckGo. All rights reserved."; + diff --git a/AutofillCredentialProvider/de.lproj/Localizable.strings b/AutofillCredentialProvider/de.lproj/Localizable.strings new file mode 100644 index 0000000000..e36875c16b --- /dev/null +++ b/AutofillCredentialProvider/de.lproj/Localizable.strings @@ -0,0 +1,96 @@ +/* Close button title */ +"action.button.close" = "Schließen"; + +/* Done button title */ +"action.button.done" = "Fertig"; + +/* Title of button to launch the DuckDuckGo app */ +"credential.provider.activated.button" = "DuckDuckGo öffnen"; + +/* The title of the screen confirming DuckDuckGo can now be used for autofilling passwords */ +"credential.provider.activated.title" = "Automatisches Ausfüllen von Passwörtern aktiviert!"; + +/* Default string used if users device is not iPhone or iPad */ +"credential.provider.device.type.default" = "Gerät"; + +/* Device type is iPhone */ +"credential.provider.device.type.iphone" = "iPhone"; + +/* Device type is iPad */ +"credential.provider.device.type.pad" = "iPad"; + +/* Cancel button for auth when opening login list */ +"credential.provider.list.auth.cancel" = "Abbrechen"; + +/* Reason for auth when opening screen with list of saved passwords */ +"credential.provider.list.auth.reason" = "Gerät entsperren, um auf Passwörter zuzugreifen"; + +/* Address label for login details on autofill */ +"credential.provider.list.details.address" = "URL der Website"; + +/* Menu item text for copying autofill login details */ +"credential.provider.list.details.copy-prompt" = "%@ kopieren"; + +/* Title for toast when copying address */ +"credential.provider.list.details.copy-toast.address-copied" = "Adresse kopiert"; + +/* Title for toast when copying notes */ +"credential.provider.list.details.copy-toast.notes-copied" = "Notizen kopiert"; + +/* Title for toast when copying password */ +"credential.provider.list.details.copy-toast.password-copied" = "Passwort kopiert"; + +/* Title for toast when copying username */ +"credential.provider.list.details.copy-toast.username-copied" = "Benutzername kopiert"; + +/* Accessibility title for a Hide Password button replacing displayed password with ***** */ +"credential.provider.list.details.hide-password" = "Passwort ausblenden"; + +/* Message displaying when the login was last updated */ +"credential.provider.list.details.last-updated" = "Zuletzt aktualisiert %@"; + +/* Login name label for login details on autofill */ +"credential.provider.list.details.login-name" = "Titel"; + +/* Notes label for login details on autofill */ +"credential.provider.list.details.notes" = "Notizen"; + +/* Password label for login details on autofill */ +"credential.provider.list.details.password" = "Passwort"; + +/* Accessibility title for a Show Password button displaying actial password instead of ***** */ +"credential.provider.list.details.show-password" = "Passwort anzeigen"; + +/* Username label for login details on autofill */ +"credential.provider.list.details.username" = "Benutzername"; + +/* Footer label displayed below table section with option to enable autofill */ +"credential.provider.list.empty-view.footer" = "Passwörter werden sicher auf deinem Gerät gespeichert."; + +/* Title for view displayed when autofill has no items */ +"credential.provider.list.empty-view.title" = "Noch keine Passwörter gespeichert"; + +/* Prompt above the title for screen listing autofill logins, example: Choose a password to use for "website.com" */ +"credential.provider.list.prompt" = "Wähle ein Passwort, das du für „%@“ verwendest"; + +/* Placeholder for search field on autofill login listing */ +"credential.provider.list.search-placeholder" = "Passwörter suchen"; + +/* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ +"credential.provider.list.search.no-results.subtitle" = "für „%@“"; + +/* Title displayed when there are no results on Autofill search */ +"credential.provider.list.search.no-results.title" = "Keine Ergebnisse"; + +/* Section title for group of suggested saved logins */ +"credential.provider.list.suggested" = "Vorgeschlagen"; + +/* Title for screen listing autofill logins */ +"credential.provider.list.title" = "Passwörter"; + +/* Message for alert when device authentication is not set, where %@ is iPhone|iPad|device */ +"credential.provider.no-device-auth-set.message" = "Lege einen Passcode für dein %@ fest, um deine DuckDuckGo-Passwörter automatisch auszufüllen."; + +/* Title for alert when device authentication is not set */ +"credential.provider.no-device-auth-set.title" = "Geräte-Passcode erforderlich"; + diff --git a/AutofillCredentialProvider/el.lproj/InfoPlist.strings b/AutofillCredentialProvider/el.lproj/InfoPlist.strings new file mode 100644 index 0000000000..9809aa19f5 --- /dev/null +++ b/AutofillCredentialProvider/el.lproj/InfoPlist.strings @@ -0,0 +1,9 @@ +/* Bundle display name */ +"CFBundleDisplayName" = "AutofillCredentialProvider"; + +/* Bundle name */ +"CFBundleName" = "AutofillCredentialProvider"; + +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "Copyright © 2024 DuckDuckGo. All rights reserved."; + diff --git a/AutofillCredentialProvider/el.lproj/Localizable.strings b/AutofillCredentialProvider/el.lproj/Localizable.strings new file mode 100644 index 0000000000..cc073f02b6 --- /dev/null +++ b/AutofillCredentialProvider/el.lproj/Localizable.strings @@ -0,0 +1,96 @@ +/* Close button title */ +"action.button.close" = "Κλείσιμο"; + +/* Done button title */ +"action.button.done" = "Ολοκληρώθηκε"; + +/* Title of button to launch the DuckDuckGo app */ +"credential.provider.activated.button" = "Άνοιγμα του DuckDuckGo"; + +/* The title of the screen confirming DuckDuckGo can now be used for autofilling passwords */ +"credential.provider.activated.title" = "Η Αυτόματη συμπλήρωση κωδικών πρόσβασης ενεργοποιήθηκε!"; + +/* Default string used if users device is not iPhone or iPad */ +"credential.provider.device.type.default" = "συσκευή"; + +/* Device type is iPhone */ +"credential.provider.device.type.iphone" = "iPhone"; + +/* Device type is iPad */ +"credential.provider.device.type.pad" = "iPad"; + +/* Cancel button for auth when opening login list */ +"credential.provider.list.auth.cancel" = "Ακύρωση"; + +/* Reason for auth when opening screen with list of saved passwords */ +"credential.provider.list.auth.reason" = "Ξεκλειδώστε τη συσκευή για πρόσβαση σε κωδικούς πρόσβασης"; + +/* Address label for login details on autofill */ +"credential.provider.list.details.address" = "Διεύθυνση URL ιστότοπου"; + +/* Menu item text for copying autofill login details */ +"credential.provider.list.details.copy-prompt" = "Αντιγραφή %@"; + +/* Title for toast when copying address */ +"credential.provider.list.details.copy-toast.address-copied" = "Η διεύθυνση αντιγράφηκε"; + +/* Title for toast when copying notes */ +"credential.provider.list.details.copy-toast.notes-copied" = "Οι σημειώσεις αντιγράφηκαν"; + +/* Title for toast when copying password */ +"credential.provider.list.details.copy-toast.password-copied" = "Ο κωδικός πρόσβασης αντιγράφηκε"; + +/* Title for toast when copying username */ +"credential.provider.list.details.copy-toast.username-copied" = "Το όνομα χρήστη αντιγράφηκε"; + +/* Accessibility title for a Hide Password button replacing displayed password with ***** */ +"credential.provider.list.details.hide-password" = "Απόκρυψη κωδικού πρόσβασης"; + +/* Message displaying when the login was last updated */ +"credential.provider.list.details.last-updated" = "Τελευταία ενημέρωση %@"; + +/* Login name label for login details on autofill */ +"credential.provider.list.details.login-name" = "Τίτλος"; + +/* Notes label for login details on autofill */ +"credential.provider.list.details.notes" = "Σημειώσεις"; + +/* Password label for login details on autofill */ +"credential.provider.list.details.password" = "Κωδικός πρόσβασης"; + +/* Accessibility title for a Show Password button displaying actial password instead of ***** */ +"credential.provider.list.details.show-password" = "Εμφάνιση κωδικού πρόσβασης"; + +/* Username label for login details on autofill */ +"credential.provider.list.details.username" = "Όνομα χρήστη"; + +/* Footer label displayed below table section with option to enable autofill */ +"credential.provider.list.empty-view.footer" = "Οι κωδικοί πρόσβασης αποθηκεύονται με ασφάλεια στη συσκευή σας."; + +/* Title for view displayed when autofill has no items */ +"credential.provider.list.empty-view.title" = "Δεν έχουν αποθηκευτεί ακόμα κωδικοί πρόσβασης"; + +/* Prompt above the title for screen listing autofill logins, example: Choose a password to use for "website.com" */ +"credential.provider.list.prompt" = "Επιλέξτε έναν κωδικό πρόσβασης για χρήση στο «%@»"; + +/* Placeholder for search field on autofill login listing */ +"credential.provider.list.search-placeholder" = "Αναζήτηση κωδικών πρόσβασης"; + +/* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ +"credential.provider.list.search.no-results.subtitle" = "για '%@'"; + +/* Title displayed when there are no results on Autofill search */ +"credential.provider.list.search.no-results.title" = "Κανένα αποτέλεσμα"; + +/* Section title for group of suggested saved logins */ +"credential.provider.list.suggested" = "Προτεινόμενο"; + +/* Title for screen listing autofill logins */ +"credential.provider.list.title" = "Κωδικός πρόσβασης"; + +/* Message for alert when device authentication is not set, where %@ is iPhone|iPad|device */ +"credential.provider.no-device-auth-set.message" = "Ορίστε έναν κωδικό πρόσβασης στο %@ για αυτόματη συμπλήρωση των κωδικών πρόσβασης DuckDuckGo."; + +/* Title for alert when device authentication is not set */ +"credential.provider.no-device-auth-set.title" = "Απαιτείται κωδικός πρόσβασης συσκευής"; + diff --git a/AutofillCredentialProvider/es.lproj/InfoPlist.strings b/AutofillCredentialProvider/es.lproj/InfoPlist.strings new file mode 100644 index 0000000000..9809aa19f5 --- /dev/null +++ b/AutofillCredentialProvider/es.lproj/InfoPlist.strings @@ -0,0 +1,9 @@ +/* Bundle display name */ +"CFBundleDisplayName" = "AutofillCredentialProvider"; + +/* Bundle name */ +"CFBundleName" = "AutofillCredentialProvider"; + +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "Copyright © 2024 DuckDuckGo. All rights reserved."; + diff --git a/AutofillCredentialProvider/es.lproj/Localizable.strings b/AutofillCredentialProvider/es.lproj/Localizable.strings new file mode 100644 index 0000000000..572db888b4 --- /dev/null +++ b/AutofillCredentialProvider/es.lproj/Localizable.strings @@ -0,0 +1,96 @@ +/* Close button title */ +"action.button.close" = "Cerrar"; + +/* Done button title */ +"action.button.done" = "Hecho"; + +/* Title of button to launch the DuckDuckGo app */ +"credential.provider.activated.button" = "Abrir DuckDuckGo"; + +/* The title of the screen confirming DuckDuckGo can now be used for autofilling passwords */ +"credential.provider.activated.title" = "¡La función de autocompletar contraseñas está activada!"; + +/* Default string used if users device is not iPhone or iPad */ +"credential.provider.device.type.default" = "dispositivo"; + +/* Device type is iPhone */ +"credential.provider.device.type.iphone" = "iPhone"; + +/* Device type is iPad */ +"credential.provider.device.type.pad" = "iPad"; + +/* Cancel button for auth when opening login list */ +"credential.provider.list.auth.cancel" = "Cancelar"; + +/* Reason for auth when opening screen with list of saved passwords */ +"credential.provider.list.auth.reason" = "Desbloquear dispositivo para acceder a contraseñas"; + +/* Address label for login details on autofill */ +"credential.provider.list.details.address" = "URL del sitio web"; + +/* Menu item text for copying autofill login details */ +"credential.provider.list.details.copy-prompt" = "Copiar %@"; + +/* Title for toast when copying address */ +"credential.provider.list.details.copy-toast.address-copied" = "Dirección copiada"; + +/* Title for toast when copying notes */ +"credential.provider.list.details.copy-toast.notes-copied" = "Notas copiadas"; + +/* Title for toast when copying password */ +"credential.provider.list.details.copy-toast.password-copied" = "Contraseña copiada"; + +/* Title for toast when copying username */ +"credential.provider.list.details.copy-toast.username-copied" = "Nombre de usuario copiado"; + +/* Accessibility title for a Hide Password button replacing displayed password with ***** */ +"credential.provider.list.details.hide-password" = "Ocultar contraseña"; + +/* Message displaying when the login was last updated */ +"credential.provider.list.details.last-updated" = "Última actualización % @"; + +/* Login name label for login details on autofill */ +"credential.provider.list.details.login-name" = "Título"; + +/* Notes label for login details on autofill */ +"credential.provider.list.details.notes" = "Notas"; + +/* Password label for login details on autofill */ +"credential.provider.list.details.password" = "Contraseña"; + +/* Accessibility title for a Show Password button displaying actial password instead of ***** */ +"credential.provider.list.details.show-password" = "Mostrar contraseña"; + +/* Username label for login details on autofill */ +"credential.provider.list.details.username" = "Nombre de usuario"; + +/* Footer label displayed below table section with option to enable autofill */ +"credential.provider.list.empty-view.footer" = "Las contraseñas se almacenan de forma segura en tu dispositivo."; + +/* Title for view displayed when autofill has no items */ +"credential.provider.list.empty-view.title" = "Aún no hay contraseñas guardadas"; + +/* Prompt above the title for screen listing autofill logins, example: Choose a password to use for "website.com" */ +"credential.provider.list.prompt" = "Elige una contraseña para \"%@\""; + +/* Placeholder for search field on autofill login listing */ +"credential.provider.list.search-placeholder" = "Buscar contraseñas"; + +/* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ +"credential.provider.list.search.no-results.subtitle" = "para '%@'"; + +/* Title displayed when there are no results on Autofill search */ +"credential.provider.list.search.no-results.title" = "Sin resultados"; + +/* Section title for group of suggested saved logins */ +"credential.provider.list.suggested" = "Sugerencias"; + +/* Title for screen listing autofill logins */ +"credential.provider.list.title" = "Contraseñas"; + +/* Message for alert when device authentication is not set, where %@ is iPhone|iPad|device */ +"credential.provider.no-device-auth-set.message" = "Configura un código de acceso en %@ para autocompletar tus contraseñas de DuckDuckGo."; + +/* Title for alert when device authentication is not set */ +"credential.provider.no-device-auth-set.title" = "Se requiere código de acceso del dispositivo"; + diff --git a/AutofillCredentialProvider/et.lproj/InfoPlist.strings b/AutofillCredentialProvider/et.lproj/InfoPlist.strings new file mode 100644 index 0000000000..9809aa19f5 --- /dev/null +++ b/AutofillCredentialProvider/et.lproj/InfoPlist.strings @@ -0,0 +1,9 @@ +/* Bundle display name */ +"CFBundleDisplayName" = "AutofillCredentialProvider"; + +/* Bundle name */ +"CFBundleName" = "AutofillCredentialProvider"; + +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "Copyright © 2024 DuckDuckGo. All rights reserved."; + diff --git a/AutofillCredentialProvider/et.lproj/Localizable.strings b/AutofillCredentialProvider/et.lproj/Localizable.strings new file mode 100644 index 0000000000..0e60b0e2e6 --- /dev/null +++ b/AutofillCredentialProvider/et.lproj/Localizable.strings @@ -0,0 +1,96 @@ +/* Close button title */ +"action.button.close" = "Sulge"; + +/* Done button title */ +"action.button.done" = "Valmis"; + +/* Title of button to launch the DuckDuckGo app */ +"credential.provider.activated.button" = "Ava DuckDuckGo"; + +/* The title of the screen confirming DuckDuckGo can now be used for autofilling passwords */ +"credential.provider.activated.title" = "Paroolide automaatne täitmine on aktiveeritud!"; + +/* Default string used if users device is not iPhone or iPad */ +"credential.provider.device.type.default" = "seade"; + +/* Device type is iPhone */ +"credential.provider.device.type.iphone" = "iPhone"; + +/* Device type is iPad */ +"credential.provider.device.type.pad" = "iPad"; + +/* Cancel button for auth when opening login list */ +"credential.provider.list.auth.cancel" = "Tühista"; + +/* Reason for auth when opening screen with list of saved passwords */ +"credential.provider.list.auth.reason" = "Paroolidele juurdepääsuks ava seade"; + +/* Address label for login details on autofill */ +"credential.provider.list.details.address" = "Veebisaidi URL"; + +/* Menu item text for copying autofill login details */ +"credential.provider.list.details.copy-prompt" = "Kopeeri %@"; + +/* Title for toast when copying address */ +"credential.provider.list.details.copy-toast.address-copied" = "Aadress on kopeeritud"; + +/* Title for toast when copying notes */ +"credential.provider.list.details.copy-toast.notes-copied" = "Märkmed on kopeeritud"; + +/* Title for toast when copying password */ +"credential.provider.list.details.copy-toast.password-copied" = "Parool on kopeeritud"; + +/* Title for toast when copying username */ +"credential.provider.list.details.copy-toast.username-copied" = "Kasutajanimi on kopeeritud"; + +/* Accessibility title for a Hide Password button replacing displayed password with ***** */ +"credential.provider.list.details.hide-password" = "Peida parool"; + +/* Message displaying when the login was last updated */ +"credential.provider.list.details.last-updated" = "Viimati uuendatud %@"; + +/* Login name label for login details on autofill */ +"credential.provider.list.details.login-name" = "Pealkiri"; + +/* Notes label for login details on autofill */ +"credential.provider.list.details.notes" = "Märkused"; + +/* Password label for login details on autofill */ +"credential.provider.list.details.password" = "Parool"; + +/* Accessibility title for a Show Password button displaying actial password instead of ***** */ +"credential.provider.list.details.show-password" = "Kuva parool"; + +/* Username label for login details on autofill */ +"credential.provider.list.details.username" = "Kasutajanimi"; + +/* Footer label displayed below table section with option to enable autofill */ +"credential.provider.list.empty-view.footer" = "Paroolid salvestatakse turvaliselt sinu seadmesse."; + +/* Title for view displayed when autofill has no items */ +"credential.provider.list.empty-view.title" = "Paroole ei ole veel salvestatud"; + +/* Prompt above the title for screen listing autofill logins, example: Choose a password to use for "website.com" */ +"credential.provider.list.prompt" = "Valige salasõna, mida kasutada \"%@\" jaoks"; + +/* Placeholder for search field on autofill login listing */ +"credential.provider.list.search-placeholder" = "Otsi paroole"; + +/* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ +"credential.provider.list.search.no-results.subtitle" = "otsinguga '%@'"; + +/* Title displayed when there are no results on Autofill search */ +"credential.provider.list.search.no-results.title" = "Tulemusi pole"; + +/* Section title for group of suggested saved logins */ +"credential.provider.list.suggested" = "Soovitatud"; + +/* Title for screen listing autofill logins */ +"credential.provider.list.title" = "Paroolid"; + +/* Message for alert when device authentication is not set, where %@ is iPhone|iPad|device */ +"credential.provider.no-device-auth-set.message" = "DuckDuckGo paroolide automaatseks täitmiseks määrake saidile %@ pääsukood."; + +/* Title for alert when device authentication is not set */ +"credential.provider.no-device-auth-set.title" = "Nõutav seadme pääsukood"; + diff --git a/AutofillCredentialProvider/fi.lproj/InfoPlist.strings b/AutofillCredentialProvider/fi.lproj/InfoPlist.strings new file mode 100644 index 0000000000..9809aa19f5 --- /dev/null +++ b/AutofillCredentialProvider/fi.lproj/InfoPlist.strings @@ -0,0 +1,9 @@ +/* Bundle display name */ +"CFBundleDisplayName" = "AutofillCredentialProvider"; + +/* Bundle name */ +"CFBundleName" = "AutofillCredentialProvider"; + +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "Copyright © 2024 DuckDuckGo. All rights reserved."; + diff --git a/AutofillCredentialProvider/fi.lproj/Localizable.strings b/AutofillCredentialProvider/fi.lproj/Localizable.strings new file mode 100644 index 0000000000..6bbcdd63c0 --- /dev/null +++ b/AutofillCredentialProvider/fi.lproj/Localizable.strings @@ -0,0 +1,96 @@ +/* Close button title */ +"action.button.close" = "Sulje"; + +/* Done button title */ +"action.button.done" = "Valmis"; + +/* Title of button to launch the DuckDuckGo app */ +"credential.provider.activated.button" = "Avaa DuckDuckGo"; + +/* The title of the screen confirming DuckDuckGo can now be used for autofilling passwords */ +"credential.provider.activated.title" = "Salasanojen automaattinen täyttö on nyt käytössä!"; + +/* Default string used if users device is not iPhone or iPad */ +"credential.provider.device.type.default" = "laitteelle"; + +/* Device type is iPhone */ +"credential.provider.device.type.iphone" = "iPhonelle"; + +/* Device type is iPad */ +"credential.provider.device.type.pad" = "iPadille"; + +/* Cancel button for auth when opening login list */ +"credential.provider.list.auth.cancel" = "Peruuta"; + +/* Reason for auth when opening screen with list of saved passwords */ +"credential.provider.list.auth.reason" = "Avaa laitteen lukitus päästäksesi salasanoihin"; + +/* Address label for login details on autofill */ +"credential.provider.list.details.address" = "Sivuston URL-osoite"; + +/* Menu item text for copying autofill login details */ +"credential.provider.list.details.copy-prompt" = "Kopioi %@"; + +/* Title for toast when copying address */ +"credential.provider.list.details.copy-toast.address-copied" = "Osoite kopioitu"; + +/* Title for toast when copying notes */ +"credential.provider.list.details.copy-toast.notes-copied" = "Muistiinpanot kopioitu"; + +/* Title for toast when copying password */ +"credential.provider.list.details.copy-toast.password-copied" = "Salasana kopioitu"; + +/* Title for toast when copying username */ +"credential.provider.list.details.copy-toast.username-copied" = "Käyttäjätunnus kopioitu"; + +/* Accessibility title for a Hide Password button replacing displayed password with ***** */ +"credential.provider.list.details.hide-password" = "Piilota salasana"; + +/* Message displaying when the login was last updated */ +"credential.provider.list.details.last-updated" = "Viimeksi päivitetty %@"; + +/* Login name label for login details on autofill */ +"credential.provider.list.details.login-name" = "Otsikko"; + +/* Notes label for login details on autofill */ +"credential.provider.list.details.notes" = "Huomautukset"; + +/* Password label for login details on autofill */ +"credential.provider.list.details.password" = "Salasana"; + +/* Accessibility title for a Show Password button displaying actial password instead of ***** */ +"credential.provider.list.details.show-password" = "Näytä salasana"; + +/* Username label for login details on autofill */ +"credential.provider.list.details.username" = "Käyttäjätunnus"; + +/* Footer label displayed below table section with option to enable autofill */ +"credential.provider.list.empty-view.footer" = "Salasanat tallennetaan laitteellesi turvallisesti."; + +/* Title for view displayed when autofill has no items */ +"credential.provider.list.empty-view.title" = "Salasanoja ei ole vielä tallennettu"; + +/* Prompt above the title for screen listing autofill logins, example: Choose a password to use for "website.com" */ +"credential.provider.list.prompt" = "Valitse sivuston salasana: %@"; + +/* Placeholder for search field on autofill login listing */ +"credential.provider.list.search-placeholder" = "Etsi salasanoja"; + +/* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ +"credential.provider.list.search.no-results.subtitle" = "kohteelle '%@'"; + +/* Title displayed when there are no results on Autofill search */ +"credential.provider.list.search.no-results.title" = "Ei tuloksia"; + +/* Section title for group of suggested saved logins */ +"credential.provider.list.suggested" = "Ehdotettu"; + +/* Title for screen listing autofill logins */ +"credential.provider.list.title" = "Salasanat"; + +/* Message for alert when device authentication is not set, where %@ is iPhone|iPad|device */ +"credential.provider.no-device-auth-set.message" = "Jos haluat, että DuckDuckGo täyttää salasanasi automaattisesti, määritä pääsykoodi laitteessa %@."; + +/* Title for alert when device authentication is not set */ +"credential.provider.no-device-auth-set.title" = "Edellyttää laitteen pääsykoodia"; + diff --git a/AutofillCredentialProvider/fr.lproj/InfoPlist.strings b/AutofillCredentialProvider/fr.lproj/InfoPlist.strings new file mode 100644 index 0000000000..9809aa19f5 --- /dev/null +++ b/AutofillCredentialProvider/fr.lproj/InfoPlist.strings @@ -0,0 +1,9 @@ +/* Bundle display name */ +"CFBundleDisplayName" = "AutofillCredentialProvider"; + +/* Bundle name */ +"CFBundleName" = "AutofillCredentialProvider"; + +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "Copyright © 2024 DuckDuckGo. All rights reserved."; + diff --git a/AutofillCredentialProvider/fr.lproj/Localizable.strings b/AutofillCredentialProvider/fr.lproj/Localizable.strings new file mode 100644 index 0000000000..8f01a4e036 --- /dev/null +++ b/AutofillCredentialProvider/fr.lproj/Localizable.strings @@ -0,0 +1,96 @@ +/* Close button title */ +"action.button.close" = "Fermer"; + +/* Done button title */ +"action.button.done" = "Terminé"; + +/* Title of button to launch the DuckDuckGo app */ +"credential.provider.activated.button" = "Ouvrir DuckDuckGo"; + +/* The title of the screen confirming DuckDuckGo can now be used for autofilling passwords */ +"credential.provider.activated.title" = "Saisie automatique des mots de passe activée !"; + +/* Default string used if users device is not iPhone or iPad */ +"credential.provider.device.type.default" = "appareil"; + +/* Device type is iPhone */ +"credential.provider.device.type.iphone" = "iPhone"; + +/* Device type is iPad */ +"credential.provider.device.type.pad" = "iPad"; + +/* Cancel button for auth when opening login list */ +"credential.provider.list.auth.cancel" = "Annuler"; + +/* Reason for auth when opening screen with list of saved passwords */ +"credential.provider.list.auth.reason" = "Déverrouiller l'appareil pour accéder aux mots de passe"; + +/* Address label for login details on autofill */ +"credential.provider.list.details.address" = "URL du site Web"; + +/* Menu item text for copying autofill login details */ +"credential.provider.list.details.copy-prompt" = "Copier %@"; + +/* Title for toast when copying address */ +"credential.provider.list.details.copy-toast.address-copied" = "Adresse copiée"; + +/* Title for toast when copying notes */ +"credential.provider.list.details.copy-toast.notes-copied" = "Notes copiées"; + +/* Title for toast when copying password */ +"credential.provider.list.details.copy-toast.password-copied" = "Mot de passe copié"; + +/* Title for toast when copying username */ +"credential.provider.list.details.copy-toast.username-copied" = "Nom d'utilisateur copié"; + +/* Accessibility title for a Hide Password button replacing displayed password with ***** */ +"credential.provider.list.details.hide-password" = "Masquer le mot de passe"; + +/* Message displaying when the login was last updated */ +"credential.provider.list.details.last-updated" = "Dernière modification : %@"; + +/* Login name label for login details on autofill */ +"credential.provider.list.details.login-name" = "Titre"; + +/* Notes label for login details on autofill */ +"credential.provider.list.details.notes" = "Notes"; + +/* Password label for login details on autofill */ +"credential.provider.list.details.password" = "Mot de passe"; + +/* Accessibility title for a Show Password button displaying actial password instead of ***** */ +"credential.provider.list.details.show-password" = "Afficher le mot de passe"; + +/* Username label for login details on autofill */ +"credential.provider.list.details.username" = "Nom d'utilisateur"; + +/* Footer label displayed below table section with option to enable autofill */ +"credential.provider.list.empty-view.footer" = "Les mots de passe sont stockés en toute sécurité sur votre appareil."; + +/* Title for view displayed when autofill has no items */ +"credential.provider.list.empty-view.title" = "Aucun mot de passe n'a été enregistré"; + +/* Prompt above the title for screen listing autofill logins, example: Choose a password to use for "website.com" */ +"credential.provider.list.prompt" = "Choisissez un mot de passe à utiliser pour « %@ »"; + +/* Placeholder for search field on autofill login listing */ +"credential.provider.list.search-placeholder" = "Rechercher un mot de passe"; + +/* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ +"credential.provider.list.search.no-results.subtitle" = "pour '%@'"; + +/* Title displayed when there are no results on Autofill search */ +"credential.provider.list.search.no-results.title" = "Aucun résultat"; + +/* Section title for group of suggested saved logins */ +"credential.provider.list.suggested" = "Suggéré"; + +/* Title for screen listing autofill logins */ +"credential.provider.list.title" = "Mots de passe"; + +/* Message for alert when device authentication is not set, where %@ is iPhone|iPad|device */ +"credential.provider.no-device-auth-set.message" = "Définissez un code d'accès sur %@ pour saisir automatiquement vos mots de passe DuckDuckGo."; + +/* Title for alert when device authentication is not set */ +"credential.provider.no-device-auth-set.title" = "Code d'accès de l'appareil requis"; + diff --git a/AutofillCredentialProvider/hr.lproj/InfoPlist.strings b/AutofillCredentialProvider/hr.lproj/InfoPlist.strings new file mode 100644 index 0000000000..9809aa19f5 --- /dev/null +++ b/AutofillCredentialProvider/hr.lproj/InfoPlist.strings @@ -0,0 +1,9 @@ +/* Bundle display name */ +"CFBundleDisplayName" = "AutofillCredentialProvider"; + +/* Bundle name */ +"CFBundleName" = "AutofillCredentialProvider"; + +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "Copyright © 2024 DuckDuckGo. All rights reserved."; + diff --git a/AutofillCredentialProvider/hr.lproj/Localizable.strings b/AutofillCredentialProvider/hr.lproj/Localizable.strings new file mode 100644 index 0000000000..38cc9387d7 --- /dev/null +++ b/AutofillCredentialProvider/hr.lproj/Localizable.strings @@ -0,0 +1,96 @@ +/* Close button title */ +"action.button.close" = "Zatvori"; + +/* Done button title */ +"action.button.done" = "Gotovo"; + +/* Title of button to launch the DuckDuckGo app */ +"credential.provider.activated.button" = "Otvori DuckDuckGo"; + +/* The title of the screen confirming DuckDuckGo can now be used for autofilling passwords */ +"credential.provider.activated.title" = "Automatsko popunjavanje lozinki je aktivirano!"; + +/* Default string used if users device is not iPhone or iPad */ +"credential.provider.device.type.default" = "uređaj"; + +/* Device type is iPhone */ +"credential.provider.device.type.iphone" = "iPhone"; + +/* Device type is iPad */ +"credential.provider.device.type.pad" = "iPad"; + +/* Cancel button for auth when opening login list */ +"credential.provider.list.auth.cancel" = "Otkaži"; + +/* Reason for auth when opening screen with list of saved passwords */ +"credential.provider.list.auth.reason" = "Otključaj uređaj za pristup lozinkama"; + +/* Address label for login details on autofill */ +"credential.provider.list.details.address" = "URL web lokacije"; + +/* Menu item text for copying autofill login details */ +"credential.provider.list.details.copy-prompt" = "Kopiraj %@"; + +/* Title for toast when copying address */ +"credential.provider.list.details.copy-toast.address-copied" = "Adresa je kopirana"; + +/* Title for toast when copying notes */ +"credential.provider.list.details.copy-toast.notes-copied" = "Bilješke su kopirane"; + +/* Title for toast when copying password */ +"credential.provider.list.details.copy-toast.password-copied" = "Lozinka je kopirana"; + +/* Title for toast when copying username */ +"credential.provider.list.details.copy-toast.username-copied" = "Korisničko ime je kopirano"; + +/* Accessibility title for a Hide Password button replacing displayed password with ***** */ +"credential.provider.list.details.hide-password" = "Sakrij lozinku"; + +/* Message displaying when the login was last updated */ +"credential.provider.list.details.last-updated" = "Posljednje ažuriranje: %@"; + +/* Login name label for login details on autofill */ +"credential.provider.list.details.login-name" = "Naslov"; + +/* Notes label for login details on autofill */ +"credential.provider.list.details.notes" = "Bilješke"; + +/* Password label for login details on autofill */ +"credential.provider.list.details.password" = "Lozinka"; + +/* Accessibility title for a Show Password button displaying actial password instead of ***** */ +"credential.provider.list.details.show-password" = "Pokaži lozinku"; + +/* Username label for login details on autofill */ +"credential.provider.list.details.username" = "Korisničko ime"; + +/* Footer label displayed below table section with option to enable autofill */ +"credential.provider.list.empty-view.footer" = "Lozinke su sigurno pohranjene na tvom uređaju."; + +/* Title for view displayed when autofill has no items */ +"credential.provider.list.empty-view.title" = "Još nema spremljenih lozinki"; + +/* Prompt above the title for screen listing autofill logins, example: Choose a password to use for "website.com" */ +"credential.provider.list.prompt" = "Odaberi lozinku koju ćeš koristiti za \"%@\""; + +/* Placeholder for search field on autofill login listing */ +"credential.provider.list.search-placeholder" = "Pretraživanje lozinki"; + +/* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ +"credential.provider.list.search.no-results.subtitle" = "za '%@'"; + +/* Title displayed when there are no results on Autofill search */ +"credential.provider.list.search.no-results.title" = "Nema rezultata"; + +/* Section title for group of suggested saved logins */ +"credential.provider.list.suggested" = "Predloženo"; + +/* Title for screen listing autofill logins */ +"credential.provider.list.title" = "Lozinke"; + +/* Message for alert when device authentication is not set, where %@ is iPhone|iPad|device */ +"credential.provider.no-device-auth-set.message" = "Postavi šifru na uređaju %@ kako bi se tvoje DuckDuckGo lozinke popunjavale automatski."; + +/* Title for alert when device authentication is not set */ +"credential.provider.no-device-auth-set.title" = "Potrebna je šifra uređaja."; + diff --git a/AutofillCredentialProvider/hu.lproj/InfoPlist.strings b/AutofillCredentialProvider/hu.lproj/InfoPlist.strings new file mode 100644 index 0000000000..9809aa19f5 --- /dev/null +++ b/AutofillCredentialProvider/hu.lproj/InfoPlist.strings @@ -0,0 +1,9 @@ +/* Bundle display name */ +"CFBundleDisplayName" = "AutofillCredentialProvider"; + +/* Bundle name */ +"CFBundleName" = "AutofillCredentialProvider"; + +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "Copyright © 2024 DuckDuckGo. All rights reserved."; + diff --git a/AutofillCredentialProvider/hu.lproj/Localizable.strings b/AutofillCredentialProvider/hu.lproj/Localizable.strings new file mode 100644 index 0000000000..c21a3bb9fb --- /dev/null +++ b/AutofillCredentialProvider/hu.lproj/Localizable.strings @@ -0,0 +1,96 @@ +/* Close button title */ +"action.button.close" = "Bezárás"; + +/* Done button title */ +"action.button.done" = "Kész"; + +/* Title of button to launch the DuckDuckGo app */ +"credential.provider.activated.button" = "Nyisd meg a DuckDuckGo-alkalmazást"; + +/* The title of the screen confirming DuckDuckGo can now be used for autofilling passwords */ +"credential.provider.activated.title" = "Jelszavak automatikus kitöltése aktiválva!"; + +/* Default string used if users device is not iPhone or iPad */ +"credential.provider.device.type.default" = "eszközön"; + +/* Device type is iPhone */ +"credential.provider.device.type.iphone" = "iPhone készüléken"; + +/* Device type is iPad */ +"credential.provider.device.type.pad" = "iPad készüléken"; + +/* Cancel button for auth when opening login list */ +"credential.provider.list.auth.cancel" = "Mégsem"; + +/* Reason for auth when opening screen with list of saved passwords */ +"credential.provider.list.auth.reason" = "Oldd fel az eszközt a jelszavakhoz való hozzáféréshez"; + +/* Address label for login details on autofill */ +"credential.provider.list.details.address" = "Webhely URL-címe"; + +/* Menu item text for copying autofill login details */ +"credential.provider.list.details.copy-prompt" = "%@ másolása"; + +/* Title for toast when copying address */ +"credential.provider.list.details.copy-toast.address-copied" = "Cím másolva"; + +/* Title for toast when copying notes */ +"credential.provider.list.details.copy-toast.notes-copied" = "Megjegyzések másolva"; + +/* Title for toast when copying password */ +"credential.provider.list.details.copy-toast.password-copied" = "Jelszó másolva"; + +/* Title for toast when copying username */ +"credential.provider.list.details.copy-toast.username-copied" = "Felhasználónév másolva"; + +/* Accessibility title for a Hide Password button replacing displayed password with ***** */ +"credential.provider.list.details.hide-password" = "Jelszó elrejtése"; + +/* Message displaying when the login was last updated */ +"credential.provider.list.details.last-updated" = "Utolsó frissítés: %@"; + +/* Login name label for login details on autofill */ +"credential.provider.list.details.login-name" = "Cím"; + +/* Notes label for login details on autofill */ +"credential.provider.list.details.notes" = "Megjegyzések"; + +/* Password label for login details on autofill */ +"credential.provider.list.details.password" = "Jelszó"; + +/* Accessibility title for a Show Password button displaying actial password instead of ***** */ +"credential.provider.list.details.show-password" = "Jelszó megjelenítése"; + +/* Username label for login details on autofill */ +"credential.provider.list.details.username" = "Felhasználónév"; + +/* Footer label displayed below table section with option to enable autofill */ +"credential.provider.list.empty-view.footer" = "A jelszavakat az eszközöd biztonságosan tárolja."; + +/* Title for view displayed when autofill has no items */ +"credential.provider.list.empty-view.title" = "Még nincsenek mentett jelszavak"; + +/* Prompt above the title for screen listing autofill logins, example: Choose a password to use for "website.com" */ +"credential.provider.list.prompt" = "Válassz egy jelszót ehhez: \"%@\""; + +/* Placeholder for search field on autofill login listing */ +"credential.provider.list.search-placeholder" = "Jelszavak keresése"; + +/* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ +"credential.provider.list.search.no-results.subtitle" = "erre: „%@“"; + +/* Title displayed when there are no results on Autofill search */ +"credential.provider.list.search.no-results.title" = "Nincs találat"; + +/* Section title for group of suggested saved logins */ +"credential.provider.list.suggested" = "Javasolt"; + +/* Title for screen listing autofill logins */ +"credential.provider.list.title" = "Jelszavak"; + +/* Message for alert when device authentication is not set, where %@ is iPhone|iPad|device */ +"credential.provider.no-device-auth-set.message" = "A DuckDuckGo-jelszavak automatikus kitöltéséhez állíts be egy jelkódot itt: %@."; + +/* Title for alert when device authentication is not set */ +"credential.provider.no-device-auth-set.title" = "Meg kell adni az eszköz jelkódját"; + diff --git a/AutofillCredentialProvider/it.lproj/InfoPlist.strings b/AutofillCredentialProvider/it.lproj/InfoPlist.strings new file mode 100644 index 0000000000..9809aa19f5 --- /dev/null +++ b/AutofillCredentialProvider/it.lproj/InfoPlist.strings @@ -0,0 +1,9 @@ +/* Bundle display name */ +"CFBundleDisplayName" = "AutofillCredentialProvider"; + +/* Bundle name */ +"CFBundleName" = "AutofillCredentialProvider"; + +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "Copyright © 2024 DuckDuckGo. All rights reserved."; + diff --git a/AutofillCredentialProvider/it.lproj/Localizable.strings b/AutofillCredentialProvider/it.lproj/Localizable.strings new file mode 100644 index 0000000000..5b97f6c41c --- /dev/null +++ b/AutofillCredentialProvider/it.lproj/Localizable.strings @@ -0,0 +1,96 @@ +/* Close button title */ +"action.button.close" = "Chiudi"; + +/* Done button title */ +"action.button.done" = "Fatto"; + +/* Title of button to launch the DuckDuckGo app */ +"credential.provider.activated.button" = "Apri DuckDuckGo"; + +/* The title of the screen confirming DuckDuckGo can now be used for autofilling passwords */ +"credential.provider.activated.title" = "Compilazione automatica delle password attivata!"; + +/* Default string used if users device is not iPhone or iPad */ +"credential.provider.device.type.default" = "dispositivo"; + +/* Device type is iPhone */ +"credential.provider.device.type.iphone" = "iPhone"; + +/* Device type is iPad */ +"credential.provider.device.type.pad" = "iPad"; + +/* Cancel button for auth when opening login list */ +"credential.provider.list.auth.cancel" = "Annulla"; + +/* Reason for auth when opening screen with list of saved passwords */ +"credential.provider.list.auth.reason" = "Sblocca il dispositivo per accedere alle password"; + +/* Address label for login details on autofill */ +"credential.provider.list.details.address" = "URL del sito Web"; + +/* Menu item text for copying autofill login details */ +"credential.provider.list.details.copy-prompt" = "Copia %@"; + +/* Title for toast when copying address */ +"credential.provider.list.details.copy-toast.address-copied" = "Indirizzo copiato"; + +/* Title for toast when copying notes */ +"credential.provider.list.details.copy-toast.notes-copied" = "Appunti copiati"; + +/* Title for toast when copying password */ +"credential.provider.list.details.copy-toast.password-copied" = "Password copiata"; + +/* Title for toast when copying username */ +"credential.provider.list.details.copy-toast.username-copied" = "Nome utente copiato"; + +/* Accessibility title for a Hide Password button replacing displayed password with ***** */ +"credential.provider.list.details.hide-password" = "Nascondi password"; + +/* Message displaying when the login was last updated */ +"credential.provider.list.details.last-updated" = "Ultimo aggiornamento %@"; + +/* Login name label for login details on autofill */ +"credential.provider.list.details.login-name" = "Titolo"; + +/* Notes label for login details on autofill */ +"credential.provider.list.details.notes" = "Note"; + +/* Password label for login details on autofill */ +"credential.provider.list.details.password" = "Password"; + +/* Accessibility title for a Show Password button displaying actial password instead of ***** */ +"credential.provider.list.details.show-password" = "Mostra password"; + +/* Username label for login details on autofill */ +"credential.provider.list.details.username" = "Nome utente"; + +/* Footer label displayed below table section with option to enable autofill */ +"credential.provider.list.empty-view.footer" = "Le password sono archiviate in modo sicuro sul tuo dispositivo."; + +/* Title for view displayed when autofill has no items */ +"credential.provider.list.empty-view.title" = "Nessuna password ancora salvata"; + +/* Prompt above the title for screen listing autofill logins, example: Choose a password to use for "website.com" */ +"credential.provider.list.prompt" = "Scegli una password da usare per \"%@\""; + +/* Placeholder for search field on autofill login listing */ +"credential.provider.list.search-placeholder" = "Cerca password"; + +/* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ +"credential.provider.list.search.no-results.subtitle" = "per \"%@\""; + +/* Title displayed when there are no results on Autofill search */ +"credential.provider.list.search.no-results.title" = "Nessun risultato"; + +/* Section title for group of suggested saved logins */ +"credential.provider.list.suggested" = "Suggerimenti"; + +/* Title for screen listing autofill logins */ +"credential.provider.list.title" = "Password"; + +/* Message for alert when device authentication is not set, where %@ is iPhone|iPad|device */ +"credential.provider.no-device-auth-set.message" = "Imposta un codice di accesso su %@ per inserire automaticamente le tue password DuckDuckGo."; + +/* Title for alert when device authentication is not set */ +"credential.provider.no-device-auth-set.title" = "È necessario il codice di accesso del dispositivo"; + diff --git a/AutofillCredentialProvider/lt.lproj/InfoPlist.strings b/AutofillCredentialProvider/lt.lproj/InfoPlist.strings new file mode 100644 index 0000000000..9809aa19f5 --- /dev/null +++ b/AutofillCredentialProvider/lt.lproj/InfoPlist.strings @@ -0,0 +1,9 @@ +/* Bundle display name */ +"CFBundleDisplayName" = "AutofillCredentialProvider"; + +/* Bundle name */ +"CFBundleName" = "AutofillCredentialProvider"; + +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "Copyright © 2024 DuckDuckGo. All rights reserved."; + diff --git a/AutofillCredentialProvider/lt.lproj/Localizable.strings b/AutofillCredentialProvider/lt.lproj/Localizable.strings new file mode 100644 index 0000000000..9867833bfd --- /dev/null +++ b/AutofillCredentialProvider/lt.lproj/Localizable.strings @@ -0,0 +1,96 @@ +/* Close button title */ +"action.button.close" = "Uždaryti"; + +/* Done button title */ +"action.button.done" = "Atlikta"; + +/* Title of button to launch the DuckDuckGo app */ +"credential.provider.activated.button" = "Atidaryti „DuckDuckGo“"; + +/* The title of the screen confirming DuckDuckGo can now be used for autofilling passwords */ +"credential.provider.activated.title" = "Automatinis slaptažodžių pildymas įjungtas!"; + +/* Default string used if users device is not iPhone or iPad */ +"credential.provider.device.type.default" = "įrenginys"; + +/* Device type is iPhone */ +"credential.provider.device.type.iphone" = "iPhone"; + +/* Device type is iPad */ +"credential.provider.device.type.pad" = "iPad"; + +/* Cancel button for auth when opening login list */ +"credential.provider.list.auth.cancel" = "Atšaukti"; + +/* Reason for auth when opening screen with list of saved passwords */ +"credential.provider.list.auth.reason" = "Atrakinkite įrenginį, kad galėtumėte pasiekti slaptažodžius"; + +/* Address label for login details on autofill */ +"credential.provider.list.details.address" = "Svetainės URL"; + +/* Menu item text for copying autofill login details */ +"credential.provider.list.details.copy-prompt" = "Kopijuoti %@"; + +/* Title for toast when copying address */ +"credential.provider.list.details.copy-toast.address-copied" = "Adresas nukopijuotas"; + +/* Title for toast when copying notes */ +"credential.provider.list.details.copy-toast.notes-copied" = "Pastabos nukopijuotos"; + +/* Title for toast when copying password */ +"credential.provider.list.details.copy-toast.password-copied" = "Slaptažodis nukopijuotas"; + +/* Title for toast when copying username */ +"credential.provider.list.details.copy-toast.username-copied" = "Naudotojo vardas nukopijuotas"; + +/* Accessibility title for a Hide Password button replacing displayed password with ***** */ +"credential.provider.list.details.hide-password" = "Paslėpti slaptažodį"; + +/* Message displaying when the login was last updated */ +"credential.provider.list.details.last-updated" = "Paskutinį kartą atnaujinta %@"; + +/* Login name label for login details on autofill */ +"credential.provider.list.details.login-name" = "Pavadinimas"; + +/* Notes label for login details on autofill */ +"credential.provider.list.details.notes" = "Pastabos"; + +/* Password label for login details on autofill */ +"credential.provider.list.details.password" = "Slaptažodis"; + +/* Accessibility title for a Show Password button displaying actial password instead of ***** */ +"credential.provider.list.details.show-password" = "Rodyti slaptažodį"; + +/* Username label for login details on autofill */ +"credential.provider.list.details.username" = "Naudotojo vardas"; + +/* Footer label displayed below table section with option to enable autofill */ +"credential.provider.list.empty-view.footer" = "Slaptažodžiai saugiai saugomi jūsų įrenginyje."; + +/* Title for view displayed when autofill has no items */ +"credential.provider.list.empty-view.title" = "Dar nėra išsaugotų slaptažodžių"; + +/* Prompt above the title for screen listing autofill logins, example: Choose a password to use for "website.com" */ +"credential.provider.list.prompt" = "Pasirinkite slaptažodį, kurį naudosite „%@“"; + +/* Placeholder for search field on autofill login listing */ +"credential.provider.list.search-placeholder" = "Ieškoti slaptažodžių"; + +/* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ +"credential.provider.list.search.no-results.subtitle" = "„%@“"; + +/* Title displayed when there are no results on Autofill search */ +"credential.provider.list.search.no-results.title" = "Rezultatų nerasta"; + +/* Section title for group of suggested saved logins */ +"credential.provider.list.suggested" = "Siūloma"; + +/* Title for screen listing autofill logins */ +"credential.provider.list.title" = "Slaptažodžiai"; + +/* Message for alert when device authentication is not set, where %@ is iPhone|iPad|device */ +"credential.provider.no-device-auth-set.message" = "Nustatykite %@ prieigos kodą, kad automatiškai užpildytumėte „DuckDuckGo“ slaptažodžius."; + +/* Title for alert when device authentication is not set */ +"credential.provider.no-device-auth-set.title" = "Reikalingas įrenginio kodas"; + diff --git a/AutofillCredentialProvider/lv.lproj/InfoPlist.strings b/AutofillCredentialProvider/lv.lproj/InfoPlist.strings new file mode 100644 index 0000000000..9809aa19f5 --- /dev/null +++ b/AutofillCredentialProvider/lv.lproj/InfoPlist.strings @@ -0,0 +1,9 @@ +/* Bundle display name */ +"CFBundleDisplayName" = "AutofillCredentialProvider"; + +/* Bundle name */ +"CFBundleName" = "AutofillCredentialProvider"; + +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "Copyright © 2024 DuckDuckGo. All rights reserved."; + diff --git a/AutofillCredentialProvider/lv.lproj/Localizable.strings b/AutofillCredentialProvider/lv.lproj/Localizable.strings new file mode 100644 index 0000000000..5c9150e72f --- /dev/null +++ b/AutofillCredentialProvider/lv.lproj/Localizable.strings @@ -0,0 +1,96 @@ +/* Close button title */ +"action.button.close" = "Aizvērt"; + +/* Done button title */ +"action.button.done" = "Gatavs"; + +/* Title of button to launch the DuckDuckGo app */ +"credential.provider.activated.button" = "Atvērt DuckDuckGo"; + +/* The title of the screen confirming DuckDuckGo can now be used for autofilling passwords */ +"credential.provider.activated.title" = "Paroļu automātiskā aizpildīšana ir aktivizēta!"; + +/* Default string used if users device is not iPhone or iPad */ +"credential.provider.device.type.default" = "ierīcē"; + +/* Device type is iPhone */ +"credential.provider.device.type.iphone" = "iPhone"; + +/* Device type is iPad */ +"credential.provider.device.type.pad" = "iPad"; + +/* Cancel button for auth when opening login list */ +"credential.provider.list.auth.cancel" = "Atcelt"; + +/* Reason for auth when opening screen with list of saved passwords */ +"credential.provider.list.auth.reason" = "Atbloķē ierīci, lai piekļūtu parolēm"; + +/* Address label for login details on autofill */ +"credential.provider.list.details.address" = "Tīmekļa vietnes URL"; + +/* Menu item text for copying autofill login details */ +"credential.provider.list.details.copy-prompt" = "Kopēt %@"; + +/* Title for toast when copying address */ +"credential.provider.list.details.copy-toast.address-copied" = "Adrese nokopēta"; + +/* Title for toast when copying notes */ +"credential.provider.list.details.copy-toast.notes-copied" = "Piezīmes nokopētas"; + +/* Title for toast when copying password */ +"credential.provider.list.details.copy-toast.password-copied" = "Parole nokopēta"; + +/* Title for toast when copying username */ +"credential.provider.list.details.copy-toast.username-copied" = "Lietotājvārds nokopēts"; + +/* Accessibility title for a Hide Password button replacing displayed password with ***** */ +"credential.provider.list.details.hide-password" = "Paslēpt paroli"; + +/* Message displaying when the login was last updated */ +"credential.provider.list.details.last-updated" = "Pēdējoreiz atjaunināts %@"; + +/* Login name label for login details on autofill */ +"credential.provider.list.details.login-name" = "Nosaukums"; + +/* Notes label for login details on autofill */ +"credential.provider.list.details.notes" = "Piezīmes"; + +/* Password label for login details on autofill */ +"credential.provider.list.details.password" = "Parole"; + +/* Accessibility title for a Show Password button displaying actial password instead of ***** */ +"credential.provider.list.details.show-password" = "Rādīt paroli"; + +/* Username label for login details on autofill */ +"credential.provider.list.details.username" = "Lietotājvārds"; + +/* Footer label displayed below table section with option to enable autofill */ +"credential.provider.list.empty-view.footer" = "Paroles tiek droši glabātas tavā ierīcē."; + +/* Title for view displayed when autofill has no items */ +"credential.provider.list.empty-view.title" = "Vēl nav saglabāta neviena parole"; + +/* Prompt above the title for screen listing autofill logins, example: Choose a password to use for "website.com" */ +"credential.provider.list.prompt" = "Izvēlies paroli, ko izmantot \"%@\""; + +/* Placeholder for search field on autofill login listing */ +"credential.provider.list.search-placeholder" = "Meklēt paroles"; + +/* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ +"credential.provider.list.search.no-results.subtitle" = "meklējumam \"%@\""; + +/* Title displayed when there are no results on Autofill search */ +"credential.provider.list.search.no-results.title" = "Nav rezultātu"; + +/* Section title for group of suggested saved logins */ +"credential.provider.list.suggested" = "Ieteikts"; + +/* Title for screen listing autofill logins */ +"credential.provider.list.title" = "Paroles"; + +/* Message for alert when device authentication is not set, where %@ is iPhone|iPad|device */ +"credential.provider.no-device-auth-set.message" = "Iestati piekļuves kodu %@, lai automātiski aizpildītu savas DuckDuckGo paroles."; + +/* Title for alert when device authentication is not set */ +"credential.provider.no-device-auth-set.title" = "Nepieciešams ierīces piekļuves kods"; + diff --git a/AutofillCredentialProvider/nb.lproj/InfoPlist.strings b/AutofillCredentialProvider/nb.lproj/InfoPlist.strings new file mode 100644 index 0000000000..9809aa19f5 --- /dev/null +++ b/AutofillCredentialProvider/nb.lproj/InfoPlist.strings @@ -0,0 +1,9 @@ +/* Bundle display name */ +"CFBundleDisplayName" = "AutofillCredentialProvider"; + +/* Bundle name */ +"CFBundleName" = "AutofillCredentialProvider"; + +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "Copyright © 2024 DuckDuckGo. All rights reserved."; + diff --git a/AutofillCredentialProvider/nb.lproj/Localizable.strings b/AutofillCredentialProvider/nb.lproj/Localizable.strings new file mode 100644 index 0000000000..858f84a0d9 --- /dev/null +++ b/AutofillCredentialProvider/nb.lproj/Localizable.strings @@ -0,0 +1,96 @@ +/* Close button title */ +"action.button.close" = "Lukk"; + +/* Done button title */ +"action.button.done" = "Ferdig"; + +/* Title of button to launch the DuckDuckGo app */ +"credential.provider.activated.button" = "Åpne DuckDuckGo"; + +/* The title of the screen confirming DuckDuckGo can now be used for autofilling passwords */ +"credential.provider.activated.title" = "Automatisk fylling av passord er aktivert!"; + +/* Default string used if users device is not iPhone or iPad */ +"credential.provider.device.type.default" = "enhet"; + +/* Device type is iPhone */ +"credential.provider.device.type.iphone" = "iPhone"; + +/* Device type is iPad */ +"credential.provider.device.type.pad" = "iPad"; + +/* Cancel button for auth when opening login list */ +"credential.provider.list.auth.cancel" = "Avbryt"; + +/* Reason for auth when opening screen with list of saved passwords */ +"credential.provider.list.auth.reason" = "Lås opp enheten for å få tilgang til passord"; + +/* Address label for login details on autofill */ +"credential.provider.list.details.address" = "URL-adresse til nettsted"; + +/* Menu item text for copying autofill login details */ +"credential.provider.list.details.copy-prompt" = "Kopier %@"; + +/* Title for toast when copying address */ +"credential.provider.list.details.copy-toast.address-copied" = "Adressen er kopiert"; + +/* Title for toast when copying notes */ +"credential.provider.list.details.copy-toast.notes-copied" = "Notatene er kopiert"; + +/* Title for toast when copying password */ +"credential.provider.list.details.copy-toast.password-copied" = "Passordet er kopiert"; + +/* Title for toast when copying username */ +"credential.provider.list.details.copy-toast.username-copied" = "Brukernavnet er kopiert"; + +/* Accessibility title for a Hide Password button replacing displayed password with ***** */ +"credential.provider.list.details.hide-password" = "Skjul passord"; + +/* Message displaying when the login was last updated */ +"credential.provider.list.details.last-updated" = "Sist oppdatert %@"; + +/* Login name label for login details on autofill */ +"credential.provider.list.details.login-name" = "Tittel"; + +/* Notes label for login details on autofill */ +"credential.provider.list.details.notes" = "Notater"; + +/* Password label for login details on autofill */ +"credential.provider.list.details.password" = "Passord"; + +/* Accessibility title for a Show Password button displaying actial password instead of ***** */ +"credential.provider.list.details.show-password" = "Vis passord"; + +/* Username label for login details on autofill */ +"credential.provider.list.details.username" = "Brukernavn"; + +/* Footer label displayed below table section with option to enable autofill */ +"credential.provider.list.empty-view.footer" = "Passord lagres på enheten din på en sikker måte."; + +/* Title for view displayed when autofill has no items */ +"credential.provider.list.empty-view.title" = "Ingen passord er lagret ennå"; + +/* Prompt above the title for screen listing autofill logins, example: Choose a password to use for "website.com" */ +"credential.provider.list.prompt" = "Velg et passord du vil bruke til «%@»"; + +/* Placeholder for search field on autofill login listing */ +"credential.provider.list.search-placeholder" = "Søk i passord"; + +/* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ +"credential.provider.list.search.no-results.subtitle" = "for «%@»"; + +/* Title displayed when there are no results on Autofill search */ +"credential.provider.list.search.no-results.title" = "Ingen resultater"; + +/* Section title for group of suggested saved logins */ +"credential.provider.list.suggested" = "Forslag"; + +/* Title for screen listing autofill logins */ +"credential.provider.list.title" = "Passord"; + +/* Message for alert when device authentication is not set, where %@ is iPhone|iPad|device */ +"credential.provider.no-device-auth-set.message" = "Angi en kode på %@ for å fylle inn DuckDuckGo-passordene dine automatisk."; + +/* Title for alert when device authentication is not set */ +"credential.provider.no-device-auth-set.title" = "Enhetens kode kreves"; + diff --git a/AutofillCredentialProvider/nl.lproj/InfoPlist.strings b/AutofillCredentialProvider/nl.lproj/InfoPlist.strings new file mode 100644 index 0000000000..9809aa19f5 --- /dev/null +++ b/AutofillCredentialProvider/nl.lproj/InfoPlist.strings @@ -0,0 +1,9 @@ +/* Bundle display name */ +"CFBundleDisplayName" = "AutofillCredentialProvider"; + +/* Bundle name */ +"CFBundleName" = "AutofillCredentialProvider"; + +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "Copyright © 2024 DuckDuckGo. All rights reserved."; + diff --git a/AutofillCredentialProvider/nl.lproj/Localizable.strings b/AutofillCredentialProvider/nl.lproj/Localizable.strings new file mode 100644 index 0000000000..5737a0c75a --- /dev/null +++ b/AutofillCredentialProvider/nl.lproj/Localizable.strings @@ -0,0 +1,96 @@ +/* Close button title */ +"action.button.close" = "Sluiten"; + +/* Done button title */ +"action.button.done" = "Klaar"; + +/* Title of button to launch the DuckDuckGo app */ +"credential.provider.activated.button" = "DuckDuckGo openen"; + +/* The title of the screen confirming DuckDuckGo can now be used for autofilling passwords */ +"credential.provider.activated.title" = "Automatisch invullen van wachtwoorden geactiveerd!"; + +/* Default string used if users device is not iPhone or iPad */ +"credential.provider.device.type.default" = "apparaat"; + +/* Device type is iPhone */ +"credential.provider.device.type.iphone" = "iPhone"; + +/* Device type is iPad */ +"credential.provider.device.type.pad" = "iPad"; + +/* Cancel button for auth when opening login list */ +"credential.provider.list.auth.cancel" = "Annuleren"; + +/* Reason for auth when opening screen with list of saved passwords */ +"credential.provider.list.auth.reason" = "Ontgrendel het apparaat om toegang te krijgen tot wachtwoorden"; + +/* Address label for login details on autofill */ +"credential.provider.list.details.address" = "URL van de website"; + +/* Menu item text for copying autofill login details */ +"credential.provider.list.details.copy-prompt" = "%@ kopiëren"; + +/* Title for toast when copying address */ +"credential.provider.list.details.copy-toast.address-copied" = "Adres gekopieerd"; + +/* Title for toast when copying notes */ +"credential.provider.list.details.copy-toast.notes-copied" = "Opmerkingen gekopieerd"; + +/* Title for toast when copying password */ +"credential.provider.list.details.copy-toast.password-copied" = "Wachtwoord gekopieerd"; + +/* Title for toast when copying username */ +"credential.provider.list.details.copy-toast.username-copied" = "Gebruikersnaam gekopieerd"; + +/* Accessibility title for a Hide Password button replacing displayed password with ***** */ +"credential.provider.list.details.hide-password" = "Wachtwoord verbergen"; + +/* Message displaying when the login was last updated */ +"credential.provider.list.details.last-updated" = "Laatst bijgewerkt op %@"; + +/* Login name label for login details on autofill */ +"credential.provider.list.details.login-name" = "Titel"; + +/* Notes label for login details on autofill */ +"credential.provider.list.details.notes" = "Opmerkingen"; + +/* Password label for login details on autofill */ +"credential.provider.list.details.password" = "Wachtwoord"; + +/* Accessibility title for a Show Password button displaying actial password instead of ***** */ +"credential.provider.list.details.show-password" = "Wachtwoord weergeven"; + +/* Username label for login details on autofill */ +"credential.provider.list.details.username" = "Gebruikersnaam"; + +/* Footer label displayed below table section with option to enable autofill */ +"credential.provider.list.empty-view.footer" = "Wachtwoorden worden veilig opgeslagen op je apparaat."; + +/* Title for view displayed when autofill has no items */ +"credential.provider.list.empty-view.title" = "Nog geen wachtwoorden opgeslagen"; + +/* Prompt above the title for screen listing autofill logins, example: Choose a password to use for "website.com" */ +"credential.provider.list.prompt" = "Kies een wachtwoord voor '%@'"; + +/* Placeholder for search field on autofill login listing */ +"credential.provider.list.search-placeholder" = "Wachtwoorden zoeken"; + +/* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ +"credential.provider.list.search.no-results.subtitle" = "voor '%@'"; + +/* Title displayed when there are no results on Autofill search */ +"credential.provider.list.search.no-results.title" = "Geen resultaten"; + +/* Section title for group of suggested saved logins */ +"credential.provider.list.suggested" = "Aanbevolen"; + +/* Title for screen listing autofill logins */ +"credential.provider.list.title" = "Wachtwoorden"; + +/* Message for alert when device authentication is not set, where %@ is iPhone|iPad|device */ +"credential.provider.no-device-auth-set.message" = "Stel een toegangscode in op %@ om je DuckDuckGo-wachtwoorden automatisch in te vullen."; + +/* Title for alert when device authentication is not set */ +"credential.provider.no-device-auth-set.title" = "Toegangscode voor apparaat vereist"; + diff --git a/AutofillCredentialProvider/pl.lproj/InfoPlist.strings b/AutofillCredentialProvider/pl.lproj/InfoPlist.strings new file mode 100644 index 0000000000..9809aa19f5 --- /dev/null +++ b/AutofillCredentialProvider/pl.lproj/InfoPlist.strings @@ -0,0 +1,9 @@ +/* Bundle display name */ +"CFBundleDisplayName" = "AutofillCredentialProvider"; + +/* Bundle name */ +"CFBundleName" = "AutofillCredentialProvider"; + +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "Copyright © 2024 DuckDuckGo. All rights reserved."; + diff --git a/AutofillCredentialProvider/pl.lproj/Localizable.strings b/AutofillCredentialProvider/pl.lproj/Localizable.strings new file mode 100644 index 0000000000..b2198855c4 --- /dev/null +++ b/AutofillCredentialProvider/pl.lproj/Localizable.strings @@ -0,0 +1,96 @@ +/* Close button title */ +"action.button.close" = "Zamknij"; + +/* Done button title */ +"action.button.done" = "Gotowe"; + +/* Title of button to launch the DuckDuckGo app */ +"credential.provider.activated.button" = "Otwórz DuckDuckGo"; + +/* The title of the screen confirming DuckDuckGo can now be used for autofilling passwords */ +"credential.provider.activated.title" = "Automatyczne uzupełnianie haseł zostało aktywowane!"; + +/* Default string used if users device is not iPhone or iPad */ +"credential.provider.device.type.default" = "tym urządzeniu"; + +/* Device type is iPhone */ +"credential.provider.device.type.iphone" = "tym telefonie iPhone"; + +/* Device type is iPad */ +"credential.provider.device.type.pad" = "tym iPadzie"; + +/* Cancel button for auth when opening login list */ +"credential.provider.list.auth.cancel" = "Anuluj"; + +/* Reason for auth when opening screen with list of saved passwords */ +"credential.provider.list.auth.reason" = "Odblokuj urządzenie, aby uzyskać dostęp do haseł"; + +/* Address label for login details on autofill */ +"credential.provider.list.details.address" = "Adres URL witryny"; + +/* Menu item text for copying autofill login details */ +"credential.provider.list.details.copy-prompt" = "Kopiuj %@"; + +/* Title for toast when copying address */ +"credential.provider.list.details.copy-toast.address-copied" = "Skopiowano adres"; + +/* Title for toast when copying notes */ +"credential.provider.list.details.copy-toast.notes-copied" = "Skopiowano notatki"; + +/* Title for toast when copying password */ +"credential.provider.list.details.copy-toast.password-copied" = "Skopiowano hasło"; + +/* Title for toast when copying username */ +"credential.provider.list.details.copy-toast.username-copied" = "Skopiowano nazwę użytkownika"; + +/* Accessibility title for a Hide Password button replacing displayed password with ***** */ +"credential.provider.list.details.hide-password" = "Ukryj hasło"; + +/* Message displaying when the login was last updated */ +"credential.provider.list.details.last-updated" = "Ostatnia aktualizacja %@"; + +/* Login name label for login details on autofill */ +"credential.provider.list.details.login-name" = "Tytuł"; + +/* Notes label for login details on autofill */ +"credential.provider.list.details.notes" = "Uwagi"; + +/* Password label for login details on autofill */ +"credential.provider.list.details.password" = "Hasło"; + +/* Accessibility title for a Show Password button displaying actial password instead of ***** */ +"credential.provider.list.details.show-password" = "Pokaż hasło"; + +/* Username label for login details on autofill */ +"credential.provider.list.details.username" = "Nazwa użytkownika"; + +/* Footer label displayed below table section with option to enable autofill */ +"credential.provider.list.empty-view.footer" = "Hasła są bezpiecznie przechowywane na Twoim urządzeniu."; + +/* Title for view displayed when autofill has no items */ +"credential.provider.list.empty-view.title" = "Nie zapisano jeszcze żadnych haseł"; + +/* Prompt above the title for screen listing autofill logins, example: Choose a password to use for "website.com" */ +"credential.provider.list.prompt" = "Wybierz hasło do wykorzystania z „%@”"; + +/* Placeholder for search field on autofill login listing */ +"credential.provider.list.search-placeholder" = "Wyszukaj hasła"; + +/* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ +"credential.provider.list.search.no-results.subtitle" = "dla frazy: %@"; + +/* Title displayed when there are no results on Autofill search */ +"credential.provider.list.search.no-results.title" = "Brak wyników"; + +/* Section title for group of suggested saved logins */ +"credential.provider.list.suggested" = "Sugerowane"; + +/* Title for screen listing autofill logins */ +"credential.provider.list.title" = "Hasła"; + +/* Message for alert when device authentication is not set, where %@ is iPhone|iPad|device */ +"credential.provider.no-device-auth-set.message" = "Ustaw kod dostępu na urządzeniu %@, aby automatycznie uzupełniać hasła DuckDuckGo."; + +/* Title for alert when device authentication is not set */ +"credential.provider.no-device-auth-set.title" = "Wymagany kod dostępu urządzenia"; + diff --git a/AutofillCredentialProvider/pt.lproj/InfoPlist.strings b/AutofillCredentialProvider/pt.lproj/InfoPlist.strings new file mode 100644 index 0000000000..9809aa19f5 --- /dev/null +++ b/AutofillCredentialProvider/pt.lproj/InfoPlist.strings @@ -0,0 +1,9 @@ +/* Bundle display name */ +"CFBundleDisplayName" = "AutofillCredentialProvider"; + +/* Bundle name */ +"CFBundleName" = "AutofillCredentialProvider"; + +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "Copyright © 2024 DuckDuckGo. All rights reserved."; + diff --git a/AutofillCredentialProvider/pt.lproj/Localizable.strings b/AutofillCredentialProvider/pt.lproj/Localizable.strings new file mode 100644 index 0000000000..6d2929f0ee --- /dev/null +++ b/AutofillCredentialProvider/pt.lproj/Localizable.strings @@ -0,0 +1,96 @@ +/* Close button title */ +"action.button.close" = "Fechar"; + +/* Done button title */ +"action.button.done" = "Feito"; + +/* Title of button to launch the DuckDuckGo app */ +"credential.provider.activated.button" = "Abrir DuckDuckGo"; + +/* The title of the screen confirming DuckDuckGo can now be used for autofilling passwords */ +"credential.provider.activated.title" = "Preenchimento automático de palavras-passe ativado!"; + +/* Default string used if users device is not iPhone or iPad */ +"credential.provider.device.type.default" = "dispositivo"; + +/* Device type is iPhone */ +"credential.provider.device.type.iphone" = "iPhone"; + +/* Device type is iPad */ +"credential.provider.device.type.pad" = "iPad"; + +/* Cancel button for auth when opening login list */ +"credential.provider.list.auth.cancel" = "Cancelar"; + +/* Reason for auth when opening screen with list of saved passwords */ +"credential.provider.list.auth.reason" = "Desbloquear dispositivo para aceder às palavras-passe"; + +/* Address label for login details on autofill */ +"credential.provider.list.details.address" = "URL do site"; + +/* Menu item text for copying autofill login details */ +"credential.provider.list.details.copy-prompt" = "Copiar %@"; + +/* Title for toast when copying address */ +"credential.provider.list.details.copy-toast.address-copied" = "Endereço copiado"; + +/* Title for toast when copying notes */ +"credential.provider.list.details.copy-toast.notes-copied" = "Notas copiadas"; + +/* Title for toast when copying password */ +"credential.provider.list.details.copy-toast.password-copied" = "Palavra-passe copiada"; + +/* Title for toast when copying username */ +"credential.provider.list.details.copy-toast.username-copied" = "Nome de utilizador copiado"; + +/* Accessibility title for a Hide Password button replacing displayed password with ***** */ +"credential.provider.list.details.hide-password" = "Ocultar palavra-passe"; + +/* Message displaying when the login was last updated */ +"credential.provider.list.details.last-updated" = "Última atualização em %@"; + +/* Login name label for login details on autofill */ +"credential.provider.list.details.login-name" = "Título"; + +/* Notes label for login details on autofill */ +"credential.provider.list.details.notes" = "Notas"; + +/* Password label for login details on autofill */ +"credential.provider.list.details.password" = "Palavra-passe"; + +/* Accessibility title for a Show Password button displaying actial password instead of ***** */ +"credential.provider.list.details.show-password" = "Mostrar palavra-passe"; + +/* Username label for login details on autofill */ +"credential.provider.list.details.username" = "Nome de utilizador"; + +/* Footer label displayed below table section with option to enable autofill */ +"credential.provider.list.empty-view.footer" = "As palavras-passe são armazenadas com segurança no teu dispositivo."; + +/* Title for view displayed when autofill has no items */ +"credential.provider.list.empty-view.title" = "Ainda não há palavras-passe guardadas"; + +/* Prompt above the title for screen listing autofill logins, example: Choose a password to use for "website.com" */ +"credential.provider.list.prompt" = "Escolhe uma palavra-passe para usar em \"%@\""; + +/* Placeholder for search field on autofill login listing */ +"credential.provider.list.search-placeholder" = "Pesquisar palavras-passe"; + +/* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ +"credential.provider.list.search.no-results.subtitle" = "para \"%@\""; + +/* Title displayed when there are no results on Autofill search */ +"credential.provider.list.search.no-results.title" = "Sem resultados"; + +/* Section title for group of suggested saved logins */ +"credential.provider.list.suggested" = "Sugerido"; + +/* Title for screen listing autofill logins */ +"credential.provider.list.title" = "Palavras-passe"; + +/* Message for alert when device authentication is not set, where %@ is iPhone|iPad|device */ +"credential.provider.no-device-auth-set.message" = "Define um código de acesso em %@ para preencher automaticamente as tuas palavras-passe DuckDuckGo."; + +/* Title for alert when device authentication is not set */ +"credential.provider.no-device-auth-set.title" = "Código de acesso do dispositivo necessário"; + diff --git a/AutofillCredentialProvider/ro.lproj/InfoPlist.strings b/AutofillCredentialProvider/ro.lproj/InfoPlist.strings new file mode 100644 index 0000000000..9809aa19f5 --- /dev/null +++ b/AutofillCredentialProvider/ro.lproj/InfoPlist.strings @@ -0,0 +1,9 @@ +/* Bundle display name */ +"CFBundleDisplayName" = "AutofillCredentialProvider"; + +/* Bundle name */ +"CFBundleName" = "AutofillCredentialProvider"; + +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "Copyright © 2024 DuckDuckGo. All rights reserved."; + diff --git a/AutofillCredentialProvider/ro.lproj/Localizable.strings b/AutofillCredentialProvider/ro.lproj/Localizable.strings new file mode 100644 index 0000000000..e90eb1030d --- /dev/null +++ b/AutofillCredentialProvider/ro.lproj/Localizable.strings @@ -0,0 +1,96 @@ +/* Close button title */ +"action.button.close" = "Închidere"; + +/* Done button title */ +"action.button.done" = "Terminat"; + +/* Title of button to launch the DuckDuckGo app */ +"credential.provider.activated.button" = "Deschide DuckDuckGo"; + +/* The title of the screen confirming DuckDuckGo can now be used for autofilling passwords */ +"credential.provider.activated.title" = "Completarea automată a parolelor a fost activată!"; + +/* Default string used if users device is not iPhone or iPad */ +"credential.provider.device.type.default" = "dispozitiv"; + +/* Device type is iPhone */ +"credential.provider.device.type.iphone" = "iPhone"; + +/* Device type is iPad */ +"credential.provider.device.type.pad" = "iPad"; + +/* Cancel button for auth when opening login list */ +"credential.provider.list.auth.cancel" = "Renunță"; + +/* Reason for auth when opening screen with list of saved passwords */ +"credential.provider.list.auth.reason" = "Deblochează dispozitivul pentru a accesa parolele"; + +/* Address label for login details on autofill */ +"credential.provider.list.details.address" = "URL-ul site-ului"; + +/* Menu item text for copying autofill login details */ +"credential.provider.list.details.copy-prompt" = "Copiază %@"; + +/* Title for toast when copying address */ +"credential.provider.list.details.copy-toast.address-copied" = "Adresă copiată"; + +/* Title for toast when copying notes */ +"credential.provider.list.details.copy-toast.notes-copied" = "Note copiate"; + +/* Title for toast when copying password */ +"credential.provider.list.details.copy-toast.password-copied" = "Parolă copiată"; + +/* Title for toast when copying username */ +"credential.provider.list.details.copy-toast.username-copied" = "Numele de utilizator a fost copiat"; + +/* Accessibility title for a Hide Password button replacing displayed password with ***** */ +"credential.provider.list.details.hide-password" = "Ascunde parola"; + +/* Message displaying when the login was last updated */ +"credential.provider.list.details.last-updated" = "Ultima actualizare la %@"; + +/* Login name label for login details on autofill */ +"credential.provider.list.details.login-name" = "Titlu"; + +/* Notes label for login details on autofill */ +"credential.provider.list.details.notes" = "Note"; + +/* Password label for login details on autofill */ +"credential.provider.list.details.password" = "Parolă"; + +/* Accessibility title for a Show Password button displaying actial password instead of ***** */ +"credential.provider.list.details.show-password" = "Arată parola"; + +/* Username label for login details on autofill */ +"credential.provider.list.details.username" = "Nume utilizator"; + +/* Footer label displayed below table section with option to enable autofill */ +"credential.provider.list.empty-view.footer" = "Parolele sunt stocate în siguranță pe dispozitivul tău."; + +/* Title for view displayed when autofill has no items */ +"credential.provider.list.empty-view.title" = "Nici o parolă nu a fost salvată încă"; + +/* Prompt above the title for screen listing autofill logins, example: Choose a password to use for "website.com" */ +"credential.provider.list.prompt" = "Alege o parolă pe care să o utilizezi pentru „%@”"; + +/* Placeholder for search field on autofill login listing */ +"credential.provider.list.search-placeholder" = "Caută parole"; + +/* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ +"credential.provider.list.search.no-results.subtitle" = "pentru „%@”"; + +/* Title displayed when there are no results on Autofill search */ +"credential.provider.list.search.no-results.title" = "Niciun rezultat"; + +/* Section title for group of suggested saved logins */ +"credential.provider.list.suggested" = "Sugerat"; + +/* Title for screen listing autofill logins */ +"credential.provider.list.title" = "Parole"; + +/* Message for alert when device authentication is not set, where %@ is iPhone|iPad|device */ +"credential.provider.no-device-auth-set.message" = "Setează o parolă pe %@ pentru a-ți completa automat parolele DuckDuckGo."; + +/* Title for alert when device authentication is not set */ +"credential.provider.no-device-auth-set.title" = "Codul de acces al dispozitivului este necesar"; + diff --git a/AutofillCredentialProvider/ru.lproj/InfoPlist.strings b/AutofillCredentialProvider/ru.lproj/InfoPlist.strings new file mode 100644 index 0000000000..9809aa19f5 --- /dev/null +++ b/AutofillCredentialProvider/ru.lproj/InfoPlist.strings @@ -0,0 +1,9 @@ +/* Bundle display name */ +"CFBundleDisplayName" = "AutofillCredentialProvider"; + +/* Bundle name */ +"CFBundleName" = "AutofillCredentialProvider"; + +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "Copyright © 2024 DuckDuckGo. All rights reserved."; + diff --git a/AutofillCredentialProvider/ru.lproj/Localizable.strings b/AutofillCredentialProvider/ru.lproj/Localizable.strings new file mode 100644 index 0000000000..823459918c --- /dev/null +++ b/AutofillCredentialProvider/ru.lproj/Localizable.strings @@ -0,0 +1,96 @@ +/* Close button title */ +"action.button.close" = "Закрыть"; + +/* Done button title */ +"action.button.done" = "Готово"; + +/* Title of button to launch the DuckDuckGo app */ +"credential.provider.activated.button" = "Открыть DuckDuckGo"; + +/* The title of the screen confirming DuckDuckGo can now be used for autofilling passwords */ +"credential.provider.activated.title" = "Автозаполнение паролей включено!"; + +/* Default string used if users device is not iPhone or iPad */ +"credential.provider.device.type.default" = "устройстве"; + +/* Device type is iPhone */ +"credential.provider.device.type.iphone" = "iPhone"; + +/* Device type is iPad */ +"credential.provider.device.type.pad" = "iPad"; + +/* Cancel button for auth when opening login list */ +"credential.provider.list.auth.cancel" = "Отменить"; + +/* Reason for auth when opening screen with list of saved passwords */ +"credential.provider.list.auth.reason" = "Разблокируйте устройство, чтобы получить доступ к паролям"; + +/* Address label for login details on autofill */ +"credential.provider.list.details.address" = "Адрес сайта"; + +/* Menu item text for copying autofill login details */ +"credential.provider.list.details.copy-prompt" = "Копировать %@"; + +/* Title for toast when copying address */ +"credential.provider.list.details.copy-toast.address-copied" = "Адрес скопирован"; + +/* Title for toast when copying notes */ +"credential.provider.list.details.copy-toast.notes-copied" = "Примечания скопированы"; + +/* Title for toast when copying password */ +"credential.provider.list.details.copy-toast.password-copied" = "Пароль скопирован"; + +/* Title for toast when copying username */ +"credential.provider.list.details.copy-toast.username-copied" = "Имя пользователя скопировано!"; + +/* Accessibility title for a Hide Password button replacing displayed password with ***** */ +"credential.provider.list.details.hide-password" = "Скрыть пароль"; + +/* Message displaying when the login was last updated */ +"credential.provider.list.details.last-updated" = "Последнее обновление: %@"; + +/* Login name label for login details on autofill */ +"credential.provider.list.details.login-name" = "Название"; + +/* Notes label for login details on autofill */ +"credential.provider.list.details.notes" = "Примечания"; + +/* Password label for login details on autofill */ +"credential.provider.list.details.password" = "Пароль"; + +/* Accessibility title for a Show Password button displaying actial password instead of ***** */ +"credential.provider.list.details.show-password" = "Показать пароль"; + +/* Username label for login details on autofill */ +"credential.provider.list.details.username" = "Имя пользователя"; + +/* Footer label displayed below table section with option to enable autofill */ +"credential.provider.list.empty-view.footer" = "Пароли надежно защищены и хранятся на вашем устройстве."; + +/* Title for view displayed when autofill has no items */ +"credential.provider.list.empty-view.title" = "Сохраненных паролей пока нет"; + +/* Prompt above the title for screen listing autofill logins, example: Choose a password to use for "website.com" */ +"credential.provider.list.prompt" = "Выберите пароль для сайта %@"; + +/* Placeholder for search field on autofill login listing */ +"credential.provider.list.search-placeholder" = "Найти пароль"; + +/* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ +"credential.provider.list.search.no-results.subtitle" = "по запросу «%@»"; + +/* Title displayed when there are no results on Autofill search */ +"credential.provider.list.search.no-results.title" = "Нет результатов"; + +/* Section title for group of suggested saved logins */ +"credential.provider.list.suggested" = "Рекомендации"; + +/* Title for screen listing autofill logins */ +"credential.provider.list.title" = "Пароли"; + +/* Message for alert when device authentication is not set, where %@ is iPhone|iPad|device */ +"credential.provider.no-device-auth-set.message" = "Задайте код доступа, и %@ будет заполнять пароли из DuckDuckGo автоматически."; + +/* Title for alert when device authentication is not set */ +"credential.provider.no-device-auth-set.title" = "Требуется код доступа к устройству"; + diff --git a/AutofillCredentialProvider/sk.lproj/InfoPlist.strings b/AutofillCredentialProvider/sk.lproj/InfoPlist.strings new file mode 100644 index 0000000000..9809aa19f5 --- /dev/null +++ b/AutofillCredentialProvider/sk.lproj/InfoPlist.strings @@ -0,0 +1,9 @@ +/* Bundle display name */ +"CFBundleDisplayName" = "AutofillCredentialProvider"; + +/* Bundle name */ +"CFBundleName" = "AutofillCredentialProvider"; + +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "Copyright © 2024 DuckDuckGo. All rights reserved."; + diff --git a/AutofillCredentialProvider/sk.lproj/Localizable.strings b/AutofillCredentialProvider/sk.lproj/Localizable.strings new file mode 100644 index 0000000000..c704caedba --- /dev/null +++ b/AutofillCredentialProvider/sk.lproj/Localizable.strings @@ -0,0 +1,96 @@ +/* Close button title */ +"action.button.close" = "Zatvoriť"; + +/* Done button title */ +"action.button.done" = "Hotovo"; + +/* Title of button to launch the DuckDuckGo app */ +"credential.provider.activated.button" = "Otvoriť DuckDuckGo"; + +/* The title of the screen confirming DuckDuckGo can now be used for autofilling passwords */ +"credential.provider.activated.title" = "Automatické dopĺňanie hesiel je aktivované!"; + +/* Default string used if users device is not iPhone or iPad */ +"credential.provider.device.type.default" = "zariadenie"; + +/* Device type is iPhone */ +"credential.provider.device.type.iphone" = "iPhone"; + +/* Device type is iPad */ +"credential.provider.device.type.pad" = "iPad"; + +/* Cancel button for auth when opening login list */ +"credential.provider.list.auth.cancel" = "Zrušiť"; + +/* Reason for auth when opening screen with list of saved passwords */ +"credential.provider.list.auth.reason" = "Ak chcete získať prístup k heslám, odomknite zariadenie"; + +/* Address label for login details on autofill */ +"credential.provider.list.details.address" = "Adresa URL webových stránok"; + +/* Menu item text for copying autofill login details */ +"credential.provider.list.details.copy-prompt" = "Kopírovať %@"; + +/* Title for toast when copying address */ +"credential.provider.list.details.copy-toast.address-copied" = "Adresa bola skopírovaná"; + +/* Title for toast when copying notes */ +"credential.provider.list.details.copy-toast.notes-copied" = "Poznámky boli skopírované"; + +/* Title for toast when copying password */ +"credential.provider.list.details.copy-toast.password-copied" = "Heslo bolo skopírované"; + +/* Title for toast when copying username */ +"credential.provider.list.details.copy-toast.username-copied" = "Meno používateľa bolo skopírované"; + +/* Accessibility title for a Hide Password button replacing displayed password with ***** */ +"credential.provider.list.details.hide-password" = "Skryť heslo"; + +/* Message displaying when the login was last updated */ +"credential.provider.list.details.last-updated" = "Naposledy aktualizované %@"; + +/* Login name label for login details on autofill */ +"credential.provider.list.details.login-name" = "Názov"; + +/* Notes label for login details on autofill */ +"credential.provider.list.details.notes" = "Poznámky"; + +/* Password label for login details on autofill */ +"credential.provider.list.details.password" = "Heslo"; + +/* Accessibility title for a Show Password button displaying actial password instead of ***** */ +"credential.provider.list.details.show-password" = "Zobraziť heslo"; + +/* Username label for login details on autofill */ +"credential.provider.list.details.username" = "Používateľské meno"; + +/* Footer label displayed below table section with option to enable autofill */ +"credential.provider.list.empty-view.footer" = "Heslá sú bezpečne uložené vo vašom zariadení."; + +/* Title for view displayed when autofill has no items */ +"credential.provider.list.empty-view.title" = "Zatiaľ nie sú uložené žiadne heslá"; + +/* Prompt above the title for screen listing autofill logins, example: Choose a password to use for "website.com" */ +"credential.provider.list.prompt" = "Vyber si heslo, ktoré chceš použiť pre „%@“"; + +/* Placeholder for search field on autofill login listing */ +"credential.provider.list.search-placeholder" = "Vyhľadávanie hesiel"; + +/* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ +"credential.provider.list.search.no-results.subtitle" = "pre „%@”"; + +/* Title displayed when there are no results on Autofill search */ +"credential.provider.list.search.no-results.title" = "Žiadne výsledky"; + +/* Section title for group of suggested saved logins */ +"credential.provider.list.suggested" = "Navrhované"; + +/* Title for screen listing autofill logins */ +"credential.provider.list.title" = "Heslo"; + +/* Message for alert when device authentication is not set, where %@ is iPhone|iPad|device */ +"credential.provider.no-device-auth-set.message" = "Nastav prístupový kód na %@ na automatické vypĺňanie tvojich hesiel DuckDuckGo."; + +/* Title for alert when device authentication is not set */ +"credential.provider.no-device-auth-set.title" = "Vyžaduje sa prístupový kód zariadenia."; + diff --git a/AutofillCredentialProvider/sl.lproj/InfoPlist.strings b/AutofillCredentialProvider/sl.lproj/InfoPlist.strings new file mode 100644 index 0000000000..9809aa19f5 --- /dev/null +++ b/AutofillCredentialProvider/sl.lproj/InfoPlist.strings @@ -0,0 +1,9 @@ +/* Bundle display name */ +"CFBundleDisplayName" = "AutofillCredentialProvider"; + +/* Bundle name */ +"CFBundleName" = "AutofillCredentialProvider"; + +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "Copyright © 2024 DuckDuckGo. All rights reserved."; + diff --git a/AutofillCredentialProvider/sl.lproj/Localizable.strings b/AutofillCredentialProvider/sl.lproj/Localizable.strings new file mode 100644 index 0000000000..2ccec47f15 --- /dev/null +++ b/AutofillCredentialProvider/sl.lproj/Localizable.strings @@ -0,0 +1,96 @@ +/* Close button title */ +"action.button.close" = "Zapri"; + +/* Done button title */ +"action.button.done" = "Končano"; + +/* Title of button to launch the DuckDuckGo app */ +"credential.provider.activated.button" = "Odpri DuckDuckGo"; + +/* The title of the screen confirming DuckDuckGo can now be used for autofilling passwords */ +"credential.provider.activated.title" = "Samodejno izpolnjevanje gesel je aktivirano."; + +/* Default string used if users device is not iPhone or iPad */ +"credential.provider.device.type.default" = "naprava"; + +/* Device type is iPhone */ +"credential.provider.device.type.iphone" = "iPhone"; + +/* Device type is iPad */ +"credential.provider.device.type.pad" = "iPad"; + +/* Cancel button for auth when opening login list */ +"credential.provider.list.auth.cancel" = "Prekliči"; + +/* Reason for auth when opening screen with list of saved passwords */ +"credential.provider.list.auth.reason" = "Če želite dostopati do gesel, odklenite napravo"; + +/* Address label for login details on autofill */ +"credential.provider.list.details.address" = "URL spletnega mesta"; + +/* Menu item text for copying autofill login details */ +"credential.provider.list.details.copy-prompt" = "Kopiraj %@"; + +/* Title for toast when copying address */ +"credential.provider.list.details.copy-toast.address-copied" = "Naslov je bil kopiran"; + +/* Title for toast when copying notes */ +"credential.provider.list.details.copy-toast.notes-copied" = "Opombe so kopirane"; + +/* Title for toast when copying password */ +"credential.provider.list.details.copy-toast.password-copied" = "Geslo je bilo kopirano"; + +/* Title for toast when copying username */ +"credential.provider.list.details.copy-toast.username-copied" = "Uporabniško ime je bilo kopirano"; + +/* Accessibility title for a Hide Password button replacing displayed password with ***** */ +"credential.provider.list.details.hide-password" = "Skrij geslo"; + +/* Message displaying when the login was last updated */ +"credential.provider.list.details.last-updated" = "Zadnja posodobitev %@"; + +/* Login name label for login details on autofill */ +"credential.provider.list.details.login-name" = "Naslov"; + +/* Notes label for login details on autofill */ +"credential.provider.list.details.notes" = "Opombe"; + +/* Password label for login details on autofill */ +"credential.provider.list.details.password" = "Geslo"; + +/* Accessibility title for a Show Password button displaying actial password instead of ***** */ +"credential.provider.list.details.show-password" = "Prikaži geslo"; + +/* Username label for login details on autofill */ +"credential.provider.list.details.username" = "Uporabniško ime"; + +/* Footer label displayed below table section with option to enable autofill */ +"credential.provider.list.empty-view.footer" = "Gesla so varno shranjena v vaši napravi."; + +/* Title for view displayed when autofill has no items */ +"credential.provider.list.empty-view.title" = "Nobeno geslo še ni shranjeno"; + +/* Prompt above the title for screen listing autofill logins, example: Choose a password to use for "website.com" */ +"credential.provider.list.prompt" = "Izberite geslo za »%@«"; + +/* Placeholder for search field on autofill login listing */ +"credential.provider.list.search-placeholder" = "Iskanje gesel"; + +/* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ +"credential.provider.list.search.no-results.subtitle" = "za »%@«"; + +/* Title displayed when there are no results on Autofill search */ +"credential.provider.list.search.no-results.title" = "Ni rezultatov"; + +/* Section title for group of suggested saved logins */ +"credential.provider.list.suggested" = "Predlagano"; + +/* Title for screen listing autofill logins */ +"credential.provider.list.title" = "Gesla"; + +/* Message for alert when device authentication is not set, where %@ is iPhone|iPad|device */ +"credential.provider.no-device-auth-set.message" = "Za samodejno izpolnjevanje gesel DuckDuckGo nastavite kodo za dostop v svoji napravi (%@)."; + +/* Title for alert when device authentication is not set */ +"credential.provider.no-device-auth-set.title" = "Zahtevana je koda za dostop do naprave"; + diff --git a/AutofillCredentialProvider/sv.lproj/InfoPlist.strings b/AutofillCredentialProvider/sv.lproj/InfoPlist.strings new file mode 100644 index 0000000000..9809aa19f5 --- /dev/null +++ b/AutofillCredentialProvider/sv.lproj/InfoPlist.strings @@ -0,0 +1,9 @@ +/* Bundle display name */ +"CFBundleDisplayName" = "AutofillCredentialProvider"; + +/* Bundle name */ +"CFBundleName" = "AutofillCredentialProvider"; + +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "Copyright © 2024 DuckDuckGo. All rights reserved."; + diff --git a/AutofillCredentialProvider/sv.lproj/Localizable.strings b/AutofillCredentialProvider/sv.lproj/Localizable.strings new file mode 100644 index 0000000000..04f1b6425c --- /dev/null +++ b/AutofillCredentialProvider/sv.lproj/Localizable.strings @@ -0,0 +1,96 @@ +/* Close button title */ +"action.button.close" = "Stäng"; + +/* Done button title */ +"action.button.done" = "Klart"; + +/* Title of button to launch the DuckDuckGo app */ +"credential.provider.activated.button" = "Öppna DuckDuckGo"; + +/* The title of the screen confirming DuckDuckGo can now be used for autofilling passwords */ +"credential.provider.activated.title" = "Automatisk ifyllning av lösenord har aktiverats!"; + +/* Default string used if users device is not iPhone or iPad */ +"credential.provider.device.type.default" = "enhet"; + +/* Device type is iPhone */ +"credential.provider.device.type.iphone" = "iPhone"; + +/* Device type is iPad */ +"credential.provider.device.type.pad" = "iPad"; + +/* Cancel button for auth when opening login list */ +"credential.provider.list.auth.cancel" = "Avbryt"; + +/* Reason for auth when opening screen with list of saved passwords */ +"credential.provider.list.auth.reason" = "Lås upp enheten för att komma åt lösenord"; + +/* Address label for login details on autofill */ +"credential.provider.list.details.address" = "Webbplats-URL"; + +/* Menu item text for copying autofill login details */ +"credential.provider.list.details.copy-prompt" = "Kopiera %@"; + +/* Title for toast when copying address */ +"credential.provider.list.details.copy-toast.address-copied" = "Adress kopierad"; + +/* Title for toast when copying notes */ +"credential.provider.list.details.copy-toast.notes-copied" = "Anteckningar kopierade"; + +/* Title for toast when copying password */ +"credential.provider.list.details.copy-toast.password-copied" = "Lösenord kopierat"; + +/* Title for toast when copying username */ +"credential.provider.list.details.copy-toast.username-copied" = "Användarnamn kopierat"; + +/* Accessibility title for a Hide Password button replacing displayed password with ***** */ +"credential.provider.list.details.hide-password" = "Dölj lösenord"; + +/* Message displaying when the login was last updated */ +"credential.provider.list.details.last-updated" = "Uppdaterades senast %@"; + +/* Login name label for login details on autofill */ +"credential.provider.list.details.login-name" = "Rubrik"; + +/* Notes label for login details on autofill */ +"credential.provider.list.details.notes" = "Anteckningar"; + +/* Password label for login details on autofill */ +"credential.provider.list.details.password" = "Lösenord"; + +/* Accessibility title for a Show Password button displaying actial password instead of ***** */ +"credential.provider.list.details.show-password" = "Visa lösenord"; + +/* Username label for login details on autofill */ +"credential.provider.list.details.username" = "Användarnamn"; + +/* Footer label displayed below table section with option to enable autofill */ +"credential.provider.list.empty-view.footer" = "Lösenord lagras säkert på din enhet."; + +/* Title for view displayed when autofill has no items */ +"credential.provider.list.empty-view.title" = "Inga lösenord sparade ännu"; + +/* Prompt above the title for screen listing autofill logins, example: Choose a password to use for "website.com" */ +"credential.provider.list.prompt" = "Välj ett lösenord att använda för %@"; + +/* Placeholder for search field on autofill login listing */ +"credential.provider.list.search-placeholder" = "Sök lösenord"; + +/* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ +"credential.provider.list.search.no-results.subtitle" = "för ”%@”"; + +/* Title displayed when there are no results on Autofill search */ +"credential.provider.list.search.no-results.title" = "Inga resultat"; + +/* Section title for group of suggested saved logins */ +"credential.provider.list.suggested" = "Förslag"; + +/* Title for screen listing autofill logins */ +"credential.provider.list.title" = "Lösenord"; + +/* Message for alert when device authentication is not set, where %@ is iPhone|iPad|device */ +"credential.provider.no-device-auth-set.message" = "Ställ in en lösenkod på %@ för att automatiskt fylla i dina DuckDuckGo-lösenord."; + +/* Title for alert when device authentication is not set */ +"credential.provider.no-device-auth-set.title" = "Enhetens lösenkod krävs"; + diff --git a/AutofillCredentialProvider/tr.lproj/InfoPlist.strings b/AutofillCredentialProvider/tr.lproj/InfoPlist.strings new file mode 100644 index 0000000000..9809aa19f5 --- /dev/null +++ b/AutofillCredentialProvider/tr.lproj/InfoPlist.strings @@ -0,0 +1,9 @@ +/* Bundle display name */ +"CFBundleDisplayName" = "AutofillCredentialProvider"; + +/* Bundle name */ +"CFBundleName" = "AutofillCredentialProvider"; + +/* Copyright (human-readable) */ +"NSHumanReadableCopyright" = "Copyright © 2024 DuckDuckGo. All rights reserved."; + diff --git a/AutofillCredentialProvider/tr.lproj/Localizable.strings b/AutofillCredentialProvider/tr.lproj/Localizable.strings new file mode 100644 index 0000000000..1bf39ce8dc --- /dev/null +++ b/AutofillCredentialProvider/tr.lproj/Localizable.strings @@ -0,0 +1,96 @@ +/* Close button title */ +"action.button.close" = "Kapat"; + +/* Done button title */ +"action.button.done" = "Bitti"; + +/* Title of button to launch the DuckDuckGo app */ +"credential.provider.activated.button" = "DuckDuckGo'yu aç"; + +/* The title of the screen confirming DuckDuckGo can now be used for autofilling passwords */ +"credential.provider.activated.title" = "Şifreleri otomatik doldurma etkinleştirildi!"; + +/* Default string used if users device is not iPhone or iPad */ +"credential.provider.device.type.default" = "cihaz"; + +/* Device type is iPhone */ +"credential.provider.device.type.iphone" = "iPhone"; + +/* Device type is iPad */ +"credential.provider.device.type.pad" = "iPad"; + +/* Cancel button for auth when opening login list */ +"credential.provider.list.auth.cancel" = "İptal"; + +/* Reason for auth when opening screen with list of saved passwords */ +"credential.provider.list.auth.reason" = "Şifrelere erişmek için cihazın kilidini açın"; + +/* Address label for login details on autofill */ +"credential.provider.list.details.address" = "Web sitesi URL'si"; + +/* Menu item text for copying autofill login details */ +"credential.provider.list.details.copy-prompt" = "%@ Ögesini Kopyala"; + +/* Title for toast when copying address */ +"credential.provider.list.details.copy-toast.address-copied" = "Adres kopyalandı"; + +/* Title for toast when copying notes */ +"credential.provider.list.details.copy-toast.notes-copied" = "Notlar kopyalandı"; + +/* Title for toast when copying password */ +"credential.provider.list.details.copy-toast.password-copied" = "Şifre kopyalandı"; + +/* Title for toast when copying username */ +"credential.provider.list.details.copy-toast.username-copied" = "Kullanıcı adı kopyalandı"; + +/* Accessibility title for a Hide Password button replacing displayed password with ***** */ +"credential.provider.list.details.hide-password" = "Parolayı gizle"; + +/* Message displaying when the login was last updated */ +"credential.provider.list.details.last-updated" = "Son güncelleme %@"; + +/* Login name label for login details on autofill */ +"credential.provider.list.details.login-name" = "Title"; + +/* Notes label for login details on autofill */ +"credential.provider.list.details.notes" = "Notlar"; + +/* Password label for login details on autofill */ +"credential.provider.list.details.password" = "Parola"; + +/* Accessibility title for a Show Password button displaying actial password instead of ***** */ +"credential.provider.list.details.show-password" = "Parolayı göster"; + +/* Username label for login details on autofill */ +"credential.provider.list.details.username" = "Kullanıcı adı"; + +/* Footer label displayed below table section with option to enable autofill */ +"credential.provider.list.empty-view.footer" = "Şifreler cihazınızda güvenli bir şekilde saklanır."; + +/* Title for view displayed when autofill has no items */ +"credential.provider.list.empty-view.title" = "Henüz şifre kaydedilmedi"; + +/* Prompt above the title for screen listing autofill logins, example: Choose a password to use for "website.com" */ +"credential.provider.list.prompt" = "\"%@\" için kullanılacak bir şifre seçin"; + +/* Placeholder for search field on autofill login listing */ +"credential.provider.list.search-placeholder" = "Şifreleri ara"; + +/* Subtitle displayed when there are no results on Autofill search, example : No Result (Title) for Duck (Subtitle) */ +"credential.provider.list.search.no-results.subtitle" = "\"%@\" için"; + +/* Title displayed when there are no results on Autofill search */ +"credential.provider.list.search.no-results.title" = "Sonuç yok"; + +/* Section title for group of suggested saved logins */ +"credential.provider.list.suggested" = "Önerilen"; + +/* Title for screen listing autofill logins */ +"credential.provider.list.title" = "Şifreler"; + +/* Message for alert when device authentication is not set, where %@ is iPhone|iPad|device */ +"credential.provider.no-device-auth-set.message" = "DuckDuckGo şifrelerinizi otomatik olarak doldurmak için %@ üzerinde bir parola belirleyin."; + +/* Title for alert when device authentication is not set */ +"credential.provider.no-device-auth-set.title" = "Cihaz Parolası Gerekli"; + diff --git a/Configuration/Version.xcconfig b/Configuration/Version.xcconfig index 2f435d72f7..9ef4c72f39 100644 --- a/Configuration/Version.xcconfig +++ b/Configuration/Version.xcconfig @@ -1 +1 @@ -MARKETING_VERSION = 7.148.0 +MARKETING_VERSION = 7.149.0 diff --git a/Core/AppPrivacyConfigurationDataProvider.swift b/Core/AppPrivacyConfigurationDataProvider.swift index 3d1a36860f..538a5c786b 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 = "\"a913df909743eadb5bd381c7fddf4902\"" - public static let embeddedDataSHA = "d1fb789ab4def06b6cf359d5e9971c840668ab5307f5690bc1483bb2266a2558" + public static let embeddedDataETag = "\"5e5dc1c97834210a4803eb2683f21f95\"" + public static let embeddedDataSHA = "758a4d35540518b71b74ef7769a1652d124b75c12dd244fe7612b829c824d510" } public var embeddedDataEtag: String { diff --git a/Core/AppTrackerDataSetProvider.swift b/Core/AppTrackerDataSetProvider.swift index 1ad2d9fb89..4e73164f0a 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 = "\"7af63a1c5812c9200d3120f5dd598993\"" - public static let embeddedDataSHA = "ef3eb8b998faa201192a190cff3fe0fc228cf2212be44271036dbd63ade5ddcf" + public static let embeddedDataETag = "\"382541021cbc55b218714db779561a51\"" + public static let embeddedDataSHA = "5e8293a4c3e3ea5217e8e39db0c8525de4647ec78b102cff292ab5fa213578aa" } public var embeddedDataEtag: String { diff --git a/DuckDuckGo/AutofillInterfaceEmailTruncator.swift b/Core/AutofillInterfaceEmailTruncator.swift similarity index 91% rename from DuckDuckGo/AutofillInterfaceEmailTruncator.swift rename to Core/AutofillInterfaceEmailTruncator.swift index 2eb28faa1b..41fb28342c 100644 --- a/DuckDuckGo/AutofillInterfaceEmailTruncator.swift +++ b/Core/AutofillInterfaceEmailTruncator.swift @@ -19,8 +19,8 @@ import Foundation -struct AutofillInterfaceEmailTruncator { - static func truncateEmail(_ email: String, maxLength: Int) -> String { +public struct AutofillInterfaceEmailTruncator { + public static func truncateEmail(_ email: String, maxLength: Int) -> String { let emailComponents = email.components(separatedBy: "@") if emailComponents.count > 1 && email.count > maxLength { let ellipsis = "..." diff --git a/DuckDuckGo/PasswordHider.swift b/Core/PasswordHider.swift similarity index 83% rename from DuckDuckGo/PasswordHider.swift rename to Core/PasswordHider.swift index 1849248f24..ffe3a70929 100644 --- a/DuckDuckGo/PasswordHider.swift +++ b/Core/PasswordHider.swift @@ -19,11 +19,15 @@ import Foundation -struct PasswordHider { - let password: String - var hiddenPassword: String { +public struct PasswordHider { + public let password: String + public var hiddenPassword: String { let maximumPasswordDisplayCount = 22 let passwordCount = password.count > maximumPasswordDisplayCount ? maximumPasswordDisplayCount : password.count return String(repeating: "•", count: passwordCount) } + + public init(password: String) { + self.password = password + } } diff --git a/Core/PixelEvent.swift b/Core/PixelEvent.swift index 4c9d909115..29eadee0f7 100644 --- a/Core/PixelEvent.swift +++ b/Core/PixelEvent.swift @@ -312,6 +312,8 @@ extension Pixel { case autofillOnboardedUser case autofillToggledOn case autofillToggledOff + case autofillExtensionToggledOn + case autofillExtensionToggledOff case autofillLoginsStacked case autofillManagementOpened @@ -332,7 +334,18 @@ extension Pixel { case getDesktopCopy case getDesktopShare - + + case autofillExtensionEnabled + case autofillExtensionDisabled + case autofillExtensionWelcomeDismiss + case autofillExtensionWelcomeLaunchApp + case autofillExtensionQuickTypeConfirmed + case autofillExtensionQuickTypeCancelled + case autofillExtensionPasswordsOpened + case autofillExtensionPasswordsDismissed + case autofillExtensionPasswordSelected + case autofillExtensionPasswordsSearch + case autofillJSPixelFired(_ pixel: AutofillUserScript.JSPixel) case secureVaultError @@ -1203,6 +1216,8 @@ extension Pixel.Event { case .autofillOnboardedUser: return "m_autofill_onboardeduser" case .autofillToggledOn: return "m_autofill_toggled_on" case .autofillToggledOff: return "m_autofill_toggled_off" + case .autofillExtensionToggledOn: return "m_autofill_extension_toggled_on" + case .autofillExtensionToggledOff: return "m_autofill_extension_toggled_off" case .autofillLoginsStacked: return "m_autofill_logins_stacked" @@ -1232,6 +1247,18 @@ extension Pixel.Event { case .getDesktopCopy: return "m_get_desktop_copy" case .getDesktopShare: return "m_get_desktop_share" + // Autofill Credential Provider Extension + case .autofillExtensionEnabled: return "autofill_extension_enabled" + case .autofillExtensionDisabled: return "autofill_extension_disabled" + case .autofillExtensionWelcomeDismiss: return "autofill_extension_welcome_dismiss" + case .autofillExtensionWelcomeLaunchApp: return "autofill_extension_welcome_launch_app" + case .autofillExtensionQuickTypeConfirmed: return "autofill_extension_quicktype_confirmed" + case .autofillExtensionQuickTypeCancelled: return "autofill_extension_quicktype_cancelled" + case .autofillExtensionPasswordsOpened: return "autofill_extension_passwords_opened" + case .autofillExtensionPasswordsDismissed: return "autofill_extension_passwords_dismissed" + case .autofillExtensionPasswordSelected: return "autofill_extension_password_selected" + case .autofillExtensionPasswordsSearch: return "autofill_extension_passwords_search" + case .autofillJSPixelFired(let pixel): return "m_ios_\(pixel.pixelName)" diff --git a/Core/UserDefaultsPropertyWrapper.swift b/Core/UserDefaultsPropertyWrapper.swift index 4858ad964d..4b0b9682ab 100644 --- a/Core/UserDefaultsPropertyWrapper.swift +++ b/Core/UserDefaultsPropertyWrapper.swift @@ -95,6 +95,7 @@ public struct UserDefaultsWrapper { case autofillFillDate = "com.duckduckgo.app.autofill.FillDate" case autofillOnboardedUser = "com.duckduckgo.app.autofill.OnboardedUser" case autofillSurveysCompleted = "com.duckduckgo.app.autofill.SurveysCompleted" + case autofillExtensionEnabled = "com.duckduckgo.app.autofill.ExtensionEnabled" case syncPromoBookmarksDismissed = "com.duckduckgo.app.sync.PromoBookmarksDismissed" case syncPromoPasswordsDismissed = "com.duckduckgo.app.sync.PromoPasswordsDismissed" diff --git a/Core/ios-config.json b/Core/ios-config.json index 188f9299e7..2263fb2097 100644 --- a/Core/ios-config.json +++ b/Core/ios-config.json @@ -1,6 +1,6 @@ { "readme": "https://github.com/duckduckgo/privacy-configuration", - "version": 1733157661102, + "version": 1733826965137, "features": { "adAttributionReporting": { "state": "disabled", @@ -75,20 +75,20 @@ "hash": "c292bb627849854515cebbded288ef5a" }, "aiChat": { - "state": "enabled", + "state": "disabled", "exceptions": [], "features": { "browsingToolbarShortcut": { - "state": "enabled" + "state": "disabled" }, "addressBarShortcut": { - "state": "enabled" + "state": "disabled" } }, "settings": { "aiChatURL": "https://duckduckgo.com/?q=DuckDuckGo+AI+Chat&ia=chat&duckai=4" }, - "hash": "14908e76cd3a8b4919e03003fd201300" + "hash": "4b5209f8cbe489299641ea30ed9a2542" }, "ampLinks": { "exceptions": [ @@ -116,6 +116,9 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } @@ -144,7 +147,7 @@ ] }, "state": "enabled", - "hash": "fa5f86bac5946c528cd6bc7449a2718a" + "hash": "2e91c1024751b208d974721cd5c4a020" }, "androidBrowserConfig": { "exceptions": [], @@ -156,6 +159,14 @@ "state": "disabled", "hash": "728493ef7a1488e4781656d3f9db84aa" }, + "auraExperiment": { + "exceptions": [], + "settings": { + "packages": [] + }, + "state": "disabled", + "hash": "527fd2e156c7669f001516ee2d3d7c0e" + }, "autocompleteTabs": { "state": "enabled", "exceptions": [], @@ -601,6 +612,201 @@ { "domain": "outlet46.de" }, + { + "domain": "mytolino.de" + }, + { + "domain": "google.ae" + }, + { + "domain": "google.at" + }, + { + "domain": "google.be" + }, + { + "domain": "google.bg" + }, + { + "domain": "google.by" + }, + { + "domain": "google.ca" + }, + { + "domain": "google.ch" + }, + { + "domain": "google.cl" + }, + { + "domain": "google.co.id" + }, + { + "domain": "google.co.il" + }, + { + "domain": "google.co.in" + }, + { + "domain": "google.co.jp" + }, + { + "domain": "google.co.ke" + }, + { + "domain": "google.co.kr" + }, + { + "domain": "google.co.nz" + }, + { + "domain": "google.co.th" + }, + { + "domain": "google.co.uk" + }, + { + "domain": "google.co.ve" + }, + { + "domain": "google.co.za" + }, + { + "domain": "google.com" + }, + { + "domain": "google.com.ar" + }, + { + "domain": "google.com.au" + }, + { + "domain": "google.com.br" + }, + { + "domain": "google.com.co" + }, + { + "domain": "google.com.ec" + }, + { + "domain": "google.com.eg" + }, + { + "domain": "google.com.hk" + }, + { + "domain": "google.com.mx" + }, + { + "domain": "google.com.my" + }, + { + "domain": "google.com.pe" + }, + { + "domain": "google.com.ph" + }, + { + "domain": "google.com.pk" + }, + { + "domain": "google.com.py" + }, + { + "domain": "google.com.sa" + }, + { + "domain": "google.com.sg" + }, + { + "domain": "google.com.tr" + }, + { + "domain": "google.com.tw" + }, + { + "domain": "google.com.ua" + }, + { + "domain": "google.com.uy" + }, + { + "domain": "google.com.vn" + }, + { + "domain": "google.cz" + }, + { + "domain": "google.de" + }, + { + "domain": "google.dk" + }, + { + "domain": "google.dz" + }, + { + "domain": "google.ee" + }, + { + "domain": "google.es" + }, + { + "domain": "google.fi" + }, + { + "domain": "google.fr" + }, + { + "domain": "google.gr" + }, + { + "domain": "google.hr" + }, + { + "domain": "google.hu" + }, + { + "domain": "google.ie" + }, + { + "domain": "google.it" + }, + { + "domain": "google.lt" + }, + { + "domain": "google.lv" + }, + { + "domain": "google.nl" + }, + { + "domain": "google.no" + }, + { + "domain": "google.pl" + }, + { + "domain": "google.pt" + }, + { + "domain": "google.ro" + }, + { + "domain": "google.rs" + }, + { + "domain": "google.ru" + }, + { + "domain": "google.se" + }, + { + "domain": "google.sk" + }, { "domain": "marvel.com" }, @@ -613,6 +819,9 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } @@ -643,7 +852,7 @@ } } }, - "hash": "2c73b04e22812bf92bc2a859e7540c3a" + "hash": "32cbf1af6d2dd1ef9c61bb3cc34852dd" }, "autofillBreakageReporter": { "state": "enabled", @@ -656,10 +865,15 @@ "autofillSurveys": { "state": "enabled", "settings": { - "surveys": [] + "surveys": [ + { + "id": "2024-12-04", + "url": "https://selfserve.decipherinc.com/survey/selfserve/32ab/241201" + } + ] }, "exceptions": [], - "hash": "1d554e00b6a8adc2a7514accf9a92fdb" + "hash": "2f7e9f55c5dbcb35ee01be966b079512" }, "autofill": { "exceptions": [ @@ -724,9 +938,12 @@ } ] } + }, + "partialFormSaves": { + "state": "enabled" } }, - "hash": "28d4af98382248e184c4315bd49f4222" + "hash": "07b6b3bb0e6ddc4bf3dadbbbd0419478" }, "backgroundAgentPixelTest": { "state": "enabled", @@ -776,11 +993,14 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } ], - "hash": "37e0cf88badfc8b01b6394f0884502f6" + "hash": "2b0962b6ea0b84b7450358766ccf667d" }, "brokenSitePrompt": { "state": "enabled", @@ -1482,6 +1702,9 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } @@ -1501,7 +1724,7 @@ } }, "state": "disabled", - "hash": "cb1f114a9e0314393b2a0f789cba163f" + "hash": "9b33d212830c6b5b67317c0621b15006" }, "clickToPlay": { "exceptions": [ @@ -1517,6 +1740,9 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } @@ -1531,7 +1757,7 @@ } }, "state": "disabled", - "hash": "894fb86c1f058aee9db47cfcdf3637de" + "hash": "1533ba1f2ef66001f0e4d6faf0d48be7" }, "clientBrandHint": { "exceptions": [], @@ -1574,11 +1800,14 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } ], - "hash": "96b2f778bab196aa424e9c859ddea778" + "hash": "ee5eabf360024d267d4668e73c053a48" }, "contextualOnboarding": { "exceptions": [], @@ -1650,12 +1879,15 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } ], "state": "disabled", - "hash": "fce0a9ccd7ae060d25e7debe4d8905fb" + "hash": "91ceb18e840b0b322c2fd818e6b5453a" }, "customUserAgent": { "settings": { @@ -1846,6 +2078,9 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } @@ -2791,7 +3026,7 @@ }, { "selector": "[data-identity='billboard-ad']", - "type": "hide-empty" + "type": "hide" }, { "selector": "[data-identity='leaderboard-ad']", @@ -2994,6 +3229,23 @@ } ] }, + { + "domain": "e-chords.com", + "rules": [ + { + "selector": ".adscifra", + "type": "hide" + }, + { + "selector": ".banner", + "type": "hide-empty" + }, + { + "selector": "#banner", + "type": "hide-empty" + } + ] + }, { "domain": "ebay.com", "rules": [ @@ -5210,7 +5462,7 @@ ] }, "state": "enabled", - "hash": "16e64ea4c926bdf7c865a8b7cbde1b2b" + "hash": "a3957788141533420149b5c96c8de136" }, "exceptionHandler": { "exceptions": [ @@ -5226,12 +5478,15 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } ], "state": "disabled", - "hash": "be6751fe0307a7e1b9476f4d8b8d0aaf" + "hash": "01c90bccc9b20770953ff3f786fa4dac" }, "extendedOnboarding": { "exceptions": [], @@ -5256,11 +5511,14 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } ], - "hash": "7f042650922da2636492e77ed1101bce" + "hash": "0cc652d37e184686c92eb64e6ab9d3fa" }, "fingerprintingBattery": { "exceptions": [ @@ -5279,12 +5537,15 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } ], "state": "enabled", - "hash": "fcc2138fa97c35ded544b39708fda919" + "hash": "3821c0fed8912dd05b1618e3a0594fcf" }, "fingerprintingCanvas": { "settings": { @@ -5387,12 +5648,15 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } ], "state": "disabled", - "hash": "49a3d497835bf5715aaaa73f87dd974f" + "hash": "1165c91b6e289988a60b72a97d3a5a3b" }, "fingerprintingHardware": { "settings": { @@ -5462,6 +5726,9 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "target.com" }, @@ -5470,7 +5737,7 @@ } ], "state": "enabled", - "hash": "b1f406c6ff87e27244d26289c0e383f9" + "hash": "b1de304ce2c53c1fc1ef395c98296f8f" }, "fingerprintingScreenSize": { "settings": { @@ -5522,12 +5789,15 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } ], "state": "enabled", - "hash": "046340bb9287a20efed6189525ec5fed" + "hash": "7e7b65104a08a935f2263eb34b84d3cb" }, "fingerprintingTemporaryStorage": { "exceptions": [ @@ -5552,12 +5822,15 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } ], "state": "enabled", - "hash": "14b7fe3d276b52109c59f0c71aee4f71" + "hash": "934f0960313eb7801841ee99cd3dc802" }, "googleRejected": { "exceptions": [ @@ -5573,12 +5846,15 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } ], "state": "disabled", - "hash": "be6751fe0307a7e1b9476f4d8b8d0aaf" + "hash": "01c90bccc9b20770953ff3f786fa4dac" }, "gpc": { "state": "enabled", @@ -5625,6 +5901,9 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } @@ -5638,7 +5917,7 @@ "privacy-test-pages.site" ] }, - "hash": "501bbc6471eb079cb27fa8a2a47467a5" + "hash": "92dbff4d73bdec464f5767165933b0bf" }, "harmfulApis": { "settings": { @@ -5752,12 +6031,15 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } ], "state": "disabled", - "hash": "fb598c4167ff166d85dd49c701cc5579" + "hash": "603b489064ac5a2379d18a946644e499" }, "history": { "state": "enabled", @@ -5806,11 +6088,14 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } ], - "hash": "b47d255c6f836ecb7ae0b3e61cc2c025" + "hash": "a0a328c1f5189fabc27bd1659146c3a2" }, "incontextSignup": { "exceptions": [], @@ -5838,11 +6123,6 @@ "exceptions": [], "hash": "429cea8d27316dc62af04159ec7c42b5" }, - "loadingBarExp": { - "exceptions": [], - "state": "disabled", - "hash": "728493ef7a1488e4781656d3f9db84aa" - }, "maliciousSiteProtection": { "state": "internal", "exceptions": [], @@ -5885,6 +6165,9 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } @@ -5897,7 +6180,7 @@ ] }, "state": "enabled", - "hash": "d14f6e3a9aa4139ee1d517016b59691e" + "hash": "ac148f97532e086f27bedc5b7f6fc4a2" }, "networkProtection": { "state": "enabled", @@ -5945,12 +6228,15 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } ], "state": "disabled", - "hash": "82088db85ca7f64418fbfd57db25ade1" + "hash": "e3342b0dc61ba52c56a90f553b7bfc43" }, "performanceMetrics": { "state": "enabled", @@ -5967,11 +6253,14 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } ], - "hash": "6792064606a5a72c5cd44addb4d40bda" + "hash": "04fb7d6e0337563a26060b1a32d2332e" }, "phishingDetection": { "state": "disabled", @@ -6110,12 +6399,15 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } ], "state": "disabled", - "hash": "138c3b2409f6b3bf967b804ab9bf2ce2" + "hash": "359af23cc499c17b84ef08a118fedc4a" }, "remoteMessaging": { "state": "enabled", @@ -6137,6 +6429,9 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } @@ -6144,7 +6439,7 @@ "settings": { "windowInMs": 0 }, - "hash": "baf19d9e0f506ed09f46c95b1849adee" + "hash": "54b249ffdfd7710373849720c7bf1ed8" }, "runtimeChecks": { "state": "disabled", @@ -6161,12 +6456,15 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } ], "settings": {}, - "hash": "dfede9f06b9e322e198736703d013d15" + "hash": "c2c2d48b0fc1b03db53065ca5da92675" }, "sendFullPackageInstallSource": { "state": "enabled", @@ -6188,12 +6486,15 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } ], "state": "disabled", - "hash": "be6751fe0307a7e1b9476f4d8b8d0aaf" + "hash": "01c90bccc9b20770953ff3f786fa4dac" }, "showOnAppLaunch": { "exceptions": [ @@ -6209,12 +6510,15 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } ], "state": "disabled", - "hash": "be6751fe0307a7e1b9476f4d8b8d0aaf" + "hash": "01c90bccc9b20770953ff3f786fa4dac" }, "sslCertificates": { "state": "enabled", @@ -6240,12 +6544,15 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } ], "state": "disabled", - "hash": "be6751fe0307a7e1b9476f4d8b8d0aaf" + "hash": "01c90bccc9b20770953ff3f786fa4dac" }, "syncPromotion": { "state": "enabled", @@ -7154,6 +7461,7 @@ "itsthevibe.com", "nytimes.com", "realmadrid.com", + "repretel.com", "rocketnews24.com", "solitaired.com", "stuff.co.nz", @@ -7171,6 +7479,7 @@ { "rule": "securepubads.g.doubleclick.net/pagead/ppub_config", "domains": [ + "repretel.com", "rocketnews24.com", "weather.com", "wunderground.com" @@ -9715,11 +10024,14 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } ], - "hash": "f5b235ed3c5c9afdd44edfa3464235cf" + "hash": "cc188a741d0bbe34cd7de16f70a69df7" }, "trackingCookies1p": { "settings": { @@ -9741,12 +10053,15 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } ], "state": "disabled", - "hash": "763f56424b0827b5731927a043219912" + "hash": "2426b21363085484652b231ca66897a5" }, "trackingCookies3p": { "settings": { @@ -9765,12 +10080,15 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } ], "state": "disabled", - "hash": "82088db85ca7f64418fbfd57db25ade1" + "hash": "e3342b0dc61ba52c56a90f553b7bfc43" }, "trackingParameters": { "exceptions": [ @@ -9801,6 +10119,9 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "theverge.com" }, @@ -9838,7 +10159,7 @@ ] }, "state": "enabled", - "hash": "3792a4970c07fe00da08f77e7dcf01ed" + "hash": "51753ddb14b1c7a22eb20f74f46c092d" }, "userAgentRotation": { "settings": { @@ -9857,12 +10178,15 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "instructure.com" } ], "state": "disabled", - "hash": "9225b8785d6973db37abde99d81d219c" + "hash": "fbc6687658b62b108ed7769a660dd8e0" }, "voiceSearch": { "exceptions": [], @@ -9888,6 +10212,9 @@ { "domain": "flexmls.com" }, + { + "domain": "asuracomic.net" + }, { "domain": "wsj.com" }, @@ -9965,7 +10292,7 @@ } ] }, - "hash": "2853748f3ebb813d59f4db4a7bb13c83" + "hash": "39bd8f30c68f608ae78ffde4e13bef93" }, "webViewBlobDownload": { "exceptions": [], @@ -10021,6 +10348,26 @@ "exceptions": [], "state": "disabled", "hash": "728493ef7a1488e4781656d3f9db84aa" + }, + "experimentTest": { + "state": "enabled", + "exceptions": [], + "features": { + "experimentTestAA": { + "state": "enabled", + "cohorts": [ + { + "name": "control", + "weight": 1 + }, + { + "name": "treatment", + "weight": 1 + } + ] + } + }, + "hash": "0fe5af5a94e036bf5d78076df6dd771b" } }, "unprotectedTemporary": [] diff --git a/Core/trackerData.json b/Core/trackerData.json index b2123dd778..f09798f0e6 100644 --- a/Core/trackerData.json +++ b/Core/trackerData.json @@ -1,6 +1,6 @@ { "_builtWith": { - "tracker-radar": "e270978af9ffd0c909a62969df5f894128d41682920fb7a4c913e25e9ab1ecef-4013b4e91930c643394cb31c6c745356f133b04f", + "tracker-radar": "1108f03ca047465b2b8d8ab3385ba2cd4f21e1d0111571f8342b3eb0735b1c4a-4013b4e91930c643394cb31c6c745356f133b04f", "tracker-surrogates": "fe15c53e755af1257774459ecf066f673f485cb0" }, "readme": "https://github.com/duckduckgo/tracker-blocklists", @@ -6604,44 +6604,7 @@ "fingerprinting": 2, "cookies": 0.00112, "categories": [], - "default": "ignore", - "rules": [ - { - "rule": "coveo\\.com\\/coveo\\.analytics\\.js\\/2\\/coveoua\\.js", - "fingerprinting": 2, - "cookies": 0.000163 - }, - { - "rule": "coveo\\.com\\/coveo\\.analytics\\.js\\/1\\.0\\/coveoua\\.js", - "fingerprinting": 2, - "cookies": 0.0000613 - }, - { - "rule": "coveo\\.com\\/coveo\\.analytics\\.js\\/coveoua\\.js", - "fingerprinting": 1, - "cookies": 0.0000681 - }, - { - "rule": "coveo\\.com\\/coveo\\.analytics\\.js\\/latest\\/coveoua\\.js", - "fingerprinting": 1, - "cookies": 0.0000204 - }, - { - "rule": "coveo\\.com\\/atomic\\/v1\\.110\\/p-f4cb35d7\\.js", - "fingerprinting": 2, - "cookies": 0.0000136 - }, - { - "rule": "coveo\\.com\\/atomic\\/v1\\/p-217d4a01\\.js", - "fingerprinting": 2, - "cookies": 0 - }, - { - "rule": "coveo\\.com\\/coveo\\.analytics\\.js\\/2\\/coveoua\\.browser\\.js", - "fingerprinting": 2, - "cookies": 0.0000136 - } - ] + "default": "ignore" }, "cpmstar.com": { "domain": "cpmstar.com", @@ -8652,14 +8615,7 @@ "fingerprinting": 2, "cookies": 0.00114, "categories": [], - "default": "ignore", - "rules": [ - { - "rule": "elfsight\\.com\\/apps\\/social-share-buttons\\/release\\/bcbd1ca01fc572c7bc650c98dbe032152aa706f5\\/app\\/socialShareButtons\\.js", - "fingerprinting": 3, - "cookies": 0 - } - ] + "default": "ignore" }, "elitrack.com": { "domain": "elitrack.com", @@ -13283,7 +13239,27 @@ "default": "ignore", "rules": [ { - "rule": "impervadns\\.net//SP2013v1/Enterprise/JS/", + "rule": "impervadns\\.net\\/\\/SP2013v1\\/Enterprise\\/JS\\/foundation\\.min\\.js", + "fingerprinting": 1, + "cookies": 0.000136 + }, + { + "rule": "impervadns\\.net\\/\\/SP2013v1\\/Enterprise\\/JS\\/enterprise\\.min\\.js", + "fingerprinting": 1, + "cookies": 0.000136 + }, + { + "rule": "impervadns\\.net\\/\\/SP2013v1\\/Enterprise\\/JS\\/jquery\\.cookie\\.js", + "fingerprinting": 1, + "cookies": 0.000136 + }, + { + "rule": "impervadns\\.net\\/\\/SP2013v1\\/Enterprise\\/JS\\/knockout\\.min\\.js", + "fingerprinting": 1, + "cookies": 0.000136 + }, + { + "rule": "impervadns\\.net\\/\\/SP2013v1\\/Enterprise\\/JS\\/jquery-ui\\.js", "fingerprinting": 1, "cookies": 0.000136 }, @@ -15753,30 +15729,9 @@ { "rule": "listrakbi\\.com/v1/Product" }, - { - "rule": "listrakbi\\.com/json/07c34100-1080-4c55-9097-05c7f4a2b19b" - }, - { - "rule": "listrakbi\\.com/json/f5f04466-f923-491d-9354-679d54e32def" - }, - { - "rule": "listrakbi\\.com/json/eb9d26f3-d7e9-4df8-9800-a79cfaf345be" - }, { "rule": "listrakbi\\.com/SadvKLqKgI5T/cart/update" }, - { - "rule": "listrakbi\\.com/json/a6c8a6f0-379f-4e0e-8f1a-db4e3efa6123" - }, - { - "rule": "listrakbi\\.com/json/86d9476c-c670-4b5d-a33c-bca65c91576f" - }, - { - "rule": "listrakbi\\.com/json/043b15b6-cb62-4e61-9d8a-89856bdbf496" - }, - { - "rule": "listrakbi\\.com/json/9902c090-0d30-4673-b94b-3851cb8d6035" - }, { "rule": "listrakbi\\.com/RmR1Kqh2AYPr/cart/update" }, @@ -15797,6 +15752,9 @@ }, { "rule": "listrakbi\\.com/[a-zA-Z0-9]+\\.js" + }, + { + "rule": "listrakbi\\.com/json/.*" } ] }, @@ -21827,18 +21785,6 @@ { "rule": "qualtrics\\.com/WRSiteInterceptEngine/" }, - { - "rule": "qualtrics\\.com/WRQualtricsShared/Graphics/siteintercept/wr-dialog-close-btn-black\\.png" - }, - { - "rule": "qualtrics\\.com/WRQualtricsShared/Graphics/siteintercept/wr-dialog-close-btn-white\\.png" - }, - { - "rule": "qualtrics\\.com/WRQualtricsShared/Graphics/siteintercept/building_preview\\.gif" - }, - { - "rule": "qualtrics\\.com/WRQualtricsShared/Graphics/siteintercept/remove_screen_capture\\.png" - }, { "rule": "qualtrics\\.com/static/prototype-ui-modules/SharedGraphics/siteintercept/svg-close-btn-black-7\\.svg" }, @@ -21854,12 +21800,6 @@ { "rule": "qualtrics\\.com/static/prototype-ui-modules/SharedGraphics/siteintercept/svg-close-btn-black-4\\.svg" }, - { - "rule": "qualtrics\\.com/WRQualtricsShared/Graphics/siteintercept/popup_shadow_transparent\\.png" - }, - { - "rule": "qualtrics\\.com/WRQualtricsShared/Graphics/siteintercept/feedback-blue-right\\.png" - }, { "rule": "qualtrics\\.com/ControlPanel/Graphic\\.php" }, @@ -21874,6 +21814,9 @@ }, { "rule": "qualtrics\\.com/static/q-siteintercept/" + }, + { + "rule": "qualtrics\\.com/WRQualtricsShared/" } ] }, @@ -22243,6 +22186,18 @@ "cookies": 0.01, "default": "block" }, + "rebuyengine.com": { + "domain": "rebuyengine.com", + "owner": { + "name": "rebuyengine.com", + "displayName": "rebuyengine.com" + }, + "prevalence": 0.00142, + "fingerprinting": 2, + "cookies": 0.00125, + "categories": [], + "default": "ignore" + }, "reconditerake.com": { "domain": "reconditerake.com", "owner": { @@ -26891,30 +26846,12 @@ "categories": [], "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" }, @@ -26934,13 +26871,7 @@ "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" + "rule": "tiktok\\.com/i18n/pixel/" } ] }, @@ -32665,17 +32596,6 @@ "cookies": 0.01, "default": "block" }, - "acceptableauthority.com": { - "domain": "acceptableauthority.com", - "owner": { - "name": "Leven Labs, Inc. DBA Admiral (acceptableauthority.com)", - "displayName": "Admiral" - }, - "prevalence": 0.0107, - "fingerprinting": 1, - "cookies": 0.01, - "default": "block" - }, "accountsdoor.com": { "domain": "accountsdoor.com", "owner": { @@ -32951,17 +32871,6 @@ "cookies": 0.01, "default": "block" }, - "alertarithmetic.com": { - "domain": "alertarithmetic.com", - "owner": { - "name": "Leven Labs, Inc. DBA Admiral (alertarithmetic.com)", - "displayName": "Admiral" - }, - "prevalence": 0.0107, - "fingerprinting": 1, - "cookies": 0.01, - "default": "block" - }, "aliasanvil.com": { "domain": "aliasanvil.com", "owner": { @@ -35107,17 +35016,6 @@ "cookies": 0.01, "default": "block" }, - "concernedchange.com": { - "domain": "concernedchange.com", - "owner": { - "name": "Leven Labs, Inc. DBA Admiral (concernedchange.com)", - "displayName": "Admiral" - }, - "prevalence": 0.0107, - "fingerprinting": 1, - "cookies": 0.01, - "default": "block" - }, "concernedchickens.com": { "domain": "concernedchickens.com", "owner": { @@ -37516,17 +37414,6 @@ "cookies": 0.01, "default": "block" }, - "fertilefeeling.com": { - "domain": "fertilefeeling.com", - "owner": { - "name": "Leven Labs, Inc. DBA Admiral (fertilefeeling.com)", - "displayName": "Admiral" - }, - "prevalence": 0.0107, - "fingerprinting": 1, - "cookies": 0.01, - "default": "block" - }, "fewjuice.com": { "domain": "fewjuice.com", "owner": { @@ -38913,17 +38800,6 @@ "cookies": 0.01, "default": "block" }, - "hatefulrequest.com": { - "domain": "hatefulrequest.com", - "owner": { - "name": "Leven Labs, Inc. DBA Admiral (hatefulrequest.com)", - "displayName": "Admiral" - }, - "prevalence": 0.0107, - "fingerprinting": 1, - "cookies": 0.01, - "default": "block" - }, "headydegree.com": { "domain": "headydegree.com", "owner": { @@ -41454,17 +41330,6 @@ "cookies": 0.01, "default": "block" }, - "numberlessring.com": { - "domain": "numberlessring.com", - "owner": { - "name": "Leven Labs, Inc. DBA Admiral (numberlessring.com)", - "displayName": "Admiral" - }, - "prevalence": 0.0107, - "fingerprinting": 1, - "cookies": 0.01, - "default": "block" - }, "numerousnest.com": { "domain": "numerousnest.com", "owner": { @@ -42928,6 +42793,17 @@ "cookies": 0.01, "default": "block" }, + "razzweb.com": { + "domain": "razzweb.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral (razzweb.com)", + "displayName": "Admiral" + }, + "prevalence": 0.0107, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, "reactjspdf.com": { "domain": "reactjspdf.com", "owner": { @@ -43082,17 +42958,6 @@ "cookies": 0.01, "default": "block" }, - "reflectivestatement.com": { - "domain": "reflectivestatement.com", - "owner": { - "name": "Leven Labs, Inc. DBA Admiral (reflectivestatement.com)", - "displayName": "Admiral" - }, - "prevalence": 0.0107, - "fingerprinting": 1, - "cookies": 0.01, - "default": "block" - }, "refundradar.com": { "domain": "refundradar.com", "owner": { @@ -43500,6 +43365,17 @@ "cookies": 0.01, "default": "block" }, + "sableshelf.com": { + "domain": "sableshelf.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral (sableshelf.com)", + "displayName": "Admiral" + }, + "prevalence": 0.0107, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, "sablesmile.com": { "domain": "sablesmile.com", "owner": { @@ -43588,6 +43464,17 @@ "cookies": 0.01, "default": "block" }, + "samuraibots.com": { + "domain": "samuraibots.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral (samuraibots.com)", + "displayName": "Admiral" + }, + "prevalence": 0.0107, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, "sandstrophies.com": { "domain": "sandstrophies.com", "owner": { @@ -43841,17 +43728,6 @@ "cookies": 0.01, "default": "block" }, - "scribbleson.com": { - "domain": "scribbleson.com", - "owner": { - "name": "Leven Labs, Inc. DBA Admiral (scribbleson.com)", - "displayName": "Admiral" - }, - "prevalence": 0.0107, - "fingerprinting": 1, - "cookies": 0.01, - "default": "block" - }, "scrollservice.com": { "domain": "scrollservice.com", "owner": { @@ -43940,17 +43816,6 @@ "cookies": 0.01, "default": "block" }, - "seemlysuggestion.com": { - "domain": "seemlysuggestion.com", - "owner": { - "name": "Leven Labs, Inc. DBA Admiral (seemlysuggestion.com)", - "displayName": "Admiral" - }, - "prevalence": 0.0107, - "fingerprinting": 1, - "cookies": 0.01, - "default": "block" - }, "selfishsea.com": { "domain": "selfishsea.com", "owner": { @@ -44171,6 +44036,17 @@ "cookies": 0.01, "default": "block" }, + "shallowart.com": { + "domain": "shallowart.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral (shallowart.com)", + "displayName": "Admiral" + }, + "prevalence": 0.0107, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, "shallowblade.com": { "domain": "shallowblade.com", "owner": { @@ -44402,17 +44278,6 @@ "cookies": 0.01, "default": "block" }, - "sinkbooks.com": { - "domain": "sinkbooks.com", - "owner": { - "name": "Leven Labs, Inc. DBA Admiral (sinkbooks.com)", - "displayName": "Admiral" - }, - "prevalence": 0.0107, - "fingerprinting": 1, - "cookies": 0.01, - "default": "block" - }, "sixscissors.com": { "domain": "sixscissors.com", "owner": { @@ -45293,17 +45158,6 @@ "cookies": 0.01, "default": "block" }, - "steepscale.com": { - "domain": "steepscale.com", - "owner": { - "name": "Leven Labs, Inc. DBA Admiral (steepscale.com)", - "displayName": "Admiral" - }, - "prevalence": 0.0107, - "fingerprinting": 1, - "cookies": 0.01, - "default": "block" - }, "steepsister.com": { "domain": "steepsister.com", "owner": { @@ -45491,17 +45345,6 @@ "cookies": 0.01, "default": "block" }, - "strangersponge.com": { - "domain": "strangersponge.com", - "owner": { - "name": "Leven Labs, Inc. DBA Admiral (strangersponge.com)", - "displayName": "Admiral" - }, - "prevalence": 0.0107, - "fingerprinting": 1, - "cookies": 0.01, - "default": "block" - }, "strangesink.com": { "domain": "strangesink.com", "owner": { @@ -45678,17 +45521,6 @@ "cookies": 0.01, "default": "block" }, - "sugarfriction.com": { - "domain": "sugarfriction.com", - "owner": { - "name": "Leven Labs, Inc. DBA Admiral (sugarfriction.com)", - "displayName": "Admiral" - }, - "prevalence": 0.0107, - "fingerprinting": 1, - "cookies": 0.01, - "default": "block" - }, "suggestionbridge.com": { "domain": "suggestionbridge.com", "owner": { @@ -45777,17 +45609,6 @@ "cookies": 0.01, "default": "block" }, - "swelteringsleep.com": { - "domain": "swelteringsleep.com", - "owner": { - "name": "Leven Labs, Inc. DBA Admiral (swelteringsleep.com)", - "displayName": "Admiral" - }, - "prevalence": 0.0107, - "fingerprinting": 1, - "cookies": 0.01, - "default": "block" - }, "swimfreely.com": { "domain": "swimfreely.com", "owner": { @@ -45942,17 +45763,6 @@ "cookies": 0.01, "default": "block" }, - "tastelesstrucks.com": { - "domain": "tastelesstrucks.com", - "owner": { - "name": "Leven Labs, Inc. DBA Admiral (tastelesstrucks.com)", - "displayName": "Admiral" - }, - "prevalence": 0.0107, - "fingerprinting": 1, - "cookies": 0.01, - "default": "block" - }, "tastesnake.com": { "domain": "tastesnake.com", "owner": { @@ -47251,17 +47061,6 @@ "cookies": 0.01, "default": "block" }, - "voicelessvein.com": { - "domain": "voicelessvein.com", - "owner": { - "name": "Leven Labs, Inc. DBA Admiral (voicelessvein.com)", - "displayName": "Admiral" - }, - "prevalence": 0.0107, - "fingerprinting": 1, - "cookies": 0.01, - "default": "block" - }, "voidgoo.com": { "domain": "voidgoo.com", "owner": { @@ -47548,6 +47347,17 @@ "cookies": 0.01, "default": "block" }, + "wildwoodavenue.com": { + "domain": "wildwoodavenue.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral (wildwoodavenue.com)", + "displayName": "Admiral" + }, + "prevalence": 0.0107, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, "wirecomic.com": { "domain": "wirecomic.com", "owner": { @@ -55488,6 +55298,13 @@ "prevalence": 0.0136, "displayName": "Rating-Widget" }, + "rebuyengine.com": { + "domains": [ + "rebuyengine.com" + ], + "prevalence": 0, + "displayName": "rebuyengine.com" + }, "Recruitics LLC": { "domains": [ "recruitics.com" @@ -57949,13 +57766,6 @@ "prevalence": 0.0107, "displayName": "Admiral" }, - "Leven Labs, Inc. DBA Admiral (acceptableauthority.com)": { - "domains": [ - "acceptableauthority.com" - ], - "prevalence": 0.0107, - "displayName": "Admiral" - }, "Leven Labs, Inc. DBA Admiral (accountsdoor.com)": { "domains": [ "accountsdoor.com" @@ -58138,13 +57948,6 @@ "prevalence": 0.0107, "displayName": "Admiral" }, - "Leven Labs, Inc. DBA Admiral (alertarithmetic.com)": { - "domains": [ - "alertarithmetic.com" - ], - "prevalence": 0.0107, - "displayName": "Admiral" - }, "Leven Labs, Inc. DBA Admiral (aliasanvil.com)": { "domains": [ "aliasanvil.com" @@ -59755,13 +59558,6 @@ "prevalence": 0.0107, "displayName": "Admiral" }, - "Leven Labs, Inc. DBA Admiral (concernedchange.com)": { - "domains": [ - "concernedchange.com" - ], - "prevalence": 0.0107, - "displayName": "Admiral" - }, "Leven Labs, Inc. DBA Admiral (concernedchickens.com)": { "domains": [ "concernedchickens.com" @@ -61477,13 +61273,6 @@ "prevalence": 0.0107, "displayName": "Admiral" }, - "Leven Labs, Inc. DBA Admiral (fertilefeeling.com)": { - "domains": [ - "fertilefeeling.com" - ], - "prevalence": 0.0107, - "displayName": "Admiral" - }, "Leven Labs, Inc. DBA Admiral (fewjuice.com)": { "domains": [ "fewjuice.com" @@ -62520,13 +62309,6 @@ "prevalence": 0.0107, "displayName": "Admiral" }, - "Leven Labs, Inc. DBA Admiral (hatefulrequest.com)": { - "domains": [ - "hatefulrequest.com" - ], - "prevalence": 0.0107, - "displayName": "Admiral" - }, "Leven Labs, Inc. DBA Admiral (headydegree.com)": { "domains": [ "headydegree.com" @@ -64284,13 +64066,6 @@ "prevalence": 0.0107, "displayName": "Admiral" }, - "Leven Labs, Inc. DBA Admiral (numberlessring.com)": { - "domains": [ - "numberlessring.com" - ], - "prevalence": 0.0107, - "displayName": "Admiral" - }, "Leven Labs, Inc. DBA Admiral (numerousnest.com)": { "domains": [ "numerousnest.com" @@ -65418,6 +65193,13 @@ "prevalence": 0.0107, "displayName": "Admiral" }, + "Leven Labs, Inc. DBA Admiral (razzweb.com)": { + "domains": [ + "razzweb.com" + ], + "prevalence": 0.0107, + "displayName": "Admiral" + }, "Leven Labs, Inc. DBA Admiral (reactjspdf.com)": { "domains": [ "reactjspdf.com" @@ -65537,13 +65319,6 @@ "prevalence": 0.0107, "displayName": "Admiral" }, - "Leven Labs, Inc. DBA Admiral (reflectivestatement.com)": { - "domains": [ - "reflectivestatement.com" - ], - "prevalence": 0.0107, - "displayName": "Admiral" - }, "Leven Labs, Inc. DBA Admiral (refundradar.com)": { "domains": [ "refundradar.com" @@ -65866,6 +65641,13 @@ "prevalence": 0.0107, "displayName": "Admiral" }, + "Leven Labs, Inc. DBA Admiral (sableshelf.com)": { + "domains": [ + "sableshelf.com" + ], + "prevalence": 0.0107, + "displayName": "Admiral" + }, "Leven Labs, Inc. DBA Admiral (sablesmile.com)": { "domains": [ "sablesmile.com" @@ -65936,6 +65718,13 @@ "prevalence": 0.0107, "displayName": "Admiral" }, + "Leven Labs, Inc. DBA Admiral (samuraibots.com)": { + "domains": [ + "samuraibots.com" + ], + "prevalence": 0.0107, + "displayName": "Admiral" + }, "Leven Labs, Inc. DBA Admiral (sandstrophies.com)": { "domains": [ "sandstrophies.com" @@ -66153,13 +65942,6 @@ "prevalence": 0.0107, "displayName": "Admiral" }, - "Leven Labs, Inc. DBA Admiral (scribbleson.com)": { - "domains": [ - "scribbleson.com" - ], - "prevalence": 0.0107, - "displayName": "Admiral" - }, "Leven Labs, Inc. DBA Admiral (scribblestring.com)": { "domains": [ "scribblestring.com" @@ -66230,13 +66012,6 @@ "prevalence": 0.0107, "displayName": "Admiral" }, - "Leven Labs, Inc. DBA Admiral (seemlysuggestion.com)": { - "domains": [ - "seemlysuggestion.com" - ], - "prevalence": 0.0107, - "displayName": "Admiral" - }, "Leven Labs, Inc. DBA Admiral (selectivesummer.com)": { "domains": [ "selectivesummer.com" @@ -66398,6 +66173,13 @@ "prevalence": 0.0107, "displayName": "Admiral" }, + "Leven Labs, Inc. DBA Admiral (shallowart.com)": { + "domains": [ + "shallowart.com" + ], + "prevalence": 0.0107, + "displayName": "Admiral" + }, "Leven Labs, Inc. DBA Admiral (shallowblade.com)": { "domains": [ "shallowblade.com" @@ -66580,13 +66362,6 @@ "prevalence": 0.0107, "displayName": "Admiral" }, - "Leven Labs, Inc. DBA Admiral (sinkbooks.com)": { - "domains": [ - "sinkbooks.com" - ], - "prevalence": 0.0107, - "displayName": "Admiral" - }, "Leven Labs, Inc. DBA Admiral (sixauthority.com)": { "domains": [ "sixauthority.com" @@ -67266,13 +67041,6 @@ "prevalence": 0.0107, "displayName": "Admiral" }, - "Leven Labs, Inc. DBA Admiral (steepscale.com)": { - "domains": [ - "steepscale.com" - ], - "prevalence": 0.0107, - "displayName": "Admiral" - }, "Leven Labs, Inc. DBA Admiral (steepsister.com)": { "domains": [ "steepsister.com" @@ -67427,13 +67195,6 @@ "prevalence": 0.0107, "displayName": "Admiral" }, - "Leven Labs, Inc. DBA Admiral (strangersponge.com)": { - "domains": [ - "strangersponge.com" - ], - "prevalence": 0.0107, - "displayName": "Admiral" - }, "Leven Labs, Inc. DBA Admiral (strangesink.com)": { "domains": [ "strangesink.com" @@ -67581,13 +67342,6 @@ "prevalence": 0.0107, "displayName": "Admiral" }, - "Leven Labs, Inc. DBA Admiral (sugarfriction.com)": { - "domains": [ - "sugarfriction.com" - ], - "prevalence": 0.0107, - "displayName": "Admiral" - }, "Leven Labs, Inc. DBA Admiral (suggestionbridge.com)": { "domains": [ "suggestionbridge.com" @@ -67672,13 +67426,6 @@ "prevalence": 0.0107, "displayName": "Admiral" }, - "Leven Labs, Inc. DBA Admiral (swelteringsleep.com)": { - "domains": [ - "swelteringsleep.com" - ], - "prevalence": 0.0107, - "displayName": "Admiral" - }, "Leven Labs, Inc. DBA Admiral (swimfreely.com)": { "domains": [ "swimfreely.com" @@ -67784,13 +67531,6 @@ "prevalence": 0.0107, "displayName": "Admiral" }, - "Leven Labs, Inc. DBA Admiral (tastelesstrucks.com)": { - "domains": [ - "tastelesstrucks.com" - ], - "prevalence": 0.0107, - "displayName": "Admiral" - }, "Leven Labs, Inc. DBA Admiral (tastesnake.com)": { "domains": [ "tastesnake.com" @@ -68708,13 +68448,6 @@ "prevalence": 0.0107, "displayName": "Admiral" }, - "Leven Labs, Inc. DBA Admiral (voicelessvein.com)": { - "domains": [ - "voicelessvein.com" - ], - "prevalence": 0.0107, - "displayName": "Admiral" - }, "Leven Labs, Inc. DBA Admiral (voidgoo.com)": { "domains": [ "voidgoo.com" @@ -68925,6 +68658,13 @@ "prevalence": 0.0107, "displayName": "Admiral" }, + "Leven Labs, Inc. DBA Admiral (wildwoodavenue.com)": { + "domains": [ + "wildwoodavenue.com" + ], + "prevalence": 0.0107, + "displayName": "Admiral" + }, "Leven Labs, Inc. DBA Admiral (wirecomic.com)": { "domains": [ "wirecomic.com" @@ -69842,7 +69582,6 @@ "abstractedauthority.com": "Leven Labs, Inc. DBA Admiral (abstractedauthority.com)", "absurdapple.com": "Leven Labs, Inc. DBA Admiral (absurdapple.com)", "abundantcoin.com": "Leven Labs, Inc. DBA Admiral (abundantcoin.com)", - "acceptableauthority.com": "Leven Labs, Inc. DBA Admiral (acceptableauthority.com)", "accountsdoor.com": "Leven Labs, Inc. DBA Admiral (accountsdoor.com)", "accurateanimal.com": "Leven Labs, Inc. DBA Admiral (accurateanimal.com)", "accuratecoal.com": "Leven Labs, Inc. DBA Admiral (accuratecoal.com)", @@ -69869,7 +69608,6 @@ "aheadgrow.com": "Leven Labs, Inc. DBA Admiral (aheadgrow.com)", "aheadmachine.com": "Leven Labs, Inc. DBA Admiral (aheadmachine.com)", "ak0gsh40.com": "Leven Labs, Inc. DBA Admiral (ak0gsh40.com)", - "alertarithmetic.com": "Leven Labs, Inc. DBA Admiral (alertarithmetic.com)", "aliasanvil.com": "Leven Labs, Inc. DBA Admiral (aliasanvil.com)", "alikeaddition.com": "Leven Labs, Inc. DBA Admiral (alikeaddition.com)", "aliveachiever.com": "Leven Labs, Inc. DBA Admiral (aliveachiever.com)", @@ -70100,7 +69838,6 @@ "comfygoodness.com": "Leven Labs, Inc. DBA Admiral (comfygoodness.com)", "comparereaction.com": "Leven Labs, Inc. DBA Admiral (comparereaction.com)", "compiledoctor.com": "Leven Labs, Inc. DBA Admiral (compiledoctor.com)", - "concernedchange.com": "Leven Labs, Inc. DBA Admiral (concernedchange.com)", "concernedchickens.com": "Leven Labs, Inc. DBA Admiral (concernedchickens.com)", "condemnedcomb.com": "Leven Labs, Inc. DBA Admiral (condemnedcomb.com)", "conditionchange.com": "Leven Labs, Inc. DBA Admiral (conditionchange.com)", @@ -70346,7 +70083,6 @@ "feeblestamp.com": "Leven Labs, Inc. DBA Admiral (feeblestamp.com)", "feignedfaucet.com": "Leven Labs, Inc. DBA Admiral (feignedfaucet.com)", "fernwaycloud.com": "Leven Labs, Inc. DBA Admiral (fernwaycloud.com)", - "fertilefeeling.com": "Leven Labs, Inc. DBA Admiral (fertilefeeling.com)", "fewjuice.com": "Leven Labs, Inc. DBA Admiral (fewjuice.com)", "fewkittens.com": "Leven Labs, Inc. DBA Admiral (fewkittens.com)", "finalizeforce.com": "Leven Labs, Inc. DBA Admiral (finalizeforce.com)", @@ -70495,7 +70231,6 @@ "harborcub.com": "Leven Labs, Inc. DBA Admiral (harborcub.com)", "harmonicbamboo.com": "Leven Labs, Inc. DBA Admiral (harmonicbamboo.com)", "harmonywing.com": "Leven Labs, Inc. DBA Admiral (harmonywing.com)", - "hatefulrequest.com": "Leven Labs, Inc. DBA Admiral (hatefulrequest.com)", "headydegree.com": "Leven Labs, Inc. DBA Admiral (headydegree.com)", "headyhook.com": "Leven Labs, Inc. DBA Admiral (headyhook.com)", "healflowers.com": "Leven Labs, Inc. DBA Admiral (healflowers.com)", @@ -70747,7 +70482,6 @@ "notifyglass.com": "Leven Labs, Inc. DBA Admiral (notifyglass.com)", "nudgeduck.com": "Leven Labs, Inc. DBA Admiral (nudgeduck.com)", "nullnorth.com": "Leven Labs, Inc. DBA Admiral (nullnorth.com)", - "numberlessring.com": "Leven Labs, Inc. DBA Admiral (numberlessring.com)", "numerousnest.com": "Leven Labs, Inc. DBA Admiral (numerousnest.com)", "nutritiousbean.com": "Leven Labs, Inc. DBA Admiral (nutritiousbean.com)", "nuttyorganization.com": "Leven Labs, Inc. DBA Admiral (nuttyorganization.com)", @@ -70909,6 +70643,7 @@ "rangergustav.com": "Leven Labs, Inc. DBA Admiral (rangergustav.com)", "rarestcandy.com": "Leven Labs, Inc. DBA Admiral (rarestcandy.com)", "raresummer.com": "Leven Labs, Inc. DBA Admiral (raresummer.com)", + "razzweb.com": "Leven Labs, Inc. DBA Admiral (razzweb.com)", "reactjspdf.com": "Leven Labs, Inc. DBA Admiral (reactjspdf.com)", "readingguilt.com": "Leven Labs, Inc. DBA Admiral (readingguilt.com)", "readymoon.com": "Leven Labs, Inc. DBA Admiral (readymoon.com)", @@ -70926,7 +70661,6 @@ "reconditeprison.com": "Leven Labs, Inc. DBA Admiral (reconditeprison.com)", "reconditerake.com": "Leven Labs, Inc. DBA Admiral (reconditerake.com)", "reconditerespect.com": "Leven Labs, Inc. DBA Admiral (reconditerespect.com)", - "reflectivestatement.com": "Leven Labs, Inc. DBA Admiral (reflectivestatement.com)", "refundradar.com": "Leven Labs, Inc. DBA Admiral (refundradar.com)", "regexmail.com": "Leven Labs, Inc. DBA Admiral (regexmail.com)", "regularplants.com": "Leven Labs, Inc. DBA Admiral (regularplants.com)", @@ -70973,6 +70707,7 @@ "ruthlessdegree.com": "Leven Labs, Inc. DBA Admiral (ruthlessdegree.com)", "ruthlessmilk.com": "Leven Labs, Inc. DBA Admiral (ruthlessmilk.com)", "sableloss.com": "Leven Labs, Inc. DBA Admiral (sableloss.com)", + "sableshelf.com": "Leven Labs, Inc. DBA Admiral (sableshelf.com)", "sablesmile.com": "Leven Labs, Inc. DBA Admiral (sablesmile.com)", "sablesong.com": "Leven Labs, Inc. DBA Admiral (sablesong.com)", "sadloaf.com": "Leven Labs, Inc. DBA Admiral (sadloaf.com)", @@ -70983,6 +70718,7 @@ "samesticks.com": "Leven Labs, Inc. DBA Admiral (samesticks.com)", "samestretch.com": "Leven Labs, Inc. DBA Admiral (samestretch.com)", "samplesamba.com": "Leven Labs, Inc. DBA Admiral (samplesamba.com)", + "samuraibots.com": "Leven Labs, Inc. DBA Admiral (samuraibots.com)", "sandstrophies.com": "Leven Labs, Inc. DBA Admiral (sandstrophies.com)", "satisfycork.com": "Leven Labs, Inc. DBA Admiral (satisfycork.com)", "savoryorange.com": "Leven Labs, Inc. DBA Admiral (savoryorange.com)", @@ -71014,7 +70750,6 @@ "screechingfurniture.com": "Leven Labs, Inc. DBA Admiral (screechingfurniture.com)", "screechingstocking.com": "Leven Labs, Inc. DBA Admiral (screechingstocking.com)", "screechingstove.com": "Leven Labs, Inc. DBA Admiral (screechingstove.com)", - "scribbleson.com": "Leven Labs, Inc. DBA Admiral (scribbleson.com)", "scribblestring.com": "Leven Labs, Inc. DBA Admiral (scribblestring.com)", "scrollservice.com": "Leven Labs, Inc. DBA Admiral (scrollservice.com)", "scrubswim.com": "Leven Labs, Inc. DBA Admiral (scrubswim.com)", @@ -71025,7 +70760,6 @@ "secretspiders.com": "Leven Labs, Inc. DBA Admiral (secretspiders.com)", "secretturtle.com": "Leven Labs, Inc. DBA Admiral (secretturtle.com)", "seedscissors.com": "Leven Labs, Inc. DBA Admiral (seedscissors.com)", - "seemlysuggestion.com": "Leven Labs, Inc. DBA Admiral (seemlysuggestion.com)", "selectivesummer.com": "Leven Labs, Inc. DBA Admiral (selectivesummer.com)", "selfishsea.com": "Leven Labs, Inc. DBA Admiral (selfishsea.com)", "selfishsnake.com": "Leven Labs, Inc. DBA Admiral (selfishsnake.com)", @@ -71049,6 +70783,7 @@ "shakyseat.com": "Leven Labs, Inc. DBA Admiral (shakyseat.com)", "shakysurprise.com": "Leven Labs, Inc. DBA Admiral (shakysurprise.com)", "shakytaste.com": "Leven Labs, Inc. DBA Admiral (shakytaste.com)", + "shallowart.com": "Leven Labs, Inc. DBA Admiral (shallowart.com)", "shallowblade.com": "Leven Labs, Inc. DBA Admiral (shallowblade.com)", "shamerain.com": "Leven Labs, Inc. DBA Admiral (shamerain.com)", "shapecomb.com": "Leven Labs, Inc. DBA Admiral (shapecomb.com)", @@ -71075,7 +70810,6 @@ "sincerepelican.com": "Leven Labs, Inc. DBA Admiral (sincerepelican.com)", "sinceresubstance.com": "Leven Labs, Inc. DBA Admiral (sinceresubstance.com)", "singroot.com": "Leven Labs, Inc. DBA Admiral (singroot.com)", - "sinkbooks.com": "Leven Labs, Inc. DBA Admiral (sinkbooks.com)", "sixauthority.com": "Leven Labs, Inc. DBA Admiral (sixauthority.com)", "sixscissors.com": "Leven Labs, Inc. DBA Admiral (sixscissors.com)", "sizzlingsmoke.com": "Leven Labs, Inc. DBA Admiral (sizzlingsmoke.com)", @@ -71173,7 +70907,6 @@ "steadfastsystem.com": "Leven Labs, Inc. DBA Admiral (steadfastsystem.com)", "steadycopper.com": "Leven Labs, Inc. DBA Admiral (steadycopper.com)", "stealsteel.com": "Leven Labs, Inc. DBA Admiral (stealsteel.com)", - "steepscale.com": "Leven Labs, Inc. DBA Admiral (steepscale.com)", "steepsister.com": "Leven Labs, Inc. DBA Admiral (steepsister.com)", "steepsquirrel.com": "Leven Labs, Inc. DBA Admiral (steepsquirrel.com)", "stepcattle.com": "Leven Labs, Inc. DBA Admiral (stepcattle.com)", @@ -71196,7 +70929,6 @@ "stormyachiever.com": "Leven Labs, Inc. DBA Admiral (stormyachiever.com)", "straightnest.com": "Leven Labs, Inc. DBA Admiral (straightnest.com)", "strangeclocks.com": "Leven Labs, Inc. DBA Admiral (strangeclocks.com)", - "strangersponge.com": "Leven Labs, Inc. DBA Admiral (strangersponge.com)", "strangesink.com": "Leven Labs, Inc. DBA Admiral (strangesink.com)", "streetsort.com": "Leven Labs, Inc. DBA Admiral (streetsort.com)", "stretchsister.com": "Leven Labs, Inc. DBA Admiral (stretchsister.com)", @@ -71218,7 +70950,6 @@ "succeedscene.com": "Leven Labs, Inc. DBA Admiral (succeedscene.com)", "successfulscent.com": "Leven Labs, Inc. DBA Admiral (successfulscent.com)", "suddensoda.com": "Leven Labs, Inc. DBA Admiral (suddensoda.com)", - "sugarfriction.com": "Leven Labs, Inc. DBA Admiral (sugarfriction.com)", "suggestionbridge.com": "Leven Labs, Inc. DBA Admiral (suggestionbridge.com)", "sulkycook.com": "Leven Labs, Inc. DBA Admiral (sulkycook.com)", "summerobject.com": "Leven Labs, Inc. DBA Admiral (summerobject.com)", @@ -71231,7 +70962,6 @@ "suspectmark.com": "Leven Labs, Inc. DBA Admiral (suspectmark.com)", "swankysquare.com": "Leven Labs, Inc. DBA Admiral (swankysquare.com)", "swellstocking.com": "Leven Labs, Inc. DBA Admiral (swellstocking.com)", - "swelteringsleep.com": "Leven Labs, Inc. DBA Admiral (swelteringsleep.com)", "swimfreely.com": "Leven Labs, Inc. DBA Admiral (swimfreely.com)", "swingslip.com": "Leven Labs, Inc. DBA Admiral (swingslip.com)", "swordgoose.com": "Leven Labs, Inc. DBA Admiral (swordgoose.com)", @@ -71247,7 +70977,6 @@ "tangyamount.com": "Leven Labs, Inc. DBA Admiral (tangyamount.com)", "tangycover.com": "Leven Labs, Inc. DBA Admiral (tangycover.com)", "tastelesstrees.com": "Leven Labs, Inc. DBA Admiral (tastelesstrees.com)", - "tastelesstrucks.com": "Leven Labs, Inc. DBA Admiral (tastelesstrucks.com)", "tastesnake.com": "Leven Labs, Inc. DBA Admiral (tastesnake.com)", "tawdryson.com": "Leven Labs, Inc. DBA Admiral (tawdryson.com)", "tdzvm.pw": "Leven Labs, Inc. DBA Admiral (tdzvm.pw)", @@ -71379,7 +71108,6 @@ "vividfrost.com": "Leven Labs, Inc. DBA Admiral (vividfrost.com)", "vividmeadow.com": "Leven Labs, Inc. DBA Admiral (vividmeadow.com)", "vividplume.com": "Leven Labs, Inc. DBA Admiral (vividplume.com)", - "voicelessvein.com": "Leven Labs, Inc. DBA Admiral (voicelessvein.com)", "voidgoo.com": "Leven Labs, Inc. DBA Admiral (voidgoo.com)", "volatileprofit.com": "Leven Labs, Inc. DBA Admiral (volatileprofit.com)", "volatilevessel.com": "Leven Labs, Inc. DBA Admiral (volatilevessel.com)", @@ -71410,6 +71138,7 @@ "whisperingsummit.com": "Leven Labs, Inc. DBA Admiral (whisperingsummit.com)", "whispermeeting.com": "Leven Labs, Inc. DBA Admiral (whispermeeting.com)", "wildcommittee.com": "Leven Labs, Inc. DBA Admiral (wildcommittee.com)", + "wildwoodavenue.com": "Leven Labs, Inc. DBA Admiral (wildwoodavenue.com)", "wirecomic.com": "Leven Labs, Inc. DBA Admiral (wirecomic.com)", "wiredforcoffee.com": "Leven Labs, Inc. DBA Admiral (wiredforcoffee.com)", "wirypaste.com": "Leven Labs, Inc. DBA Admiral (wirypaste.com)", @@ -74914,6 +74643,7 @@ "secretmag.ru": "Rambler Internet Holding, LLC", "top100.ru": "Rambler Internet Holding, LLC", "rating-widget.com": "Rating-Widget, Inc.", + "rebuyengine.com": "rebuyengine.com", "recruitics.com": "Recruitics LLC", "dubsmash.com": "Reddit Inc.", "redd.it": "Reddit Inc.", diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 86e91dc461..fce5b52b68 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -175,7 +175,6 @@ 317F5F982C94A9EB0081666F /* MarketplaceAdPostbackStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 317F5F972C94A9EB0081666F /* MarketplaceAdPostbackStorage.swift */; }; 31860A5B2C57ED2D005561F5 /* DuckPlayerStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31860A5A2C57ED2D005561F5 /* DuckPlayerStorage.swift */; }; 31951E8E2823003200CAF535 /* AutofillLoginDetailsHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31951E8D2823003200CAF535 /* AutofillLoginDetailsHeaderView.swift */; }; - 319A371028299A850079FBCE /* PasswordHider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 319A370F28299A850079FBCE /* PasswordHider.swift */; }; 319A37152829A55F0079FBCE /* AutofillListItemTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 319A37142829A55F0079FBCE /* AutofillListItemTableViewCell.swift */; }; 319A37172829C8AD0079FBCE /* UITableViewExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 319A37162829C8AD0079FBCE /* UITableViewExtension.swift */; }; 31A42564285A09E800049386 /* FaviconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31A42563285A09E800049386 /* FaviconView.swift */; }; @@ -919,6 +918,15 @@ C1BF0BA529B63D7200482B73 /* AutofillLoginPromptHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1BF0BA429B63D7200482B73 /* AutofillLoginPromptHelper.swift */; }; C1BF0BA929B63E2200482B73 /* AutofillLoginPromptViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1BF0BA729B63E1A00482B73 /* AutofillLoginPromptViewModelTests.swift */; }; C1BF26152C74D10F00F6405E /* SyncPromoManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1BF26142C74D10F00F6405E /* SyncPromoManager.swift */; }; + C1C1FF452D085A280017ACCE /* CredentialProviderListDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1C1FF412D085A280017ACCE /* CredentialProviderListDetailsView.swift */; }; + C1C1FF462D085A280017ACCE /* CredentialProviderListDetailsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1C1FF422D085A280017ACCE /* CredentialProviderListDetailsViewController.swift */; }; + C1C1FF472D085A280017ACCE /* CredentialProviderListDetailsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1C1FF432D085A280017ACCE /* CredentialProviderListDetailsViewModel.swift */; }; + C1C1FF4A2D085A4C0017ACCE /* AutofillInterfaceEmailTruncator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1C1FF482D085A4C0017ACCE /* AutofillInterfaceEmailTruncator.swift */; }; + C1C1FF4B2D085A4C0017ACCE /* PasswordHider.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1C1FF492D085A4C0017ACCE /* PasswordHider.swift */; }; + C1C1FF502D085AD70017ACCE /* ActionMessageView.xib in Resources */ = {isa = PBXBuildFile; fileRef = C1C1FF4D2D085AD70017ACCE /* ActionMessageView.xib */; }; + C1C1FF512D085AD70017ACCE /* FaviconHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1C1FF4E2D085AD70017ACCE /* FaviconHelper.swift */; }; + C1C1FF522D085AD70017ACCE /* ActionMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1C1FF4C2D085AD70017ACCE /* ActionMessageView.swift */; }; + C1C1FF532D085AD70017ACCE /* NibLoading.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1C1FF4F2D085AD70017ACCE /* NibLoading.swift */; }; C1CAAA6A2CF8BABF00C37EE6 /* CredentialProviderActivatedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1CAAA692CF8BABF00C37EE6 /* CredentialProviderActivatedView.swift */; }; C1CAAA712CF8BC0B00C37EE6 /* UIViewControllerExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1CAAA702CF8BC0B00C37EE6 /* UIViewControllerExtension.swift */; }; C1CAAA732CF8BD1C00C37EE6 /* CredentialProviderActivatedViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1CAAA722CF8BD1C00C37EE6 /* CredentialProviderActivatedViewModel.swift */; }; @@ -945,6 +953,8 @@ C1D21E2D293A5965006E5A05 /* AutofillLoginSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1D21E2C293A5965006E5A05 /* AutofillLoginSession.swift */; }; C1D21E2F293A599C006E5A05 /* AutofillLoginSessionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1D21E2E293A599C006E5A05 /* AutofillLoginSessionTests.swift */; }; C1E42C7B2C5CD8AE00509204 /* AutofillCredentialsDebugViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1E42C7A2C5CD8AD00509204 /* AutofillCredentialsDebugViewController.swift */; }; + C1E4E9A62D0861AD00AA39AF /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = C1E4E9A42D0861AD00AA39AF /* InfoPlist.strings */; }; + C1E4E9A92D0861AD00AA39AF /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = C1E4E9A72D0861AD00AA39AF /* Localizable.strings */; }; C1EA86602C74CB6C00E8604D /* SyncPromoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1EA865F2C74CB6C00E8604D /* SyncPromoView.swift */; }; C1EA86622C74CB8B00E8604D /* SyncPromoViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1EA86612C74CB8B00E8604D /* SyncPromoViewModel.swift */; }; C1EF5B232CC0457B002980E6 /* AuthenticationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C1EF5B222CC0457B002980E6 /* AuthenticationServices.framework */; }; @@ -1205,7 +1215,6 @@ F486D3382506A225002D07D7 /* OHHTTPStubsSwift in Frameworks */ = {isa = PBXBuildFile; productRef = F486D3372506A225002D07D7 /* OHHTTPStubsSwift */; }; F4B0B78C252CAFF700830156 /* OnboardingWidgetsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4B0B78B252CAFF700830156 /* OnboardingWidgetsViewController.swift */; }; F4B0B796252CB35700830156 /* OnboardingWidgetsDetailsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4B0B795252CB35700830156 /* OnboardingWidgetsDetailsViewController.swift */; }; - F4C9FBF528340DDA002281CC /* AutofillInterfaceEmailTruncator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4C9FBF428340DDA002281CC /* AutofillInterfaceEmailTruncator.swift */; }; F4CE6D1B257EA33C00D0A6AA /* FireButtonAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4CE6D1A257EA33C00D0A6AA /* FireButtonAnimator.swift */; }; F4D7221026F29A70007D6193 /* BookmarkDetailsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4D7220F26F29A70007D6193 /* BookmarkDetailsCell.swift */; }; F4D7F634298C00C3006C3AE9 /* FindInPageIOSJSSupport in Frameworks */ = {isa = PBXBuildFile; productRef = F4D7F633298C00C3006C3AE9 /* FindInPageIOSJSSupport */; }; @@ -1542,7 +1551,6 @@ 317F5F972C94A9EB0081666F /* MarketplaceAdPostbackStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarketplaceAdPostbackStorage.swift; sourceTree = ""; }; 31860A5A2C57ED2D005561F5 /* DuckPlayerStorage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DuckPlayerStorage.swift; sourceTree = ""; }; 31951E8D2823003200CAF535 /* AutofillLoginDetailsHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutofillLoginDetailsHeaderView.swift; sourceTree = ""; }; - 319A370F28299A850079FBCE /* PasswordHider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasswordHider.swift; sourceTree = ""; }; 319A37142829A55F0079FBCE /* AutofillListItemTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutofillListItemTableViewCell.swift; sourceTree = ""; }; 319A37162829C8AD0079FBCE /* UITableViewExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITableViewExtension.swift; sourceTree = ""; }; 31A42563285A09E800049386 /* FaviconView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FaviconView.swift; sourceTree = ""; }; @@ -2707,14 +2715,28 @@ BDFF03242BA3D92E00F324C9 /* NetworkProtectionFeatureVisibilityTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProtectionFeatureVisibilityTests.swift; sourceTree = ""; }; C10CB5F22A1A5BDF0048E503 /* AutofillViews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutofillViews.swift; sourceTree = ""; }; C111B26827F579EF006558B1 /* BookmarkOrFolderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkOrFolderTests.swift; sourceTree = ""; }; + C1193F602D08642900CB3239 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/InfoPlist.strings; sourceTree = ""; }; + C1193F612D08642900CB3239 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = ""; }; + C11C4D302D08648100288E85 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/InfoPlist.strings; sourceTree = ""; }; + C11C4D312D08648100288E85 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Localizable.strings; sourceTree = ""; }; C12726ED2A5FF88C00215B02 /* EmailSignupPromptView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmailSignupPromptView.swift; sourceTree = ""; }; C12726EF2A5FF89900215B02 /* EmailSignupPromptViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmailSignupPromptViewModel.swift; sourceTree = ""; }; C12726F12A5FF8CB00215B02 /* EmailSignupPromptViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmailSignupPromptViewController.swift; sourceTree = ""; }; + C12854D82D08636E00C8353F /* lv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = lv; path = lv.lproj/InfoPlist.strings; sourceTree = ""; }; + C12854D92D08636E00C8353F /* lv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = lv; path = lv.lproj/Localizable.strings; sourceTree = ""; }; + C129DF092D0862D7007AB046 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/InfoPlist.strings; sourceTree = ""; }; + C129DF0A2D0862D7007AB046 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = ""; }; + C132F5A32D0862B8000C81D0 /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/InfoPlist.strings; sourceTree = ""; }; + C132F5A42D0862B8000C81D0 /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/Localizable.strings; sourceTree = ""; }; C13B32D12A0E750700A59236 /* AutofillSettingStatus.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AutofillSettingStatus.swift; sourceTree = ""; }; C13C076B2D00A6B7006386CF /* VaultCredentialManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VaultCredentialManager.swift; sourceTree = ""; }; C13F3F672B7F88100083BE40 /* AuthConfirmationPromptView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthConfirmationPromptView.swift; sourceTree = ""; }; C13F3F692B7F883A0083BE40 /* AuthConfirmationPromptViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthConfirmationPromptViewController.swift; sourceTree = ""; }; C13F3F6B2B7F88470083BE40 /* AuthConfirmationPromptViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthConfirmationPromptViewModel.swift; sourceTree = ""; }; + C1406D862D0862F30082CB50 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/InfoPlist.strings; sourceTree = ""; }; + C1406D872D0862F30082CB50 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/Localizable.strings; sourceTree = ""; }; + C1453E322D0863C80024449B /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/InfoPlist.strings; sourceTree = ""; }; + C1453E332D0863C80024449B /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Localizable.strings; sourceTree = ""; }; C14882D727F2011C00D59F0C /* BookmarksExporter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BookmarksExporter.swift; sourceTree = ""; }; C14882D927F2011C00D59F0C /* BookmarksImporter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BookmarksImporter.swift; sourceTree = ""; }; C14882E127F20D9A00D59F0C /* BookmarksExporterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BookmarksExporterTests.swift; sourceTree = ""; }; @@ -2722,23 +2744,37 @@ C14882E527F20DAA00D59F0C /* HtmlTestDataLoader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HtmlTestDataLoader.swift; sourceTree = ""; }; C14882E627F20DAB00D59F0C /* TestDataLoader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestDataLoader.swift; sourceTree = ""; }; C14882E927F20DD000D59F0C /* MockBookmarksCoreDataStorage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockBookmarksCoreDataStorage.swift; sourceTree = ""; }; + C14D37D62D08649E00FCFC59 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/InfoPlist.strings; sourceTree = ""; }; + C14D37D72D08649E00FCFC59 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Localizable.strings; sourceTree = ""; }; C14D43002B45D6CD00ACA4DC /* AutofillDebugViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AutofillDebugViewController.swift; sourceTree = ""; }; C14E2F7629DE14EA002AC515 /* AutofillInterfaceUsernameTruncatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutofillInterfaceUsernameTruncatorTests.swift; sourceTree = ""; }; + C1588FC42D08644800C9BE70 /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/InfoPlist.strings; sourceTree = ""; }; + C1588FC52D08644800C9BE70 /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/Localizable.strings; sourceTree = ""; }; C158AC7A297AB5DC0008723A /* MockSecureVault.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockSecureVault.swift; sourceTree = ""; }; C159DF062A430B60007834BB /* EmailSignupViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmailSignupViewController.swift; sourceTree = ""; }; C160544029D6044D00B715A1 /* AutofillInterfaceUsernameTruncator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutofillInterfaceUsernameTruncator.swift; sourceTree = ""; }; + C163677A2D08638C001D1094 /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/InfoPlist.strings; sourceTree = ""; }; + C163677B2D08638C001D1094 /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/Localizable.strings; sourceTree = ""; }; C1641EAE2BC2F5140012607A /* ImportPasswordsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImportPasswordsViewController.swift; sourceTree = ""; }; C1641EB02BC2F52B0012607A /* ImportPasswordsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImportPasswordsView.swift; sourceTree = ""; }; C1641EB22BC2F53C0012607A /* ImportPasswordsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImportPasswordsViewModel.swift; sourceTree = ""; }; + C164F9472D0861D600BAE88E /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/InfoPlist.strings; sourceTree = ""; }; + C164F9482D0861D600BAE88E /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = ""; }; + C174E08E2D08625300ACE1AF /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/InfoPlist.strings; sourceTree = ""; }; + C174E08F2D08625300ACE1AF /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/Localizable.strings; sourceTree = ""; }; C177D9F52CFDDFEB0039CBF7 /* UIAlertControllerExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIAlertControllerExtension.swift; sourceTree = ""; }; C17B59562A03AAD30055F2D1 /* PasswordGenerationPromptViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordGenerationPromptViewModel.swift; sourceTree = ""; }; C17B59572A03AAD30055F2D1 /* PasswordGenerationPromptViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordGenerationPromptViewController.swift; sourceTree = ""; }; C17B59582A03AAD30055F2D1 /* PasswordGenerationPromptView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordGenerationPromptView.swift; sourceTree = ""; }; + C180CAFA2D0863E500ADB0FE /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/InfoPlist.strings; sourceTree = ""; }; + C180CAFB2D0863E500ADB0FE /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/Localizable.strings; sourceTree = ""; }; C1836CE02C359EC90016D057 /* AutofillBreakageReportCellContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutofillBreakageReportCellContentView.swift; sourceTree = ""; }; C1836CE42C35A0EA0016D057 /* AutofillBreakageReportTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutofillBreakageReportTableViewCell.swift; sourceTree = ""; }; C185ED602BD4329700BAE9DC /* ImportPasswordsStatusHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImportPasswordsStatusHandler.swift; sourceTree = ""; }; C185ED632BD438AF00BAE9DC /* ImportPasswordsStatusHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImportPasswordsStatusHandlerTests.swift; sourceTree = ""; }; C185ED652BD43A5500BAE9DC /* MockDDGSyncing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockDDGSyncing.swift; sourceTree = ""; }; + C18D7C412D08620D00FB3F87 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/InfoPlist.strings; sourceTree = ""; }; + C18D7C422D08620D00FB3F87 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/Localizable.strings; sourceTree = ""; }; C18ED4392AB6F77600BF3805 /* AutofillSettingsEnableFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutofillSettingsEnableFooterView.swift; sourceTree = ""; }; C18ED43B2AB8364400BF3805 /* FileTextPreviewDebugViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileTextPreviewDebugViewController.swift; sourceTree = ""; }; C1935A0D2C88D11D001AD72D /* AutofillSurveyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutofillSurveyView.swift; sourceTree = ""; }; @@ -2748,15 +2784,30 @@ C1935A232C89CC6D001AD72D /* AutofillHeaderViewFactoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutofillHeaderViewFactoryTests.swift; sourceTree = ""; }; C1963862283794A000298D4D /* BookmarksCachingSearch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BookmarksCachingSearch.swift; sourceTree = ""; }; C19D90D02CFE3A7F00D17DF3 /* AutofillLoginListSectionType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutofillLoginListSectionType.swift; sourceTree = ""; }; + C1A001092D08635100372C87 /* lt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = lt; path = lt.lproj/InfoPlist.strings; sourceTree = ""; }; + C1A0010A2D08635100372C87 /* lt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = lt; path = lt.lproj/Localizable.strings; sourceTree = ""; }; C1B0F6412AB08BE9001EAF05 /* MockPrivacyConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockPrivacyConfiguration.swift; sourceTree = ""; }; + C1B783DB2D0863110071C53B /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/InfoPlist.strings; sourceTree = ""; }; + C1B783DC2D0863110071C53B /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/Localizable.strings; sourceTree = ""; }; C1B7B51B28941E980098FD6A /* HomeMessageViewModelBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HomeMessageViewModelBuilder.swift; sourceTree = ""; }; C1B7B52128941F2A0098FD6A /* RemoteMessagingClient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RemoteMessagingClient.swift; sourceTree = ""; }; C1B7B52C2894469D0098FD6A /* DefaultVariantManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultVariantManager.swift; sourceTree = ""; }; C1B7B53328944EFA0098FD6A /* CoreDataTestUtilities.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataTestUtilities.swift; sourceTree = ""; }; + C1B7BF522D08640B0024FF56 /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/InfoPlist.strings; sourceTree = ""; }; + C1B7BF532D08640B0024FF56 /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/Localizable.strings; 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 = ""; }; C1BF26142C74D10F00F6405E /* SyncPromoManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncPromoManager.swift; sourceTree = ""; }; + C1C1FF412D085A280017ACCE /* CredentialProviderListDetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CredentialProviderListDetailsView.swift; sourceTree = ""; }; + C1C1FF422D085A280017ACCE /* CredentialProviderListDetailsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CredentialProviderListDetailsViewController.swift; sourceTree = ""; }; + C1C1FF432D085A280017ACCE /* CredentialProviderListDetailsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CredentialProviderListDetailsViewModel.swift; sourceTree = ""; }; + C1C1FF482D085A4C0017ACCE /* AutofillInterfaceEmailTruncator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutofillInterfaceEmailTruncator.swift; sourceTree = ""; }; + C1C1FF492D085A4C0017ACCE /* PasswordHider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasswordHider.swift; sourceTree = ""; }; + C1C1FF4C2D085AD70017ACCE /* ActionMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionMessageView.swift; sourceTree = ""; }; + C1C1FF4D2D085AD70017ACCE /* ActionMessageView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ActionMessageView.xib; sourceTree = ""; }; + C1C1FF4E2D085AD70017ACCE /* FaviconHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FaviconHelper.swift; sourceTree = ""; }; + C1C1FF4F2D085AD70017ACCE /* NibLoading.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NibLoading.swift; sourceTree = ""; }; C1CAAA672CF8B74200C37EE6 /* AutofillCredentialProviderAlpha.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = AutofillCredentialProviderAlpha.entitlements; sourceTree = ""; }; C1CAAA692CF8BABF00C37EE6 /* CredentialProviderActivatedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CredentialProviderActivatedView.swift; sourceTree = ""; }; C1CAAA702CF8BC0B00C37EE6 /* UIViewControllerExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIViewControllerExtension.swift; sourceTree = ""; }; @@ -2776,11 +2827,19 @@ C1CAAAA72CFCBE4800C37EE6 /* EmptySearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptySearchView.swift; sourceTree = ""; }; C1CAAAA92CFCC13E00C37EE6 /* SecureVaultReporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureVaultReporter.swift; sourceTree = ""; }; C1CAAAAB2CFCC91D00C37EE6 /* EmptyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyView.swift; sourceTree = ""; }; + C1CB0AA52D08629800335287 /* et */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = et; path = et.lproj/InfoPlist.strings; sourceTree = ""; }; + C1CB0AA62D08629800335287 /* et */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = et; path = et.lproj/Localizable.strings; 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 = ""; }; + C1DCF3502D0862330055F8B0 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/InfoPlist.strings; sourceTree = ""; }; + C1DCF3512D0862330055F8B0 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; C1E42C7A2C5CD8AD00509204 /* AutofillCredentialsDebugViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AutofillCredentialsDebugViewController.swift; sourceTree = ""; }; + C1E490582D08646400F86C5A /* sl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sl; path = sl.lproj/InfoPlist.strings; sourceTree = ""; }; + C1E490592D08646400F86C5A /* sl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sl; path = sl.lproj/Localizable.strings; sourceTree = ""; }; + C1E4E9A52D0861AD00AA39AF /* bg */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bg; path = bg.lproj/InfoPlist.strings; sourceTree = ""; }; + C1E4E9A82D0861AD00AA39AF /* bg */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bg; path = bg.lproj/Localizable.strings; sourceTree = ""; }; C1EA865F2C74CB6C00E8604D /* SyncPromoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncPromoView.swift; sourceTree = ""; }; C1EA86612C74CB8B00E8604D /* SyncPromoViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncPromoViewModel.swift; sourceTree = ""; }; C1EF5B212CC0457B002980E6 /* AutofillCredentialProvider.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = AutofillCredentialProvider.appex; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -2791,6 +2850,12 @@ C1F341C42A6924000032057B /* EmailAddressPromptView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmailAddressPromptView.swift; sourceTree = ""; }; C1F341C62A6924100032057B /* EmailAddressPromptViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmailAddressPromptViewModel.swift; sourceTree = ""; }; C1F341C82A6926920032057B /* EmailAddressPromptViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmailAddressPromptViewController.swift; sourceTree = ""; }; + C1F883372D08627900DFF79A /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = ""; }; + C1F883382D08627900DFF79A /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; + C1FE93E52D0863AA009F8F5E /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/InfoPlist.strings; sourceTree = ""; }; + C1FE93E62D0863AA009F8F5E /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = ""; }; + C1FEDCEA2D08633100BFBF3F /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/InfoPlist.strings; sourceTree = ""; }; + C1FEDCEB2D08633100BFBF3F /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Localizable.strings; sourceTree = ""; }; C1FFBD452C761BE20073622B /* SyncPromoManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncPromoManagerTests.swift; sourceTree = ""; }; C1FFBD472C7749A90073622B /* SyncSettingsViewController+PlatformLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SyncSettingsViewController+PlatformLinks.swift"; sourceTree = ""; }; CB1143DD2AF6D4B600C1CCD3 /* bg */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bg; path = bg.lproj/InfoPlist.strings; sourceTree = ""; }; @@ -3076,7 +3141,6 @@ F47E53DA250A9A1C0037C686 /* Onboarding.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Onboarding.xcassets; sourceTree = ""; }; F4B0B78B252CAFF700830156 /* OnboardingWidgetsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnboardingWidgetsViewController.swift; sourceTree = ""; }; F4B0B795252CB35700830156 /* OnboardingWidgetsDetailsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingWidgetsDetailsViewController.swift; sourceTree = ""; }; - F4C9FBF428340DDA002281CC /* AutofillInterfaceEmailTruncator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutofillInterfaceEmailTruncator.swift; sourceTree = ""; }; F4CE6D1A257EA33C00D0A6AA /* FireButtonAnimator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FireButtonAnimator.swift; sourceTree = ""; }; F4D7220F26F29A70007D6193 /* BookmarkDetailsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkDetailsCell.swift; sourceTree = ""; }; F4D9C4F925117A0F00814B71 /* HomeMessageStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeMessageStorage.swift; sourceTree = ""; }; @@ -3721,7 +3785,6 @@ 31951E9328230D8900CAF535 /* Shared */ = { isa = PBXGroup; children = ( - F4C9FBF428340DDA002281CC /* AutofillInterfaceEmailTruncator.swift */, 31A42563285A09E800049386 /* FaviconView.swift */, 31A42565285A0A6300049386 /* FaviconViewModel.swift */, C160544029D6044D00B715A1 /* AutofillInterfaceUsernameTruncator.swift */, @@ -5329,6 +5392,16 @@ name = AutofillLoginUI; sourceTree = ""; }; + C1C1FF442D085A280017ACCE /* CredentialProviderListDetails */ = { + isa = PBXGroup; + children = ( + C1C1FF412D085A280017ACCE /* CredentialProviderListDetailsView.swift */, + C1C1FF422D085A280017ACCE /* CredentialProviderListDetailsViewController.swift */, + C1C1FF432D085A280017ACCE /* CredentialProviderListDetailsViewModel.swift */, + ); + path = CredentialProviderListDetails; + sourceTree = ""; + }; C1CAA3D52A630ECB00807703 /* EmailSignup */ = { isa = PBXGroup; children = ( @@ -5355,6 +5428,7 @@ C1EF5B252CC0457B002980E6 /* CredentialProviderViewController.swift */, C1CAAA682CF8B8C400C37EE6 /* CredentialProviderActivation */, C1CAAA862CF9FFBE00C37EE6 /* CredentialProviderList */, + C1C1FF442D085A280017ACCE /* CredentialProviderListDetails */, C1CAAA6E2CF8BBC900C37EE6 /* Extensions */, C1CAAA742CF8BDC400C37EE6 /* Resources */, C1CAAAA42CFCBD6B00C37EE6 /* Shared */, @@ -5398,6 +5472,8 @@ C1CAAA962CFCAB8000C37EE6 /* Autofill */ = { isa = PBXGroup; children = ( + C1C1FF482D085A4C0017ACCE /* AutofillInterfaceEmailTruncator.swift */, + C1C1FF492D085A4C0017ACCE /* PasswordHider.swift */, C19D90D02CFE3A7F00D17DF3 /* AutofillLoginListSectionType.swift */, C1CAAA992CFCAD3E00C37EE6 /* AutofillLoginItem.swift */, C1CAAA9B2CFCB39800C37EE6 /* AutofillLoginListSorting.swift */, @@ -5416,7 +5492,11 @@ C1CAAAA42CFCBD6B00C37EE6 /* Shared */ = { isa = PBXGroup; children = ( + C1C1FF4C2D085AD70017ACCE /* ActionMessageView.swift */, + C1C1FF4D2D085AD70017ACCE /* ActionMessageView.xib */, + C1C1FF4E2D085AD70017ACCE /* FaviconHelper.swift */, C1CAAAA52CFCBD7900C37EE6 /* LockScreenView.swift */, + C1C1FF4F2D085AD70017ACCE /* NibLoading.swift */, C1CAAAA92CFCC13E00C37EE6 /* SecureVaultReporter.swift */, C13C076B2D00A6B7006386CF /* VaultCredentialManager.swift */, ); @@ -5439,6 +5519,8 @@ C1CAAA6D2CF8BBBC00C37EE6 /* CredentialProvider */, C1CAAA672CF8B74200C37EE6 /* AutofillCredentialProviderAlpha.entitlements */, C1EF5B2A2CC0457B002980E6 /* Info.plist */, + C1E4E9A72D0861AD00AA39AF /* Localizable.strings */, + C1E4E9A42D0861AD00AA39AF /* InfoPlist.strings */, C1EF5B2B2CC0457B002980E6 /* AutofillCredentialProvider.entitlements */, ); path = AutofillCredentialProvider; @@ -6633,7 +6715,6 @@ C1D21E2C293A5965006E5A05 /* AutofillLoginSession.swift */, C1CDA3152AFB9C7F006D1476 /* AutofillNeverPromptWebsitesManager.swift */, C13B32D12A0E750700A59236 /* AutofillSettingStatus.swift */, - 319A370F28299A850079FBCE /* PasswordHider.swift */, 31C70B5428045E3500FB6AD1 /* SecureVaultReporter.swift */, C1AFFC4B2B8773060060448E /* AuthConfirmation */, F407605328131910006B1E0B /* AutofillLoginUI */, @@ -7396,6 +7477,9 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + C1C1FF502D085AD70017ACCE /* ActionMessageView.xib in Resources */, + C1E4E9A92D0861AD00AA39AF /* Localizable.strings in Resources */, + C1E4E9A62D0861AD00AA39AF /* InfoPlist.strings in Resources */, C1CAAA7A2CF8BE0200C37EE6 /* Assets.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -7616,7 +7700,6 @@ 6F03CAFE2C32DD08004179A8 /* HomePageMessagesConfiguration.swift in Sources */, 851952682CE2522700578553 /* AutocompleteSuggestionsDataSource.swift in Sources */, EE9D68D12AE00CF300B55EF4 /* NetworkProtectionVPNSettingsView.swift in Sources */, - 319A371028299A850079FBCE /* PasswordHider.swift in Sources */, 982C87C42255559A00919035 /* UITableViewCellExtension.swift in Sources */, B623C1C42862CD670043013E /* WKDownloadSession.swift in Sources */, 6FD1BAE42B87A107000C475C /* AdAttributionPixelReporter.swift in Sources */, @@ -7865,7 +7948,6 @@ 6F5CC0812C2AFFE400AFC840 /* ToggleExpandButtonStyle.swift in Sources */, D68A21462B7EC16200BB372E /* SubscriptionExternalLinkViewModel.swift in Sources */, 31DE43C22C2C480D00F8C51F /* DuckPlayerFeaturePresentationView.swift in Sources */, - F4C9FBF528340DDA002281CC /* AutofillInterfaceEmailTruncator.swift in Sources */, 1E016AB42949FEB500F21625 /* OmniBarNotificationViewModel.swift in Sources */, 6AC6DAB328804F97002723C0 /* BarsAnimator.swift in Sources */, CB4FA44E2C78AACE00A16F5A /* SpecialErrorPageUserScript.swift in Sources */, @@ -8536,8 +8618,14 @@ C1CAAA9E2CFCB78700C37EE6 /* UIColorExtension.swift in Sources */, C1CAAA8A2CF9FFF300C37EE6 /* CredentialProviderListViewModel.swift in Sources */, C1CAAAA02CFCB7C200C37EE6 /* UImageExtension.swift in Sources */, + C1C1FF512D085AD70017ACCE /* FaviconHelper.swift in Sources */, + C1C1FF522D085AD70017ACCE /* ActionMessageView.swift in Sources */, + C1C1FF532D085AD70017ACCE /* NibLoading.swift in Sources */, C177D9F62CFDDFEB0039CBF7 /* UIAlertControllerExtension.swift in Sources */, C1CAAA882CF9FFE100C37EE6 /* CredentialProviderListViewController.swift in Sources */, + C1C1FF452D085A280017ACCE /* CredentialProviderListDetailsView.swift in Sources */, + C1C1FF462D085A280017ACCE /* CredentialProviderListDetailsViewController.swift in Sources */, + C1C1FF472D085A280017ACCE /* CredentialProviderListDetailsViewModel.swift in Sources */, C1CAAAAA2CFCC13E00C37EE6 /* SecureVaultReporter.swift in Sources */, C1CAAAA82CFCBE4800C37EE6 /* EmptySearchView.swift in Sources */, ); @@ -8577,6 +8665,8 @@ 85BDC3192436161C0053DB07 /* LoginFormDetectionUserScript.swift in Sources */, 37DF000A29F9C416002B7D3E /* SyncMetadataDatabase.swift in Sources */, F143C3291E4A9A0E00CFDE3A /* URLExtension.swift in Sources */, + C1C1FF4A2D085A4C0017ACCE /* AutofillInterfaceEmailTruncator.swift in Sources */, + C1C1FF4B2D085A4C0017ACCE /* PasswordHider.swift in Sources */, 85E065BC2C73A54700D73E2A /* UsageSegmentationStorage.swift in Sources */, F143C3271E4A9A0E00CFDE3A /* Logger+Multiple.swift in Sources */, 85372447220DD103009D09CD /* UIKeyCommandExtension.swift in Sources */, @@ -9314,6 +9404,68 @@ name = OmniBar.xib; sourceTree = ""; }; + C1E4E9A42D0861AD00AA39AF /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + C1E4E9A52D0861AD00AA39AF /* bg */, + C164F9472D0861D600BAE88E /* cs */, + C18D7C412D08620D00FB3F87 /* da */, + C1DCF3502D0862330055F8B0 /* de */, + C174E08E2D08625300ACE1AF /* el */, + C1F883372D08627900DFF79A /* es */, + C1CB0AA52D08629800335287 /* et */, + C132F5A32D0862B8000C81D0 /* fi */, + C129DF092D0862D7007AB046 /* fr */, + C1406D862D0862F30082CB50 /* hr */, + C1B783DB2D0863110071C53B /* hu */, + C1FEDCEA2D08633100BFBF3F /* it */, + C1A001092D08635100372C87 /* lt */, + C12854D82D08636E00C8353F /* lv */, + C163677A2D08638C001D1094 /* nb */, + C1FE93E52D0863AA009F8F5E /* nl */, + C1453E322D0863C80024449B /* pl */, + C180CAFA2D0863E500ADB0FE /* pt */, + C1B7BF522D08640B0024FF56 /* ro */, + C1193F602D08642900CB3239 /* ru */, + C1588FC42D08644800C9BE70 /* sk */, + C1E490582D08646400F86C5A /* sl */, + C11C4D302D08648100288E85 /* sv */, + C14D37D62D08649E00FCFC59 /* tr */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + C1E4E9A72D0861AD00AA39AF /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + C1E4E9A82D0861AD00AA39AF /* bg */, + C164F9482D0861D600BAE88E /* cs */, + C18D7C422D08620D00FB3F87 /* da */, + C1DCF3512D0862330055F8B0 /* de */, + C174E08F2D08625300ACE1AF /* el */, + C1F883382D08627900DFF79A /* es */, + C1CB0AA62D08629800335287 /* et */, + C132F5A42D0862B8000C81D0 /* fi */, + C129DF0A2D0862D7007AB046 /* fr */, + C1406D872D0862F30082CB50 /* hr */, + C1B783DC2D0863110071C53B /* hu */, + C1FEDCEB2D08633100BFBF3F /* it */, + C1A0010A2D08635100372C87 /* lt */, + C12854D92D08636E00C8353F /* lv */, + C163677B2D08638C001D1094 /* nb */, + C1FE93E62D0863AA009F8F5E /* nl */, + C1453E332D0863C80024449B /* pl */, + C180CAFB2D0863E500ADB0FE /* pt */, + C1B7BF532D08640B0024FF56 /* ro */, + C1193F612D08642900CB3239 /* ru */, + C1588FC52D08644800C9BE70 /* sk */, + C1E490592D08646400F86C5A /* sl */, + C11C4D312D08648100288E85 /* sv */, + C14D37D72D08649E00FCFC59 /* tr */, + ); + name = Localizable.strings; + sourceTree = ""; + }; CB1143DC2AF6D4B600C1CCD3 /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( @@ -9518,7 +9670,7 @@ CODE_SIGN_ENTITLEMENTS = PacketTunnelProvider/PacketTunnelProvider.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 0; DEVELOPMENT_TEAM = HKE973VLUW; GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; @@ -9555,7 +9707,7 @@ CODE_SIGN_IDENTITY = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 0; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -9645,7 +9797,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 0; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = ShareExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -9672,7 +9824,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 0; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -9820,7 +9972,7 @@ CODE_SIGN_ENTITLEMENTS = DuckDuckGo/DuckDuckGo.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 0; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_ASSET_PATHS = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; @@ -9846,7 +9998,7 @@ CODE_SIGN_ENTITLEMENTS = DuckDuckGo/DuckDuckGo.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 0; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; INFOPLIST_FILE = DuckDuckGo/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -9913,7 +10065,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 0; DEAD_CODE_STRIPPING = NO; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = Widgets/Info.plist; @@ -9947,7 +10099,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 0; DEAD_CODE_STRIPPING = NO; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; @@ -9980,7 +10132,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 0; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = OpenAction/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -10010,7 +10162,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 0; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -10341,7 +10493,7 @@ CODE_SIGN_ENTITLEMENTS = AutofillCredentialProvider/AutofillCredentialProvider.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 0; DEVELOPMENT_TEAM = HKE973VLUW; ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu17; @@ -10357,7 +10509,7 @@ ); MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = com.duckduckgo.mobile.ios.AutofillCredentialProvider; + PRODUCT_BUNDLE_IDENTIFIER = com.duckduckgo.mobile.ios.CredentialExtension; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; @@ -10379,7 +10531,7 @@ CODE_SIGN_ENTITLEMENTS = AutofillCredentialProvider/AutofillCredentialProviderAlpha.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 0; DEVELOPMENT_TEAM = HKE973VLUW; ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu17; @@ -10416,7 +10568,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 0; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -10435,7 +10587,7 @@ MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.duckduckgo.mobile.ios.alpha.CredentialExtension; PRODUCT_NAME = "$(TARGET_NAME)"; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AdHoc com.duckduckgo.mobile.ios.alpha.CredentialExtension"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore com.duckduckgo.mobile.ios.alpha.CredentialExtension"; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; @@ -10455,7 +10607,7 @@ CODE_SIGN_IDENTITY = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 0; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -10472,8 +10624,9 @@ ); LOCALIZATION_PREFERS_STRING_CATALOGS = NO; MTL_FAST_MATH = YES; - PRODUCT_BUNDLE_IDENTIFIER = com.duckduckgo.mobile.ios.AutofillCredentialProvider; + PRODUCT_BUNDLE_IDENTIFIER = com.duckduckgo.mobile.ios.CredentialExtension; PRODUCT_NAME = "$(TARGET_NAME)"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore com.duckduckgo.mobile.ios.CredentialExtension"; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; @@ -10552,7 +10705,7 @@ CODE_SIGN_ENTITLEMENTS = DuckDuckGo/DuckDuckGoAlpha.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 0; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_ASSET_PATHS = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; @@ -10583,7 +10736,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 0; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = ShareExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -10611,7 +10764,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 0; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = OpenAction/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -10644,7 +10797,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 0; DEAD_CODE_STRIPPING = NO; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = Widgets/Info.plist; @@ -10674,7 +10827,7 @@ CODE_SIGN_ENTITLEMENTS = PacketTunnelProvider/PacketTunnelProviderAlpha.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 0; DEVELOPMENT_TEAM = HKE973VLUW; GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; @@ -10707,11 +10860,11 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 0; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 3; + DYLIB_CURRENT_VERSION = 0; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = Core/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -10943,7 +11096,7 @@ CODE_SIGN_ENTITLEMENTS = DuckDuckGo/DuckDuckGoAlpha.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 0; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_ASSET_PATHS = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; @@ -10971,7 +11124,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 0; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -11003,7 +11156,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 0; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -11040,7 +11193,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 0; DEAD_CODE_STRIPPING = NO; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; @@ -11075,7 +11228,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 0; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = HKE973VLUW; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -11110,11 +11263,11 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 0; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 3; + DYLIB_CURRENT_VERSION = 0; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = Core/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -11286,11 +11439,11 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 0; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 3; + DYLIB_CURRENT_VERSION = 0; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = Core/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -11319,10 +11472,10 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 0; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 3; + DYLIB_CURRENT_VERSION = 0; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = Core/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; diff --git a/DuckDuckGo/AppDelegate.swift b/DuckDuckGo/AppDelegate.swift index 75296ae8ea..38ff685038 100644 --- a/DuckDuckGo/AppDelegate.swift +++ b/DuckDuckGo/AppDelegate.swift @@ -1108,7 +1108,7 @@ import os.log autofillPixelReporter = AutofillPixelReporter( userDefaults: .standard, autofillEnabled: AppDependencyProvider.shared.appSettings.autofillCredentialsEnabled, - eventMapping: EventMapping {event, _, params, _ in + eventMapping: EventMapping {[weak self] event, _, params, _ in switch event { case .autofillActiveUser: Pixel.fire(pixel: .autofillActiveUser) @@ -1118,8 +1118,16 @@ import os.log Pixel.fire(pixel: .autofillOnboardedUser) case .autofillToggledOn: Pixel.fire(pixel: .autofillToggledOn, withAdditionalParameters: params ?? [:]) + if let autofillExtensionToggled = self?.autofillUsageMonitor.autofillExtensionEnabled { + Pixel.fire(pixel: autofillExtensionToggled ? .autofillExtensionToggledOn : .autofillExtensionToggledOff, + withAdditionalParameters: params ?? [:]) + } case .autofillToggledOff: Pixel.fire(pixel: .autofillToggledOff, withAdditionalParameters: params ?? [:]) + if let autofillExtensionToggled = self?.autofillUsageMonitor.autofillExtensionEnabled { + Pixel.fire(pixel: autofillExtensionToggled ? .autofillExtensionToggledOn : .autofillExtensionToggledOff, + withAdditionalParameters: params ?? [:]) + } case .autofillLoginsStacked: Pixel.fire(pixel: .autofillLoginsStacked, withAdditionalParameters: params ?? [:]) default: diff --git a/DuckDuckGo/AutofillLoginPromptViewModel.swift b/DuckDuckGo/AutofillLoginPromptViewModel.swift index da3a3e551a..4193ba26af 100644 --- a/DuckDuckGo/AutofillLoginPromptViewModel.swift +++ b/DuckDuckGo/AutofillLoginPromptViewModel.swift @@ -20,6 +20,7 @@ import Foundation import UIKit import BrowserServicesKit +import Core protocol AutofillLoginPromptViewModelDelegate: AnyObject { func autofillLoginPromptViewModel(_ viewModel: AutofillLoginPromptViewModel, didSelectAccount account: SecureVaultModels.WebsiteAccount) diff --git a/DuckDuckGo/AutofillUsageMonitor.swift b/DuckDuckGo/AutofillUsageMonitor.swift index 4302aec266..5c9f9bf87f 100644 --- a/DuckDuckGo/AutofillUsageMonitor.swift +++ b/DuckDuckGo/AutofillUsageMonitor.swift @@ -18,13 +18,28 @@ // import Core +import AuthenticationServices final class AutofillUsageMonitor { init() { NotificationCenter.default.addObserver(self, selector: #selector(didReceiveSaveEvent), name: .autofillSaveEvent, object: nil) + + ASCredentialIdentityStore.shared.getState({ state in + if state.isEnabled { + self.autofillExtensionEnabled = true + } else { + if self.autofillExtensionEnabled != nil { + Pixel.fire(pixel: .autofillExtensionDisabled) + self.autofillExtensionEnabled = false + } + } + }) } - + + @UserDefaultsWrapper(key: .autofillExtensionEnabled, defaultValue: nil) + var autofillExtensionEnabled: Bool? + @UserDefaultsWrapper(key: .autofillFirstTimeUser, defaultValue: true) private var autofillFirstTimeUser: Bool diff --git a/DuckDuckGo/DuckDuckGo.entitlements b/DuckDuckGo/DuckDuckGo.entitlements index b798cc1099..ee77dff2bf 100644 --- a/DuckDuckGo/DuckDuckGo.entitlements +++ b/DuckDuckGo/DuckDuckGo.entitlements @@ -2,6 +2,8 @@ + com.apple.developer.authentication-services.autofill-credential-provider + com.apple.developer.browser.app-installation com.apple.developer.networking.networkextension diff --git a/DuckDuckGo/Settings.bundle/Root.plist b/DuckDuckGo/Settings.bundle/Root.plist index c23b94b9bc..740cfbe9a5 100644 --- a/DuckDuckGo/Settings.bundle/Root.plist +++ b/DuckDuckGo/Settings.bundle/Root.plist @@ -6,7 +6,7 @@ DefaultValue - 7.148.0 + 7.149.0 Key version Title diff --git a/DuckDuckGoTests/AutofillInterfaceEmailTruncatorTests.swift b/DuckDuckGoTests/AutofillInterfaceEmailTruncatorTests.swift index c247ea0d97..a3d9340697 100644 --- a/DuckDuckGoTests/AutofillInterfaceEmailTruncatorTests.swift +++ b/DuckDuckGoTests/AutofillInterfaceEmailTruncatorTests.swift @@ -18,6 +18,7 @@ // import XCTest +import Core @testable import DuckDuckGo class AutofillInterfaceEmailTruncatorTests: XCTestCase { diff --git a/adhocExportOptions.plist b/adhocExportOptions.plist index 8af7edc154..de2b86d155 100644 --- a/adhocExportOptions.plist +++ b/adhocExportOptions.plist @@ -25,6 +25,9 @@ com.duckduckgo.mobile.ios.NetworkExtension match AdHoc com.duckduckgo.mobile.ios.NetworkExtension + + com.duckduckgo.mobile.ios.CredentialExtension + match AdHoc com.duckduckgo.mobile.ios.CredentialExtension diff --git a/appStoreExportOptions.plist b/appStoreExportOptions.plist index ff60631b5c..ed346823e8 100644 --- a/appStoreExportOptions.plist +++ b/appStoreExportOptions.plist @@ -18,6 +18,8 @@ match AppStore com.duckduckgo.mobile.ios.Widgets com.duckduckgo.mobile.ios.NetworkExtension match AppStore com.duckduckgo.mobile.ios.NetworkExtension + com.duckduckgo.mobile.ios.CredentialExtension + match AppStore com.duckduckgo.mobile.ios.CredentialExtension diff --git a/fastlane/Matchfile b/fastlane/Matchfile index 4212b95ef5..f577d97171 100644 --- a/fastlane/Matchfile +++ b/fastlane/Matchfile @@ -4,7 +4,7 @@ git_branch "ios" platform "ios" type "appstore" -app_identifier ["com.duckduckgo.mobile.ios", "com.duckduckgo.mobile.ios.ShareExtension", "com.duckduckgo.mobile.ios.OpenAction2", "com.duckduckgo.mobile.ios.Widgets", "com.duckduckgo.mobile.ios.NetworkExtension"] +app_identifier ["com.duckduckgo.mobile.ios", "com.duckduckgo.mobile.ios.ShareExtension", "com.duckduckgo.mobile.ios.OpenAction2", "com.duckduckgo.mobile.ios.Widgets", "com.duckduckgo.mobile.ios.NetworkExtension", "com.duckduckgo.mobile.ios.CredentialExtension"] generate_apple_certs false for_lane :sync_signing_adhoc do @@ -21,7 +21,7 @@ end for_lane :adhoc do type "adhoc" - app_identifier ["com.duckduckgo.mobile.ios.alpha", "com.duckduckgo.mobile.ios.alpha.ShareExtension", "com.duckduckgo.mobile.ios.alpha.OpenAction2", "com.duckduckgo.mobile.ios.alpha.Widgets", "com.duckduckgo.mobile.ios.alpha.NetworkExtension"] + app_identifier ["com.duckduckgo.mobile.ios.alpha", "com.duckduckgo.mobile.ios.alpha.ShareExtension", "com.duckduckgo.mobile.ios.alpha.OpenAction2", "com.duckduckgo.mobile.ios.alpha.Widgets", "com.duckduckgo.mobile.ios.alpha.NetworkExtension", "com.duckduckgo.mobile.ios.alpha.CredentialExtension"] force_for_new_devices true template_name "Default Web Browser iOS (Dist)" end @@ -40,11 +40,11 @@ for_lane :alpha_adhoc do end for_lane :sync_signing_alpha do - app_identifier ["com.duckduckgo.mobile.ios.alpha", "com.duckduckgo.mobile.ios.alpha.ShareExtension", "com.duckduckgo.mobile.ios.alpha.OpenAction2", "com.duckduckgo.mobile.ios.alpha.Widgets", "com.duckduckgo.mobile.ios.alpha.NetworkExtension"] + app_identifier ["com.duckduckgo.mobile.ios.alpha", "com.duckduckgo.mobile.ios.alpha.ShareExtension", "com.duckduckgo.mobile.ios.alpha.OpenAction2", "com.duckduckgo.mobile.ios.alpha.Widgets", "com.duckduckgo.mobile.ios.alpha.NetworkExtension", "com.duckduckgo.mobile.ios.alpha.CredentialExtension"] template_name "Default Web Browser iOS (Dist)" end for_lane :release_alpha do - app_identifier ["com.duckduckgo.mobile.ios.alpha", "com.duckduckgo.mobile.ios.alpha.ShareExtension", "com.duckduckgo.mobile.ios.alpha.OpenAction2", "com.duckduckgo.mobile.ios.alpha.Widgets", "com.duckduckgo.mobile.ios.alpha.NetworkExtension"] + app_identifier ["com.duckduckgo.mobile.ios.alpha", "com.duckduckgo.mobile.ios.alpha.ShareExtension", "com.duckduckgo.mobile.ios.alpha.OpenAction2", "com.duckduckgo.mobile.ios.alpha.Widgets", "com.duckduckgo.mobile.ios.alpha.NetworkExtension", "com.duckduckgo.mobile.ios.alpha.CredentialExtension"] template_name "Default Web Browser iOS (Dist)" end diff --git a/fastlane/metadata/default/release_notes.txt b/fastlane/metadata/default/release_notes.txt index 098fd1666f..66b16c0810 100644 --- a/fastlane/metadata/default/release_notes.txt +++ b/fastlane/metadata/default/release_notes.txt @@ -1 +1 @@ -- Bug fixes and other improvements. \ No newline at end of file +- Bug fixes and other improvements \ No newline at end of file